auto import from //branches/cupcake/...@127101
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 71744be..dd585c9 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -275,7 +275,7 @@
             STOPPED = 1
         };
 
-            status_t    obtainBuffer(Buffer* audioBuffer, bool blocking);
+            status_t    obtainBuffer(Buffer* audioBuffer, int32_t waitCount);
             void        releaseBuffer(Buffer* audioBuffer);
 
 
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index f382451..fd62daa 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -358,7 +358,7 @@
             STOPPED = 1
         };
 
-            status_t    obtainBuffer(Buffer* audioBuffer, bool blocking);
+            status_t    obtainBuffer(Buffer* audioBuffer, int32_t waitCount);
             void        releaseBuffer(Buffer* audioBuffer);
 
 
diff --git a/include/media/ToneGenerator.h b/include/media/ToneGenerator.h
index 0ddfb8e..0cfdeec 100644
--- a/include/media/ToneGenerator.h
+++ b/include/media/ToneGenerator.h
@@ -134,7 +134,7 @@
     Condition mWaitCbkCond; // condition enabling interface to wait for audio callback completion after a change is requested
     float mVolume;  // Volume applied to audio track
     int mStreamType; // Audio stream used for output
-    int mProcessSize;  // Size of audio blocks generated at a time by audioCallback() (in PCM frames).
+    unsigned int mProcessSize;  // Size of audio blocks generated at a time by audioCallback() (in PCM frames).
 
     bool initAudioTrack();
     static void audioCallback(int event, void* user, void *info);
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 72ed281..1991aa7 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -28,6 +28,11 @@
 
 #define MAX_SAMPLE_RATE     65535
 #define THREAD_PRIORITY_AUDIO_CLIENT (ANDROID_PRIORITY_AUDIO)
+// Maximum cumulated timeout milliseconds before restarting audioflinger thread
+#define MAX_STARTUP_TIMEOUT_MS  3000    // Longer timeout period at startup to cope with A2DP init time
+#define MAX_RUN_TIMEOUT_MS      1000
+#define WAIT_PERIOD_MS          10
+
 
 struct audio_track_cblk_t
 {
@@ -55,9 +60,11 @@
                 int16_t     flowControlFlag; // underrun (out) or overrrun (in) indication
                 uint8_t     out;        // out equals 1 for AudioTrack and 0 for AudioRecord
                 uint8_t     forceReady; 
+                uint16_t    bufferTimeoutMs; // Maximum cumulated timeout before restarting audioflinger
+                uint16_t    waitTimeMs;      // Cumulated wait time
                 // Padding ensuring that data buffer starts on a cache line boundary (32 bytes). 
                 // See AudioFlinger::TrackBase constructor
-                int32_t     Padding[4];
+                int32_t     Padding[3];
                 
                             audio_track_cblk_t();
                 uint32_t    stepUser(uint32_t frameCount);
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index bbb9548..3d39181 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -245,6 +245,8 @@
 
     if (android_atomic_or(1, &mActive) == 0) {
         mNewPosition = mCblk->user + mUpdatePeriod;
+        mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+        mCblk->waitTimeMs = 0;
         if (t != 0) {
            t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
         } else {
@@ -342,7 +344,7 @@
 
 // -------------------------------------------------------------------------
 
-status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, bool blocking)
+status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
 {
     int active;
     int timeout = 0;
@@ -362,14 +364,21 @@
             active = mActive;
             if (UNLIKELY(!active))
                 return NO_MORE_BUFFERS;
-            if (UNLIKELY(!blocking))
+            if (UNLIKELY(!waitCount))
                 return WOULD_BLOCK;
             timeout = 0;
-            result = cblk->cv.waitRelative(cblk->lock, seconds(1));
+            result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS));
             if (__builtin_expect(result!=NO_ERROR, false)) {
-                LOGW(   "obtainBuffer timed out (is the CPU pegged?) "
-                        "user=%08x, server=%08x", cblk->user, cblk->server);
-                timeout = 1;
+                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);
+                    timeout = 1;
+                    cblk->waitTimeMs = 0;
+                }
+                if (--waitCount == 0) {
+                    return TIMED_OUT;
+                }
             }
             // read the server count again
         start_loop_here:
@@ -382,6 +391,8 @@
         "but didn't need to be locked. We recovered, but "
         "this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server);
 
+    cblk->waitTimeMs = 0;
+    
     if (framesReq > framesReady) {
         framesReq = framesReady;
     }
@@ -430,7 +441,9 @@
 
         audioBuffer.frameCount = userSize/mChannelCount/sizeof(int16_t);
 
-        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))
@@ -457,7 +470,7 @@
 {
     Buffer audioBuffer;
     uint32_t frames = mRemainingFrames;
-    size_t readSize = 0;
+    size_t readSize;
 
     // Manage marker callback
     if (mMarkerPosition > 0) {
@@ -477,17 +490,19 @@
 
     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).
+        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;
-
         size_t reqSize = audioBuffer.size;
         mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
         readSize = audioBuffer.size;
@@ -514,13 +529,6 @@
         }
     }
 
-    // If no data was read, it is likely that obtainBuffer() did
-    // not find available data in PCM buffer: we release the processor for
-    // a few millisecond before polling again for available data.
-    if (readSize == 0) {
-        usleep(5000);
-    } 
-
     if (frames == 0) {
         mRemainingFrames = mNotificationFrames;
     } else {
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) {