Merge commit 'remotes/korg/cupcake' into merge

Conflicts:
	core/java/android/view/animation/TranslateAnimation.java
	core/jni/Android.mk
	core/res/res/values-en-rGB/strings.xml
	libs/audioflinger/AudioFlinger.cpp
	libs/surfaceflinger/LayerScreenshot.cpp
	packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index dd585c9..ff64855 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -125,7 +125,8 @@
      * channelCount:       Number of PCM channels (e.g 2 for stereo).
      * frameCount:         Total size of track PCM buffer in frames. This defines the
      *                     latency of the track.
-     * flags:              Reserved for future use.
+     * flags:              A bitmask of acoustic values from enum record_flags.  It enables
+     *                     AGC, NS, and IIR.
      * cbf:                Callback function. If not null, this function is called periodically
      *                     to provide new PCM data.
      * notificationFrames: The callback function is called each time notificationFrames PCM
@@ -133,6 +134,12 @@
      * user                Context for use by the callback receiver.
      */
 
+     enum record_flags {
+         RECORD_AGC_ENABLE = AudioSystem::AGC_ENABLE,
+         RECORD_NS_ENABLE  = AudioSystem::NS_ENABLE,
+         RECORD_IIR_ENABLE = AudioSystem::TX_IIR_ENABLE
+     };
+
                         AudioRecord(int streamType,
                                     uint32_t sampleRate = 0,
                                     int format          = 0,
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 77676bf..77c90ba 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -29,8 +29,27 @@
 {
 public:
 
+    enum stream_type {
+        DEFAULT         =-1,
+        VOICE_CALL      = 0,
+        SYSTEM          = 1,
+        RING            = 2,
+        MUSIC           = 3,
+        ALARM           = 4,
+        NOTIFICATION    = 5,
+        BLUETOOTH_SCO   = 6,
+        NUM_STREAM_TYPES
+    };
+
+    enum audio_output_type {
+        AUDIO_OUTPUT_DEFAULT      =-1,
+        AUDIO_OUTPUT_HARDWARE     = 0,
+        AUDIO_OUTPUT_A2DP         = 1,
+        NUM_AUDIO_OUTPUT_TYPES
+    };
+
     enum audio_format {
-        DEFAULT = 0,
+        FORMAT_DEFAULT = 0,
         PCM_16_BIT,
         PCM_8_BIT,
         INVALID_FORMAT
@@ -51,7 +70,16 @@
         ROUTE_BLUETOOTH_SCO  = (1 << 2),
         ROUTE_HEADSET        = (1 << 3),
         ROUTE_BLUETOOTH_A2DP = (1 << 4),
-        ROUTE_ALL       = 0xFFFFFFFF
+        ROUTE_ALL            = -1UL,
+    };
+
+    enum audio_in_acoustics {
+        AGC_ENABLE    = 0x0001,
+        AGC_DISABLE   = 0,
+        NS_ENABLE     = 0x0002,
+        NS_DISABLE    = 0,
+        TX_IIR_ENABLE = 0x0004,
+        TX_DISABLE    = 0
     };
 
     /* These are static methods to control the system-wide AudioFlinger
@@ -96,33 +124,52 @@
     static float linearToLog(int volume);
     static int logToLinear(float volume);
 
-    static status_t getOutputSamplingRate(int* samplingRate);
-    static status_t getOutputFrameCount(int* frameCount);
-    static status_t getOutputLatency(uint32_t* latency);
+    static status_t getOutputSamplingRate(int* samplingRate, int stream = DEFAULT);
+    static status_t getOutputFrameCount(int* frameCount, int stream = DEFAULT);
+    static status_t getOutputLatency(uint32_t* latency, int stream = DEFAULT);
+
+    static bool routedToA2dpOutput(int streamType);
+    
+    static status_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount, 
+        size_t* buffSize);
 
     // ----------------------------------------------------------------------------
 
 private:
 
-    class DeathNotifier: public IBinder::DeathRecipient
+    class AudioFlingerClient: public IBinder::DeathRecipient, public BnAudioFlingerClient
     {
     public:
-        DeathNotifier() {      
+        AudioFlingerClient() {      
         }
         
+        // DeathRecipient
         virtual void binderDied(const wp<IBinder>& who);
+        
+        // IAudioFlingerClient
+        virtual void a2dpEnabledChanged(bool enabled);
+        
     };
+    static int getOutput(int streamType);
 
-    static sp<DeathNotifier> gDeathNotifier;
+    static sp<AudioFlingerClient> gAudioFlingerClient;
 
-    friend class DeathNotifier;
+    friend class AudioFlingerClient;
 
     static Mutex gLock;
     static sp<IAudioFlinger> gAudioFlinger;
     static audio_error_callback gAudioErrorCallback;
-    static int gOutSamplingRate;
-    static int gOutFrameCount;
-    static uint32_t gOutLatency;
+    static int gOutSamplingRate[NUM_AUDIO_OUTPUT_TYPES];
+    static int gOutFrameCount[NUM_AUDIO_OUTPUT_TYPES];
+    static uint32_t gOutLatency[NUM_AUDIO_OUTPUT_TYPES];
+    static bool gA2dpEnabled;
+    
+    static size_t gInBuffSize;
+    // previous parameters for recording buffer size queries
+    static uint32_t gPrevInSamplingRate;
+    static int gPrevInFormat;
+    static int gPrevInChannelCount;
+
 };
 
 };  // namespace android
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index fd62daa..659f5f8 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -42,18 +42,6 @@
 class AudioTrack
 {
 public:
-
-    enum stream_type {
-        DEFAULT         =-1,
-        VOICE_CALL      = 0,
-        SYSTEM          = 1,
-        RING            = 2,
-        MUSIC           = 3,
-        ALARM           = 4,
-        NOTIFICATION    = 5,
-        NUM_STREAM_TYPES
-    };
-
     enum channel_index {
         MONO   = 0,
         LEFT   = 0,
@@ -127,7 +115,7 @@
      * Parameters:
      *
      * streamType:         Select the type of audio stream this track is attached to
-     *                     (e.g. AudioTrack::MUSIC).
+     *                     (e.g. AudioSystem::MUSIC).
      * sampleRate:         Track sampling rate in Hz.
      * format:             PCM sample format (e.g AudioSystem::PCM_16_BIT for signed
      *                     16 bits per sample).
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index 69703b2..6f13fe0 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -26,6 +26,7 @@
 #include <utils/IInterface.h>
 #include <media/IAudioTrack.h>
 #include <media/IAudioRecord.h>
+#include <media/IAudioFlingerClient.h>
 
 
 namespace android {
@@ -64,11 +65,11 @@
     /* query the audio hardware state. This state never changes,
      * and therefore can be cached.
      */
-    virtual     uint32_t    sampleRate() const = 0;
-    virtual     int         channelCount() const = 0;
-    virtual     int         format() const = 0;
-    virtual     size_t      frameCount() const = 0;
-    virtual     uint32_t    latency() const = 0;
+    virtual     uint32_t    sampleRate(int output) const = 0;
+    virtual     int         channelCount(int output) const = 0;
+    virtual     int         format(int output) const = 0;
+    virtual     size_t      frameCount(int output) const = 0;
+    virtual     uint32_t    latency(int output) const = 0;
 
     /* set/get the audio hardware state. This will probably be used by
      * the preference panel, mostly.
@@ -107,6 +108,18 @@
     // Temporary interface, do not use
     // TODO: Replace with a more generic key:value get/set mechanism
     virtual     status_t  setParameter(const char* key, const char* value) = 0;
+    
+    // register a current process for audio output change notifications
+    virtual void registerClient(const sp<IAudioFlingerClient>& client) = 0;
+    
+    // retrieve the audio recording buffer size
+    virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount) = 0;
+    
+    // force AudioFlinger thread out of standby
+    virtual     void        wakeUp() = 0;
+
+    // is A2DP output enabled
+    virtual     bool        isA2dpEnabled() const = 0;
 };
 
 
diff --git a/include/media/IAudioFlingerClient.h b/include/media/IAudioFlingerClient.h
new file mode 100644
index 0000000..c3deb0b
--- /dev/null
+++ b/include/media/IAudioFlingerClient.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_IAUDIOFLINGERCLIENT_H
+#define ANDROID_IAUDIOFLINGERCLIENT_H
+
+
+#include <utils/RefBase.h>
+#include <utils/IInterface.h>
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class IAudioFlingerClient : public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(AudioFlingerClient);
+
+    // Notifies a change of audio output from/to hardware to/from A2DP.
+    virtual void a2dpEnabledChanged(bool enabled) = 0;
+
+};
+
+
+// ----------------------------------------------------------------------------
+
+class BnAudioFlingerClient : public BnInterface<IAudioFlingerClient>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IAUDIOFLINGERCLIENT_H
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 49e45d1..64d3a40 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -24,6 +24,7 @@
 
 class ISurface;
 class ICamera;
+class IMediaPlayerClient;
 
 class IMediaRecorder: public IInterface
 {
@@ -38,8 +39,11 @@
     virtual	status_t		setVideoEncoder(int ve) = 0;
     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		setVideoSize(int width, int height) = 0;
     virtual	status_t		setVideoFrameRate(int frames_per_second) = 0;
+    virtual     status_t                setParameters(const String8& params) = 0;
+    virtual     status_t                setListener(const sp<IMediaPlayerClient>& listener) = 0;
     virtual	status_t		prepare() = 0;
     virtual	status_t		getMaxAmplitude(int* max) = 0;
     virtual	status_t		start() = 0;
diff --git a/include/media/JetPlayer.h b/include/media/JetPlayer.h
index 4268170..16764a9 100644
--- a/include/media/JetPlayer.h
+++ b/include/media/JetPlayer.h
@@ -33,9 +33,12 @@
 
 public:
 
-    static const int JET_USERID_UPDATE           = 1;
-    static const int JET_NUMQUEUEDSEGMENT_UPDATE = 2;
-    static const int JET_PAUSE_UPDATE            = 3;
+    // to keep in sync with the JetPlayer class constants
+    // defined in frameworks/base/media/java/android/media/JetPlayer.java
+    static const int JET_EVENT                   = 1;
+    static const int JET_USERID_UPDATE           = 2;
+    static const int JET_NUMQUEUEDSEGMENT_UPDATE = 3;
+    static const int JET_PAUSE_UPDATE            = 4;
 
     JetPlayer(jobject javaJetPlayer, 
             int maxTracks = 32, 
@@ -44,7 +47,8 @@
     int init();
     int release();
     
-    int openFile(const char* url);
+    int loadFromFile(const char* url);
+    int loadFromFD(const int fd, const long long offset, const long long length);
     int closeFile();
     int play();
     int pause();
@@ -53,6 +57,7 @@
     int setMuteFlags(EAS_U32 muteFlags, bool sync);
     int setMuteFlag(int trackNum, bool muteFlag, bool sync);
     int triggerClip(int clipId);
+    int clearQueue();
 
     void setEventCallback(jetevent_callback callback);
     
@@ -62,7 +67,8 @@
 private:
     static  int         renderThread(void*);
     int                 render();
-    void                fireEventOnStatusChange();
+    void                fireUpdateOnStatusChange();
+    void                fireEventsFromJetQueue();
 
     JetPlayer() {} // no default constructor
     void dump();
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 30e4578..7f0e7b3 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -17,9 +17,6 @@
 #ifndef ANDROID_MEDIAPLAYERINTERFACE_H
 #define ANDROID_MEDIAPLAYERINTERFACE_H
 
-#include <pthread.h>
-#include <signal.h>
-
 #ifdef __cplusplus
 
 #include <ui/ISurface.h>
@@ -74,7 +71,6 @@
     virtual             ~MediaPlayerBase() {}
     virtual status_t    initCheck() = 0;
     virtual bool        hardwareOutput() = 0;
-    virtual status_t    setSigBusHandlerStructTLSKey(pthread_key_t key) { return 0; }
     virtual status_t    setDataSource(const char *url) = 0;
     virtual status_t    setDataSource(int fd, int64_t offset, int64_t length) = 0;
     virtual status_t    setVideoSurface(const sp<ISurface>& surface) = 0;
@@ -125,34 +121,6 @@
 
 #endif // __cplusplus
 
-// A thread can set the thread local variable identified by the pthread_key_t
-// that was passed to the player using the setSigBusHandlerStructTLSKey()
-// method to the address of the following structure.
-// If 'handlesigbus' is non-NULL, the function it points to will be called,
-// and if it returns 0, the signal will be assumed to have been handled,
-// and no other action will be taken. If it returns non-zero, the old SIGBUS
-// handler will be called.
-// If 'handlesigbus is NULL, then sigbusvar must be non NULL. The system's
-// SIGBUS handler will map an accessible page filled with zeroes at the
-// location that caused the original fault, set the variable pointed to by
-// sigbusvar to a non-zero value, and exit (which causes the operation to
-// be retried, which should now succeed).
-// If base and len are non zero, which is strongly recommended, they will
-// be used as additional constraints on the signal handler. That is, when
-// specified, the fault address must be in the range specified by base and
-// len in order for handlesigbus() to be called or sigbusvar to be set.
-// If the fault address is outside of the range, the old SIGBUS handler
-// will be called.
-struct mediasigbushandler {
-    int (*handlesigbus)(siginfo_t *, struct mediasigbushandler *);
-    int  *sigbusvar;
-    char *base;
-    int len;
-    // these next two are free for application use
-    struct mediasigbushandler *next;
-    void *data;
-};
-
 
 #endif // ANDROID_MEDIAPLAYERINTERFACE_H
 
diff --git a/include/media/PVMediaRecorder.h b/include/media/PVMediaRecorder.h
index 5fee0d6..0c71932 100644
--- a/include/media/PVMediaRecorder.h
+++ b/include/media/PVMediaRecorder.h
@@ -19,6 +19,7 @@
 #define ANDROID_PVMEDIARECORDER_H
 
 #include <media/mediarecorder.h>
+#include <media/IMediaPlayerClient.h>
 
 namespace android {
 
@@ -43,6 +44,9 @@
     status_t setCamera(const sp<ICamera>& camera);
     status_t setPreviewSurface(const sp<ISurface>& surface);
     status_t setOutputFile(const char *path);
+    status_t setOutputFile(int fd, int64_t offset, int64_t length);
+    status_t setParameters(const String8& params);
+    status_t setListener(const sp<IMediaPlayerClient>& listener);
     status_t prepare();
     status_t start();
     status_t stop();
diff --git a/include/media/PVPlayer.h b/include/media/PVPlayer.h
index 5f302ed..8122df6 100644
--- a/include/media/PVPlayer.h
+++ b/include/media/PVPlayer.h
@@ -20,6 +20,12 @@
 #include <utils/Errors.h>
 #include <media/MediaPlayerInterface.h>
 
+#define MAX_OPENCORE_INSTANCES 25
+
+#ifdef MAX_OPENCORE_INSTANCES
+#include <cutils/atomic.h>
+#endif
+
 class PlayerDriver;
 
 namespace android {
@@ -31,7 +37,6 @@
     virtual             ~PVPlayer();
 
     virtual status_t    initCheck();
-    virtual status_t    setSigBusHandlerStructTLSKey(pthread_key_t key);
     virtual status_t    setDataSource(const char *url);
     virtual status_t    setDataSource(int fd, int64_t offset, int64_t length);
     virtual status_t    setVideoSurface(const sp<ISurface>& surface);
@@ -48,8 +53,8 @@
     virtual status_t    setLooping(int loop);
     virtual player_type playerType() { return PV_PLAYER; }
 
-            // make available to PlayerDriver
-            void        sendEvent(int msg, int ext1=0, int ext2=0) { MediaPlayerBase::sendEvent(msg, ext1, ext2); }
+    // make available to PlayerDriver
+    void        sendEvent(int msg, int ext1=0, int ext2=0) { MediaPlayerBase::sendEvent(msg, ext1, ext2); }
 
 private:
     static void         do_nothing(status_t s, void *cookie, bool cancelled) { }
@@ -62,10 +67,13 @@
     char *                      mDataSourcePath;
     bool                        mIsDataSourceSet;
     sp<ISurface>                mSurface;
-    void *                      mMemBase;
-    off_t                       mMemSize;
+    int                         mSharedFd;
     status_t                    mInit;
     int                         mDuration;
+
+#ifdef MAX_OPENCORE_INSTANCES
+    static volatile int32_t     sNumInstances;
+#endif
 };
 
 }; // namespace android
diff --git a/include/media/ToneGenerator.h b/include/media/ToneGenerator.h
index 0cfdeec..ec64e4d 100644
--- a/include/media/ToneGenerator.h
+++ b/include/media/ToneGenerator.h
@@ -85,8 +85,6 @@
         TONE_RESTARTING  //
     };
 
-    static const unsigned int NUM_PCM_BUFFERS = 2; // Number of AudioTrack pcm buffers
-    
     static const unsigned int TONEGEN_MAX_WAVES = 3;
     static const unsigned int TONEGEN_MAX_SEGMENTS = 4;  // Maximun number of elenemts in
     static const unsigned int TONEGEN_INF = 0xFFFFFFFF;  // Represents infinite time duration
@@ -127,7 +125,6 @@
     const ToneDescriptor *mpNewToneDesc;  // pointer to next active tone descriptor
 
     int mSamplingRate;  // AudioFlinger Sampling rate
-    int mBufferSize;  // PCM buffer size in frames
     AudioTrack *mpAudioTrack;  // Pointer to audio track used for playback
     Mutex mLock;  // Mutex to control concurent access to ToneGenerator object from audio callback and application API
     Mutex mCbkCondLock; // Mutex associated to mWaitCbkCond
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 7288445..58906d1 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -34,11 +34,72 @@
     MEDIA_SEEK_COMPLETE     = 4,
     MEDIA_SET_VIDEO_SIZE    = 5,
     MEDIA_ERROR             = 100,
+    MEDIA_INFO              = 200,
 };
 
-typedef int media_error_type;
-const media_error_type MEDIA_ERROR_UNKNOWN = 1;
-const media_error_type MEDIA_ERROR_SERVER_DIED = 100;
+// Generic error codes for the media player framework.  Errors are fatal, the
+// playback must abort.
+//
+// Errors are communicated back to the client using the
+// MediaPlayerListener::notify method defined below.
+// In this situation, 'notify' is invoked with the following:
+//   'msg' is set to MEDIA_ERROR.
+//   'ext1' should be a value from the enum media_error_type.
+//   'ext2' contains an implementation dependant error code to provide
+//          more details. Should default to 0 when not used.
+//
+// The codes are distributed as follow:
+//   0xx: Reserved
+//   1xx: Android Player errors. Something went wrong inside the MediaPlayer.
+//   2xx: Media errors (e.g Codec not supported). There is a problem with the
+//        media itself.
+//   3xx: Runtime errors. Some extraordinary condition arose making the playback
+//        impossible.
+//
+enum media_error_type {
+    // 0xx
+    MEDIA_ERROR_UNKNOWN = 1,
+    // 1xx
+    MEDIA_ERROR_SERVER_DIED = 100,
+    // 2xx
+    MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200,
+    // 3xx
+};
+
+
+// Info and warning codes for the media player framework.  These are non fatal,
+// the playback is going on but there might be some user visible issues.
+//
+// Info and warning messages are communicated back to the client using the
+// MediaPlayerListener::notify method defined below.  In this situation,
+// 'notify' is invoked with the following:
+//   'msg' is set to MEDIA_INFO.
+//   'ext1' should be a value from the enum media_info_type.
+//   'ext2' contains an implementation dependant error code to provide
+//          more details. Should default to 0 when not used.
+//
+// The codes are distributed as follow:
+//   0xx: Reserved
+//   7xx: Android Player info/warning (e.g player lagging behind.)
+//   8xx: Media info/warning (e.g media badly interleaved.)
+// 
+enum media_info_type {
+    // 0xx
+    MEDIA_INFO_UNKNOWN = 1,
+    // 7xx
+    // The video is too complex for the decoder: it can't decode frames fast
+    // enough. Possibly only the audio plays fine at this stage.
+    MEDIA_INFO_VIDEO_TRACK_LAGGING = 700,
+    // 8xx
+    // Bad interleaving means that a media has been improperly interleaved or not
+    // interleaved at all, e.g has all the video samples first then all the audio
+    // ones. Video is playing but a lot of disk seek may be happening.
+    MEDIA_INFO_BAD_INTERLEAVING = 800,
+    // The media is not seekable (e.g live stream).
+    MEDIA_INFO_NOT_SEEKABLE = 801,
+};
+
+
 
 enum media_player_states {
     MEDIA_PLAYER_STATE_ERROR        = 0,
@@ -141,4 +202,3 @@
 }; // namespace android
 
 #endif // ANDROID_MEDIAPLAYER_H
-
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index a901d32..78d7621 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -19,6 +19,7 @@
 #define ANDROID_MEDIARECORDER_H
 
 #include <utils.h>
+#include <media/IMediaPlayerClient.h>
 
 namespace android {
 
@@ -87,7 +88,34 @@
     MEDIA_RECORDER_RECORDING             = 1 << 4,
 };
 
-class MediaRecorder
+// The "msg" code passed to the listener in notify.
+enum media_recorder_event_type {
+    MEDIA_RECORDER_EVENT_ERROR                    = 1,
+    MEDIA_RECORDER_EVENT_INFO                     = 2
+};
+
+enum media_recorder_error_type {
+    MEDIA_RECORDER_ERROR_UNKNOWN                  = 1
+};
+
+// The codes are distributed as follow:
+//   0xx: Reserved
+//   8xx: General info/warning
+// 
+enum media_recorder_info_type {
+    MEDIA_RECORDER_INFO_UNKNOWN                   = 1,
+    MEDIA_RECORDER_INFO_MAX_DURATION_REACHED      = 800
+};
+
+// ----------------------------------------------------------------------------
+// ref-counted object for callbacks
+class MediaRecorderListener: virtual public RefBase
+{
+public:
+    virtual void notify(int msg, int ext1, int ext2) = 0;
+};
+
+class MediaRecorder : public BnMediaPlayerClient
 {
 public:
     MediaRecorder();
@@ -102,8 +130,11 @@
     status_t    setVideoEncoder(int ve);
     status_t    setAudioEncoder(int ae);
     status_t    setOutputFile(const char* path);
+    status_t    setOutputFile(int fd, int64_t offset, int64_t length);
     status_t    setVideoSize(int width, int height);
     status_t    setVideoFrameRate(int frames_per_second);
+    status_t    setParameters(const String8& params);
+    status_t    setListener(const sp<MediaRecorderListener>& listener);
     status_t    prepare();
     status_t    getMaxAmplitude(int* max);
     status_t    start();
@@ -112,18 +143,22 @@
     status_t    init();
     status_t    close();
     status_t    release();
+    void        notify(int msg, int ext1, int ext2);
 
 private:
     void                    doCleanUp();
     status_t                doReset();
 
-    sp<IMediaRecorder>      mMediaRecorder;
-    media_recorder_states   mCurrentState;
-    bool                    mIsAudioSourceSet;
-    bool                    mIsVideoSourceSet;
-    bool                    mIsAudioEncoderSet;
-    bool                    mIsVideoEncoderSet;
-    bool                    mIsOutputFileSet;
+    sp<IMediaRecorder>          mMediaRecorder;
+    sp<MediaRecorderListener>   mListener;
+    media_recorder_states       mCurrentState;
+    bool                        mIsAudioSourceSet;
+    bool                        mIsVideoSourceSet;
+    bool                        mIsAudioEncoderSet;
+    bool                        mIsVideoEncoderSet;
+    bool                        mIsOutputFileSet;
+    Mutex                       mLock;
+    Mutex                       mNotifyLock;
 };
 
 };  // namespace android
diff --git a/include/media/thread_init.h b/include/media/thread_init.h
index 2c0c1f1..2feac86 100644
--- a/include/media/thread_init.h
+++ b/include/media/thread_init.h
@@ -19,7 +19,6 @@
 
 bool InitializeForThread();
 void UninitializeForThread();
-void keydestructor(void*);
 
 #endif /* THREAD_INIT_H*/
 	
diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h
index 3056139..0c7ad46 100644
--- a/include/private/opengles/gl_context.h
+++ b/include/private/opengles/gl_context.h
@@ -28,6 +28,7 @@
 #include <private/pixelflinger/ggl_context.h>
 
 #include <GLES/gl.h>
+#include <GLES/glext.h>
 
 namespace android {
 
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 2a697b9..8020da2 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -4,6 +4,7 @@
 LOCAL_SRC_FILES:= \
 	AudioTrack.cpp \
 	IAudioFlinger.cpp \
+	IAudioFlingerClient.cpp \
 	IAudioTrack.cpp \
 	IAudioRecord.cpp \
 	AudioRecord.cpp \
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index e833c85..7594ff0 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -128,8 +128,23 @@
         return BAD_VALUE;
     }
 
-    // TODO: Get input frame count from hardware.
-    int minFrameCount = 1024*2;
+    // validate framecount
+    size_t inputBuffSizeInBytes = -1;
+    if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &inputBuffSizeInBytes)
+            != NO_ERROR) {
+        LOGE("AudioSystem could not query the input buffer size.");
+        return NO_INIT;    
+    }
+    if (inputBuffSizeInBytes == 0) {
+        LOGE("Recording parameters are not supported: sampleRate %d, channelCount %d, format %d",
+            sampleRate, channelCount, format);
+        return BAD_VALUE;
+    }
+    int frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1);
+
+    // We use 2* size of input buffer for ping pong use of record buffer.
+    int minFrameCount = 2 * inputBuffSizeInBytes / frameSizeInBytes;
+    LOGV("AudioRecord::set() minFrameCount = %d", minFrameCount);
 
     if (frameCount == 0) {
         frameCount = minFrameCount;
@@ -144,7 +159,11 @@
     // open record channel
     status_t status;
     sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), streamType,
-            sampleRate, format, channelCount, frameCount, flags, &status);
+                                                       sampleRate, format,
+                                                       channelCount,
+                                                       frameCount,
+                                                       ((uint16_t)flags) << 16, 
+                                                       &status);
     if (record == 0) {
         LOGE("AudioFlinger could not create record track, status: %d", status);
         return status;
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index a375b55..63dfc3b 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -15,10 +15,11 @@
  */
 
 #define LOG_TAG "AudioSystem"
+//#define LOG_NDEBUG 0
+
 #include <utils/Log.h>
 #include <utils/IServiceManager.h>
 #include <media/AudioSystem.h>
-#include <media/AudioTrack.h>
 #include <math.h>
 
 namespace android {
@@ -26,12 +27,18 @@
 // client singleton for AudioFlinger binder interface
 Mutex AudioSystem::gLock;
 sp<IAudioFlinger> AudioSystem::gAudioFlinger;
-sp<AudioSystem::DeathNotifier> AudioSystem::gDeathNotifier;
+sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient;
 audio_error_callback AudioSystem::gAudioErrorCallback = NULL;
 // Cached values
-int AudioSystem::gOutSamplingRate = 0;
-int AudioSystem::gOutFrameCount = 0;
-uint32_t AudioSystem::gOutLatency = 0;
+int AudioSystem::gOutSamplingRate[NUM_AUDIO_OUTPUT_TYPES];
+int AudioSystem::gOutFrameCount[NUM_AUDIO_OUTPUT_TYPES];
+uint32_t AudioSystem::gOutLatency[NUM_AUDIO_OUTPUT_TYPES];
+bool AudioSystem::gA2dpEnabled;
+// Cached values for recording queries
+uint32_t AudioSystem::gPrevInSamplingRate = 16000;
+int AudioSystem::gPrevInFormat = AudioSystem::PCM_16_BIT;
+int AudioSystem::gPrevInChannelCount = 1;
+size_t AudioSystem::gInBuffSize = 0;
 
 
 // establish binder interface to AudioFlinger service
@@ -48,19 +55,23 @@
             LOGW("AudioFlinger not published, waiting...");
             usleep(500000); // 0.5 s
         } while(true);
-        if (gDeathNotifier == NULL) {
-            gDeathNotifier = new DeathNotifier();
+        if (gAudioFlingerClient == NULL) {
+            gAudioFlingerClient = new AudioFlingerClient();
         } else {
             if (gAudioErrorCallback) {
                 gAudioErrorCallback(NO_ERROR);
             }
          }
-        binder->linkToDeath(gDeathNotifier);
+        binder->linkToDeath(gAudioFlingerClient);
         gAudioFlinger = interface_cast<IAudioFlinger>(binder);
+        gAudioFlinger->registerClient(gAudioFlingerClient);
         // Cache frequently accessed parameters 
-        gOutFrameCount = (int)gAudioFlinger->frameCount();
-        gOutSamplingRate = (int)gAudioFlinger->sampleRate();
-        gOutLatency = gAudioFlinger->latency();
+        for (int output = 0; output < NUM_AUDIO_OUTPUT_TYPES; output++) {
+            gOutFrameCount[output] = (int)gAudioFlinger->frameCount(output);
+            gOutSamplingRate[output] = (int)gAudioFlinger->sampleRate(output);
+            gOutLatency[output] = gAudioFlinger->latency(output);
+        }
+        gA2dpEnabled = gAudioFlinger->isA2dpEnabled();
     }
     LOGE_IF(gAudioFlinger==0, "no AudioFlinger!?");
     return gAudioFlinger;
@@ -139,7 +150,7 @@
 
 status_t AudioSystem::setStreamVolume(int stream, float value)
 {
-    if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE;
+    if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE;
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
     af->setStreamVolume(stream, value);
@@ -148,7 +159,7 @@
 
 status_t AudioSystem::setStreamMute(int stream, bool mute)
 {
-    if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE;
+    if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE;
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
     af->setStreamMute(stream, mute);
@@ -157,7 +168,7 @@
 
 status_t AudioSystem::getStreamVolume(int stream, float* volume)
 {
-    if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE;
+    if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE;
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
     *volume = af->streamVolume(stream);
@@ -166,7 +177,7 @@
 
 status_t AudioSystem::getStreamMute(int stream, bool* mute)
 {
-    if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE;
+    if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE;
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
     *mute = af->streamMute(stream);
@@ -244,60 +255,129 @@
     return volume ? 100 - int(dBConvertInverse * log(volume) + 0.5) : 0;
 }
 
-status_t AudioSystem::getOutputSamplingRate(int* samplingRate)
+status_t AudioSystem::getOutputSamplingRate(int* samplingRate, int streamType)
 {
-    if (gOutSamplingRate == 0) {
-        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
-        if (af == 0) return PERMISSION_DENIED;
-        // gOutSamplingRate is updated by get_audio_flinger()
-    }    
-    *samplingRate = gOutSamplingRate;
-    
-    return NO_ERROR;
-}
+    int output = getOutput(streamType);
 
-status_t AudioSystem::getOutputFrameCount(int* frameCount)
-{
-    if (gOutFrameCount == 0) {
+    if (gOutSamplingRate[output] == 0) {
         const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
         if (af == 0) return PERMISSION_DENIED;
         // gOutSamplingRate is updated by get_audio_flinger()
     }
-    *frameCount = gOutFrameCount;
+    LOGV("getOutputSamplingRate() streamType %d, output %d, sampling rate %d", streamType, output, gOutSamplingRate[output]);
+    *samplingRate = gOutSamplingRate[output];
+    
     return NO_ERROR;
 }
 
-status_t AudioSystem::getOutputLatency(uint32_t* latency)
+status_t AudioSystem::getOutputFrameCount(int* frameCount, int streamType)
 {
-    if (gOutLatency == 0) {
+    int output = getOutput(streamType);
+
+    if (gOutFrameCount[output] == 0) {
+        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+        if (af == 0) return PERMISSION_DENIED;
+        // gOutFrameCount is updated by get_audio_flinger()
+    }
+    LOGV("getOutputFrameCount() streamType %d, output %d, frame count %d", streamType, output, gOutFrameCount[output]);
+
+    *frameCount = gOutFrameCount[output];
+    return NO_ERROR;
+}
+
+status_t AudioSystem::getOutputLatency(uint32_t* latency, int streamType)
+{
+    int output = getOutput(streamType);
+
+    if (gOutLatency[output] == 0) {
         const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
         if (af == 0) return PERMISSION_DENIED;
         // gOutLatency is updated by get_audio_flinger()
-    }    
-    *latency = gOutLatency;
+    }
+    LOGV("getOutputLatency() streamType %d, output %d, latency %d", streamType, output, gOutLatency[output]);
+
+    *latency = gOutLatency[output];
+    
+    return NO_ERROR;
+}
+
+status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, int format, int channelCount, 
+    size_t* buffSize)
+{
+    // Do we have a stale gInBufferSize or are we requesting the input buffer size for new values
+    if ((gInBuffSize == 0) || (sampleRate != gPrevInSamplingRate) || (format != gPrevInFormat) 
+        || (channelCount != gPrevInChannelCount)) {
+        // save the request params
+        gPrevInSamplingRate = sampleRate;
+        gPrevInFormat = format; 
+        gPrevInChannelCount = channelCount;
+
+        gInBuffSize = 0;
+        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+        if (af == 0) {
+            return PERMISSION_DENIED;
+        }
+        gInBuffSize = af->getInputBufferSize(sampleRate, format, channelCount);
+    } 
+    *buffSize = gInBuffSize;
     
     return NO_ERROR;
 }
 
 // ---------------------------------------------------------------------------
 
-void AudioSystem::DeathNotifier::binderDied(const wp<IBinder>& who) {
+void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) {   
     Mutex::Autolock _l(AudioSystem::gLock);
     AudioSystem::gAudioFlinger.clear();
-    AudioSystem::gOutSamplingRate = 0;
-    AudioSystem::gOutFrameCount = 0;
-    AudioSystem::gOutLatency = 0;
-    
+
+    for (int output = 0; output < NUM_AUDIO_OUTPUT_TYPES; output++) {
+        gOutFrameCount[output] = 0;
+        gOutSamplingRate[output] = 0;
+        gOutLatency[output] = 0;
+    }
+    AudioSystem::gInBuffSize = 0;
+
     if (gAudioErrorCallback) {
         gAudioErrorCallback(DEAD_OBJECT);
     }
     LOGW("AudioFlinger server died!");
 }
 
+void AudioSystem::AudioFlingerClient::a2dpEnabledChanged(bool enabled) {
+    gA2dpEnabled = enabled;        
+    LOGV("AudioFlinger A2DP enabled status changed! %d", enabled);
+}
+
 void AudioSystem::setErrorCallback(audio_error_callback cb) {
     Mutex::Autolock _l(AudioSystem::gLock);
     gAudioErrorCallback = cb;
 }
 
+int AudioSystem::getOutput(int streamType)
+{  
+    if (streamType == DEFAULT) {
+        streamType = MUSIC;
+    }
+    if (gA2dpEnabled && routedToA2dpOutput(streamType)) {
+        return AUDIO_OUTPUT_A2DP;
+    } else {
+        return AUDIO_OUTPUT_HARDWARE;
+    }
+}
+
+bool AudioSystem::routedToA2dpOutput(int streamType) {
+    switch(streamType) {
+    case MUSIC:
+    case VOICE_CALL:
+    case BLUETOOTH_SCO:
+    case SYSTEM:
+        return true;
+    default:
+        return false;
+    }
+}
+
+
+
 }; // namespace android
 
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index f9f8568..d26b0c5 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -128,22 +128,21 @@
        return NO_INIT;
     }
     int afSampleRate;
-    if (AudioSystem::getOutputSamplingRate(&afSampleRate) != NO_ERROR) {
+    if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
         return NO_INIT;
     }
     int afFrameCount;
-    if (AudioSystem::getOutputFrameCount(&afFrameCount) != NO_ERROR) {
+    if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
         return NO_INIT;
     }
     uint32_t afLatency;
-    if (AudioSystem::getOutputLatency(&afLatency) != NO_ERROR) {
+    if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) {
         return NO_INIT;
     }
 
-
     // handle default values first.
-    if (streamType == DEFAULT) {
-        streamType = MUSIC;
+    if (streamType == AudioSystem::DEFAULT) {
+        streamType = AudioSystem::MUSIC;
     }
     if (sampleRate == 0) {
         sampleRate = afSampleRate;
@@ -157,7 +156,7 @@
     }
 
     // validate parameters
-    if (((format != AudioSystem::PCM_8_BIT) || mSharedBuffer != 0) &&
+    if (((format != AudioSystem::PCM_8_BIT) || sharedBuffer != 0) &&
         (format != AudioSystem::PCM_16_BIT)) {
         LOGE("Invalid format");
         return BAD_VALUE;
@@ -169,6 +168,8 @@
 
     // Ensure that buffer depth covers at least audio hardware latency
     uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
+    if (minBufCount < 2) minBufCount = 2;
+
     // When playing from shared buffer, playback will start even if last audioflinger
     // block is partly filled.
     if (sharedBuffer != 0 && minBufCount > 1) {
@@ -260,7 +261,7 @@
     mMarkerPosition = 0;
     mNewPosition = 0;
     mUpdatePeriod = 0;
-    
+
     return NO_ERROR;
 }
 
@@ -317,7 +318,7 @@
 {
     sp<AudioTrackThread> t = mAudioTrackThread;
 
-    LOGV("start");
+    LOGV("start %p", this);
     if (t != 0) {
         if (t->exitPending()) {
             if (t->requestExitAndWait() == WOULD_BLOCK) {
@@ -349,7 +350,7 @@
 {
     sp<AudioTrackThread> t = mAudioTrackThread;
 
-    LOGV("stop");
+    LOGV("stop %p", this);
     if (t != 0) {
         t->mLock.lock();
     }
@@ -434,12 +435,12 @@
 {
     int afSamplingRate;
 
-    if (AudioSystem::getOutputSamplingRate(&afSamplingRate) != NO_ERROR) {
+    if (AudioSystem::getOutputSamplingRate(&afSamplingRate, mStreamType) != NO_ERROR) {
         return;
     }
     // Resampler implementation limits input sampling rate to 2 x output sampling rate.
+    if (rate <= 0) rate = 1;
     if (rate > afSamplingRate*2) rate = afSamplingRate*2;
-
     if (rate > MAX_SAMPLE_RATE) rate = MAX_SAMPLE_RATE;
 
     mCblk->sampleRate = rate;
@@ -467,10 +468,15 @@
 
     if (loopStart >= loopEnd ||
         loopEnd - loopStart > mFrameCount) {
-        LOGW("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, mFrameCount, cblk->user);
+        LOGE("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, mFrameCount, cblk->user);
         return BAD_VALUE;
     }
-    // TODO handle shared buffer here: limit loop end to framecount
+
+    if ((mSharedBuffer != 0) && (loopEnd   > mFrameCount)) {
+        LOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, framecount %d",
+            loopStart, loopEnd, mFrameCount);
+        return BAD_VALUE;
+    }   
 
     cblk->loopStart = loopStart;
     cblk->loopEnd = loopEnd;
@@ -603,13 +609,20 @@
             if (__builtin_expect(result!=NO_ERROR, false)) { 
                 cblk->waitTimeMs += WAIT_PERIOD_MS;
                 if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
-                    LOGW(   "obtainBuffer timed out (is the CPU pegged?) "
-                            "user=%08x, server=%08x", cblk->user, cblk->server);
-                    mAudioTrack->start(); // FIXME: Wake up audioflinger
-                    timeout = 1;
+                    // timing out when a loop has been set and we have already written upto loop end
+                    // is a normal condition: no need to wake AudioFlinger up.
+                    if (cblk->user < cblk->loopEnd) {
+                        LOGW(   "obtainBuffer timed out (is the CPU pegged?) %p "
+                                "user=%08x, server=%08x", this, cblk->user, cblk->server);
+                        //unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140) 
+                        cblk->lock.unlock();
+                        mAudioTrack->start();
+                        cblk->lock.lock();
+                        timeout = 1;
+                    }
                     cblk->waitTimeMs = 0;
                 }
-                ;
+                
                 if (--waitCount == 0) {
                     return TIMED_OUT;
                 }
@@ -668,7 +681,7 @@
         return BAD_VALUE;
     }
 
-    LOGV("write %d bytes, mActive=%d", userSize, mActive);
+    LOGV("write %p: %d bytes, mActive=%d", this, userSize, mActive);
 
     ssize_t written = 0;
     const int8_t *src = (const int8_t *)buffer;
@@ -795,7 +808,14 @@
         writtenSize = audioBuffer.size;
 
         // Sanity check on returned size
-        if (ssize_t(writtenSize) <= 0) break;
+        if (ssize_t(writtenSize) <= 0) {
+            // The callback is done filling buffers
+            // Keep this thread going to handle timed events and
+            // still try to get more data in intervals of WAIT_PERIOD_MS
+            // but don't just loop and block the CPU, so wait
+            usleep(WAIT_PERIOD_MS*1000);
+            break;
+        }
         if (writtenSize > reqSize) writtenSize = reqSize;
 
         if (mFormat == AudioSystem::PCM_8_BIT) {
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 018ea6c..5cbb25c 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -51,6 +51,10 @@
     GET_MIC_MUTE,
     IS_MUSIC_ACTIVE,
     SET_PARAMETER,
+    REGISTER_CLIENT,
+    GET_INPUTBUFFERSIZE,
+    WAKE_UP,
+    IS_A2DP_ENABLED
 };
 
 class BpAudioFlinger : public BpInterface<IAudioFlinger>
@@ -120,42 +124,47 @@
         return interface_cast<IAudioRecord>(reply.readStrongBinder());
     }
 
-    virtual uint32_t sampleRate() const
+    virtual uint32_t sampleRate(int output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(output);
         remote()->transact(SAMPLE_RATE, data, &reply);
         return reply.readInt32();
     }
 
-    virtual int channelCount() const
+    virtual int channelCount(int output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(output);
         remote()->transact(CHANNEL_COUNT, data, &reply);
         return reply.readInt32();
     }
 
-    virtual int format() const
+    virtual int format(int output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(output);
         remote()->transact(FORMAT, data, &reply);
         return reply.readInt32();
     }
 
-    virtual size_t frameCount() const
+    virtual size_t frameCount(int output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(output);
         remote()->transact(FRAME_COUNT, data, &reply);
         return reply.readInt32();
     }
 
-    virtual uint32_t latency() const
+    virtual uint32_t latency(int output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(output);
         remote()->transact(LATENCY, data, &reply);
         return reply.readInt32();
     }
@@ -303,6 +312,41 @@
         remote()->transact(SET_PARAMETER, data, &reply);
         return reply.readInt32();
     }
+    
+    virtual void registerClient(const sp<IAudioFlingerClient>& client)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeStrongBinder(client->asBinder());
+        remote()->transact(REGISTER_CLIENT, data, &reply);
+    }
+    
+    virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(sampleRate);
+        data.writeInt32(format);
+        data.writeInt32(channelCount);
+        remote()->transact(GET_INPUTBUFFERSIZE, data, &reply);
+        return reply.readInt32();
+    }
+    
+    virtual void wakeUp()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        remote()->transact(WAKE_UP, data, &reply);
+        return;
+    }
+
+    virtual bool isA2dpEnabled() const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        remote()->transact(IS_A2DP_ENABLED, data, &reply);
+        return (bool)reply.readInt32();
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
@@ -355,27 +399,32 @@
         } break;
         case SAMPLE_RATE: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( sampleRate() );
+            int output = data.readInt32();
+            reply->writeInt32( sampleRate(output) );
             return NO_ERROR;
         } break;
         case CHANNEL_COUNT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( channelCount() );
+            int output = data.readInt32();
+            reply->writeInt32( channelCount(output) );
             return NO_ERROR;
         } break;
         case FORMAT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( format() );
+            int output = data.readInt32();
+            reply->writeInt32( format(output) );
             return NO_ERROR;
         } break;
         case FRAME_COUNT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( frameCount() );
+            int output = data.readInt32();
+            reply->writeInt32( frameCount(output) );
             return NO_ERROR;
         } break;
         case LATENCY: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( latency() );
+            int output = data.readInt32();
+            reply->writeInt32( latency(output) );
             return NO_ERROR;
         } break;
          case SET_MASTER_VOLUME: {
@@ -470,6 +519,30 @@
             reply->writeInt32( setParameter(key, value) );
             return NO_ERROR;
         } break;
+        case REGISTER_CLIENT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient>(data.readStrongBinder());
+            registerClient(client);
+            return NO_ERROR;
+        } break;
+        case GET_INPUTBUFFERSIZE: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            uint32_t sampleRate = data.readInt32();
+            int format = data.readInt32();
+            int channelCount = data.readInt32();
+            reply->writeInt32( getInputBufferSize(sampleRate, format, channelCount) );
+            return NO_ERROR;
+        } break;
+        case WAKE_UP: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            wakeUp();
+            return NO_ERROR;
+        } break;
+        case IS_A2DP_ENABLED: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            reply->writeInt32( (int)isA2dpEnabled() );
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp
new file mode 100644
index 0000000..5feb11f
--- /dev/null
+++ b/media/libmedia/IAudioFlingerClient.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "IAudioFlingerClient"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Parcel.h>
+
+#include <media/IAudioFlingerClient.h>
+
+namespace android {
+
+enum {
+    AUDIO_OUTPUT_CHANGED = IBinder::FIRST_CALL_TRANSACTION
+};
+
+class BpAudioFlingerClient : public BpInterface<IAudioFlingerClient>
+{
+public:
+    BpAudioFlingerClient(const sp<IBinder>& impl)
+        : BpInterface<IAudioFlingerClient>(impl)
+    {
+    }
+
+    void a2dpEnabledChanged(bool enabled)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor());
+        data.writeInt32((int)enabled);
+        remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(AudioFlingerClient, "android.media.IAudioFlingerClient");
+
+// ----------------------------------------------------------------------
+
+#define CHECK_INTERFACE(interface, data, reply) \
+        do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
+            LOGW("Call incorrectly routed to " #interface); \
+            return PERMISSION_DENIED; \
+        } } while (0)
+
+status_t BnAudioFlingerClient::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case AUDIO_OUTPUT_CHANGED: {
+            CHECK_INTERFACE(IAudioFlingerClient, data, reply);
+            bool enabled = (bool)data.readInt32();
+            a2dpEnabledChanged(enabled);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 1f6d599..84d08c4 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -21,6 +21,7 @@
 #include <utils/Parcel.h>
 #include <ui/ISurface.h>
 #include <ui/ICamera.h>
+#include <media/IMediaPlayerClient.h>
 #include <media/IMediaRecorder.h>
 
 namespace android {
@@ -39,11 +40,14 @@
     SET_OUTPUT_FORMAT,
     SET_VIDEO_ENCODER,
     SET_AUDIO_ENCODER,
-    SET_OUTPUT_FILE,
+    SET_OUTPUT_FILE_PATH,
+    SET_OUTPUT_FILE_FD,
     SET_VIDEO_SIZE,
     SET_VIDEO_FRAMERATE,
+    SET_PARAMETERS,
     SET_PREVIEW_SURFACE,
-    SET_CAMERA
+    SET_CAMERA,
+    SET_LISTENER
 };
 
 class BpMediaRecorder: public BpInterface<IMediaRecorder>
@@ -139,7 +143,18 @@
         Parcel data, reply;
         data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
         data.writeCString(path);
-        remote()->transact(SET_OUTPUT_FILE, data, &reply);
+        remote()->transact(SET_OUTPUT_FILE_PATH, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setOutputFile(int fd, int64_t offset, int64_t length) {
+        LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length);
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeFileDescriptor(fd);
+        data.writeInt64(offset);
+        data.writeInt64(length);
+        remote()->transact(SET_OUTPUT_FILE_FD, data, &reply);
         return reply.readInt32();
     }
 
@@ -164,6 +179,26 @@
         return reply.readInt32();
     }
 
+    status_t setParameters(const String8& params)
+    {
+        LOGV("setParameter(%s)", params.string());
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeString8(params);
+        remote()->transact(SET_PARAMETERS, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setListener(const sp<IMediaPlayerClient>& listener)
+    {
+        LOGV("setListener(%p)", listener.get());
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeStrongBinder(listener->asBinder());
+        remote()->transact(SET_LISTENER, data, &reply);
+        return reply.readInt32();
+    }
+
     status_t prepare()
     {
         LOGV("prepare");
@@ -330,13 +365,22 @@
             return NO_ERROR;
 
         } break;
-        case SET_OUTPUT_FILE: {
-            LOGV("SET_OUTPUT_FILE");
+        case SET_OUTPUT_FILE_PATH: {
+            LOGV("SET_OUTPUT_FILE_PATH");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
             const char* path = data.readCString();
             reply->writeInt32(setOutputFile(path));
             return NO_ERROR;
         } break;
+        case SET_OUTPUT_FILE_FD: {
+            LOGV("SET_OUTPUT_FILE_FD");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            int fd = dup(data.readFileDescriptor());
+            int64_t offset = data.readInt64();
+            int64_t length = data.readInt64();
+            reply->writeInt32(setOutputFile(fd, offset, length));
+            return NO_ERROR;
+        } break;
         case SET_VIDEO_SIZE: {
             LOGV("SET_VIDEO_SIZE");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
@@ -352,6 +396,20 @@
             reply->writeInt32(setVideoFrameRate(frames_per_second));
             return NO_ERROR;
         } break;
+        case SET_PARAMETERS: {
+            LOGV("SET_PARAMETER");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            reply->writeInt32(setParameters(data.readString8()));
+            return NO_ERROR;
+        } break;
+        case SET_LISTENER: {
+            LOGV("SET_LISTENER");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            sp<IMediaPlayerClient> listener =
+                interface_cast<IMediaPlayerClient>(data.readStrongBinder());
+            reply->writeInt32(setListener(listener));
+            return NO_ERROR;
+        } break;
         case SET_PREVIEW_SURFACE: {
             LOGV("SET_PREVIEW_SURFACE");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp
index f0edf88..2c62104 100644
--- a/media/libmedia/JetPlayer.cpp
+++ b/media/libmedia/JetPlayer.cpp
@@ -86,8 +86,8 @@
         mState = EAS_STATE_ERROR;
         return result;
     }
-    // init the JET library
-    result = JET_Init(mEasData, NULL, 0);
+    // init the JET library with the default app event controller range
+    result = JET_Init(mEasData, NULL, sizeof(S_JET_CONFIG));
     if( result != EAS_SUCCESS) {
         LOGE("JetPlayer::init(): Error initializing JET library, aborting.");
         mState = EAS_STATE_ERROR;
@@ -96,7 +96,7 @@
 
     // create the output AudioTrack
     mAudioTrack = new AudioTrack();
-    mAudioTrack->set(AudioTrack::MUSIC,  //TODO parametrize this
+    mAudioTrack->set(AudioSystem::MUSIC,  //TODO parametrize this
             pLibConfig->sampleRate,
             1, // format = PCM 16bits per sample,
             pLibConfig->numChannels,
@@ -200,6 +200,11 @@
         while (!mRender)
         {
             LOGV("JetPlayer::render(): signal wait");
+            if (audioStarted) { 
+                mAudioTrack->pause(); 
+                // we have to restart the playback once we start rendering again
+                audioStarted = false;
+            }
             mCondition.wait(mMutex);
             LOGV("JetPlayer::render(): signal rx'd");
         }
@@ -214,12 +219,15 @@
             }
             p += count * pLibConfig->numChannels;
             num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM);
+            
+             // send events that were generated (if any) to the event callback
+            fireEventsFromJetQueue();
         }
 
         // update playback state
         //LOGV("JetPlayer::render(): updating state");
         JET_Status(mEasData, &mJetStatus);
-        fireEventOnStatusChange();
+        fireUpdateOnStatusChange();
         mPaused = mJetStatus.paused;
 
         mMutex.unlock(); // UNLOCK ]]]]]]]] -----------------------------------
@@ -261,9 +269,9 @@
 
 
 //-------------------------------------------------------------------------------------------------
-// fire up an event if any of the status fields has changed
+// fire up an update if any of the status fields has changed
 // precondition: mMutex locked
-void JetPlayer::fireEventOnStatusChange()
+void JetPlayer::fireUpdateOnStatusChange()
 {
     if(  (mJetStatus.currentUserID      != mPreviousJetStatus.currentUserID)
        ||(mJetStatus.segmentRepeatCount != mPreviousJetStatus.segmentRepeatCount) ) {
@@ -303,9 +311,31 @@
 
 
 //-------------------------------------------------------------------------------------------------
-int JetPlayer::openFile(const char* path)
+// fire up all the JET events in the JET engine queue (until the queue is empty)
+// precondition: mMutex locked
+void JetPlayer::fireEventsFromJetQueue()
 {
-    LOGV("JetPlayer::openFile(): path=%s", path);
+    if(!mEventCallback) {
+        // no callback, just empty the event queue
+        while (JET_GetEvent(mEasData, NULL, NULL)) { }
+        return;
+    }
+
+    EAS_U32 rawEvent;
+    while (JET_GetEvent(mEasData, &rawEvent, NULL)) {
+        mEventCallback(
+            JetPlayer::JET_EVENT,
+            rawEvent,
+            -1,
+            mJavaJetPlayerRef);
+    }
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::loadFromFile(const char* path)
+{
+    LOGV("JetPlayer::loadFromFile(): path=%s", path);
 
     Mutex::Autolock lock(mMutex);
 
@@ -326,6 +356,29 @@
     return( result );
 }
 
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::loadFromFD(const int fd, const long long offset, const long long length)
+{
+    LOGV("JetPlayer::loadFromFD(): fd=%d offset=%lld length=%lld", fd, offset, length);
+    
+    Mutex::Autolock lock(mMutex);
+
+    mEasJetFileLoc = (EAS_FILE_LOCATOR) malloc(sizeof(EAS_FILE));
+    mEasJetFileLoc->fd = fd;
+    mEasJetFileLoc->offset = offset;
+    mEasJetFileLoc->length = length;
+    mEasJetFileLoc->path = NULL;
+    
+    EAS_RESULT result = JET_OpenFile(mEasData, mEasJetFileLoc);
+    if(result != EAS_SUCCESS)
+        mState = EAS_STATE_ERROR;
+    else
+        mState = EAS_STATE_OPEN;
+    return( result );
+}
+
+
 //-------------------------------------------------------------------------------------------------
 int JetPlayer::closeFile()
 {
@@ -348,7 +401,7 @@
     JET_Status(mEasData, &mJetStatus);
     this->dumpJetStatus(&mJetStatus);
     
-    fireEventOnStatusChange();
+    fireUpdateOnStatusChange();
 
     // wake up render thread
     LOGV("JetPlayer::play(): wakeup render thread");
@@ -368,7 +421,7 @@
 
     JET_Status(mEasData, &mJetStatus);
     this->dumpJetStatus(&mJetStatus);
-    fireEventOnStatusChange();
+    fireUpdateOnStatusChange();
 
 
     return result;
@@ -408,6 +461,14 @@
 }
 
 //-------------------------------------------------------------------------------------------------
+int JetPlayer::clearQueue()
+{
+    LOGV("JetPlayer::clearQueue");
+    Mutex::Autolock lock(mMutex);
+    return JET_Clear_Queue(mEasData);
+}
+
+//-------------------------------------------------------------------------------------------------
 void JetPlayer::dump()
 {
     LOGE("JetPlayer dump: JET file=%s", mEasJetFileLoc->path);
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 584d135..8560593 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -93,11 +93,7 @@
 
     mState = TONE_IDLE;
 
-    if (AudioSystem::getOutputSamplingRate(&mSamplingRate) != NO_ERROR) {
-        LOGE("Unable to marshal AudioFlinger");
-        return;
-    }
-    if (AudioSystem::getOutputFrameCount(&mBufferSize) != NO_ERROR) {
+    if (AudioSystem::getOutputSamplingRate(&mSamplingRate, streamType) != NO_ERROR) {
         LOGE("Unable to marshal AudioFlinger");
         return;
     }
@@ -179,38 +175,42 @@
     if (mState == TONE_INIT) {
         if (prepareWave()) {
             LOGV("Immediate start, time %d\n", (unsigned int)(systemTime()/1000000));
-
+            lResult = true;
             mState = TONE_STARTING;
             mLock.unlock();
             mpAudioTrack->start();
             mLock.lock();
             if (mState == TONE_STARTING) {
-                if (mWaitCbkCond.waitRelative(mLock, seconds(1)) != NO_ERROR) {
-                    LOGE("--- timed out");
+                LOGV("Wait for start callback");
+                status_t lStatus = mWaitCbkCond.waitRelative(mLock, seconds(1));
+                if (lStatus != NO_ERROR) {
+                    LOGE("--- Immediate start timed out, status %d", lStatus);
                     mState = TONE_IDLE;
+                    lResult = false;
                 }
             }
-
-            if (mState == TONE_PLAYING)
-                lResult = true;
+        } else {
+            mState == TONE_IDLE;
         }
     } else {
         LOGV("Delayed start\n");
 
         mState = TONE_RESTARTING;
-        if (mWaitCbkCond.waitRelative(mLock, seconds(1)) == NO_ERROR) {
-            if (mState != TONE_INIT) {
+        status_t lStatus = mWaitCbkCond.waitRelative(mLock, seconds(1));
+        if (lStatus == NO_ERROR) {
+            if (mState != TONE_IDLE) {
                 lResult = true;
             }
             LOGV("cond received");
         } else {
-            LOGE("--- timed out");
+            LOGE("--- Delayed start timed out, status %d", lStatus);
             mState = TONE_IDLE;
         }
     }
     mLock.unlock();
 
-    LOGV("Tone started, time %d\n", (unsigned int)(systemTime()/1000000));
+    LOGV_IF(lResult, "Tone started, time %d\n", (unsigned int)(systemTime()/1000000));
+    LOGW_IF(!lResult, "Tone start failed!!!, time %d\n", (unsigned int)(systemTime()/1000000));
 
     return lResult;
 }
@@ -239,7 +239,7 @@
         if (lStatus == NO_ERROR) {
             LOGV("track stop complete, time %d", (unsigned int)(systemTime()/1000000));
         } else {
-            LOGE("--- timed out");
+            LOGE("--- Stop timed out");
             mState = TONE_IDLE;
             mpAudioTrack->stop();
         }
@@ -275,9 +275,9 @@
         mpAudioTrack = 0;
     }
 
-   // Open audio track in mono, PCM 16bit, default sampling rate, 2 buffers of
+   // Open audio track in mono, PCM 16bit, default sampling rate, default buffer size
     mpAudioTrack
-            = new AudioTrack(mStreamType, 0, AudioSystem::PCM_16_BIT, 1, NUM_PCM_BUFFERS*mBufferSize, 0, audioCallback, this, mBufferSize);
+            = new AudioTrack(mStreamType, 0, AudioSystem::PCM_16_BIT, 1, 0, 0, audioCallback, this, 0);
 
     if (mpAudioTrack == 0) {
         LOGE("AudioTrack allocation failed");
@@ -370,6 +370,8 @@
             break;
         default:
             LOGV("Extra Cbk");
+            // Force loop exit
+            lNumSmp = 0;
             goto audioCallback_EndLoop;
         }
         
@@ -461,8 +463,11 @@
             if (lpToneGen->prepareWave()) {
                 lpToneGen->mState = TONE_STARTING;
             } else {
-                lpToneGen->mState = TONE_INIT;
+                LOGW("Cbk restarting prepareWave() failed\n");
+                lpToneGen->mState = TONE_IDLE;
                 lpToneGen->mpAudioTrack->stop();
+                // Force loop exit
+                lNumSmp = 0;
             }
             lSignal = true;
             break;
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index ebdbda8..6b40412 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -82,7 +82,7 @@
     mListener = NULL;
     mCookie = NULL;
     mDuration = -1;
-    mStreamType = AudioTrack::MUSIC;
+    mStreamType = AudioSystem::MUSIC;
     mCurrentPosition = -1;
     mSeekPosition = -1;
     mCurrentState = MEDIA_PLAYER_IDLE;
@@ -172,7 +172,7 @@
 status_t MediaPlayer::setDataSource(const char *url)
 {
     LOGV("setDataSource(%s)", url);
-    status_t err = UNKNOWN_ERROR;
+    status_t err = BAD_VALUE;
     if (url != NULL) {
         const sp<IMediaPlayerService>& service(getMediaPlayerService());
         if (service != 0) {
@@ -199,7 +199,7 @@
 {
     LOGV("setVideoSurface");
     Mutex::Autolock _l(mLock);
-    if (mPlayer == 0) return UNKNOWN_ERROR;
+    if (mPlayer == 0) return NO_INIT;
     return  mPlayer->setVideoSurface(surface->getISurface());
 }
 
@@ -215,11 +215,15 @@
     return INVALID_OPERATION;
 }
 
+// TODO: In case of error, prepareAsync provides the caller with 2 error codes,
+// one defined in the Android framework and one provided by the implementation
+// that generated the error. The sync version of prepare returns only 1 error
+// code.
 status_t MediaPlayer::prepare()
 {
     LOGV("prepare");
     Mutex::Autolock _l(mLock);
-    if (mPrepareSync) return UNKNOWN_ERROR;
+    if (mPrepareSync) return -EALREADY;
     mPrepareSync = true;
     status_t ret = prepareAsync_l();
     if (ret != NO_ERROR) return ret;
@@ -253,7 +257,6 @@
         status_t ret = mPlayer->start();
         if (ret != NO_ERROR) {
             mCurrentState = MEDIA_PLAYER_STATE_ERROR;
-            ret = UNKNOWN_ERROR;
         } else {
             if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) {
                 LOGV("playback completed immediately following start()");
@@ -275,7 +278,6 @@
         status_t ret = mPlayer->stop();
         if (ret != NO_ERROR) {
             mCurrentState = MEDIA_PLAYER_STATE_ERROR;
-            ret = UNKNOWN_ERROR;
         } else {
             mCurrentState = MEDIA_PLAYER_STOPPED;
         }
@@ -295,7 +297,6 @@
         status_t ret = mPlayer->pause();
         if (ret != NO_ERROR) {
             mCurrentState = MEDIA_PLAYER_STATE_ERROR;
-            ret = UNKNOWN_ERROR;
         } else {
             mCurrentState = MEDIA_PLAYER_PAUSED;
         }
@@ -422,7 +423,6 @@
         if (ret != NO_ERROR) {
             LOGE("reset() failed with return code (%d)", ret);
             mCurrentState = MEDIA_PLAYER_STATE_ERROR;
-            ret = UNKNOWN_ERROR;
         } else {
             mCurrentState = MEDIA_PLAYER_IDLE;
         }
@@ -516,7 +516,9 @@
         }
         break;
     case MEDIA_ERROR:
-        // Always log errors
+        // Always log errors.
+        // ext1: Media framework error code.
+        // ext2: Implementation dependant error code.
         LOGE("error (%d, %d)", ext1, ext2);
         mCurrentState = MEDIA_PLAYER_STATE_ERROR;
         if (mPrepareSync)
@@ -528,6 +530,11 @@
             send = false;
         }
         break;
+    case MEDIA_INFO:
+        // ext1: Media framework error code.
+        // ext2: Implementation dependant error code.
+        LOGW("info/warning (%d, %d)", ext1, ext2);
+        break;
     case MEDIA_SEEK_COMPLETE:
         LOGV("Received seek complete");
         if (mSeekPosition != mCurrentPosition) {
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 6ee4c0d..23b3b9d 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -21,6 +21,7 @@
 #include <ui/Surface.h>
 #include <media/mediarecorder.h>
 #include <utils/IServiceManager.h>
+#include <utils/String8.h>
 #include <media/IMediaPlayerService.h>
 #include <media/IMediaRecorder.h>
 
@@ -42,7 +43,7 @@
     if (OK != ret) {
         LOGV("setCamera failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     return ret;
 }
@@ -58,12 +59,16 @@
         LOGE("setPreviewSurface called in an invalid state(%d)", mCurrentState);
         return INVALID_OPERATION;
     }
+    if (!mIsVideoSourceSet) {
+        LOGE("try to set preview surface without setting the video source first");
+        return INVALID_OPERATION;
+    }
 
     status_t ret = mMediaRecorder->setPreviewSurface(surface->getISurface());
     if (OK != ret) {
         LOGV("setPreviewSurface failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     return ret;
 }
@@ -84,8 +89,16 @@
     if (OK != ret) {
         LOGV("init failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
+
+    ret = mMediaRecorder->setListener(this);
+    if (OK != ret) {
+        LOGV("setListener failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return ret;
+    }
+
     mCurrentState = MEDIA_RECORDER_INITIALIZED;
     return ret;
 }
@@ -117,7 +130,7 @@
     if (OK != ret) {
         LOGV("setVideoSource failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     mIsVideoSourceSet = true;
     return ret;
@@ -150,7 +163,7 @@
     if (OK != ret) {
         LOGV("setAudioSource failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     mIsAudioSourceSet = true;
     return ret;
@@ -167,12 +180,16 @@
         LOGE("setOutputFormat called in an invalid state: %d", mCurrentState);
         return INVALID_OPERATION;
     }
+    if (mIsVideoSourceSet && of >= OUTPUT_FORMAT_RAW_AMR) {
+        LOGE("output format (%d) is meant for audio recording only and incompatible with video recording", of);
+        return INVALID_OPERATION;
+    }
 
     status_t ret = mMediaRecorder->setOutputFormat(of);
     if (OK != ret) {
         LOGE("setOutputFormat failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     mCurrentState = MEDIA_RECORDER_DATASOURCE_CONFIGURED;
     return ret;
@@ -185,6 +202,10 @@
         LOGE("media recorder is not initialized yet");
         return INVALID_OPERATION;
     }
+    if (!mIsVideoSourceSet) {
+        LOGE("try to set the video encoder without setting the video source first");
+        return INVALID_OPERATION;
+    }
     if (mIsVideoEncoderSet) {
         LOGE("video encoder has already been set");
         return INVALID_OPERATION;
@@ -198,7 +219,7 @@
     if (OK != ret) {
         LOGV("setVideoEncoder failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     mIsVideoEncoderSet = true;
     return ret;
@@ -211,6 +232,10 @@
         LOGE("media recorder is not initialized yet");
         return INVALID_OPERATION;
     }
+    if (!mIsAudioSourceSet) {
+        LOGE("try to set the audio encoder without setting the audio source first");
+        return INVALID_OPERATION;
+    }
     if (mIsAudioEncoderSet) {
         LOGE("audio encoder has already been set");
         return INVALID_OPERATION;
@@ -224,7 +249,7 @@
     if (OK != ret) {
         LOGV("setAudioEncoder failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     mIsAudioEncoderSet = true;
     return ret;
@@ -248,9 +273,35 @@
 
     status_t ret = mMediaRecorder->setOutputFile(path);
     if (OK != ret) {
-        LOGV("setAudioEncoder failed: %d", ret);
+        LOGV("setOutputFile failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
+    }
+    mIsOutputFileSet = true;
+    return ret;
+}
+
+status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length)
+{
+    LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length);
+    if(mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    if (mIsOutputFileSet) {
+        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->setOutputFile(fd, offset, length);
+    if (OK != ret) {
+        LOGV("setOutputFile failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return ret;
     }
     mIsOutputFileSet = true;
     return ret;
@@ -267,12 +318,16 @@
         LOGE("setVideoSize called in an invalid state: %d", mCurrentState);
         return INVALID_OPERATION;
     }
+    if (!mIsVideoSourceSet) {
+        LOGE("try to set video size without setting video source first");
+        return INVALID_OPERATION;
+    }
 
     status_t ret = mMediaRecorder->setVideoSize(width, height);
     if (OK != ret) {
         LOGE("setVideoSize failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     return ret;
 }
@@ -288,16 +343,37 @@
         LOGE("setVideoFrameRate called in an invalid state: %d", mCurrentState);
         return INVALID_OPERATION;
     }
+    if (!mIsVideoSourceSet) {
+        LOGE("try to set video frame rate without setting video source first");
+        return INVALID_OPERATION; 
+    }
 
     status_t ret = mMediaRecorder->setVideoFrameRate(frames_per_second);
     if (OK != ret) {
         LOGE("setVideoFrameRate failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     return ret;
 }
 
+status_t MediaRecorder::setParameters(const String8& params) {
+    LOGV("setParameters(%s)", params.string());
+    if(mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->setParameters(params);
+    if (OK != ret) {
+        LOGE("setParameters(%s) failed: %d", params.string(), ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return ret;
+    }
+
+    return ret;
+}
+
 status_t MediaRecorder::prepare()
 {
     LOGV("prepare");
@@ -306,7 +382,24 @@
         return INVALID_OPERATION;
     }
     if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
-        LOGE("setVideoFrameRate called in an invalid state: %d", mCurrentState);
+        LOGE("prepare called in an invalid state: %d", mCurrentState);
+        return INVALID_OPERATION;
+    }
+    if (mIsAudioSourceSet != mIsAudioEncoderSet) {
+        if (mIsAudioSourceSet) {
+            LOGE("audio source is set, but audio encoder is not set");
+        } else {  // must not happen, since setAudioEncoder checks this already
+            LOGE("audio encoder is set, but audio source is not set");
+        }
+        return INVALID_OPERATION;
+    }
+
+    if (mIsVideoSourceSet != mIsVideoEncoderSet) {
+        if (mIsVideoSourceSet) {
+            LOGE("video source is set, but video encoder is not set");
+        } else {  // must not happen, since setVideoEncoder checks this already
+            LOGE("video encoder is set, but video source is not set");
+        }
         return INVALID_OPERATION;
     }
 
@@ -314,7 +407,7 @@
     if (OK != ret) {
         LOGE("prepare failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     mCurrentState = MEDIA_RECORDER_PREPARED;
     return ret;
@@ -328,7 +421,7 @@
         return INVALID_OPERATION;
     }
     if (mCurrentState & MEDIA_RECORDER_ERROR) {
-        LOGE("setVideoFrameRate called in an invalid state: %d", mCurrentState);
+        LOGE("getMaxAmplitude called in an invalid state: %d", mCurrentState);
         return INVALID_OPERATION;
     }
 
@@ -336,7 +429,7 @@
     if (OK != ret) {
         LOGE("getMaxAmplitude failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     return ret;
 }
@@ -357,7 +450,7 @@
     if (OK != ret) {
         LOGE("start failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     mCurrentState = MEDIA_RECORDER_RECORDING;
     return ret;
@@ -379,8 +472,13 @@
     if (OK != ret) {
         LOGE("stop failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
+ 
+    // FIXME:
+    // stop and reset are semantically different.
+    // We treat them the same for now, and will change this in the future.
+    doCleanUp();
     mCurrentState = MEDIA_RECORDER_IDLE;
     return ret;
 }
@@ -447,7 +545,7 @@
     if (OK != ret) {
         LOGE("doReset failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     } else {
         mCurrentState = MEDIA_RECORDER_INITIALIZED;
     }
@@ -512,5 +610,31 @@
     }
 }
 
+status_t MediaRecorder::setListener(const sp<MediaRecorderListener>& listener)
+{
+    LOGV("setListener");
+    Mutex::Autolock _l(mLock);
+    mListener = listener;
+
+    return NO_ERROR;
+}
+
+void MediaRecorder::notify(int msg, int ext1, int ext2)
+{
+    LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
+
+    sp<MediaRecorderListener> listener;
+    mLock.lock();
+    listener = mListener;
+    mLock.unlock();
+
+    if (listener != NULL) {
+        Mutex::Autolock _l(mNotifyLock);
+        LOGV("callback application");
+        listener->notify(msg, ext1, ext2);
+        LOGV("back from callback");
+    }
+}
+
 }; // namespace android
 
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 5383171..40705c6 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -61,113 +61,32 @@
 #undef __KERNEL__
 #endif
 
-/*
-    When USE_SIGBUS_HANDLER is set to 1, a handler for SIGBUS will be
-    installed, which allows us to recover when there is a read error
-    when accessing an mmap'ed file. However, since the kernel folks
-    don't seem to like it when non kernel folks install signal handlers
-    in their own process, this is currently disabled.
-    Without the handler, the process hosting this service will die and
-    then be restarted. This is mostly OK right now because the process is
-    not being shared with any other services, and clients of the service
-    will be notified of its death in their MediaPlayer.onErrorListener
-    callback, assuming they have installed one, and can then attempt to
-    do their own recovery.
-    It does open us up to a DOS attack against the media server, where
-    a malicious application can trivially force the media server to
-    restart continuously.
-*/
-#define USE_SIGBUS_HANDLER 0
-
-// TODO: Temp hack until we can register players
-static const char* MIDI_FILE_EXTS[] =
-{
-        ".mid",
-        ".smf",
-        ".xmf",
-        ".imy",
-        ".rtttl",
-        ".rtx",
-        ".ota"
-};
 
 namespace android {
 
+// TODO: Temp hack until we can register players
+typedef struct {
+    const char *extension;
+    const player_type playertype;
+} extmap;
+extmap FILE_EXTS [] =  {
+        {".mid", SONIVOX_PLAYER},
+        {".midi", SONIVOX_PLAYER},
+        {".smf", SONIVOX_PLAYER},
+        {".xmf", SONIVOX_PLAYER},
+        {".imy", SONIVOX_PLAYER},
+        {".rtttl", SONIVOX_PLAYER},
+        {".rtx", SONIVOX_PLAYER},
+        {".ota", SONIVOX_PLAYER},
+        {".ogg", VORBIS_PLAYER},
+        {".oga", VORBIS_PLAYER},
+};
+
 // TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
 /* static */ const uint32_t MediaPlayerService::AudioOutput::kAudioVideoDelayMs = 96;
 /* static */ int MediaPlayerService::AudioOutput::mMinBufferCount = 4;
 /* static */ bool MediaPlayerService::AudioOutput::mIsOnEmulator = false;
 
-static struct sigaction oldact;
-static pthread_key_t sigbuskey;
-
-static void sigbushandler(int signal, siginfo_t *info, void *context)
-{
-    char *faultaddr = (char*) info->si_addr;
-    LOGE("SIGBUS at %p\n", faultaddr);
-
-    struct mediasigbushandler* h = (struct mediasigbushandler*) pthread_getspecific(sigbuskey);
-
-    if (h) {
-        if (h->len) {
-            if (faultaddr < h->base || faultaddr >= h->base + h->len) {
-                // outside specified range, call old handler
-                if (oldact.sa_flags & SA_SIGINFO) {
-                    oldact.sa_sigaction(signal, info, context);
-                } else {
-                    oldact.sa_handler(signal);
-                }
-                return;
-            }
-        }
-
-        // no range specified or address was in range
-
-        if (h->handlesigbus) {
-            if (h->handlesigbus(info, h)) {
-                // thread's handler didn't handle the signal
-                if (oldact.sa_flags & SA_SIGINFO) {
-                    oldact.sa_sigaction(signal, info, context);
-                } else {
-                    oldact.sa_handler(signal);
-                }
-            }
-            return;
-        }
-
-        if (h->sigbusvar) {
-            // map in a zeroed out page so the operation can succeed
-            long pagesize = sysconf(_SC_PAGE_SIZE);
-            long pagemask = ~(pagesize - 1);
-            void * pageaddr = (void*) (((long)(faultaddr)) & pagemask);
-
-            void * bar = mmap( pageaddr, pagesize, PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED, -1, 0);
-            if (bar == MAP_FAILED) {
-                LOGE("couldn't map zero page at %p: %s", pageaddr, strerror(errno));
-                if (oldact.sa_flags & SA_SIGINFO) {
-                    oldact.sa_sigaction(signal, info, context);
-                } else {
-                    oldact.sa_handler(signal);
-                }
-                return;
-            }
-
-            LOGE("setting sigbusvar at %p", h->sigbusvar);
-            *(h->sigbusvar) = 1;
-            return;
-        }
-    }
-
-    LOGE("SIGBUS: no handler, or improperly configured handler (%p)", h);
-
-    if (oldact.sa_flags & SA_SIGINFO) {
-        oldact.sa_sigaction(signal, info, context);
-    } else {
-        oldact.sa_handler(signal);
-    }
-    return;
-}
-
 void MediaPlayerService::instantiate() {
     defaultServiceManager()->addService(
             String16("media.player"), new MediaPlayerService());
@@ -177,25 +96,10 @@
 {
     LOGV("MediaPlayerService created");
     mNextConnId = 1;
-
-    pthread_key_create(&sigbuskey, NULL);
-
-
-#if USE_SIGBUS_HANDLER
-    struct sigaction act;
-    memset(&act,0, sizeof act);
-    act.sa_sigaction = sigbushandler;
-    act.sa_flags = SA_SIGINFO;
-    sigaction(SIGBUS, &act, &oldact);
-#endif
 }
 
 MediaPlayerService::~MediaPlayerService()
 {
-#if USE_SIGBUS_HANDLER
-    sigaction(SIGBUS, &oldact, NULL);
-#endif
-    pthread_key_delete(sigbuskey);
     LOGV("MediaPlayerService destroyed");
 }
 
@@ -314,6 +218,104 @@
 #endif
 }
 
+#if defined(__arm__)
+extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
+        size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
+extern "C" void free_malloc_leak_info(uint8_t* info);
+
+void memStatus(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    typedef struct {
+        size_t size;
+        size_t dups;
+        intptr_t * backtrace;
+    } AllocEntry;
+
+    uint8_t *info = NULL;
+    size_t overallSize = 0;
+    size_t infoSize = 0;
+    size_t totalMemory = 0;
+    size_t backtraceSize = 0;
+
+    get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize);
+    if (info) {
+        uint8_t *ptr = info;
+        size_t count = overallSize / infoSize;
+
+        snprintf(buffer, SIZE, " Allocation count %i\n", count);
+        result.append(buffer);
+
+        AllocEntry * entries = new AllocEntry[count];
+
+        for (size_t i = 0; i < count; i++) {
+            // Each entry should be size_t, size_t, intptr_t[backtraceSize]
+            AllocEntry *e = &entries[i];
+
+            e->size = *reinterpret_cast<size_t *>(ptr);
+            ptr += sizeof(size_t);
+
+            e->dups = *reinterpret_cast<size_t *>(ptr);
+            ptr += sizeof(size_t);
+
+            e->backtrace = reinterpret_cast<intptr_t *>(ptr);
+            ptr += sizeof(intptr_t) * backtraceSize;
+        }
+
+        // Now we need to sort the entries.  They come sorted by size but
+        // not by stack trace which causes problems using diff.
+        bool moved;
+        do {
+            moved = false;
+            for (size_t i = 0; i < (count - 1); i++) {
+                AllocEntry *e1 = &entries[i];
+                AllocEntry *e2 = &entries[i+1];
+
+                bool swap = e1->size < e2->size;
+                if (e1->size == e2->size) {
+                    for(size_t j = 0; j < backtraceSize; j++) {
+                        if (e1->backtrace[j] == e2->backtrace[j]) {
+                            continue;
+                        }
+                        swap = e1->backtrace[j] < e2->backtrace[j];
+                        break;
+                    }
+                }
+                if (swap) {
+                    AllocEntry t = entries[i];
+                    entries[i] = entries[i+1];
+                    entries[i+1] = t;
+                    moved = true;
+                }
+            }
+        } while (moved);
+
+        for (size_t i = 0; i < count; i++) {
+            AllocEntry *e = &entries[i];
+
+            snprintf(buffer, SIZE, "size %8i, dup %4i", e->size, e->dups);
+            result.append(buffer);
+            for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) {
+                if (ct) {
+                    result.append(", ");
+                }
+                snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]);
+                result.append(buffer);
+            }
+            result.append("\n");
+        }
+
+        delete[] entries;
+        free_malloc_leak_info(info);
+    }
+
+    write(fd, result.string(), result.size());
+}
+#endif
+
 status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
 {
     const size_t SIZE = 256;
@@ -396,6 +398,18 @@
             result.append(buffer);
             result.append("\n");
         }
+
+#if defined(__arm__)
+        bool dumpMem = false;
+        for (size_t i = 0; i < args.size(); i++) {
+            if (args[i] == String16("-m")) {
+                dumpMem = true;
+            }
+        }
+        if (dumpMem) {
+            memStatus(fd, args);
+        }
+#endif
     }
     write(fd, result.string(), result.size());
     return NO_ERROR;
@@ -481,7 +495,7 @@
         locator.offset = offset;
         locator.length = length;
         EAS_HANDLE  eashandle;
-        if (EAS_OpenFile(easdata, &locator, &eashandle, NULL) == EAS_SUCCESS) {
+        if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) {
             EAS_CloseFile(easdata, eashandle);
             EAS_Shutdown(easdata);
             return SONIVOX_PLAYER;
@@ -498,22 +512,16 @@
 
     // use MidiFile for MIDI extensions
     int lenURL = strlen(url);
-    for (int i = 0; i < NELEM(MIDI_FILE_EXTS); ++i) {
-        int len = strlen(MIDI_FILE_EXTS[i]);
+    for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
+        int len = strlen(FILE_EXTS[i].extension);
         int start = lenURL - len;
         if (start > 0) {
-            if (!strncmp(url + start, MIDI_FILE_EXTS[i], len)) {
-                LOGV("Type is MIDI");
-                return SONIVOX_PLAYER;
+            if (!strncmp(url + start, FILE_EXTS[i].extension, len)) {
+                return FILE_EXTS[i].playertype;
             }
         }
     }
 
-    if (strcmp(url + strlen(url) - 4, ".ogg") == 0) {
-        LOGV("Type is Vorbis");
-        return VORBIS_PLAYER;
-    }
-
     // Fall through to PV
     return PV_PLAYER;
 }
@@ -539,7 +547,6 @@
     if (p != NULL) {
         if (p->initCheck() == NO_ERROR) {
             p->setNotifyCallback(cookie, notifyFunc);
-            p->setSigBusHandlerStructTLSKey(sigbuskey);
         } else {
             p.clear();
         }
@@ -921,7 +928,7 @@
 MediaPlayerService::AudioOutput::AudioOutput()
 {
     mTrack = 0;
-    mStreamType = AudioTrack::MUSIC;
+    mStreamType = AudioSystem::MUSIC;
     mLeftVolume = 1.0;
     mRightVolume = 1.0;
     mLatency = 0;
@@ -1003,15 +1010,15 @@
     int afFrameCount;
     int frameCount;
 
-    if (AudioSystem::getOutputFrameCount(&afFrameCount) != NO_ERROR) {
+    if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
         return NO_INIT;
     }
-    if (AudioSystem::getOutputSamplingRate(&afSampleRate) != NO_ERROR) {
+    if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) {
         return NO_INIT;
     }
 
-    frameCount = (sampleRate*afFrameCount)/afSampleRate;
-    AudioTrack *t = new AudioTrack(mStreamType, sampleRate, format, channelCount, frameCount*bufferCount);
+    frameCount = (sampleRate*afFrameCount*bufferCount)/afSampleRate;
+    AudioTrack *t = new AudioTrack(mStreamType, sampleRate, format, channelCount, frameCount);
     if ((t == 0) || (t->initCheck() != NO_ERROR)) {
         LOGE("Unable to create audio track");
         delete t;
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index f326a0e..5d1887d 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -121,6 +121,17 @@
     return mRecorder->setOutputFile(path);
 }
 
+status_t MediaRecorderClient::setOutputFile(int fd, int64_t offset, int64_t length)
+{
+    LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setOutputFile(fd, offset, length);
+}
+
 status_t MediaRecorderClient::setVideoSize(int width, int height)
 {
     LOGV("setVideoSize(%dx%d)", width, height);
@@ -143,6 +154,16 @@
     return mRecorder->setVideoFrameRate(frames_per_second);
 }
 
+status_t MediaRecorderClient::setParameters(const String8& params) {
+    LOGV("setParameters(%s)", params.string());
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setParameters(params);
+}
+
 status_t MediaRecorderClient::prepare()
 {
     LOGV("prepare");
@@ -247,5 +268,16 @@
     release();
 }
 
+status_t MediaRecorderClient::setListener(const sp<IMediaPlayerClient>& listener)
+{
+    LOGV("setListener");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setListener(listener);
+}
+
 }; // namespace android
 
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 3158017..6a1c2d5 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -36,8 +36,11 @@
     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<IMediaPlayerClient>& listener);
     virtual     status_t        prepare();
     virtual     status_t        getMaxAmplitude(int* max);
     virtual     status_t        start();
diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp
index cfad66c..d03caa5 100644
--- a/media/libmediaplayerservice/MidiFile.cpp
+++ b/media/libmediaplayerservice/MidiFile.cpp
@@ -40,8 +40,6 @@
 
 // ----------------------------------------------------------------------------
 
-extern pthread_key_t EAS_sigbuskey;
-
 namespace android {
 
 // ----------------------------------------------------------------------------
@@ -60,7 +58,7 @@
 MidiFile::MidiFile() :
     mEasData(NULL), mEasHandle(NULL), mAudioBuffer(NULL),
     mPlayTime(-1), mDuration(-1), mState(EAS_STATE_ERROR),
-    mStreamType(AudioTrack::MUSIC), mLoop(false), mExit(false),
+    mStreamType(AudioSystem::MUSIC), mLoop(false), mExit(false),
     mPaused(false), mRender(false), mTid(-1)
 {
     LOGV("constructor");
@@ -132,7 +130,7 @@
     mFileLocator.fd = -1;
     mFileLocator.offset = 0;
     mFileLocator.length = 0;
-    EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle, &mMemFailedVar);
+    EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle);
     if (result == EAS_SUCCESS) {
         updateState();
     }
@@ -148,12 +146,6 @@
     return NO_ERROR;
 }
 
-status_t MidiFile::setSigBusHandlerStructTLSKey(pthread_key_t key)
-{
-    EAS_sigbuskey = key;
-    return 0;
-}
-
 status_t MidiFile::setDataSource(int fd, int64_t offset, int64_t length)
 {
     LOGV("MidiFile::setDataSource fd=%d", fd);
@@ -168,7 +160,7 @@
     mFileLocator.fd = dup(fd);
     mFileLocator.offset = offset;
     mFileLocator.length = length;
-    EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle, &mMemFailedVar);
+    EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle);
     updateState();
 
     if (result != EAS_SUCCESS) {
@@ -332,7 +324,7 @@
         EAS_HANDLE easHandle = NULL;
         EAS_RESULT result = EAS_Init(&easData);
         if (result == EAS_SUCCESS) {
-            result = EAS_OpenFile(easData, &mFileLocator, &easHandle, NULL);
+            result = EAS_OpenFile(easData, &mFileLocator, &easHandle);
         }
         if (result == EAS_SUCCESS) {
             result = EAS_Prepare(easData, easHandle);
@@ -451,8 +443,6 @@
 
     LOGV("MidiFile::render");
 
-    struct mediasigbushandler sigbushandler;
-
     // allocate render buffer
     mAudioBuffer = new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * NUM_BUFFERS];
     if (!mAudioBuffer) {
@@ -468,10 +458,6 @@
         mCondition.signal();
     }
 
-    sigbushandler.handlesigbus = NULL;
-    sigbushandler.sigbusvar = mMemFailedVar;
-    pthread_setspecific(EAS_sigbuskey, &sigbushandler);
-
     while (1) {
         mMutex.lock();
 
diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h
index 9d2dfdd..302f1cf 100644
--- a/media/libmediaplayerservice/MidiFile.h
+++ b/media/libmediaplayerservice/MidiFile.h
@@ -30,7 +30,6 @@
                         ~MidiFile();
 
     virtual status_t    initCheck();
-    virtual status_t    setSigBusHandlerStructTLSKey(pthread_key_t key);
     virtual status_t    setDataSource(const char* path);
     virtual status_t    setDataSource(int fd, int64_t offset, int64_t length);
     virtual status_t    setVideoSurface(const sp<ISurface>& surface) { return UNKNOWN_ERROR; }
@@ -57,7 +56,6 @@
 
     Mutex               mMutex;
     Condition           mCondition;
-    int*                mMemFailedVar;
     EAS_DATA_HANDLE     mEasData;
     EAS_HANDLE          mEasHandle;
     EAS_PCM*            mAudioBuffer;
diff --git a/media/libmediaplayerservice/VorbisPlayer.cpp b/media/libmediaplayerservice/VorbisPlayer.cpp
index 9a64403..0ad335f 100644
--- a/media/libmediaplayerservice/VorbisPlayer.cpp
+++ b/media/libmediaplayerservice/VorbisPlayer.cpp
@@ -55,7 +55,7 @@
 
 VorbisPlayer::VorbisPlayer() :
     mAudioBuffer(NULL), mPlayTime(-1), mDuration(-1), mState(STATE_ERROR),
-    mStreamType(AudioTrack::MUSIC), mLoop(false), mAndroidLoop(false),
+    mStreamType(AudioSystem::MUSIC), mLoop(false), mAndroidLoop(false),
     mExit(false), mPaused(false), mRender(false), mRenderTid(-1)
 {
     LOGV("constructor\n");
@@ -455,13 +455,15 @@
                     current_section = 0;
                     numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, &current_section);
                 } else {
-                    sendEvent(MEDIA_PLAYBACK_COMPLETE);
                     mAudioSink->stop();
                     audioStarted = false;
                     mRender = false;
                     mPaused = true;
                     int endpos = ov_time_tell(&mVorbisFile);
 
+                    LOGV("send MEDIA_PLAYBACK_COMPLETE");
+                    sendEvent(MEDIA_PLAYBACK_COMPLETE);
+
                     // wait until we're started again
                     LOGV("playback complete - wait for signal");
                     mCondition.wait(mMutex);