auto import from //branches/cupcake/...@130745
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 77676bf..6bd54ba 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -99,23 +99,31 @@
     static status_t getOutputSamplingRate(int* samplingRate);
     static status_t getOutputFrameCount(int* frameCount);
     static status_t getOutputLatency(uint32_t* latency);
+    
+    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 audioOutputChanged(uint32_t frameCount, uint32_t samplingRate, uint32_t latency);
+        
     };
 
-    static sp<DeathNotifier> gDeathNotifier;
+    static sp<AudioFlingerClient> gAudioFlingerClient;
 
-    friend class DeathNotifier;
+    friend class AudioFlingerClient;
 
     static Mutex gLock;
     static sp<IAudioFlinger> gAudioFlinger;
@@ -123,6 +131,13 @@
     static int gOutSamplingRate;
     static int gOutFrameCount;
     static uint32_t gOutLatency;
+    
+    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..5b2bab9 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -51,6 +51,7 @@
         MUSIC           = 3,
         ALARM           = 4,
         NOTIFICATION    = 5,
+        BLUETOOTH_SCO   = 6,
         NUM_STREAM_TYPES
     };
 
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index 69703b2..df601d7 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 {
@@ -107,6 +108,15 @@
     // 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;
 };
 
 
diff --git a/include/media/IAudioFlingerClient.h b/include/media/IAudioFlingerClient.h
new file mode 100644
index 0000000..10c3e0f
--- /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 audioOutputChanged(uint32_t frameCount, uint32_t samplingRate, uint32_t latency) = 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/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/PVPlayer.h b/include/media/PVPlayer.h
index 5f302ed..6d98852 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);
@@ -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/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 3d39181..a987b92 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -128,8 +128,22 @@
         return BAD_VALUE;
     }
 
-    // TODO: Get input frame count from hardware.
-    int minFrameCount = 1024*2;
+    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;
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index a375b55..cf91105 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -15,6 +15,8 @@
  */
 
 #define LOG_TAG "AudioSystem"
+//#define LOG_NDEBUG 0
+
 #include <utils/Log.h>
 #include <utils/IServiceManager.h>
 #include <media/AudioSystem.h>
@@ -26,12 +28,17 @@
 // 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;
+// 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,15 +55,16 @@
             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();
@@ -250,7 +258,7 @@
         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;
@@ -261,7 +269,7 @@
     if (gOutFrameCount == 0) {
         const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
         if (af == 0) return PERMISSION_DENIED;
-        // gOutSamplingRate is updated by get_audio_flinger()
+        // gOutFrameCount is updated by get_audio_flinger()
     }
     *frameCount = gOutFrameCount;
     return NO_ERROR;
@@ -279,14 +287,38 @@
     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;
+    AudioSystem::gInBuffSize = 0;
     
     if (gAudioErrorCallback) {
         gAudioErrorCallback(DEAD_OBJECT);
@@ -294,6 +326,15 @@
     LOGW("AudioFlinger server died!");
 }
 
+void AudioSystem::AudioFlingerClient::audioOutputChanged(uint32_t frameCount, uint32_t samplingRate, uint32_t latency) {
+
+    AudioSystem::gOutFrameCount = frameCount;
+    AudioSystem::gOutSamplingRate = samplingRate;
+    AudioSystem::gOutLatency = latency;
+
+    LOGV("AudioFlinger output changed!");
+}
+
 void AudioSystem::setErrorCallback(audio_error_callback cb) {
     Mutex::Autolock _l(AudioSystem::gLock);
     gAudioErrorCallback = cb;
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index f9f8568..63b2012 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -603,13 +603,17 @@
             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?) "
+                                "user=%08x, server=%08x", cblk->user, cblk->server);
+                        mAudioFlinger->wakeUp();
+                        timeout = 1;
+                    }
                     cblk->waitTimeMs = 0;
                 }
-                ;
+                
                 if (--waitCount == 0) {
                     return TIMED_OUT;
                 }
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 018ea6c..4215820 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -51,6 +51,9 @@
     GET_MIC_MUTE,
     IS_MUSIC_ACTIVE,
     SET_PARAMETER,
+    REGISTER_CLIENT,
+    GET_INPUTBUFFERSIZE,
+    WAKE_UP
 };
 
 class BpAudioFlinger : public BpInterface<IAudioFlinger>
@@ -303,6 +306,33 @@
         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;
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
@@ -470,6 +500,26 @@
             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;
+
         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..d956266
--- /dev/null
+++ b/media/libmedia/IAudioFlingerClient.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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 audioOutputChanged(uint32_t frameCount, uint32_t samplingRate, uint32_t latency)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor());
+        data.writeInt32(frameCount);
+        data.writeInt32(samplingRate);
+        data.writeInt32(latency);
+        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);
+            uint32_t frameCount = data.readInt32();
+            uint32_t samplingRate = data.readInt32();
+            uint32_t latency = data.readInt32();
+            audioOutputChanged(frameCount, samplingRate, latency);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp
index f0edf88..ead24d4 100644
--- a/media/libmedia/JetPlayer.cpp
+++ b/media/libmedia/JetPlayer.cpp
@@ -214,12 +214,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 +264,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 +306,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 +351,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 +396,7 @@
     JET_Status(mEasData, &mJetStatus);
     this->dumpJetStatus(&mJetStatus);
     
-    fireEventOnStatusChange();
+    fireUpdateOnStatusChange();
 
     // wake up render thread
     LOGV("JetPlayer::play(): wakeup render thread");
@@ -368,7 +416,7 @@
 
     JET_Status(mEasData, &mJetStatus);
     this->dumpJetStatus(&mJetStatus);
-    fireEventOnStatusChange();
+    fireUpdateOnStatusChange();
 
 
     return result;
@@ -408,6 +456,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..fa36460 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -97,10 +97,6 @@
         LOGE("Unable to marshal AudioFlinger");
         return;
     }
-    if (AudioSystem::getOutputFrameCount(&mBufferSize) != NO_ERROR) {
-        LOGE("Unable to marshal AudioFlinger");
-        return;
-    }
     mStreamType = streamType;
     mVolume = volume;
     mpAudioTrack = 0;
@@ -275,9 +271,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");
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index ebdbda8..31ff507 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -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());
 }
 
@@ -219,7 +219,7 @@
 {
     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 +253,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 +274,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 +293,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 +419,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;
         }
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 5383171..9e366e2 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");
 }
 
@@ -481,7 +385,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 +402,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 +437,6 @@
     if (p != NULL) {
         if (p->initCheck() == NO_ERROR) {
             p->setNotifyCallback(cookie, notifyFunc);
-            p->setSigBusHandlerStructTLSKey(sigbuskey);
         } else {
             p.clear();
         }
diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp
index cfad66c..7ce2fab 100644
--- a/media/libmediaplayerservice/MidiFile.cpp
+++ b/media/libmediaplayerservice/MidiFile.cpp
@@ -40,8 +40,6 @@
 
 // ----------------------------------------------------------------------------
 
-extern pthread_key_t EAS_sigbuskey;
-
 namespace android {
 
 // ----------------------------------------------------------------------------
@@ -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..009d628 100644
--- a/media/libmediaplayerservice/VorbisPlayer.cpp
+++ b/media/libmediaplayerservice/VorbisPlayer.cpp
@@ -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);