Merge cherrypicks of [3898864, 3898788, 3898789, 3898836, 3898617, 3898865, 3898683, 3898866, 3898867, 3897560, 3898868, 3898790, 3898791, 3898792, 3898793, 3898794, 3898048, 3898049, 3898050, 3897937, 3897938, 3897867, 3897868, 3897939, 3898869, 3898978, 3898799, 3898763] into sparse-4669640-L25700000163305736

Change-Id: I8de01b7c1cf62d9fcfaec395f42529d0649ccec6
diff --git a/media/libheif/HeifDecoderImpl.cpp b/media/libheif/HeifDecoderImpl.cpp
index 4b131a7..57209e2 100644
--- a/media/libheif/HeifDecoderImpl.cpp
+++ b/media/libheif/HeifDecoderImpl.cpp
@@ -139,6 +139,11 @@
     // have been caught above.
     CHECK(offset >= mCachedOffset);
 
+    off64_t resultOffset;
+    if (__builtin_add_overflow(offset, size, &resultOffset)) {
+        return ERROR_IO;
+    }
+
     if (size == 0) {
         return 0;
     }
@@ -321,8 +326,8 @@
 
     if (frameInfo != nullptr) {
         frameInfo->set(
-                videoFrame->mDisplayWidth,
-                videoFrame->mDisplayHeight,
+                videoFrame->mWidth,
+                videoFrame->mHeight,
                 videoFrame->mRotationAngle,
                 videoFrame->mBytesPerPixel,
                 videoFrame->mIccSize,
@@ -393,8 +398,8 @@
 
     if (frameInfo != nullptr) {
         frameInfo->set(
-                videoFrame->mDisplayWidth,
-                videoFrame->mDisplayHeight,
+                videoFrame->mWidth,
+                videoFrame->mHeight,
                 videoFrame->mRotationAngle,
                 videoFrame->mBytesPerPixel,
                 videoFrame->mIccSize,
@@ -413,12 +418,12 @@
         return false;
     }
     VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->pointer());
-    if (mCurScanline >= videoFrame->mDisplayHeight) {
+    if (mCurScanline >= videoFrame->mHeight) {
         ALOGE("no more scanline available");
         return false;
     }
     uint8_t* src = videoFrame->getFlattenedData() + videoFrame->mRowBytes * mCurScanline++;
-    memcpy(dst, src, videoFrame->mBytesPerPixel * videoFrame->mDisplayWidth);
+    memcpy(dst, src, videoFrame->mBytesPerPixel * videoFrame->mWidth);
     return true;
 }
 
@@ -430,8 +435,8 @@
 
     uint32_t oldScanline = mCurScanline;
     mCurScanline += count;
-    if (mCurScanline > videoFrame->mDisplayHeight) {
-        mCurScanline = videoFrame->mDisplayHeight;
+    if (mCurScanline > videoFrame->mHeight) {
+        mCurScanline = videoFrame->mHeight;
     }
     return (mCurScanline > oldScanline) ? (mCurScanline - oldScanline) : 0;
 }
diff --git a/media/libstagefright/ItemTable.cpp b/media/libstagefright/ItemTable.cpp
index 7bc4f3c..f9ee1c4 100644
--- a/media/libstagefright/ItemTable.cpp
+++ b/media/libstagefright/ItemTable.cpp
@@ -1441,16 +1441,11 @@
         if (tileIndex < 0) {
             return NULL;
         }
-        // when there are tiles, (kKeyWidth, kKeyHeight) is the full tiled area,
-        // and (kKeyDisplayWidth, kKeyDisplayHeight) may be smaller than that.
-        meta->setInt32(kKeyDisplayWidth, image->width);
-        meta->setInt32(kKeyDisplayHeight, image->height);
-        int32_t gridRows = image->rows, gridCols = image->columns;
+        meta->setInt32(kKeyGridRows, image->rows);
+        meta->setInt32(kKeyGridCols, image->columns);
 
         // point image to the first tile for grid size and HVCC
         image = &mItemIdToImageMap.editValueAt(tileIndex);
-        meta->setInt32(kKeyWidth, image->width * gridCols);
-        meta->setInt32(kKeyHeight, image->height * gridRows);
         meta->setInt32(kKeyGridWidth, image->width);
         meta->setInt32(kKeyGridHeight, image->height);
         meta->setInt32(kKeyMaxInputSize, image->width * image->height * 1.5);
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index 103da95..e8c3dd3 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -276,30 +276,27 @@
     int32_t gridRows = 1, gridCols = 1;
     if (overrideMeta == NULL) {
         // check if we're dealing with a tiled heif
-        int32_t gridWidth, gridHeight;
+        int32_t gridWidth, gridHeight, tmpRows, tmpCols;
         if (trackMeta->findInt32(kKeyGridWidth, &gridWidth) && gridWidth > 0
-         && trackMeta->findInt32(kKeyGridHeight, &gridHeight) && gridHeight > 0) {
-            int32_t width, height, displayWidth, displayHeight;
+         && trackMeta->findInt32(kKeyGridHeight, &gridHeight) && gridHeight > 0
+         && trackMeta->findInt32(kKeyGridRows, &tmpRows) && tmpRows > 0
+         && trackMeta->findInt32(kKeyGridCols, &tmpCols) && tmpCols > 0) {
+            int32_t width, height;
             CHECK(trackMeta->findInt32(kKeyWidth, &width));
             CHECK(trackMeta->findInt32(kKeyHeight, &height));
-            CHECK(trackMeta->findInt32(kKeyDisplayWidth, &displayWidth));
-            CHECK(trackMeta->findInt32(kKeyDisplayHeight, &displayHeight));
 
-            if (width >= displayWidth && height >= displayHeight
-                    && (width % gridWidth == 0) && (height % gridHeight == 0)) {
-                ALOGV("grid config: %dx%d, display %dx%d, grid %dx%d",
-                        width, height, displayWidth, displayHeight, gridWidth, gridHeight);
+            if (width <= gridWidth * tmpCols && height <= gridHeight * tmpRows) {
+                ALOGV("grid: %dx%d, size: %dx%d, picture size: %dx%d",
+                        tmpCols, tmpRows, gridWidth, gridHeight, width, height);
 
                 overrideMeta = new MetaData(*trackMeta);
-                overrideMeta->remove(kKeyDisplayWidth);
-                overrideMeta->remove(kKeyDisplayHeight);
                 overrideMeta->setInt32(kKeyWidth, gridWidth);
                 overrideMeta->setInt32(kKeyHeight, gridHeight);
-                gridCols = width / gridWidth;
-                gridRows = height / gridHeight;
+                gridCols = tmpCols;
+                gridRows = tmpRows;
             } else {
-                ALOGE("Bad grid config: %dx%d, display %dx%d, grid %dx%d",
-                        width, height, displayWidth, displayHeight, gridWidth, gridHeight);
+                ALOGE("bad grid: %dx%d, size: %dx%d, picture size: %dx%d",
+                        tmpCols, tmpRows, gridWidth, gridHeight, width, height);
             }
         }
         if (overrideMeta == NULL) {
@@ -497,13 +494,18 @@
                     ALOGV("Timed-out waiting for output.. retries left = %zu", retriesLeft);
                     err = OK;
                 } else if (err == OK) {
+	            if (outputFormat == NULL) {
+                        decoder->releaseOutputBuffer(index);
+                        err = ERROR_MALFORMED;
+                        break;
+                    }
+
                     // If we're seeking with CLOSEST option and obtained a valid targetTimeUs
                     // from the extractor, decode to the specified frame. Otherwise we're done.
                     ALOGV("Received an output buffer, timeUs=%lld", (long long)timeUs);
                     sp<MediaCodecBuffer> videoFrameBuffer = outputBuffers.itemAt(index);
 
                     int32_t width, height;
-                    CHECK(outputFormat != NULL);
                     CHECK(outputFormat->findInt32("width", &width));
                     CHECK(outputFormat->findInt32("height", &height));
 
@@ -541,28 +543,31 @@
                         dstBottom = dstTop + height - 1;
                     }
 
-                    if (converter.isValid()) {
-                        err = converter.convert(
-                                (const uint8_t *)videoFrameBuffer->data(),
-                                width, height,
-                                crop_left, crop_top, crop_right, crop_bottom,
-                                frame->mData,
-                                frame->mWidth,
-                                frame->mHeight,
-                                dstLeft, dstTop, dstRight, dstBottom);
-                    } else {
-                        ALOGE("Unable to convert from format 0x%08x to 0x%08x",
-                                srcFormat, dstFormat);
-
-                        err = ERROR_UNSUPPORTED;
-                    }
-
                     done = (targetTimeUs < 0ll) || (timeUs >= targetTimeUs);
-                    if (numTiles > 1) {
-                        tilesDecoded++;
-                        done &= (tilesDecoded >= numTiles);
+
+                    if (done) {
+                        if (converter.isValid()) {
+                            err = converter.convert(
+                                    (const uint8_t *)videoFrameBuffer->data(),
+                                    width, height,
+                                    crop_left, crop_top, crop_right, crop_bottom,
+                                    frame->mData,
+                                    frame->mWidth,
+                                    frame->mHeight,
+                                    dstLeft, dstTop, dstRight, dstBottom);
+                        } else {
+                            ALOGE("Unable to convert from format 0x%08x to 0x%08x",
+                                    srcFormat, dstFormat);
+
+                            err = ERROR_UNSUPPORTED;
+                        }
+                        if (numTiles > 1) {
+                            tilesDecoded++;
+                            done &= (tilesDecoded >= numTiles);
+                        }
                     }
-                    err = decoder->releaseOutputBuffer(index);
+
+                    decoder->releaseOutputBuffer(index);
                 } else {
                     ALOGW("Received error %d (%s) instead of output", err, asString(err));
                     done = true;
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.cpp
index d443b7c..bc5fd79 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.cpp
@@ -184,7 +184,7 @@
     info->emphasis           = (temp << 30) >> 30;  /* 2 */
 
 
-    if (!info->bitrate_index || info->sampling_frequency == 3)
+    if (!info->bitrate_index || info->bitrate_index == 15 || info->sampling_frequency == 3)
     {
         err = UNSUPPORTED_FREE_BITRATE;
     }
diff --git a/media/libstagefright/include/media/stagefright/MetaData.h b/media/libstagefright/include/media/stagefright/MetaData.h
index 6cfde9c..f2113f4 100644
--- a/media/libstagefright/include/media/stagefright/MetaData.h
+++ b/media/libstagefright/include/media/stagefright/MetaData.h
@@ -215,6 +215,8 @@
 
     kKeyGridWidth        = 'grdW', // int32_t, HEIF grid width
     kKeyGridHeight       = 'grdH', // int32_t, HEIF grid height
+    kKeyGridRows         = 'grdR', // int32_t, HEIF grid rows
+    kKeyGridCols         = 'grdC', // int32_t, HEIF grid columns
     kKeyIccProfile       = 'prof', // raw data, ICC prifile data
 };
 
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 1cf9744..11f3ed1 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -1486,7 +1486,9 @@
         const uint8_t *data, size_t size) {
     static const char kStartCode[] = "\x00\x00\x01";
 
-    if (size < 3) {
+    // per ISO/IEC 14496-2 6.2.1, a chunk has a 3-byte prefix + 1-byte start code
+    // we need at least <prefix><start><next prefix> to successfully scan
+    if (size < 3 + 1 + 3) {
         return -EAGAIN;
     }
 
@@ -1494,7 +1496,7 @@
         return -EAGAIN;
     }
 
-    size_t offset = 3;
+    size_t offset = 4;
     while (offset + 2 < size) {
         if (!memcmp(&data[offset], kStartCode, 3)) {
             return offset;
@@ -1545,6 +1547,9 @@
                     state = EXPECT_VISUAL_OBJECT_START;
                 } else {
                     discard = true;
+                    offset += chunkSize;
+                    ALOGW("b/74114680, advance to next chunk");
+                    android_errorWriteLog(0x534e4554, "74114680");
                 }
                 break;
             }