Merge "Fix for bug 4371230. - Generate unique ID for each DrmManagerClient in native side - Fix the bug where multiple clients could use the same ID - Return the correct unique ID back to Java - Add a flag in the unique ID to separate native client and Java client"
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index b42f1c5..34f0a64 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -803,9 +803,9 @@
             printf("type '%s':\n", kMimeTypes[k]);
 
             Vector<CodecCapabilities> results;
+            // will retrieve hardware and software codecs
             CHECK_EQ(QueryCodecs(omx, kMimeTypes[k],
                                  true, // queryDecoders
-                                 false, // hwCodecOnly
                                  &results), (status_t)OK);
 
             for (size_t i = 0; i < results.size(); ++i) {
diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h
index dd93fd8..1417416 100644
--- a/include/media/AudioEffect.h
+++ b/include/media/AudioEffect.h
@@ -21,6 +21,7 @@
 #include <sys/types.h>
 
 #include <media/IAudioFlinger.h>
+#include <media/IAudioPolicyService.h>
 #include <media/IEffect.h>
 #include <media/IEffectClient.h>
 #include <hardware/audio_effect.h>
@@ -111,6 +112,36 @@
 
 
     /*
+     * Returns a list of descriptors corresponding to the pre processings enabled by default
+     * on an AudioRecord with the supplied audio session ID.
+     *
+     * Parameters:
+     *      audioSession:  audio session ID.
+     *      descriptors: address where the effect descriptors should be returned.
+     *      count: as input, the maximum number of descriptor than should be returned
+     *             as output, the number of descriptor returned if status is NO_ERROR or the actual
+     *             number of enabled pre processings if status is NO_MEMORY
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *      NO_ERROR        successful operation.
+     *      NO_MEMORY       the number of descriptor to return is more than the maximum number
+     *                      indicated by count.
+     *      PERMISSION_DENIED could not get AudioFlinger interface
+     *      NO_INIT         effect library failed to initialize
+     *      BAD_VALUE       invalid audio session or descriptor pointers
+     *
+     * Returned value
+     *   *descriptor updated with descriptors of pre processings enabled by default
+     *   *count      number of descriptors returned if returned status is N_ERROR.
+     *               total number of pre processing enabled by default if returned status is
+     *               NO_MEMORY. This happens if the count passed as input is less than the number
+     *               of descriptors to return
+     */
+    static status_t queryDefaultPreProcessing(int audioSession,
+                                              effect_descriptor_t *descriptors,
+                                              uint32_t *count);
+
+    /*
      * Events used by callback function (effect_callback_t).
      */
     enum event_type {
@@ -188,7 +219,7 @@
      * sessionID:   audio session this effect is associated to. If 0, the effect will be global to
      *      the output mix. If not 0, the effect will be applied to all players
      *      (AudioTrack or MediaPLayer) within the same audio session.
-     * output:  HAL audio output stream to which this effect must be attached. Leave at 0 for
+     * io:  HAL audio output or input stream to which this effect must be attached. Leave at 0 for
      *      automatic output selection by AudioFlinger.
      */
 
@@ -198,7 +229,7 @@
                   effect_callback_t cbf = 0,
                   void* user = 0,
                   int sessionId = 0,
-                  audio_io_handle_t output = 0
+                  audio_io_handle_t io = 0
                   );
 
     /* Constructor.
@@ -210,7 +241,7 @@
                     effect_callback_t cbf = 0,
                     void* user = 0,
                     int sessionId = 0,
-                    audio_io_handle_t output = 0
+                    audio_io_handle_t io = 0
                     );
 
     /* Terminates the AudioEffect and unregisters it from AudioFlinger.
@@ -232,7 +263,7 @@
                             effect_callback_t cbf = 0,
                             void* user = 0,
                             int sessionId = 0,
-                            audio_io_handle_t output = 0
+                            audio_io_handle_t io = 0
                             );
 
     /* Result of constructing the AudioEffect. This must be checked
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 89213b7..f20e234 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -160,7 +160,8 @@
                                     uint32_t samplingRate = 0,
                                     uint32_t format = AUDIO_FORMAT_DEFAULT,
                                     uint32_t channels = AUDIO_CHANNEL_IN_MONO,
-                                    audio_in_acoustics_t acoustics = (audio_in_acoustics_t)0);
+                                    audio_in_acoustics_t acoustics = (audio_in_acoustics_t)0,
+                                    int sessionId = 0);
     static status_t startInput(audio_io_handle_t input);
     static status_t stopInput(audio_io_handle_t input);
     static void releaseInput(audio_io_handle_t input);
@@ -175,7 +176,7 @@
 
     static audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
     static status_t registerEffect(effect_descriptor_t *desc,
-                                    audio_io_handle_t output,
+                                    audio_io_handle_t io,
                                     uint32_t strategy,
                                     int session,
                                     int id);
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index 0fc8dbf..ed265e1 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -65,7 +65,8 @@
                                     uint32_t samplingRate = 0,
                                     uint32_t format = AUDIO_FORMAT_DEFAULT,
                                     uint32_t channels = 0,
-                                    audio_in_acoustics_t acoustics = (audio_in_acoustics_t)0) = 0;
+                                    audio_in_acoustics_t acoustics = (audio_in_acoustics_t)0,
+                                    int audioSession = 0) = 0;
     virtual status_t startInput(audio_io_handle_t input) = 0;
     virtual status_t stopInput(audio_io_handle_t input) = 0;
     virtual void releaseInput(audio_io_handle_t input) = 0;
@@ -78,12 +79,15 @@
     virtual uint32_t getDevicesForStream(audio_stream_type_t stream) = 0;
     virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc) = 0;
     virtual status_t registerEffect(effect_descriptor_t *desc,
-                                    audio_io_handle_t output,
+                                    audio_io_handle_t io,
                                     uint32_t strategy,
                                     int session,
                                     int id) = 0;
     virtual status_t unregisterEffect(int id) = 0;
     virtual bool     isStreamActive(int stream, uint32_t inPastMs = 0) const = 0;
+    virtual status_t queryDefaultPreProcessing(int audioSession,
+                                              effect_descriptor_t *descriptors,
+                                              uint32_t *count) = 0;
 };
 
 
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index a73267d..ec84e25 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -26,6 +26,7 @@
 class ICamera;
 class ICameraRecordingProxy;
 class IMediaRecorderClient;
+class ISurfaceTexture;
 
 class IMediaRecorder: public IInterface
 {
@@ -42,7 +43,6 @@
     virtual status_t setAudioEncoder(int ae) = 0;
     virtual status_t setOutputFile(const char* path) = 0;
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
-    virtual status_t setOutputFileAuxiliary(int fd) = 0;
     virtual status_t setVideoSize(int width, int height) = 0;
     virtual status_t setVideoFrameRate(int frames_per_second) = 0;
     virtual status_t setParameters(const String8& params) = 0;
@@ -55,6 +55,7 @@
     virtual status_t init() = 0;
     virtual status_t close() = 0;
     virtual status_t release() = 0;
+    virtual sp<ISurfaceTexture> querySurfaceMediaSource() = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/media/MediaProfiles.h b/include/media/MediaProfiles.h
index ed26e63..69d5001 100644
--- a/include/media/MediaProfiles.h
+++ b/include/media/MediaProfiles.h
@@ -45,6 +45,18 @@
     CAMCORDER_QUALITY_TIME_LAPSE_LIST_END = 1006,
 };
 
+/**
+ *Set CIF as default maximum import and export resolution of video editor.
+ *The maximum import and export resolutions are platform specific,
+ *which should be defined in media_profiles.xml.
+ */
+enum videoeditor_capability {
+    VIDEOEDITOR_DEFAULT_MAX_INPUT_FRAME_WIDTH = 352,
+    VIDEOEDITOR_DEFUALT_MAX_INPUT_FRAME_HEIGHT = 288,
+    VIDEOEDITOR_DEFAULT_MAX_OUTPUT_FRAME_WIDTH = 352,
+    VIDEOEDITOR_DEFUALT_MAX_OUTPUT_FRAME_HEIGHT = 288,
+};
+
 enum video_decoder {
     VIDEO_DECODER_WMV,
 };
@@ -117,6 +129,17 @@
     int getVideoEncoderParamByName(const char *name, video_encoder codec) const;
 
     /**
+     * Returns the value for the given param name for the video editor cap
+     * param or -1 if error.
+     * Supported param name are:
+     * videoeditor.input.width.max - max input video frame width
+     * videoeditor.input.height.max - max input video frame height
+     * videoeditor.output.width.max - max output video frame width
+     * videoeditor.output.height.max - max output video frame height
+     */
+    int getVideoEditorCapParamByName(const char *name) const;
+
+    /**
      * Returns the audio encoders supported.
      */
     Vector<audio_encoder> getAudioEncoders() const;
@@ -164,7 +187,7 @@
 
     MediaProfiles& operator=(const MediaProfiles&);  // Don't call me
     MediaProfiles(const MediaProfiles&);             // Don't call me
-    MediaProfiles() {}                               // Dummy default constructor
+    MediaProfiles() { mVideoEditorCap = NULL; }        // Dummy default constructor
     ~MediaProfiles();                                // Don't delete me
 
     struct VideoCodec {
@@ -310,6 +333,22 @@
         Vector<int> mLevels;
     };
 
+    struct VideoEditorCap {
+        VideoEditorCap(int inFrameWidth, int inFrameHeight,
+            int outFrameWidth, int outFrameHeight)
+            : mMaxInputFrameWidth(inFrameWidth),
+              mMaxInputFrameHeight(inFrameHeight),
+              mMaxOutputFrameWidth(outFrameWidth),
+              mMaxOutputFrameHeight(outFrameHeight) {}
+
+        ~VideoEditorCap() {}
+
+        int mMaxInputFrameWidth;
+        int mMaxInputFrameHeight;
+        int mMaxOutputFrameWidth;
+        int mMaxOutputFrameHeight;
+    };
+
     int getCamcorderProfileIndex(int cameraId, camcorder_quality quality) const;
     void initRequiredProfileRefs(const Vector<int>& cameraIds);
     int getRequiredProfileRefIndex(int cameraId);
@@ -321,6 +360,7 @@
     static void logAudioEncoderCap(const AudioEncoderCap& cap);
     static void logVideoDecoderCap(const VideoDecoderCap& cap);
     static void logAudioDecoderCap(const AudioDecoderCap& cap);
+    static void logVideoEditorCap(const VideoEditorCap& cap);
 
     // If the xml configuration file does exist, use the settings
     // from the xml
@@ -332,6 +372,8 @@
     static VideoDecoderCap* createVideoDecoderCap(const char **atts);
     static VideoEncoderCap* createVideoEncoderCap(const char **atts);
     static AudioEncoderCap* createAudioEncoderCap(const char **atts);
+    static VideoEditorCap* createVideoEditorCap(
+                const char **atts, MediaProfiles *profiles);
 
     static CamcorderProfile* createCamcorderProfile(
                 int cameraId, const char **atts, Vector<int>& cameraIds);
@@ -375,6 +417,7 @@
     static void createDefaultEncoderOutputFileFormats(MediaProfiles *profiles);
     static void createDefaultImageEncodingQualityLevels(MediaProfiles *profiles);
     static void createDefaultImageDecodingMaxMemory(MediaProfiles *profiles);
+    static void createDefaultVideoEditorCap(MediaProfiles *profiles);
     static VideoEncoderCap* createDefaultH263VideoEncoderCap();
     static VideoEncoderCap* createDefaultM4vVideoEncoderCap();
     static AudioEncoderCap* createDefaultAmrNBEncoderCap();
@@ -431,6 +474,7 @@
 
     RequiredProfiles *mRequiredProfileRefs;
     Vector<int>              mCameraIds;
+    VideoEditorCap* mVideoEditorCap;
 };
 
 }; // namespace android
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index 1c08969..ef799f5 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -26,6 +26,7 @@
 
 class ICameraRecordingProxy;
 class Surface;
+class ISurfaceTexture;
 
 struct MediaRecorderBase {
     MediaRecorderBase() {}
@@ -54,6 +55,7 @@
     virtual status_t reset() = 0;
     virtual status_t getMaxAmplitude(int *max) = 0;
     virtual status_t dump(int fd, const Vector<String16>& args) const = 0;
+    virtual sp<ISurfaceTexture> querySurfaceMediaSource() const = 0;
 
 private:
     MediaRecorderBase(const MediaRecorderBase &);
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index af12d3c..30db642 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -31,12 +31,15 @@
 class IMediaRecorder;
 class ICamera;
 class ICameraRecordingProxy;
+class ISurfaceTexture;
+class SurfaceTextureClient;
 
 typedef void (*media_completion_f)(status_t status, void *cookie);
 
 enum video_source {
     VIDEO_SOURCE_DEFAULT = 0,
     VIDEO_SOURCE_CAMERA = 1,
+    VIDEO_SOURCE_GRALLOC_BUFFER = 2,
 
     VIDEO_SOURCE_LIST_END  // must be last - used to validate audio source type
 };
@@ -212,7 +215,6 @@
     status_t    setAudioEncoder(int ae);
     status_t    setOutputFile(const char* path);
     status_t    setOutputFile(int fd, int64_t offset, int64_t length);
-    status_t    setOutputFileAuxiliary(int fd);
     status_t    setVideoSize(int width, int height);
     status_t    setVideoFrameRate(int frames_per_second);
     status_t    setParameters(const String8& params);
@@ -226,6 +228,7 @@
     status_t    close();
     status_t    release();
     void        notify(int msg, int ext1, int ext2);
+    sp<ISurfaceTexture>     querySurfaceMediaSourceFromMediaServer();
 
 private:
     void                    doCleanUp();
@@ -233,13 +236,18 @@
 
     sp<IMediaRecorder>          mMediaRecorder;
     sp<MediaRecorderListener>   mListener;
+
+    // Reference toISurfaceTexture
+    // for encoding GL Frames. That is useful only when the
+    // video source is set to VIDEO_SOURCE_GRALLOC_BUFFER
+    sp<ISurfaceTexture>         mSurfaceMediaSource;
+
     media_recorder_states       mCurrentState;
     bool                        mIsAudioSourceSet;
     bool                        mIsVideoSourceSet;
     bool                        mIsAudioEncoderSet;
     bool                        mIsVideoEncoderSet;
     bool                        mIsOutputFileSet;
-    bool                        mIsAuxiliaryOutputFileSet;
     Mutex                       mLock;
     Mutex                       mNotifyLock;
 };
diff --git a/include/media/mediascanner.h b/include/media/mediascanner.h
index 765c039..803bffb 100644
--- a/include/media/mediascanner.h
+++ b/include/media/mediascanner.h
@@ -23,23 +23,33 @@
 #include <utils/Errors.h>
 #include <pthread.h>
 
+struct dirent;
+
 namespace android {
 
 class MediaScannerClient;
 class StringArray;
 
+enum MediaScanResult {
+    // This file or directory was scanned successfully.
+    MEDIA_SCAN_RESULT_OK,
+    // This file or directory was skipped because it was not found, could
+    // not be opened, was of an unsupported type, or was malfored in some way.
+    MEDIA_SCAN_RESULT_SKIPPED,
+    // The scan should be aborted due to a fatal error such as out of memory
+    // or an exception.
+    MEDIA_SCAN_RESULT_ERROR,
+};
+
 struct MediaScanner {
     MediaScanner();
     virtual ~MediaScanner();
 
-    virtual status_t processFile(
-            const char *path, const char *mimeType,
-            MediaScannerClient &client) = 0;
+    virtual MediaScanResult processFile(
+            const char *path, const char *mimeType, MediaScannerClient &client) = 0;
 
-    typedef bool (*ExceptionCheck)(void* env);
-    virtual status_t processDirectory(
-            const char *path, MediaScannerClient &client,
-            ExceptionCheck exceptionCheck, void *exceptionEnv);
+    virtual MediaScanResult processDirectory(
+            const char *path, MediaScannerClient &client);
 
     void setLocale(const char *locale);
 
@@ -53,9 +63,11 @@
     // current locale (like "ja_JP"), created/destroyed with strdup()/free()
     char *mLocale;
 
-    status_t doProcessDirectory(
-            char *path, int pathRemaining, MediaScannerClient &client,
-            bool noMedia, ExceptionCheck exceptionCheck, void *exceptionEnv);
+    MediaScanResult doProcessDirectory(
+            char *path, int pathRemaining, MediaScannerClient &client, bool noMedia);
+    MediaScanResult doProcessDirectoryEntry(
+            char *path, int pathRemaining, MediaScannerClient &client, bool noMedia,
+            struct dirent* entry, char* fileSpot);
 
     MediaScanner(const MediaScanner &);
     MediaScanner &operator=(const MediaScanner &);
@@ -68,13 +80,13 @@
     virtual ~MediaScannerClient();
     void setLocale(const char* locale);
     void beginFile();
-    bool addStringTag(const char* name, const char* value);
+    status_t addStringTag(const char* name, const char* value);
     void endFile();
 
-    virtual bool scanFile(const char* path, long long lastModified,
+    virtual status_t scanFile(const char* path, long long lastModified,
             long long fileSize, bool isDirectory, bool noMedia) = 0;
-    virtual bool handleStringTag(const char* name, const char* value) = 0;
-    virtual bool setMimeType(const char* mimeType) = 0;
+    virtual status_t handleStringTag(const char* name, const char* value) = 0;
+    virtual status_t setMimeType(const char* mimeType) = 0;
 
 protected:
     void convertValues(uint32_t encoding);
diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h
index f07ebba..0e264c7 100644
--- a/include/media/stagefright/CameraSourceTimeLapse.h
+++ b/include/media/stagefright/CameraSourceTimeLapse.h
@@ -53,27 +53,10 @@
     void startQuickReadReturns();
 
 private:
-    // If true, will use still camera takePicture() for time lapse frames
-    // If false, will use the videocamera frames instead.
-    bool mUseStillCameraForTimeLapse;
-
-    // Size of picture taken from still camera. This may be larger than the size
-    // of the video, as still camera may not support the exact video resolution
-    // demanded. See setPictureSizeToClosestSupported().
-    int32_t mPictureWidth;
-    int32_t mPictureHeight;
-
     // size of the encoded video.
     int32_t mVideoWidth;
     int32_t mVideoHeight;
 
-    // True if we need to crop the still camera image to get the video frame.
-    bool mNeedCropping;
-
-    // Start location of the cropping rectangle.
-    int32_t mCropRectStartX;
-    int32_t mCropRectStartY;
-
     // Time between capture of two frames during time lapse recording
     // Negative value indicates that timelapse is disabled.
     int64_t mTimeBetweenTimeLapseFrameCaptureUs;
@@ -84,9 +67,6 @@
     // Real timestamp of the last encoded time lapse frame
     int64_t mLastTimeLapseFrameRealTimestampUs;
 
-    // Thread id of thread which takes still picture and sleeps in a loop.
-    pthread_t mThreadTimeLapse;
-
     // Variable set in dataCallbackTimestamp() to help skipCurrentFrame()
     // to know if current frame needs to be skipped.
     bool mSkipCurrentFrame;
@@ -111,9 +91,6 @@
     // Lock for accessing quick stop variables.
     Mutex mQuickStopLock;
 
-    // Condition variable to wake up still picture thread.
-    Condition mTakePictureCondition;
-
     // mQuickStop is set to true if we use quick read() returns, otherwise it is set
     // to false. Once in this mode read() return a copy of the last read frame
     // with the same time stamp. See startQuickReadReturns().
@@ -148,32 +125,13 @@
     // Wrapper over CameraSource::read() to implement quick stop.
     virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
 
-    // For still camera case starts a thread which calls camera's takePicture()
-    // in a loop. For video camera case, just starts the camera's video recording.
-    virtual void startCameraRecording();
-
-    // For still camera case joins the thread created in startCameraRecording().
     // For video camera case, just stops the camera's video recording.
     virtual void stopCameraRecording();
 
-    // For still camera case don't need to do anything as memory is locally
-    // allocated with refcounting.
-    // For video camera case just tell the camera to release the frame.
-    virtual void releaseRecordingFrame(const sp<IMemory>& frame);
-
     // mSkipCurrentFrame is set to true in dataCallbackTimestamp() if the current
     // frame needs to be skipped and this function just returns the value of mSkipCurrentFrame.
     virtual bool skipCurrentFrame(int64_t timestampUs);
 
-    // Handles the callback to handle raw frame data from the still camera.
-    // Creates a copy of the frame data as the camera can reuse the frame memory
-    // once this callback returns. The function also sets a new timstamp corresponding
-    // to one frame time ahead of the last encoded frame's time stamp. It then
-    // calls dataCallbackTimestamp() of the base class with the copied data and the
-    // modified timestamp, which will think that it recieved the frame from a video
-    // camera and proceed as usual.
-    virtual void dataCallback(int32_t msgType, const sp<IMemory> &data);
-
     // In the video camera case calls skipFrameAndModifyTimeStamp() to modify
     // timestamp and set mSkipCurrentFrame.
     // Then it calls the base CameraSource::dataCallbackTimestamp()
@@ -189,24 +147,6 @@
     // Otherwise returns false.
     bool trySettingVideoSize(int32_t width, int32_t height);
 
-    // The still camera may not support the demanded video width and height.
-    // We look for the supported picture sizes from the still camera and
-    // choose the smallest one with either dimensions higher than the corresponding
-    // video dimensions. The still picture will be cropped to get the video frame.
-    // The function returns true if the camera supports picture sizes greater than
-    // or equal to the passed in width and height, and false otherwise.
-    bool setPictureSizeToClosestSupported(int32_t width, int32_t height);
-
-    // Computes the offset of the rectangle from where to start cropping the
-    // still image into the video frame. We choose the center of the image to be
-    // cropped. The offset is stored in (mCropRectStartX, mCropRectStartY).
-    bool computeCropRectangleOffset();
-
-    // Crops the source data into a smaller image starting at
-    // (mCropRectStartX, mCropRectStartY) and of the size of the video frame.
-    // The data is returned into a newly allocated IMemory.
-    sp<IMemory> cropYUVImage(const sp<IMemory> &source_data);
-
     // When video camera is used for time lapse capture, returns true
     // until enough time has passed for the next time lapse frame. When
     // the frame needs to be encoded, it returns false and also modifies
@@ -217,22 +157,6 @@
     // Wrapper to enter threadTimeLapseEntry()
     static void *ThreadTimeLapseWrapper(void *me);
 
-    // Runs a loop which sleeps until a still picture is required
-    // and then calls mCamera->takePicture() to take the still picture.
-    // Used only in the case mUseStillCameraForTimeLapse = true.
-    void threadTimeLapseEntry();
-
-    // Wrapper to enter threadStartPreview()
-    static void *ThreadStartPreviewWrapper(void *me);
-
-    // Starts the camera's preview.
-    void threadStartPreview();
-
-    // Starts thread ThreadStartPreviewWrapper() for restarting preview.
-    // Needs to be done in a thread so that dataCallback() which calls this function
-    // can return, and the camera can know that takePicture() is done.
-    void restartPreview();
-
     // Creates a copy of source_data into a new memory of final type MemoryBase.
     sp<IMemory> createIMemoryCopy(const sp<IMemory> &source_data);
 
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index 48d1464..713af92 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -20,6 +20,7 @@
 
 #include <sys/types.h>
 
+#include <media/stagefright/MediaErrors.h>
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
 #include <utils/List.h>
@@ -61,6 +62,10 @@
         return 0;
     }
 
+    virtual status_t reconnectAtOffset(off64_t offset) {
+        return ERROR_UNSUPPORTED;
+    }
+
     ////////////////////////////////////////////////////////////////////////////
 
     bool sniff(String8 *mimeType, float *confidence, sp<AMessage> *meta);
diff --git a/include/media/stagefright/HardwareAPI.h b/include/media/stagefright/HardwareAPI.h
index 946a0aa..32eed3f 100644
--- a/include/media/stagefright/HardwareAPI.h
+++ b/include/media/stagefright/HardwareAPI.h
@@ -99,6 +99,13 @@
     OMX_U32 nUsage;             // OUT
 };
 
+// An enum OMX_COLOR_FormatAndroidOpaque to indicate an opaque colorformat
+// is declared in media/stagefright/openmax/OMX_IVCommon.h
+// This will inform the encoder that the actual
+// colorformat will be relayed by the GRalloc Buffers.
+// OMX_COLOR_FormatAndroidOpaque  = 0x7F000001,
+
+
 }  // namespace android
 
 extern android::OMXPluginBase *createOMXPlugin();
diff --git a/include/media/stagefright/MediaSource.h b/include/media/stagefright/MediaSource.h
index 37dbcd8..3818e63 100644
--- a/include/media/stagefright/MediaSource.h
+++ b/include/media/stagefright/MediaSource.h
@@ -29,7 +29,7 @@
 class MediaBuffer;
 class MetaData;
 
-struct MediaSource : public RefBase {
+struct MediaSource : public virtual RefBase {
     MediaSource();
 
     // To be called before any other methods on this object, except
diff --git a/include/media/stagefright/MetadataBufferType.h b/include/media/stagefright/MetadataBufferType.h
index 52a3257..4eaf8ac 100644
--- a/include/media/stagefright/MetadataBufferType.h
+++ b/include/media/stagefright/MetadataBufferType.h
@@ -69,6 +69,16 @@
      * kMetadataBufferTypeGrallocSource is used to indicate that
      * the payload of the metadata buffers can be interpreted as
      * a buffer_handle_t.
+     * So in this case,the metadata that the encoder receives
+     * will have a byte stream that consists of two parts:
+     * 1. First, there is an integer indicating that it is a GRAlloc
+     * source (kMetadataBufferTypeGrallocSource)
+     * 2. This is followed by the buffer_handle_t that is a handle to the
+     * GRalloc buffer. The encoder needs to interpret this GRalloc handle
+     * and encode the frames.
+     * --------------------------------------------------------------
+     * |  kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
+     * --------------------------------------------------------------
      */
     kMetadataBufferTypeGrallocSource = 1,
 
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 20fcde5..2932744 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -329,6 +329,7 @@
     void restorePatchedDataPointer(BufferInfo *info);
 
     status_t applyRotation();
+    status_t waitForBufferFilled_l();
 
     int64_t retrieveDecodingTimeUs(bool isCodecSpecific);
 
@@ -348,6 +349,8 @@
 // that encode content of the given type.
 // profile and level indications only make sense for h.263, mpeg4 and avc
 // video.
+// If hwCodecOnly==true, only returns hardware-based components, software and
+// hardware otherwise.
 // The profile/level values correspond to
 // OMX_VIDEO_H263PROFILETYPE, OMX_VIDEO_MPEG4PROFILETYPE,
 // OMX_VIDEO_AVCPROFILETYPE, OMX_VIDEO_H263LEVELTYPE, OMX_VIDEO_MPEG4LEVELTYPE
@@ -358,6 +361,11 @@
         const char *mimeType, bool queryDecoders, bool hwCodecOnly,
         Vector<CodecCapabilities> *results);
 
+status_t QueryCodecs(
+        const sp<IOMX> &omx,
+        const char *mimeType, bool queryDecoders,
+        Vector<CodecCapabilities> *results);
+
 }  // namespace android
 
 #endif  // OMX_CODEC_H_
diff --git a/include/media/stagefright/StagefrightMediaScanner.h b/include/media/stagefright/StagefrightMediaScanner.h
index 108acb4..6510a59 100644
--- a/include/media/stagefright/StagefrightMediaScanner.h
+++ b/include/media/stagefright/StagefrightMediaScanner.h
@@ -26,7 +26,7 @@
     StagefrightMediaScanner();
     virtual ~StagefrightMediaScanner();
 
-    virtual status_t processFile(
+    virtual MediaScanResult processFile(
             const char *path, const char *mimeType,
             MediaScannerClient &client);
 
@@ -35,6 +35,10 @@
 private:
     StagefrightMediaScanner(const StagefrightMediaScanner &);
     StagefrightMediaScanner &operator=(const StagefrightMediaScanner &);
+
+    MediaScanResult processFileInternal(
+            const char *path, const char *mimeType,
+            MediaScannerClient &client);
 };
 
 }  // namespace android
diff --git a/include/media/stagefright/SurfaceMediaSource.h b/include/media/stagefright/SurfaceMediaSource.h
new file mode 100644
index 0000000..fab258c
--- /dev/null
+++ b/include/media/stagefright/SurfaceMediaSource.h
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2011 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_GUI_SURFACEMEDIASOURCE_H
+#define ANDROID_GUI_SURFACEMEDIASOURCE_H
+
+#include <gui/ISurfaceTexture.h>
+
+#include <utils/threads.h>
+#include <utils/Vector.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MediaBuffer.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class IGraphicBufferAlloc;
+class String8;
+class GraphicBuffer;
+
+class SurfaceMediaSource : public BnSurfaceTexture, public MediaSource,
+                                            public MediaBufferObserver {
+public:
+    enum { MIN_UNDEQUEUED_BUFFERS = 3 };
+    enum {
+        MIN_ASYNC_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS + 1,
+        MIN_SYNC_BUFFER_SLOTS  = MIN_UNDEQUEUED_BUFFERS
+    };
+    enum { NUM_BUFFER_SLOTS = 32 };
+    enum { NO_CONNECTED_API = 0 };
+
+    struct FrameAvailableListener : public virtual RefBase {
+        // onFrameAvailable() is called from queueBuffer() is the FIFO is
+        // empty. You can use SurfaceMediaSource::getQueuedCount() to
+        // figure out if there are more frames waiting.
+        // This is called without any lock held can be called concurrently by
+        // multiple threads.
+        virtual void onFrameAvailable() = 0;
+    };
+
+    SurfaceMediaSource(uint32_t bufW, uint32_t bufH);
+
+    virtual ~SurfaceMediaSource();
+
+
+    // For the MediaSource interface for use by StageFrightRecorder:
+    virtual status_t start(MetaData *params = NULL);
+    virtual status_t stop();
+    virtual status_t read(
+            MediaBuffer **buffer, const ReadOptions *options = NULL);
+    virtual sp<MetaData> getFormat();
+
+    // Pass the metadata over to the buffer, call when you have the lock
+    void passMetadataBufferLocked(MediaBuffer **buffer);
+    bool checkBufferMatchesSlot(int slot, MediaBuffer *buffer);
+
+    // Get / Set the frame rate used for encoding. Default fps = 30
+    status_t setFrameRate(int32_t fps) ;
+    int32_t getFrameRate( ) const;
+
+    // The call for the StageFrightRecorder to tell us that
+    // it is done using the MediaBuffer data so that its state
+    // can be set to FREE for dequeuing
+    virtual void signalBufferReturned(MediaBuffer* buffer);
+    // end of MediaSource interface
+
+    uint32_t getBufferCount( ) const { return mBufferCount;}
+
+
+    // setBufferCount updates the number of available buffer slots.  After
+    // calling this all buffer slots are both unallocated and owned by the
+    // SurfaceMediaSource object (i.e. they are not owned by the client).
+    virtual status_t setBufferCount(int bufferCount);
+
+    virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
+
+    // dequeueBuffer gets the next buffer slot index for the client to use. If a
+    // buffer slot is available then that slot index is written to the location
+    // pointed to by the buf argument and a status of OK is returned.  If no
+    // slot is available then a status of -EBUSY is returned and buf is
+    // unmodified.
+    virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,
+            uint32_t format, uint32_t usage);
+
+    // queueBuffer returns a filled buffer to the SurfaceMediaSource. In addition, a
+    // timestamp must be provided for the buffer. The timestamp is in
+    // nanoseconds, and must be monotonically increasing. Its other semantics
+    // (zero point, etc) are client-dependent and should be documented by the
+    // client.
+    virtual status_t queueBuffer(int buf, int64_t timestamp,
+            uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform);
+    virtual void cancelBuffer(int buf);
+
+    // onFrameReceivedLocked informs the buffer consumers (StageFrightRecorder)
+    // or listeners that a frame has been received
+    // The buffer is not made available for dequeueing immediately. We need to
+    // wait to hear from StageFrightRecorder to set the buffer FREE
+    // Make sure this is called when the mutex is locked
+    virtual status_t onFrameReceivedLocked();
+
+    virtual status_t setScalingMode(int mode) { } // no op for encoding
+    virtual int query(int what, int* value);
+
+    // Just confirming to the ISurfaceTexture interface as of now
+    virtual status_t setCrop(const Rect& reg) { return OK; }
+    virtual status_t setTransform(uint32_t transform) {return OK;}
+
+    // setSynchronousMode set whether dequeueBuffer is synchronous or
+    // asynchronous. In synchronous mode, dequeueBuffer blocks until
+    // a buffer is available, the currently bound buffer can be dequeued and
+    // queued buffers will be retired in order.
+    // The default mode is synchronous.
+    // TODO: Clarify the minute differences bet sycn /async
+    // modes (S.Encoder vis-a-vis SurfaceTexture)
+    virtual status_t setSynchronousMode(bool enabled);
+
+    // connect attempts to connect a client API to the SurfaceMediaSource.  This
+    // must be called before any other ISurfaceTexture methods are called except
+    // for getAllocator.
+    //
+    // This method will fail if the connect was previously called on the
+    // SurfaceMediaSource and no corresponding disconnect call was made.
+    virtual status_t connect(int api);
+
+    // disconnect attempts to disconnect a client API from the SurfaceMediaSource.
+    // Calling this method will cause any subsequent calls to other
+    // ISurfaceTexture methods to fail except for getAllocator and connect.
+    // Successfully calling connect after this will allow the other methods to
+    // succeed again.
+    //
+    // This method will fail if the the SurfaceMediaSource is not currently
+    // connected to the specified client API.
+    virtual status_t disconnect(int api);
+
+    // getqueuedCount returns the number of queued frames waiting in the
+    // FIFO. In asynchronous mode, this always returns 0 or 1 since
+    // frames are not accumulating in the FIFO.
+    size_t getQueuedCount() const;
+
+    // setBufferCountServer set the buffer count. If the client has requested
+    // a buffer count using setBufferCount, the server-buffer count will
+    // take effect once the client sets the count back to zero.
+    status_t setBufferCountServer(int bufferCount);
+
+    // getTimestamp retrieves the timestamp associated with the image
+    // set by the most recent call to read()
+    //
+    // The timestamp is in nanoseconds, and is monotonically increasing. Its
+    // other semantics (zero point, etc) are source-dependent and should be
+    // documented by the source.
+    int64_t getTimestamp();
+
+    // setFrameAvailableListener sets the listener object that will be notified
+    // when a new frame becomes available.
+    void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
+
+    // getCurrentBuffer returns the buffer associated with the current image.
+    sp<GraphicBuffer> getCurrentBuffer() const;
+
+    // dump our state in a String
+    void dump(String8& result) const;
+    void dump(String8& result, const char* prefix, char* buffer,
+                                                    size_t SIZE) const;
+
+    // isMetaDataStoredInVideoBuffers tells the encoder whether we will
+    // pass metadata through the buffers. Currently, it is force set to true
+    bool isMetaDataStoredInVideoBuffers() const;
+
+protected:
+
+    // freeAllBuffers frees the resources (both GraphicBuffer and EGLImage) for
+    // all slots.
+    void freeAllBuffers();
+    static bool isExternalFormat(uint32_t format);
+
+private:
+
+    status_t setBufferCountServerLocked(int bufferCount);
+
+    enum { INVALID_BUFFER_SLOT = -1 };
+
+    struct BufferSlot {
+
+        BufferSlot()
+            : mBufferState(BufferSlot::FREE),
+              mRequestBufferCalled(false),
+              mTimestamp(0) {
+        }
+
+        // mGraphicBuffer points to the buffer allocated for this slot or is
+        // NULL if no buffer has been allocated.
+        sp<GraphicBuffer> mGraphicBuffer;
+
+        // BufferState represents the different states in which a buffer slot
+        // can be.
+        enum BufferState {
+            // FREE indicates that the buffer is not currently being used and
+            // will not be used in the future until it gets dequeued and
+            // subseqently queued by the client.
+            FREE = 0,
+
+            // DEQUEUED indicates that the buffer has been dequeued by the
+            // client, but has not yet been queued or canceled. The buffer is
+            // considered 'owned' by the client, and the server should not use
+            // it for anything.
+            //
+            // Note that when in synchronous-mode (mSynchronousMode == true),
+            // the buffer that's currently attached to the texture may be
+            // dequeued by the client.  That means that the current buffer can
+            // be in either the DEQUEUED or QUEUED state.  In asynchronous mode,
+            // however, the current buffer is always in the QUEUED state.
+            DEQUEUED = 1,
+
+            // QUEUED indicates that the buffer has been queued by the client,
+            // and has not since been made available for the client to dequeue.
+            // Attaching the buffer to the texture does NOT transition the
+            // buffer away from the QUEUED state. However, in Synchronous mode
+            // the current buffer may be dequeued by the client under some
+            // circumstances. See the note about the current buffer in the
+            // documentation for DEQUEUED.
+            QUEUED = 2,
+        };
+
+        // mBufferState is the current state of this buffer slot.
+        BufferState mBufferState;
+
+        // mRequestBufferCalled is used for validating that the client did
+        // call requestBuffer() when told to do so. Technically this is not
+        // needed but useful for debugging and catching client bugs.
+        bool mRequestBufferCalled;
+
+        // mTimestamp is the current timestamp for this buffer slot. This gets
+        // to set by queueBuffer each time this slot is queued.
+        int64_t mTimestamp;
+    };
+
+    // mSlots is the array of buffer slots that must be mirrored on the client
+    // side. This allows buffer ownership to be transferred between the client
+    // and server without sending a GraphicBuffer over binder. The entire array
+    // is initialized to NULL at construction time, and buffers are allocated
+    // for a slot when requestBuffer is called with that slot's index.
+    BufferSlot mSlots[NUM_BUFFER_SLOTS];
+
+    // mDefaultWidth holds the default width of allocated buffers. It is used
+    // in requestBuffers() if a width and height of zero is specified.
+    uint32_t mDefaultWidth;
+
+    // mDefaultHeight holds the default height of allocated buffers. It is used
+    // in requestBuffers() if a width and height of zero is specified.
+    uint32_t mDefaultHeight;
+
+    // mPixelFormat holds the pixel format of allocated buffers. It is used
+    // in requestBuffers() if a format of zero is specified.
+    uint32_t mPixelFormat;
+
+    // mBufferCount is the number of buffer slots that the client and server
+    // must maintain. It defaults to MIN_ASYNC_BUFFER_SLOTS and can be changed
+    // by calling setBufferCount or setBufferCountServer
+    int mBufferCount;
+
+    // mClientBufferCount is the number of buffer slots requested by the
+    // client. The default is zero, which means the client doesn't care how
+    // many buffers there are
+    int mClientBufferCount;
+
+    // mServerBufferCount buffer count requested by the server-side
+    int mServerBufferCount;
+
+    // mCurrentSlot is the buffer slot index of the buffer that is currently
+    // being used by buffer consumer
+    // (e.g. StageFrightRecorder in the case of SurfaceMediaSource or GLTexture
+    // in the case of SurfaceTexture).
+    // It is initialized to INVALID_BUFFER_SLOT,
+    // indicating that no buffer slot is currently bound to the texture. Note,
+    // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean
+    // that no buffer is bound to the texture. A call to setBufferCount will
+    // reset mCurrentTexture to INVALID_BUFFER_SLOT.
+    int mCurrentSlot;
+
+
+    // mCurrentBuf is the graphic buffer of the current slot to be used by
+    // buffer consumer. It's possible that this buffer is not associated
+    // with any buffer slot, so we must track it separately in order to
+    // properly use IGraphicBufferAlloc::freeAllGraphicBuffersExcept.
+    sp<GraphicBuffer> mCurrentBuf;
+
+
+    // mCurrentTimestamp is the timestamp for the current texture. It
+    // gets set to mLastQueuedTimestamp each time updateTexImage is called.
+    int64_t mCurrentTimestamp;
+
+    // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to
+    // allocate new GraphicBuffer objects.
+    sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
+
+    // mFrameAvailableListener is the listener object that will be called when a
+    // new frame becomes available. If it is not NULL it will be called from
+    // queueBuffer.
+    sp<FrameAvailableListener> mFrameAvailableListener;
+
+    // mSynchronousMode whether we're in synchronous mode or not
+    bool mSynchronousMode;
+
+    // mConnectedApi indicates the API that is currently connected to this
+    // SurfaceTexture.  It defaults to NO_CONNECTED_API (= 0), and gets updated
+    // by the connect and disconnect methods.
+    int mConnectedApi;
+
+    // mDequeueCondition condition used for dequeueBuffer in synchronous mode
+    mutable Condition mDequeueCondition;
+
+
+    // mQueue is a FIFO of queued buffers used in synchronous mode
+    typedef Vector<int> Fifo;
+    Fifo mQueue;
+
+    // mMutex is the mutex used to prevent concurrent access to the member
+    // variables of SurfaceMediaSource objects. It must be locked whenever the
+    // member variables are accessed.
+    mutable Mutex mMutex;
+
+    ////////////////////////// For MediaSource
+    // Set to a default of 30 fps if not specified by the client side
+    int32_t mFrameRate;
+
+    // mStarted is a flag to check if the recording has started
+    bool mStarted;
+
+    // mFrameAvailableCondition condition used to indicate whether there
+    // is a frame available for dequeuing
+    Condition mFrameAvailableCondition;
+    Condition mFrameCompleteCondition;
+
+    // Avoid copying and equating and default constructor
+    DISALLOW_IMPLICIT_CONSTRUCTORS(SurfaceMediaSource);
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_GUI_SURFACEMEDIASOURCE_H
diff --git a/include/media/stagefright/openmax/OMX_IVCommon.h b/include/media/stagefright/openmax/OMX_IVCommon.h
index 7ed072b..97170d7 100644
--- a/include/media/stagefright/openmax/OMX_IVCommon.h
+++ b/include/media/stagefright/openmax/OMX_IVCommon.h
@@ -16,29 +16,29 @@
  * -------------------------------------------------------------------
  */
 /**
- * Copyright (c) 2008 The Khronos Group Inc. 
- * 
+ * Copyright (c) 2008 The Khronos Group Inc.
+ *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
  * "Software"), to deal in the Software without restriction, including
  * without limitation the rights to use, copy, modify, merge, publish,
  * distribute, sublicense, and/or sell copies of the Software, and to
  * permit persons to whom the Software is furnished to do so, subject
- * to the following conditions: 
+ * to the following conditions:
  * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software. 
- * 
+ * in all copies or substantial portions of the Software.
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
 
-/** 
+/**
  * @file OMX_IVCommon.h - OpenMax IL version 1.1.2
  *  The structures needed by Video and Image components to exchange
  *  parameters and configuration data with the components.
@@ -53,7 +53,7 @@
 /**
  * Each OMX header must include all required header files to allow the header
  * to compile without errors.  The includes below are required for this header
- * file to compile successfully 
+ * file to compile successfully
  */
 
 #include <OMX_Core.h>
@@ -64,8 +64,8 @@
  */
 
 
-/** 
- * Enumeration defining possible uncompressed image/video formats. 
+/**
+ * Enumeration defining possible uncompressed image/video formats.
  *
  * ENUMS:
  *  Unused                 : Placeholder value when format is N/A
@@ -113,7 +113,7 @@
     OMX_COLOR_Format16bitBGR565,
     OMX_COLOR_Format18bitRGB666,
     OMX_COLOR_Format18bitARGB1665,
-    OMX_COLOR_Format19bitARGB1666, 
+    OMX_COLOR_Format19bitARGB1666,
     OMX_COLOR_Format24bitRGB888,
     OMX_COLOR_Format24bitBGR888,
     OMX_COLOR_Format24bitARGB1887,
@@ -136,55 +136,62 @@
     OMX_COLOR_FormatRawBayer8bit,
     OMX_COLOR_FormatRawBayer10bit,
     OMX_COLOR_FormatRawBayer8bitcompressed,
-    OMX_COLOR_FormatL2, 
-    OMX_COLOR_FormatL4, 
-    OMX_COLOR_FormatL8, 
-    OMX_COLOR_FormatL16, 
-    OMX_COLOR_FormatL24, 
+    OMX_COLOR_FormatL2,
+    OMX_COLOR_FormatL4,
+    OMX_COLOR_FormatL8,
+    OMX_COLOR_FormatL16,
+    OMX_COLOR_FormatL24,
     OMX_COLOR_FormatL32,
     OMX_COLOR_FormatYUV420PackedSemiPlanar,
     OMX_COLOR_FormatYUV422PackedSemiPlanar,
     OMX_COLOR_Format18BitBGR666,
     OMX_COLOR_Format24BitARGB6666,
     OMX_COLOR_Format24BitABGR6666,
-    OMX_COLOR_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_COLOR_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_COLOR_FormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+    /**<Reserved android opaque colorformat. Tells the encoder that
+     * the actual colorformat will be  relayed by the
+     * Gralloc Buffers.
+     * FIXME: In the process of reserving some enum values for
+     * Android-specific OMX IL colorformats. Change this enum to
+     * an acceptable range once that is done.*/
+    OMX_COLOR_FormatAndroidOpaque = 0x7F000001,
     OMX_TI_COLOR_FormatYUV420PackedSemiPlanar = 0x7F000100,
     OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00,
     OMX_COLOR_FormatMax = 0x7FFFFFFF
 } OMX_COLOR_FORMATTYPE;
 
 
-/** 
+/**
  * Defines the matrix for conversion from RGB to YUV or vice versa.
- * iColorMatrix should be initialized with the fixed point values 
+ * iColorMatrix should be initialized with the fixed point values
  * used in converting between formats.
  */
 typedef struct OMX_CONFIG_COLORCONVERSIONTYPE {
     OMX_U32 nSize;              /**< Size of the structure in bytes */
-    OMX_VERSIONTYPE nVersion;   /**< OMX specification version info */ 
+    OMX_VERSIONTYPE nVersion;   /**< OMX specification version info */
     OMX_U32 nPortIndex;         /**< Port that this struct applies to */
     OMX_S32 xColorMatrix[3][3]; /**< Stored in signed Q16 format */
     OMX_S32 xColorOffset[4];    /**< Stored in signed Q16 format */
 }OMX_CONFIG_COLORCONVERSIONTYPE;
 
 
-/** 
- * Structure defining percent to scale each frame dimension.  For example:  
+/**
+ * Structure defining percent to scale each frame dimension.  For example:
  * To make the width 50% larger, use fWidth = 1.5 and to make the width
  * 1/2 the original size, use fWidth = 0.5
  */
 typedef struct OMX_CONFIG_SCALEFACTORTYPE {
     OMX_U32 nSize;            /**< Size of the structure in bytes */
-    OMX_VERSIONTYPE nVersion; /**< OMX specification version info */ 
+    OMX_VERSIONTYPE nVersion; /**< OMX specification version info */
     OMX_U32 nPortIndex;       /**< Port that this struct applies to */
     OMX_S32 xWidth;           /**< Fixed point value stored as Q16 */
     OMX_S32 xHeight;          /**< Fixed point value stored as Q16 */
 }OMX_CONFIG_SCALEFACTORTYPE;
 
 
-/** 
- * Enumeration of possible image filter types 
+/**
+ * Enumeration of possible image filter types
  */
 typedef enum OMX_IMAGEFILTERTYPE {
     OMX_ImageFilterNone,
@@ -195,23 +202,23 @@
     OMX_ImageFilterOilPaint,
     OMX_ImageFilterHatch,
     OMX_ImageFilterGpen,
-    OMX_ImageFilterAntialias, 
-    OMX_ImageFilterDeRing,       
+    OMX_ImageFilterAntialias,
+    OMX_ImageFilterDeRing,
     OMX_ImageFilterSolarize,
-    OMX_ImageFilterKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_ImageFilterKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_ImageFilterVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_ImageFilterMax = 0x7FFFFFFF
 } OMX_IMAGEFILTERTYPE;
 
 
-/** 
- * Image filter configuration 
+/**
+ * Image filter configuration
  *
  * STRUCT MEMBERS:
- *  nSize        : Size of the structure in bytes       
+ *  nSize        : Size of the structure in bytes
  *  nVersion     : OMX specification version information
- *  nPortIndex   : Port that this structure applies to 
- *  eImageFilter : Image filter type enumeration      
+ *  nPortIndex   : Port that this structure applies to
+ *  eImageFilter : Image filter type enumeration
  */
 typedef struct OMX_CONFIG_IMAGEFILTERTYPE {
     OMX_U32 nSize;
@@ -221,22 +228,22 @@
 } OMX_CONFIG_IMAGEFILTERTYPE;
 
 
-/** 
- * Customized U and V for color enhancement 
+/**
+ * Customized U and V for color enhancement
  *
  * STRUCT MEMBERS:
  *  nSize             : Size of the structure in bytes
- *  nVersion          : OMX specification version information 
+ *  nVersion          : OMX specification version information
  *  nPortIndex        : Port that this structure applies to
  *  bColorEnhancement : Enable/disable color enhancement
- *  nCustomizedU      : Practical values: 16-240, range: 0-255, value set for 
+ *  nCustomizedU      : Practical values: 16-240, range: 0-255, value set for
  *                      U component
- *  nCustomizedV      : Practical values: 16-240, range: 0-255, value set for 
+ *  nCustomizedV      : Practical values: 16-240, range: 0-255, value set for
  *                      V component
  */
 typedef struct OMX_CONFIG_COLORENHANCEMENTTYPE {
     OMX_U32 nSize;
-    OMX_VERSIONTYPE nVersion; 
+    OMX_VERSIONTYPE nVersion;
     OMX_U32 nPortIndex;
     OMX_BOOL bColorEnhancement;
     OMX_U8 nCustomizedU;
@@ -244,12 +251,12 @@
 } OMX_CONFIG_COLORENHANCEMENTTYPE;
 
 
-/** 
- * Define color key and color key mask 
+/**
+ * Define color key and color key mask
  *
  * STRUCT MEMBERS:
  *  nSize      : Size of the structure in bytes
- *  nVersion   : OMX specification version information 
+ *  nVersion   : OMX specification version information
  *  nPortIndex : Port that this structure applies to
  *  nARGBColor : 32bit Alpha, Red, Green, Blue Color
  *  nARGBMask  : 32bit Mask for Alpha, Red, Green, Blue channels
@@ -263,12 +270,12 @@
 } OMX_CONFIG_COLORKEYTYPE;
 
 
-/** 
- * List of color blend types for pre/post processing 
+/**
+ * List of color blend types for pre/post processing
  *
  * ENUMS:
  *  None          : No color blending present
- *  AlphaConstant : Function is (alpha_constant * src) + 
+ *  AlphaConstant : Function is (alpha_constant * src) +
  *                  (1 - alpha_constant) * dst)
  *  AlphaPerPixel : Function is (alpha * src) + (1 - alpha) * dst)
  *  Alternate     : Function is alternating pixels from src and dst
@@ -284,21 +291,21 @@
     OMX_ColorBlendAnd,
     OMX_ColorBlendOr,
     OMX_ColorBlendInvert,
-    OMX_ColorBlendKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_ColorBlendKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_ColorBlendVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_ColorBlendMax = 0x7FFFFFFF
 } OMX_COLORBLENDTYPE;
 
 
-/** 
- * Color blend configuration 
+/**
+ * Color blend configuration
  *
  * STRUCT MEMBERS:
- *  nSize             : Size of the structure in bytes                        
- *  nVersion          : OMX specification version information                
- *  nPortIndex        : Port that this structure applies to                   
+ *  nSize             : Size of the structure in bytes
+ *  nVersion          : OMX specification version information
+ *  nPortIndex        : Port that this structure applies to
  *  nRGBAlphaConstant : Constant global alpha values when global alpha is used
- *  eColorBlend       : Color blend type enumeration                         
+ *  eColorBlend       : Color blend type enumeration
  */
 typedef struct OMX_CONFIG_COLORBLENDTYPE {
     OMX_U32 nSize;
@@ -309,15 +316,15 @@
 } OMX_CONFIG_COLORBLENDTYPE;
 
 
-/** 
+/**
  * Hold frame dimension
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes      
+ *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
- *  nPortIndex : Port that this structure applies to     
- *  nWidth     : Frame width in pixels                 
- *  nHeight    : Frame height in pixels                
+ *  nPortIndex : Port that this structure applies to
+ *  nWidth     : Frame width in pixels
+ *  nHeight    : Frame height in pixels
  */
 typedef struct OMX_FRAMESIZETYPE {
     OMX_U32 nSize;
@@ -329,69 +336,69 @@
 
 
 /**
- * Rotation configuration 
+ * Rotation configuration
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes             
+ *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
  *  nPortIndex : Port that this structure applies to
- *  nRotation  : +/- integer rotation value               
+ *  nRotation  : +/- integer rotation value
  */
 typedef struct OMX_CONFIG_ROTATIONTYPE {
     OMX_U32 nSize;
     OMX_VERSIONTYPE nVersion;
     OMX_U32 nPortIndex;
-    OMX_S32 nRotation; 
+    OMX_S32 nRotation;
 } OMX_CONFIG_ROTATIONTYPE;
 
 
-/** 
- * Possible mirroring directions for pre/post processing 
+/**
+ * Possible mirroring directions for pre/post processing
  *
  * ENUMS:
- *  None       : No mirroring                         
- *  Vertical   : Vertical mirroring, flip on X axis   
- *  Horizontal : Horizontal mirroring, flip on Y axis  
+ *  None       : No mirroring
+ *  Vertical   : Vertical mirroring, flip on X axis
+ *  Horizontal : Horizontal mirroring, flip on Y axis
  *  Both       : Both vertical and horizontal mirroring
  */
 typedef enum OMX_MIRRORTYPE {
     OMX_MirrorNone = 0,
     OMX_MirrorVertical,
     OMX_MirrorHorizontal,
-    OMX_MirrorBoth, 
-    OMX_MirrorKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_MirrorBoth,
+    OMX_MirrorKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_MirrorVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
-    OMX_MirrorMax = 0x7FFFFFFF   
+    OMX_MirrorMax = 0x7FFFFFFF
 } OMX_MIRRORTYPE;
 
 
-/** 
- * Mirroring configuration 
+/**
+ * Mirroring configuration
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes      
+ *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
- *  nPortIndex : Port that this structure applies to  
- *  eMirror    : Mirror type enumeration              
+ *  nPortIndex : Port that this structure applies to
+ *  eMirror    : Mirror type enumeration
  */
 typedef struct OMX_CONFIG_MIRRORTYPE {
     OMX_U32 nSize;
-    OMX_VERSIONTYPE nVersion; 
+    OMX_VERSIONTYPE nVersion;
     OMX_U32 nPortIndex;
     OMX_MIRRORTYPE  eMirror;
 } OMX_CONFIG_MIRRORTYPE;
 
 
-/** 
- * Position information only 
+/**
+ * Position information only
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes               
+ *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
  *  nPortIndex : Port that this structure applies to
- *  nX         : X coordinate for the point                     
- *  nY         : Y coordinate for the point 
- */                      
+ *  nX         : X coordinate for the point
+ *  nY         : Y coordinate for the point
+ */
 typedef struct OMX_CONFIG_POINTTYPE {
     OMX_U32 nSize;
     OMX_VERSIONTYPE nVersion;
@@ -401,37 +408,37 @@
 } OMX_CONFIG_POINTTYPE;
 
 
-/** 
- * Frame size plus position 
+/**
+ * Frame size plus position
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes                    
- *  nVersion   : OMX specification version information      
- *  nPortIndex : Port that this structure applies to    
+ *  nSize      : Size of the structure in bytes
+ *  nVersion   : OMX specification version information
+ *  nPortIndex : Port that this structure applies to
  *  nLeft      : X Coordinate of the top left corner of the rectangle
  *  nTop       : Y Coordinate of the top left corner of the rectangle
- *  nWidth     : Width of the rectangle                              
- *  nHeight    : Height of the rectangle                             
+ *  nWidth     : Width of the rectangle
+ *  nHeight    : Height of the rectangle
  */
 typedef struct OMX_CONFIG_RECTTYPE {
     OMX_U32 nSize;
-    OMX_VERSIONTYPE nVersion;  
-    OMX_U32 nPortIndex; 
-    OMX_S32 nLeft; 
+    OMX_VERSIONTYPE nVersion;
+    OMX_U32 nPortIndex;
+    OMX_S32 nLeft;
     OMX_S32 nTop;
     OMX_U32 nWidth;
     OMX_U32 nHeight;
 } OMX_CONFIG_RECTTYPE;
 
 
-/** 
- * Deblocking state; it is required to be set up before starting the codec 
+/**
+ * Deblocking state; it is required to be set up before starting the codec
  *
  * STRUCT MEMBERS:
- *  nSize       : Size of the structure in bytes      
- *  nVersion    : OMX specification version information 
+ *  nSize       : Size of the structure in bytes
+ *  nVersion    : OMX specification version information
  *  nPortIndex  : Port that this structure applies to
- *  bDeblocking : Enable/disable deblocking mode    
+ *  bDeblocking : Enable/disable deblocking mode
  */
 typedef struct OMX_PARAM_DEBLOCKINGTYPE {
     OMX_U32 nSize;
@@ -441,13 +448,13 @@
 } OMX_PARAM_DEBLOCKINGTYPE;
 
 
-/** 
- * Stabilization state 
+/**
+ * Stabilization state
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes          
- *  nVersion   : OMX specification version information    
- *  nPortIndex : Port that this structure applies to   
+ *  nSize      : Size of the structure in bytes
+ *  nVersion   : OMX specification version information
+ *  nPortIndex : Port that this structure applies to
  *  bStab      : Enable/disable frame stabilization state
  */
 typedef struct OMX_CONFIG_FRAMESTABTYPE {
@@ -458,8 +465,8 @@
 } OMX_CONFIG_FRAMESTABTYPE;
 
 
-/** 
- * White Balance control type 
+/**
+ * White Balance control type
  *
  * STRUCT MEMBERS:
  *  SunLight : Referenced in JSR-234
@@ -476,20 +483,20 @@
     OMX_WhiteBalControlIncandescent,
     OMX_WhiteBalControlFlash,
     OMX_WhiteBalControlHorizon,
-    OMX_WhiteBalControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_WhiteBalControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_WhiteBalControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_WhiteBalControlMax = 0x7FFFFFFF
 } OMX_WHITEBALCONTROLTYPE;
 
 
-/** 
- * White Balance control configuration 
+/**
+ * White Balance control configuration
  *
  * STRUCT MEMBERS:
- *  nSize            : Size of the structure in bytes       
+ *  nSize            : Size of the structure in bytes
  *  nVersion         : OMX specification version information
- *  nPortIndex       : Port that this structure applies to                 
- *  eWhiteBalControl : White balance enumeration            
+ *  nPortIndex       : Port that this structure applies to
+ *  eWhiteBalControl : White balance enumeration
  */
 typedef struct OMX_CONFIG_WHITEBALCONTROLTYPE {
     OMX_U32 nSize;
@@ -499,8 +506,8 @@
 } OMX_CONFIG_WHITEBALCONTROLTYPE;
 
 
-/** 
- * Exposure control type 
+/**
+ * Exposure control type
  */
 typedef enum OMX_EXPOSURECONTROLTYPE {
     OMX_ExposureControlOff = 0,
@@ -513,20 +520,20 @@
     OMX_ExposureControlBeach,
     OMX_ExposureControlLargeAperture,
     OMX_ExposureControlSmallApperture,
-    OMX_ExposureControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_ExposureControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_ExposureControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_ExposureControlMax = 0x7FFFFFFF
 } OMX_EXPOSURECONTROLTYPE;
 
 
-/** 
- * White Balance control configuration 
+/**
+ * White Balance control configuration
  *
  * STRUCT MEMBERS:
- *  nSize            : Size of the structure in bytes      
+ *  nSize            : Size of the structure in bytes
  *  nVersion         : OMX specification version information
- *  nPortIndex       : Port that this structure applies to                
- *  eExposureControl : Exposure control enumeration         
+ *  nPortIndex       : Port that this structure applies to
+ *  eExposureControl : Exposure control enumeration
  */
 typedef struct OMX_CONFIG_EXPOSURECONTROLTYPE {
     OMX_U32 nSize;
@@ -536,16 +543,16 @@
 } OMX_CONFIG_EXPOSURECONTROLTYPE;
 
 
-/** 
- * Defines sensor supported mode. 
+/**
+ * Defines sensor supported mode.
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes           
+ *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
- *  nPortIndex : Port that this structure applies to 
- *  nFrameRate : Single shot mode is indicated by a 0     
+ *  nPortIndex : Port that this structure applies to
+ *  nFrameRate : Single shot mode is indicated by a 0
  *  bOneShot   : Enable for single shot, disable for streaming
- *  sFrameSize : Framesize                                          
+ *  sFrameSize : Framesize
  */
 typedef struct OMX_PARAM_SENSORMODETYPE {
     OMX_U32 nSize;
@@ -557,13 +564,13 @@
 } OMX_PARAM_SENSORMODETYPE;
 
 
-/** 
- * Defines contrast level 
+/**
+ * Defines contrast level
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes                              
- *  nVersion   : OMX specification version information                
- *  nPortIndex : Port that this structure applies to                 
+ *  nSize      : Size of the structure in bytes
+ *  nVersion   : OMX specification version information
+ *  nPortIndex : Port that this structure applies to
  *  nContrast  : Values allowed for contrast -100 to 100, zero means no change
  */
 typedef struct OMX_CONFIG_CONTRASTTYPE {
@@ -574,14 +581,14 @@
 } OMX_CONFIG_CONTRASTTYPE;
 
 
-/** 
- * Defines brightness level 
+/**
+ * Defines brightness level
  *
  * STRUCT MEMBERS:
- *  nSize       : Size of the structure in bytes          
- *  nVersion    : OMX specification version information 
- *  nPortIndex  : Port that this structure applies to 
- *  nBrightness : 0-100%        
+ *  nSize       : Size of the structure in bytes
+ *  nVersion    : OMX specification version information
+ *  nPortIndex  : Port that this structure applies to
+ *  nBrightness : 0-100%
  */
 typedef struct OMX_CONFIG_BRIGHTNESSTYPE {
     OMX_U32 nSize;
@@ -591,16 +598,16 @@
 } OMX_CONFIG_BRIGHTNESSTYPE;
 
 
-/** 
- * Defines backlight level configuration for a video sink, e.g. LCD panel 
+/**
+ * Defines backlight level configuration for a video sink, e.g. LCD panel
  *
  * STRUCT MEMBERS:
  *  nSize      : Size of the structure in bytes
- *  nVersion   : OMX specification version information 
+ *  nVersion   : OMX specification version information
  *  nPortIndex : Port that this structure applies to
  *  nBacklight : Values allowed for backlight 0-100%
- *  nTimeout   : Number of milliseconds before backlight automatically turns 
- *               off.  A value of 0x0 disables backight timeout 
+ *  nTimeout   : Number of milliseconds before backlight automatically turns
+ *               off.  A value of 0x0 disables backight timeout
  */
 typedef struct OMX_CONFIG_BACKLIGHTTYPE {
     OMX_U32 nSize;
@@ -611,12 +618,12 @@
 } OMX_CONFIG_BACKLIGHTTYPE;
 
 
-/** 
- * Defines setting for Gamma 
+/**
+ * Defines setting for Gamma
  *
  * STRUCT MEMBERS:
  *  nSize      : Size of the structure in bytes
- *  nVersion   : OMX specification version information 
+ *  nVersion   : OMX specification version information
  *  nPortIndex : Port that this structure applies to
  *  nGamma     : Values allowed for gamma -100 to 100, zero means no change
  */
@@ -628,14 +635,14 @@
 } OMX_CONFIG_GAMMATYPE;
 
 
-/** 
- * Define for setting saturation 
- * 
+/**
+ * Define for setting saturation
+ *
  * STRUCT MEMBERS:
  *  nSize       : Size of the structure in bytes
  *  nVersion    : OMX specification version information
  *  nPortIndex  : Port that this structure applies to
- *  nSaturation : Values allowed for saturation -100 to 100, zero means 
+ *  nSaturation : Values allowed for saturation -100 to 100, zero means
  *                no change
  */
 typedef struct OMX_CONFIG_SATURATIONTYPE {
@@ -646,14 +653,14 @@
 } OMX_CONFIG_SATURATIONTYPE;
 
 
-/** 
- * Define for setting Lightness 
+/**
+ * Define for setting Lightness
  *
  * STRUCT MEMBERS:
  *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
  *  nPortIndex : Port that this structure applies to
- *  nLightness : Values allowed for lightness -100 to 100, zero means no 
+ *  nLightness : Values allowed for lightness -100 to 100, zero means no
  *               change
  */
 typedef struct OMX_CONFIG_LIGHTNESSTYPE {
@@ -664,17 +671,17 @@
 } OMX_CONFIG_LIGHTNESSTYPE;
 
 
-/** 
- * Plane blend configuration 
+/**
+ * Plane blend configuration
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes 
+ *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
  *  nPortIndex : Index of input port associated with the plane.
- *  nDepth     : Depth of the plane in relation to the screen. Higher 
- *               numbered depths are "behind" lower number depths.  
+ *  nDepth     : Depth of the plane in relation to the screen. Higher
+ *               numbered depths are "behind" lower number depths.
  *               This number defaults to the Port Index number.
- *  nAlpha     : Transparency blending component for the entire plane.  
+ *  nAlpha     : Transparency blending component for the entire plane.
  *               See blending modes for more detail.
  */
 typedef struct OMX_CONFIG_PLANEBLENDTYPE {
@@ -686,17 +693,17 @@
 } OMX_CONFIG_PLANEBLENDTYPE;
 
 
-/** 
+/**
  * Define interlace type
  *
  * STRUCT MEMBERS:
- *  nSize                 : Size of the structure in bytes 
- *  nVersion              : OMX specification version information 
+ *  nSize                 : Size of the structure in bytes
+ *  nVersion              : OMX specification version information
  *  nPortIndex            : Port that this structure applies to
- *  bEnable               : Enable control variable for this functionality 
+ *  bEnable               : Enable control variable for this functionality
  *                          (see below)
- *  nInterleavePortIndex  : Index of input or output port associated with  
- *                          the interleaved plane. 
+ *  nInterleavePortIndex  : Index of input or output port associated with
+ *                          the interleaved plane.
  *  pPlanarPortIndexes[4] : Index of input or output planar ports.
  */
 typedef struct OMX_PARAM_INTERLEAVETYPE {
@@ -708,8 +715,8 @@
 } OMX_PARAM_INTERLEAVETYPE;
 
 
-/** 
- * Defines the picture effect used for an input picture 
+/**
+ * Defines the picture effect used for an input picture
  */
 typedef enum OMX_TRANSITIONEFFECTTYPE {
     OMX_EffectNone,
@@ -719,18 +726,18 @@
     OMX_EffectDissolve,
     OMX_EffectWipe,
     OMX_EffectUnspecifiedMixOfTwoScenes,
-    OMX_EffectKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_EffectKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_EffectVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_EffectMax = 0x7FFFFFFF
 } OMX_TRANSITIONEFFECTTYPE;
 
 
-/** 
- * Structure used to configure current transition effect 
+/**
+ * Structure used to configure current transition effect
  *
  * STRUCT MEMBERS:
  * nSize      : Size of the structure in bytes
- * nVersion   : OMX specification version information 
+ * nVersion   : OMX specification version information
  * nPortIndex : Port that this structure applies to
  * eEffect    : Effect to enable
  */
@@ -742,43 +749,43 @@
 } OMX_CONFIG_TRANSITIONEFFECTTYPE;
 
 
-/** 
- * Defines possible data unit types for encoded video data. The data unit 
+/**
+ * Defines possible data unit types for encoded video data. The data unit
  * types are used both for encoded video input for playback as well as
- * encoded video output from recording. 
+ * encoded video output from recording.
  */
 typedef enum OMX_DATAUNITTYPE {
     OMX_DataUnitCodedPicture,
     OMX_DataUnitVideoSegment,
     OMX_DataUnitSeveralSegments,
     OMX_DataUnitArbitraryStreamSection,
-    OMX_DataUnitKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_DataUnitKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_DataUnitVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_DataUnitMax = 0x7FFFFFFF
 } OMX_DATAUNITTYPE;
 
 
-/** 
- * Defines possible encapsulation types for coded video data unit. The 
- * encapsulation information is used both for encoded video input for 
- * playback as well as encoded video output from recording. 
+/**
+ * Defines possible encapsulation types for coded video data unit. The
+ * encapsulation information is used both for encoded video input for
+ * playback as well as encoded video output from recording.
  */
 typedef enum OMX_DATAUNITENCAPSULATIONTYPE {
     OMX_DataEncapsulationElementaryStream,
     OMX_DataEncapsulationGenericPayload,
     OMX_DataEncapsulationRtpPayload,
-    OMX_DataEncapsulationKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_DataEncapsulationKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_DataEncapsulationVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_DataEncapsulationMax = 0x7FFFFFFF
 } OMX_DATAUNITENCAPSULATIONTYPE;
 
 
-/** 
- * Structure used to configure the type of being decoded/encoded 
+/**
+ * Structure used to configure the type of being decoded/encoded
  */
 typedef struct OMX_PARAM_DATAUNITTYPE {
     OMX_U32 nSize;            /**< Size of the structure in bytes */
-    OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ 
+    OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
     OMX_U32 nPortIndex;       /**< Port that this structure applies to */
     OMX_DATAUNITTYPE eUnitType;
     OMX_DATAUNITENCAPSULATIONTYPE eEncapsulationType;
@@ -786,25 +793,25 @@
 
 
 /**
- * Defines dither types 
+ * Defines dither types
  */
 typedef enum OMX_DITHERTYPE {
     OMX_DitherNone,
     OMX_DitherOrdered,
     OMX_DitherErrorDiffusion,
     OMX_DitherOther,
-    OMX_DitherKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_DitherKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_DitherVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_DitherMax = 0x7FFFFFFF
 } OMX_DITHERTYPE;
 
 
-/** 
- * Structure used to configure current type of dithering 
+/**
+ * Structure used to configure current type of dithering
  */
 typedef struct OMX_CONFIG_DITHERTYPE {
     OMX_U32 nSize;            /**< Size of the structure in bytes */
-    OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ 
+    OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
     OMX_U32 nPortIndex;       /**< Port that this structure applies to */
     OMX_DITHERTYPE eDither;   /**< Type of dithering to use */
 } OMX_CONFIG_DITHERTYPE;
@@ -813,28 +820,28 @@
     OMX_U32 nSize;
     OMX_VERSIONTYPE nVersion;
     OMX_U32 nPortIndex;     /**< Port that this structure applies to */
-    OMX_BOOL bContinuous;   /**< If true then ignore frame rate and emit capture 
+    OMX_BOOL bContinuous;   /**< If true then ignore frame rate and emit capture
                              *   data as fast as possible (otherwise obey port's frame rate). */
-    OMX_BOOL bFrameLimited; /**< If true then terminate capture after the port emits the 
-                             *   specified number of frames (otherwise the port does not 
-                             *   terminate the capture until instructed to do so by the client). 
-                             *   Even if set, the client may manually terminate the capture prior 
+    OMX_BOOL bFrameLimited; /**< If true then terminate capture after the port emits the
+                             *   specified number of frames (otherwise the port does not
+                             *   terminate the capture until instructed to do so by the client).
+                             *   Even if set, the client may manually terminate the capture prior
                              *   to reaching the limit. */
     OMX_U32 nFrameLimit;      /**< Limit on number of frames emitted during a capture (only
                                *   valid if bFrameLimited is set). */
 } OMX_CONFIG_CAPTUREMODETYPE;
 
 typedef enum OMX_METERINGTYPE {
- 
+
     OMX_MeteringModeAverage,     /**< Center-weighted average metering. */
     OMX_MeteringModeSpot,  	      /**< Spot (partial) metering. */
     OMX_MeteringModeMatrix,      /**< Matrix or evaluative metering. */
- 
-    OMX_MeteringKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+
+    OMX_MeteringKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_MeteringVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_EVModeMax = 0x7fffffff
 } OMX_METERINGTYPE;
- 
+
 typedef struct OMX_CONFIG_EXPOSUREVALUETYPE {
     OMX_U32 nSize;
     OMX_VERSIONTYPE nVersion;
@@ -843,14 +850,14 @@
     OMX_S32 xEVCompensation;      /**< Fixed point value stored as Q16 */
     OMX_U32 nApertureFNumber;     /**< e.g. nApertureFNumber = 2 implies "f/2" - Q16 format */
     OMX_BOOL bAutoAperture;		/**< Whether aperture number is defined automatically */
-    OMX_U32 nShutterSpeedMsec;    /**< Shutterspeed in milliseconds */ 
-    OMX_BOOL bAutoShutterSpeed;	/**< Whether shutter speed is defined automatically */ 
+    OMX_U32 nShutterSpeedMsec;    /**< Shutterspeed in milliseconds */
+    OMX_BOOL bAutoShutterSpeed;	/**< Whether shutter speed is defined automatically */
     OMX_U32 nSensitivity;         /**< e.g. nSensitivity = 100 implies "ISO 100" */
     OMX_BOOL bAutoSensitivity;	/**< Whether sensitivity is defined automatically */
 } OMX_CONFIG_EXPOSUREVALUETYPE;
 
-/** 
- * Focus region configuration 
+/**
+ * Focus region configuration
  *
  * STRUCT MEMBERS:
  *  nSize           : Size of the structure in bytes
@@ -881,8 +888,8 @@
     OMX_BOOL bBottomRight;
 } OMX_CONFIG_FOCUSREGIONTYPE;
 
-/** 
- * Focus Status type 
+/**
+ * Focus Status type
  */
 typedef enum OMX_FOCUSSTATUSTYPE {
     OMX_FocusStatusOff = 0,
@@ -890,13 +897,13 @@
     OMX_FocusStatusReached,
     OMX_FocusStatusUnableToReach,
     OMX_FocusStatusLost,
-    OMX_FocusStatusKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_FocusStatusKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_FocusStatusVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_FocusStatusMax = 0x7FFFFFFF
 } OMX_FOCUSSTATUSTYPE;
 
-/** 
- * Focus status configuration 
+/**
+ * Focus status configuration
  *
  * STRUCT MEMBERS:
  *  nSize               : Size of the structure in bytes
diff --git a/media/libeffects/data/audio_effects.conf b/media/libeffects/data/audio_effects.conf
index e6a7b37..b8fa487 100644
--- a/media/libeffects/data/audio_effects.conf
+++ b/media/libeffects/data/audio_effects.conf
@@ -1,5 +1,10 @@
 # List of effect libraries to load. Each library element must contain a "path" element
 # giving the full path of the library .so file.
+#    libraries {
+#        <lib name> {
+#          path <lib path>
+#        }
+#    }
 libraries {
   bundle {
     path /system/lib/soundfx/libbundlewrapper.so
@@ -10,6 +15,9 @@
   visualizer {
     path /system/lib/soundfx/libvisualizer.so
   }
+  pre_processing {
+    path /system/lib/soundfx/libaudiopreprocessing.so
+  }
 }
 
 # list of effects to load. Each effect element must contain a "library" and a "uuid" element.
@@ -17,6 +25,16 @@
 # "libraries" element.
 # The name of the effect element is indicative, only the value of the "uuid" element
 # designates the effect.
+# The uuid is the implementation specific UUID as specified by the effect vendor. This is not the
+# generic effect type UUID.
+#    effects {
+#        <fx name> {
+#            library <lib name>
+#            uuid <effect uuid>
+#        }
+#        ...
+#    }
+
 effects {
   bassboost {
     library bundle
@@ -54,4 +72,55 @@
     library visualizer
     uuid d069d9e0-8329-11df-9168-0002a5d5c51b
   }
+  agc {
+    library pre_processing
+    uuid aa8130e0-66fc-11e0-bad0-0002a5d5c51b
+  }
+  aec {
+    library pre_processing
+    uuid bb392ec0-8d4d-11e0-a896-0002a5d5c51b
+  }
+  ns {
+    library pre_processing
+    uuid c06c8400-8e06-11e0-9cb6-0002a5d5c51b
+  }
 }
+# Audio preprocessor configurations.
+# The pre processor configuration consists in a list of elements each describing
+# pre processor settings for a given input source. Valid input source names are:
+# "mic", "camcorder", "voice_recognition", "voice_communication"
+# Each input source element contains a list of effects elements. The name of the effect
+# element must be the name of one of the effects in the "effects" list of the file.
+# Each effect element may optionally contain a list of parameters and their
+# default value to apply when the pre processor effect is created.
+# A parameter is defined by a "param" element and a "value" element. Each of these elements
+# consists in one or more elements specifying a type followed by a value.
+# The types defined are: "int", "short", "float", "bool" and "string"
+# When both "param" and "value" are a single int, a simple form is allowed where just
+# the param and value pair is present in the parameter description
+#    pre_processing {
+#        <input source name> {
+#            <fx name> {
+#                <param 1 name> {
+#                    param {
+#                        int|short|float|bool|string <value>
+#                        [ int|short|float|bool|string <value> ]
+#                        ...
+#                    }
+#                    value {
+#                        int|short|float|bool|string <value>
+#                        [ int|short|float|bool|string <value> ]
+#                        ...
+#                    }
+#                }
+#                <param 2 name > {<param> <value>}
+#                ...
+#            }
+#            ...
+#        }
+#        ...
+#    }
+
+#
+# TODO: add default audio pre processor configurations after debug and tuning phase
+#
diff --git a/media/libeffects/factory/Android.mk b/media/libeffects/factory/Android.mk
index 26265ae..2f2b974 100644
--- a/media/libeffects/factory/Android.mk
+++ b/media/libeffects/factory/Android.mk
@@ -14,4 +14,7 @@
 
 LOCAL_SHARED_LIBRARIES += libdl
 
+LOCAL_C_INCLUDES := \
+    system/media/audio_effects/include
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/factory/EffectsFactory.c b/media/libeffects/factory/EffectsFactory.c
index a9689bc..d333510 100644
--- a/media/libeffects/factory/EffectsFactory.c
+++ b/media/libeffects/factory/EffectsFactory.c
@@ -24,6 +24,7 @@
 
 #include <cutils/misc.h>
 #include <cutils/config_utils.h>
+#include <audio_effects/audio_effects_conf.h>
 
 static list_elem_t *gEffectList; // list of effect_entry_t: all currently created effects
 static list_elem_t *gLibraryList; // list of lib_entry_t: all currently loaded libraries
diff --git a/media/libeffects/factory/EffectsFactory.h b/media/libeffects/factory/EffectsFactory.h
index fcc0dba..c1d4319 100644
--- a/media/libeffects/factory/EffectsFactory.h
+++ b/media/libeffects/factory/EffectsFactory.h
@@ -26,13 +26,6 @@
 extern "C" {
 #endif
 
-#define AUDIO_EFFECT_DEFAULT_CONFIG_FILE "/system/etc/audio_effects.conf"
-#define AUDIO_EFFECT_VENDOR_CONFIG_FILE "/vendor/etc/audio_effects.conf"
-#define EFFECTS_TAG "effects"
-#define LIBRARIES_TAG "libraries"
-#define PATH_TAG "path"
-#define LIBRARY_TAG "library"
-#define UUID_TAG "uuid"
 
 typedef struct list_elem_s {
     void *object;
diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp
index 8d98900..0633744 100644
--- a/media/libmedia/AudioEffect.cpp
+++ b/media/libmedia/AudioEffect.cpp
@@ -47,11 +47,11 @@
                 effect_callback_t cbf,
                 void* user,
                 int sessionId,
-                audio_io_handle_t output
+                audio_io_handle_t io
                 )
     : mStatus(NO_INIT)
 {
-    mStatus = set(type, uuid, priority, cbf, user, sessionId, output);
+    mStatus = set(type, uuid, priority, cbf, user, sessionId, io);
 }
 
 AudioEffect::AudioEffect(const char *typeStr,
@@ -60,7 +60,7 @@
                 effect_callback_t cbf,
                 void* user,
                 int sessionId,
-                audio_io_handle_t output
+                audio_io_handle_t io
                 )
     : mStatus(NO_INIT)
 {
@@ -83,7 +83,7 @@
         }
     }
 
-    mStatus = set(pType, pUuid, priority, cbf, user, sessionId, output);
+    mStatus = set(pType, pUuid, priority, cbf, user, sessionId, io);
 }
 
 status_t AudioEffect::set(const effect_uuid_t *type,
@@ -92,13 +92,13 @@
                 effect_callback_t cbf,
                 void* user,
                 int sessionId,
-                audio_io_handle_t output)
+                audio_io_handle_t io)
 {
     sp<IEffect> iEffect;
     sp<IMemory> cblk;
     int enabled;
 
-    LOGV("set %p mUserData: %p", this, user);
+    LOGV("set %p mUserData: %p uuid: %p timeLow %08x", this, user, type, type ? type->timeLow : 0);
 
     if (mIEffect != 0) {
         LOGW("Effect already in use");
@@ -135,7 +135,7 @@
     mIEffectClient = new EffectClient(this);
 
     iEffect = audioFlinger->createEffect(getpid(), (effect_descriptor_t *)&mDescriptor,
-            mIEffectClient, priority, output, mSessionId, &mStatus, &mId, &enabled);
+            mIEffectClient, priority, io, mSessionId, &mStatus, &mId, &enabled);
 
     if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {
         LOGE("set(): AudioFlinger could not create effect, status: %d", mStatus);
@@ -419,6 +419,15 @@
     return af->getEffectDescriptor(uuid, descriptor);
 }
 
+
+status_t AudioEffect::queryDefaultPreProcessing(int audioSession,
+                                          effect_descriptor_t *descriptors,
+                                          uint32_t *count)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->queryDefaultPreProcessing(audioSession, descriptors, count);
+}
 // -------------------------------------------------------------------------
 
 status_t AudioEffect::stringToGuid(const char *str, effect_uuid_t *guid)
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 4c4aad0..1ec596e 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -162,8 +162,19 @@
 
     int channelCount = popcount(channelMask);
 
+    if (sessionId == 0 ) {
+        mSessionId = AudioSystem::newAudioSessionId();
+    } else {
+        mSessionId = sessionId;
+    }
+    LOGV("set(): mSessionId %d", mSessionId);
+
     audio_io_handle_t input = AudioSystem::getInput(inputSource,
-                                    sampleRate, format, channelMask, (audio_in_acoustics_t)flags);
+                                                    sampleRate,
+                                                    format,
+                                                    channelMask,
+                                                    (audio_in_acoustics_t)flags,
+                                                    mSessionId);
     if (input == 0) {
         LOGE("Could not get audio input for record source %d", inputSource);
         return BAD_VALUE;
@@ -187,8 +198,6 @@
         notificationFrames = frameCount/2;
     }
 
-    mSessionId = sessionId;
-
     // create the IAudioRecord
     status = openRecord_l(sampleRate, format, channelMask,
                         frameCount, flags, input);
@@ -589,8 +598,10 @@
 {
     mInput = AudioSystem::getInput(mInputSource,
                                 mCblk->sampleRate,
-                                mFormat, mChannelMask,
-                                (audio_in_acoustics_t)mFlags);
+                                mFormat,
+                                mChannelMask,
+                                (audio_in_acoustics_t)mFlags,
+                                mSessionId);
     return mInput;
 }
 
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 6cb3847..5009957 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -605,11 +605,12 @@
                                     uint32_t samplingRate,
                                     uint32_t format,
                                     uint32_t channels,
-                                    audio_in_acoustics_t acoustics)
+                                    audio_in_acoustics_t acoustics,
+                                    int sessionId)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return 0;
-    return aps->getInput(inputSource, samplingRate, format, channels, acoustics);
+    return aps->getInput(inputSource, samplingRate, format, channels, acoustics, sessionId);
 }
 
 status_t AudioSystem::startInput(audio_io_handle_t input)
@@ -678,14 +679,14 @@
 }
 
 status_t AudioSystem::registerEffect(effect_descriptor_t *desc,
-                                audio_io_handle_t output,
+                                audio_io_handle_t io,
                                 uint32_t strategy,
                                 int session,
                                 int id)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
-    return aps->registerEffect(desc, output, strategy, session, id);
+    return aps->registerEffect(desc, io, strategy, session, id);
 }
 
 status_t AudioSystem::unregisterEffect(int id)
@@ -695,9 +696,11 @@
     return aps->unregisterEffect(id);
 }
 
-status_t AudioSystem::isStreamActive(int stream, bool* state, uint32_t inPastMs) {
+status_t AudioSystem::isStreamActive(int stream, bool* state, uint32_t inPastMs)
+{
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
+    if (state == NULL) return BAD_VALUE;
     *state = aps->isStreamActive(stream, inPastMs);
     return NO_ERROR;
 }
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 9fbcee0..15f4be0 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -53,6 +53,7 @@
     UNREGISTER_EFFECT,
     IS_STREAM_ACTIVE,
     GET_DEVICES_FOR_STREAM,
+    QUERY_DEFAULT_PRE_PROCESSING
 };
 
 class BpAudioPolicyService : public BpInterface<IAudioPolicyService>
@@ -184,7 +185,8 @@
                                     uint32_t samplingRate,
                                     uint32_t format,
                                     uint32_t channels,
-                                    audio_in_acoustics_t acoustics)
+                                    audio_in_acoustics_t acoustics,
+                                    int audioSession)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
@@ -193,6 +195,7 @@
         data.writeInt32(static_cast <uint32_t>(format));
         data.writeInt32(channels);
         data.writeInt32(static_cast <uint32_t>(acoustics));
+        data.writeInt32(audioSession);
         remote()->transact(GET_INPUT, data, &reply);
         return static_cast <audio_io_handle_t> (reply.readInt32());
     }
@@ -285,7 +288,7 @@
     }
 
     virtual status_t registerEffect(effect_descriptor_t *desc,
-                                        audio_io_handle_t output,
+                                        audio_io_handle_t io,
                                         uint32_t strategy,
                                         int session,
                                         int id)
@@ -293,7 +296,7 @@
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
         data.write(desc, sizeof(effect_descriptor_t));
-        data.writeInt32(output);
+        data.writeInt32(io);
         data.writeInt32(strategy);
         data.writeInt32(session);
         data.writeInt32(id);
@@ -319,6 +322,31 @@
         remote()->transact(IS_STREAM_ACTIVE, data, &reply);
         return reply.readInt32();
     }
+
+    virtual status_t queryDefaultPreProcessing(int audioSession,
+                                               effect_descriptor_t *descriptors,
+                                               uint32_t *count)
+    {
+        if (descriptors == NULL || count == NULL) {
+            return BAD_VALUE;
+        }
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(audioSession);
+        data.writeInt32(*count);
+        status_t status = remote()->transact(QUERY_DEFAULT_PRE_PROCESSING, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = static_cast <status_t> (reply.readInt32());
+        uint32_t retCount = reply.readInt32();
+        if (retCount != 0) {
+            uint32_t numDesc = (retCount < *count) ? retCount : *count;
+            reply.read(descriptors, sizeof(effect_descriptor_t) * numDesc);
+        }
+        *count = retCount;
+        return status;
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -439,11 +467,13 @@
             uint32_t channels = data.readInt32();
             audio_in_acoustics_t acoustics =
                     static_cast <audio_in_acoustics_t>(data.readInt32());
+            int audioSession = data.readInt32();
             audio_io_handle_t input = getInput(inputSource,
                                                samplingRate,
                                                format,
                                                channels,
-                                               acoustics);
+                                               acoustics,
+                                               audioSession);
             reply->writeInt32(static_cast <int>(input));
             return NO_ERROR;
         } break;
@@ -528,12 +558,12 @@
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             effect_descriptor_t desc;
             data.read(&desc, sizeof(effect_descriptor_t));
-            audio_io_handle_t output = data.readInt32();
+            audio_io_handle_t io = data.readInt32();
             uint32_t strategy = data.readInt32();
             int session = data.readInt32();
             int id = data.readInt32();
             reply->writeInt32(static_cast <int32_t>(registerEffect(&desc,
-                                                                   output,
+                                                                   io,
                                                                    strategy,
                                                                    session,
                                                                    id)));
@@ -555,6 +585,29 @@
             return NO_ERROR;
         } break;
 
+        case QUERY_DEFAULT_PRE_PROCESSING: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            int audioSession = data.readInt32();
+            uint32_t count = data.readInt32();
+            uint32_t retCount = count;
+            effect_descriptor_t *descriptors =
+                    (effect_descriptor_t *)new char[count * sizeof(effect_descriptor_t)];
+            status_t status = queryDefaultPreProcessing(audioSession, descriptors, &retCount);
+            reply->writeInt32(status);
+            if (status != NO_ERROR && status != NO_MEMORY) {
+                retCount = 0;
+            }
+            reply->writeInt32(retCount);
+            if (retCount) {
+                if (retCount < count) {
+                    count = retCount;
+                }
+                reply->write(descriptors, sizeof(effect_descriptor_t) * count);
+            }
+            delete[] descriptors;
+            return status;
+        }
+
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index a44ef5a..38e111e 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -23,14 +23,17 @@
 #include <camera/ICamera.h>
 #include <media/IMediaRecorderClient.h>
 #include <media/IMediaRecorder.h>
+#include <gui/ISurfaceTexture.h>
 #include <unistd.h>
 
+
 namespace android {
 
 enum {
     RELEASE = IBinder::FIRST_CALL_TRANSACTION,
     INIT,
     CLOSE,
+    QUERY_SURFACE_MEDIASOURCE,
     RESET,
     STOP,
     START,
@@ -43,7 +46,6 @@
     SET_AUDIO_ENCODER,
     SET_OUTPUT_FILE_PATH,
     SET_OUTPUT_FILE_FD,
-    SET_OUTPUT_FILE_AUXILIARY_FD,
     SET_VIDEO_SIZE,
     SET_VIDEO_FRAMERATE,
     SET_PARAMETERS,
@@ -71,6 +73,19 @@
         return reply.readInt32();
     }
 
+    sp<ISurfaceTexture> querySurfaceMediaSource()
+    {
+        LOGV("Query SurfaceMediaSource");
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        remote()->transact(QUERY_SURFACE_MEDIASOURCE, data, &reply);
+        int returnedNull = reply.readInt32();
+        if (returnedNull) {
+            return NULL;
+        }
+        return interface_cast<ISurfaceTexture>(reply.readStrongBinder());
+    }
+
     status_t setPreviewSurface(const sp<Surface>& surface)
     {
         LOGV("setPreviewSurface(%p)", surface.get());
@@ -161,15 +176,6 @@
         return reply.readInt32();
     }
 
-    status_t setOutputFileAuxiliary(int fd) {
-        LOGV("setOutputFileAuxiliary(%d)", fd);
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
-        data.writeFileDescriptor(fd);
-        remote()->transact(SET_OUTPUT_FILE_AUXILIARY_FD, data, &reply);
-        return reply.readInt32();
-    }
-
     status_t setVideoSize(int width, int height)
     {
         LOGV("setVideoSize(%dx%d)", width, height);
@@ -388,13 +394,6 @@
             ::close(fd);
             return NO_ERROR;
         } break;
-        case SET_OUTPUT_FILE_AUXILIARY_FD: {
-            LOGV("SET_OUTPUT_FILE_AUXILIARY_FD");
-            CHECK_INTERFACE(IMediaRecorder, data, reply);
-            int fd = dup(data.readFileDescriptor());
-            reply->writeInt32(setOutputFileAuxiliary(fd));
-            return NO_ERROR;
-        } break;
         case SET_VIDEO_SIZE: {
             LOGV("SET_VIDEO_SIZE");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
@@ -440,6 +439,20 @@
             reply->writeInt32(setCamera(camera, proxy));
             return NO_ERROR;
         } break;
+        case QUERY_SURFACE_MEDIASOURCE: {
+            LOGV("QUERY_SURFACE_MEDIASOURCE");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            // call the mediaserver side to create
+            // a surfacemediasource
+            sp<ISurfaceTexture> surfaceMediaSource = querySurfaceMediaSource();
+            // The mediaserver might have failed to create a source
+            int returnedNull= (surfaceMediaSource == NULL) ? 1 : 0 ;
+            reply->writeInt32(returnedNull);
+            if (!returnedNull) {
+                reply->writeStrongBinder(surfaceMediaSource->asBinder());
+            }
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 069bbb7..f0f07a2 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -132,6 +132,16 @@
     LOGV("codec = %d", cap.mCodec);
 }
 
+/*static*/ void
+MediaProfiles::logVideoEditorCap(const MediaProfiles::VideoEditorCap& cap)
+{
+    LOGV("videoeditor cap:");
+    LOGV("mMaxInputFrameWidth = %d", cap.mMaxInputFrameWidth);
+    LOGV("mMaxInputFrameHeight = %d", cap.mMaxInputFrameHeight);
+    LOGV("mMaxOutputFrameWidth = %d", cap.mMaxOutputFrameWidth);
+    LOGV("mMaxOutputFrameHeight = %d", cap.mMaxOutputFrameHeight);
+}
+
 /*static*/ int
 MediaProfiles::findTagForName(const MediaProfiles::NameToTagMap *map, size_t nMappings, const char *name)
 {
@@ -368,6 +378,24 @@
     mStartTimeOffsets.replaceValueFor(cameraId, offsetTimeMs);
 }
 
+/*static*/ MediaProfiles::VideoEditorCap*
+MediaProfiles::createVideoEditorCap(const char **atts, MediaProfiles *profiles)
+{
+    CHECK(!strcmp("maxInputFrameWidth", atts[0]) &&
+          !strcmp("maxInputFrameHeight", atts[2])  &&
+          !strcmp("maxOutputFrameWidth", atts[4]) &&
+          !strcmp("maxOutputFrameHeight", atts[6]));
+
+    MediaProfiles::VideoEditorCap *pVideoEditorCap =
+        new MediaProfiles::VideoEditorCap(atoi(atts[1]), atoi(atts[3]),
+                atoi(atts[5]), atoi(atts[7]));
+
+    logVideoEditorCap(*pVideoEditorCap);
+    profiles->mVideoEditorCap = pVideoEditorCap;
+
+    return pVideoEditorCap;
+}
+
 /*static*/ void
 MediaProfiles::startElementHandler(void *userData, const char *name, const char **atts)
 {
@@ -398,6 +426,8 @@
             createCamcorderProfile(profiles->mCurrentCameraId, atts, profiles->mCameraIds));
     } else if (strcmp("ImageEncoding", name) == 0) {
         profiles->addImageEncodingQualityLevel(profiles->mCurrentCameraId, atts);
+    } else if (strcmp("VideoEditorCap", name) == 0) {
+        createVideoEditorCap(atts, profiles);
     }
 }
 
@@ -790,6 +820,17 @@
     profiles->mImageEncodingQualityLevels.add(levels);
 }
 
+/*static*/ void
+MediaProfiles::createDefaultVideoEditorCap(MediaProfiles *profiles)
+{
+    profiles->mVideoEditorCap =
+        new MediaProfiles::VideoEditorCap(
+                VIDEOEDITOR_DEFAULT_MAX_INPUT_FRAME_WIDTH,
+                VIDEOEDITOR_DEFUALT_MAX_INPUT_FRAME_HEIGHT,
+                VIDEOEDITOR_DEFAULT_MAX_OUTPUT_FRAME_WIDTH,
+                VIDEOEDITOR_DEFUALT_MAX_OUTPUT_FRAME_HEIGHT);
+}
+
 /*static*/ MediaProfiles*
 MediaProfiles::createDefaultInstance()
 {
@@ -801,6 +842,7 @@
     createDefaultAudioDecoders(profiles);
     createDefaultEncoderOutputFileFormats(profiles);
     createDefaultImageEncodingQualityLevels(profiles);
+    createDefaultVideoEditorCap(profiles);
     return profiles;
 }
 
@@ -899,6 +941,28 @@
     return -1;
 }
 
+int MediaProfiles::getVideoEditorCapParamByName(const char *name) const
+{
+    LOGV("getVideoEditorCapParamByName: %s", name);
+
+    if (mVideoEditorCap == NULL) {
+        LOGE("The mVideoEditorCap is not created, then create default cap.");
+        createDefaultVideoEditorCap(sInstance);
+    }
+
+    if (!strcmp("videoeditor.input.width.max", name))
+        return mVideoEditorCap->mMaxInputFrameWidth;
+    if (!strcmp("videoeditor.input.height.max", name))
+        return mVideoEditorCap->mMaxInputFrameHeight;
+    if (!strcmp("videoeditor.output.width.max", name))
+        return mVideoEditorCap->mMaxOutputFrameWidth;
+    if (!strcmp("videoeditor.output.height.max", name))
+        return mVideoEditorCap->mMaxOutputFrameHeight;
+
+    LOGE("The given video editor param name %s is not found", name);
+    return -1;
+}
+
 Vector<audio_encoder> MediaProfiles::getAudioEncoders() const
 {
     Vector<audio_encoder> encoders;
diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp
index 45bdff4..41f8593 100644
--- a/media/libmedia/MediaScanner.cpp
+++ b/media/libmedia/MediaScanner.cpp
@@ -47,16 +47,15 @@
     return mLocale;
 }
 
-status_t MediaScanner::processDirectory(
-        const char *path, MediaScannerClient &client,
-        ExceptionCheck exceptionCheck, void *exceptionEnv) {
+MediaScanResult MediaScanner::processDirectory(
+        const char *path, MediaScannerClient &client) {
     int pathLength = strlen(path);
     if (pathLength >= PATH_MAX) {
-        return UNKNOWN_ERROR;
+        return MEDIA_SCAN_RESULT_SKIPPED;
     }
     char* pathBuffer = (char *)malloc(PATH_MAX + 1);
     if (!pathBuffer) {
-        return UNKNOWN_ERROR;
+        return MEDIA_SCAN_RESULT_ERROR;
     }
 
     int pathRemaining = PATH_MAX - pathLength;
@@ -69,21 +68,18 @@
 
     client.setLocale(locale());
 
-    status_t result =
-        doProcessDirectory(pathBuffer, pathRemaining, client, false, exceptionCheck, exceptionEnv);
+    MediaScanResult result = doProcessDirectory(pathBuffer, pathRemaining, client, false);
 
     free(pathBuffer);
 
     return result;
 }
 
-status_t MediaScanner::doProcessDirectory(
-        char *path, int pathRemaining, MediaScannerClient &client,
-        bool noMedia, ExceptionCheck exceptionCheck, void *exceptionEnv) {
+MediaScanResult MediaScanner::doProcessDirectory(
+        char *path, int pathRemaining, MediaScannerClient &client, bool noMedia) {
     // place to copy file or directory name
     char* fileSpot = path + strlen(path);
     struct dirent* entry;
-    struct stat statbuf;
 
     // Treat all files as non-media in directories that contain a  ".nomedia" file
     if (pathRemaining >= 8 /* strlen(".nomedia") */ ) {
@@ -99,76 +95,88 @@
 
     DIR* dir = opendir(path);
     if (!dir) {
-        LOGD("opendir %s failed, errno: %d", path, errno);
-        return UNKNOWN_ERROR;
+        LOGW("Error opening directory '%s', skipping: %s.", path, strerror(errno));
+        return MEDIA_SCAN_RESULT_SKIPPED;
     }
 
+    MediaScanResult result = MEDIA_SCAN_RESULT_OK;
     while ((entry = readdir(dir))) {
-        const char* name = entry->d_name;
-
-        // ignore "." and ".."
-        if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
-            continue;
+        if (doProcessDirectoryEntry(path, pathRemaining, client, noMedia, entry, fileSpot)
+                == MEDIA_SCAN_RESULT_ERROR) {
+            result = MEDIA_SCAN_RESULT_ERROR;
+            break;
         }
+    }
+    closedir(dir);
+    return result;
+}
 
-        int nameLength = strlen(name);
-        if (nameLength + 1 > pathRemaining) {
-            // path too long!
-            continue;
+MediaScanResult MediaScanner::doProcessDirectoryEntry(
+        char *path, int pathRemaining, MediaScannerClient &client, bool noMedia,
+        struct dirent* entry, char* fileSpot) {
+    struct stat statbuf;
+    const char* name = entry->d_name;
+
+    // ignore "." and ".."
+    if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
+        return MEDIA_SCAN_RESULT_SKIPPED;
+    }
+
+    int nameLength = strlen(name);
+    if (nameLength + 1 > pathRemaining) {
+        // path too long!
+        return MEDIA_SCAN_RESULT_SKIPPED;
+    }
+    strcpy(fileSpot, name);
+
+    int type = entry->d_type;
+    if (type == DT_UNKNOWN) {
+        // If the type is unknown, stat() the file instead.
+        // This is sometimes necessary when accessing NFS mounted filesystems, but
+        // could be needed in other cases well.
+        if (stat(path, &statbuf) == 0) {
+            if (S_ISREG(statbuf.st_mode)) {
+                type = DT_REG;
+            } else if (S_ISDIR(statbuf.st_mode)) {
+                type = DT_DIR;
+            }
+        } else {
+            LOGD("stat() failed for %s: %s", path, strerror(errno) );
         }
-        strcpy(fileSpot, name);
+    }
+    if (type == DT_DIR) {
+        bool childNoMedia = noMedia;
+        // set noMedia flag on directories with a name that starts with '.'
+        // for example, the Mac ".Trashes" directory
+        if (name[0] == '.')
+            childNoMedia = true;
 
-        int type = entry->d_type;
-        if (type == DT_UNKNOWN) {
-            // If the type is unknown, stat() the file instead.
-            // This is sometimes necessary when accessing NFS mounted filesystems, but
-            // could be needed in other cases well.
-            if (stat(path, &statbuf) == 0) {
-                if (S_ISREG(statbuf.st_mode)) {
-                    type = DT_REG;
-                } else if (S_ISDIR(statbuf.st_mode)) {
-                    type = DT_DIR;
-                }
-            } else {
-                LOGD("stat() failed for %s: %s", path, strerror(errno) );
+        // report the directory to the client
+        if (stat(path, &statbuf) == 0) {
+            status_t status = client.scanFile(path, statbuf.st_mtime, 0,
+                    true /*isDirectory*/, childNoMedia);
+            if (status) {
+                return MEDIA_SCAN_RESULT_ERROR;
             }
         }
-        if (type == DT_REG || type == DT_DIR) {
-            if (type == DT_DIR) {
-                bool childNoMedia = noMedia;
-                // set noMedia flag on directories with a name that starts with '.'
-                // for example, the Mac ".Trashes" directory
-                if (name[0] == '.')
-                    childNoMedia = true;
 
-                // report the directory to the client
-                if (stat(path, &statbuf) == 0) {
-                    client.scanFile(path, statbuf.st_mtime, 0, true, childNoMedia);
-                }
-
-                // and now process its contents
-                strcat(fileSpot, "/");
-                int err = doProcessDirectory(path, pathRemaining - nameLength - 1, client,
-                        childNoMedia, exceptionCheck, exceptionEnv);
-                if (err) {
-                    // pass exceptions up - ignore other errors
-                    if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure;
-                    LOGE("Error processing '%s' - skipping\n", path);
-                    continue;
-                }
-            } else {
-                stat(path, &statbuf);
-                client.scanFile(path, statbuf.st_mtime, statbuf.st_size, false, noMedia);
-                if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure;
-            }
+        // and now process its contents
+        strcat(fileSpot, "/");
+        MediaScanResult result = doProcessDirectory(path, pathRemaining - nameLength - 1,
+                client, childNoMedia);
+        if (result == MEDIA_SCAN_RESULT_ERROR) {
+            return MEDIA_SCAN_RESULT_ERROR;
+        }
+    } else if (type == DT_REG) {
+        stat(path, &statbuf);
+        status_t status = client.scanFile(path, statbuf.st_mtime, statbuf.st_size,
+                false /*isDirectory*/, noMedia);
+        if (status) {
+            return MEDIA_SCAN_RESULT_ERROR;
         }
     }
 
-    closedir(dir);
-    return OK;
-failure:
-    closedir(dir);
-    return -1;
+    return MEDIA_SCAN_RESULT_OK;
 }
 
 }  // namespace android
diff --git a/media/libmedia/MediaScannerClient.cpp b/media/libmedia/MediaScannerClient.cpp
index bd3596e..7a7aeb6 100644
--- a/media/libmedia/MediaScannerClient.cpp
+++ b/media/libmedia/MediaScannerClient.cpp
@@ -62,7 +62,7 @@
     mValues = new StringArray;
 }
 
-bool MediaScannerClient::addStringTag(const char* name, const char* value)
+status_t MediaScannerClient::addStringTag(const char* name, const char* value)
 {
     if (mLocaleEncoding != kEncodingNone) {
         // don't bother caching strings that are all ASCII.
@@ -212,8 +212,10 @@
 
         // finally, push all name/value pairs to the client
         for (int i = 0; i < mNames->size(); i++) {
-            if (!handleStringTag(mNames->getEntry(i), mValues->getEntry(i)))
+            status_t status = handleStringTag(mNames->getEntry(i), mValues->getEntry(i));
+            if (status) {
                 break;
+            }
         }
     }
     // else addStringTag() has done all the work so we have nothing to do
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index ed6e3c7..a11fb80 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -228,6 +228,7 @@
                 NATIVE_WINDOW_API_MEDIA);
 
         if (err != OK) {
+            LOGE("setVideoSurface failed: %d", err);
             // Note that we must do the reset before disconnecting from the ANW.
             // Otherwise queue/dequeue calls could be made on the disconnected
             // ANW, which may result in errors.
@@ -277,6 +278,7 @@
                 NATIVE_WINDOW_API_MEDIA);
 
         if (err != OK) {
+            LOGE("setVideoSurfaceTexture failed: %d", err);
             // Note that we must do the reset before disconnecting from the ANW.
             // Otherwise queue/dequeue calls could be made on the disconnected
             // ANW, which may result in errors.
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 9e4edd0..11d281f 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -25,6 +25,7 @@
 #include <media/IMediaPlayerService.h>
 #include <media/IMediaRecorder.h>
 #include <media/mediaplayer.h>  // for MEDIA_ERROR_SERVER_DIED
+#include <gui/ISurfaceTexture.h>
 
 namespace android {
 
@@ -127,7 +128,9 @@
         return INVALID_OPERATION;
     }
 
+    // following call is made over the Binder Interface
     status_t ret = mMediaRecorder->setVideoSource(vs);
+
     if (OK != ret) {
         LOGV("setVideoSource failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
@@ -319,32 +322,6 @@
     return ret;
 }
 
-status_t MediaRecorder::setOutputFileAuxiliary(int fd)
-{
-    LOGV("setOutputFileAuxiliary(%d)", fd);
-    if(mMediaRecorder == NULL) {
-        LOGE("media recorder is not initialized yet");
-        return INVALID_OPERATION;
-    }
-    if (mIsAuxiliaryOutputFileSet) {
-        LOGE("output file has already been set");
-        return INVALID_OPERATION;
-    }
-    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
-        LOGE("setOutputFile called in an invalid state(%d)", mCurrentState);
-        return INVALID_OPERATION;
-    }
-
-    status_t ret = mMediaRecorder->setOutputFileAuxiliary(fd);
-    if (OK != ret) {
-        LOGV("setOutputFileAuxiliary failed: %d", ret);
-        mCurrentState = MEDIA_RECORDER_ERROR;
-        return ret;
-    }
-    mIsAuxiliaryOutputFileSet = true;
-    return ret;
-}
-
 status_t MediaRecorder::setVideoSize(int width, int height)
 {
     LOGV("setVideoSize(%d, %d)", width, height);
@@ -357,7 +334,7 @@
         return INVALID_OPERATION;
     }
     if (!mIsVideoSourceSet) {
-        LOGE("try to set video size without setting video source first");
+        LOGE("Cannot set video size without setting video source first");
         return INVALID_OPERATION;
     }
 
@@ -367,9 +344,27 @@
         mCurrentState = MEDIA_RECORDER_ERROR;
         return ret;
     }
+
     return ret;
 }
 
+// Query a SurfaceMediaSurface through the Mediaserver, over the
+// binder interface. This is used by the Filter Framework (MeidaEncoder)
+// to get an <ISurfaceTexture> object to hook up to ANativeWindow.
+sp<ISurfaceTexture> MediaRecorder::
+        querySurfaceMediaSourceFromMediaServer()
+{
+    Mutex::Autolock _l(mLock);
+    mSurfaceMediaSource =
+            mMediaRecorder->querySurfaceMediaSource();
+    if (mSurfaceMediaSource == NULL) {
+        LOGE("SurfaceMediaSource could not be initialized!");
+    }
+    return mSurfaceMediaSource;
+}
+
+
+
 status_t MediaRecorder::setVideoFrameRate(int frames_per_second)
 {
     LOGV("setVideoFrameRate(%d)", frames_per_second);
@@ -382,7 +377,7 @@
         return INVALID_OPERATION;
     }
     if (!mIsVideoSourceSet) {
-        LOGE("try to set video frame rate without setting video source first");
+        LOGE("Cannot set video frame rate without setting video source first");
         return INVALID_OPERATION;
     }
 
@@ -608,7 +603,6 @@
     mIsAudioEncoderSet = false;
     mIsVideoEncoderSet = false;
     mIsOutputFileSet   = false;
-    mIsAuxiliaryOutputFileSet = false;
 }
 
 // Release should be OK in any state
@@ -621,7 +615,7 @@
     return INVALID_OPERATION;
 }
 
-MediaRecorder::MediaRecorder()
+MediaRecorder::MediaRecorder() : mSurfaceMediaSource(NULL)
 {
     LOGV("constructor");
 
@@ -632,6 +626,8 @@
     if (mMediaRecorder != NULL) {
         mCurrentState = MEDIA_RECORDER_IDLE;
     }
+
+
     doCleanUp();
 }
 
@@ -646,6 +642,10 @@
     if (mMediaRecorder != NULL) {
         mMediaRecorder.clear();
     }
+
+    if (mSurfaceMediaSource != NULL) {
+        mSurfaceMediaSource.clear();
+    }
 }
 
 status_t MediaRecorder::setListener(const sp<MediaRecorderListener>& listener)
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 115db1a..6f80b35 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -41,6 +41,7 @@
 #include "MediaPlayerService.h"
 
 #include "StagefrightRecorder.h"
+#include <gui/ISurfaceTexture.h>
 
 namespace android {
 
@@ -57,6 +58,20 @@
     return ok;
 }
 
+
+sp<ISurfaceTexture> MediaRecorderClient::querySurfaceMediaSource()
+{
+    LOGV("Query SurfaceMediaSource");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NULL;
+    }
+    return mRecorder->querySurfaceMediaSource();
+}
+
+
+
 status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera,
                                         const sp<ICameraRecordingProxy>& proxy)
 {
@@ -163,17 +178,6 @@
     return mRecorder->setOutputFile(fd, offset, length);
 }
 
-status_t MediaRecorderClient::setOutputFileAuxiliary(int fd)
-{
-    LOGV("setOutputFileAuxiliary(%d)", fd);
-    Mutex::Autolock lock(mLock);
-    if (mRecorder == NULL) {
-        LOGE("recorder is not initialized");
-        return NO_INIT;
-    }
-    return mRecorder->setOutputFileAuxiliary(fd);
-}
-
 status_t MediaRecorderClient::setVideoSize(int width, int height)
 {
     LOGV("setVideoSize(%dx%d)", width, height);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index bbca529..c9ccf22 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -25,45 +25,50 @@
 class MediaRecorderBase;
 class MediaPlayerService;
 class ICameraRecordingProxy;
+class ISurfaceTexture;
 
 class MediaRecorderClient : public BnMediaRecorder
 {
 public:
-    virtual     status_t        setCamera(const sp<ICamera>& camera,
-                                          const sp<ICameraRecordingProxy>& proxy);
-    virtual     status_t        setPreviewSurface(const sp<Surface>& surface);
-    virtual     status_t        setVideoSource(int vs);
-    virtual     status_t        setAudioSource(int as);
-    virtual     status_t        setOutputFormat(int of);
-    virtual     status_t        setVideoEncoder(int ve);
-    virtual     status_t        setAudioEncoder(int ae);
-    virtual     status_t        setOutputFile(const char* path);
-    virtual     status_t        setOutputFile(int fd, int64_t offset, int64_t length);
-    virtual     status_t        setOutputFileAuxiliary(int fd);
-    virtual     status_t        setVideoSize(int width, int height);
-    virtual     status_t        setVideoFrameRate(int frames_per_second);
-    virtual     status_t        setParameters(const String8& params);
-    virtual     status_t        setListener(const sp<IMediaRecorderClient>& listener);
-    virtual     status_t        prepare();
-    virtual     status_t        getMaxAmplitude(int* max);
-    virtual     status_t        start();
-    virtual     status_t        stop();
-    virtual     status_t        reset();
-    virtual     status_t        init();
-    virtual     status_t        close();
-    virtual     status_t        release();
+    virtual     status_t   setCamera(const sp<ICamera>& camera,
+                                    const sp<ICameraRecordingProxy>& proxy);
+    virtual     status_t   setPreviewSurface(const sp<Surface>& surface);
+    virtual     status_t   setVideoSource(int vs);
+    virtual     status_t   setAudioSource(int as);
+    virtual     status_t   setOutputFormat(int of);
+    virtual     status_t   setVideoEncoder(int ve);
+    virtual     status_t   setAudioEncoder(int ae);
+    virtual     status_t   setOutputFile(const char* path);
+    virtual     status_t   setOutputFile(int fd, int64_t offset,
+                                                  int64_t length);
+    virtual     status_t   setVideoSize(int width, int height);
+    virtual     status_t   setVideoFrameRate(int frames_per_second);
+    virtual     status_t   setParameters(const String8& params);
+    virtual     status_t   setListener(
+                              const sp<IMediaRecorderClient>& listener);
+    virtual     status_t   prepare();
+    virtual     status_t   getMaxAmplitude(int* max);
+    virtual     status_t   start();
+    virtual     status_t   stop();
+    virtual     status_t   reset();
+    virtual     status_t   init();
+    virtual     status_t   close();
+    virtual     status_t   release();
+    virtual     status_t   dump(int fd, const Vector<String16>& args) const;
+    virtual     sp<ISurfaceTexture> querySurfaceMediaSource();
 
-    virtual     status_t        dump(int fd, const Vector<String16>& args) const;
 private:
-    friend class                MediaPlayerService;  // for accessing private constructor
+    friend class           MediaPlayerService;  // for accessing private constructor
 
-                                MediaRecorderClient(const sp<MediaPlayerService>& service, pid_t pid);
-    virtual                     ~MediaRecorderClient();
+                           MediaRecorderClient(
+                                   const sp<MediaPlayerService>& service,
+                                                               pid_t pid);
+    virtual                ~MediaRecorderClient();
 
-    pid_t                       mPid;
-    Mutex                       mLock;
-    MediaRecorderBase           *mRecorder;
-    sp<MediaPlayerService>      mMediaPlayerService;
+    pid_t                  mPid;
+    Mutex                  mLock;
+    MediaRecorderBase      *mRecorder;
+    sp<MediaPlayerService> mMediaPlayerService;
 };
 
 }; // namespace android
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 223e0be..6fdb726 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -28,9 +28,7 @@
 #include <media/stagefright/AMRWriter.h>
 #include <media/stagefright/AACWriter.h>
 #include <media/stagefright/CameraSource.h>
-#include <media/stagefright/VideoSourceDownSampler.h>
 #include <media/stagefright/CameraSourceTimeLapse.h>
-#include <media/stagefright/MediaSourceSplitter.h>
 #include <media/stagefright/MPEG2TSWriter.h>
 #include <media/stagefright/MPEG4Writer.h>
 #include <media/stagefright/MediaDebug.h>
@@ -38,10 +36,12 @@
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/OMXClient.h>
 #include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/SurfaceMediaSource.h>
 #include <media/MediaProfiles.h>
 #include <camera/ICamera.h>
 #include <camera/CameraParameters.h>
 #include <surfaceflinger/Surface.h>
+
 #include <utils/Errors.h>
 #include <sys/types.h>
 #include <ctype.h>
@@ -65,11 +65,11 @@
 
 
 StagefrightRecorder::StagefrightRecorder()
-    : mWriter(NULL), mWriterAux(NULL),
-      mOutputFd(-1), mOutputFdAux(-1),
+    : mWriter(NULL),
+      mOutputFd(-1),
       mAudioSource(AUDIO_SOURCE_CNT),
       mVideoSource(VIDEO_SOURCE_LIST_END),
-      mStarted(false) {
+      mStarted(false), mSurfaceMediaSource(NULL) {
 
     LOGV("Constructor");
     reset();
@@ -85,6 +85,14 @@
     return OK;
 }
 
+// The client side of mediaserver asks it to creat a SurfaceMediaSource
+// and return a interface reference. The client side will use that
+// while encoding GL Frames
+sp<ISurfaceTexture> StagefrightRecorder::querySurfaceMediaSource() const {
+    LOGV("Get SurfaceMediaSource");
+    return mSurfaceMediaSource;
+}
+
 status_t StagefrightRecorder::setAudioSource(audio_source_t as) {
     LOGV("setAudioSource: %d", as);
     if (as < AUDIO_SOURCE_DEFAULT ||
@@ -249,24 +257,6 @@
     return OK;
 }
 
-status_t StagefrightRecorder::setOutputFileAuxiliary(int fd) {
-    LOGV("setOutputFileAuxiliary: %d", fd);
-
-    if (fd < 0) {
-        LOGE("Invalid file descriptor: %d", fd);
-        return -EBADF;
-    }
-
-    mCaptureAuxVideo = true;
-
-    if (mOutputFdAux >= 0) {
-        ::close(mOutputFdAux);
-    }
-    mOutputFdAux = dup(fd);
-
-    return OK;
-}
-
 // Attempt to parse an int64 literal optionally surrounded by whitespace,
 // returns true on success, false otherwise.
 static bool safe_strtoi64(const char *s, int64_t *val) {
@@ -563,42 +553,6 @@
     return OK;
 }
 
-status_t StagefrightRecorder::setParamAuxVideoWidth(int32_t width) {
-    LOGV("setParamAuxVideoWidth : %d", width);
-
-    if (width <= 0) {
-        LOGE("Width (%d) is not positive", width);
-        return BAD_VALUE;
-    }
-
-    mAuxVideoWidth = width;
-    return OK;
-}
-
-status_t StagefrightRecorder::setParamAuxVideoHeight(int32_t height) {
-    LOGV("setParamAuxVideoHeight : %d", height);
-
-    if (height <= 0) {
-        LOGE("Height (%d) is not positive", height);
-        return BAD_VALUE;
-    }
-
-    mAuxVideoHeight = height;
-    return OK;
-}
-
-status_t StagefrightRecorder::setParamAuxVideoEncodingBitRate(int32_t bitRate) {
-    LOGV("StagefrightRecorder::setParamAuxVideoEncodingBitRate: %d", bitRate);
-
-    if (bitRate <= 0) {
-        LOGE("Invalid video encoding bit rate: %d", bitRate);
-        return BAD_VALUE;
-    }
-
-    mAuxVideoBitRate = bitRate;
-    return OK;
-}
-
 status_t StagefrightRecorder::setParamGeoDataLongitude(
     int32_t longitudex10000) {
 
@@ -728,21 +682,6 @@
             return setParamTimeBetweenTimeLapseFrameCapture(
                     1000LL * timeBetweenTimeLapseFrameCaptureMs);
         }
-    } else if (key == "video-aux-param-width") {
-        int32_t auxWidth;
-        if (safe_strtoi32(value.string(), &auxWidth)) {
-            return setParamAuxVideoWidth(auxWidth);
-        }
-    } else if (key == "video-aux-param-height") {
-        int32_t auxHeight;
-        if (safe_strtoi32(value.string(), &auxHeight)) {
-            return setParamAuxVideoHeight(auxHeight);
-        }
-    } else if (key == "video-aux-param-encoding-bitrate") {
-        int32_t auxVideoBitRate;
-        if (safe_strtoi32(value.string(), &auxVideoBitRate)) {
-            return setParamAuxVideoEncodingBitRate(auxVideoBitRate);
-        }
     } else {
         LOGE("setParameter: failed to find key %s", key.string());
     }
@@ -1006,13 +945,13 @@
         source = createAudioSource();
     } else {
 
-        sp<CameraSource> cameraSource;
-        status_t err = setupCameraSource(&cameraSource);
+        sp<MediaSource> mediaSource;
+        status_t err = setupMediaSource(&mediaSource);
         if (err != OK) {
             return err;
         }
 
-        err = setupVideoEncoder(cameraSource, mVideoBitRate, &source);
+        err = setupVideoEncoder(mediaSource, mVideoBitRate, &source);
         if (err != OK) {
             return err;
         }
@@ -1042,20 +981,19 @@
         }
     }
 
-    if (mVideoSource == VIDEO_SOURCE_DEFAULT
-            || mVideoSource == VIDEO_SOURCE_CAMERA) {
+    if (mVideoSource < VIDEO_SOURCE_LIST_END) {
         if (mVideoEncoder != VIDEO_ENCODER_H264) {
             return ERROR_UNSUPPORTED;
         }
 
-        sp<CameraSource> cameraSource;
-        status_t err = setupCameraSource(&cameraSource);
+        sp<MediaSource> mediaSource;
+        status_t err = setupMediaSource(&mediaSource);
         if (err != OK) {
             return err;
         }
 
         sp<MediaSource> encoder;
-        err = setupVideoEncoder(cameraSource, mVideoBitRate, &encoder);
+        err = setupVideoEncoder(mediaSource, mVideoBitRate, &encoder);
 
         if (err != OK) {
             return err;
@@ -1289,6 +1227,60 @@
     }
 }
 
+// Set up the appropriate MediaSource depending on the chosen option
+status_t StagefrightRecorder::setupMediaSource(
+                      sp<MediaSource> *mediaSource) {
+    if (mVideoSource == VIDEO_SOURCE_DEFAULT
+            || mVideoSource == VIDEO_SOURCE_CAMERA) {
+        sp<CameraSource> cameraSource;
+        status_t err = setupCameraSource(&cameraSource);
+        if (err != OK) {
+            return err;
+        }
+        *mediaSource = cameraSource;
+    } else if (mVideoSource == VIDEO_SOURCE_GRALLOC_BUFFER) {
+        // If using GRAlloc buffers, setup surfacemediasource.
+        // Later a handle to that will be passed
+        // to the client side when queried
+        status_t err = setupSurfaceMediaSource();
+        if (err != OK) {
+            return err;
+        }
+        *mediaSource = mSurfaceMediaSource;
+    } else {
+        return INVALID_OPERATION;
+    }
+    return OK;
+}
+
+// setupSurfaceMediaSource creates a source with the given
+// width and height and framerate.
+// TODO: This could go in a static function inside SurfaceMediaSource
+// similar to that in CameraSource
+status_t StagefrightRecorder::setupSurfaceMediaSource() {
+    status_t err = OK;
+    mSurfaceMediaSource = new SurfaceMediaSource(mVideoWidth, mVideoHeight);
+    if (mSurfaceMediaSource == NULL) {
+        return NO_INIT;
+    }
+
+    if (mFrameRate == -1) {
+        int32_t frameRate = 0;
+        CHECK (mSurfaceMediaSource->getFormat()->findInt32(
+                                        kKeyFrameRate, &frameRate));
+        LOGI("Frame rate is not explicitly set. Use the current frame "
+             "rate (%d fps)", frameRate);
+        mFrameRate = frameRate;
+    } else {
+        err = mSurfaceMediaSource->setFrameRate(mFrameRate);
+    }
+    CHECK(mFrameRate != -1);
+
+    mIsMetaDataStoredInVideoBuffers =
+        mSurfaceMediaSource->isMetaDataStoredInVideoBuffers();
+    return err;
+}
+
 status_t StagefrightRecorder::setupCameraSource(
         sp<CameraSource> *cameraSource) {
     status_t err = OK;
@@ -1454,7 +1446,6 @@
 }
 
 status_t StagefrightRecorder::setupMPEG4Recording(
-        bool useSplitCameraSource,
         int outputFd,
         int32_t videoWidth, int32_t videoHeight,
         int32_t videoBitRate,
@@ -1465,29 +1456,16 @@
     status_t err = OK;
     sp<MediaWriter> writer = new MPEG4Writer(outputFd);
 
-    if (mVideoSource == VIDEO_SOURCE_DEFAULT
-            || mVideoSource == VIDEO_SOURCE_CAMERA) {
+    if (mVideoSource < VIDEO_SOURCE_LIST_END) {
 
-        sp<MediaSource> cameraMediaSource;
-        if (useSplitCameraSource) {
-            LOGV("Using Split camera source");
-            cameraMediaSource = mCameraSourceSplitter->createClient();
-        } else {
-            sp<CameraSource> cameraSource;
-            err = setupCameraSource(&cameraSource);
-            cameraMediaSource = cameraSource;
-        }
-        if ((videoWidth != mVideoWidth) || (videoHeight != mVideoHeight)) {
-            // Use downsampling from the original source.
-            cameraMediaSource =
-                new VideoSourceDownSampler(cameraMediaSource, videoWidth, videoHeight);
-        }
+        sp<MediaSource> mediaSource;
+        err = setupMediaSource(&mediaSource);
         if (err != OK) {
             return err;
         }
 
         sp<MediaSource> encoder;
-        err = setupVideoEncoder(cameraMediaSource, videoBitRate, &encoder);
+        err = setupVideoEncoder(mediaSource, videoBitRate, &encoder);
         if (err != OK) {
             return err;
         }
@@ -1549,24 +1527,8 @@
 }
 
 status_t StagefrightRecorder::startMPEG4Recording() {
-    if (mCaptureAuxVideo) {
-        if (!mCaptureTimeLapse) {
-            LOGE("Auxiliary video can be captured only in time lapse mode");
-            return UNKNOWN_ERROR;
-        }
-        LOGV("Creating MediaSourceSplitter");
-        sp<CameraSource> cameraSource;
-        status_t err = setupCameraSource(&cameraSource);
-        if (err != OK) {
-            return err;
-        }
-        mCameraSourceSplitter = new MediaSourceSplitter(cameraSource);
-    } else {
-        mCameraSourceSplitter = NULL;
-    }
-
     int32_t totalBitRate;
-    status_t err = setupMPEG4Recording(mCaptureAuxVideo,
+    status_t err = setupMPEG4Recording(
             mOutputFd, mVideoWidth, mVideoHeight,
             mVideoBitRate, &totalBitRate, &mWriter);
     if (err != OK) {
@@ -1582,33 +1544,6 @@
         return err;
     }
 
-    if (mCaptureAuxVideo) {
-        CHECK(mOutputFdAux >= 0);
-        if (mWriterAux != NULL) {
-            LOGE("Auxiliary File writer is not avaialble");
-            return UNKNOWN_ERROR;
-        }
-        if ((mAuxVideoWidth > mVideoWidth) || (mAuxVideoHeight > mVideoHeight) ||
-                ((mAuxVideoWidth == mVideoWidth) && mAuxVideoHeight == mVideoHeight)) {
-            LOGE("Auxiliary video size (%d x %d) same or larger than the main video size (%d x %d)",
-                    mAuxVideoWidth, mAuxVideoHeight, mVideoWidth, mVideoHeight);
-            return UNKNOWN_ERROR;
-        }
-
-        int32_t totalBitrateAux;
-        err = setupMPEG4Recording(mCaptureAuxVideo,
-                mOutputFdAux, mAuxVideoWidth, mAuxVideoHeight,
-                mAuxVideoBitRate, &totalBitrateAux, &mWriterAux);
-        if (err != OK) {
-            return err;
-        }
-
-        sp<MetaData> metaAux = new MetaData;
-        setupMPEG4MetaData(startTimeUs, totalBitrateAux, &metaAux);
-
-        return mWriterAux->start(metaAux.get());
-    }
-
     return OK;
 }
 
@@ -1619,13 +1554,6 @@
     }
     mWriter->pause();
 
-    if (mCaptureAuxVideo) {
-        if (mWriterAux == NULL) {
-            return UNKNOWN_ERROR;
-        }
-        mWriterAux->pause();
-    }
-
     if (mStarted) {
         mStarted = false;
 
@@ -1653,13 +1581,6 @@
         mCameraSourceTimeLapse = NULL;
     }
 
-    if (mCaptureAuxVideo) {
-        if (mWriterAux != NULL) {
-            mWriterAux->stop();
-            mWriterAux.clear();
-        }
-    }
-
     if (mWriter != NULL) {
         err = mWriter->stop();
         mWriter.clear();
@@ -1670,13 +1591,6 @@
         mOutputFd = -1;
     }
 
-    if (mCaptureAuxVideo) {
-        if (mOutputFdAux >= 0) {
-            ::close(mOutputFdAux);
-            mOutputFdAux = -1;
-        }
-    }
-
     if (mStarted) {
         mStarted = false;
 
@@ -1716,11 +1630,8 @@
     mVideoEncoder  = VIDEO_ENCODER_H263;
     mVideoWidth    = 176;
     mVideoHeight   = 144;
-    mAuxVideoWidth    = 176;
-    mAuxVideoHeight   = 144;
     mFrameRate     = -1;
     mVideoBitRate  = 192000;
-    mAuxVideoBitRate = 192000;
     mSampleRate    = 8000;
     mAudioChannels = 1;
     mAudioBitRate  = 12200;
@@ -1740,8 +1651,6 @@
     mTrackEveryTimeDurationUs = 0;
     mCaptureTimeLapse = false;
     mTimeBetweenTimeLapseFrameCaptureUs = -1;
-    mCaptureAuxVideo = false;
-    mCameraSourceSplitter = NULL;
     mCameraSourceTimeLapse = NULL;
     mIsMetaDataStoredInVideoBuffers = false;
     mEncoderProfiles = MediaProfiles::getInstance();
@@ -1750,7 +1659,6 @@
     mLongitudex10000 = -3600000;
 
     mOutputFd = -1;
-    mOutputFdAux = -1;
 
     return OK;
 }
@@ -1787,8 +1695,6 @@
     snprintf(buffer, SIZE, "   Recorder: %p\n", this);
     snprintf(buffer, SIZE, "   Output file (fd %d):\n", mOutputFd);
     result.append(buffer);
-    snprintf(buffer, SIZE, "   Output file Auxiliary (fd %d):\n", mOutputFdAux);
-    result.append(buffer);
     snprintf(buffer, SIZE, "     File format: %d\n", mOutputFormat);
     result.append(buffer);
     snprintf(buffer, SIZE, "     Max file size (bytes): %lld\n", mMaxFileSizeBytes);
@@ -1833,14 +1739,10 @@
     result.append(buffer);
     snprintf(buffer, SIZE, "     Frame size (pixels): %dx%d\n", mVideoWidth, mVideoHeight);
     result.append(buffer);
-    snprintf(buffer, SIZE, "     Aux Frame size (pixels): %dx%d\n", mAuxVideoWidth, mAuxVideoHeight);
-    result.append(buffer);
     snprintf(buffer, SIZE, "     Frame rate (fps): %d\n", mFrameRate);
     result.append(buffer);
     snprintf(buffer, SIZE, "     Bit rate (bps): %d\n", mVideoBitRate);
     result.append(buffer);
-    snprintf(buffer, SIZE, "     Aux Bit rate (bps): %d\n", mAuxVideoBitRate);
-    result.append(buffer);
     ::write(fd, result.string(), result.size());
     return OK;
 }
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 034b373..5c5f05c 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -30,12 +30,13 @@
 class ICameraRecordingProxy;
 class CameraSource;
 class CameraSourceTimeLapse;
-class MediaSourceSplitter;
 struct MediaSource;
 struct MediaWriter;
 class MetaData;
 struct AudioSource;
 class MediaProfiles;
+class ISurfaceTexture;
+class SurfaceMediaSource;
 
 struct StagefrightRecorder : public MediaRecorderBase {
     StagefrightRecorder();
@@ -53,7 +54,6 @@
     virtual status_t setPreviewSurface(const sp<Surface>& surface);
     virtual status_t setOutputFile(const char *path);
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
-    virtual status_t setOutputFileAuxiliary(int fd);
     virtual status_t setParameters(const String8& params);
     virtual status_t setListener(const sp<IMediaRecorderClient>& listener);
     virtual status_t prepare();
@@ -64,14 +64,16 @@
     virtual status_t reset();
     virtual status_t getMaxAmplitude(int *max);
     virtual status_t dump(int fd, const Vector<String16>& args) const;
+    // Querying a SurfaceMediaSourcer
+    virtual sp<ISurfaceTexture> querySurfaceMediaSource() const;
 
 private:
     sp<ICamera> mCamera;
     sp<ICameraRecordingProxy> mCameraProxy;
     sp<Surface> mPreviewSurface;
     sp<IMediaRecorderClient> mListener;
-    sp<MediaWriter> mWriter, mWriterAux;
-    int mOutputFd, mOutputFdAux;
+    sp<MediaWriter> mWriter;
+    int mOutputFd;
     sp<AudioSource> mAudioSourceNode;
 
     audio_source_t mAudioSource;
@@ -81,9 +83,8 @@
     video_encoder mVideoEncoder;
     bool mUse64BitFileOffset;
     int32_t mVideoWidth, mVideoHeight;
-    int32_t mAuxVideoWidth, mAuxVideoHeight;
     int32_t mFrameRate;
-    int32_t mVideoBitRate, mAuxVideoBitRate;
+    int32_t mVideoBitRate;
     int32_t mAudioBitRate;
     int32_t mAudioChannels;
     int32_t mSampleRate;
@@ -105,19 +106,22 @@
 
     bool mCaptureTimeLapse;
     int64_t mTimeBetweenTimeLapseFrameCaptureUs;
-    bool mCaptureAuxVideo;
-    sp<MediaSourceSplitter> mCameraSourceSplitter;
     sp<CameraSourceTimeLapse> mCameraSourceTimeLapse;
 
+
     String8 mParams;
 
     bool mIsMetaDataStoredInVideoBuffers;
     MediaProfiles *mEncoderProfiles;
 
     bool mStarted;
+    // Needed when GLFrames are encoded.
+    // An <ISurfaceTexture> pointer
+    // will be sent to the client side using which the
+    // frame buffers will be queued and dequeued
+    sp<SurfaceMediaSource> mSurfaceMediaSource;
 
     status_t setupMPEG4Recording(
-        bool useSplitCameraSource,
         int outputFd,
         int32_t videoWidth, int32_t videoHeight,
         int32_t videoBitRate,
@@ -134,7 +138,14 @@
     sp<MediaSource> createAudioSource();
     status_t checkVideoEncoderCapabilities();
     status_t checkAudioEncoderCapabilities();
+    // Generic MediaSource set-up. Returns the appropriate
+    // source (CameraSource or SurfaceMediaSource)
+    // depending on the videosource type
+    status_t setupMediaSource(sp<MediaSource> *mediaSource);
     status_t setupCameraSource(sp<CameraSource> *cameraSource);
+    // setup the surfacemediasource for the encoder
+    status_t setupSurfaceMediaSource();
+
     status_t setupAudioEncoder(const sp<MediaWriter>& writer);
     status_t setupVideoEncoder(
             sp<MediaSource> cameraSource,
@@ -149,9 +160,6 @@
     status_t setParamAudioTimeScale(int32_t timeScale);
     status_t setParamTimeLapseEnable(int32_t timeLapseEnable);
     status_t setParamTimeBetweenTimeLapseFrameCapture(int64_t timeUs);
-    status_t setParamAuxVideoHeight(int32_t height);
-    status_t setParamAuxVideoWidth(int32_t width);
-    status_t setParamAuxVideoEncodingBitRate(int32_t bitRate);
     status_t setParamVideoEncodingBitRate(int32_t bitRate);
     status_t setParamVideoIFramesInterval(int32_t seconds);
     status_t setParamVideoEncoderProfile(int32_t profile);
@@ -176,6 +184,7 @@
     void clipNumberOfAudioChannels();
     void setDefaultProfileIfNecessary();
 
+
     StagefrightRecorder(const StagefrightRecorder &);
     StagefrightRecorder &operator=(const StagefrightRecorder &);
 };
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index e17e1e8..3a3c082 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -42,6 +42,7 @@
         SampleTable.cpp                   \
         StagefrightMediaScanner.cpp       \
         StagefrightMetadataRetriever.cpp  \
+        SurfaceMediaSource.cpp            \
         ThrottledSource.cpp               \
         TimeSource.cpp                    \
         TimedEventQueue.cpp               \
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 1bc2fb9..de66d99 100755
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -179,9 +179,6 @@
     if (camera == 0) {
         mCamera = Camera::connect(cameraId);
         if (mCamera == 0) return -EBUSY;
-        // If proxy is not passed in by applications, still use the proxy of
-        // our own Camera to simplify the code.
-        mCameraRecordingProxy = mCamera->getRecordingProxy();
         mCameraFlags &= ~FLAGS_HOT_CAMERA;
     } else {
         // We get the proxy from Camera, not ICamera. We need to get the proxy
@@ -192,12 +189,12 @@
         if (mCamera == 0) return -EBUSY;
         mCameraRecordingProxy = proxy;
         mCameraFlags |= FLAGS_HOT_CAMERA;
+        mDeathNotifier = new DeathNotifier();
+        // isBinderAlive needs linkToDeath to work.
+        mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier);
     }
 
     mCamera->lock();
-    mDeathNotifier = new DeathNotifier();
-    // isBinderAlive needs linkToDeath to work.
-    mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier);
 
     return OK;
 }
@@ -292,7 +289,7 @@
         CameraParameters* params,
         int32_t width, int32_t height,
         int32_t frameRate) {
-
+    LOGV("configureCamera");
     Vector<Size> sizes;
     bool isSetVideoSizeSupportedByCamera = true;
     getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes);
@@ -368,6 +365,7 @@
         const CameraParameters& params,
         int32_t width, int32_t height) {
 
+    LOGV("checkVideoSize");
     // The actual video size is the same as the preview size
     // if the camera hal does not support separate video and
     // preview output. In this case, we retrieve the video
@@ -419,6 +417,7 @@
         const CameraParameters& params,
         int32_t frameRate) {
 
+    LOGV("checkFrameRate");
     int32_t frameRateActual = params.getPreviewFrameRate();
     if (frameRateActual < 0) {
         LOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
@@ -464,6 +463,7 @@
         int32_t frameRate,
         bool storeMetaDataInVideoBuffers) {
 
+    LOGV("init");
     status_t err = OK;
     int64_t token = IPCThreadState::self()->clearCallingIdentity();
     err = initWithCameraAccess(camera, proxy, cameraId,
@@ -480,6 +480,7 @@
         Size videoSize,
         int32_t frameRate,
         bool storeMetaDataInVideoBuffers) {
+    LOGV("initWithCameraAccess");
     status_t err = OK;
 
     if ((err = isCameraAvailable(camera, proxy, cameraId)) != OK) {
@@ -552,17 +553,25 @@
 }
 
 void CameraSource::startCameraRecording() {
+    LOGV("startCameraRecording");
     // Reset the identity to the current thread because media server owns the
     // camera and recording is started by the applications. The applications
     // will connect to the camera in ICameraRecordingProxy::startRecording.
     int64_t token = IPCThreadState::self()->clearCallingIdentity();
-    mCamera->unlock();
-    mCamera.clear();
+    if (mCameraFlags & FLAGS_HOT_CAMERA) {
+        mCamera->unlock();
+        mCamera.clear();
+        CHECK_EQ(OK, mCameraRecordingProxy->startRecording(new ProxyListener(this)));
+    } else {
+        mCamera->setListener(new CameraSourceListener(this));
+        mCamera->startRecording();
+        CHECK(mCamera->recordingEnabled());
+    }
     IPCThreadState::self()->restoreCallingIdentity(token);
-    CHECK_EQ(OK, mCameraRecordingProxy->startRecording(new ProxyListener(this)));
 }
 
 status_t CameraSource::start(MetaData *meta) {
+    LOGV("start");
     CHECK(!mStarted);
     if (mInitCheck != OK) {
         LOGE("CameraSource is not initialized yet");
@@ -588,7 +597,13 @@
 }
 
 void CameraSource::stopCameraRecording() {
-    mCameraRecordingProxy->stopRecording();
+    LOGV("stopCameraRecording");
+    if (mCameraFlags & FLAGS_HOT_CAMERA) {
+        mCameraRecordingProxy->stopRecording();
+    } else {
+        mCamera->setListener(NULL);
+        mCamera->stopRecording();
+    }
 }
 
 void CameraSource::releaseCamera() {
@@ -599,11 +614,10 @@
             LOGV("Camera was cold when we started, stopping preview");
             mCamera->stopPreview();
             mCamera->disconnect();
-        } else {
-            // Unlock the camera so the application can lock it back.
-            mCamera->unlock();
         }
+        mCamera->unlock();
         mCamera.clear();
+        mCamera = 0;
         IPCThreadState::self()->restoreCallingIdentity(token);
     }
     if (mCameraRecordingProxy != 0) {
@@ -646,8 +660,13 @@
 }
 
 void CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
+    LOGV("releaseRecordingFrame");
     if (mCameraRecordingProxy != NULL) {
         mCameraRecordingProxy->releaseRecordingFrame(frame);
+    } else {
+        int64_t token = IPCThreadState::self()->clearCallingIdentity();
+        mCamera->releaseRecordingFrame(frame);
+        IPCThreadState::self()->restoreCallingIdentity(token);
     }
 }
 
@@ -707,7 +726,8 @@
         while (mStarted && mFramesReceived.empty()) {
             if (NO_ERROR !=
                 mFrameAvailableCondition.waitRelative(mLock, 1000000000LL)) {
-                if (!mCameraRecordingProxy->asBinder()->isBinderAlive()) {
+                if (mCameraRecordingProxy != 0 &&
+                    !mCameraRecordingProxy->asBinder()->isBinderAlive()) {
                     LOGW("camera recording proxy is gone");
                     return ERROR_END_OF_STREAM;
                 }
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index fe78c46..1ba79e5 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -24,15 +24,10 @@
 #include <media/stagefright/CameraSourceTimeLapse.h>
 #include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MetaData.h>
-#include <media/stagefright/YUVImage.h>
-#include <media/stagefright/YUVCanvas.h>
 #include <camera/Camera.h>
 #include <camera/CameraParameters.h>
-#include <ui/Rect.h>
 #include <utils/String8.h>
 #include <utils/Vector.h>
-#include "OMX_Video.h"
-#include <limits.h>
 
 namespace android {
 
@@ -74,20 +69,14 @@
       mLastTimeLapseFrameRealTimestampUs(0),
       mSkipCurrentFrame(false) {
 
-    LOGD("starting time lapse mode: %lld us", mTimeBetweenTimeLapseFrameCaptureUs);
+    LOGD("starting time lapse mode: %lld us",
+        mTimeBetweenTimeLapseFrameCaptureUs);
+
     mVideoWidth = videoSize.width;
     mVideoHeight = videoSize.height;
 
-    if (trySettingVideoSize(videoSize.width, videoSize.height)) {
-        mUseStillCameraForTimeLapse = false;
-    } else {
-        // TODO: Add a check to see that mTimeBetweenTimeLapseFrameCaptureUs is greater
-        // than the fastest rate at which the still camera can take pictures.
-        mUseStillCameraForTimeLapse = true;
-        CHECK(setPictureSizeToClosestSupported(videoSize.width, videoSize.height));
-        mNeedCropping = computeCropRectangleOffset();
-        mMeta->setInt32(kKeyWidth, videoSize.width);
-        mMeta->setInt32(kKeyHeight, videoSize.height);
+    if (!trySettingVideoSize(videoSize.width, videoSize.height)) {
+        mInitCheck = NO_INIT;
     }
 
     // Initialize quick stop variables.
@@ -101,24 +90,22 @@
 }
 
 void CameraSourceTimeLapse::startQuickReadReturns() {
+    LOGV("startQuickReadReturns");
     Mutex::Autolock autoLock(mQuickStopLock);
-    LOGV("Enabling quick read returns");
 
     // Enable quick stop mode.
     mQuickStop = true;
 
-    if (mUseStillCameraForTimeLapse) {
-        // wake up the thread right away.
-        mTakePictureCondition.signal();
-    } else {
-        // Force dataCallbackTimestamp() coming from the video camera to not skip the
-        // next frame as we want read() to get a get a frame right away.
-        mForceRead = true;
-    }
+    // Force dataCallbackTimestamp() coming from the video camera to
+    // not skip the next frame as we want read() to get a get a frame
+    // right away.
+    mForceRead = true;
 }
 
-bool CameraSourceTimeLapse::trySettingVideoSize(int32_t width, int32_t height) {
-    LOGV("trySettingVideoSize: %dx%d", width, height);
+bool CameraSourceTimeLapse::trySettingVideoSize(
+        int32_t width, int32_t height) {
+
+    LOGV("trySettingVideoSize");
     int64_t token = IPCThreadState::self()->clearCallingIdentity();
     String8 s = mCamera->getParameters();
 
@@ -162,53 +149,8 @@
     return isSuccessful;
 }
 
-bool CameraSourceTimeLapse::setPictureSizeToClosestSupported(int32_t width, int32_t height) {
-    LOGV("setPictureSizeToClosestSupported: %dx%d", width, height);
-    int64_t token = IPCThreadState::self()->clearCallingIdentity();
-    String8 s = mCamera->getParameters();
-    IPCThreadState::self()->restoreCallingIdentity(token);
-
-    CameraParameters params(s);
-    Vector<Size> supportedSizes;
-    params.getSupportedPictureSizes(supportedSizes);
-
-    int32_t minPictureSize = INT_MAX;
-    for (uint32_t i = 0; i < supportedSizes.size(); ++i) {
-        int32_t pictureWidth = supportedSizes[i].width;
-        int32_t pictureHeight = supportedSizes[i].height;
-
-        if ((pictureWidth >= width) && (pictureHeight >= height)) {
-            int32_t pictureSize = pictureWidth*pictureHeight;
-            if (pictureSize < minPictureSize) {
-                minPictureSize = pictureSize;
-                mPictureWidth = pictureWidth;
-                mPictureHeight = pictureHeight;
-            }
-        }
-    }
-    LOGV("Picture size = (%d, %d)", mPictureWidth, mPictureHeight);
-    return (minPictureSize != INT_MAX);
-}
-
-bool CameraSourceTimeLapse::computeCropRectangleOffset() {
-    if ((mPictureWidth == mVideoWidth) && (mPictureHeight == mVideoHeight)) {
-        return false;
-    }
-
-    CHECK((mPictureWidth > mVideoWidth) && (mPictureHeight > mVideoHeight));
-
-    int32_t widthDifference = mPictureWidth - mVideoWidth;
-    int32_t heightDifference = mPictureHeight - mVideoHeight;
-
-    mCropRectStartX = widthDifference/2;
-    mCropRectStartY = heightDifference/2;
-
-    LOGV("setting crop rectangle offset to (%d, %d)", mCropRectStartX, mCropRectStartY);
-
-    return true;
-}
-
 void CameraSourceTimeLapse::signalBufferReturned(MediaBuffer* buffer) {
+    LOGV("signalBufferReturned");
     Mutex::Autolock autoLock(mQuickStopLock);
     if (mQuickStop && (buffer == mLastReadBufferCopy)) {
         buffer->setObserver(NULL);
@@ -218,7 +160,12 @@
     }
 }
 
-void createMediaBufferCopy(const MediaBuffer& sourceBuffer, int64_t frameTime, MediaBuffer **newBuffer) {
+void createMediaBufferCopy(
+        const MediaBuffer& sourceBuffer,
+        int64_t frameTime,
+        MediaBuffer **newBuffer) {
+
+    LOGV("createMediaBufferCopy");
     size_t sourceSize = sourceBuffer.size();
     void* sourcePointer = sourceBuffer.data();
 
@@ -229,6 +176,7 @@
 }
 
 void CameraSourceTimeLapse::fillLastReadBufferCopy(MediaBuffer& sourceBuffer) {
+    LOGV("fillLastReadBufferCopy");
     int64_t frameTime;
     CHECK(sourceBuffer.meta_data()->findInt64(kKeyTime, &frameTime));
     createMediaBufferCopy(sourceBuffer, frameTime, &mLastReadBufferCopy);
@@ -238,11 +186,12 @@
 
 status_t CameraSourceTimeLapse::read(
         MediaBuffer **buffer, const ReadOptions *options) {
+    LOGV("read");
     if (mLastReadBufferCopy == NULL) {
         mLastReadStatus = CameraSource::read(buffer, options);
 
-        // mQuickStop may have turned to true while read was blocked. Make a copy of
-        // the buffer in that case.
+        // mQuickStop may have turned to true while read was blocked.
+        // Make a copy of the buffer in that case.
         Mutex::Autolock autoLock(mQuickStopLock);
         if (mQuickStop && *buffer) {
             fillLastReadBufferCopy(**buffer);
@@ -255,105 +204,19 @@
     }
 }
 
-// static
-void *CameraSourceTimeLapse::ThreadTimeLapseWrapper(void *me) {
-    CameraSourceTimeLapse *source = static_cast<CameraSourceTimeLapse *>(me);
-    source->threadTimeLapseEntry();
-    return NULL;
-}
-
-void CameraSourceTimeLapse::threadTimeLapseEntry() {
-    while (mStarted) {
-        {
-            Mutex::Autolock autoLock(mCameraIdleLock);
-            if (!mCameraIdle) {
-                mCameraIdleCondition.wait(mCameraIdleLock);
-            }
-            CHECK(mCameraIdle);
-            mCameraIdle = false;
-        }
-
-        // Even if mQuickStop == true we need to take one more picture
-        // as a read() may be blocked, waiting for a frame to get available.
-        // After this takePicture, if mQuickStop == true, we can safely exit
-        // this thread as read() will make a copy of this last frame and keep
-        // returning it in the quick stop mode.
-        Mutex::Autolock autoLock(mQuickStopLock);
-        CHECK_EQ(OK, mCamera->takePicture(CAMERA_MSG_RAW_IMAGE));
-        if (mQuickStop) {
-            LOGV("threadTimeLapseEntry: Exiting due to mQuickStop = true");
-            return;
-        }
-        mTakePictureCondition.waitRelative(mQuickStopLock,
-                mTimeBetweenTimeLapseFrameCaptureUs * 1000);
-    }
-    LOGV("threadTimeLapseEntry: Exiting due to mStarted = false");
-}
-
-void CameraSourceTimeLapse::startCameraRecording() {
-    if (mUseStillCameraForTimeLapse) {
-        LOGV("start time lapse recording using still camera");
-
-        int64_t token = IPCThreadState::self()->clearCallingIdentity();
-        String8 s = mCamera->getParameters();
-
-        CameraParameters params(s);
-        params.setPictureSize(mPictureWidth, mPictureHeight);
-        mCamera->setParameters(params.flatten());
-        mCameraIdle = true;
-        mStopWaitingForIdleCamera = false;
-
-        // disable shutter sound and play the recording sound.
-        mCamera->sendCommand(CAMERA_CMD_ENABLE_SHUTTER_SOUND, 0, 0);
-        mCamera->sendCommand(CAMERA_CMD_PLAY_RECORDING_SOUND, 0, 0);
-        IPCThreadState::self()->restoreCallingIdentity(token);
-
-        // create a thread which takes pictures in a loop
-        pthread_attr_t attr;
-        pthread_attr_init(&attr);
-        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
-
-        pthread_create(&mThreadTimeLapse, &attr, ThreadTimeLapseWrapper, this);
-        pthread_attr_destroy(&attr);
-    } else {
-        LOGV("start time lapse recording using video camera");
-        CameraSource::startCameraRecording();
-    }
-}
-
 void CameraSourceTimeLapse::stopCameraRecording() {
-    if (mUseStillCameraForTimeLapse) {
-        void *dummy;
-        pthread_join(mThreadTimeLapse, &dummy);
-
-        // Last takePicture may still be underway. Wait for the camera to get
-        // idle.
-        Mutex::Autolock autoLock(mCameraIdleLock);
-        mStopWaitingForIdleCamera = true;
-        if (!mCameraIdle) {
-            mCameraIdleCondition.wait(mCameraIdleLock);
-        }
-        CHECK(mCameraIdle);
-        mCamera->setListener(NULL);
-
-        // play the recording sound.
-        mCamera->sendCommand(CAMERA_CMD_PLAY_RECORDING_SOUND, 0, 0);
-    } else {
-        CameraSource::stopCameraRecording();
-    }
+    LOGV("stopCameraRecording");
+    CameraSource::stopCameraRecording();
     if (mLastReadBufferCopy) {
         mLastReadBufferCopy->release();
         mLastReadBufferCopy = NULL;
     }
 }
 
-void CameraSourceTimeLapse::releaseRecordingFrame(const sp<IMemory>& frame) {
-    if (!mUseStillCameraForTimeLapse) {
-        CameraSource::releaseRecordingFrame(frame);
-    }
-}
+sp<IMemory> CameraSourceTimeLapse::createIMemoryCopy(
+        const sp<IMemory> &source_data) {
 
-sp<IMemory> CameraSourceTimeLapse::createIMemoryCopy(const sp<IMemory> &source_data) {
+    LOGV("createIMemoryCopy");
     size_t source_size = source_data->size();
     void* source_pointer = source_data->pointer();
 
@@ -363,102 +226,8 @@
     return newMemory;
 }
 
-// Allocates IMemory of final type MemoryBase with the given size.
-sp<IMemory> allocateIMemory(size_t size) {
-    sp<MemoryHeapBase> newMemoryHeap = new MemoryHeapBase(size);
-    sp<MemoryBase> newMemory = new MemoryBase(newMemoryHeap, 0, size);
-    return newMemory;
-}
-
-// static
-void *CameraSourceTimeLapse::ThreadStartPreviewWrapper(void *me) {
-    CameraSourceTimeLapse *source = static_cast<CameraSourceTimeLapse *>(me);
-    source->threadStartPreview();
-    return NULL;
-}
-
-void CameraSourceTimeLapse::threadStartPreview() {
-    CHECK_EQ(OK, mCamera->startPreview());
-    Mutex::Autolock autoLock(mCameraIdleLock);
-    mCameraIdle = true;
-    mCameraIdleCondition.signal();
-}
-
-void CameraSourceTimeLapse::restartPreview() {
-    // Start this in a different thread, so that the dataCallback can return
-    LOGV("restartPreview");
-    pthread_attr_t attr;
-    pthread_attr_init(&attr);
-    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
-    pthread_t threadPreview;
-    pthread_create(&threadPreview, &attr, ThreadStartPreviewWrapper, this);
-    pthread_attr_destroy(&attr);
-}
-
-sp<IMemory> CameraSourceTimeLapse::cropYUVImage(const sp<IMemory> &source_data) {
-    // find the YUV format
-    int32_t srcFormat;
-    CHECK(mMeta->findInt32(kKeyColorFormat, &srcFormat));
-    YUVImage::YUVFormat yuvFormat;
-    if (srcFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
-        yuvFormat = YUVImage::YUV420SemiPlanar;
-    } else {
-        CHECK_EQ(srcFormat, OMX_COLOR_FormatYUV420Planar);
-        yuvFormat = YUVImage::YUV420Planar;
-    }
-
-    // allocate memory for cropped image and setup a canvas using it.
-    sp<IMemory> croppedImageMemory = allocateIMemory(
-            YUVImage::bufferSize(yuvFormat, mVideoWidth, mVideoHeight));
-    YUVImage yuvImageCropped(yuvFormat,
-            mVideoWidth, mVideoHeight,
-            (uint8_t *)croppedImageMemory->pointer());
-    YUVCanvas yuvCanvasCrop(yuvImageCropped);
-
-    YUVImage yuvImageSource(yuvFormat,
-            mPictureWidth, mPictureHeight,
-            (uint8_t *)source_data->pointer());
-    yuvCanvasCrop.CopyImageRect(
-            Rect(mCropRectStartX, mCropRectStartY,
-                mCropRectStartX + mVideoWidth,
-                mCropRectStartY + mVideoHeight),
-            0, 0,
-            yuvImageSource);
-
-    return croppedImageMemory;
-}
-
-void CameraSourceTimeLapse::dataCallback(int32_t msgType, const sp<IMemory> &data) {
-    if (msgType == CAMERA_MSG_COMPRESSED_IMAGE) {
-        // takePicture will complete after this callback, so restart preview.
-        restartPreview();
-        return;
-    }
-    if (msgType != CAMERA_MSG_RAW_IMAGE) {
-        return;
-    }
-
-    LOGV("dataCallback for timelapse still frame");
-    CHECK_EQ(true, mUseStillCameraForTimeLapse);
-
-    int64_t timestampUs;
-    if (mNumFramesReceived == 0) {
-        timestampUs = mStartTimeUs;
-    } else {
-        timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
-    }
-
-    if (mNeedCropping) {
-        sp<IMemory> croppedImageData = cropYUVImage(data);
-        dataCallbackTimestamp(timestampUs, msgType, croppedImageData);
-    } else {
-        sp<IMemory> dataCopy = createIMemoryCopy(data);
-        dataCallbackTimestamp(timestampUs, msgType, dataCopy);
-    }
-}
-
 bool CameraSourceTimeLapse::skipCurrentFrame(int64_t timestampUs) {
+    LOGV("skipCurrentFrame");
     if (mSkipCurrentFrame) {
         mSkipCurrentFrame = false;
         return true;
@@ -468,72 +237,58 @@
 }
 
 bool CameraSourceTimeLapse::skipFrameAndModifyTimeStamp(int64_t *timestampUs) {
-    if (!mUseStillCameraForTimeLapse) {
-        if (mLastTimeLapseFrameRealTimestampUs == 0) {
-            // First time lapse frame. Initialize mLastTimeLapseFrameRealTimestampUs
-            // to current time (timestampUs) and save frame data.
-            LOGV("dataCallbackTimestamp timelapse: initial frame");
+    LOGV("skipFrameAndModifyTimeStamp");
+    if (mLastTimeLapseFrameRealTimestampUs == 0) {
+        // First time lapse frame. Initialize mLastTimeLapseFrameRealTimestampUs
+        // to current time (timestampUs) and save frame data.
+        LOGV("dataCallbackTimestamp timelapse: initial frame");
 
-            mLastTimeLapseFrameRealTimestampUs = *timestampUs;
+        mLastTimeLapseFrameRealTimestampUs = *timestampUs;
+        return false;
+    }
+
+    {
+        Mutex::Autolock autoLock(mQuickStopLock);
+
+        // mForceRead may be set to true by startQuickReadReturns(). In that
+        // case don't skip this frame.
+        if (mForceRead) {
+            LOGV("dataCallbackTimestamp timelapse: forced read");
+            mForceRead = false;
+            *timestampUs =
+                mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
             return false;
         }
+    }
 
-        {
-            Mutex::Autolock autoLock(mQuickStopLock);
+    // Workaround to bypass the first 2 input frames for skipping.
+    // The first 2 output frames from the encoder are: decoder specific info and
+    // the compressed video frame data for the first input video frame.
+    if (mNumFramesEncoded >= 1 && *timestampUs <
+        (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenTimeLapseFrameCaptureUs)) {
+        // Skip all frames from last encoded frame until
+        // sufficient time (mTimeBetweenTimeLapseFrameCaptureUs) has passed.
+        // Tell the camera to release its recording frame and return.
+        LOGV("dataCallbackTimestamp timelapse: skipping intermediate frame");
+        return true;
+    } else {
+        // Desired frame has arrived after mTimeBetweenTimeLapseFrameCaptureUs time:
+        // - Reset mLastTimeLapseFrameRealTimestampUs to current time.
+        // - Artificially modify timestampUs to be one frame time (1/framerate) ahead
+        // of the last encoded frame's time stamp.
+        LOGV("dataCallbackTimestamp timelapse: got timelapse frame");
 
-            // mForceRead may be set to true by startQuickReadReturns(). In that
-            // case don't skip this frame.
-            if (mForceRead) {
-                LOGV("dataCallbackTimestamp timelapse: forced read");
-                mForceRead = false;
-                *timestampUs =
-                    mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
-                return false;
-            }
-        }
-
-        // Workaround to bypass the first 2 input frames for skipping.
-        // The first 2 output frames from the encoder are: decoder specific info and
-        // the compressed video frame data for the first input video frame.
-        if (mNumFramesEncoded >= 1 && *timestampUs <
-                (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenTimeLapseFrameCaptureUs)) {
-            // Skip all frames from last encoded frame until
-            // sufficient time (mTimeBetweenTimeLapseFrameCaptureUs) has passed.
-            // Tell the camera to release its recording frame and return.
-            LOGV("dataCallbackTimestamp timelapse: skipping intermediate frame");
-            return true;
-        } else {
-            // Desired frame has arrived after mTimeBetweenTimeLapseFrameCaptureUs time:
-            // - Reset mLastTimeLapseFrameRealTimestampUs to current time.
-            // - Artificially modify timestampUs to be one frame time (1/framerate) ahead
-            // of the last encoded frame's time stamp.
-            LOGV("dataCallbackTimestamp timelapse: got timelapse frame");
-
-            mLastTimeLapseFrameRealTimestampUs = *timestampUs;
-            *timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
-            return false;
-        }
+        mLastTimeLapseFrameRealTimestampUs = *timestampUs;
+        *timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
+        return false;
     }
     return false;
 }
 
 void CameraSourceTimeLapse::dataCallbackTimestamp(int64_t timestampUs, int32_t msgType,
             const sp<IMemory> &data) {
-    if (!mUseStillCameraForTimeLapse) {
-        mSkipCurrentFrame = skipFrameAndModifyTimeStamp(&timestampUs);
-    } else {
-        Mutex::Autolock autoLock(mCameraIdleLock);
-        // If we are using the still camera and stop() has been called, it may
-        // be waiting for the camera to get idle. In that case return
-        // immediately. Calling CameraSource::dataCallbackTimestamp() will lead
-        // to a deadlock since it tries to access CameraSource::mLock which in
-        // this case is held by CameraSource::stop() currently waiting for the
-        // camera to get idle. And camera will not get idle until this call
-        // returns.
-        if (mStopWaitingForIdleCamera) {
-            return;
-        }
-    }
+    LOGV("dataCallbackTimestamp");
+    mSkipCurrentFrame = skipFrameAndModifyTimeStamp(&timestampUs);
     CameraSource::dataCallbackTimestamp(timestampUs, msgType, data);
 }
 
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 77a6602..4edb613 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -185,7 +185,8 @@
       mFinalStatus(OK),
       mLastAccessPos(0),
       mFetching(true),
-      mLastFetchTimeUs(-1) {
+      mLastFetchTimeUs(-1),
+      mNumRetriesLeft(kMaxNumRetries) {
     mLooper->setName("NuCachedSource2");
     mLooper->registerHandler(mReflector);
     mLooper->start();
@@ -254,7 +255,27 @@
 void NuCachedSource2::fetchInternal() {
     LOGV("fetchInternal");
 
-    CHECK_EQ(mFinalStatus, (status_t)OK);
+    {
+        Mutex::Autolock autoLock(mLock);
+        CHECK(mFinalStatus == OK || mNumRetriesLeft > 0);
+
+        if (mFinalStatus != OK) {
+            --mNumRetriesLeft;
+
+            status_t err =
+                mSource->reconnectAtOffset(mCacheOffset + mCache->totalSize());
+
+            if (err == ERROR_UNSUPPORTED) {
+                mNumRetriesLeft = 0;
+                return;
+            } else if (err != OK) {
+                LOGI("The attempt to reconnect failed, %d retries remaining",
+                     mNumRetriesLeft);
+
+                return;
+            }
+        }
+    }
 
     PageCache::Page *page = mCache->acquirePage();
 
@@ -264,14 +285,23 @@
     Mutex::Autolock autoLock(mLock);
 
     if (n < 0) {
-        LOGE("source returned error %ld", n);
+        LOGE("source returned error %ld, %d retries left", n, mNumRetriesLeft);
         mFinalStatus = n;
         mCache->releasePage(page);
     } else if (n == 0) {
         LOGI("ERROR_END_OF_STREAM");
+
+        mNumRetriesLeft = 0;
         mFinalStatus = ERROR_END_OF_STREAM;
+
         mCache->releasePage(page);
     } else {
+        if (mFinalStatus != OK) {
+            LOGI("retrying a previously failed read succeeded.");
+        }
+        mNumRetriesLeft = kMaxNumRetries;
+        mFinalStatus = OK;
+
         page->mSize = n;
         mCache->appendPage(page);
     }
@@ -280,7 +310,7 @@
 void NuCachedSource2::onFetch() {
     LOGV("onFetch");
 
-    if (mFinalStatus != OK) {
+    if (mFinalStatus != OK && mNumRetriesLeft == 0) {
         LOGV("EOS reached, done prefetching for now");
         mFetching = false;
     }
@@ -308,8 +338,19 @@
         restartPrefetcherIfNecessary_l();
     }
 
-    (new AMessage(kWhatFetchMore, mReflector->id()))->post(
-            mFetching ? 0 : 100000ll);
+    int64_t delayUs;
+    if (mFetching) {
+        if (mFinalStatus != OK && mNumRetriesLeft > 0) {
+            // We failed this time and will try again in 3 seconds.
+            delayUs = 3000000ll;
+        } else {
+            delayUs = 0;
+        }
+    } else {
+        delayUs = 100000ll;
+    }
+
+    (new AMessage(kWhatFetchMore, mReflector->id()))->post(delayUs);
 }
 
 void NuCachedSource2::onRead(const sp<AMessage> &msg) {
@@ -345,7 +386,7 @@
         bool ignoreLowWaterThreshold, bool force) {
     static const size_t kGrayArea = 1024 * 1024;
 
-    if (mFetching || mFinalStatus != OK) {
+    if (mFetching || (mFinalStatus != OK && mNumRetriesLeft == 0)) {
         return;
     }
 
@@ -427,6 +468,12 @@
 
 size_t NuCachedSource2::approxDataRemaining_l(status_t *finalStatus) {
     *finalStatus = mFinalStatus;
+
+    if (mFinalStatus != OK && mNumRetriesLeft > 0) {
+        // Pretend that everything is fine until we're out of retries.
+        *finalStatus = OK;
+    }
+
     off64_t lastBytePosCached = mCacheOffset + mCache->totalSize();
     if (mLastAccessPos < lastBytePosCached) {
         return lastBytePosCached - mLastAccessPos;
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 7bcbdcf..ac73351 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -48,6 +48,10 @@
 
 namespace android {
 
+// Treat time out as an error if we have not received any output
+// buffers after 3 seconds.
+const static int64_t kBufferFilledEventTimeOutUs = 3000000000LL;
+
 struct CodecInfo {
     const char *mime;
     const char *codec;
@@ -3191,6 +3195,16 @@
     mBufferFilled.signal();
 }
 
+status_t OMXCodec::waitForBufferFilled_l() {
+    status_t err = mBufferFilled.waitRelative(mLock, kBufferFilledEventTimeOutUs);
+    if (err != OK) {
+        LOGE("Timed out waiting for buffers from video encoder: %d/%d",
+            countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
+            countBuffersWeOwn(mPortBuffers[kPortIndexOutput]));
+    }
+    return err;
+}
+
 void OMXCodec::setRawAudioFormat(
         OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
 
@@ -3623,6 +3637,7 @@
 
 status_t OMXCodec::read(
         MediaBuffer **buffer, const ReadOptions *options) {
+    status_t err = OK;
     *buffer = NULL;
 
     Mutex::Autolock autoLock(mLock);
@@ -3663,7 +3678,9 @@
 
     if (seeking) {
         while (mState == RECONFIGURING) {
-            mBufferFilled.wait(mLock);
+            if ((err = waitForBufferFilled_l()) != OK) {
+                return err;
+            }
         }
 
         if (mState != EXECUTING) {
@@ -3694,19 +3711,15 @@
         }
 
         while (mSeekTimeUs >= 0) {
-            mBufferFilled.wait(mLock);
+            if ((err = waitForBufferFilled_l()) != OK) {
+                return err;
+            }
         }
     }
 
     while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) {
-        if (mIsEncoder) {
-            if (NO_ERROR != mBufferFilled.waitRelative(mLock, 3000000000LL)) {
-                LOGW("Timed out waiting for buffers from video encoder: %d/%d",
-                    countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
-                    countBuffersWeOwn(mPortBuffers[kPortIndexOutput]));
-            }
-        } else {
-            mBufferFilled.wait(mLock);
+        if ((err = waitForBufferFilled_l()) != OK) {
+            return err;
         }
     }
 
@@ -4415,6 +4428,13 @@
     return OK;
 }
 
+status_t QueryCodecs(
+        const sp<IOMX> &omx,
+        const char *mimeType, bool queryDecoders,
+        Vector<CodecCapabilities> *results) {
+    return QueryCodecs(omx, mimeType, queryDecoders, false /*hwCodecOnly*/, results);
+}
+
 void OMXCodec::restorePatchedDataPointer(BufferInfo *info) {
     CHECK(mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames));
     CHECK(mOMXLivesLocally);
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 89faff7..571e8be 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -52,13 +52,13 @@
     return false;
 }
 
-static status_t HandleMIDI(
+static MediaScanResult HandleMIDI(
         const char *filename, MediaScannerClient *client) {
     // get the library configuration and do sanity check
     const S_EAS_LIB_CONFIG* pLibConfig = EAS_Config();
     if ((pLibConfig == NULL) || (LIB_VERSION != pLibConfig->libVersion)) {
         LOGE("EAS library/header mismatch\n");
-        return UNKNOWN_ERROR;
+        return MEDIA_SCAN_RESULT_ERROR;
     }
     EAS_I32 temp;
 
@@ -88,34 +88,41 @@
     }
 
     if (result != EAS_SUCCESS) {
-        return UNKNOWN_ERROR;
+        return MEDIA_SCAN_RESULT_SKIPPED;
     }
 
     char buffer[20];
     sprintf(buffer, "%ld", temp);
-    if (!client->addStringTag("duration", buffer)) return UNKNOWN_ERROR;
-
-    return OK;
+    status_t status = client->addStringTag("duration", buffer);
+    if (status) {
+        return MEDIA_SCAN_RESULT_ERROR;
+    }
+    return MEDIA_SCAN_RESULT_OK;
 }
 
-status_t StagefrightMediaScanner::processFile(
+MediaScanResult StagefrightMediaScanner::processFile(
         const char *path, const char *mimeType,
         MediaScannerClient &client) {
     LOGV("processFile '%s'.", path);
 
     client.setLocale(locale());
     client.beginFile();
+    MediaScanResult result = processFileInternal(path, mimeType, client);
+    client.endFile();
+    return result;
+}
 
+MediaScanResult StagefrightMediaScanner::processFileInternal(
+        const char *path, const char *mimeType,
+        MediaScannerClient &client) {
     const char *extension = strrchr(path, '.');
 
     if (!extension) {
-        return UNKNOWN_ERROR;
+        return MEDIA_SCAN_RESULT_SKIPPED;
     }
 
     if (!FileHasAcceptableExtension(extension)) {
-        client.endFile();
-
-        return UNKNOWN_ERROR;
+        return MEDIA_SCAN_RESULT_SKIPPED;
     }
 
     if (!strcasecmp(extension, ".mid")
@@ -127,53 +134,57 @@
             || !strcasecmp(extension, ".rtx")
             || !strcasecmp(extension, ".ota")
             || !strcasecmp(extension, ".mxmf")) {
-        status_t status = HandleMIDI(path, &client);
-        if (status != OK) {
-            return status;
+        return HandleMIDI(path, &client);
+    }
+
+    sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever);
+
+    status_t status = mRetriever->setDataSource(path);
+    if (status) {
+        return MEDIA_SCAN_RESULT_ERROR;
+    }
+
+    const char *value;
+    if ((value = mRetriever->extractMetadata(
+                    METADATA_KEY_MIMETYPE)) != NULL) {
+        status = client.setMimeType(value);
+        if (status) {
+            return MEDIA_SCAN_RESULT_ERROR;
         }
-    } else {
-        sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever);
+    }
 
-         if (mRetriever->setDataSource(path) == OK) {
-            const char *value;
-            if ((value = mRetriever->extractMetadata(
-                            METADATA_KEY_MIMETYPE)) != NULL) {
-                client.setMimeType(value);
-            }
+    struct KeyMap {
+        const char *tag;
+        int key;
+    };
+    static const KeyMap kKeyMap[] = {
+        { "tracknumber", METADATA_KEY_CD_TRACK_NUMBER },
+        { "discnumber", METADATA_KEY_DISC_NUMBER },
+        { "album", METADATA_KEY_ALBUM },
+        { "artist", METADATA_KEY_ARTIST },
+        { "albumartist", METADATA_KEY_ALBUMARTIST },
+        { "composer", METADATA_KEY_COMPOSER },
+        { "genre", METADATA_KEY_GENRE },
+        { "title", METADATA_KEY_TITLE },
+        { "year", METADATA_KEY_YEAR },
+        { "duration", METADATA_KEY_DURATION },
+        { "writer", METADATA_KEY_WRITER },
+        { "compilation", METADATA_KEY_COMPILATION },
+        { "isdrm", METADATA_KEY_IS_DRM },
+    };
+    static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]);
 
-            struct KeyMap {
-                const char *tag;
-                int key;
-            };
-            static const KeyMap kKeyMap[] = {
-                { "tracknumber", METADATA_KEY_CD_TRACK_NUMBER },
-                { "discnumber", METADATA_KEY_DISC_NUMBER },
-                { "album", METADATA_KEY_ALBUM },
-                { "artist", METADATA_KEY_ARTIST },
-                { "albumartist", METADATA_KEY_ALBUMARTIST },
-                { "composer", METADATA_KEY_COMPOSER },
-                { "genre", METADATA_KEY_GENRE },
-                { "title", METADATA_KEY_TITLE },
-                { "year", METADATA_KEY_YEAR },
-                { "duration", METADATA_KEY_DURATION },
-                { "writer", METADATA_KEY_WRITER },
-                { "compilation", METADATA_KEY_COMPILATION },
-                { "isdrm", METADATA_KEY_IS_DRM },
-            };
-            static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]);
-
-            for (size_t i = 0; i < kNumEntries; ++i) {
-                const char *value;
-                if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) {
-                    client.addStringTag(kKeyMap[i].tag, value);
-                }
+    for (size_t i = 0; i < kNumEntries; ++i) {
+        const char *value;
+        if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) {
+            status = client.addStringTag(kKeyMap[i].tag, value);
+            if (status) {
+                return MEDIA_SCAN_RESULT_ERROR;
             }
         }
     }
 
-    client.endFile();
-
-    return OK;
+    return MEDIA_SCAN_RESULT_OK;
 }
 
 char *StagefrightMediaScanner::extractAlbumArt(int fd) {
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
new file mode 100644
index 0000000..3d8c56a
--- /dev/null
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -0,0 +1,792 @@
+/*
+ * Copyright (C) 2011 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_TAG "SurfaceMediaSource"
+
+#include <media/stagefright/SurfaceMediaSource.h>
+#include <ui/GraphicBuffer.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/openmax/OMX_IVCommon.h>
+#include <media/stagefright/MetadataBufferType.h>
+
+#include <surfaceflinger/ISurfaceComposer.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
+#include <surfaceflinger/IGraphicBufferAlloc.h>
+#include <OMX_Component.h>
+
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+namespace android {
+
+SurfaceMediaSource::SurfaceMediaSource(uint32_t bufW, uint32_t bufH) :
+                mDefaultWidth(bufW),
+                mDefaultHeight(bufH),
+                mPixelFormat(0),
+                mBufferCount(MIN_ASYNC_BUFFER_SLOTS),
+                mClientBufferCount(0),
+                mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
+                mCurrentSlot(INVALID_BUFFER_SLOT),
+                mCurrentTimestamp(0),
+                mSynchronousMode(true),
+                mConnectedApi(NO_CONNECTED_API),
+                mFrameRate(30),
+                mStarted(false)   {
+    LOGV("SurfaceMediaSource::SurfaceMediaSource");
+    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
+    mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
+}
+
+SurfaceMediaSource::~SurfaceMediaSource() {
+    LOGV("SurfaceMediaSource::~SurfaceMediaSource");
+    if (mStarted) {
+        stop();
+    }
+    freeAllBuffers();
+}
+
+size_t SurfaceMediaSource::getQueuedCount() const {
+    Mutex::Autolock lock(mMutex);
+    return mQueue.size();
+}
+
+status_t SurfaceMediaSource::setBufferCountServerLocked(int bufferCount) {
+    if (bufferCount > NUM_BUFFER_SLOTS)
+        return BAD_VALUE;
+
+    // special-case, nothing to do
+    if (bufferCount == mBufferCount)
+        return OK;
+
+    if (!mClientBufferCount &&
+        bufferCount >= mBufferCount) {
+        // easy, we just have more buffers
+        mBufferCount = bufferCount;
+        mServerBufferCount = bufferCount;
+        mDequeueCondition.signal();
+    } else {
+        // we're here because we're either
+        // - reducing the number of available buffers
+        // - or there is a client-buffer-count in effect
+
+        // less than 2 buffers is never allowed
+        if (bufferCount < 2)
+            return BAD_VALUE;
+
+        // when there is non client-buffer-count in effect, the client is not
+        // allowed to dequeue more than one buffer at a time,
+        // so the next time they dequeue a buffer, we know that they don't
+        // own one. the actual resizing will happen during the next
+        // dequeueBuffer.
+
+        mServerBufferCount = bufferCount;
+    }
+    return OK;
+}
+
+// Called from the consumer side
+status_t SurfaceMediaSource::setBufferCountServer(int bufferCount) {
+    Mutex::Autolock lock(mMutex);
+    return setBufferCountServerLocked(bufferCount);
+}
+
+status_t SurfaceMediaSource::setBufferCount(int bufferCount) {
+    LOGV("SurfaceMediaSource::setBufferCount");
+    if (bufferCount > NUM_BUFFER_SLOTS) {
+        LOGE("setBufferCount: bufferCount is larger than the number of buffer slots");
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock lock(mMutex);
+    // Error out if the user has dequeued buffers
+    for (int i = 0 ; i < mBufferCount ; i++) {
+        if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
+            LOGE("setBufferCount: client owns some buffers");
+            return INVALID_OPERATION;
+        }
+    }
+
+    if (bufferCount == 0) {
+        const int minBufferSlots = mSynchronousMode ?
+                MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
+        mClientBufferCount = 0;
+        bufferCount = (mServerBufferCount >= minBufferSlots) ?
+                mServerBufferCount : minBufferSlots;
+        return setBufferCountServerLocked(bufferCount);
+    }
+
+    // We don't allow the client to set a buffer-count less than
+    // MIN_ASYNC_BUFFER_SLOTS (3), there is no reason for it.
+    if (bufferCount < MIN_ASYNC_BUFFER_SLOTS) {
+        return BAD_VALUE;
+    }
+
+    // here we're guaranteed that the client doesn't have dequeued buffers
+    // and will release all of its buffer references.
+    freeAllBuffers();
+    mBufferCount = bufferCount;
+    mClientBufferCount = bufferCount;
+    mCurrentSlot = INVALID_BUFFER_SLOT;
+    mQueue.clear();
+    mDequeueCondition.signal();
+    return OK;
+}
+
+status_t SurfaceMediaSource::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
+    LOGV("SurfaceMediaSource::requestBuffer");
+    Mutex::Autolock lock(mMutex);
+    if (slot < 0 || mBufferCount <= slot) {
+        LOGE("requestBuffer: slot index out of range [0, %d]: %d",
+                mBufferCount, slot);
+        return BAD_VALUE;
+    }
+    mSlots[slot].mRequestBufferCalled = true;
+    *buf = mSlots[slot].mGraphicBuffer;
+    return NO_ERROR;
+}
+
+status_t SurfaceMediaSource::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
+                                            uint32_t format, uint32_t usage) {
+    LOGV("dequeueBuffer");
+
+
+    // Check for the buffer size- the client should just use the
+    // default width and height, and not try to set those.
+    // This is needed since
+    // the getFormat() returns mDefaultWidth/ Height for the OMX. It is
+    // queried by OMX in the beginning and not every time a frame comes.
+    // Not sure if there is  a way to update the
+    // frame size while recording. So as of now, the client side
+    // sets the default values via the constructor, and the encoder is
+    // setup to encode frames of that size
+    // The design might need to change in the future.
+    // TODO: Currently just uses mDefaultWidth/Height. In the future
+    // we might declare mHeight and mWidth and check against those here.
+    if ((w != 0) || (h != 0)) {
+        LOGE("dequeuebuffer: invalid buffer size! Req: %dx%d, Found: %dx%d",
+                mDefaultWidth, mDefaultHeight, w, h);
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock lock(mMutex);
+
+    status_t returnFlags(OK);
+
+    int found, foundSync;
+    int dequeuedCount = 0;
+    bool tryAgain = true;
+    while (tryAgain) {
+        // We need to wait for the FIFO to drain if the number of buffer
+        // needs to change.
+        //
+        // The condition "number of buffer needs to change" is true if
+        // - the client doesn't care about how many buffers there are
+        // - AND the actual number of buffer is different from what was
+        //   set in the last setBufferCountServer()
+        //                         - OR -
+        //   setBufferCountServer() was set to a value incompatible with
+        //   the synchronization mode (for instance because the sync mode
+        //   changed since)
+        //
+        // As long as this condition is true AND the FIFO is not empty, we
+        // wait on mDequeueCondition.
+
+        int minBufferCountNeeded = mSynchronousMode ?
+                MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
+
+        if (!mClientBufferCount &&
+                ((mServerBufferCount != mBufferCount) ||
+                        (mServerBufferCount < minBufferCountNeeded))) {
+            // wait for the FIFO to drain
+            while (!mQueue.isEmpty()) {
+                LOGV("Waiting for the FIFO to drain");
+                mDequeueCondition.wait(mMutex);
+            }
+            // need to check again since the mode could have changed
+            // while we were waiting
+            minBufferCountNeeded = mSynchronousMode ?
+                    MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
+        }
+
+        if (!mClientBufferCount &&
+                ((mServerBufferCount != mBufferCount) ||
+                        (mServerBufferCount < minBufferCountNeeded))) {
+            // here we're guaranteed that mQueue is empty
+            freeAllBuffers();
+            mBufferCount = mServerBufferCount;
+            if (mBufferCount < minBufferCountNeeded)
+                mBufferCount = minBufferCountNeeded;
+            mCurrentSlot = INVALID_BUFFER_SLOT;
+            returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
+        }
+
+        // look for a free buffer to give to the client
+        found = INVALID_BUFFER_SLOT;
+        foundSync = INVALID_BUFFER_SLOT;
+        dequeuedCount = 0;
+        for (int i = 0; i < mBufferCount; i++) {
+            const int state = mSlots[i].mBufferState;
+            if (state == BufferSlot::DEQUEUED) {
+                dequeuedCount++;
+                continue; // won't be continuing if could
+                // dequeue a non 'FREE' current slot like
+                // that in SurfaceTexture
+            }
+            // In case of Encoding, we do not deque the mCurrentSlot buffer
+            //  since we follow synchronous mode (unlike possibly in
+            //  SurfaceTexture that could be using the asynch mode
+            //  or has some mechanism in GL to be able to wait till the
+            //  currentslot is done using the data)
+            // Here, we have to wait for the MPEG4Writer(or equiv)
+            // to tell us when it's done using the current buffer
+            if (state == BufferSlot::FREE) {
+                foundSync = i;
+                // Unlike that in SurfaceTexture,
+                // We don't need to worry if it is the
+                // currentslot or not as it is in state FREE
+                found = i;
+                break;
+            }
+        }
+
+        // clients are not allowed to dequeue more than one buffer
+        // if they didn't set a buffer count.
+        if (!mClientBufferCount && dequeuedCount) {
+            return -EINVAL;
+        }
+
+        // See whether a buffer has been queued since the last setBufferCount so
+        // we know whether to perform the MIN_UNDEQUEUED_BUFFERS check below.
+        bool bufferHasBeenQueued = mCurrentSlot != INVALID_BUFFER_SLOT;
+        if (bufferHasBeenQueued) {
+            // make sure the client is not trying to dequeue more buffers
+            // than allowed.
+            const int avail = mBufferCount - (dequeuedCount+1);
+            if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
+                LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded (dequeued=%d)",
+                        MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
+                        dequeuedCount);
+                return -EBUSY;
+            }
+        }
+
+        // we're in synchronous mode and didn't find a buffer, we need to wait
+        // for for some buffers to be consumed
+        tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
+        if (tryAgain) {
+            LOGW("Waiting..In synchronous mode and no buffer to dQ");
+            mDequeueCondition.wait(mMutex);
+        }
+    }
+
+    if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
+        // foundSync guaranteed to be != INVALID_BUFFER_SLOT
+        found = foundSync;
+    }
+
+    if (found == INVALID_BUFFER_SLOT) {
+        return -EBUSY;
+    }
+
+    const int buf = found;
+    *outBuf = found;
+
+    const bool useDefaultSize = !w && !h;
+    if (useDefaultSize) {
+        // use the default size
+        w = mDefaultWidth;
+        h = mDefaultHeight;
+    }
+
+    const bool updateFormat = (format != 0);
+    if (!updateFormat) {
+        // keep the current (or default) format
+        format = mPixelFormat;
+    }
+
+    // buffer is now in DEQUEUED (but can also be current at the same time,
+    // if we're in synchronous mode)
+    mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
+
+    const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
+    if ((buffer == NULL) ||
+        (uint32_t(buffer->width)  != w) ||
+        (uint32_t(buffer->height) != h) ||
+        (uint32_t(buffer->format) != format) ||
+        ((uint32_t(buffer->usage) & usage) != usage)) {
+            usage |= GraphicBuffer::USAGE_HW_TEXTURE;
+            status_t error;
+            sp<GraphicBuffer> graphicBuffer(
+                    mGraphicBufferAlloc->createGraphicBuffer(
+                                    w, h, format, usage, &error));
+            if (graphicBuffer == 0) {
+                LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed");
+                return error;
+            }
+            if (updateFormat) {
+                mPixelFormat = format;
+            }
+            mSlots[buf].mGraphicBuffer = graphicBuffer;
+            mSlots[buf].mRequestBufferCalled = false;
+            returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
+    }
+    return returnFlags;
+}
+
+status_t SurfaceMediaSource::setSynchronousMode(bool enabled) {
+    Mutex::Autolock lock(mMutex);
+
+    status_t err = OK;
+    if (!enabled) {
+        // going to asynchronous mode, drain the queue
+        while (mSynchronousMode != enabled && !mQueue.isEmpty()) {
+            mDequeueCondition.wait(mMutex);
+        }
+    }
+
+    if (mSynchronousMode != enabled) {
+        // - if we're going to asynchronous mode, the queue is guaranteed to be
+        // empty here
+        // - if the client set the number of buffers, we're guaranteed that
+        // we have at least 3 (because we don't allow less)
+        mSynchronousMode = enabled;
+        mDequeueCondition.signal();
+    }
+    return err;
+}
+
+status_t SurfaceMediaSource::connect(int api) {
+    LOGV("SurfaceMediaSource::connect");
+    Mutex::Autolock lock(mMutex);
+    status_t err = NO_ERROR;
+    switch (api) {
+        case NATIVE_WINDOW_API_EGL:
+        case NATIVE_WINDOW_API_CPU:
+        case NATIVE_WINDOW_API_MEDIA:
+        case NATIVE_WINDOW_API_CAMERA:
+            if (mConnectedApi != NO_CONNECTED_API) {
+                err = -EINVAL;
+            } else {
+                mConnectedApi = api;
+            }
+            break;
+        default:
+            err = -EINVAL;
+            break;
+    }
+    return err;
+}
+
+status_t SurfaceMediaSource::disconnect(int api) {
+    LOGV("SurfaceMediaSource::disconnect");
+    Mutex::Autolock lock(mMutex);
+    status_t err = NO_ERROR;
+    switch (api) {
+        case NATIVE_WINDOW_API_EGL:
+        case NATIVE_WINDOW_API_CPU:
+        case NATIVE_WINDOW_API_MEDIA:
+        case NATIVE_WINDOW_API_CAMERA:
+            if (mConnectedApi == api) {
+                mConnectedApi = NO_CONNECTED_API;
+            } else {
+                err = -EINVAL;
+            }
+            break;
+        default:
+            err = -EINVAL;
+            break;
+    }
+    return err;
+}
+
+status_t SurfaceMediaSource::queueBuffer(int buf, int64_t timestamp,
+        uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
+    LOGV("queueBuffer");
+
+    Mutex::Autolock lock(mMutex);
+    if (buf < 0 || buf >= mBufferCount) {
+        LOGE("queueBuffer: slot index out of range [0, %d]: %d",
+                mBufferCount, buf);
+        return -EINVAL;
+    } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
+        LOGE("queueBuffer: slot %d is not owned by the client (state=%d)",
+                buf, mSlots[buf].mBufferState);
+        return -EINVAL;
+    } else if (!mSlots[buf].mRequestBufferCalled) {
+        LOGE("queueBuffer: slot %d was enqueued without requesting a "
+                "buffer", buf);
+        return -EINVAL;
+    }
+
+    if (mSynchronousMode) {
+        // in synchronous mode we queue all buffers in a FIFO
+        mQueue.push_back(buf);
+        LOGV("Client queued buffer on slot: %d, Q size = %d",
+                                                buf, mQueue.size());
+    } else {
+        // in asynchronous mode we only keep the most recent buffer
+        if (mQueue.empty()) {
+            mQueue.push_back(buf);
+        } else {
+            Fifo::iterator front(mQueue.begin());
+            // buffer currently queued is freed
+            mSlots[*front].mBufferState = BufferSlot::FREE;
+            // and we record the new buffer index in the queued list
+            *front = buf;
+        }
+    }
+
+    mSlots[buf].mBufferState = BufferSlot::QUEUED;
+    mSlots[buf].mTimestamp = timestamp;
+    // TODO: (Confirm) Don't want to signal dequeue here.
+    // May be just in asynchronous mode?
+    // mDequeueCondition.signal();
+
+    // Once the queuing is done, we need to let the listener
+    // and signal the buffer consumer (encoder) know that a
+    // buffer is available
+    onFrameReceivedLocked();
+
+    *outWidth = mDefaultWidth;
+    *outHeight = mDefaultHeight;
+    *outTransform = 0;
+
+    return OK;
+}
+
+
+// onFrameReceivedLocked informs the buffer consumers (StageFrightRecorder)
+// or listeners that a frame has been received
+// It is supposed to be called only from queuebuffer.
+// The buffer is NOT made available for dequeueing immediately. We need to
+// wait to hear from StageFrightRecorder to set the buffer FREE
+// Make sure this is called when the mutex is locked
+status_t SurfaceMediaSource::onFrameReceivedLocked() {
+    LOGV("On Frame Received");
+    // Signal the encoder that a new frame has arrived
+    mFrameAvailableCondition.signal();
+
+    // call back the listener
+    // TODO: The listener may not be needed in SurfaceMediaSource at all.
+    // This can be made a SurfaceTexture specific thing
+    sp<FrameAvailableListener> listener;
+    if (mSynchronousMode || mQueue.empty()) {
+        listener = mFrameAvailableListener;
+    }
+
+    if (listener != 0) {
+        listener->onFrameAvailable();
+    }
+    return OK;
+}
+
+
+void SurfaceMediaSource::cancelBuffer(int buf) {
+    LOGV("SurfaceMediaSource::cancelBuffer");
+    Mutex::Autolock lock(mMutex);
+    if (buf < 0 || buf >= mBufferCount) {
+        LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
+                mBufferCount, buf);
+        return;
+    } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
+        LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
+                buf, mSlots[buf].mBufferState);
+        return;
+    }
+    mSlots[buf].mBufferState = BufferSlot::FREE;
+    mDequeueCondition.signal();
+}
+
+nsecs_t SurfaceMediaSource::getTimestamp() {
+    LOGV("SurfaceMediaSource::getTimestamp");
+    Mutex::Autolock lock(mMutex);
+    return mCurrentTimestamp;
+}
+
+
+void SurfaceMediaSource::setFrameAvailableListener(
+        const sp<FrameAvailableListener>& listener) {
+    LOGV("SurfaceMediaSource::setFrameAvailableListener");
+    Mutex::Autolock lock(mMutex);
+    mFrameAvailableListener = listener;
+}
+
+void SurfaceMediaSource::freeAllBuffers() {
+    LOGV("freeAllBuffers");
+    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+        mSlots[i].mGraphicBuffer = 0;
+        mSlots[i].mBufferState = BufferSlot::FREE;
+    }
+}
+
+sp<GraphicBuffer> SurfaceMediaSource::getCurrentBuffer() const {
+    Mutex::Autolock lock(mMutex);
+    return mCurrentBuf;
+}
+
+int SurfaceMediaSource::query(int what, int* outValue)
+{
+    LOGV("query");
+    Mutex::Autolock lock(mMutex);
+    int value;
+    switch (what) {
+    case NATIVE_WINDOW_WIDTH:
+        value = mDefaultWidth;
+        if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0)
+            value = mCurrentBuf->width;
+        break;
+    case NATIVE_WINDOW_HEIGHT:
+        value = mDefaultHeight;
+        if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0)
+            value = mCurrentBuf->height;
+        break;
+    case NATIVE_WINDOW_FORMAT:
+        value = mPixelFormat;
+        break;
+    case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
+        value = mSynchronousMode ?
+                (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
+        break;
+    default:
+        return BAD_VALUE;
+    }
+    outValue[0] = value;
+    return NO_ERROR;
+}
+
+void SurfaceMediaSource::dump(String8& result) const
+{
+    char buffer[1024];
+    dump(result, "", buffer, 1024);
+}
+
+void SurfaceMediaSource::dump(String8& result, const char* prefix,
+        char* buffer, size_t SIZE) const
+{
+    Mutex::Autolock _l(mMutex);
+    snprintf(buffer, SIZE,
+            "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
+            "mPixelFormat=%d, \n",
+            prefix, mBufferCount, mSynchronousMode, mDefaultWidth, mDefaultHeight,
+            mPixelFormat);
+    result.append(buffer);
+
+    String8 fifo;
+    int fifoSize = 0;
+    Fifo::const_iterator i(mQueue.begin());
+    while (i != mQueue.end()) {
+        snprintf(buffer, SIZE, "%02d ", *i++);
+        fifoSize++;
+        fifo.append(buffer);
+    }
+
+    result.append(buffer);
+
+    struct {
+        const char * operator()(int state) const {
+            switch (state) {
+                case BufferSlot::DEQUEUED: return "DEQUEUED";
+                case BufferSlot::QUEUED: return "QUEUED";
+                case BufferSlot::FREE: return "FREE";
+                default: return "Unknown";
+            }
+        }
+    } stateName;
+
+    for (int i = 0; i < mBufferCount; i++) {
+        const BufferSlot& slot(mSlots[i]);
+        snprintf(buffer, SIZE,
+                "%s%s[%02d] state=%-8s, "
+                "timestamp=%lld\n",
+                prefix, (i==mCurrentSlot)?">":" ", i, stateName(slot.mBufferState),
+                slot.mTimestamp
+        );
+        result.append(buffer);
+    }
+}
+
+status_t SurfaceMediaSource::setFrameRate(int32_t fps)
+{
+    Mutex::Autolock lock(mMutex);
+    const int MAX_FRAME_RATE = 60;
+    if (fps < 0 || fps > MAX_FRAME_RATE) {
+        return BAD_VALUE;
+    }
+    mFrameRate = fps;
+    return OK;
+}
+
+bool SurfaceMediaSource::isMetaDataStoredInVideoBuffers() const {
+    LOGV("isMetaDataStoredInVideoBuffers");
+    return true;
+}
+
+int32_t SurfaceMediaSource::getFrameRate( ) const {
+    Mutex::Autolock lock(mMutex);
+    return mFrameRate;
+}
+
+status_t SurfaceMediaSource::start(MetaData *params)
+{
+    LOGV("start");
+    Mutex::Autolock lock(mMutex);
+    CHECK(!mStarted);
+    mStarted = true;
+    return OK;
+}
+
+
+status_t SurfaceMediaSource::stop()
+{
+    LOGV("Stop");
+
+    Mutex::Autolock lock(mMutex);
+    // TODO: Add waiting on mFrameCompletedCondition here?
+    mStarted = false;
+    mFrameAvailableCondition.signal();
+
+    return OK;
+}
+
+sp<MetaData> SurfaceMediaSource::getFormat()
+{
+    LOGV("getFormat");
+    Mutex::Autolock autoLock(mMutex);
+    sp<MetaData> meta = new MetaData;
+
+    meta->setInt32(kKeyWidth, mDefaultWidth);
+    meta->setInt32(kKeyHeight, mDefaultHeight);
+    // The encoder format is set as an opaque colorformat
+    // The encoder will later find out the actual colorformat
+    // from the GL Frames itself.
+    meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatAndroidOpaque);
+    meta->setInt32(kKeyStride, mDefaultWidth);
+    meta->setInt32(kKeySliceHeight, mDefaultHeight);
+    meta->setInt32(kKeyFrameRate, mFrameRate);
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
+    return meta;
+}
+
+status_t SurfaceMediaSource::read( MediaBuffer **buffer,
+                                const ReadOptions *options)
+{
+    LOGV("Read. Size of queued buffer: %d", mQueue.size());
+    *buffer = NULL;
+
+    Mutex::Autolock autoLock(mMutex) ;
+    // If the recording has started and the queue is empty, then just
+    // wait here till the frames come in from the client side
+    while (mStarted && mQueue.empty()) {
+        LOGV("NO FRAMES! Recorder waiting for FrameAvailableCondition");
+        mFrameAvailableCondition.wait(mMutex);
+    }
+
+    // If the loop was exited as a result of stopping the recording,
+    // it is OK
+    if (!mStarted) {
+        return OK;
+    }
+
+    // Update the current buffer info
+    // TODO: mCurrentSlot can be made a bufferstate since there
+    // can be more than one "current" slots.
+    Fifo::iterator front(mQueue.begin());
+    mCurrentSlot = *front;
+    mCurrentBuf = mSlots[mCurrentSlot].mGraphicBuffer;
+    mCurrentTimestamp = mSlots[mCurrentSlot].mTimestamp;
+
+    // Pass the data to the MediaBuffer. Pass in only the metadata
+    passMetadataBufferLocked(buffer);
+
+    (*buffer)->setObserver(this);
+    (*buffer)->add_ref();
+    (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp);
+
+    return OK;
+}
+
+// Pass the data to the MediaBuffer. Pass in only the metadata
+// The metadata passed consists of two parts:
+// 1. First, there is an integer indicating that it is a GRAlloc
+// source (kMetadataBufferTypeGrallocSource)
+// 2. This is followed by the buffer_handle_t that is a handle to the
+// GRalloc buffer. The encoder needs to interpret this GRalloc handle
+// and encode the frames.
+// --------------------------------------------------------------
+// |  kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
+// --------------------------------------------------------------
+// Note: Call only when you have the lock
+void SurfaceMediaSource::passMetadataBufferLocked(MediaBuffer **buffer) {
+    LOGV("passMetadataBuffer");
+    // MediaBuffer allocates and owns this data
+    MediaBuffer *tempBuffer =
+        new MediaBuffer(4 + sizeof(buffer_handle_t));
+    char *data = (char *)tempBuffer->data();
+    if (data == NULL) {
+        LOGE("Cannot allocate memory for passing buffer metadata!");
+        return;
+    }
+    OMX_U32 type = kMetadataBufferTypeGrallocSource;
+    memcpy(data, &type, 4);
+    memcpy(data + 4, &(mCurrentBuf->handle), sizeof(buffer_handle_t));
+    *buffer = tempBuffer;
+}
+
+
+void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
+    LOGV("signalBufferReturned");
+
+    bool foundBuffer = false;
+    Mutex::Autolock autoLock(mMutex);
+
+    if (!mStarted) {
+        LOGW("signalBufferReturned: mStarted = false! Nothing to do!");
+        return;
+    }
+
+    for (Fifo::iterator it = mQueue.begin(); it != mQueue.end(); ++it) {
+        CHECK(mSlots[*it].mGraphicBuffer != NULL);
+        if (checkBufferMatchesSlot(*it, buffer)) {
+            mSlots[*it].mBufferState = BufferSlot::FREE;
+            mQueue.erase(it);
+            buffer->setObserver(0);
+            buffer->release();
+            mDequeueCondition.signal();
+            mFrameCompleteCondition.signal();
+            foundBuffer = true;
+            break;
+        }
+    }
+
+    if (!foundBuffer) {
+        CHECK_EQ(0, "signalBufferReturned: bogus buffer");
+    }
+}
+
+bool SurfaceMediaSource::checkBufferMatchesSlot(int slot, MediaBuffer *buffer) {
+    LOGV("Check if Buffer matches slot");
+    // need to convert to char* for pointer arithmetic and then
+    // copy the byte stream into our handle
+    buffer_handle_t bufferHandle ;
+    memcpy( &bufferHandle, (char *)(buffer->data()) + 4, sizeof(buffer_handle_t));
+    return mSlots[slot].mGraphicBuffer->handle  ==  bufferHandle;
+}
+
+
+} // end of namespace android
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index bf978d7..c406964 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -370,7 +370,9 @@
 
             int16_t *dst = (int16_t *)tmp->data();
             const uint8_t *src = (const uint8_t *)buffer->data();
-            while (n-- > 0) {
+            ssize_t numBytes = n;
+
+            while (numBytes-- > 0) {
                 *dst++ = ((int16_t)(*src) - 128) * 256;
                 ++src;
             }
diff --git a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
index 588a74d..07a9eb8 100644
--- a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
+++ b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
@@ -25,6 +25,8 @@
 
 #include "support.h"
 
+#include <cutils/properties.h> // for property_get
+
 namespace android {
 
 ChromiumHTTPDataSource::ChromiumHTTPDataSource(uint32_t flags)
@@ -111,7 +113,7 @@
     mState = DISCONNECTED;
     mCondition.broadcast();
 
-    mURI.clear();
+    // mURI.clear();
 
     mIOResult = err;
 
@@ -150,9 +152,19 @@
     Mutex::Autolock autoLock(mLock);
 
     if (mState != CONNECTED) {
-        return ERROR_NOT_CONNECTED;
+        return INVALID_OPERATION;
     }
 
+#if 0
+    char value[PROPERTY_VALUE_MAX];
+    if (property_get("media.stagefright.disable-net", value, 0)
+            && (!strcasecmp(value, "true") || !strcmp(value, "1"))) {
+        LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "Simulating that the network is down.");
+        disconnect_l();
+        return ERROR_IO;
+    }
+#endif
+
     if (offset != mCurrentOffset) {
         AString tmp = mURI;
         KeyedVector<String8, String8> tmpHeaders = mHeaders;
@@ -236,7 +248,7 @@
     CHECK_EQ((int)mState, (int)DISCONNECTING);
 
     mState = DISCONNECTED;
-    mURI.clear();
+    // mURI.clear();
 
     mCondition.broadcast();
 
@@ -299,5 +311,21 @@
     }
 }
 
+status_t ChromiumHTTPDataSource::reconnectAtOffset(off64_t offset) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mURI.empty()) {
+        return INVALID_OPERATION;
+    }
+
+    LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "Reconnecting...");
+    status_t err = connect_l(mURI.c_str(), &mHeaders, offset);
+    if (err != OK) {
+        LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "Reconnect failed w/ err 0x%08x", err);
+    }
+
+    return err;
+}
+
 }  // namespace android
 
diff --git a/media/libstagefright/include/ChromiumHTTPDataSource.h b/media/libstagefright/include/ChromiumHTTPDataSource.h
index d833e2e..18f8913 100644
--- a/media/libstagefright/include/ChromiumHTTPDataSource.h
+++ b/media/libstagefright/include/ChromiumHTTPDataSource.h
@@ -51,6 +51,8 @@
 
     virtual String8 getMIMEType() const;
 
+    virtual status_t reconnectAtOffset(off64_t offset);
+
 protected:
     virtual ~ChromiumHTTPDataSource();
 
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index 2d6cb84..22b2855 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -77,6 +77,10 @@
         kWhatRead       = 'read',
     };
 
+    enum {
+        kMaxNumRetries = 10,
+    };
+
     sp<DataSource> mSource;
     sp<AHandlerReflector<NuCachedSource2> > mReflector;
     sp<ALooper> mLooper;
@@ -93,6 +97,8 @@
     bool mFetching;
     int64_t mLastFetchTimeUs;
 
+    int32_t mNumRetriesLeft;
+
     void onMessageReceived(const sp<AMessage> &msg);
     void onFetch();
     void onRead(const sp<AMessage> &msg);
diff --git a/media/libstagefright/tests/Android.mk b/media/libstagefright/tests/Android.mk
new file mode 100644
index 0000000..3ea8f39
--- /dev/null
+++ b/media/libstagefright/tests/Android.mk
@@ -0,0 +1,53 @@
+# Build the unit tests.
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+ifneq ($(TARGET_SIMULATOR),true)
+
+LOCAL_MODULE := SurfaceMediaSource_test
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := \
+    SurfaceMediaSource_test.cpp \
+	DummyRecorder.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+	libEGL \
+	libGLESv2 \
+	libandroid \
+	libbinder \
+	libcutils \
+	libgui \
+	libstlport \
+	libui \
+	libutils \
+	libstagefright \
+	libstagefright_omx \
+	libstagefright_foundation \
+
+LOCAL_STATIC_LIBRARIES := \
+	libgtest \
+	libgtest_main \
+
+LOCAL_C_INCLUDES := \
+    bionic \
+    bionic/libstdc++/include \
+    external/gtest/include \
+    external/stlport/stlport \
+	frameworks/base/media/libstagefright \
+	frameworks/base/media/libstagefright/include \
+	$(TOP)/frameworks/base/include/media/stagefright/openmax \
+
+include $(BUILD_EXECUTABLE)
+
+endif
+
+# Include subdirectory makefiles
+# ============================================================
+
+# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework
+# team really wants is to build the stuff defined by this makefile.
+ifeq (,$(ONE_SHOT_MAKEFILE))
+include $(call first-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/media/libstagefright/tests/DummyRecorder.cpp b/media/libstagefright/tests/DummyRecorder.cpp
new file mode 100644
index 0000000..8d75d6b
--- /dev/null
+++ b/media/libstagefright/tests/DummyRecorder.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2011 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 "DummyRecorder"
+// #define LOG_NDEBUG 0
+
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaSource.h>
+#include "DummyRecorder.h"
+
+#include <utils/Log.h>
+
+namespace android {
+
+// static
+void *DummyRecorder::threadWrapper(void *pthis) {
+    LOGV("ThreadWrapper: %p", pthis);
+    DummyRecorder *writer = static_cast<DummyRecorder *>(pthis);
+    writer->readFromSource();
+    return NULL;
+}
+
+
+status_t DummyRecorder::start() {
+    LOGV("Start");
+    mStarted = true;
+
+    mSource->start();
+
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+    int err = pthread_create(&mThread, &attr, threadWrapper, this);
+    pthread_attr_destroy(&attr);
+
+    if (err) {
+        LOGE("Error creating thread!");
+        return -ENODEV;
+    }
+    return OK;
+}
+
+
+status_t DummyRecorder::stop() {
+    LOGV("Stop");
+    mStarted = false;
+
+    mSource->stop();
+    void *dummy;
+    pthread_join(mThread, &dummy);
+    status_t err = (status_t) dummy;
+
+    LOGV("Ending the reading thread");
+    return err;
+}
+
+// pretend to read the source buffers
+void DummyRecorder::readFromSource() {
+    LOGV("ReadFromSource");
+    if (!mStarted) {
+        return;
+    }
+
+    status_t err = OK;
+    MediaBuffer *buffer;
+    LOGV("A fake writer accessing the frames");
+    while (mStarted && (err = mSource->read(&buffer)) == OK){
+        // if not getting a valid buffer from source, then exit
+        if (buffer == NULL) {
+            return;
+        }
+        buffer->release();
+        buffer = NULL;
+    }
+}
+
+
+} // end of namespace android
diff --git a/media/libstagefright/tests/DummyRecorder.h b/media/libstagefright/tests/DummyRecorder.h
new file mode 100644
index 0000000..1cbea1b
--- /dev/null
+++ b/media/libstagefright/tests/DummyRecorder.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011 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 DUMMY_RECORDER_H_
+#define DUMMY_RECORDER_H_
+
+#include <pthread.h>
+#include <utils/String8.h>
+#include <media/stagefright/foundation/ABase.h>
+
+
+namespace android {
+
+class MediaSource;
+class MediaBuffer;
+
+class DummyRecorder {
+    public:
+    // The media source from which this will receive frames
+    sp<MediaSource> mSource;
+    bool mStarted;
+    pthread_t mThread;
+
+    status_t start();
+    status_t stop();
+
+    // actual entry point for the thread
+    void readFromSource();
+
+    // static function to wrap the actual thread entry point
+    static void *threadWrapper(void *pthis);
+
+    DummyRecorder(const sp<MediaSource> &source) : mSource(source)
+                                                    , mStarted(false) {}
+    ~DummyRecorder( ) {}
+
+    private:
+
+    DISALLOW_EVIL_CONSTRUCTORS(DummyRecorder);
+};
+
+} // end of namespace android
+#endif
+
+
diff --git a/media/libstagefright/tests/SurfaceMediaSource_test.cpp b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
new file mode 100644
index 0000000..dc6f2c9
--- /dev/null
+++ b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) 2011 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 "SurfaceMediaSource_test"
+// #define LOG_NDEBUG 0
+
+#include <gtest/gtest.h>
+#include <utils/String8.h>
+#include <utils/Errors.h>
+
+#include <media/stagefright/SurfaceMediaSource.h>
+
+#include <gui/SurfaceTextureClient.h>
+#include <ui/GraphicBuffer.h>
+#include <surfaceflinger/ISurfaceComposer.h>
+#include <surfaceflinger/Surface.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
+
+#include <binder/ProcessState.h>
+#include <ui/FramebufferNativeWindow.h>
+
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MPEG4Writer.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+#include <OMX_Component.h>
+
+#include "DummyRecorder.h"
+
+namespace android {
+
+
+class SurfaceMediaSourceTest : public ::testing::Test {
+public:
+
+    SurfaceMediaSourceTest( ): mYuvTexWidth(64), mYuvTexHeight(66) { }
+    sp<MPEG4Writer>  setUpWriter(OMXClient &client );
+    void oneBufferPass(int width, int height );
+    static void fillYV12Buffer(uint8_t* buf, int w, int h, int stride) ;
+    static void fillYV12BufferRect(uint8_t* buf, int w, int h,
+                        int stride, const android_native_rect_t& rect) ;
+protected:
+
+    virtual void SetUp() {
+        mSMS = new SurfaceMediaSource(mYuvTexWidth, mYuvTexHeight);
+        mSMS->setSynchronousMode(true);
+        mSTC = new SurfaceTextureClient(mSMS);
+        mANW = mSTC;
+
+    }
+
+
+    virtual void TearDown() {
+        mSMS.clear();
+        mSTC.clear();
+        mANW.clear();
+    }
+
+    const int mYuvTexWidth;
+    const int mYuvTexHeight;
+
+    sp<SurfaceMediaSource> mSMS;
+    sp<SurfaceTextureClient> mSTC;
+    sp<ANativeWindow> mANW;
+
+};
+
+void SurfaceMediaSourceTest::oneBufferPass(int width, int height ) {
+    LOGV("One Buffer Pass");
+    ANativeWindowBuffer* anb;
+    ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+    ASSERT_TRUE(anb != NULL);
+
+    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+    ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
+
+    // Fill the buffer with the a checkerboard pattern
+    uint8_t* img = NULL;
+    buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+    SurfaceMediaSourceTest::fillYV12Buffer(img, width, height, buf->getStride());
+    buf->unlock();
+
+    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
+}
+
+sp<MPEG4Writer> SurfaceMediaSourceTest::setUpWriter(OMXClient &client ) {
+    // Writing to a file
+    const char *fileName = "/sdcard/outputSurfEnc.mp4";
+    sp<MetaData> enc_meta = new MetaData;
+    enc_meta->setInt32(kKeyBitRate, 300000);
+    enc_meta->setInt32(kKeyFrameRate, 30);
+
+    enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+
+    sp<MetaData> meta = mSMS->getFormat();
+
+    int32_t width, height, stride, sliceHeight, colorFormat;
+    CHECK(meta->findInt32(kKeyWidth, &width));
+    CHECK(meta->findInt32(kKeyHeight, &height));
+    CHECK(meta->findInt32(kKeyStride, &stride));
+    CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight));
+    CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
+
+    enc_meta->setInt32(kKeyWidth, width);
+    enc_meta->setInt32(kKeyHeight, height);
+    enc_meta->setInt32(kKeyIFramesInterval, 1);
+    enc_meta->setInt32(kKeyStride, stride);
+    enc_meta->setInt32(kKeySliceHeight, sliceHeight);
+    // TODO: overwriting the colorformat since the format set by GRAlloc
+    // could be wrong or not be read by OMX
+    enc_meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
+
+
+    sp<MediaSource> encoder =
+        OMXCodec::Create(
+                client.interface(), enc_meta, true /* createEncoder */, mSMS);
+
+    sp<MPEG4Writer> writer = new MPEG4Writer(fileName);
+    writer->addSource(encoder);
+
+    return writer;
+}
+
+// Fill a YV12 buffer with a multi-colored checkerboard pattern
+void SurfaceMediaSourceTest::fillYV12Buffer(uint8_t* buf, int w, int h, int stride) {
+    const int blockWidth = w > 16 ? w / 16 : 1;
+    const int blockHeight = h > 16 ? h / 16 : 1;
+    const int yuvTexOffsetY = 0;
+    int yuvTexStrideY = stride;
+    int yuvTexOffsetV = yuvTexStrideY * h;
+    int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
+    int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2;
+    int yuvTexStrideU = yuvTexStrideV;
+    for (int x = 0; x < w; x++) {
+        for (int y = 0; y < h; y++) {
+            int parityX = (x / blockWidth) & 1;
+            int parityY = (y / blockHeight) & 1;
+            unsigned char intensity = (parityX ^ parityY) ? 63 : 191;
+            buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity;
+            if (x < w / 2 && y < h / 2) {
+                buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = intensity;
+                if (x * 2 < w / 2 && y * 2 < h / 2) {
+                    buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 0] =
+                    buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 1] =
+                    buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 0] =
+                    buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 1] =
+                        intensity;
+                }
+            }
+        }
+    }
+}
+
+// Fill a YV12 buffer with red outside a given rectangle and green inside it.
+void SurfaceMediaSourceTest::fillYV12BufferRect(uint8_t* buf, int w,
+                  int h, int stride, const android_native_rect_t& rect) {
+    const int yuvTexOffsetY = 0;
+    int yuvTexStrideY = stride;
+    int yuvTexOffsetV = yuvTexStrideY * h;
+    int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
+    int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2;
+    int yuvTexStrideU = yuvTexStrideV;
+    for (int x = 0; x < w; x++) {
+        for (int y = 0; y < h; y++) {
+            bool inside = rect.left <= x && x < rect.right &&
+                    rect.top <= y && y < rect.bottom;
+            buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = inside ? 240 : 64;
+            if (x < w / 2 && y < h / 2) {
+                bool inside = rect.left <= 2*x && 2*x < rect.right &&
+                        rect.top <= 2*y && 2*y < rect.bottom;
+                buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = 16;
+                buf[yuvTexOffsetV + (y * yuvTexStrideV) + x] =
+                                                inside ? 16 : 255;
+            }
+        }
+    }
+}  ///////// End of class SurfaceMediaSourceTest
+
+///////////////////////////////////////////////////////////////////
+// Class to imitate the recording     /////////////////////////////
+// ////////////////////////////////////////////////////////////////
+struct SimpleDummyRecorder {
+        sp<MediaSource> mSource;
+
+        SimpleDummyRecorder
+                (const sp<MediaSource> &source): mSource(source) {}
+
+        status_t start() { return mSource->start();}
+        status_t stop()  { return mSource->stop();}
+
+        // fakes reading from a media source
+        status_t readFromSource() {
+            MediaBuffer *buffer;
+            status_t err = mSource->read(&buffer);
+            if (err != OK) {
+                return err;
+            }
+            buffer->release();
+            buffer = NULL;
+            return OK;
+        }
+};
+
+///////////////////////////////////////////////////////////////////
+//           TESTS
+// Just pass one buffer from the native_window to the SurfaceMediaSource
+TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotOneBufferPass) {
+    LOGV("Testing OneBufferPass ******************************");
+
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+            0, 0, HAL_PIXEL_FORMAT_YV12));
+    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+    oneBufferPass(mYuvTexWidth, mYuvTexHeight);
+}
+
+// Pass the buffer with the wrong height and weight and should not be accepted
+TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotWrongSizeBufferPass) {
+    LOGV("Testing Wrong size BufferPass ******************************");
+
+    // setting the client side buffer size different than the server size
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+             10, 10, HAL_PIXEL_FORMAT_YV12));
+    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+    ANativeWindowBuffer* anb;
+
+    // make sure we get an error back when dequeuing!
+    ASSERT_NE(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+}
+
+
+// pass multiple buffers from the native_window the SurfaceMediaSource
+// A dummy writer is used to simulate actual MPEG4Writer
+TEST_F(SurfaceMediaSourceTest,  EncodingFromCpuFilledYV12BufferNpotMultiBufferPass) {
+    LOGV("Testing MultiBufferPass, Dummy Recorder *********************");
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+            0, 0, HAL_PIXEL_FORMAT_YV12));
+    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+    SimpleDummyRecorder writer(mSMS);
+    writer.start();
+
+    int32_t nFramesCount = 0;
+    while (nFramesCount < 300) {
+        oneBufferPass(mYuvTexWidth, mYuvTexHeight);
+
+        ASSERT_EQ(NO_ERROR, writer.readFromSource());
+
+        nFramesCount++;
+    }
+    writer.stop();
+}
+
+// Delayed pass of multiple buffers from the native_window the SurfaceMediaSource
+// A dummy writer is used to simulate actual MPEG4Writer
+TEST_F(SurfaceMediaSourceTest,  EncodingFromCpuFilledYV12BufferNpotMultiBufferPassLag) {
+    LOGV("Testing MultiBufferPass, Dummy Recorder Lagging **************");
+
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+            0, 0, HAL_PIXEL_FORMAT_YV12));
+    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+    SimpleDummyRecorder writer(mSMS);
+    writer.start();
+
+    int32_t nFramesCount = 1;
+    const int FRAMES_LAG = mSMS->getBufferCount() - 1;
+    while (nFramesCount <= 300) {
+        oneBufferPass(mYuvTexWidth, mYuvTexHeight);
+        // Forcing the writer to lag behind a few frames
+        if (nFramesCount > FRAMES_LAG) {
+            ASSERT_EQ(NO_ERROR, writer.readFromSource());
+        }
+        nFramesCount++;
+    }
+    writer.stop();
+}
+
+// pass multiple buffers from the native_window the SurfaceMediaSource
+// A dummy writer (MULTITHREADED) is used to simulate actual MPEG4Writer
+TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotMultiBufferPassThreaded) {
+    LOGV("Testing MultiBufferPass, Dummy Recorder Multi-Threaded **********");
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+            0, 0, HAL_PIXEL_FORMAT_YV12));
+    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+    DummyRecorder writer(mSMS);
+    writer.start();
+
+    int32_t nFramesCount = 0;
+    while (nFramesCount <= 300) {
+        oneBufferPass(mYuvTexWidth, mYuvTexHeight);
+
+        nFramesCount++;
+    }
+    writer.stop();
+}
+
+// Test to examine the actual encoding. Temporarily disabled till the
+// colorformat and encoding from GRAlloc data is resolved
+TEST_F(SurfaceMediaSourceTest, DISABLED_EncodingFromCpuFilledYV12BufferNpotWrite) {
+    LOGV("Testing the whole pipeline with actual Recorder");
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+            0, 0, HAL_PIXEL_FORMAT_YV12));
+    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+    OMXClient client;
+    CHECK_EQ(OK, client.connect());
+
+    sp<MPEG4Writer> writer = setUpWriter(client);
+    int64_t start = systemTime();
+    CHECK_EQ(OK, writer->start());
+
+    int32_t nFramesCount = 0;
+    while (nFramesCount <= 300) {
+        oneBufferPass(mYuvTexWidth, mYuvTexHeight);
+        nFramesCount++;
+    }
+
+    CHECK_EQ(OK, writer->stop());
+    writer.clear();
+    int64_t end = systemTime();
+    client.disconnect();
+}
+
+
+} // namespace android
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 86d4cc3..cb1f921 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -81,6 +81,8 @@
 
 static const nsecs_t kWarningThrottle = seconds(5);
 
+// RecordThread loop sleep time upon application overrun or audio HAL read error
+static const int kRecordThreadSleepUs = 5000;
 
 // ----------------------------------------------------------------------------
 
@@ -417,7 +419,7 @@
             lSessionId = *sessionId;
         } else {
             // if no audio session id is provided, create one here
-            lSessionId = nextUniqueId_l();
+            lSessionId = nextUniqueId();
             if (sessionId != NULL) {
                 *sessionId = lSessionId;
             }
@@ -725,6 +727,15 @@
         thread = checkPlaybackThread_l(ioHandle);
         if (thread == NULL) {
             thread = checkRecordThread_l(ioHandle);
+        } else if (thread.get() == primaryPlaybackThread_l()) {
+            // indicate output device change to all input threads for pre processing
+            AudioParameter param = AudioParameter(keyValuePairs);
+            int value;
+            if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
+                for (size_t i = 0; i < mRecordThreads.size(); i++) {
+                    mRecordThreads.valueAt(i)->setParameters(keyValuePairs);
+                }
+            }
         }
     }
     if (thread != NULL) {
@@ -873,10 +884,10 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id)
+AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id, uint32_t device)
     :   Thread(false),
         mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
-        mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false)
+        mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false), mDevice(device)
 {
 }
 
@@ -1032,14 +1043,34 @@
     return NO_ERROR;
 }
 
+status_t AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
+    write(fd, buffer, strlen(buffer));
+
+    for (size_t i = 0; i < mEffectChains.size(); ++i) {
+        sp<EffectChain> chain = mEffectChains[i];
+        if (chain != 0) {
+            chain->dump(fd, args);
+        }
+    }
+    return NO_ERROR;
+}
+
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
-    :   ThreadBase(audioFlinger, id),
+AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
+                                             AudioStreamOut* output,
+                                             int id,
+                                             uint32_t device)
+    :   ThreadBase(audioFlinger, id, device),
         mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
-        mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
-        mDevice(device)
+        mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
 {
     readOutputParameters();
 
@@ -1099,24 +1130,6 @@
     return NO_ERROR;
 }
 
-status_t AudioFlinger::PlaybackThread::dumpEffectChains(int fd, const Vector<String16>& args)
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
-    write(fd, buffer, strlen(buffer));
-
-    for (size_t i = 0; i < mEffectChains.size(); ++i) {
-        sp<EffectChain> chain = mEffectChains[i];
-        if (chain != 0) {
-            chain->dump(fd, args);
-        }
-    }
-    return NO_ERROR;
-}
-
 status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
 {
     const size_t SIZE = 256;
@@ -1199,9 +1212,9 @@
         }
     }
 
-    if (mOutput == 0) {
+    lStatus = initCheck();
+    if (lStatus != NO_ERROR) {
         LOGE("Audio driver not initialized.");
-        lStatus = NO_INIT;
         goto Exit;
     }
 
@@ -1423,7 +1436,7 @@
     if (halFrames == 0 || dspFrames == 0) {
         return BAD_VALUE;
     }
-    if (mOutput == 0) {
+    if (initCheck() != NO_ERROR) {
         return INVALID_OPERATION;
     }
     *halFrames = mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
@@ -1468,34 +1481,6 @@
     return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
 }
 
-sp<AudioFlinger::EffectChain> AudioFlinger::PlaybackThread::getEffectChain(int sessionId)
-{
-    Mutex::Autolock _l(mLock);
-    return getEffectChain_l(sessionId);
-}
-
-sp<AudioFlinger::EffectChain> AudioFlinger::PlaybackThread::getEffectChain_l(int sessionId)
-{
-    sp<EffectChain> chain;
-
-    size_t size = mEffectChains.size();
-    for (size_t i = 0; i < size; i++) {
-        if (mEffectChains[i]->sessionId() == sessionId) {
-            chain = mEffectChains[i];
-            break;
-        }
-    }
-    return chain;
-}
-
-void AudioFlinger::PlaybackThread::setMode(uint32_t mode)
-{
-    Mutex::Autolock _l(mLock);
-    size_t size = mEffectChains.size();
-    for (size_t i = 0; i < size; i++) {
-        mEffectChains[i]->setMode_l(mode);
-    }
-}
 
 // ----------------------------------------------------------------------------
 
@@ -1503,7 +1488,7 @@
     :   PlaybackThread(audioFlinger, output, id, device),
         mAudioMixer(0)
 {
-    mType = PlaybackThread::MIXER;
+    mType = ThreadBase::MIXER;
     mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
 
     // FIXME - Current mixer implementation only supports stereo output
@@ -2072,7 +2057,7 @@
 AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
     :   PlaybackThread(audioFlinger, output, id, device)
 {
-    mType = PlaybackThread::DIRECT;
+    mType = ThreadBase::DIRECT;
 }
 
 AudioFlinger::DirectOutputThread::~DirectOutputThread()
@@ -2551,7 +2536,7 @@
 AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id)
     :   MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->device()), mWaitTimeMs(UINT_MAX)
 {
-    mType = PlaybackThread::DUPLICATING;
+    mType = ThreadBase::DUPLICATING;
     addOutputTrack(mainThread);
 }
 
@@ -2970,7 +2955,7 @@
         mStreamType = streamType;
         // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
         // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
-        mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * audio_bytes_per_sample(format) : sizeof(uint8_t);
+        mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * sizeof(int16_t) : sizeof(uint8_t);
     }
 }
 
@@ -3751,21 +3736,26 @@
         if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
             lSessionId = *sessionId;
         } else {
-            lSessionId = nextUniqueId_l();
+            lSessionId = nextUniqueId();
             if (sessionId != NULL) {
                 *sessionId = lSessionId;
             }
         }
         // create new record track. The record track uses one track in mHardwareMixerThread by convention.
-        recordTrack = new RecordThread::RecordTrack(thread, client, sampleRate,
-                                                   format, channelMask, frameCount, flags, lSessionId);
+        recordTrack = thread->createRecordTrack_l(client,
+                                                sampleRate,
+                                                format,
+                                                channelMask,
+                                                frameCount,
+                                                flags,
+                                                lSessionId,
+                                                &lStatus);
     }
-    if (recordTrack->getCblk() == NULL) {
+    if (lStatus != NO_ERROR) {
         // remove local strong reference to Client before deleting the RecordTrack so that the Client
         // destructor is called by the TrackBase destructor with mLock held
         client.clear();
         recordTrack.clear();
-        lStatus = NO_MEMORY;
         goto Exit;
     }
 
@@ -3814,10 +3804,16 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, int id) :
-    ThreadBase(audioFlinger, id),
-    mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
+AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
+                                         AudioStreamIn *input,
+                                         uint32_t sampleRate,
+                                         uint32_t channels,
+                                         int id,
+                                         uint32_t device) :
+    ThreadBase(audioFlinger, id, device),
+    mInput(input), mTrack(NULL), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
 {
+    mType = ThreadBase::RECORD;
     mReqChannelCount = popcount(channels);
     mReqSampleRate = sampleRate;
     readInputParameters();
@@ -3847,6 +3843,7 @@
 {
     AudioBufferProvider::Buffer buffer;
     sp<RecordTrack> activeTrack;
+    Vector< sp<EffectChain> > effectChains;
 
     nsecs_t lastWarning = 0;
 
@@ -3897,14 +3894,22 @@
                     mStandby = false;
                 }
             }
+            lockEffectChains_l(effectChains);
         }
 
         if (mActiveTrack != 0) {
             if (mActiveTrack->mState != TrackBase::ACTIVE &&
                 mActiveTrack->mState != TrackBase::RESUMING) {
-                usleep(5000);
+                unlockEffectChains(effectChains);
+                usleep(kRecordThreadSleepUs);
                 continue;
             }
+            for (size_t i = 0; i < effectChains.size(); i ++) {
+                effectChains[i]->process_l();
+            }
+            // enable changes in effect chain
+            unlockEffectChains(effectChains);
+
             buffer.frameCount = mFrameCount;
             if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
                 size_t framesOut = buffer.frameCount;
@@ -3953,7 +3958,7 @@
                                     // Force input into standby so that it tries to
                                     // recover at next read attempt
                                     mInput->stream->common.standby(&mInput->stream->common);
-                                    usleep(5000);
+                                    usleep(kRecordThreadSleepUs);
                                 }
                                 mRsmpInIndex = mFrameCount;
                                 framesOut = 0;
@@ -4001,9 +4006,12 @@
                 // Release the processor for a while before asking for a new buffer.
                 // This will give the application more chance to read from the buffer and
                 // clear the overflow.
-                usleep(5000);
+                usleep(kRecordThreadSleepUs);
             }
+        } else {
+            unlockEffectChains(effectChains);
         }
+        effectChains.clear();
     }
 
     if (!mStandby) {
@@ -4017,6 +4025,49 @@
     return false;
 }
 
+
+sp<AudioFlinger::RecordThread::RecordTrack>  AudioFlinger::RecordThread::createRecordTrack_l(
+        const sp<AudioFlinger::Client>& client,
+        uint32_t sampleRate,
+        int format,
+        int channelMask,
+        int frameCount,
+        uint32_t flags,
+        int sessionId,
+        status_t *status)
+{
+    sp<RecordTrack> track;
+    status_t lStatus;
+
+    lStatus = initCheck();
+    if (lStatus != NO_ERROR) {
+        LOGE("Audio driver not initialized.");
+        goto Exit;
+    }
+
+    { // scope for mLock
+        Mutex::Autolock _l(mLock);
+
+        track = new RecordTrack(this, client, sampleRate,
+                      format, channelMask, frameCount, flags, sessionId);
+
+        if (track->getCblk() == NULL) {
+            lStatus = NO_MEMORY;
+            goto Exit;
+        }
+
+        mTrack = track.get();
+
+    }
+    lStatus = NO_ERROR;
+
+Exit:
+    if (status) {
+        *status = lStatus;
+    }
+    return track;
+}
+
 status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
 {
     LOGV("RecordThread::start");
@@ -4128,6 +4179,7 @@
     write(fd, result.string(), result.size());
 
     dumpBase(fd, args);
+    dumpEffectChains(fd, args);
 
     return NO_ERROR;
 }
@@ -4146,7 +4198,7 @@
                 // Force input into standby so that it tries to
                 // recover at next read attempt
                 mInput->stream->common.standby(&mInput->stream->common);
-                usleep(5000);
+                usleep(kRecordThreadSleepUs);
             }
             buffer->raw = 0;
             buffer->frameCount = 0;
@@ -4211,6 +4263,23 @@
                 reconfig = true;
             }
         }
+        if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
+            // forward device change to effects that have requested to be
+            // aware of attached audio device.
+            for (size_t i = 0; i < mEffectChains.size(); i++) {
+                mEffectChains[i]->setDevice_l(value);
+            }
+            // store input device and output device but do not forward output device to audio HAL.
+            // Note that status is ignored by the caller for output device
+            // (see AudioFlinger::setParameters()
+            if (value & AUDIO_DEVICE_OUT_ALL) {
+                mDevice &= (uint32_t)~(value & AUDIO_DEVICE_OUT_ALL);
+                status = BAD_VALUE;
+            } else {
+                mDevice &= (uint32_t)~(value & AUDIO_DEVICE_IN_ALL);
+            }
+            mDevice |= (uint32_t)value;
+        }
         if (status == NO_ERROR) {
             status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
             if (status == INVALID_OPERATION) {
@@ -4320,6 +4389,21 @@
     return mInput->stream->get_input_frames_lost(mInput->stream);
 }
 
+uint32_t AudioFlinger::RecordThread::hasAudioSession(int sessionId)
+{
+    Mutex::Autolock _l(mLock);
+    uint32_t result = 0;
+    if (getEffectChain_l(sessionId) != 0) {
+        result = EFFECT_SESSION;
+    }
+
+    if (mTrack != NULL && sessionId == mTrack->sessionId()) {
+        result |= TRACK_SESSION;
+    }
+
+    return result;
+}
+
 // ----------------------------------------------------------------------------
 
 int AudioFlinger::openOutput(uint32_t *pDevices,
@@ -4368,7 +4452,7 @@
     mHardwareStatus = AUDIO_HW_IDLE;
     if (outStream != NULL) {
         AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream);
-        int id = nextUniqueId_l();
+        int id = nextUniqueId();
 
         if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) ||
             (format != AUDIO_FORMAT_PCM_16_BIT) ||
@@ -4405,7 +4489,7 @@
         return 0;
     }
 
-    int id = nextUniqueId_l();
+    int id = nextUniqueId();
     DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);
     thread->addOutputTrack(thread2);
     mPlaybackThreads.add(id, thread);
@@ -4428,9 +4512,9 @@
 
         LOGV("closeOutput() %d", output);
 
-        if (thread->type() == PlaybackThread::MIXER) {
+        if (thread->type() == ThreadBase::MIXER) {
             for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
-                if (mPlaybackThreads.valueAt(i)->type() == PlaybackThread::DUPLICATING) {
+                if (mPlaybackThreads.valueAt(i)->type() == ThreadBase::DUPLICATING) {
                     DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
                     dupThread->removeOutputTrack((MixerThread *)thread.get());
                 }
@@ -4442,7 +4526,7 @@
     }
     thread->exit();
 
-    if (thread->type() != PlaybackThread::DUPLICATING) {
+    if (thread->type() != ThreadBase::DUPLICATING) {
         AudioStreamOut *out = thread->getOutput();
         out->hwDev->close_output_stream(out->hwDev, out->stream);
         delete out;
@@ -4537,9 +4621,17 @@
     if (inStream != NULL) {
         AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);
 
-        int id = nextUniqueId_l();
-         // Start record thread
-        thread = new RecordThread(this, input, reqSamplingRate, reqChannels, id);
+        int id = nextUniqueId();
+        // Start record thread
+        // RecorThread require both input and output device indication to forward to audio
+        // pre processing modules
+        uint32_t device = (*pDevices) | primaryOutputDevice_l();
+        thread = new RecordThread(this,
+                                  input,
+                                  reqSamplingRate,
+                                  reqChannels,
+                                  id,
+                                  device);
         mRecordThreads.add(id, thread);
         LOGV("openInput() created record thread: ID %d thread %p", id, thread);
         if (pSamplingRate) *pSamplingRate = reqSamplingRate;
@@ -4597,7 +4689,7 @@
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
         PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
         if (thread != dstThread &&
-            thread->type() != PlaybackThread::DIRECT) {
+            thread->type() != ThreadBase::DIRECT) {
             MixerThread *srcThread = (MixerThread *)thread;
             srcThread->invalidateTracks(stream);
         }
@@ -4609,8 +4701,7 @@
 
 int AudioFlinger::newAudioSessionId()
 {
-    AutoMutex _l(mLock);
-    return nextUniqueId_l();
+    return nextUniqueId();
 }
 
 // checkPlaybackThread_l() must be called with AudioFlinger::mLock held
@@ -4628,7 +4719,7 @@
 {
     PlaybackThread *thread = checkPlaybackThread_l(output);
     if (thread != NULL) {
-        if (thread->type() == PlaybackThread::DIRECT) {
+        if (thread->type() == ThreadBase::DIRECT) {
             thread = NULL;
         }
     }
@@ -4645,12 +4736,34 @@
     return thread;
 }
 
-// nextUniqueId_l() must be called with AudioFlinger::mLock held
-int AudioFlinger::nextUniqueId_l()
+uint32_t AudioFlinger::nextUniqueId()
 {
-    return mNextUniqueId++;
+    return android_atomic_inc(&mNextUniqueId);
 }
 
+AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l()
+{
+    for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+        PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
+        if (thread->getOutput()->hwDev == mPrimaryHardwareDev) {
+            return thread;
+        }
+    }
+    return NULL;
+}
+
+uint32_t AudioFlinger::primaryOutputDevice_l()
+{
+    PlaybackThread *thread = primaryPlaybackThread_l();
+
+    if (thread == NULL) {
+        return 0;
+    }
+
+    return thread->device();
+}
+
+
 // ----------------------------------------------------------------------------
 //  Effect management
 // ----------------------------------------------------------------------------
@@ -4683,7 +4796,7 @@
         effect_descriptor_t *pDesc,
         const sp<IEffectClient>& effectClient,
         int32_t priority,
-        int output,
+        int io,
         int sessionId,
         status_t *status,
         int *id,
@@ -4695,8 +4808,8 @@
     sp<Client> client;
     wp<Client> wclient;
 
-    LOGV("createEffect pid %d, client %p, priority %d, sessionId %d, output %d",
-            pid, effectClient.get(), priority, sessionId, output);
+    LOGV("createEffect pid %d, client %p, priority %d, sessionId %d, io %d",
+            pid, effectClient.get(), priority, sessionId, io);
 
     if (pDesc == NULL) {
         lStatus = BAD_VALUE;
@@ -4724,7 +4837,7 @@
         goto Exit;
     }
 
-    if (output == 0) {
+    if (io == 0) {
         if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
             // output must be specified by AudioPolicyManager when using session
             // AUDIO_SESSION_OUTPUT_STAGE
@@ -4732,9 +4845,9 @@
             goto Exit;
         } else if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
             // if the output returned by getOutputForEffect() is removed before we lock the
-            // mutex below, the call to checkPlaybackThread_l(output) below will detect it
+            // mutex below, the call to checkPlaybackThread_l(io) below will detect it
             // and we will exit safely
-            output = AudioSystem::getOutputForEffect(&desc);
+            io = AudioSystem::getOutputForEffect(&desc);
         }
     }
 
@@ -4811,30 +4924,40 @@
         // output threads.
         // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
         // because of code checking output when entering the function.
-        if (output == 0) {
+        // Note: io is never 0 when creating an effect on an input
+        if (io == 0) {
              // look for the thread where the specified audio session is present
             for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
                 if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
-                    output = mPlaybackThreads.keyAt(i);
+                    io = mPlaybackThreads.keyAt(i);
                     break;
                 }
             }
+            if (io == 0) {
+               for (size_t i = 0; i < mRecordThreads.size(); i++) {
+                   if (mRecordThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
+                       io = mRecordThreads.keyAt(i);
+                       break;
+                   }
+               }
+            }
             // If no output thread contains the requested session ID, default to
             // first output. The effect chain will be moved to the correct output
             // thread when a track with the same session ID is created
-            if (output == 0 && mPlaybackThreads.size()) {
-                output = mPlaybackThreads.keyAt(0);
+            if (io == 0 && mPlaybackThreads.size()) {
+                io = mPlaybackThreads.keyAt(0);
+            }
+            LOGV("createEffect() got io %d for effect %s", io, desc.name);
+        }
+        ThreadBase *thread = checkRecordThread_l(io);
+        if (thread == NULL) {
+            thread = checkPlaybackThread_l(io);
+            if (thread == NULL) {
+                LOGE("createEffect() unknown output thread");
+                lStatus = BAD_VALUE;
+                goto Exit;
             }
         }
-        LOGV("createEffect() got output %d for effect %s", output, desc.name);
-        PlaybackThread *thread = checkPlaybackThread_l(output);
-        if (thread == NULL) {
-            LOGE("createEffect() unknown output thread");
-            lStatus = BAD_VALUE;
-            goto Exit;
-        }
-
-        // TODO: allow attachment of effect to inputs
 
         wclient = mClients.valueFor(pid);
 
@@ -4943,8 +5066,9 @@
     return NO_ERROR;
 }
 
+
 // PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l(
+sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
         const sp<AudioFlinger::Client>& client,
         const sp<IEffectClient>& effectClient,
         int32_t priority,
@@ -4957,24 +5081,14 @@
     sp<EffectModule> effect;
     sp<EffectHandle> handle;
     status_t lStatus;
-    sp<Track> track;
     sp<EffectChain> chain;
     bool chainCreated = false;
     bool effectCreated = false;
     bool effectRegistered = false;
 
-    if (mOutput == 0) {
+    lStatus = initCheck();
+    if (lStatus != NO_ERROR) {
         LOGW("createEffect_l() Audio driver not initialized.");
-        lStatus = NO_INIT;
-        goto Exit;
-    }
-
-    // Do not allow auxiliary effect on session other than 0
-    if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY &&
-        sessionId != AUDIO_SESSION_OUTPUT_MIX) {
-        LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
-                desc->name, sessionId);
-        lStatus = BAD_VALUE;
         goto Exit;
     }
 
@@ -4986,6 +5100,16 @@
         lStatus = BAD_VALUE;
         goto Exit;
     }
+    // Only Pre processor effects are allowed on input threads and only on input threads
+    if ((mType == RECORD &&
+            (desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) ||
+            (mType != RECORD &&
+                    (desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC)) {
+        LOGW("createEffect_l() effect %s (flags %08x) created on wrong thread type %d",
+                desc->name, desc->flags, mType);
+        lStatus = BAD_VALUE;
+        goto Exit;
+    }
 
     LOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);
 
@@ -5008,7 +5132,7 @@
         LOGV("createEffect_l() got effect %p on chain %p", effect == 0 ? 0 : effect.get(), chain.get());
 
         if (effect == 0) {
-            int id = mAudioFlinger->nextUniqueId_l();
+            int id = mAudioFlinger->nextUniqueId();
             // Check CPU and memory usage
             lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id);
             if (lStatus != NO_ERROR) {
@@ -5059,9 +5183,20 @@
     return handle;
 }
 
+sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect_l(int sessionId, int effectId)
+{
+    sp<EffectModule> effect;
+
+    sp<EffectChain> chain = getEffectChain_l(sessionId);
+    if (chain != 0) {
+        effect = chain->getEffectFromId_l(effectId);
+    }
+    return effect;
+}
+
 // PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
 // PlaybackThread::mLock held
-status_t AudioFlinger::PlaybackThread::addEffect_l(const sp<EffectModule>& effect)
+status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect)
 {
     // check for existing effect chain with the requested audio session
     int sessionId = effect->sessionId();
@@ -5097,7 +5232,7 @@
     return NO_ERROR;
 }
 
-void AudioFlinger::PlaybackThread::removeEffect_l(const sp<EffectModule>& effect) {
+void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect) {
 
     LOGV("removeEffect_l() %p effect %p", this, effect.get());
     effect_descriptor_t desc = effect->desc();
@@ -5116,7 +5251,53 @@
     }
 }
 
-void AudioFlinger::PlaybackThread::disconnectEffect(const sp<EffectModule>& effect,
+void AudioFlinger::ThreadBase::lockEffectChains_l(
+        Vector<sp <AudioFlinger::EffectChain> >& effectChains)
+{
+    effectChains = mEffectChains;
+    for (size_t i = 0; i < mEffectChains.size(); i++) {
+        mEffectChains[i]->lock();
+    }
+}
+
+void AudioFlinger::ThreadBase::unlockEffectChains(
+        Vector<sp <AudioFlinger::EffectChain> >& effectChains)
+{
+    for (size_t i = 0; i < effectChains.size(); i++) {
+        effectChains[i]->unlock();
+    }
+}
+
+sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain(int sessionId)
+{
+    Mutex::Autolock _l(mLock);
+    return getEffectChain_l(sessionId);
+}
+
+sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain_l(int sessionId)
+{
+    sp<EffectChain> chain;
+
+    size_t size = mEffectChains.size();
+    for (size_t i = 0; i < size; i++) {
+        if (mEffectChains[i]->sessionId() == sessionId) {
+            chain = mEffectChains[i];
+            break;
+        }
+    }
+    return chain;
+}
+
+void AudioFlinger::ThreadBase::setMode(uint32_t mode)
+{
+    Mutex::Autolock _l(mLock);
+    size_t size = mEffectChains.size();
+    for (size_t i = 0; i < size; i++) {
+        mEffectChains[i]->setMode_l(mode);
+    }
+}
+
+void AudioFlinger::ThreadBase::disconnectEffect(const sp<EffectModule>& effect,
                                                     const wp<EffectHandle>& handle) {
     Mutex::Autolock _l(mLock);
     LOGV("disconnectEffect() %p effect %p", this, effect.get());
@@ -5222,35 +5403,6 @@
     return mEffectChains.size();
 }
 
-void AudioFlinger::PlaybackThread::lockEffectChains_l(
-        Vector<sp <AudioFlinger::EffectChain> >& effectChains)
-{
-    effectChains = mEffectChains;
-    for (size_t i = 0; i < mEffectChains.size(); i++) {
-        mEffectChains[i]->lock();
-    }
-}
-
-void AudioFlinger::PlaybackThread::unlockEffectChains(
-        Vector<sp <AudioFlinger::EffectChain> >& effectChains)
-{
-    for (size_t i = 0; i < effectChains.size(); i++) {
-        effectChains[i]->unlock();
-    }
-}
-
-
-sp<AudioFlinger::EffectModule> AudioFlinger::PlaybackThread::getEffect_l(int sessionId, int effectId)
-{
-    sp<EffectModule> effect;
-
-    sp<EffectChain> chain = getEffectChain_l(sessionId);
-    if (chain != 0) {
-        effect = chain->getEffectFromId_l(effectId);
-    }
-    return effect;
-}
-
 status_t AudioFlinger::PlaybackThread::attachAuxEffect(
         const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
 {
@@ -5291,6 +5443,34 @@
     }
 }
 
+status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain)
+{
+    // only one chain per input thread
+    if (mEffectChains.size() != 0) {
+        return INVALID_OPERATION;
+    }
+    LOGV("addEffectChain_l() %p on thread %p", chain.get(), this);
+
+    chain->setInBuffer(NULL);
+    chain->setOutBuffer(NULL);
+
+    mEffectChains.add(chain);
+
+    return NO_ERROR;
+}
+
+size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<EffectChain>& chain)
+{
+    LOGV("removeEffectChain_l() %p from thread %p", chain.get(), this);
+    LOGW_IF(mEffectChains.size() != 1,
+            "removeEffectChain_l() %p invalid chain size %d on thread %p",
+            chain.get(), mEffectChains.size(), this);
+    if (mEffectChains.size() == 1) {
+        mEffectChains.removeAt(0);
+    }
+    return 0;
+}
+
 // ----------------------------------------------------------------------------
 //  EffectModule implementation
 // ----------------------------------------------------------------------------
@@ -5312,12 +5492,11 @@
     if (thread == 0) {
         return;
     }
-    PlaybackThread *p = (PlaybackThread *)thread.get();
 
     memcpy(&mDescriptor, desc, sizeof(effect_descriptor_t));
 
     // create effect engine from effect factory
-    mStatus = EffectCreate(&desc->uuid, sessionId, p->id(), &mEffectInterface);
+    mStatus = EffectCreate(&desc->uuid, sessionId, thread->id(), &mEffectInterface);
 
     if (mStatus != NO_ERROR) {
         return;
@@ -5340,6 +5519,13 @@
 {
     LOGV("Destructor %p", this);
     if (mEffectInterface != NULL) {
+        if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
+                (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
+            sp<ThreadBase> thread = mThread.promote();
+            if (thread != 0) {
+                thread->stream()->remove_audio_effect(thread->stream(), mEffectInterface);
+            }
+        }
         // release effect engine
         EffectRelease(mEffectInterface);
     }
@@ -5415,8 +5601,7 @@
     {
         sp<ThreadBase> thread = mThread.promote();
         if (thread != 0) {
-            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
-            playbackThread->disconnectEffect(keep, handle);
+            thread->disconnectEffect(keep, handle);
         }
     }
 }
@@ -5626,6 +5811,14 @@
     if (status == 0) {
         status = cmdStatus;
     }
+    if (status == 0 &&
+            ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
+             (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
+        sp<ThreadBase> thread = mThread.promote();
+        if (thread != 0) {
+            thread->stream()->add_audio_effect(thread->stream(), mEffectInterface);
+        }
+    }
     return status;
 }
 
@@ -5645,6 +5838,14 @@
     if (status == 0) {
         status = cmdStatus;
     }
+    if (status == 0 &&
+            ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
+             (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
+        sp<ThreadBase> thread = mThread.promote();
+        if (thread != 0) {
+            thread->stream()->remove_audio_effect(thread->stream(), mEffectInterface);
+        }
+    }
     return status;
 }
 
@@ -5784,17 +5985,41 @@
 {
     Mutex::Autolock _l(mLock);
     status_t status = NO_ERROR;
-    if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
-        status_t cmdStatus;
-        uint32_t size = sizeof(status_t);
-        status = (*mEffectInterface)->command(mEffectInterface,
-                                              EFFECT_CMD_SET_DEVICE,
-                                              sizeof(uint32_t),
-                                              &device,
-                                              &size,
-                                              &cmdStatus);
-        if (status == NO_ERROR) {
-            status = cmdStatus;
+    if (device && (mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
+        // audio pre processing modules on RecordThread can receive both output and
+        // input device indication in the same call
+        uint32_t dev = device & AUDIO_DEVICE_OUT_ALL;
+        if (dev) {
+            status_t cmdStatus;
+            uint32_t size = sizeof(status_t);
+
+            status = (*mEffectInterface)->command(mEffectInterface,
+                                                  EFFECT_CMD_SET_DEVICE,
+                                                  sizeof(uint32_t),
+                                                  &dev,
+                                                  &size,
+                                                  &cmdStatus);
+            if (status == NO_ERROR) {
+                status = cmdStatus;
+            }
+        }
+        dev = device & AUDIO_DEVICE_IN_ALL;
+        if (dev) {
+            status_t cmdStatus;
+            uint32_t size = sizeof(status_t);
+
+            status_t status2 = (*mEffectInterface)->command(mEffectInterface,
+                                                  EFFECT_CMD_SET_INPUT_DEVICE,
+                                                  sizeof(uint32_t),
+                                                  &dev,
+                                                  &size,
+                                                  &cmdStatus);
+            if (status2 == NO_ERROR) {
+                status2 = cmdStatus;
+            }
+            if (status == NO_ERROR) {
+                status = status2;
+            }
         }
     }
     return status;
@@ -6168,7 +6393,6 @@
         LOGW("process_l(): cannot promote mixer thread");
         return;
     }
-    PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
     bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
             (mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
     bool tracksOnSession = false;
@@ -6180,7 +6404,7 @@
     // will not do it
     if (tracksOnSession &&
             activeTrackCnt() == 0) {
-        size_t numSamples = playbackThread->frameCount() * playbackThread->channelCount();
+        size_t numSamples = thread->frameCount() * thread->channelCount();
         memset(mInBuffer, 0, numSamples * sizeof(int16_t));
     }
 
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 1fad987..e2cf946 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -157,7 +157,7 @@
                         effect_descriptor_t *pDesc,
                         const sp<IEffectClient>& effectClient,
                         int32_t priority,
-                        int output,
+                        int io,
                         int sessionId,
                         status_t *status,
                         int *id,
@@ -273,10 +273,19 @@
 
     class ThreadBase : public Thread {
     public:
-        ThreadBase (const sp<AudioFlinger>& audioFlinger, int id);
+        ThreadBase (const sp<AudioFlinger>& audioFlinger, int id, uint32_t device);
         virtual             ~ThreadBase();
 
+
+        enum type {
+            MIXER,              // Thread class is MixerThread
+            DIRECT,             // Thread class is DirectOutputThread
+            DUPLICATING,        // Thread class is DuplicatingThread
+            RECORD              // Thread class is RecordThread
+        };
+
         status_t dumpBase(int fd, const Vector<String16>& args);
+        status_t dumpEffectChains(int fd, const Vector<String16>& args);
 
         // base for record and playback
         class TrackBase : public AudioBufferProvider, public RefBase {
@@ -377,6 +386,8 @@
             int mParam;
         };
 
+        virtual     status_t    initCheck() const = 0;
+                    int         type() const { return mType; }
                     uint32_t    sampleRate() const;
                     int         channelCount() const;
                     uint32_t    format() const;
@@ -392,6 +403,60 @@
                     void        processConfigEvents();
                     int         id() const { return mId;}
                     bool        standby() { return mStandby; }
+                    uint32_t    device() { return mDevice; }
+        virtual     audio_stream_t* stream() = 0;
+
+                    sp<EffectHandle> createEffect_l(
+                                        const sp<AudioFlinger::Client>& client,
+                                        const sp<IEffectClient>& effectClient,
+                                        int32_t priority,
+                                        int sessionId,
+                                        effect_descriptor_t *desc,
+                                        int *enabled,
+                                        status_t *status);
+                    void disconnectEffect(const sp< EffectModule>& effect,
+                                          const wp<EffectHandle>& handle);
+
+                    // return values for hasAudioSession (bit field)
+                    enum effect_state {
+                        EFFECT_SESSION = 0x1,   // the audio session corresponds to at least one
+                                                // effect
+                        TRACK_SESSION = 0x2     // the audio session corresponds to at least one
+                                                // track
+                    };
+
+                    // get effect chain corresponding to session Id.
+                    sp<EffectChain> getEffectChain(int sessionId);
+                    // same as getEffectChain() but must be called with ThreadBase mutex locked
+                    sp<EffectChain> getEffectChain_l(int sessionId);
+                    // add an effect chain to the chain list (mEffectChains)
+        virtual     status_t addEffectChain_l(const sp<EffectChain>& chain) = 0;
+                    // remove an effect chain from the chain list (mEffectChains)
+        virtual     size_t removeEffectChain_l(const sp<EffectChain>& chain) = 0;
+                    // lock mall effect chains Mutexes. Must be called before releasing the
+                    // ThreadBase mutex before processing the mixer and effects. This guarantees the
+                    // integrity of the chains during the process.
+                    void lockEffectChains_l(Vector<sp <EffectChain> >& effectChains);
+                    // unlock effect chains after process
+                    void unlockEffectChains(Vector<sp <EffectChain> >& effectChains);
+                    // set audio mode to all effect chains
+                    void setMode(uint32_t mode);
+                    // get effect module with corresponding ID on specified audio session
+                    sp<AudioFlinger::EffectModule> getEffect_l(int sessionId, int effectId);
+                    // add and effect module. Also creates the effect chain is none exists for
+                    // the effects audio session
+                    status_t addEffect_l(const sp< EffectModule>& effect);
+                    // remove and effect module. Also removes the effect chain is this was the last
+                    // effect
+                    void removeEffect_l(const sp< EffectModule>& effect);
+                    // detach all tracks connected to an auxiliary effect
+        virtual     void detachAuxEffect_l(int effectId) {}
+                    // returns either EFFECT_SESSION if effects on this audio session exist in one
+                    // chain, or TRACK_SESSION if tracks on this audio session exist, or both
+                    virtual uint32_t hasAudioSession(int sessionId) = 0;
+                    // the value returned by default implementation is not important as the
+                    // strategy is only meaningful for PlaybackThread which implements this method
+                    virtual uint32_t getStrategyForSession_l(int sessionId) { return 0; }
 
         mutable     Mutex                   mLock;
 
@@ -406,6 +471,7 @@
         friend class RecordThread;
         friend class RecordTrack;
 
+                    int                     mType;
                     Condition               mWaitWorkCV;
                     sp<AudioFlinger>        mAudioFlinger;
                     uint32_t                mSampleRate;
@@ -421,18 +487,15 @@
                     bool                    mStandby;
                     int                     mId;
                     bool                    mExiting;
+                    Vector< sp<EffectChain> > mEffectChains;
+                    uint32_t                mDevice;    // output device for PlaybackThread
+                                                        // input + output devices for RecordThread
     };
 
     // --- PlaybackThread ---
     class PlaybackThread : public ThreadBase {
     public:
 
-        enum type {
-            MIXER,
-            DIRECT,
-            DUPLICATING
-        };
-
         enum mixer_state {
             MIXER_IDLE,
             MIXER_TRACKS_ENABLED,
@@ -569,6 +632,8 @@
         virtual     status_t    readyToRun();
         virtual     void        onFirstRef();
 
+        virtual     status_t    initCheck() const { return (mOutput == 0) ? NO_INIT : NO_ERROR; }
+
         virtual     uint32_t    latency() const;
 
         virtual     status_t    setMasterVolume(float value);
@@ -595,8 +660,8 @@
                                     status_t *status);
 
                     AudioStreamOut* getOutput() { return mOutput; }
+                    virtual audio_stream_t* stream() { return &mOutput->stream->common; }
 
-        virtual     int         type() const { return mType; }
                     void        suspend() { mSuspended++; }
                     void        restore() { if (mSuspended) mSuspended--; }
                     bool        isSuspended() { return (mSuspended != 0); }
@@ -605,45 +670,16 @@
         virtual     status_t    getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
                     int16_t     *mixBuffer() { return mMixBuffer; };
 
-                    sp<EffectHandle> createEffect_l(
-                                        const sp<AudioFlinger::Client>& client,
-                                        const sp<IEffectClient>& effectClient,
-                                        int32_t priority,
-                                        int sessionId,
-                                        effect_descriptor_t *desc,
-                                        int *enabled,
-                                        status_t *status);
-                    void disconnectEffect(const sp< EffectModule>& effect,
-                                          const wp<EffectHandle>& handle);
-
-                    // return values for hasAudioSession (bit field)
-                    enum effect_state {
-                        EFFECT_SESSION = 0x1,   // the audio session corresponds to at least one
-                                                // effect
-                        TRACK_SESSION = 0x2     // the audio session corresponds to at least one
-                                                // track
-                    };
-
-                    uint32_t hasAudioSession(int sessionId);
-                    sp<EffectChain> getEffectChain(int sessionId);
-                    sp<EffectChain> getEffectChain_l(int sessionId);
-                    status_t addEffectChain_l(const sp<EffectChain>& chain);
-                    size_t removeEffectChain_l(const sp<EffectChain>& chain);
-                    void lockEffectChains_l(Vector<sp <EffectChain> >& effectChains);
-                    void unlockEffectChains(Vector<sp <EffectChain> >& effectChains);
-
-                    sp<AudioFlinger::EffectModule> getEffect_l(int sessionId, int effectId);
-                    void detachAuxEffect_l(int effectId);
+        virtual     void detachAuxEffect_l(int effectId);
                     status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track> track,
                             int EffectId);
                     status_t attachAuxEffect_l(const sp<AudioFlinger::PlaybackThread::Track> track,
                             int EffectId);
-                    void setMode(uint32_t mode);
 
-                    status_t addEffect_l(const sp< EffectModule>& effect);
-                    void removeEffect_l(const sp< EffectModule>& effect);
-
-                    uint32_t getStrategyForSession_l(int sessionId);
+                    virtual status_t addEffectChain_l(const sp<EffectChain>& chain);
+                    virtual size_t removeEffectChain_l(const sp<EffectChain>& chain);
+                    virtual uint32_t hasAudioSession(int sessionId);
+                    virtual uint32_t getStrategyForSession_l(int sessionId);
 
         struct  stream_type_t {
             stream_type_t()
@@ -656,7 +692,6 @@
         };
 
     protected:
-        int                             mType;
         int16_t*                        mMixBuffer;
         int                             mSuspended;
         int                             mBytesWritten;
@@ -688,11 +723,8 @@
 
         void        readOutputParameters();
 
-        uint32_t    device() { return mDevice; }
-
         virtual status_t    dumpInternals(int fd, const Vector<String16>& args);
         status_t    dumpTracks(int fd, const Vector<String16>& args);
-        status_t    dumpEffectChains(int fd, const Vector<String16>& args);
 
         SortedVector< sp<Track> >       mTracks;
         // mStreamTypes[] uses 1 additionnal stream type internally for the OutputTrack used by DuplicatingThread
@@ -703,8 +735,6 @@
         int                             mNumWrites;
         int                             mNumDelayedWrites;
         bool                            mInWrite;
-        Vector< sp<EffectChain> >       mEffectChains;
-        uint32_t                        mDevice;
     };
 
     class MixerThread : public PlaybackThread {
@@ -788,11 +818,13 @@
               float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; }
               void audioConfigChanged_l(int event, int ioHandle, void *param2);
 
-              int  nextUniqueId_l();
+              uint32_t nextUniqueId();
               status_t moveEffectChain_l(int session,
                                      AudioFlinger::PlaybackThread *srcThread,
                                      AudioFlinger::PlaybackThread *dstThread,
                                      bool reRegister);
+              PlaybackThread *primaryPlaybackThread_l();
+              uint32_t primaryOutputDevice_l();
 
     friend class AudioBuffer;
 
@@ -864,18 +896,33 @@
                         AudioStreamIn *input,
                         uint32_t sampleRate,
                         uint32_t channels,
-                        int id);
+                        int id,
+                        uint32_t device);
                 ~RecordThread();
 
         virtual bool        threadLoop();
         virtual status_t    readyToRun() { return NO_ERROR; }
         virtual void        onFirstRef();
 
+        virtual status_t    initCheck() const { return (mInput == 0) ? NO_INIT : NO_ERROR; }
+                sp<AudioFlinger::RecordThread::RecordTrack>  createRecordTrack_l(
+                        const sp<AudioFlinger::Client>& client,
+                        uint32_t sampleRate,
+                        int format,
+                        int channelMask,
+                        int frameCount,
+                        uint32_t flags,
+                        int sessionId,
+                        status_t *status);
+
                 status_t    start(RecordTrack* recordTrack);
                 void        stop(RecordTrack* recordTrack);
                 status_t    dump(int fd, const Vector<String16>& args);
                 AudioStreamIn* getInput() { return mInput; }
+                virtual audio_stream_t* stream() { return &mInput->stream->common; }
 
+
+                void        setTrack(RecordTrack *recordTrack) { mTrack = recordTrack; }
         virtual status_t    getNextBuffer(AudioBufferProvider::Buffer* buffer);
         virtual void        releaseBuffer(AudioBufferProvider::Buffer* buffer);
         virtual bool        checkForNewParameters_l();
@@ -884,9 +931,14 @@
                 void        readInputParameters();
         virtual unsigned int  getInputFramesLost();
 
+        virtual status_t addEffectChain_l(const sp<EffectChain>& chain);
+        virtual size_t removeEffectChain_l(const sp<EffectChain>& chain);
+        virtual uint32_t hasAudioSession(int sessionId);
+
     private:
                 RecordThread();
                 AudioStreamIn                       *mInput;
+                RecordTrack*                        mTrack;
                 sp<RecordTrack>                     mActiveTrack;
                 Condition                           mStartStopCond;
                 AudioResampler                      *mResampler;
@@ -1103,9 +1155,8 @@
         status_t addEffect_l(const sp<EffectModule>& handle);
         size_t removeEffect_l(const sp<EffectModule>& handle);
 
-        int sessionId() {
-            return mSessionId;
-        }
+        int sessionId() { return mSessionId; }
+        void setSessionId(int sessionId) { mSessionId = sessionId; }
 
         sp<EffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor);
         sp<EffectModule> getEffectFromId_l(int id);
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 8e16d94..6d06d83 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -33,11 +33,14 @@
 #include <cutils/properties.h>
 #include <dlfcn.h>
 #include <hardware_legacy/power.h>
+#include <media/AudioEffect.h>
+#include <media/EffectsFactoryApi.h>
 
 #include <hardware/hardware.h>
 #include <system/audio.h>
 #include <system/audio_policy.h>
 #include <hardware/audio_policy.h>
+#include <audio_effects/audio_effects_conf.h>
 
 namespace android {
 
@@ -101,6 +104,13 @@
     mpAudioPolicy->set_can_mute_enforced_audible(mpAudioPolicy, !forced_val);
 
     LOGI("Loaded audio policy from %s (%s)", module->name, module->id);
+
+    // load audio pre processing modules
+    if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
+        loadPreProcessorConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
+    } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
+        loadPreProcessorConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
+    }
 }
 
 AudioPolicyService::~AudioPolicyService()
@@ -110,6 +120,31 @@
     mAudioCommandThread->exit();
     mAudioCommandThread.clear();
 
+
+    // release audio pre processing resources
+    for (size_t i = 0; i < mInputSources.size(); i++) {
+        InputSourceDesc *source = mInputSources.valueAt(i);
+        Vector <EffectDesc *> effects = source->mEffects;
+        for (size_t j = 0; j < effects.size(); j++) {
+            delete effects[j]->mName;
+            Vector <effect_param_t *> params = effects[j]->mParams;
+            for (size_t k = 0; k < params.size(); k++) {
+                delete params[k];
+            }
+            params.clear();
+            delete effects[j];
+        }
+        effects.clear();
+        delete source;
+    }
+    mInputSources.clear();
+
+    for (size_t i = 0; i < mInputs.size(); i++) {
+        mInputs.valueAt(i)->mEffects.clear();
+        delete mInputs.valueAt(i);
+    }
+    mInputs.clear();
+
     if (mpAudioPolicy && mpAudioPolicyDev)
         mpAudioPolicyDev->destroy_audio_policy(mpAudioPolicyDev, mpAudioPolicy);
     if (mpAudioPolicyDev)
@@ -276,13 +311,51 @@
                                     uint32_t samplingRate,
                                     uint32_t format,
                                     uint32_t channels,
-                                    audio_in_acoustics_t acoustics)
+                                    audio_in_acoustics_t acoustics,
+                                    int audioSession)
 {
     if (mpAudioPolicy == NULL) {
         return 0;
     }
     Mutex::Autolock _l(mLock);
-    return mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate, format, channels, acoustics);
+    audio_io_handle_t input = mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate,
+                                                       format, channels, acoustics);
+
+    if (input == 0) {
+        return input;
+    }
+    // create audio pre processors according to input source
+    ssize_t index = mInputSources.indexOfKey((audio_source_t)inputSource);
+    if (index < 0) {
+        return input;
+    }
+    ssize_t idx = mInputs.indexOfKey(input);
+    InputDesc *inputDesc;
+    if (idx < 0) {
+        inputDesc = new InputDesc();
+        inputDesc->mSessionId = audioSession;
+        mInputs.add(input, inputDesc);
+    } else {
+        inputDesc = mInputs.valueAt(idx);
+    }
+
+    Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
+    for (size_t i = 0; i < effects.size(); i++) {
+        EffectDesc *effect = effects[i];
+        sp<AudioEffect> fx = new AudioEffect(NULL, &effect->mUuid, -1, 0, 0, audioSession, input);
+        status_t status = fx->initCheck();
+        if (status != NO_ERROR && status != ALREADY_EXISTS) {
+            LOGW("Failed to create Fx %s on input %d", effect->mName, input);
+            // fx goes out of scope and strong ref on AudioEffect is released
+            continue;
+        }
+        for (size_t j = 0; j < effect->mParams.size(); j++) {
+            fx->setParameter(effect->mParams[j]);
+        }
+        inputDesc->mEffects.add(fx);
+    }
+    setPreProcessorEnabled(inputDesc, true);
+    return input;
 }
 
 status_t AudioPolicyService::startInput(audio_io_handle_t input)
@@ -291,6 +364,7 @@
         return NO_INIT;
     }
     Mutex::Autolock _l(mLock);
+
     return mpAudioPolicy->start_input(mpAudioPolicy, input);
 }
 
@@ -300,6 +374,7 @@
         return NO_INIT;
     }
     Mutex::Autolock _l(mLock);
+
     return mpAudioPolicy->stop_input(mpAudioPolicy, input);
 }
 
@@ -310,6 +385,16 @@
     }
     Mutex::Autolock _l(mLock);
     mpAudioPolicy->release_input(mpAudioPolicy, input);
+
+    ssize_t index = mInputs.indexOfKey(input);
+    if (index < 0) {
+        return;
+    }
+    InputDesc *inputDesc = mInputs.valueAt(index);
+    setPreProcessorEnabled(inputDesc, false);
+    inputDesc->mEffects.clear();
+    delete inputDesc;
+    mInputs.removeItemsAt(index);
 }
 
 status_t AudioPolicyService::initStreamVolume(audio_stream_type_t stream,
@@ -384,7 +469,7 @@
 }
 
 status_t AudioPolicyService::registerEffect(effect_descriptor_t *desc,
-                                audio_io_handle_t output,
+                                audio_io_handle_t io,
                                 uint32_t strategy,
                                 int session,
                                 int id)
@@ -392,7 +477,7 @@
     if (mpAudioPolicy == NULL) {
         return NO_INIT;
     }
-    return mpAudioPolicy->register_effect(mpAudioPolicy, desc, output, strategy, session, id);
+    return mpAudioPolicy->register_effect(mpAudioPolicy, desc, io, strategy, session, id);
 }
 
 status_t AudioPolicyService::unregisterEffect(int id)
@@ -412,6 +497,43 @@
     return mpAudioPolicy->is_stream_active(mpAudioPolicy, stream, inPastMs);
 }
 
+status_t AudioPolicyService::queryDefaultPreProcessing(int audioSession,
+                                                       effect_descriptor_t *descriptors,
+                                                       uint32_t *count)
+{
+
+    if (mpAudioPolicy == NULL) {
+        *count = 0;
+        return NO_INIT;
+    }
+    Mutex::Autolock _l(mLock);
+    status_t status = NO_ERROR;
+
+    size_t index;
+    for (index = 0; index < mInputs.size(); index++) {
+        if (mInputs.valueAt(index)->mSessionId == audioSession) {
+            break;
+        }
+    }
+    if (index == mInputs.size()) {
+        *count = 0;
+        return BAD_VALUE;
+    }
+    Vector< sp<AudioEffect> > effects = mInputs.valueAt(index)->mEffects;
+
+    for (size_t i = 0; i < effects.size(); i++) {
+        effect_descriptor_t desc = effects[i]->descriptor();
+        if (i < *count) {
+            memcpy(descriptors + i, &desc, sizeof(effect_descriptor_t));
+        }
+    }
+    if (effects.size() > *count) {
+        status = NO_MEMORY;
+    }
+    *count = effects.size();
+    return status;
+}
+
 void AudioPolicyService::binderDied(const wp<IBinder>& who) {
     LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(),
             IPCThreadState::self()->getCallingPid());
@@ -489,6 +611,15 @@
     return NO_ERROR;
 }
 
+void AudioPolicyService::setPreProcessorEnabled(InputDesc *inputDesc, bool enabled)
+{
+    Vector<sp<AudioEffect> > fxVector = inputDesc->mEffects;
+    for (size_t i = 0; i < fxVector.size(); i++) {
+        sp<AudioEffect> fx = fxVector.itemAt(i);
+        fx->setEnabled(enabled);
+    }
+}
+
 status_t AudioPolicyService::onTransact(
         uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
@@ -918,6 +1049,300 @@
     return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
 }
 
+// ----------------------------------------------------------------------------
+// Audio pre-processing configuration
+// ----------------------------------------------------------------------------
+
+const char *AudioPolicyService::kInputSourceNames[AUDIO_SOURCE_CNT -1] = {
+    MIC_SRC_TAG,
+    VOICE_UL_SRC_TAG,
+    VOICE_DL_SRC_TAG,
+    VOICE_CALL_SRC_TAG,
+    CAMCORDER_SRC_TAG,
+    VOICE_REC_SRC_TAG,
+    VOICE_COMM_SRC_TAG
+};
+
+// returns the audio_source_t enum corresponding to the input source name or
+// AUDIO_SOURCE_CNT is no match found
+audio_source_t AudioPolicyService::inputSourceNameToEnum(const char *name)
+{
+    int i;
+    for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
+        if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
+            LOGV("inputSourceNameToEnum found source %s %d", name, i);
+            break;
+        }
+    }
+    return (audio_source_t)i;
+}
+
+size_t AudioPolicyService::growParamSize(char *param,
+                                         size_t size,
+                                         size_t *curSize,
+                                         size_t *totSize)
+{
+    // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
+    size_t pos = ((*curSize - 1 ) / size + 1) * size;
+
+    if (pos + size > *totSize) {
+        while (pos + size > *totSize) {
+            *totSize += ((*totSize + 7) / 8) * 4;
+        }
+        param = (char *)realloc(param, *totSize);
+    }
+    *curSize = pos + size;
+    return pos;
+}
+
+size_t AudioPolicyService::readParamValue(cnode *node,
+                                          char *param,
+                                          size_t *curSize,
+                                          size_t *totSize)
+{
+    if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
+        size_t pos = growParamSize(param, sizeof(short), curSize, totSize);
+        *(short *)((char *)param + pos) = (short)atoi(node->value);
+        LOGV("readParamValue() reading short %d", *(short *)((char *)param + pos));
+        return sizeof(short);
+    } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
+        size_t pos = growParamSize(param, sizeof(int), curSize, totSize);
+        *(int *)((char *)param + pos) = atoi(node->value);
+        LOGV("readParamValue() reading int %d", *(int *)((char *)param + pos));
+        return sizeof(int);
+    } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
+        size_t pos = growParamSize(param, sizeof(float), curSize, totSize);
+        *(float *)((char *)param + pos) = (float)atof(node->value);
+        LOGV("readParamValue() reading float %f",*(float *)((char *)param + pos));
+        return sizeof(float);
+    } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
+        size_t pos = growParamSize(param, sizeof(bool), curSize, totSize);
+        if (strncmp(node->value, "false", strlen("false") + 1) == 0) {
+            *(bool *)((char *)param + pos) = false;
+        } else {
+            *(bool *)((char *)param + pos) = true;
+        }
+        LOGV("readParamValue() reading bool %s",*(bool *)((char *)param + pos) ? "true" : "false");
+        return sizeof(bool);
+    } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
+        size_t len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
+        if (*curSize + len + 1 > *totSize) {
+            *totSize = *curSize + len + 1;
+            param = (char *)realloc(param, *totSize);
+        }
+        strncpy(param + *curSize, node->value, len);
+        *curSize += len;
+        param[*curSize] = '\0';
+        LOGV("readParamValue() reading string %s", param + *curSize - len);
+        return len;
+    }
+    LOGW("readParamValue() unknown param type %s", node->name);
+    return 0;
+}
+
+effect_param_t *AudioPolicyService::loadEffectParameter(cnode *root)
+{
+    cnode *param;
+    cnode *value;
+    size_t curSize = sizeof(effect_param_t);
+    size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
+    effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
+
+    param = config_find(root, PARAM_TAG);
+    value = config_find(root, VALUE_TAG);
+    if (param == NULL && value == NULL) {
+        // try to parse simple parameter form {int int}
+        param = root->first_child;
+        if (param) {
+            // Note: that a pair of random strings is read as 0 0
+            int *ptr = (int *)fx_param->data;
+            int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
+            LOGW("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
+            *ptr++ = atoi(param->name);
+            *ptr = atoi(param->value);
+            fx_param->psize = sizeof(int);
+            fx_param->vsize = sizeof(int);
+            return fx_param;
+        }
+    }
+    if (param == NULL || value == NULL) {
+        LOGW("loadEffectParameter() invalid parameter description %s", root->name);
+        goto error;
+    }
+
+    fx_param->psize = 0;
+    param = param->first_child;
+    while (param) {
+        LOGV("loadEffectParameter() reading param of type %s", param->name);
+        size_t size = readParamValue(param, (char *)fx_param, &curSize, &totSize);
+        if (size == 0) {
+            goto error;
+        }
+        fx_param->psize += size;
+        param = param->next;
+    }
+
+    // align start of value field on 32 bit boundary
+    curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
+
+    fx_param->vsize = 0;
+    value = value->first_child;
+    while (value) {
+        LOGV("loadEffectParameter() reading value of type %s", value->name);
+        size_t size = readParamValue(value, (char *)fx_param, &curSize, &totSize);
+        if (size == 0) {
+            goto error;
+        }
+        fx_param->vsize += size;
+        value = value->next;
+    }
+
+    return fx_param;
+
+error:
+    delete fx_param;
+    return NULL;
+}
+
+void AudioPolicyService::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
+{
+    cnode *node = root->first_child;
+    while (node) {
+        LOGV("loadEffectParameters() loading param %s", node->name);
+        effect_param_t *param = loadEffectParameter(node);
+        if (param == NULL) {
+            node = node->next;
+            continue;
+        }
+        params.add(param);
+        node = node->next;
+    }
+}
+
+AudioPolicyService::InputSourceDesc *AudioPolicyService::loadInputSource(
+                                                            cnode *root,
+                                                            const Vector <EffectDesc *>& effects)
+{
+    cnode *node = root->first_child;
+    if (node == NULL) {
+        LOGW("loadInputSource() empty element %s", root->name);
+        return NULL;
+    }
+    InputSourceDesc *source = new InputSourceDesc();
+    while (node) {
+        size_t i;
+        for (i = 0; i < effects.size(); i++) {
+            if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
+                LOGV("loadInputSource() found effect %s in list", node->name);
+                break;
+            }
+        }
+        if (i == effects.size()) {
+            LOGV("loadInputSource() effect %s not in list", node->name);
+            node = node->next;
+            continue;
+        }
+        EffectDesc *effect = new EffectDesc(*effects[i]);
+        loadEffectParameters(node, effect->mParams);
+        LOGV("loadInputSource() adding effect %s uuid %08x", effect->mName, effect->mUuid.timeLow);
+        source->mEffects.add(effect);
+        node = node->next;
+    }
+    if (source->mEffects.size() == 0) {
+        LOGW("loadInputSource() no valid effects found in source %s", root->name);
+        delete source;
+        return NULL;
+    }
+    return source;
+}
+
+status_t AudioPolicyService::loadInputSources(cnode *root, const Vector <EffectDesc *>& effects)
+{
+    cnode *node = config_find(root, PREPROCESSING_TAG);
+    if (node == NULL) {
+        return -ENOENT;
+    }
+    node = node->first_child;
+    while (node) {
+        audio_source_t source = inputSourceNameToEnum(node->name);
+        if (source == AUDIO_SOURCE_CNT) {
+            LOGW("loadInputSources() invalid input source %s", node->name);
+            node = node->next;
+            continue;
+        }
+        LOGV("loadInputSources() loading input source %s", node->name);
+        InputSourceDesc *desc = loadInputSource(node, effects);
+        if (desc == NULL) {
+            node = node->next;
+            continue;
+        }
+        mInputSources.add(source, desc);
+        node = node->next;
+    }
+    return NO_ERROR;
+}
+
+AudioPolicyService::EffectDesc *AudioPolicyService::loadEffect(cnode *root)
+{
+    cnode *node = config_find(root, UUID_TAG);
+    if (node == NULL) {
+        return NULL;
+    }
+    effect_uuid_t uuid;
+    if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
+        LOGW("loadEffect() invalid uuid %s", node->value);
+        return NULL;
+    }
+    EffectDesc *effect = new EffectDesc();
+    effect->mName = strdup(root->name);
+    memcpy(&effect->mUuid, &uuid, sizeof(effect_uuid_t));
+
+    return effect;
+}
+
+status_t AudioPolicyService::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
+{
+    cnode *node = config_find(root, EFFECTS_TAG);
+    if (node == NULL) {
+        return -ENOENT;
+    }
+    node = node->first_child;
+    while (node) {
+        LOGV("loadEffects() loading effect %s", node->name);
+        EffectDesc *effect = loadEffect(node);
+        if (effect == NULL) {
+            node = node->next;
+            continue;
+        }
+        effects.add(effect);
+        node = node->next;
+    }
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::loadPreProcessorConfig(const char *path)
+{
+    cnode *root;
+    char *data;
+
+    data = (char *)load_file(path, NULL);
+    if (data == NULL) {
+        return -ENODEV;
+    }
+    root = config_node("", "");
+    config_load(root, data);
+
+    Vector <EffectDesc *> effects;
+    loadEffects(root, effects);
+    loadInputSources(root, effects);
+
+    config_free(root);
+    free(root);
+    free(data);
+
+    return NO_ERROR;
+}
+
 /* implementation of the interface to the policy manager */
 extern "C" {
 
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
index b830120..834b794 100644
--- a/services/audioflinger/AudioPolicyService.h
+++ b/services/audioflinger/AudioPolicyService.h
@@ -17,14 +17,17 @@
 #ifndef ANDROID_AUDIOPOLICYSERVICE_H
 #define ANDROID_AUDIOPOLICYSERVICE_H
 
-#include <media/IAudioPolicyService.h>
-#include <media/ToneGenerator.h>
+#include <cutils/misc.h>
+#include <cutils/config_utils.h>
 #include <utils/Vector.h>
+#include <utils/SortedVector.h>
 #include <binder/BinderService.h>
-
 #include <system/audio.h>
 #include <system/audio_policy.h>
 #include <hardware/audio_policy.h>
+#include <media/IAudioPolicyService.h>
+#include <media/ToneGenerator.h>
+#include <media/AudioEffect.h>
 
 namespace android {
 
@@ -78,7 +81,8 @@
                                     uint32_t format = AUDIO_FORMAT_DEFAULT,
                                     uint32_t channels = 0,
                                     audio_in_acoustics_t acoustics =
-                                            (audio_in_acoustics_t)0);
+                                            (audio_in_acoustics_t)0,
+                                    int audioSession = 0);
     virtual status_t startInput(audio_io_handle_t input);
     virtual status_t stopInput(audio_io_handle_t input);
     virtual void releaseInput(audio_io_handle_t input);
@@ -93,13 +97,16 @@
 
     virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
     virtual status_t registerEffect(effect_descriptor_t *desc,
-                                    audio_io_handle_t output,
+                                    audio_io_handle_t io,
                                     uint32_t strategy,
                                     int session,
                                     int id);
     virtual status_t unregisterEffect(int id);
     virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const;
 
+    virtual status_t queryDefaultPreProcessing(int audioSession,
+                                              effect_descriptor_t *descriptors,
+                                              uint32_t *count);
     virtual     status_t    onTransact(
                                 uint32_t code,
                                 const Parcel& data,
@@ -218,6 +225,51 @@
         String8 mName;                      // string used by wake lock fo delayed commands
     };
 
+    class EffectDesc {
+    public:
+        EffectDesc() {}
+        virtual ~EffectDesc() {}
+        char *mName;
+        effect_uuid_t mUuid;
+        Vector <effect_param_t *> mParams;
+    };
+
+    class InputSourceDesc {
+    public:
+        InputSourceDesc() {}
+        virtual ~InputSourceDesc() {}
+        Vector <EffectDesc *> mEffects;
+    };
+
+
+    class InputDesc {
+    public:
+        InputDesc() {}
+        virtual ~InputDesc() {}
+        int mSessionId;
+        Vector< sp<AudioEffect> >mEffects;
+    };
+
+    static const char *kInputSourceNames[AUDIO_SOURCE_CNT -1];
+
+    void setPreProcessorEnabled(InputDesc *inputDesc, bool enabled);
+    status_t loadPreProcessorConfig(const char *path);
+    status_t loadEffects(cnode *root, Vector <EffectDesc *>& effects);
+    EffectDesc *loadEffect(cnode *root);
+    status_t loadInputSources(cnode *root, const Vector <EffectDesc *>& effects);
+    audio_source_t inputSourceNameToEnum(const char *name);
+    InputSourceDesc *loadInputSource(cnode *root, const Vector <EffectDesc *>& effects);
+    void loadEffectParameters(cnode *root, Vector <effect_param_t *>& params);
+    effect_param_t *loadEffectParameter(cnode *root);
+    size_t readParamValue(cnode *node,
+                          char *param,
+                          size_t *curSize,
+                          size_t *totSize);
+    size_t growParamSize(char *param,
+                         size_t size,
+                         size_t *curSize,
+                         size_t *totSize);
+
     // Internal dump utilities.
     status_t dumpPermissionDenial(int fd);
 
@@ -226,9 +278,10 @@
                             // device connection state  or routing
     sp <AudioCommandThread> mAudioCommandThread;    // audio commands thread
     sp <AudioCommandThread> mTonePlaybackThread;     // tone playback thread
-
     struct audio_policy_device *mpAudioPolicyDev;
     struct audio_policy *mpAudioPolicy;
+    KeyedVector< audio_source_t, InputSourceDesc* > mInputSources;
+    KeyedVector< audio_io_handle_t, InputDesc* > mInputs;
 };
 
 }; // namespace android