auto import from //depot/cupcake/@136594
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 997cd44..316fa7a 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -153,31 +153,23 @@
      */
     private final Object mPlayStateLock = new Object();
     /**
-     * The listener the AudioTrack notifies previously set marker is reached.
-     *  @see #setMarkerReachedListener(OnMarkerReachedListener)
+     * The listener the AudioTrack notifies when the playback position reaches a marker
+     * or for periodic updates during the progression of the playback head.
+     *  @see #setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener)
      */
-    private OnMarkerReachedListener mMarkerListener = null;
+    private OnPlaybackPositionUpdateListener mPositionListener = null;
     /**
-     * Lock to protect marker listener updates against event notifications
+     * Lock to protect event listener updates against event notifications
      */
-    private final Object mMarkerListenerLock = new Object();
-    /**
-     * The listener the AudioTrack notifies periodically during playback.
-     *  @see #setPeriodicNotificationListener(OnPeriodicNotificationListener)
-     */
-    private OnPeriodicNotificationListener mPeriodicListener = null;
-    /**
-     * Lock to protect periodic listener updates against event notifications
-     */
-    private final Object mPeriodicListenerLock = new Object();
+    private final Object mPositionListenerLock = new Object();
     /**
      * Size of the native audio buffer.
      */
     private int mNativeBufferSizeInBytes = 0;
     /**
-     * Handler for events coming from the native code
+     * Handler for marker events coming from the native code
      */
-    private NativeEventHandler mNativeEventHandler = null;
+    private NativeEventHandlerDelegate mEventHandlerDelegate = null;
     /**
      * The audio data sampling rate in Hz.
      */
@@ -373,22 +365,6 @@
     }
 
 
-    // Convenience method for the creation of the native event handler
-    // It is called only when a non-null event listener is set.
-    // precondition:
-    //    mNativeEventHandler is null
-    private void createNativeEventHandler() {
-        Looper looper;
-        if ((looper = Looper.myLooper()) != null) {
-            mNativeEventHandler = new NativeEventHandler(this, looper);
-        } else if ((looper = Looper.getMainLooper()) != null) {
-            mNativeEventHandler = new NativeEventHandler(this, looper);
-        } else {
-            mNativeEventHandler = null;
-        }
-    }
-
-
     /**
      * Releases the native AudioTrack resources.
      */
@@ -592,32 +568,27 @@
     // Initialization / configuration
     //--------------------
     /**
-     * Sets the listener the AudioTrack notifies when a previously set marker is reached.
+     * Sets the listener the AudioTrack notifies when a previously set marker is reached or
+     * for each periodic playback head position update.
      * @param listener
      */
-    public void setMarkerReachedListener(OnMarkerReachedListener listener) {
-        synchronized (mMarkerListenerLock) {
-            mMarkerListener = listener;
+    public void setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener listener) {
+        setPlaybackPositionUpdateListener(listener, null);
+    }
+    
+
+    public void setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener listener, 
+                                                    Handler handler) {
+        synchronized (mPositionListenerLock) {
+            mPositionListener = listener;
         }
-        if ((listener != null) && (mNativeEventHandler == null)) {
-            createNativeEventHandler();
+        if (listener != null) {
+            mEventHandlerDelegate = new NativeEventHandlerDelegate(this, handler);
         }
+        
     }
 
 
-    /**
-     * Sets the listener the AudioTrack notifies periodically during playback.
-     * @param listener
-     */
-    public void setPeriodicNotificationListener(OnPeriodicNotificationListener listener) {
-        synchronized (mPeriodicListenerLock) {
-            mPeriodicListener = listener;
-        }
-        if ((listener != null) && (mNativeEventHandler == null)) {
-            createNativeEventHandler();
-        }
-    }
-
 
      /**
      * Sets the specified left/right output volume values on the AudioTrack. Values are clamped
@@ -895,23 +866,16 @@
     // Interface definitions
     //--------------------
     /**
-     * Interface definition for a callback to be invoked when an AudioTrack has
-     * reached a notification marker set by setNotificationMarkerPosition().
+     * Interface definition for a callback to be invoked when the playback head position of
+     * an AudioTrack has reached a notification marker or has increased by a certain period.
      */
-    public interface OnMarkerReachedListener  {
+    public interface OnPlaybackPositionUpdateListener  {
         /**
          * Called on the listener to notify it that the previously set marker has been reached
          * by the playback head.
          */
         void onMarkerReached(AudioTrack track);
-    }
-
-
-    /**
-     * Interface definition for a callback to be invoked for each periodic AudioTrack
-     * update during playback. The update interval is set by setPositionNotificationPeriod().
-     */
-    public interface OnPeriodicNotificationListener  {
+        
         /**
          * Called on the listener to periodically notify it that the playback head has reached
          * a multiple of the notification period.
@@ -924,42 +888,63 @@
     // Inner classes
     //--------------------
     /**
-     * Helper class to handle the forwarding of native events to the appropriate listeners
-     */
-    private class NativeEventHandler extends Handler
-    {
-        private AudioTrack mAudioTrack;
-
-        public NativeEventHandler(AudioTrack mp, Looper looper) {
-            super(looper);
-            mAudioTrack = mp;
+     * Helper class to handle the forwarding of native events to the appropriate listener
+     * (potentially) handled in a different thread
+     */  
+    private class NativeEventHandlerDelegate {
+        private final AudioTrack mAudioTrack;
+        private final Handler mHandler;
+        
+        NativeEventHandlerDelegate(AudioTrack track, Handler handler) {
+            mAudioTrack = track;
+            // find the looper for our new event handler
+            Looper looper;
+            if (handler != null) {
+                looper = handler.getLooper();
+            } else {
+                // no given handler, look for main looper
+                if ((looper = Looper.myLooper()) == null) {
+                    looper = Looper.getMainLooper();
+                }
+            }
+            // construct the event handler with this looper
+            if (looper != null) {
+                // implement the event handler delegate
+                mHandler = new Handler(looper) {
+                    @Override
+                    public void handleMessage(Message msg) {
+                        if (mAudioTrack == null) {
+                            return;
+                        }
+                        OnPlaybackPositionUpdateListener listener = null;
+                        synchronized (mPositionListenerLock) {
+                            listener = mAudioTrack.mPositionListener;
+                        }
+                        switch(msg.what) {
+                        case NATIVE_EVENT_MARKER:
+                            if (listener != null) {
+                                listener.onMarkerReached(mAudioTrack);
+                            }
+                            break;
+                        case NATIVE_EVENT_NEW_POS:
+                            if (listener != null) {
+                                listener.onPeriodicNotification(mAudioTrack);
+                            }
+                            break;
+                        default:
+                            Log.e(TAG, "[ android.media.AudioTrack.NativeEventHandler ] " +
+                                    "Unknown event type: " + msg.what);
+                            break;
+                        }
+                    }
+                };
+            } else {
+                mHandler = null;
+            } 
         }
-
-        @Override
-        public void handleMessage(Message msg) {
-            if (mAudioTrack == null) {
-                return;
-            }
-            switch(msg.what) {
-            case NATIVE_EVENT_MARKER:
-                synchronized (mMarkerListenerLock) {
-                    if (mAudioTrack.mMarkerListener != null) {
-                        mAudioTrack.mMarkerListener.onMarkerReached(mAudioTrack);
-                    }
-                }
-                break;
-            case NATIVE_EVENT_NEW_POS:
-                synchronized (mPeriodicListenerLock) {
-                    if (mAudioTrack.mPeriodicListener != null) {
-                        mAudioTrack.mPeriodicListener.onPeriodicNotification(mAudioTrack);
-                    }
-                }
-                break;
-            default:
-                Log.e(TAG, "[ android.media.AudioTrack.NativeEventHandler ] " +
-                        "Unknown event type: " + msg.what);
-                break;
-            }
+        
+        Handler getHandler() {
+            return mHandler;
         }
     }
 
@@ -976,9 +961,10 @@
             return;
         }
 
-        if (track.mNativeEventHandler != null) {
-            Message m = track.mNativeEventHandler.obtainMessage(what, arg1, arg2, obj);
-            track.mNativeEventHandler.sendMessage(m);
+        if (track.mEventHandlerDelegate != null) {
+            Message m = 
+                track.mEventHandlerDelegate.getHandler().obtainMessage(what, arg1, arg2, obj);
+            track.mEventHandlerDelegate.getHandler().sendMessage(m);
         }
 
     }
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 5562254..707db02 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -29,6 +29,7 @@
 #include "jni.h"
 #include "JNIHelp.h"
 #include "android_runtime/AndroidRuntime.h"
+#include "utils/Errors.h"  // for status_t
 
 
 // ----------------------------------------------------------------------------
@@ -171,6 +172,7 @@
         jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
         return;
     }
+    LOGV("setDataSource: path %s", pathStr);
     status_t opStatus = mp->setDataSource(pathStr);
 
     // Make sure that local ref is released before a potential exception
@@ -192,6 +194,7 @@
         return;
     }
     int fd = getParcelFileDescriptorFD(env, fileDescriptor);
+    LOGV("setDataSourceFD: fd %d", fd);
     process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." );
 }
 
@@ -207,8 +210,8 @@
     jobject surface = env->GetObjectField(thiz, fields.surface);
     if (surface != NULL) {
         const sp<Surface>& native_surface = get_surface(env, surface);
-        //LOGI("prepare: surface=%p (id=%d)", 
-        //        native_surface.get(), native_surface->ID());
+        LOGV("prepare: surface=%p (id=%d)", 
+             native_surface.get(), native_surface->ID());
         mp->setVideoSurface(native_surface);
     }
     process_media_player_call( env, thiz, mp->prepare(), "java/io/IOException", "Prepare failed." );
@@ -225,8 +228,8 @@
     jobject surface = env->GetObjectField(thiz, fields.surface);
     if (surface != NULL) {
         const sp<Surface>& native_surface = get_surface(env, surface);
-        LOGI("prepareAsync: surface=%p (id=%d)", 
-                native_surface.get(), native_surface->ID());
+        LOGV("prepareAsync: surface=%p (id=%d)", 
+             native_surface.get(), native_surface->ID());
         mp->setVideoSurface(native_surface);
     }
     process_media_player_call( env, thiz, mp->prepareAsync(), "java/io/IOException", "Prepare Async failed." );
@@ -235,6 +238,7 @@
 static void
 android_media_MediaPlayer_start(JNIEnv *env, jobject thiz)
 {
+    LOGV("start");
     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
@@ -246,6 +250,7 @@
 static void
 android_media_MediaPlayer_stop(JNIEnv *env, jobject thiz)
 {
+    LOGV("stop");
     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
@@ -257,6 +262,7 @@
 static void
 android_media_MediaPlayer_pause(JNIEnv *env, jobject thiz)
 {
+    LOGV("pause");
     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
@@ -273,7 +279,10 @@
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
         return false;
     }
-    return mp->isPlaying();
+    const jboolean is_playing = mp->isPlaying();
+
+    LOGV("isPlaying: %d", is_playing);
+    return is_playing;
 }
 
 static void
@@ -284,6 +293,7 @@
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
         return;
     }
+    LOGV("seekTo: %d(msec)", msec);
     process_media_player_call( env, thiz, mp->seekTo(msec), NULL, NULL );
 }
 
@@ -296,9 +306,12 @@
         return 0;
     }
     int w;
-    if (0 == mp->getVideoWidth(&w))
-        return w;
-    return 0;
+    if (0 != mp->getVideoWidth(&w)) {
+        LOGE("getVideoWidth failed");
+        w = 0;
+    }
+    LOGV("getVideoWidth: %d", w);
+    return w;
 }
 
 static int
@@ -310,9 +323,12 @@
         return 0;
     }
     int h;
-    if (0 == mp->getVideoHeight(&h))
-        return h;
-    return 0;
+    if (0 != mp->getVideoHeight(&h)) {
+        LOGE("getVideoHeight failed");
+        h = 0;
+    }
+    LOGV("getVideoHeight: %d", h);
+    return h;
 }
 
 
@@ -326,6 +342,7 @@
     }
     int msec;
     process_media_player_call( env, thiz, mp->getCurrentPosition(&msec), NULL, NULL );
+    LOGV("getCurrentPosition: %d (msec)", msec);
     return msec;
 }
 
@@ -339,12 +356,14 @@
     }
     int msec;
     process_media_player_call( env, thiz, mp->getDuration(&msec), NULL, NULL );
+    LOGV("getDuration: %d (msec)", msec);
     return msec;
 }
 
 static void
 android_media_MediaPlayer_reset(JNIEnv *env, jobject thiz)
 {
+    LOGV("reset");
     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
@@ -356,6 +375,7 @@
 static void
 android_media_MediaPlayer_setAudioStreamType(JNIEnv *env, jobject thiz, int streamtype)
 {
+    LOGV("setAudioStreamType: %d", streamtype);
     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
@@ -367,6 +387,7 @@
 static void
 android_media_MediaPlayer_setLooping(JNIEnv *env, jobject thiz, jboolean looping)
 {
+    LOGV("setLooping: %d", looping);
     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
@@ -378,6 +399,7 @@
 static jboolean
 android_media_MediaPlayer_isLooping(JNIEnv *env, jobject thiz)
 {
+    LOGV("isLooping");
     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
@@ -389,6 +411,7 @@
 static void
 android_media_MediaPlayer_setVolume(JNIEnv *env, jobject thiz, float leftVolume, float rightVolume)
 {
+    LOGV("setVolume: left %f  right %f", leftVolume, rightVolume);
     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
@@ -570,4 +593,3 @@
 }
 
 // KTHXBYE
-
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 44f875c..5f6f754 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -313,6 +313,7 @@
     sp<MediaRecorder> mr = setMediaRecorder(env, thiz, 0);
     if (mr != NULL) {
         mr->setListener(NULL);
+        mr->release();
     }
 }
 
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index e79f336..d26b0c5 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -808,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/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 98aac39..5eba0ef 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -42,7 +42,7 @@
     if (OK != ret) {
         LOGV("setCamera failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     return ret;
 }
@@ -67,7 +67,7 @@
     if (OK != ret) {
         LOGV("setPreviewSurface failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     return ret;
 }
@@ -88,14 +88,14 @@
     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 UNKNOWN_ERROR;
+        return ret;
     }
 
     mCurrentState = MEDIA_RECORDER_INITIALIZED;
@@ -129,7 +129,7 @@
     if (OK != ret) {
         LOGV("setVideoSource failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     mIsVideoSourceSet = true;
     return ret;
@@ -162,7 +162,7 @@
     if (OK != ret) {
         LOGV("setAudioSource failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     mIsAudioSourceSet = true;
     return ret;
@@ -188,7 +188,7 @@
     if (OK != ret) {
         LOGE("setOutputFormat failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     mCurrentState = MEDIA_RECORDER_DATASOURCE_CONFIGURED;
     return ret;
@@ -218,7 +218,7 @@
     if (OK != ret) {
         LOGV("setVideoEncoder failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     mIsVideoEncoderSet = true;
     return ret;
@@ -248,7 +248,7 @@
     if (OK != ret) {
         LOGV("setAudioEncoder failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     mIsAudioEncoderSet = true;
     return ret;
@@ -274,7 +274,7 @@
     if (OK != ret) {
         LOGV("setOutputFile failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     mIsOutputFileSet = true;
     return ret;
@@ -300,7 +300,7 @@
     if (OK != ret) {
         LOGV("setOutputFile failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     mIsOutputFileSet = true;
     return ret;
@@ -326,7 +326,7 @@
     if (OK != ret) {
         LOGE("setVideoSize failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     return ret;
 }
@@ -351,7 +351,7 @@
     if (OK != ret) {
         LOGE("setVideoFrameRate failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     return ret;
 }
@@ -389,7 +389,7 @@
     if (OK != ret) {
         LOGE("prepare failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     mCurrentState = MEDIA_RECORDER_PREPARED;
     return ret;
@@ -411,7 +411,7 @@
     if (OK != ret) {
         LOGE("getMaxAmplitude failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     return ret;
 }
@@ -432,7 +432,7 @@
     if (OK != ret) {
         LOGE("start failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     mCurrentState = MEDIA_RECORDER_RECORDING;
     return ret;
@@ -454,7 +454,7 @@
     if (OK != ret) {
         LOGE("stop failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     }
     mCurrentState = MEDIA_RECORDER_IDLE;
     return ret;
@@ -522,7 +522,7 @@
     if (OK != ret) {
         LOGE("doReset failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
-        return UNKNOWN_ERROR;
+        return ret;
     } else {
         mCurrentState = MEDIA_RECORDER_INITIALIZED;
     }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
index 73688cc..3c449c9 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
@@ -49,7 +49,7 @@
         suite.addTestSuite(MediaMetadataTest.class);
         suite.addTestSuite(CameraTest.class);
         suite.addTestSuite(MediaRecorderTest.class);
-        //suite.addTestSuite(MediaAudioTrackTest.class);
+        suite.addTestSuite(MediaAudioTrackTest.class);
         return suite;
     }
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java
index 59803f7d..c30db38 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java
@@ -100,6 +100,12 @@
      */
     private void terminateMessageLooper() {
         mLooper.quit();
+        //TODO yslau : take out the sleep until bug#1693519 fix
+        try {
+            Thread.sleep(1000);
+        } catch (Exception e){
+            Log.v(TAG, e.toString());
+        }
         mCamera.release();
     }