auto import from //branches/cupcake/...@127101
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index ce65312..f9f8568 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -330,6 +330,8 @@
 
     if (android_atomic_or(1, &mActive) == 0) {
         mNewPosition = mCblk->server + mUpdatePeriod;
+        mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
+        mCblk->waitTimeMs = 0;
         if (t != 0) {
            t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
         } else {
@@ -572,7 +574,7 @@
 
 // -------------------------------------------------------------------------
 
-status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, bool blocking)
+status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
 {
     int active;
     int timeout = 0;
@@ -594,15 +596,23 @@
                 LOGV("Not active and NO_MORE_BUFFERS");
                 return NO_MORE_BUFFERS;
             }
-            if (UNLIKELY(!blocking))
+            if (UNLIKELY(!waitCount))
                 return WOULD_BLOCK;
             timeout = 0;
-            result = cblk->cv.waitRelative(cblk->lock, seconds(1));
-            if (__builtin_expect(result!=NO_ERROR, false)) {
-                LOGW(   "obtainBuffer timed out (is the CPU pegged?) "
-                        "user=%08x, server=%08x", cblk->user, cblk->server);
-                mAudioTrack->start(); // FIXME: Wake up audioflinger
-                timeout = 1;
+            result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS));
+            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;
+                    cblk->waitTimeMs = 0;
+                }
+                ;
+                if (--waitCount == 0) {
+                    return TIMED_OUT;
+                }
             }
             // read the server count again
         start_loop_here:
@@ -610,6 +620,8 @@
         }
     }
 
+    cblk->waitTimeMs = 0;
+    
     if (framesReq > framesAvail) {
         framesReq = framesAvail;
     }
@@ -667,8 +679,9 @@
         if (mFormat == AudioSystem::PCM_16_BIT) {
             audioBuffer.frameCount >>= 1;
         }
-
-        status_t err = obtainBuffer(&audioBuffer, true);
+        // Calling obtainBuffer() with a negative wait count causes
+        // an (almost) infinite wait time.
+        status_t err = obtainBuffer(&audioBuffer, -1);
         if (err < 0) {
             // out of buffers, return #bytes written
             if (err == status_t(NO_MORE_BUFFERS))
@@ -706,7 +719,7 @@
 {
     Buffer audioBuffer;
     uint32_t frames;
-    size_t writtenSize = 0;
+    size_t writtenSize;
 
     // Manage underrun callback
     if (mActive && (mCblk->framesReady() == 0)) {
@@ -756,18 +769,20 @@
     do {
 
         audioBuffer.frameCount = frames;
-
-        status_t err = obtainBuffer(&audioBuffer, false);
+        
+        // Calling obtainBuffer() with a wait count of 1 
+        // limits wait time to WAIT_PERIOD_MS. This prevents from being 
+        // stuck here not being able to handle timed events (position, markers, loops). 
+        status_t err = obtainBuffer(&audioBuffer, 1);
         if (err < NO_ERROR) {
-            if (err != WOULD_BLOCK) {
+            if (err != TIMED_OUT) {
                 LOGE("Error obtaining an audio buffer, giving up.");
                 return false;
             }
+            break;
         }
         if (err == status_t(STOPPED)) return false;
 
-        if (audioBuffer.size == 0) break;
-
         // Divide buffer size by 2 to take into account the expansion
         // due to 8 to 16 bit conversion: the callback must fill only half
         // of the destination buffer
@@ -802,13 +817,6 @@
     }
     while (frames);
 
-    // If no data was written, it is likely that obtainBuffer() did
-    // not find room in PCM buffer: we release the processor for
-    // a few millisecond before polling again for available room.
-    if (writtenSize == 0) {
-        usleep(5000);
-    }
-
     if (frames == 0) {
         mRemainingFrames = mNotificationFrames;
     } else {
@@ -872,7 +880,12 @@
 
     u += frameCount;
     // Ensure that user is never ahead of server for AudioRecord
-    if (!out && u > this->server) {
+    if (out) {
+        // If stepServer() has been called once, switch to normal obtainBuffer() timeout period
+        if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS-1) {
+            bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+        }
+    } else if (u > this->server) {
         LOGW("stepServer occured after track reset");
         u = this->server;
     }
@@ -909,13 +922,20 @@
     uint32_t s = this->server;
 
     s += frameCount;
-    // It is possible that we receive a flush()
-    // while the mixer is processing a block: in this case,
-    // stepServer() is called After the flush() has reset u & s and
-    // we have s > u
-    if (out && s > this->user) {
-        LOGW("stepServer occured after track reset");
-        s = this->user;
+    if (out) {
+        // Mark that we have read the first buffer so that next time stepUser() is called
+        // we switch to normal obtainBuffer() timeout period
+        if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) {
+            bufferTimeoutMs = MAX_RUN_TIMEOUT_MS - 1;
+        }        
+        // It is possible that we receive a flush()
+        // while the mixer is processing a block: in this case,
+        // stepServer() is called After the flush() has reset u & s and
+        // we have s > u
+        if (s > this->user) {
+            LOGW("stepServer occured after track reset");
+            s = this->user;
+        }
     }
 
     if (s >= loopEnd) {