Merge "Stop metadata retriever from dereferencing a NULL pointer if"
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 3b6c64d..7509239 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -1182,16 +1182,33 @@
                                false);
 
         if (result == NO_ERROR) {
+            uint32_t user = cblk->user;
+            uint32_t server = cblk->server;
             // restore write index and set other indexes to reflect empty buffer status
-            mCblk->user = cblk->user;
-            mCblk->server = cblk->user;
-            mCblk->userBase = cblk->user;
-            mCblk->serverBase = cblk->user;
+            mCblk->user = user;
+            mCblk->server = user;
+            mCblk->userBase = user;
+            mCblk->serverBase = user;
             // restore loop: this is not guaranteed to succeed if new frame count is not
             // compatible with loop length
             setLoop_l(cblk->loopStart, cblk->loopEnd, cblk->loopCount);
             if (!fromStart) {
                 mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+                // Make sure that a client relying on callback events indicating underrun or
+                // the actual amount of audio frames played (e.g SoundPool) receives them.
+                if (mSharedBuffer == 0) {
+                    uint32_t frames = 0;
+                    if (user > server) {
+                        frames = ((user - server) > mCblk->frameCount) ?
+                                mCblk->frameCount : (user - server);
+                        memset(mCblk->buffers, 0, frames * mCblk->frameSize);
+                    }
+                    // restart playback even if buffer is not completely filled.
+                    android_atomic_or(CBLK_FORCEREADY_ON, &mCblk->flags);
+                    // stepUser() clears CBLK_UNDERRUN_ON flag enabling underrun callbacks to
+                    // the client
+                    mCblk->stepUser(frames);
+                }
             }
             if (mActive) {
                 result = mAudioTrack->start();
diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp
index 09f91f5..92e84c2 100644
--- a/media/libstagefright/MP3Extractor.cpp
+++ b/media/libstagefright/MP3Extractor.cpp
@@ -52,10 +52,7 @@
         *post_id3_pos = 0;
     }
 
-    bool resync_from_head = false;
     if (*inout_pos == 0) {
-        resync_from_head = true;
-
         // Skip an optional ID3 header if syncing at the very beginning
         // of the datasource.
 
@@ -140,20 +137,22 @@
 
         uint32_t header = U32_AT(tmp);
 
+        if (match_header != 0 && (header & kMask) != (match_header & kMask)) {
+            ++pos;
+            ++tmp;
+            --remainingBytes;
+            continue;
+        }
+
         size_t frame_size;
-        if ((match_header != 0 && (header & kMask) != (match_header & kMask))
-                || !GetMPEGAudioFrameSize(header, &frame_size)) {
-            if (resync_from_head) {
-                // This isn't a valid mp3 file because it failed to detect
-                // a header while a valid mp3 file should have a valid
-                // header here.
-                break;
-            } else {
-                ++pos;
-                ++tmp;
-                --remainingBytes;
-                continue;
-            }
+        int sample_rate, num_channels, bitrate;
+        if (!GetMPEGAudioFrameSize(
+                    header, &frame_size,
+                    &sample_rate, &num_channels, &bitrate)) {
+            ++pos;
+            ++tmp;
+            --remainingBytes;
+            continue;
         }
 
         LOGV("found possible 1st frame at %lld (header = 0x%08x)", pos, header);