Merge "audio policy: add method to query dB attenuation for a certain volume and device" into oc-dr1-dev
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index e56f675..386546f 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -411,8 +411,11 @@
     }
 
     setListener(NULL);
-    mPlugin->setListener(NULL);
+    if (mPlugin != NULL) {
+        mPlugin->setListener(NULL);
+    }
     mPlugin.clear();
+    mInitCheck = NO_INIT;
 
     return OK;
 }
@@ -960,8 +963,11 @@
 {
     Mutex::Autolock autoLock(mLock);
     setListener(NULL);
-    mPlugin->setListener(NULL);
+    if (mPlugin != NULL) {
+        mPlugin->setListener(NULL);
+    }
     mPlugin.clear();
+    mInitCheck = NO_INIT;
 }
 
 void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
diff --git a/drm/mediadrm/plugins/clearkey/Android.bp b/drm/mediadrm/plugins/clearkey/Android.bp
index 6af7cd8..f3ce65c 100644
--- a/drm/mediadrm/plugins/clearkey/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/Android.bp
@@ -38,12 +38,17 @@
     shared_libs: [
         "libcrypto",
         "liblog",
-        "libstagefright_foundation",
+        "libstagefright_foundation_vendor",
         "libutils",
     ],
 
     static_libs: ["libjsmn"],
 
+    include_dirs: [
+        "frameworks/native/include",
+        "frameworks/av/include",
+    ],
+
     export_include_dirs: ["."],
     export_static_lib_headers: ["libjsmn"],
 }
diff --git a/drm/mediadrm/plugins/clearkey/tests/Android.bp b/drm/mediadrm/plugins/clearkey/tests/Android.bp
index 1b208ad..976c590 100644
--- a/drm/mediadrm/plugins/clearkey/tests/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/tests/Android.bp
@@ -19,6 +19,7 @@
 
 cc_test {
     name: "ClearKeyDrmUnitTest",
+    vendor: true,
 
     srcs: [
         "AesCtrDecryptorUnittest.cpp",
@@ -30,7 +31,7 @@
         "libcrypto",
         "libdrmclearkeyplugin",
         "liblog",
-        "libstagefright_foundation",
+        "libstagefright_foundation_vendor",
         "libutils",
     ],
 }
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index ab33cea..bdeecb0 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1039,10 +1039,7 @@
         array[i] = {mBuffers[portIndex][i].mData, mBuffers[portIndex][i].mBufferID};
     }
     if (portIndex == kPortIndexInput) {
-        err = mBufferChannel->setInputBufferArray(array);
-        if (err != OK) {
-            return err;
-        }
+        mBufferChannel->setInputBufferArray(array);
     } else if (portIndex == kPortIndexOutput) {
         mBufferChannel->setOutputBufferArray(array);
     } else {
diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp
index 796d3dc..0d9696f 100644
--- a/media/libstagefright/ACodecBufferChannel.cpp
+++ b/media/libstagefright/ACodecBufferChannel.cpp
@@ -284,7 +284,7 @@
     return dealer;
 }
 
-status_t ACodecBufferChannel::setInputBufferArray(const std::vector<BufferAndId> &array) {
+void ACodecBufferChannel::setInputBufferArray(const std::vector<BufferAndId> &array) {
     if (hasCryptoOrDescrambler()) {
         size_t totalSize = std::accumulate(
                 array.begin(), array.end(), 0u,
@@ -311,15 +311,11 @@
         if (hasCryptoOrDescrambler()) {
             sharedEncryptedBuffer = mDealer->allocate(elem.mBuffer->capacity());
         }
-        if (elem.mBuffer->data() == NULL && sharedEncryptedBuffer == NULL) {
-            return BAD_VALUE;
-        }
         inputBuffers.emplace_back(elem.mBuffer, elem.mBufferId, sharedEncryptedBuffer);
     }
     std::atomic_store(
             &mInputBuffers,
             std::make_shared<const std::vector<const BufferInfo>>(inputBuffers));
-    return OK;
 }
 
 void ACodecBufferChannel::setOutputBufferArray(const std::vector<BufferAndId> &array) {
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index bbdcf0b..ecd62b0 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -3125,6 +3125,13 @@
         }
         case FOURCC('y', 'r', 'r', 'c'):
         {
+            if (size < 6) {
+                delete[] buffer;
+                buffer = NULL;
+                ALOGE("b/62133227");
+                android_errorWriteLog(0x534e4554, "62133227");
+                return ERROR_MALFORMED;
+            }
             char tmp[5];
             uint16_t year = U16_AT(&buffer[4]);
 
@@ -3147,6 +3154,8 @@
 
         // smallest possible valid UTF-16 string w BOM: 0xfe 0xff 0x00 0x00
         if (size < 6) {
+            delete[] buffer;
+            buffer = NULL;
             return ERROR_MALFORMED;
         }
 
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
old mode 100755
new mode 100644
index ed952e9..52e1626
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -343,6 +343,7 @@
 
     void dumpTimeStamps();
 
+    int64_t getStartTimeOffsetScaledTimeUs() const;
     int32_t getStartTimeOffsetScaledTime() const;
 
     static void *ThreadWrapper(void *me);
@@ -3162,7 +3163,7 @@
 }
 
 int64_t MPEG4Writer::Track::getDurationUs() const {
-    return mTrackDurationUs;
+    return mTrackDurationUs + getStartTimeOffsetScaledTimeUs();
 }
 
 int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
@@ -3646,14 +3647,18 @@
     mOwner->endBox();  // pasp
 }
 
-int32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
+int64_t MPEG4Writer::Track::getStartTimeOffsetScaledTimeUs() const {
     int64_t trackStartTimeOffsetUs = 0;
     int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
     if (mStartTimestampUs != moovStartTimeUs) {
         CHECK_GT(mStartTimestampUs, moovStartTimeUs);
         trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
     }
-    return (trackStartTimeOffsetUs *  mTimeScale + 500000LL) / 1000000LL;
+    return trackStartTimeOffsetUs;
+}
+
+int32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
+    return (getStartTimeOffsetScaledTimeUs() *  mTimeScale + 500000LL) / 1000000LL;
 }
 
 void MPEG4Writer::Track::writeSttsBox() {
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 280dd95..bd71632 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -735,8 +735,7 @@
             mAnalyticsItem->setInt32(kCodecCrypto, 1);
         }
     } else if (mFlags & kFlagIsSecure) {
-        ALOGE("Crypto or descrambler should be given for secure codec");
-        return BAD_VALUE;
+        ALOGW("Crypto or descrambler should be given for secure codec");
     }
 
     // save msg for reset
@@ -2596,6 +2595,10 @@
     if (csd->size() > codecInputData->capacity()) {
         return -EINVAL;
     }
+    if (codecInputData->data() == NULL) {
+        ALOGV("Input buffer %zu is not properly allocated", bufferIndex);
+        return -EINVAL;
+    }
 
     memcpy(codecInputData->data(), csd->data(), csd->size());
 
diff --git a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
index 8a569c9..d358ce4 100644
--- a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
+++ b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
@@ -62,6 +62,7 @@
             kProfileLevels, ARRAY_SIZE(kProfileLevels),
             320 /* width */, 240 /* height */, callbacks,
             appData, component),
+      mCodecCtx(NULL),
       mMemRecords(NULL),
       mFlushOutBuffer(NULL),
       mOmxColorFormat(OMX_COLOR_FormatYUV420Planar),
@@ -69,6 +70,7 @@
       mNewWidth(mWidth),
       mNewHeight(mHeight),
       mChangingResolution(false),
+      mSignalledError(false),
       mStride(mWidth) {
     initPorts(kNumBuffers, INPUT_BUF_SIZE, kNumBuffers, CODEC_MIME_TYPE);
 
@@ -76,11 +78,21 @@
     GENERATE_FILE_NAMES();
     CREATE_DUMP_FILE(mInFile);
 
-    CHECK_EQ(initDecoder(), (status_t)OK);
+    if (OK != initDecoder()) {
+        ALOGE("Failed to initialize decoder");
+        notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
+        mSignalledError = true;
+        return;
+    }
 }
 
 SoftMPEG2::~SoftMPEG2() {
-    CHECK_EQ(deInitDecoder(), (status_t)OK);
+    if (OK != deInitDecoder()) {
+        ALOGE("Failed to deinit decoder");
+        notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
+        mSignalledError = true;
+        return;
+    }
 }
 
 
@@ -198,6 +210,7 @@
     setNumCores();
 
     mStride = 0;
+    mSignalledError = false;
 
     return OK;
 }
@@ -427,6 +440,7 @@
 
     mInitNeeded = true;
     mChangingResolution = false;
+    mCodecCtx = NULL;
 
     return OK;
 }
@@ -438,10 +452,13 @@
 
     ret = initDecoder();
     if (OK != ret) {
-        ALOGE("Create failure");
+        ALOGE("Failed to initialize decoder");
         deInitDecoder();
-        return NO_MEMORY;
+        notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
+        mSignalledError = true;
+        return ret;
     }
+    mSignalledError = false;
     return OK;
 }
 
@@ -580,6 +597,9 @@
 void SoftMPEG2::onQueueFilled(OMX_U32 portIndex) {
     UNUSED(portIndex);
 
+    if (mSignalledError) {
+        return;
+    }
     if (mOutputPortSettingsChange != NONE) {
         return;
     }
@@ -636,7 +656,12 @@
             bool portWillReset = false;
             handlePortSettingsChange(&portWillReset, mNewWidth, mNewHeight);
 
-            CHECK_EQ(reInitDecoder(), (status_t)OK);
+            if (OK != reInitDecoder()) {
+                ALOGE("Failed to reinitialize decoder");
+                notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
+                mSignalledError = true;
+                return;
+            }
             return;
         }
 
@@ -709,7 +734,12 @@
                 bool portWillReset = false;
                 handlePortSettingsChange(&portWillReset, s_dec_op.u4_pic_wd, s_dec_op.u4_pic_ht);
 
-                CHECK_EQ(reInitDecoder(), (status_t)OK);
+                if (OK != reInitDecoder()) {
+                    ALOGE("Failed to reinitialize decoder");
+                    notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
+                    mSignalledError = true;
+                    return;
+                }
 
                 if (setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx)) {
                     ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
diff --git a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h
index 1921a23..6729a54 100644
--- a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h
+++ b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h
@@ -106,6 +106,7 @@
     // codec. So the codec is switching to decode the new resolution.
     bool mChangingResolution;
     bool mFlushNeeded;
+    bool mSignalledError;
     bool mWaitForI;
     size_t mStride;
 
diff --git a/media/libstagefright/include/ACodecBufferChannel.h b/media/libstagefright/include/ACodecBufferChannel.h
index 349f1f8..0da2e81 100644
--- a/media/libstagefright/include/ACodecBufferChannel.h
+++ b/media/libstagefright/include/ACodecBufferChannel.h
@@ -87,9 +87,8 @@
      *
      * @param array     Newly allocated buffers. Empty if buffers are
      *                  deallocated.
-     * @return OK if no error.
      */
-    status_t setInputBufferArray(const std::vector<BufferAndId> &array);
+    void setInputBufferArray(const std::vector<BufferAndId> &array);
     /**
      * Set output buffer array.
      *
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index e03ec66..9bc31b9 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -138,7 +138,8 @@
         mInputBuffer(nullptr),
         mProducer(nullptr),
         mInputProducer(nullptr),
-        mInputProducerSlot(-1) {
+        mInputProducerSlot(-1),
+        mBuffersToDetach(0) {
     // Initialize buffer queue and frame list based on pipeline max depth.
     size_t pipelineMaxDepth = kDefaultMaxPipelineDepth;
     if (client != 0) {
@@ -430,6 +431,11 @@
 void ZslProcessor::notifyInputReleased() {
     Mutex::Autolock l(mInputMutex);
 
+    mBuffersToDetach++;
+    mBuffersToDetachSignal.signal();
+}
+
+void ZslProcessor::doNotifyInputReleasedLocked() {
     assert(nullptr != mInputBuffer.get());
     assert(nullptr != mInputProducer.get());
 
@@ -736,9 +742,18 @@
 }
 
 bool ZslProcessor::threadLoop() {
-    // TODO: remove dependency on thread. For now, shut thread down right
-    // away.
-    return false;
+    Mutex::Autolock l(mInputMutex);
+
+    if (mBuffersToDetach == 0) {
+        status_t res = mBuffersToDetachSignal.waitRelative(mInputMutex, kWaitDuration);
+        if (res == TIMED_OUT) return true;
+    }
+    while (mBuffersToDetach > 0) {
+        doNotifyInputReleasedLocked();
+        mBuffersToDetach--;
+    }
+
+    return true;
 }
 
 void ZslProcessor::dumpZslQueue(int fd) const {
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.h b/services/camera/libcameraservice/api1/client2/ZslProcessor.h
index 6113d58..1db2403 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.h
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.h
@@ -142,6 +142,9 @@
     sp<IGraphicBufferProducer>               mInputProducer;
     int                                      mInputProducerSlot;
 
+    Condition                                mBuffersToDetachSignal;
+    int                                      mBuffersToDetach;
+
     virtual bool threadLoop();
 
     status_t clearZslQueueLocked();
@@ -156,6 +159,7 @@
         nsecs_t* actualTimestamp);
     status_t clearInputRingBufferLocked(nsecs_t* latestTimestamp);
     void notifyInputReleased();
+    void doNotifyInputReleasedLocked();
 
     bool isFixedFocusMode(uint8_t afMode) const;