Merge "Restore media.log service" into nyc-dev
diff --git a/include/camera/ndk/NdkCameraMetadataTags.h b/include/camera/ndk/NdkCameraMetadataTags.h
index 0c398be..43f5193 100644
--- a/include/camera/ndk/NdkCameraMetadataTags.h
+++ b/include/camera/ndk/NdkCameraMetadataTags.h
@@ -836,6 +836,7 @@
     ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,
     ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
     ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY,
+    ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_3,
 } acamera_metadata_enum_android_info_supported_hardware_level_t;
 
 
diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h
index f655f35..8ed07ee 100644
--- a/include/media/mediametadataretriever.h
+++ b/include/media/mediametadataretriever.h
@@ -82,7 +82,7 @@
     const char* extractMetadata(int keyCode);
 
 private:
-    static const sp<IMediaPlayerService>& getService();
+    static const sp<IMediaPlayerService> getService();
 
     class DeathNotifier: public IBinder::DeathRecipient
     {
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
index 9a76f58..08a9e6a 100644
--- a/media/libmedia/mediametadataretriever.cpp
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -35,7 +35,7 @@
 sp<IMediaPlayerService> MediaMetadataRetriever::sService;
 sp<MediaMetadataRetriever::DeathNotifier> MediaMetadataRetriever::sDeathNotifier;
 
-const sp<IMediaPlayerService>& MediaMetadataRetriever::getService()
+const sp<IMediaPlayerService> MediaMetadataRetriever::getService()
 {
     Mutex::Autolock lock(sServiceLock);
     if (sService == 0) {
@@ -62,7 +62,7 @@
 MediaMetadataRetriever::MediaMetadataRetriever()
 {
     ALOGV("constructor");
-    const sp<IMediaPlayerService>& service(getService());
+    const sp<IMediaPlayerService> service(getService());
     if (service == 0) {
         ALOGE("failed to obtain MediaMetadataRetrieverService");
         return;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index d0e7aa9..44279ce 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -731,6 +731,29 @@
             readFromAMessage(msg, &rate);
             status_t err = OK;
             if (mRenderer != NULL) {
+                // AudioSink allows only 1.f and 0.f for offload mode.
+                // For other speed, switch to non-offload mode.
+                if (mOffloadAudio && ((rate.mSpeed != 0.f && rate.mSpeed != 1.f)
+                        || rate.mPitch != 1.f)) {
+                    int64_t currentPositionUs;
+                    if (getCurrentPosition(&currentPositionUs) != OK) {
+                        currentPositionUs = mPreviousSeekTimeUs;
+                    }
+
+                    // Set mPlaybackSettings so that the new audio decoder can
+                    // be created correctly.
+                    mPlaybackSettings = rate;
+                    if (!mPaused) {
+                        mRenderer->pause();
+                    }
+                    restartAudioFromOffload(
+                            currentPositionUs, true /* forceNonOffload */,
+                            true /* needsToCreateAudioDecoder */);
+                    if (!mPaused) {
+                        mRenderer->resume();
+                    }
+                }
+
                 err = mRenderer->setPlaybackSettings(rate);
             }
             if (err == OK) {
@@ -1121,41 +1144,14 @@
                 int32_t reason;
                 CHECK(msg->findInt32("reason", &reason));
                 ALOGV("Tear down audio with reason %d.", reason);
-                mAudioDecoder->pause();
-                mAudioDecoder.clear();
-                ++mAudioDecoderGeneration;
-                bool needsToCreateAudioDecoder = true;
-                if (mFlushingAudio == FLUSHING_DECODER) {
-                    mFlushComplete[1 /* audio */][1 /* isDecoder */] = true;
-                    mFlushingAudio = FLUSHED;
-                    finishFlushIfPossible();
-                } else if (mFlushingAudio == FLUSHING_DECODER_SHUTDOWN
-                        || mFlushingAudio == SHUTTING_DOWN_DECODER) {
-                    mFlushComplete[1 /* audio */][1 /* isDecoder */] = true;
-                    mFlushingAudio = SHUT_DOWN;
-                    finishFlushIfPossible();
-                    needsToCreateAudioDecoder = false;
-                }
-                if (mRenderer == NULL) {
-                    break;
-                }
-                closeAudioSink();
-                mRenderer->flush(
-                        true /* audio */, false /* notifyComplete */);
-                if (mVideoDecoder != NULL) {
-                    mRenderer->flush(
-                            false /* audio */, false /* notifyComplete */);
-                }
-
                 int64_t positionUs;
                 if (!msg->findInt64("positionUs", &positionUs)) {
                     positionUs = mPreviousSeekTimeUs;
                 }
-                performSeek(positionUs);
 
-                if (reason == Renderer::kDueToError && needsToCreateAudioDecoder) {
-                    instantiateDecoder(true /* audio */, &mAudioDecoder);
-                }
+                restartAudioFromOffload(
+                        positionUs, false /* forceNonOffload */,
+                        reason == Renderer::kDueToError /* needsToCreateAudioDecoder */);
             }
             break;
         }
@@ -1339,7 +1335,8 @@
     sp<AMessage> videoFormat = mSource->getFormat(false /* audio */);
 
     mOffloadAudio =
-        canOffloadStream(audioMeta, (videoFormat != NULL), mSource->isStreaming(), streamType);
+        canOffloadStream(audioMeta, (videoFormat != NULL), mSource->isStreaming(), streamType)
+                && (mPlaybackSettings.mSpeed == 1.f && mPlaybackSettings.mPitch == 1.f);
     if (mOffloadAudio) {
         flags |= Renderer::FLAG_OFFLOAD_AUDIO;
     }
@@ -1491,6 +1488,45 @@
     mRenderer->closeAudioSink();
 }
 
+void NuPlayer::restartAudioFromOffload(
+        int64_t currentPositionUs, bool forceNonOffload, bool needsToCreateAudioDecoder) {
+    if (!mOffloadAudio) {
+        return;
+    }
+    mAudioDecoder->pause();
+    mAudioDecoder.clear();
+    ++mAudioDecoderGeneration;
+    if (mFlushingAudio == FLUSHING_DECODER) {
+        mFlushComplete[1 /* audio */][1 /* isDecoder */] = true;
+        mFlushingAudio = FLUSHED;
+        finishFlushIfPossible();
+    } else if (mFlushingAudio == FLUSHING_DECODER_SHUTDOWN
+            || mFlushingAudio == SHUTTING_DOWN_DECODER) {
+        mFlushComplete[1 /* audio */][1 /* isDecoder */] = true;
+        mFlushingAudio = SHUT_DOWN;
+        finishFlushIfPossible();
+        needsToCreateAudioDecoder = false;
+    }
+    if (mRenderer == NULL) {
+        return;
+    }
+    closeAudioSink();
+    mRenderer->flush(true /* audio */, false /* notifyComplete */);
+    if (mVideoDecoder != NULL) {
+        mRenderer->flush(false /* audio */, false /* notifyComplete */);
+    }
+
+    performSeek(currentPositionUs);
+
+    if (forceNonOffload) {
+        mRenderer->signalDisableOffloadAudio();
+        mOffloadAudio = false;
+    }
+    if (needsToCreateAudioDecoder) {
+        instantiateDecoder(true /* audio */, &mAudioDecoder);
+    }
+}
+
 void NuPlayer::determineAudioModeChange() {
     if (mSource == NULL || mAudioSink == NULL) {
         return;
@@ -1507,7 +1543,8 @@
     audio_stream_type_t streamType = mAudioSink->getAudioStreamType();
     const bool hasVideo = (videoFormat != NULL);
     const bool canOffload = canOffloadStream(
-            audioMeta, hasVideo, mSource->isStreaming(), streamType);
+            audioMeta, hasVideo, mSource->isStreaming(), streamType)
+                    && (mPlaybackSettings.mSpeed == 1.f && mPlaybackSettings.mPitch == 1.f);
     if (canOffload) {
         if (!mOffloadAudio) {
             mRenderer->signalEnableOffloadAudio();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index cefbb19..5e48b30 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -233,6 +233,8 @@
 
     void tryOpenAudioSinkForOffload(const sp<AMessage> &format, bool hasVideo);
     void closeAudioSink();
+    void restartAudioFromOffload(
+        int64_t currentPositionUs, bool forceNonOffload, bool needsToCreateAudioDecoder);
     void determineAudioModeChange();
 
     status_t instantiateDecoder(bool audio, sp<DecoderBase> *decoder);
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 6f4a65b..d5a869d 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -4279,7 +4279,15 @@
                     continue;
                 }
 
-                CHECK(dstOffset + 4 <= mBuffer->size());
+                if (dstOffset > SIZE_MAX - 4 ||
+                        dstOffset + 4 > SIZE_MAX - nalLength ||
+                        dstOffset + 4 + nalLength > mBuffer->size()) {
+                    ALOGE("b/27208621 : %zu %zu", dstOffset, mBuffer->size());
+                    android_errorWriteLog(0x534e4554, "27208621");
+                    mBuffer->release();
+                    mBuffer = NULL;
+                    return ERROR_MALFORMED;
+                }
 
                 dstData[dstOffset++] = 0;
                 dstData[dstOffset++] = 0;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index a5d9484..d520cb3 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -2536,6 +2536,7 @@
             ALOGE("timestampUs %" PRId64 " < lastTimestampUs %" PRId64 " for %s track",
                 timestampUs, lastTimestampUs, trackName);
             copy->release();
+            mSource->stop();
             return UNKNOWN_ERROR;
         }
 
diff --git a/media/libstagefright/SampleIterator.cpp b/media/libstagefright/SampleIterator.cpp
index 7bf3437..ad7b6fd 100644
--- a/media/libstagefright/SampleIterator.cpp
+++ b/media/libstagefright/SampleIterator.cpp
@@ -320,7 +320,18 @@
 
     *time = mTTSSampleTime + mTTSDuration * (sampleIndex - mTTSSampleIndex);
 
-    *time += mTable->getCompositionTimeOffset(sampleIndex);
+    int32_t offset = mTable->getCompositionTimeOffset(sampleIndex);
+    if ((offset < 0 && *time < (offset == INT32_MIN ?
+            INT32_MAX : uint32_t(-offset))) ||
+            (offset > 0 && *time > UINT32_MAX - offset)) {
+        ALOGE("%u + %d would overflow", *time, offset);
+        return ERROR_OUT_OF_RANGE;
+    }
+    if (offset > 0) {
+        *time += offset;
+    } else {
+        *time -= (offset == INT32_MIN ? INT32_MAX : (-offset));
+    }
 
     *duration = mTTSDuration;
 
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index 39459e2..f5d9ec7 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -49,14 +49,14 @@
     CompositionDeltaLookup();
 
     void setEntries(
-            const uint32_t *deltaEntries, size_t numDeltaEntries);
+            const int32_t *deltaEntries, size_t numDeltaEntries);
 
-    uint32_t getCompositionTimeOffset(uint32_t sampleIndex);
+    int32_t getCompositionTimeOffset(uint32_t sampleIndex);
 
 private:
     Mutex mLock;
 
-    const uint32_t *mDeltaEntries;
+    const int32_t *mDeltaEntries;
     size_t mNumDeltaEntries;
 
     size_t mCurrentDeltaEntry;
@@ -73,7 +73,7 @@
 }
 
 void SampleTable::CompositionDeltaLookup::setEntries(
-        const uint32_t *deltaEntries, size_t numDeltaEntries) {
+        const int32_t *deltaEntries, size_t numDeltaEntries) {
     Mutex::Autolock autolock(mLock);
 
     mDeltaEntries = deltaEntries;
@@ -82,7 +82,7 @@
     mCurrentEntrySampleIndex = 0;
 }
 
-uint32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset(
+int32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset(
         uint32_t sampleIndex) {
     Mutex::Autolock autolock(mLock);
 
@@ -372,6 +372,10 @@
     return OK;
 }
 
+// NOTE: per 14996-12, version 0 ctts contains unsigned values, while version 1
+// contains signed values, however some software creates version 0 files that
+// contain signed values, so we're always treating the values as signed,
+// regardless of version.
 status_t SampleTable::setCompositionTimeToSampleParams(
         off64_t data_offset, size_t data_size) {
     ALOGI("There are reordered frames present.");
@@ -387,8 +391,12 @@
         return ERROR_IO;
     }
 
-    if (U32_AT(header) != 0) {
-        // Expected version = 0, flags = 0.
+    uint32_t flags = U32_AT(header);
+    uint32_t version = flags >> 24;
+    flags &= 0xffffff;
+
+    if ((version != 0 && version != 1) || flags != 0) {
+        // Expected version = 0 or 1, flags = 0.
         return ERROR_MALFORMED;
     }
 
@@ -404,7 +412,7 @@
         return ERROR_OUT_OF_RANGE;
     }
 
-    mCompositionTimeDeltaEntries = new (std::nothrow) uint32_t[2 * numEntries];
+    mCompositionTimeDeltaEntries = new (std::nothrow) int32_t[2 * numEntries];
     if (!mCompositionTimeDeltaEntries)
         return ERROR_OUT_OF_RANGE;
 
@@ -546,12 +554,28 @@
 
                 mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;
 
-                uint32_t compTimeDelta =
+                int32_t compTimeDelta =
                     mCompositionDeltaLookup->getCompositionTimeOffset(
                             sampleIndex);
 
+                if ((compTimeDelta < 0 && sampleTime <
+                        (compTimeDelta == INT32_MIN ?
+                                INT32_MAX : uint32_t(-compTimeDelta)))
+                        || (compTimeDelta > 0 &&
+                                sampleTime > UINT32_MAX - compTimeDelta)) {
+                    ALOGE("%u + %d would overflow, clamping",
+                            sampleTime, compTimeDelta);
+                    if (compTimeDelta < 0) {
+                        sampleTime = 0;
+                    } else {
+                        sampleTime = UINT32_MAX;
+                    }
+                    compTimeDelta = 0;
+                }
+
                 mSampleTimeEntries[sampleIndex].mCompositionTime =
-                    sampleTime + compTimeDelta;
+                        compTimeDelta > 0 ? sampleTime + compTimeDelta:
+                                sampleTime - (-compTimeDelta);
             }
 
             ++sampleIndex;
@@ -841,7 +865,7 @@
     return OK;
 }
 
-uint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
+int32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
     return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex);
 }
 
diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h
index 460492b..738f864 100644
--- a/media/libstagefright/include/SampleTable.h
+++ b/media/libstagefright/include/SampleTable.h
@@ -119,7 +119,7 @@
     };
     SampleTimeEntry *mSampleTimeEntries;
 
-    uint32_t *mCompositionTimeDeltaEntries;
+    int32_t *mCompositionTimeDeltaEntries;
     size_t mNumCompositionTimeDeltaEntries;
     CompositionDeltaLookup *mCompositionDeltaLookup;
 
@@ -148,7 +148,7 @@
     }
 
     status_t getSampleSize_l(uint32_t sample_index, size_t *sample_size);
-    uint32_t getCompositionTimeOffset(uint32_t sampleIndex);
+    int32_t getCompositionTimeOffset(uint32_t sampleIndex);
 
     static int CompareIncreasingTime(const void *, const void *);
 
diff --git a/services/mediaextractor/minijail/seccomp_policy/mediaextractor-seccomp-x86.policy b/services/mediaextractor/minijail/seccomp_policy/mediaextractor-seccomp-x86.policy
index f321366..6c44886 100644
--- a/services/mediaextractor/minijail/seccomp_policy/mediaextractor-seccomp-x86.policy
+++ b/services/mediaextractor/minijail/seccomp_policy/mediaextractor-seccomp-x86.policy
@@ -28,3 +28,10 @@
 exit_group: 1
 rt_sigreturn: 1
 faccessat: 1
+
+# for attaching to debuggerd on process crash
+socketcall: 1
+sigaction: 1
+tgkill: 1
+rt_sigprocmask: 1
+fcntl64: 1