Merge "AudioTrack: Prevent stop() from reissuing last marker event" into mnc-dr-dev
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 06116a5..26a0bb2 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -399,6 +399,7 @@
         uint32_t                            mInSamplingRate;
         audio_format_t                      mInFormat;
         audio_channel_mask_t                mInChannelMask;
+        sp<AudioIoDescriptor> getIoDescriptor_l(audio_io_handle_t ioHandle);
     };
 
     class AudioPolicyServiceClient: public IBinder::DeathRecipient,
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index 3d29e4a..27ad694 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -249,6 +249,12 @@
     virtual status_t onTransact(
             uint32_t code, const Parcel &data, Parcel *reply,
             uint32_t flags = 0);
+
+protected:
+    // check if the codec is secure.
+    virtual bool isSecure(IOMX::node_id node) {
+        return false;
+    }
 };
 
 class BnOMXObserver : public BnInterface<IOMXObserver> {
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 3bfb09a..9d645f0 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -476,7 +476,7 @@
         switch (event) {
         case AUDIO_OUTPUT_OPENED:
         case AUDIO_INPUT_OPENED: {
-            sp<AudioIoDescriptor> oldDesc = getIoDescriptor(ioDesc->mIoHandle);
+            sp<AudioIoDescriptor> oldDesc = getIoDescriptor_l(ioDesc->mIoHandle);
             if (oldDesc == 0) {
                 mIoDescriptors.add(ioDesc->mIoHandle, ioDesc);
             } else {
@@ -498,7 +498,7 @@
             } break;
         case AUDIO_OUTPUT_CLOSED:
         case AUDIO_INPUT_CLOSED: {
-            if (getIoDescriptor(ioDesc->mIoHandle) == 0) {
+            if (getIoDescriptor_l(ioDesc->mIoHandle) == 0) {
                 ALOGW("ioConfigChanged() closing unknown %s %d",
                       event == AUDIO_OUTPUT_CLOSED ? "output" : "input", ioDesc->mIoHandle);
                 break;
@@ -512,7 +512,7 @@
 
         case AUDIO_OUTPUT_CONFIG_CHANGED:
         case AUDIO_INPUT_CONFIG_CHANGED: {
-            sp<AudioIoDescriptor> oldDesc = getIoDescriptor(ioDesc->mIoHandle);
+            sp<AudioIoDescriptor> oldDesc = getIoDescriptor_l(ioDesc->mIoHandle);
             if (oldDesc == 0) {
                 ALOGW("ioConfigChanged() modifying unknown output! %d", ioDesc->mIoHandle);
                 break;
@@ -575,7 +575,7 @@
     return NO_ERROR;
 }
 
-sp<AudioIoDescriptor> AudioSystem::AudioFlingerClient::getIoDescriptor(audio_io_handle_t ioHandle)
+sp<AudioIoDescriptor> AudioSystem::AudioFlingerClient::getIoDescriptor_l(audio_io_handle_t ioHandle)
 {
     sp<AudioIoDescriptor> desc;
     ssize_t index = mIoDescriptors.indexOfKey(ioHandle);
@@ -585,6 +585,12 @@
     return desc;
 }
 
+sp<AudioIoDescriptor> AudioSystem::AudioFlingerClient::getIoDescriptor(audio_io_handle_t ioHandle)
+{
+    Mutex::Autolock _l(mLock);
+    return getIoDescriptor_l(ioHandle);
+}
+
 status_t AudioSystem::AudioFlingerClient::addAudioDeviceCallback(
         const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
 {
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 16da65e..5423c2a 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -963,6 +963,12 @@
 
             node_id node = (node_id)data.readInt32();
             OMX_U32 port_index = data.readInt32();
+            if (!isSecure(node) || port_index != 0 /* kPortIndexInput */) {
+                ALOGE("b/24310423");
+                reply->writeInt32(INVALID_OPERATION);
+                return NO_ERROR;
+            }
+
             size_t size = data.readInt64();
 
             buffer_id buffer;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 38ae6f3..a1af3aa 100755
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -2564,6 +2564,12 @@
                     mLastCommentName.setTo((const char *)buffer + 4);
                     break;
                 case FOURCC('d', 'a', 't', 'a'):
+                    if (size < 8) {
+                        delete[] buffer;
+                        buffer = NULL;
+                        ALOGE("b/24346430");
+                        return ERROR_MALFORMED;
+                    }
                     mLastCommentData.setTo((const char *)buffer + 8);
                     break;
             }
@@ -4144,7 +4150,10 @@
             (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
 
         size_t nal_size = parseNALSize(src);
-        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
+        if (mNALLengthSize > SIZE_MAX - nal_size) {
+            ALOGE("b/24441553, b/24445122");
+        }
+        if (mBuffer->range_length() - mNALLengthSize < nal_size) {
             ALOGE("incomplete NAL unit.");
 
             mBuffer->release();
@@ -4431,7 +4440,11 @@
             (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
 
         size_t nal_size = parseNALSize(src);
-        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
+        if (mNALLengthSize > SIZE_MAX - nal_size) {
+            ALOGE("b/24441553, b/24445122");
+        }
+
+        if (mBuffer->range_length() - mNALLengthSize < nal_size) {
             ALOGE("incomplete NAL unit.");
 
             mBuffer->release();
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp
index e9ead01..03e4119 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp
@@ -19,6 +19,7 @@
 #include "vlc_decode.h"
 #include "bitstream.h"
 #include "scaling.h"
+#include "log/log.h"
 
 /* ====================================================================== /
 Function : ConcealTexture_I()
@@ -137,6 +138,10 @@
 ****************************************************************************/
 void CopyVopMB(Vop *curr, uint8 *prevFrame, int mbnum, int width_Y, int height)
 {
+    if (curr == NULL || prevFrame == NULL) {
+        ALOGE("b/24630158");
+        return;
+    }
     int width_C = width_Y >> 1;
     int row = MB_SIZE;
     uint8              *y1, *y2, *u1, *u2, *v1, *v2;
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index e549ff6..725a574 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -601,13 +601,24 @@
     msg->setWhat(what);
 
     msg->mNumItems = static_cast<size_t>(parcel.readInt32());
+    if (msg->mNumItems > kMaxNumItems) {
+        ALOGE("Too large number of items clipped.");
+        msg->mNumItems = kMaxNumItems;
+    }
+
     for (size_t i = 0; i < msg->mNumItems; ++i) {
         Item *item = &msg->mItems[i];
 
         const char *name = parcel.readCString();
-        item->setName(name, strlen(name));
-        item->mType = static_cast<Type>(parcel.readInt32());
+        if (name == NULL) {
+            ALOGE("Failed reading name for an item. Parsing aborted.");
+            msg->mNumItems = i;
+            break;
+        }
 
+        item->mType = static_cast<Type>(parcel.readInt32());
+        // setName() happens below so that we don't leak memory when parsing
+        // is aborted in the middle.
         switch (item->mType) {
             case kTypeInt32:
             {
@@ -641,7 +652,16 @@
 
             case kTypeString:
             {
-                item->u.stringValue = new AString(parcel.readCString());
+                const char *stringValue = parcel.readCString();
+                if (stringValue == NULL) {
+                    ALOGE("Failed reading string value from a parcel. "
+                        "Parsing aborted.");
+                    msg->mNumItems = i;
+                    continue;
+                    // The loop will terminate subsequently.
+                } else {
+                    item->u.stringValue = new AString(stringValue);
+                }
                 break;
             }
 
@@ -660,6 +680,8 @@
                 TRESPASS();
             }
         }
+
+        item->setName(name, strlen(name));
     }
 
     return msg;
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index 00f87aa..4410579 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -194,6 +194,13 @@
 
     if (header.version_major == 4) {
         void *copy = malloc(size);
+        if (copy == NULL) {
+            free(mData);
+            mData = NULL;
+            ALOGE("b/24623447, no more memory");
+            return false;
+        }
+
         memcpy(copy, mData, size);
 
         bool success = removeUnsynchronizationV2_4(false /* iTunesHack */);
@@ -234,7 +241,14 @@
             return false;
         }
 
-        size_t extendedHeaderSize = U32_AT(&mData[0]) + 4;
+        size_t extendedHeaderSize = U32_AT(&mData[0]);
+        if (extendedHeaderSize > SIZE_MAX - 4) {
+            free(mData);
+            mData = NULL;
+            ALOGE("b/24623447, extendedHeaderSize is too large");
+            return false;
+        }
+        extendedHeaderSize += 4;
 
         if (extendedHeaderSize > mSize) {
             free(mData);
@@ -252,7 +266,10 @@
             if (extendedHeaderSize >= 10) {
                 size_t paddingSize = U32_AT(&mData[6]);
 
-                if (mFirstFrameOffset + paddingSize > mSize) {
+                if (paddingSize > SIZE_MAX - mFirstFrameOffset) {
+                    ALOGE("b/24623447, paddingSize is too large");
+                }
+                if (paddingSize > mSize - mFirstFrameOffset) {
                     free(mData);
                     mData = NULL;
 
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index d468dfc..e7c4f6d 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -140,6 +140,8 @@
 
     virtual void binderDied(const wp<IBinder> &the_late_who);
 
+    virtual bool isSecure(IOMX::node_id node);
+
     OMX_ERRORTYPE OnEvent(
             node_id node,
             OMX_IN OMX_EVENTTYPE eEvent,
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index f68e0a9..e5fb45b 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -125,6 +125,10 @@
             const void *data,
             size_t size);
 
+    bool isSecure() const {
+        return mIsSecure;
+    }
+
     // handles messages and removes them from the list
     void onMessages(std::list<omx_message> &messages);
     void onMessage(const omx_message &msg);
@@ -142,6 +146,7 @@
     OMX_HANDLETYPE mHandle;
     sp<IOMXObserver> mObserver;
     bool mDying;
+    bool mIsSecure;
 
     // Lock only covers mGraphicBufferSource.  We can't always use mLock
     // because of rare instances where we'd end up locking it recursively.
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index cb7ab5e..7f357c9 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -194,6 +194,11 @@
     instance->onObserverDied(mMaster);
 }
 
+bool OMX::isSecure(node_id node) {
+    OMXNodeInstance *instance = findInstance(node);
+    return (instance == NULL ? false : instance->isSecure());
+}
+
 bool OMX::livesLocally(node_id /* node */, pid_t pid) {
     return pid == getpid();
 }
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 9f1c5d8..94a213a 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -203,6 +203,7 @@
     mDebugLevelBumpPendingBuffers[1] = 0;
     mMetadataType[0] = kMetadataBufferTypeInvalid;
     mMetadataType[1] = kMetadataBufferTypeInvalid;
+    mIsSecure = AString(name).endsWith(".secure");
 }
 
 OMXNodeInstance::~OMXNodeInstance() {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 1a3a770..50d9d75 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -67,6 +67,7 @@
         mNextResultFrameNumber(0),
         mNextReprocessResultFrameNumber(0),
         mNextShutterFrameNumber(0),
+        mNextReprocessShutterFrameNumber(0),
         mListener(NULL)
 {
     ATRACE_CALL();
@@ -2534,18 +2535,6 @@
 void Camera3Device::notifyShutter(const camera3_shutter_msg_t &msg,
         NotificationListener *listener) {
     ssize_t idx;
-    // Verify ordering of shutter notifications
-    {
-        Mutex::Autolock l(mOutputLock);
-        // TODO: need to track errors for tighter bounds on expected frame number.
-        if (msg.frame_number < mNextShutterFrameNumber) {
-            SET_ERR("Shutter notification out-of-order. Expected "
-                    "notification for frame %d, got frame %d",
-                    mNextShutterFrameNumber, msg.frame_number);
-            return;
-        }
-        mNextShutterFrameNumber = msg.frame_number + 1;
-    }
 
     // Set timestamp for the request in the in-flight tracking
     // and get the request ID to send upstream
@@ -2555,6 +2544,29 @@
         if (idx >= 0) {
             InFlightRequest &r = mInFlightMap.editValueAt(idx);
 
+            // Verify ordering of shutter notifications
+            {
+                Mutex::Autolock l(mOutputLock);
+                // TODO: need to track errors for tighter bounds on expected frame number.
+                if (r.hasInputBuffer) {
+                    if (msg.frame_number < mNextReprocessShutterFrameNumber) {
+                        SET_ERR("Shutter notification out-of-order. Expected "
+                                "notification for frame %d, got frame %d",
+                                mNextReprocessShutterFrameNumber, msg.frame_number);
+                        return;
+                    }
+                    mNextReprocessShutterFrameNumber = msg.frame_number + 1;
+                } else {
+                    if (msg.frame_number < mNextShutterFrameNumber) {
+                        SET_ERR("Shutter notification out-of-order. Expected "
+                                "notification for frame %d, got frame %d",
+                                mNextShutterFrameNumber, msg.frame_number);
+                        return;
+                    }
+                    mNextShutterFrameNumber = msg.frame_number + 1;
+                }
+            }
+
             ALOGVV("Camera %d: %s: Shutter fired for frame %d (id %d) at %" PRId64,
                     mId, __FUNCTION__,
                     msg.frame_number, r.resultExtras.requestId, msg.timestamp);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 402cb1d..2cd5af3 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -162,7 +162,7 @@
     static const size_t        kInFlightWarnLimit = 20;
     static const size_t        kInFlightWarnLimitHighSpeed = 256; // batch size 32 * pipe depth 8
     // SCHED_FIFO priority for request submission thread in HFR mode
-    static const int           kConstrainedHighSpeedThreadPriority = 3;
+    static const int           kConstrainedHighSpeedThreadPriority = 1;
 
     struct                     RequestTrigger;
     // minimal jpeg buffer size: 256KB + blob header
@@ -771,7 +771,10 @@
     uint32_t               mNextResultFrameNumber;
     // the minimal frame number of the next reprocess result
     uint32_t               mNextReprocessResultFrameNumber;
+    // the minimal frame number of the next non-reprocess shutter
     uint32_t               mNextShutterFrameNumber;
+    // the minimal frame number of the next reprocess shutter
+    uint32_t               mNextReprocessShutterFrameNumber;
     List<CaptureResult>   mResultQueue;
     Condition              mResultSignal;
     NotificationListener  *mListener;