Merge "MTP: add strict bounds checking for all incoming packets" into lmp-mr1-dev
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index b9a1a6c..b42b480 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -628,6 +628,11 @@
                 if (mLooping || (mAutoLoop
                         && (mAudioSink == NULL || mAudioSink->realtime()))) {
                     mPlayer->seekToAsync(0);
+                    if (mAudioSink != NULL) {
+                        // The renderer has stopped the sink at the end in order to play out
+                        // the last little bit of audio. If we're looping, we need to restart it.
+                        mAudioSink->start();
+                    }
                     break;
                 }
 
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index 821bd81..6219053 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -38,6 +38,7 @@
     int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb);
     int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb);
     int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb);
+    long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op);
 }
 
 namespace android {
@@ -84,6 +85,8 @@
 private:
     struct Page {
         uint64_t mGranulePosition;
+        int32_t mPrevPacketSize;
+        uint64_t mPrevPacketPos;
         uint32_t mSerialNo;
         uint32_t mPageNo;
         uint8_t mFlags;
@@ -121,6 +124,8 @@
     status_t verifyHeader(
             MediaBuffer *buffer, uint8_t type);
 
+    int32_t packetBlockSize(MediaBuffer *buffer);
+
     void parseFileMetaData();
 
     status_t findPrevGranulePosition(off64_t pageOffset, uint64_t *granulePos);
@@ -373,6 +378,7 @@
     mFirstPacketInPage = true;
     mCurrentPageSamples = 0;
     mCurrentPage.mNumSegments = 0;
+    mCurrentPage.mPrevPacketSize = -1;
     mNextLaceIndex = 0;
 
     // XXX what if new page continues packet from last???
@@ -489,16 +495,6 @@
                 tmp->set_range(0, buffer->range_length());
                 buffer->release();
             } else {
-                // XXX Not only is this not technically the correct time for
-                // this packet, we also stamp every packet in this page
-                // with the same time. This needs fixing later.
-
-                if (mVi.rate) {
-                    // Rate may not have been initialized yet if we're currently
-                    // reading the configuration packets...
-                    // Fortunately, the timestamp doesn't matter for those.
-                    timeUs = mCurrentPage.mGranulePosition * 1000000ll / mVi.rate;
-                }
                 tmp->set_range(0, 0);
             }
             buffer = tmp;
@@ -521,16 +517,34 @@
             if (gotFullPacket) {
                 // We've just read the entire packet.
 
-                if (timeUs >= 0) {
-                    buffer->meta_data()->setInt64(kKeyTime, timeUs);
-                }
-
                 if (mFirstPacketInPage) {
                     buffer->meta_data()->setInt32(
                             kKeyValidSamples, mCurrentPageSamples);
                     mFirstPacketInPage = false;
                 }
 
+                if (mVi.rate) {
+                    // Rate may not have been initialized yet if we're currently
+                    // reading the configuration packets...
+                    // Fortunately, the timestamp doesn't matter for those.
+                    int32_t curBlockSize = packetBlockSize(buffer);
+                    if (mCurrentPage.mPrevPacketSize < 0) {
+                        mCurrentPage.mPrevPacketSize = curBlockSize;
+                        mCurrentPage.mPrevPacketPos =
+                                mCurrentPage.mGranulePosition - mCurrentPageSamples;
+                        timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate;
+                    } else {
+                        // The effective block size is the average of the two overlapped blocks
+                        int32_t actualBlockSize =
+                                (curBlockSize + mCurrentPage.mPrevPacketSize) / 2;
+                        timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate;
+                        // The actual size output by the decoder will be half the effective
+                        // size, due to the overlap
+                        mCurrentPage.mPrevPacketPos += actualBlockSize / 2;
+                        mCurrentPage.mPrevPacketSize = curBlockSize;
+                    }
+                    buffer->meta_data()->setInt64(kKeyTime, timeUs);
+                }
                 *out = buffer;
 
                 return OK;
@@ -686,6 +700,35 @@
     }
 }
 
+int32_t MyVorbisExtractor::packetBlockSize(MediaBuffer *buffer) {
+    const uint8_t *data =
+        (const uint8_t *)buffer->data() + buffer->range_offset();
+
+    size_t size = buffer->range_length();
+
+    ogg_buffer buf;
+    buf.data = (uint8_t *)data;
+    buf.size = size;
+    buf.refcount = 1;
+    buf.ptr.owner = NULL;
+
+    ogg_reference ref;
+    ref.buffer = &buf;
+    ref.begin = 0;
+    ref.length = size;
+    ref.next = NULL;
+
+    ogg_packet pack;
+    pack.packet = &ref;
+    pack.bytes = ref.length;
+    pack.b_o_s = 0;
+    pack.e_o_s = 0;
+    pack.granulepos = 0;
+    pack.packetno = 0;
+
+    return vorbis_packet_blocksize(&mVi, &pack);
+}
+
 status_t MyVorbisExtractor::verifyHeader(
         MediaBuffer *buffer, uint8_t type) {
     const uint8_t *data =
@@ -730,6 +773,10 @@
             ALOGV("upper-bitrate = %ld", mVi.bitrate_upper);
             ALOGV("nominal-bitrate = %ld", mVi.bitrate_nominal);
             ALOGV("window-bitrate = %ld", mVi.bitrate_window);
+            ALOGV("blocksizes: %d/%d",
+                    vorbis_info_blocksize(&mVi, 0),
+                    vorbis_info_blocksize(&mVi, 1)
+                    );
 
             off64_t size;
             if (mSource->getSize(&size) == OK) {
diff --git a/services/camera/libcameraservice/device2/Camera2Device.cpp b/services/camera/libcameraservice/device2/Camera2Device.cpp
index 8caadd6..d1158d6 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.cpp
+++ b/services/camera/libcameraservice/device2/Camera2Device.cpp
@@ -793,11 +793,6 @@
         mStreamSlotCount = 0;
         return OK;
     }
-    camera_metadata_t *buf2 = clone_camera_metadata(buf);
-    if (!buf2) {
-        ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
-        return NO_MEMORY;
-    }
 
     if (mStreamSlotCount > 1) {
         List<camera_metadata_t*>::iterator deleter = ++mStreamSlot.begin();
@@ -806,9 +801,9 @@
     }
     if (mStreamSlotCount == 1) {
         free_camera_metadata( *(mStreamSlot.begin()) );
-        *(mStreamSlot.begin()) = buf2;
+        *(mStreamSlot.begin()) = buf;
     } else {
-        mStreamSlot.push_front(buf2);
+        mStreamSlot.push_front(buf);
         mStreamSlotCount = 1;
     }
     return signalConsumerLocked();
@@ -827,12 +822,7 @@
     mStreamSlotCount = 0;
     for (List<camera_metadata_t*>::const_iterator r = bufs.begin();
          r != bufs.end(); r++) {
-        camera_metadata_t *r2 = clone_camera_metadata(*r);
-        if (!r2) {
-            ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
-            return NO_MEMORY;
-        }
-        mStreamSlot.push_back(r2);
+        mStreamSlot.push_back(*r);
         mStreamSlotCount++;
     }
     return signalConsumerLocked();
diff --git a/services/camera/libcameraservice/device2/Camera2Device.h b/services/camera/libcameraservice/device2/Camera2Device.h
index 2a3f1d9..4def8ae 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.h
+++ b/services/camera/libcameraservice/device2/Camera2Device.h
@@ -124,8 +124,8 @@
 
         // Set repeating buffer(s); if the queue is empty on a dequeue call, the
         // queue copies the contents of the stream slot into the queue, and then
-        // dequeues the first new entry. The metadata buffers passed in are
-        // copied.
+        // dequeues the first new entry. The methods take the ownership of the
+        // metadata buffers passed in.
         status_t setStreamSlot(camera_metadata_t *buf);
         status_t setStreamSlot(const List<camera_metadata_t*> &bufs);