Merge changes from topic 'Bug 19769719'

* changes:
  stagefright: Rename mBuf to mSlot
  camera: Rename mBuf to mSlot
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
index 7c9720f..b359f57 100644
--- a/camera/ICameraService.cpp
+++ b/camera/ICameraService.cpp
@@ -94,11 +94,18 @@
     {
     }
 
-    // get number of cameras available
+    // get number of cameras available that support standard camera operations
     virtual int32_t getNumberOfCameras()
     {
+        return getNumberOfCameras(CAMERA_TYPE_BACKWARD_COMPATIBLE);
+    }
+
+    // get number of cameras available of a given type
+    virtual int32_t getNumberOfCameras(int type)
+    {
         Parcel data, reply;
         data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
+        data.writeInt32(type);
         remote()->transact(BnCameraService::GET_NUMBER_OF_CAMERAS, data, &reply);
 
         if (readExceptionCode(reply)) return 0;
@@ -337,7 +344,7 @@
         case GET_NUMBER_OF_CAMERAS: {
             CHECK_INTERFACE(ICameraService, data, reply);
             reply->writeNoException();
-            reply->writeInt32(getNumberOfCameras());
+            reply->writeInt32(getNumberOfCameras(data.readInt32()));
             return NO_ERROR;
         } break;
         case GET_CAMERA_INFO: {
diff --git a/camera/ICameraServiceProxy.cpp b/camera/ICameraServiceProxy.cpp
index 06a5afb..694e9c3 100644
--- a/camera/ICameraServiceProxy.cpp
+++ b/camera/ICameraServiceProxy.cpp
@@ -29,11 +29,21 @@
     BpCameraServiceProxy(const sp<IBinder>& impl) : BpInterface<ICameraServiceProxy>(impl) {}
 
     virtual void pingForUserUpdate() {
-        Parcel data, reply;
+        Parcel data;
         data.writeInterfaceToken(ICameraServiceProxy::getInterfaceDescriptor());
-        remote()->transact(BnCameraServiceProxy::PING_FOR_USER_UPDATE, data, &reply,
+        remote()->transact(BnCameraServiceProxy::PING_FOR_USER_UPDATE, data, nullptr,
                 IBinder::FLAG_ONEWAY);
     }
+
+    virtual void notifyCameraState(String16 cameraId, CameraState newCameraState) {
+        Parcel data;
+        data.writeInterfaceToken(ICameraServiceProxy::getInterfaceDescriptor());
+        data.writeString16(cameraId);
+        data.writeInt32(newCameraState);
+        remote()->transact(BnCameraServiceProxy::NOTIFY_CAMERA_STATE, data, nullptr,
+                IBinder::FLAG_ONEWAY);
+    }
+
 };
 
 
@@ -47,9 +57,16 @@
             pingForUserUpdate();
             return NO_ERROR;
         } break;
+        case NOTIFY_CAMERA_STATE: {
+            CHECK_INTERFACE(ICameraServiceProxy, data, reply);
+            String16 cameraId = data.readString16();
+            CameraState newCameraState =
+                static_cast<CameraState>(data.readInt32());
+            notifyCameraState(cameraId, newCameraState);
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
 }
 }; // namespace android
-
diff --git a/camera/camera2/ICameraDeviceUser.cpp b/camera/camera2/ICameraDeviceUser.cpp
index d2dc200..2a9fd2b 100644
--- a/camera/camera2/ICameraDeviceUser.cpp
+++ b/camera/camera2/ICameraDeviceUser.cpp
@@ -49,7 +49,8 @@
     WAIT_UNTIL_IDLE,
     FLUSH,
     PREPARE,
-    TEAR_DOWN
+    TEAR_DOWN,
+    PREPARE2
 };
 
 namespace {
@@ -366,6 +367,21 @@
         return reply.readInt32();
     }
 
+    virtual status_t prepare2(int maxCount, int streamId)
+    {
+        ALOGV("prepare2");
+        Parcel data, reply;
+
+        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
+        data.writeInt32(maxCount);
+        data.writeInt32(streamId);
+
+        remote()->transact(PREPARE2, data, &reply);
+
+        reply.readExceptionCode();
+        return reply.readInt32();
+    }
+
     virtual status_t tearDown(int streamId)
     {
         ALOGV("tearDown");
@@ -592,7 +608,14 @@
             reply->writeInt32(tearDown(streamId));
             return NO_ERROR;
         } break;
-
+        case PREPARE2: {
+            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
+            int maxCount = data.readInt32();
+            int streamId = data.readInt32();
+            reply->writeNoException();
+            reply->writeInt32(prepare2(maxCount, streamId));
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index a9c6eda..9368309 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -1016,7 +1016,10 @@
 
             if (meta != NULL) {
                 const char *mime;
-                CHECK(meta->findCString(kKeyMIMEType, &mime));
+                if (!meta->findCString(kKeyMIMEType, &mime)) {
+                    fprintf(stderr, "extractor did not provide MIME type.\n");
+                    return -1;
+                }
 
                 if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
                     syncInfoPresent = false;
@@ -1059,6 +1062,9 @@
                     meta = extractor->getTrackMetaData(
                             i, MediaExtractor::kIncludeExtensiveMetaData);
 
+                    if (meta == NULL) {
+                        break;
+                    }
                     const char *mime;
                     meta->findCString(kKeyMIMEType, &mime);
 
diff --git a/drm/drmserver/Android.mk b/drm/drmserver/Android.mk
index 48ea385..9b15f93 100644
--- a/drm/drmserver/Android.mk
+++ b/drm/drmserver/Android.mk
@@ -42,4 +42,6 @@
 
 LOCAL_32_BIT_ONLY := true
 
+LOCAL_INIT_RC := drmserver.rc
+
 include $(BUILD_EXECUTABLE)
diff --git a/drm/drmserver/drmserver.rc b/drm/drmserver/drmserver.rc
new file mode 100644
index 0000000..c6b8226
--- /dev/null
+++ b/drm/drmserver/drmserver.rc
@@ -0,0 +1,4 @@
+service drm /system/bin/drmserver
+    class main
+    user drm
+    group drm system inet drmrpc
diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h
index 5f85635..1b68b5f 100644
--- a/include/camera/ICameraService.h
+++ b/include/camera/ICameraService.h
@@ -64,6 +64,11 @@
     };
 
     enum {
+        CAMERA_TYPE_BACKWARD_COMPATIBLE = 0,
+        CAMERA_TYPE_ALL = 1,
+    };
+
+    enum {
         CAMERA_HAL_API_VERSION_UNSPECIFIED = -1
     };
 
@@ -81,7 +86,12 @@
 public:
     DECLARE_META_INTERFACE(CameraService);
 
+    // Get the number of cameras that support basic color camera operation
+    // (type CAMERA_TYPE_BACKWARD_COMPATIBLE)
     virtual int32_t  getNumberOfCameras() = 0;
+    // Get the number of cameras of the specified type, one of CAMERA_TYPE_*
+    // enums
+    virtual int32_t  getNumberOfCameras(int cameraType) = 0;
     virtual status_t getCameraInfo(int cameraId,
             /*out*/
             struct CameraInfo* cameraInfo) = 0;
diff --git a/include/camera/ICameraServiceProxy.h b/include/camera/ICameraServiceProxy.h
index 12a555f..2613c01 100644
--- a/include/camera/ICameraServiceProxy.h
+++ b/include/camera/ICameraServiceProxy.h
@@ -23,15 +23,30 @@
 
 namespace android {
 
+/**
+ * Interface from native camera service to managed-side camera service proxy.
+ *
+ * Keep in sync with frameworks/base/core/java/android/hardware/ICameraServiceProxy.aidl
+ *
+ */
 class ICameraServiceProxy : public IInterface {
 public:
     enum {
         PING_FOR_USER_UPDATE = IBinder::FIRST_CALL_TRANSACTION,
+        NOTIFY_CAMERA_STATE
+    };
+
+    enum CameraState {
+        CAMERA_STATE_OPEN,
+        CAMERA_STATE_ACTIVE,
+        CAMERA_STATE_IDLE,
+        CAMERA_STATE_CLOSED
     };
 
     DECLARE_META_INTERFACE(CameraServiceProxy);
 
     virtual void pingForUserUpdate() = 0;
+    virtual void notifyCameraState(String16 cameraId, CameraState newCameraState) = 0;
 };
 
 class BnCameraServiceProxy: public BnInterface<ICameraServiceProxy>
@@ -48,5 +63,3 @@
 }; // namespace android
 
 #endif // ANDROID_HARDWARE_ICAMERASERVICEPROXY_H
-
-
diff --git a/include/camera/camera2/ICameraDeviceUser.h b/include/camera/camera2/ICameraDeviceUser.h
index a7bf8ab..4d8eb53 100644
--- a/include/camera/camera2/ICameraDeviceUser.h
+++ b/include/camera/camera2/ICameraDeviceUser.h
@@ -140,6 +140,11 @@
     virtual status_t        prepare(int streamId) = 0;
 
     /**
+     * Preallocate up to maxCount buffers for a given output stream asynchronously.
+     */
+    virtual status_t        prepare2(int maxCount, int streamId) = 0;
+
+    /**
      * Free all unused buffers for a given output stream.
      */
     virtual status_t        tearDown(int streamId) = 0;
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 3fe749c..00df523 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -215,7 +215,6 @@
                     const KeyedVector<String8, String8> *headers);
 
             status_t        setDataSource(int fd, int64_t offset, int64_t length);
-            status_t        setDataSource(const sp<IStreamSource> &source);
             status_t        setDataSource(const sp<IDataSource> &source);
             status_t        setVideoSurfaceTexture(
                                     const sp<IGraphicBufferProducer>& bufferProducer);
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 05f6786..8b5b862 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -236,6 +236,7 @@
     bool mSentFormat;
     bool mIsVideo;
     bool mIsEncoder;
+    bool mFatalError;
     bool mShutdownInProgress;
     bool mExplicitShutdown;
 
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 726b197..8d4e15a 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -268,7 +268,7 @@
             return mSize <= sizeof(u.reservoir);
         }
 
-        void allocateStorage(size_t size);
+        void *allocateStorage(size_t size);
         void freeStorage();
 
         void *storage() {
diff --git a/media/img_utils/include/img_utils/DngUtils.h b/media/img_utils/include/img_utils/DngUtils.h
index 3dcedc5..1d8df9c 100644
--- a/media/img_utils/include/img_utils/DngUtils.h
+++ b/media/img_utils/include/img_utils/DngUtils.h
@@ -138,6 +138,34 @@
                                             double opticalCenterY,
                                             const double* kCoeffs);
 
+
+        /**
+         * Add FixBadPixelsList opcode for the given metadata parameters.
+         *
+         * Returns OK on success, or a negative error code.
+         */
+        virtual status_t addBadPixelListForMetadata(const uint32_t* hotPixels,
+                                                    uint32_t xyPairCount,
+                                                    uint32_t colorFilterArrangement);
+
+        /**
+         * Add FixBadPixelsList opcode.
+         *
+         * bayerPhase - 0=top-left of image is red, 1=top-left of image is green pixel in red row,
+         *              2=top-left of image is green pixel in blue row, 3=top-left of image is
+         *              blue.
+         * badPointCount - number of (x,y) pairs of bad pixels are given in badPointRowColPairs.
+         * badRectCount - number of (top, left, bottom, right) tuples are given in
+         *              badRectTopLeftBottomRightTuples
+         *
+         * Returns OK on success, or a negative error code.
+         */
+        virtual status_t addBadPixelList(uint32_t bayerPhase,
+                                         uint32_t badPointCount,
+                                         uint32_t badRectCount,
+                                         const uint32_t* badPointRowColPairs,
+                                         const uint32_t* badRectTopLeftBottomRightTuples);
+
         // TODO: Add other Opcode methods
     protected:
         static const uint32_t FLAG_OPTIONAL = 0x1u;
@@ -146,6 +174,7 @@
         // Opcode IDs
         enum {
             WARP_RECTILINEAR_ID = 1,
+            FIX_BAD_PIXELS_LIST = 5,
             GAIN_MAP_ID = 9,
         };
 
@@ -161,6 +190,8 @@
         ByteArrayOutput mOpList;
         EndianOutput mEndianOut;
 
+        status_t addOpcodePreamble(uint32_t opcodeId);
+
 };
 
 } /*namespace img_utils*/
diff --git a/media/img_utils/src/DngUtils.cpp b/media/img_utils/src/DngUtils.cpp
index b213403..9473dce 100644
--- a/media/img_utils/src/DngUtils.cpp
+++ b/media/img_utils/src/DngUtils.cpp
@@ -224,13 +224,7 @@
                                        uint32_t mapPlanes,
                                        const float* mapGains) {
 
-    uint32_t opcodeId = GAIN_MAP_ID;
-
-    status_t err = mEndianOut.write(&opcodeId, 0, 1);
-    if (err != OK) return err;
-
-    uint8_t version[] = {1, 3, 0, 0};
-    err = mEndianOut.write(version, 0, NELEMS(version));
+    status_t err = addOpcodePreamble(GAIN_MAP_ID);
     if (err != OK) return err;
 
     // Allow this opcode to be skipped if not supported
@@ -334,13 +328,7 @@
                                                double opticalCenterY,
                                                const double* kCoeffs) {
 
-    uint32_t opcodeId = WARP_RECTILINEAR_ID;
-
-    status_t err = mEndianOut.write(&opcodeId, 0, 1);
-    if (err != OK) return err;
-
-    uint8_t version[] = {1, 3, 0, 0};
-    err = mEndianOut.write(version, 0, NELEMS(version));
+    status_t err = addOpcodePreamble(WARP_RECTILINEAR_ID);
     if (err != OK) return err;
 
     // Allow this opcode to be skipped if not supported
@@ -373,5 +361,74 @@
     return OK;
 }
 
+status_t OpcodeListBuilder::addBadPixelListForMetadata(const uint32_t* hotPixels,
+                                                       uint32_t xyPairCount,
+                                                       uint32_t colorFilterArrangement) {
+    if (colorFilterArrangement > 3) {
+        ALOGE("%s:  Unknown color filter arrangement %" PRIu32, __FUNCTION__,
+                colorFilterArrangement);
+        return BAD_VALUE;
+    }
+
+    return addBadPixelList(colorFilterArrangement, xyPairCount, 0, hotPixels, nullptr);
+}
+
+status_t OpcodeListBuilder::addBadPixelList(uint32_t bayerPhase,
+                                            uint32_t badPointCount,
+                                            uint32_t badRectCount,
+                                            const uint32_t* badPointRowColPairs,
+                                            const uint32_t* badRectTopLeftBottomRightTuples) {
+
+    status_t err = addOpcodePreamble(FIX_BAD_PIXELS_LIST);
+    if (err != OK) return err;
+
+    // Allow this opcode to be skipped if not supported
+    uint32_t flags = FLAG_OPTIONAL;
+
+    err = mEndianOut.write(&flags, 0, 1);
+    if (err != OK) return err;
+
+    const uint32_t NUM_NON_VARLEN_FIELDS = 3;
+    const uint32_t SIZE_OF_POINT = 2;
+    const uint32_t SIZE_OF_RECT = 4;
+
+    uint32_t totalSize =  (NUM_NON_VARLEN_FIELDS  + badPointCount * SIZE_OF_POINT +
+            badRectCount * SIZE_OF_RECT) * sizeof(uint32_t);
+    err = mEndianOut.write(&totalSize, 0, 1);
+    if (err != OK) return err;
+
+    err = mEndianOut.write(&bayerPhase, 0, 1);
+    if (err != OK) return err;
+
+    err = mEndianOut.write(&badPointCount, 0, 1);
+    if (err != OK) return err;
+
+    err = mEndianOut.write(&badRectCount, 0, 1);
+    if (err != OK) return err;
+
+    if (badPointCount > 0) {
+        err = mEndianOut.write(badPointRowColPairs, 0, SIZE_OF_POINT * badPointCount);
+        if (err != OK) return err;
+    }
+
+    if (badRectCount > 0) {
+        err = mEndianOut.write(badRectTopLeftBottomRightTuples, 0, SIZE_OF_RECT * badRectCount);
+        if (err != OK) return err;
+    }
+
+    mCount++;
+    return OK;
+}
+
+status_t OpcodeListBuilder::addOpcodePreamble(uint32_t opcodeId) {
+    status_t err = mEndianOut.write(&opcodeId, 0, 1);
+    if (err != OK) return err;
+
+    uint8_t version[] = {1, 3, 0, 0};
+    err = mEndianOut.write(version, 0, NELEMS(version));
+    if (err != OK) return err;
+    return OK;
+}
+
 } /*namespace img_utils*/
 } /*namespace android*/
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index af904a6..999e7eb 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -722,17 +722,20 @@
 
     if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE){
         pOutTmp = pOut;
-    }else if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
+    } else if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
         if (pContext->pBundledContext->frameCount != frameCount) {
             if (pContext->pBundledContext->workBuffer != NULL) {
                 free(pContext->pBundledContext->workBuffer);
             }
             pContext->pBundledContext->workBuffer =
-                    (LVM_INT16 *)malloc(frameCount * sizeof(LVM_INT16) * 2);
+                    (LVM_INT16 *)calloc(frameCount, sizeof(LVM_INT16) * 2);
+            if (pContext->pBundledContext->workBuffer == NULL) {
+                return -ENOMEM;
+            }
             pContext->pBundledContext->frameCount = frameCount;
         }
         pOutTmp = pContext->pBundledContext->workBuffer;
-    }else{
+    } else {
         ALOGV("LVM_ERROR : LvmBundle_process invalid access mode");
         return -EINVAL;
     }
@@ -2872,7 +2875,7 @@
     EffectContext * pContext = (EffectContext *) self;
     LVM_ReturnStatus_en     LvmStatus = LVM_SUCCESS;                /* Function call status */
     int    status = 0;
-    int    lvmStatus = 0;
+    int    processStatus = 0;
     LVM_INT16   *in  = (LVM_INT16 *)inBuffer->raw;
     LVM_INT16   *out = (LVM_INT16 *)outBuffer->raw;
 
@@ -2960,19 +2963,22 @@
         //pContext->pBundledContext->NumberEffectsEnabled,
         //pContext->pBundledContext->NumberEffectsCalled, pContext->EffectType);
 
-        if(status == -ENODATA){
+        if (status == -ENODATA){
             ALOGV("\tEffect_process() processing last frame");
         }
         pContext->pBundledContext->NumberEffectsCalled = 0;
         /* Process all the available frames, block processing is
            handled internalLY by the LVM bundle */
-        lvmStatus = android::LvmBundle_process(    (LVM_INT16 *)inBuffer->raw,
+        processStatus = android::LvmBundle_process(    (LVM_INT16 *)inBuffer->raw,
                                                 (LVM_INT16 *)outBuffer->raw,
                                                 outBuffer->frameCount,
                                                 pContext);
-        if(lvmStatus != LVM_SUCCESS){
-            ALOGV("\tLVM_ERROR : LvmBundle_process returned error %d", lvmStatus);
-            return lvmStatus;
+        if (processStatus != 0){
+            ALOGV("\tLVM_ERROR : LvmBundle_process returned error %d", processStatus);
+            if (status == 0) {
+                status = processStatus;
+            }
+            return status;
         }
     } else {
         //ALOGV("\tEffect_process Not Calling process with %d effects enabled, %d called: Effect %d",
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index 6dd4439..de7bdd8 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -1214,9 +1214,17 @@
                 fr = inBuffer->frameCount;
             }
             if (session->inBufSize < session->framesIn + fr) {
+                int16_t *buf;
                 session->inBufSize = session->framesIn + fr;
-                session->inBuf = (int16_t *)realloc(session->inBuf,
+                buf = (int16_t *)realloc(session->inBuf,
                                  session->inBufSize * session->inChannelCount * sizeof(int16_t));
+                if (buf == NULL) {
+                    session->framesIn = 0;
+                    free(session->inBuf);
+                    session->inBuf = NULL;
+                    return -ENOMEM;
+                }
+                session->inBuf = buf;
             }
             memcpy(session->inBuf + session->framesIn * session->inChannelCount,
                    inBuffer->s16,
@@ -1286,9 +1294,17 @@
         effect->session->apm->ProcessStream(session->procFrame);
 
         if (session->outBufSize < session->framesOut + session->frameCount) {
+            int16_t *buf;
             session->outBufSize = session->framesOut + session->frameCount;
-            session->outBuf = (int16_t *)realloc(session->outBuf,
-                              session->outBufSize * session->outChannelCount * sizeof(int16_t));
+            buf = (int16_t *)realloc(session->outBuf,
+                             session->outBufSize * session->outChannelCount * sizeof(int16_t));
+            if (buf == NULL) {
+                session->framesOut = 0;
+                free(session->outBuf);
+                session->outBuf = NULL;
+                return -ENOMEM;
+            }
+            session->outBuf = buf;
         }
 
         if (session->outResampler != NULL) {
@@ -1744,9 +1760,17 @@
                 fr = inBuffer->frameCount;
             }
             if (session->revBufSize < session->framesRev + fr) {
+                int16_t *buf;
                 session->revBufSize = session->framesRev + fr;
-                session->revBuf = (int16_t *)realloc(session->revBuf,
-                                  session->revBufSize * session->inChannelCount * sizeof(int16_t));
+                buf = (int16_t *)realloc(session->revBuf,
+                                 session->revBufSize * session->inChannelCount * sizeof(int16_t));
+                if (buf == NULL) {
+                    session->framesRev = 0;
+                    free(session->revBuf);
+                    session->revBuf = NULL;
+                    return -ENOMEM;
+                }
+                session->revBuf = buf;
             }
             memcpy(session->revBuf + session->framesRev * session->inChannelCount,
                    inBuffer->s16,
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 7befe5d..707ac97 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -325,7 +325,7 @@
     mTransfer = transferType;
     mDoNotReconnect = doNotReconnect;
 
-    ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(),
+    ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %zu", sharedBuffer->pointer(),
             sharedBuffer->size());
 
     ALOGV("set() streamType %d frameCount %zu flags %04x", streamType, frameCount, flags);
@@ -1843,7 +1843,11 @@
         case NO_ERROR:
         case DEAD_OBJECT:
         case TIMED_OUT:
-            mCbf(EVENT_STREAM_END, mUserData, NULL);
+            if (status != DEAD_OBJECT) {
+                // for DEAD_OBJECT, we do not send a EVENT_STREAM_END after stop();
+                // instead, the application should handle the EVENT_NEW_IAUDIOTRACK.
+                mCbf(EVENT_STREAM_END, mUserData, NULL);
+            }
             {
                 AutoMutex lock(mLock);
                 // The previously assigned value of waitStreamEnd is no longer valid,
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index a3f014b..18a933f 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -1104,8 +1104,10 @@
         case OPEN_OUTPUT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             audio_module_handle_t module = (audio_module_handle_t)data.readInt32();
-            audio_config_t config;
-            data.read(&config, sizeof(audio_config_t));
+            audio_config_t config = {};
+            if (data.read(&config, sizeof(audio_config_t)) != NO_ERROR) {
+                ALOGE("b/23905951");
+            }
             audio_devices_t devices = (audio_devices_t)data.readInt32();
             String8 address(data.readString8());
             audio_output_flags_t flags = (audio_output_flags_t) data.readInt32();
@@ -1149,8 +1151,10 @@
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             audio_module_handle_t module = (audio_module_handle_t)data.readInt32();
             audio_io_handle_t input = (audio_io_handle_t)data.readInt32();
-            audio_config_t config;
-            data.read(&config, sizeof(audio_config_t));
+            audio_config_t config = {};
+            if (data.read(&config, sizeof(audio_config_t)) != NO_ERROR) {
+                ALOGE("b/23905951");
+            }
             audio_devices_t device = (audio_devices_t)data.readInt32();
             String8 address(data.readString8());
             audio_source_t source = (audio_source_t)data.readInt32();
@@ -1255,8 +1259,10 @@
         }
         case CREATE_EFFECT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            effect_descriptor_t desc;
-            data.read(&desc, sizeof(effect_descriptor_t));
+            effect_descriptor_t desc = {};
+            if (data.read(&desc, sizeof(effect_descriptor_t)) != NO_ERROR) {
+                ALOGE("b/23905951");
+            }
             sp<IEffectClient> client = interface_cast<IEffectClient>(data.readStrongBinder());
             int32_t priority = data.readInt32();
             audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
@@ -1333,8 +1339,10 @@
         } break;
         case GET_AUDIO_PORT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            struct audio_port port;
-            data.read(&port, sizeof(struct audio_port));
+            struct audio_port port = {};
+            if (data.read(&port, sizeof(struct audio_port)) != NO_ERROR) {
+                ALOGE("b/23905951");
+            }
             status_t status = getAudioPort(&port);
             reply->writeInt32(status);
             if (status == NO_ERROR) {
@@ -1346,8 +1354,10 @@
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             struct audio_patch patch;
             data.read(&patch, sizeof(struct audio_patch));
-            audio_patch_handle_t handle;
-            data.read(&handle, sizeof(audio_patch_handle_t));
+            audio_patch_handle_t handle = {};
+            if (data.read(&handle, sizeof(audio_patch_handle_t)) != NO_ERROR) {
+                ALOGE("b/23905951");
+            }
             status_t status = createAudioPatch(&patch, &handle);
             reply->writeInt32(status);
             if (status == NO_ERROR) {
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 3348441..0cc954f 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -877,7 +877,7 @@
             if (hasOffloadInfo) {
                 data.read(&offloadInfo, sizeof(audio_offload_info_t));
             }
-            audio_io_handle_t output;
+            audio_io_handle_t output = 0;
             status_t status = getOutputForAttr(hasAttributes ? &attr : NULL,
                     &output, session, &stream, uid,
                     samplingRate, format, channelMask,
@@ -994,7 +994,7 @@
             audio_stream_type_t stream =
                     static_cast <audio_stream_type_t>(data.readInt32());
             audio_devices_t device = static_cast <audio_devices_t>(data.readInt32());
-            int index;
+            int index = 0;
             status_t status = getStreamVolumeIndex(stream, &index, device);
             reply->writeInt32(index);
             reply->writeInt32(static_cast <uint32_t>(status));
@@ -1148,8 +1148,10 @@
 
         case GET_AUDIO_PORT: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
-            struct audio_port port;
-            data.read(&port, sizeof(struct audio_port));
+            struct audio_port port = {};
+            if (data.read(&port, sizeof(struct audio_port)) != NO_ERROR) {
+                ALOGE("b/23912202");
+            }
             status_t status = getAudioPort(&port);
             reply->writeInt32(status);
             if (status == NO_ERROR) {
@@ -1162,8 +1164,10 @@
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             struct audio_patch patch;
             data.read(&patch, sizeof(struct audio_patch));
-            audio_patch_handle_t handle;
-            data.read(&handle, sizeof(audio_patch_handle_t));
+            audio_patch_handle_t handle = {};
+            if (data.read(&handle, sizeof(audio_patch_handle_t)) != NO_ERROR) {
+                ALOGE("b/23912202");
+            }
             status_t status = createAudioPatch(&patch, &handle);
             reply->writeInt32(status);
             if (status == NO_ERROR) {
@@ -1292,7 +1296,7 @@
             data.read(&source, sizeof(struct audio_port_config));
             audio_attributes_t attributes;
             data.read(&attributes, sizeof(audio_attributes_t));
-            audio_io_handle_t handle;
+            audio_io_handle_t handle = {};
             status_t status = startAudioSource(&source, &attributes, &handle);
             reply->writeInt32(status);
             reply->writeInt32(handle);
diff --git a/media/libmedia/ICrypto.cpp b/media/libmedia/ICrypto.cpp
index 2f440fe..9703b0d 100644
--- a/media/libmedia/ICrypto.cpp
+++ b/media/libmedia/ICrypto.cpp
@@ -293,9 +293,9 @@
                     subSamples,
                     sizeof(CryptoPlugin::SubSample) * numSubSamples);
 
-            void *dstPtr;
+            void *secureBufferId, *dstPtr;
             if (secure) {
-                dstPtr = reinterpret_cast<void *>(static_cast<uintptr_t>(data.readInt64()));
+                secureBufferId = reinterpret_cast<void *>(static_cast<uintptr_t>(data.readInt64()));
             } else {
                 dstPtr = malloc(totalSize);
             }
@@ -303,7 +303,25 @@
             AString errorDetailMsg;
             ssize_t result;
 
-            if (offset + totalSize > sharedBuffer->size()) {
+            size_t sumSubsampleSizes = 0;
+            bool overflow = false;
+            for (int32_t i = 0; i < numSubSamples; ++i) {
+                CryptoPlugin::SubSample &ss = subSamples[i];
+                if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfEncryptedData) {
+                    sumSubsampleSizes += ss.mNumBytesOfEncryptedData;
+                } else {
+                    overflow = true;
+                }
+                if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfClearData) {
+                    sumSubsampleSizes += ss.mNumBytesOfClearData;
+                } else {
+                    overflow = true;
+                }
+            }
+
+            if (overflow || sumSubsampleSizes != totalSize) {
+                result = -EINVAL;
+            } else if (offset + totalSize > sharedBuffer->size()) {
                 result = -EINVAL;
             } else {
                 result = decrypt(
@@ -313,7 +331,7 @@
                     mode,
                     sharedBuffer, offset,
                     subSamples, numSubSamples,
-                    dstPtr,
+                    secure ? secureBufferId : dstPtr,
                     &errorDetailMsg);
             }
 
diff --git a/media/libmedia/IEffect.cpp b/media/libmedia/IEffect.cpp
index eb4b098..faf5795 100644
--- a/media/libmedia/IEffect.cpp
+++ b/media/libmedia/IEffect.cpp
@@ -85,13 +85,15 @@
         data.writeInt32(size);
 
         status_t status = remote()->transact(COMMAND, data, &reply);
+        if (status == NO_ERROR) {
+            status = reply.readInt32();
+        }
         if (status != NO_ERROR) {
             if (pReplySize != NULL)
                 *pReplySize = 0;
             return status;
         }
 
-        status = reply.readInt32();
         size = reply.readInt32();
         if (size != 0 && pReplyData != NULL && pReplySize != NULL) {
             reply.read(pReplyData, size);
@@ -154,23 +156,34 @@
             uint32_t cmdSize = data.readInt32();
             char *cmd = NULL;
             if (cmdSize) {
-                cmd = (char *)malloc(cmdSize);
+                cmd = (char *)calloc(cmdSize, 1);
+                if (cmd == NULL) {
+                    reply->writeInt32(NO_MEMORY);
+                    return NO_ERROR;
+                }
                 data.read(cmd, cmdSize);
             }
             uint32_t replySize = data.readInt32();
             uint32_t replySz = replySize;
             char *resp = NULL;
             if (replySize) {
-                resp = (char *)malloc(replySize);
+                resp = (char *)calloc(replySize, 1);
+                if (resp == NULL) {
+                    free(cmd);
+                    reply->writeInt32(NO_MEMORY);
+                    return NO_ERROR;
+                }
             }
             status_t status = command(cmdCode, cmdSize, cmd, &replySz, resp);
             reply->writeInt32(status);
-            if (replySz < replySize) {
-                replySize = replySz;
-            }
-            reply->writeInt32(replySize);
-            if (replySize) {
-                reply->write(resp, replySize);
+            if (status == NO_ERROR) {
+                if (replySz < replySize) {
+                    replySize = replySz;
+                }
+                reply->writeInt32(replySize);
+                if (replySize) {
+                    reply->write(resp, replySize);
+                }
             }
             if (cmd) {
                 free(cmd);
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index bde35f2..942aec3 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -566,7 +566,7 @@
         } break;
         case GET_CURRENT_POSITION: {
             CHECK_INTERFACE(IMediaPlayer, data, reply);
-            int msec;
+            int msec = 0;
             status_t ret = getCurrentPosition(&msec);
             reply->writeInt32(msec);
             reply->writeInt32(ret);
@@ -574,7 +574,7 @@
         } break;
         case GET_DURATION: {
             CHECK_INTERFACE(IMediaPlayer, data, reply);
-            int msec;
+            int msec = 0;
             status_t ret = getDuration(&msec);
             reply->writeInt32(msec);
             reply->writeInt32(ret);
@@ -653,6 +653,7 @@
             CHECK_INTERFACE(IMediaPlayer, data, reply);
 
             struct sockaddr_in endpoint;
+            memset(&endpoint, 0, sizeof(endpoint));
             int amt = data.readInt32();
             if (amt == sizeof(endpoint)) {
                 data.read(&endpoint, sizeof(struct sockaddr_in));
@@ -667,6 +668,7 @@
             CHECK_INTERFACE(IMediaPlayer, data, reply);
 
             struct sockaddr_in endpoint;
+            memset(&endpoint, 0, sizeof(endpoint));
             status_t res = getRetransmitEndpoint(&endpoint);
 
             reply->writeInt32(res);
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 502ab2d..337e963 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -181,22 +181,6 @@
     return err;
 }
 
-status_t MediaPlayer::setDataSource(const sp<IStreamSource> &source)
-{
-    ALOGV("setDataSource");
-    status_t err = UNKNOWN_ERROR;
-    const sp<IMediaPlayerService>& service(getMediaPlayerService());
-    if (service != 0) {
-        sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
-        if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
-            (NO_ERROR != player->setDataSource(source))) {
-            player.clear();
-        }
-        err = attachNewPlayer(player);
-    }
-    return err;
-}
-
 status_t MediaPlayer::setDataSource(const sp<IDataSource> &source)
 {
     ALOGV("setDataSource(IDataSource)");
diff --git a/media/libmediaplayerservice/Drm.cpp b/media/libmediaplayerservice/Drm.cpp
index a7f6f8b..b9cfe80 100644
--- a/media/libmediaplayerservice/Drm.cpp
+++ b/media/libmediaplayerservice/Drm.cpp
@@ -40,9 +40,6 @@
 }
 
 static bool checkPermission(const char* permissionString) {
-#ifndef HAVE_ANDROID_OS
-    return true;
-#endif
     if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
     bool ok = checkCallingPermission(String16(permissionString));
     if (!ok) ALOGE("Request requires %s", permissionString);
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index cf8ebd8..8db07ca 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -253,9 +253,6 @@
 
 
 static bool checkPermission(const char* permissionString) {
-#ifndef HAVE_ANDROID_OS
-    return true;
-#endif
     if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
     bool ok = checkCallingPermission(String16(permissionString));
     if (!ok) ALOGE("Request requires %s", permissionString);
@@ -1733,7 +1730,7 @@
     t->setVolume(mLeftVolume, mRightVolume);
 
     mSampleRateHz = sampleRate;
-    mFlags = t->getFlags(); // we suggest the flags above, but new AudioTrack() may not grant it.
+    mFlags = flags;
     mMsecsPerFrame = 1E3f / (mPlaybackRate.mSpeed * sampleRate);
     mFrameSize = t->frameSize();
     uint32_t pos;
@@ -1745,7 +1742,7 @@
     status_t res = NO_ERROR;
     // Note some output devices may give us a direct track even though we don't specify it.
     // Example: Line application b/17459982.
-    if ((mFlags & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT)) == 0) {
+    if ((t->getFlags() & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT)) == 0) {
         res = t->setPlaybackRate(mPlaybackRate);
         if (res == NO_ERROR) {
             t->setAuxEffectSendLevel(mSendLevel);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index f761dec..08c7899 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -46,9 +46,6 @@
 const char* recordAudioPermission = "android.permission.RECORD_AUDIO";
 
 static bool checkPermission(const char* permissionString) {
-#ifndef HAVE_ANDROID_OS
-    return true;
-#endif
     if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
     bool ok = checkCallingPermission(String16(permissionString));
     if (!ok) ALOGE("Request requires %s", permissionString);
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 27a2934..c5b8301 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -211,6 +211,9 @@
 
     for (size_t i = 0; i < numtracks; ++i) {
         sp<MediaSource> track = extractor->getTrack(i);
+        if (track == NULL) {
+            continue;
+        }
 
         sp<MetaData> meta = extractor->getTrackMetaData(i);
 
@@ -253,22 +256,25 @@
             }
         }
 
-        if (track != NULL) {
-            mSources.push(track);
-            int64_t durationUs;
-            if (meta->findInt64(kKeyDuration, &durationUs)) {
-                if (durationUs > mDurationUs) {
-                    mDurationUs = durationUs;
-                }
-            }
-
-            int32_t bitrate;
-            if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) {
-                totalBitrate += bitrate;
-            } else {
-                totalBitrate = -1;
+        mSources.push(track);
+        int64_t durationUs;
+        if (meta->findInt64(kKeyDuration, &durationUs)) {
+            if (durationUs > mDurationUs) {
+                mDurationUs = durationUs;
             }
         }
+
+        int32_t bitrate;
+        if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) {
+            totalBitrate += bitrate;
+        } else {
+            totalBitrate = -1;
+        }
+    }
+
+    if (mSources.size() == 0) {
+        ALOGE("b/23705695");
+        return UNKNOWN_ERROR;
     }
 
     mBitrate = totalBitrate;
@@ -318,7 +324,7 @@
 
 status_t NuPlayer::GenericSource::setBuffers(
         bool audio, Vector<MediaBuffer *> &buffers) {
-    if (mIsSecure && !audio) {
+    if (mIsSecure && !audio && mVideoTrack.mSource != NULL) {
         return mVideoTrack.mSource->setBuffers(buffers);
     }
     return INVALID_OPERATION;
@@ -467,9 +473,17 @@
 
 void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) {
     if (err != OK) {
-        mDataSource.clear();
-        mCachedSource.clear();
-        mHttpSource.clear();
+        {
+            sp<DataSource> dataSource = mDataSource;
+            sp<NuCachedSource2> cachedSource = mCachedSource;
+            sp<DataSource> httpSource = mHttpSource;
+            {
+                Mutex::Autolock _l(mDisconnectLock);
+                mDataSource.clear();
+                mCachedSource.clear();
+                mHttpSource.clear();
+            }
+        }
         mBitrate = -1;
 
         cancelPollBuffering();
@@ -522,13 +536,20 @@
 }
 
 void NuPlayer::GenericSource::disconnect() {
-    if (mDataSource != NULL) {
+    sp<DataSource> dataSource, httpSource;
+    {
+        Mutex::Autolock _l(mDisconnectLock);
+        dataSource = mDataSource;
+        httpSource = mHttpSource;
+    }
+
+    if (dataSource != NULL) {
         // disconnect data source
-        if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
-            static_cast<NuCachedSource2 *>(mDataSource.get())->disconnect();
+        if (dataSource->flags() & DataSource::kIsCachingDataSource) {
+            static_cast<NuCachedSource2 *>(dataSource.get())->disconnect();
         }
-    } else if (mHttpSource != NULL) {
-        static_cast<HTTPBase *>(mHttpSource.get())->disconnect();
+    } else if (httpSource != NULL) {
+        static_cast<HTTPBase *>(httpSource.get())->disconnect();
     }
 }
 
@@ -748,6 +769,11 @@
           break;
       }
 
+      case kWhatSendGlobalTimedTextData:
+      {
+          sendGlobalTextData(kWhatTimedTextData, mFetchTimedTextDataGeneration, msg);
+          break;
+      }
       case kWhatSendTimedTextData:
       {
           sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
@@ -942,6 +968,37 @@
     }
 }
 
+void NuPlayer::GenericSource::sendGlobalTextData(
+        uint32_t what,
+        int32_t curGen,
+        sp<AMessage> msg) {
+    int32_t msgGeneration;
+    CHECK(msg->findInt32("generation", &msgGeneration));
+    if (msgGeneration != curGen) {
+        // stale
+        return;
+    }
+
+    uint32_t textType;
+    const void *data;
+    size_t size = 0;
+    if (mTimedTextTrack.mSource->getFormat()->findData(
+                    kKeyTextFormatData, &textType, &data, &size)) {
+        mGlobalTimedText = new ABuffer(size);
+        if (mGlobalTimedText->data()) {
+            memcpy(mGlobalTimedText->data(), data, size);
+            sp<AMessage> globalMeta = mGlobalTimedText->meta();
+            globalMeta->setInt64("timeUs", 0);
+            globalMeta->setString("mime", MEDIA_MIMETYPE_TEXT_3GPP);
+            globalMeta->setInt32("global", 1);
+            sp<AMessage> notify = dupNotify();
+            notify->setInt32("what", what);
+            notify->setBuffer("buffer", mGlobalTimedText);
+            notify->post();
+        }
+    }
+}
+
 sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) {
     sp<AMessage> msg = new AMessage(kWhatGetFormat, this);
     msg->setInt32("audio", audio);
@@ -1254,6 +1311,10 @@
             msg->post();
         }
 
+        sp<AMessage> msg2 = new AMessage(kWhatSendGlobalTimedTextData, this);
+        msg2->setInt32("generation", mFetchTimedTextDataGeneration);
+        msg2->post();
+
         if (mTimedTextTrack.mSource != NULL
                 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
             sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index dc85d2d..035cc1f 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -90,6 +90,7 @@
         kWhatFetchSubtitleData,
         kWhatFetchTimedTextData,
         kWhatSendSubtitleData,
+        kWhatSendGlobalTimedTextData,
         kWhatSendTimedTextData,
         kWhatChangeAVSource,
         kWhatPollBuffering,
@@ -151,8 +152,10 @@
     bool mBuffering;
     bool mPrepareBuffering;
     int32_t mPrevBufferPercentage;
+    sp<ABuffer> mGlobalTimedText;
 
     mutable Mutex mReadBufferLock;
+    mutable Mutex mDisconnectLock;
 
     sp<ALooper> mLooper;
 
@@ -186,6 +189,10 @@
             uint32_t what, media_track_type type,
             int32_t curGen, sp<AnotherPacketSource> packets, sp<AMessage> msg);
 
+    void sendGlobalTextData(
+            uint32_t what,
+            int32_t curGen, sp<AMessage> msg);
+
     void sendTextData(
             uint32_t what, media_track_type type,
             int32_t curGen, sp<AnotherPacketSource> packets, sp<AMessage> msg);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 214315f..e5eb4be 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -632,10 +632,13 @@
 
             ALOGD("onSetVideoSurface(%p, %s video decoder)",
                     surface.get(),
-                    (mSource != NULL && mSource->getFormat(false /* audio */) != NULL
+                    (mSource != NULL && mStarted && mSource->getFormat(false /* audio */) != NULL
                             && mVideoDecoder != NULL) ? "have" : "no");
 
-            if (mSource == NULL || mSource->getFormat(false /* audio */) == NULL
+            // Need to check mStarted before calling mSource->getFormat because NuPlayer might
+            // be in preparing state and it could take long time.
+            // When mStarted is true, mSource must have been set.
+            if (mSource == NULL || !mStarted || mSource->getFormat(false /* audio */) == NULL
                     // NOTE: mVideoDecoder's mSurface is always non-null
                     || (mVideoDecoder != NULL && mVideoDecoder->setVideoSurface(surface) == OK)) {
                 performSetSurface(surface);
@@ -1485,7 +1488,9 @@
 }
 
 status_t NuPlayer::instantiateDecoder(bool audio, sp<DecoderBase> *decoder) {
-    if (*decoder != NULL) {
+    // The audio decoder could be cleared by tear down. If still in shut down
+    // process, no need to create a new audio decoder.
+    if (*decoder != NULL || (audio && mFlushingAudio == SHUT_DOWN)) {
         return OK;
     }
 
@@ -2285,7 +2290,7 @@
     const void *data;
     size_t size = 0;
     int64_t timeUs;
-    int32_t flag = TextDescriptions::LOCAL_DESCRIPTIONS;
+    int32_t flag = TextDescriptions::IN_BAND_TEXT_3GPP;
 
     AString mime;
     CHECK(buffer->meta()->findString("mime", &mime));
@@ -2297,7 +2302,12 @@
     Parcel parcel;
     if (size > 0) {
         CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
-        flag |= TextDescriptions::IN_BAND_TEXT_3GPP;
+        int32_t global = 0;
+        if (buffer->meta()->findInt32("global", &global) && global) {
+            flag |= TextDescriptions::GLOBAL_DESCRIPTIONS;
+        } else {
+            flag |= TextDescriptions::LOCAL_DESCRIPTIONS;
+        }
         TextDescriptions::getParcelOfDescriptions(
                 (const uint8_t *)data, size, flag, timeUs / 1000, &parcel);
     }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 3646828..c005f3f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -635,8 +635,11 @@
             flags = AUDIO_OUTPUT_FLAG_NONE;
         }
 
-        mRenderer->openAudioSink(
+        status_t err = mRenderer->openAudioSink(
                 format, false /* offloadOnly */, hasVideo, flags, NULL /* isOffloaed */);
+        if (err != OK) {
+            handleError(err);
+        }
     }
 }
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 7370224..018e668 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -390,7 +390,7 @@
 }
 
 status_t NuPlayerDriver::seekTo(int msec) {
-    ALOGD("seekTo(%p) %d ms", this, msec);
+    ALOGD("seekTo(%p) %d ms at state %d", this, msec, mState);
     Mutex::Autolock autoLock(mLock);
 
     int64_t seekTimeUs = msec * 1000ll;
@@ -458,7 +458,7 @@
 }
 
 status_t NuPlayerDriver::reset() {
-    ALOGD("reset(%p)", this);
+    ALOGD("reset(%p) at state %d", this, mState);
     Mutex::Autolock autoLock(mLock);
 
     switch (mState) {
@@ -725,7 +725,8 @@
 
 void NuPlayerDriver::notifyListener_l(
         int msg, int ext1, int ext2, const Parcel *in) {
-    ALOGD("notifyListener_l(%p), (%d, %d, %d)", this, msg, ext1, ext2);
+    ALOGD("notifyListener_l(%p), (%d, %d, %d), loop setting(%d, %d)",
+            this, msg, ext1, ext2, mAutoLoop, mLooping);
     switch (msg) {
         case MEDIA_PLAYBACK_COMPLETE:
         {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 116e8be..fbe463b 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -95,6 +95,7 @@
       mVideoQueueGeneration(0),
       mAudioDrainGeneration(0),
       mVideoDrainGeneration(0),
+      mAudioEOSGeneration(0),
       mPlaybackSettings(AUDIO_PLAYBACK_RATE_DEFAULT),
       mAudioFirstAnchorTimeMediaUs(-1),
       mAnchorTimeMediaUs(-1),
@@ -106,6 +107,7 @@
       mNotifyCompleteVideo(false),
       mSyncQueues(false),
       mPaused(false),
+      mPauseDrainAudioAllowedUs(0),
       mVideoSampleReceived(false),
       mVideoRenderingStarted(false),
       mVideoRenderingStartGeneration(0),
@@ -499,6 +501,19 @@
             break;
         }
 
+        case kWhatEOS:
+        {
+            int32_t generation;
+            CHECK(msg->findInt32("audioEOSGeneration", &generation));
+            if (generation != mAudioEOSGeneration) {
+                break;
+            }
+            status_t finalResult;
+            CHECK(msg->findInt32("finalResult", &finalResult));
+            notifyEOS(true /* audio */, finalResult);
+            break;
+        }
+
         case kWhatConfigPlayback:
         {
             sp<AReplyToken> replyID;
@@ -631,6 +646,14 @@
         return;
     }
 
+    // FIXME: if paused, wait until AudioTrack stop() is complete before delivering data.
+    if (mPaused) {
+        const int64_t diffUs = mPauseDrainAudioAllowedUs - ALooper::GetNowUs();
+        if (diffUs > delayUs) {
+            delayUs = diffUs;
+        }
+    }
+
     mDrainAudioQueuePending = true;
     sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this);
     msg->setInt32("drainGeneration", mAudioDrainGeneration);
@@ -879,6 +902,8 @@
                 ALOGV("AudioSink write would block when writing %zu bytes", copy);
             } else {
                 ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy);
+                // This can only happen when AudioSink was opened with doNotReconnect flag set to
+                // true, in which case the NuPlayer will handle the reconnect.
                 notifyAudioTearDown();
             }
             break;
@@ -945,6 +970,10 @@
 int64_t NuPlayer::Renderer::getDurationUsIfPlayedAtSampleRate(uint32_t numFrames) {
     int32_t sampleRate = offloadingAudio() ?
             mCurrentOffloadInfo.sample_rate : mCurrentPcmInfo.mSampleRate;
+    if (sampleRate == 0) {
+        ALOGE("sampleRate is 0 in %s mode", offloadingAudio() ? "offload" : "non-offload");
+        return 0;
+    }
     // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
     return (int64_t)((int32_t)numFrames * 1000000LL / sampleRate);
 }
@@ -1155,6 +1184,13 @@
 }
 
 void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
+    if (audio && delayUs > 0) {
+        sp<AMessage> msg = new AMessage(kWhatEOS, this);
+        msg->setInt32("audioEOSGeneration", mAudioEOSGeneration);
+        msg->setInt32("finalResult", finalResult);
+        msg->post(delayUs);
+        return;
+    }
     sp<AMessage> notify = mNotify->dup();
     notify->setInt32("what", kWhatEOS);
     notify->setInt32("audio", static_cast<int32_t>(audio));
@@ -1330,6 +1366,7 @@
             flushQueue(&mAudioQueue);
 
             ++mAudioDrainGeneration;
+            ++mAudioEOSGeneration;
             prepareForMediaRenderingStart_l();
 
             // the frame count will be reset after flush.
@@ -1349,8 +1386,16 @@
             mAudioSink->flush();
             // Call stop() to signal to the AudioSink to completely fill the
             // internal buffer before resuming playback.
+            // FIXME: this is ignored after flush().
             mAudioSink->stop();
-            if (!mPaused) {
+            if (mPaused) {
+                // Race condition: if renderer is paused and audio sink is stopped,
+                // we need to make sure that the audio track buffer fully drains
+                // before delivering data.
+                // FIXME: remove this if we can detect if stop() is complete.
+                const int delayUs = 2 * 50 * 1000; // (2 full mixer thread cycles at 50ms)
+                mPauseDrainAudioAllowedUs = ALooper::GetNowUs() + delayUs;
+            } else {
                 mAudioSink->start();
             }
             mNumFramesWritten = 0;
@@ -1480,7 +1525,10 @@
 
     if (mHasAudio) {
         cancelAudioOffloadPauseTimeout();
-        mAudioSink->start();
+        status_t err = mAudioSink->start();
+        if (err != OK) {
+            notifyAudioTearDown();
+        }
     }
 
     {
@@ -1772,6 +1820,12 @@
         const uint32_t frameCount =
                 (unsigned long long)sampleRate * getAudioSinkPcmMsSetting() / 1000;
 
+        // The doNotReconnect means AudioSink will signal back and let NuPlayer to re-construct
+        // AudioSink. We don't want this when there's video because it will cause a video seek to
+        // the previous I frame. But we do want this when there's only audio because it will give
+        // NuPlayer a chance to switch from non-offload mode to offload mode.
+        // So we only set doNotReconnect when there's no video.
+        const bool doNotReconnect = !hasVideo;
         status_t err = mAudioSink->open(
                     sampleRate,
                     numChannels,
@@ -1782,13 +1836,14 @@
                     mUseAudioCallback ? this : NULL,
                     (audio_output_flags_t)pcmFlags,
                     NULL,
-                    true /* doNotReconnect */,
+                    doNotReconnect,
                     frameCount);
         if (err == OK) {
             err = mAudioSink->setPlaybackRate(mPlaybackSettings);
         }
         if (err != OK) {
             ALOGW("openAudioSink: non offloaded open failed status: %d", err);
+            mAudioSink->close();
             mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
             return err;
         }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index 58bf121..de5f9a9 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -148,6 +148,7 @@
     int32_t mVideoQueueGeneration;
     int32_t mAudioDrainGeneration;
     int32_t mVideoDrainGeneration;
+    int32_t mAudioEOSGeneration;
 
     sp<MediaClock> mMediaClock;
     float mPlaybackRate; // audio track rate
@@ -170,6 +171,7 @@
 
     // modified on only renderer's thread.
     bool mPaused;
+    int64_t mPauseDrainAudioAllowedUs; // time when we can drain/deliver audio in pause mode.
 
     bool mVideoSampleReceived;
     bool mVideoRenderingStarted;
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index 58ff113..af0351e 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -134,7 +134,9 @@
             return;
         }
     }
-    mHandler->pause();
+    if (mHandler != NULL) {
+        mHandler->pause();
+    }
 }
 
 void NuPlayer::RTSPSource::resume() {
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 5b3947e..166600b 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -497,6 +497,7 @@
       mSentFormat(false),
       mIsVideo(false),
       mIsEncoder(false),
+      mFatalError(false),
       mShutdownInProgress(false),
       mExplicitShutdown(false),
       mEncoderDelay(0),
@@ -1312,6 +1313,11 @@
         return NULL;
     }
 
+    if (mFatalError) {
+        ALOGW("not dequeuing from native window due to fatal error");
+        return NULL;
+    }
+
     int fenceFd = -1;
     do {
         status_t err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd);
@@ -4462,6 +4468,9 @@
             ALOGW("Invalid OMX error %#x", error);
         }
     }
+
+    mFatalError = true;
+
     notify->setInt32("err", internalError);
     notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error.
     notify->post();
diff --git a/media/libstagefright/AMRExtractor.cpp b/media/libstagefright/AMRExtractor.cpp
index a6fb3d8..4a66d66 100644
--- a/media/libstagefright/AMRExtractor.cpp
+++ b/media/libstagefright/AMRExtractor.cpp
@@ -309,7 +309,13 @@
         buffer->release();
         buffer = NULL;
 
-        return ERROR_IO;
+        if (n < 0) {
+            return ERROR_IO;
+        } else {
+            // only partial frame is available, treat it as EOS.
+            mOffset += n;
+            return ERROR_END_OF_STREAM;
+        }
     }
 
     buffer->set_range(0, frameSize);
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 2529aa7..1c44285 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -135,6 +135,7 @@
 endif
 
 LOCAL_CLANG := true
+LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow
 
 LOCAL_MODULE:= libstagefright
 
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 3505844..6e4a1dd 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -290,6 +290,10 @@
 
 status_t AudioSource::dataCallback(const AudioRecord::Buffer& audioBuffer) {
     int64_t timeUs = systemTime() / 1000ll;
+    // Estimate the real sampling time of the 1st sample in this buffer
+    // from AudioRecord's latency. (Apply this adjustment first so that
+    // the start time logic is not affected.)
+    timeUs -= mRecord->latency() * 1000LL;
 
     ALOGV("dataCallbackTimestamp: %" PRId64 " us", timeUs);
     Mutex::Autolock autoLock(mLock);
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index b451021..b0efebc 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -215,6 +215,7 @@
       mDecryptHandle(NULL),
       mLastVideoTimeUs(-1),
       mTextDriver(NULL),
+      mSelectedTimedTextTrack(-1),
       mOffloadAudio(false),
       mAudioTearDown(false) {
     CHECK_EQ(mClient.connect(), (status_t)OK);
@@ -2291,11 +2292,11 @@
             // The widevine extractor does its own caching.
 
 #if 0
-            mCachedSource = new NuCachedSource2(
+            mCachedSource = NuCachedSource2::Create(
                     new ThrottledSource(
                         mConnectingDataSource, 50 * 1024 /* bytes/sec */));
 #else
-            mCachedSource = new NuCachedSource2(
+            mCachedSource = NuCachedSource2::Create(
                     mConnectingDataSource,
                     cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
                     disconnectAtHighwatermark);
@@ -2679,6 +2680,7 @@
         } else {
             reply->writeInt32(MEDIA_TRACK_TYPE_UNKNOWN);
         }
+        reply->writeString16(String16(mime));
 
         const char *lang;
         if (!meta->findCString(kKeyMediaLanguage, &lang)) {
@@ -2813,12 +2815,14 @@
                 mTextDriver->start();
                 modifyFlags(TEXT_RUNNING, SET);
             }
+            mSelectedTimedTextTrack = trackIndex;
         }
     } else {
         err = mTextDriver->unselectTrack(trackIndex);
         if (err == OK) {
             modifyFlags(TEXTPLAYER_INITIALIZED, CLEAR);
             modifyFlags(TEXT_RUNNING, CLEAR);
+            mSelectedTimedTextTrack = -1;
         }
     }
     return err;
@@ -2903,6 +2907,15 @@
             int trackIndex = request.readInt32();
             return selectTrack(trackIndex, false /* select */);
         }
+        case INVOKE_ID_GET_SELECTED_TRACK:
+        {
+            int trackType = request.readInt32();
+            if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
+                reply->writeInt32(mSelectedTimedTextTrack);
+                return mSelectedTimedTextTrack;
+            }
+
+        }
         default:
         {
             return ERROR_UNSUPPORTED;
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index bc34bcf..66280da 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -881,13 +881,6 @@
         return;
     }
 
-    if (mNumFramesReceived > 0) {
-        CHECK(timestampUs > mLastFrameTimestampUs);
-        if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
-            ++mNumGlitches;
-        }
-    }
-
     // May need to skip frame or modify timestamp. Currently implemented
     // by the subclass CameraSourceTimeLapse.
     if (skipCurrentFrame(timestampUs)) {
@@ -895,6 +888,18 @@
         return;
     }
 
+    if (mNumFramesReceived > 0) {
+        if (timestampUs <= mLastFrameTimestampUs) {
+            ALOGW("Dropping frame with backward timestamp %lld (last %lld)",
+                    (long long)timestampUs, (long long)mLastFrameTimestampUs);
+            releaseOneRecordingFrame(data);
+            return;
+        }
+        if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
+            ++mNumGlitches;
+        }
+    }
+
     mLastFrameTimestampUs = timestampUs;
     if (mNumFramesReceived == 0) {
         mFirstFrameTimeUs = timestampUs;
diff --git a/media/libstagefright/DRMExtractor.cpp b/media/libstagefright/DRMExtractor.cpp
index 63cb430..9cb6e86 100644
--- a/media/libstagefright/DRMExtractor.cpp
+++ b/media/libstagefright/DRMExtractor.cpp
@@ -186,7 +186,8 @@
 
             srcOffset += mNALLengthSize;
 
-            if (srcOffset + nalLength > len) {
+            size_t end = srcOffset + nalLength;
+            if (end > len || end < srcOffset) {
                 if (decryptedDrmBuffer.data) {
                     delete [] decryptedDrmBuffer.data;
                     decryptedDrmBuffer.data = NULL;
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 75ef288..5020c6c 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -246,7 +246,7 @@
                 *contentType = httpSource->getMIMEType();
             }
 
-            source = new NuCachedSource2(
+            source = NuCachedSource2::Create(
                     httpSource,
                     cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
                     disconnectAtHighwatermark);
diff --git a/media/libstagefright/DataURISource.cpp b/media/libstagefright/DataURISource.cpp
index 2c39314..2a61c3a 100644
--- a/media/libstagefright/DataURISource.cpp
+++ b/media/libstagefright/DataURISource.cpp
@@ -42,7 +42,8 @@
         AString encoded(commaPos + 1);
 
         // Strip CR and LF...
-        for (size_t i = encoded.size(); i-- > 0;) {
+        for (size_t i = encoded.size(); i > 0;) {
+            i--;
             if (encoded.c_str()[i] == '\r' || encoded.c_str()[i] == '\n') {
                 encoded.erase(i, 1);
             }
diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp
index 565f156..5684de7 100644
--- a/media/libstagefright/FileSource.cpp
+++ b/media/libstagefright/FileSource.cpp
@@ -99,8 +99,8 @@
         if (offset >= mLength) {
             return 0;  // read beyond EOF.
         }
-        int64_t numAvailable = mLength - offset;
-        if ((int64_t)size > numAvailable) {
+        uint64_t numAvailable = mLength - offset;
+        if ((uint64_t)size > numAvailable) {
             size = numAvailable;
         }
     }
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
old mode 100755
new mode 100644
index 15918d3..7d4b11a
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -44,6 +44,10 @@
 #include <byteswap.h>
 #include "include/ID3.h"
 
+#ifndef UINT32_MAX
+#define UINT32_MAX       (4294967295U)
+#endif
+
 namespace android {
 
 class MPEG4Source : public MediaSource {
@@ -525,11 +529,11 @@
     CHECK_NE(err, (status_t)NO_INIT);
 
     // copy pssh data into file metadata
-    int psshsize = 0;
+    uint64_t psshsize = 0;
     for (size_t i = 0; i < mPssh.size(); i++) {
         psshsize += 20 + mPssh[i].datalen;
     }
-    if (psshsize) {
+    if (psshsize > 0 && psshsize <= UINT32_MAX) {
         char *buf = (char*)malloc(psshsize);
         char *ptr = buf;
         for (size_t i = 0; i < mPssh.size(); i++) {
@@ -762,6 +766,11 @@
 
 status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
     ALOGV("entering parseChunk %lld/%d", (long long)*offset, depth);
+
+    if (*offset < 0) {
+        ALOGE("b/23540914");
+        return ERROR_MALFORMED;
+    }
     uint32_t hdr[2];
     if (mDataSource->readAt(*offset, hdr, 8) < 8) {
         return ERROR_IO;
@@ -827,7 +836,12 @@
 
     PathAdder autoAdder(&mPath, chunk_type);
 
-    off64_t chunk_data_size = *offset + chunk_size - data_offset;
+    // (data_offset - *offset) is either 8 or 16
+    off64_t chunk_data_size = chunk_size - (data_offset - *offset);
+    if (chunk_data_size < 0) {
+        ALOGE("b/23540914");
+        return ERROR_MALFORMED;
+    }
 
     if (chunk_type != FOURCC('c', 'p', 'r', 't')
             && chunk_type != FOURCC('c', 'o', 'v', 'r')
@@ -925,6 +939,11 @@
             }
 
             if (isTrack) {
+                int32_t trackId;
+                // There must be exact one track header per track.
+                if (!mLastTrack->meta->findInt32(kKeyTrackID, &trackId)) {
+                    mLastTrack->skipTrack = true;
+                }
                 if (mLastTrack->skipTrack) {
                     Track *cur = mFirstTrack;
 
@@ -1138,7 +1157,7 @@
             }
             pssh.datalen = ntohl(psshdatalen);
             ALOGV("pssh data size: %d", pssh.datalen);
-            if (pssh.datalen + 20 > chunk_size) {
+            if (chunk_size < 20 || pssh.datalen > chunk_size - 20) {
                 // pssh data length exceeds size of containing box
                 return ERROR_MALFORMED;
             }
@@ -1948,15 +1967,14 @@
                 return ERROR_IO;
             }
 
-            if (mLastTrack == NULL)
-                return ERROR_MALFORMED;
-
             uint32_t type = ntohl(buffer);
             // For the 3GPP file format, the handler-type within the 'hdlr' box
             // shall be 'text'. We also want to support 'sbtl' handler type
             // for a practical reason as various MPEG4 containers use it.
             if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
-                mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
+                if (mLastTrack != NULL) {
+                    mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
+                }
             }
 
             break;
@@ -2004,7 +2022,7 @@
                 size = 0;
             }
 
-            if (SIZE_MAX - chunk_size <= size) {
+            if ((chunk_size > SIZE_MAX) || (SIZE_MAX - chunk_size <= size)) {
                 return ERROR_MALFORMED;
             }
 
@@ -2842,10 +2860,46 @@
                 break;
             }
         }
+    } else {
+        ALOGE("b/21657957");
+        return NULL;
     }
 
     ALOGV("getTrack called, pssh: %zu", mPssh.size());
 
+    const char *mime;
+    if (!track->meta->findCString(kKeyMIMEType, &mime)) {
+        return NULL;
+    }
+
+    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+        uint32_t type;
+        const void *data;
+        size_t size;
+        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)) {
+            return NULL;
+        }
+
+        const uint8_t *ptr = (const uint8_t *)data;
+
+        if (size < 7 || ptr[0] != 1) {  // configurationVersion == 1
+            return NULL;
+        }
+    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
+        uint32_t type;
+        const void *data;
+        size_t size;
+        if (!track->meta->findData(kKeyHVCC, &type, &data, &size)) {
+            return NULL;
+        }
+
+        const uint8_t *ptr = (const uint8_t *)data;
+
+        if (size < 22 || ptr[0] != 1) {  // configurationVersion == 1
+            return NULL;
+        }
+    }
+
     return new MPEG4Source(this,
             track->meta, mDataSource, track->timescale, track->sampleTable,
             mSidxEntries, trex, mMoofOffset);
@@ -3017,12 +3071,11 @@
     int32_t sampleRate = 0;
     int32_t numChannels = 0;
     if (freqIndex == 15) {
-        if (csd_size < 5) {
-            return ERROR_MALFORMED;
-        }
+        if (br.numBitsLeft() < 28) return ERROR_MALFORMED;
         sampleRate = br.getBits(24);
         numChannels = br.getBits(4);
     } else {
+        if (br.numBitsLeft() < 4) return ERROR_MALFORMED;
         numChannels = br.getBits(4);
 
         if (freqIndex == 13 || freqIndex == 14) {
@@ -3033,12 +3086,14 @@
     }
 
     if (objectType == AOT_SBR || objectType == AOT_PS) {//SBR specific config per 14496-3 table 1.13
+        if (br.numBitsLeft() < 4) return ERROR_MALFORMED;
         uint32_t extFreqIndex = br.getBits(4);
         int32_t extSampleRate __unused;
         if (extFreqIndex == 15) {
             if (csd_size < 8) {
                 return ERROR_MALFORMED;
             }
+            if (br.numBitsLeft() < 24) return ERROR_MALFORMED;
             extSampleRate = br.getBits(24);
         } else {
             if (extFreqIndex == 13 || extFreqIndex == 14) {
@@ -3075,20 +3130,24 @@
 
     {
         if (objectType == AOT_SBR || objectType == AOT_PS) {
+            if (br.numBitsLeft() < 5) return ERROR_MALFORMED;
             objectType = br.getBits(5);
 
             if (objectType == AOT_ESCAPE) {
+                if (br.numBitsLeft() < 6) return ERROR_MALFORMED;
                 objectType = 32 + br.getBits(6);
             }
         }
         if (objectType == AOT_AAC_LC || objectType == AOT_ER_AAC_LC ||
                 objectType == AOT_ER_AAC_LD || objectType == AOT_ER_AAC_SCAL ||
                 objectType == AOT_ER_BSAC) {
+            if (br.numBitsLeft() < 2) return ERROR_MALFORMED;
             const int32_t frameLengthFlag __unused = br.getBits(1);
 
             const int32_t dependsOnCoreCoder = br.getBits(1);
 
             if (dependsOnCoreCoder ) {
+                if (br.numBitsLeft() < 14) return ERROR_MALFORMED;
                 const int32_t coreCoderDelay __unused = br.getBits(14);
             }
 
@@ -3108,7 +3167,7 @@
                     extensionFlag = 1;
                     break;
                 default:
-                    TRESPASS();
+                    return ERROR_MALFORMED;
                     break;
                 }
                 ALOGW("csd missing extension flag; assuming %d for object type %u.",
@@ -3118,6 +3177,9 @@
             if (numChannels == 0) {
                 int32_t channelsEffectiveNum = 0;
                 int32_t channelsNum = 0;
+                if (br.numBitsLeft() < 32) {
+                    return ERROR_MALFORMED;
+                }
                 const int32_t ElementInstanceTag __unused = br.getBits(4);
                 const int32_t Profile __unused = br.getBits(2);
                 const int32_t SamplingFrequencyIndex __unused = br.getBits(4);
@@ -3129,35 +3191,44 @@
                 const int32_t NumValidCcElements __unused = br.getBits(4);
 
                 const int32_t MonoMixdownPresent = br.getBits(1);
+
                 if (MonoMixdownPresent != 0) {
+                    if (br.numBitsLeft() < 4) return ERROR_MALFORMED;
                     const int32_t MonoMixdownElementNumber __unused = br.getBits(4);
                 }
 
+                if (br.numBitsLeft() < 1) return ERROR_MALFORMED;
                 const int32_t StereoMixdownPresent = br.getBits(1);
                 if (StereoMixdownPresent != 0) {
+                    if (br.numBitsLeft() < 4) return ERROR_MALFORMED;
                     const int32_t StereoMixdownElementNumber __unused = br.getBits(4);
                 }
 
+                if (br.numBitsLeft() < 1) return ERROR_MALFORMED;
                 const int32_t MatrixMixdownIndexPresent = br.getBits(1);
                 if (MatrixMixdownIndexPresent != 0) {
+                    if (br.numBitsLeft() < 3) return ERROR_MALFORMED;
                     const int32_t MatrixMixdownIndex __unused = br.getBits(2);
                     const int32_t PseudoSurroundEnable __unused = br.getBits(1);
                 }
 
                 int i;
                 for (i=0; i < NumFrontChannelElements; i++) {
+                    if (br.numBitsLeft() < 5) return ERROR_MALFORMED;
                     const int32_t FrontElementIsCpe = br.getBits(1);
                     const int32_t FrontElementTagSelect __unused = br.getBits(4);
                     channelsNum += FrontElementIsCpe ? 2 : 1;
                 }
 
                 for (i=0; i < NumSideChannelElements; i++) {
+                    if (br.numBitsLeft() < 5) return ERROR_MALFORMED;
                     const int32_t SideElementIsCpe = br.getBits(1);
                     const int32_t SideElementTagSelect __unused = br.getBits(4);
                     channelsNum += SideElementIsCpe ? 2 : 1;
                 }
 
                 for (i=0; i < NumBackChannelElements; i++) {
+                    if (br.numBitsLeft() < 5) return ERROR_MALFORMED;
                     const int32_t BackElementIsCpe = br.getBits(1);
                     const int32_t BackElementTagSelect __unused = br.getBits(4);
                     channelsNum += BackElementIsCpe ? 2 : 1;
@@ -3165,6 +3236,7 @@
                 channelsEffectiveNum = channelsNum;
 
                 for (i=0; i < NumLfeChannelElements; i++) {
+                    if (br.numBitsLeft() < 4) return ERROR_MALFORMED;
                     const int32_t LfeElementTagSelect __unused = br.getBits(4);
                     channelsNum += 1;
                 }
@@ -3283,7 +3355,7 @@
 
         const uint8_t *ptr = (const uint8_t *)data;
 
-        CHECK(size >= 7);
+        CHECK(size >= 22);
         CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
 
         mNALLengthSize = 1 + (ptr[14 + 7] & 3);
@@ -3566,13 +3638,27 @@
         return ERROR_IO;
     }
     offset += 4;
+    if (entrycount == 0) {
+        return OK;
+    }
+    if (entrycount > UINT32_MAX / 8) {
+        return ERROR_MALFORMED;
+    }
 
     if (entrycount > mCurrentSampleInfoOffsetsAllocSize) {
-        mCurrentSampleInfoOffsets = (uint64_t*) realloc(mCurrentSampleInfoOffsets, entrycount * 8);
+        uint64_t *newPtr = (uint64_t *)realloc(mCurrentSampleInfoOffsets, entrycount * 8);
+        if (newPtr == NULL) {
+            return NO_MEMORY;
+        }
+        mCurrentSampleInfoOffsets = newPtr;
         mCurrentSampleInfoOffsetsAllocSize = entrycount;
     }
     mCurrentSampleInfoOffsetCount = entrycount;
 
+    if (mCurrentSampleInfoOffsets == NULL) {
+        return OK;
+    }
+
     for (size_t i = 0; i < entrycount; i++) {
         if (version == 0) {
             uint32_t tmp;
@@ -4642,12 +4728,18 @@
                 // The smallest valid chunk is 16 bytes long in this case.
                 return false;
             }
+
         } else if (chunkSize < 8) {
             // The smallest valid chunk is 8 bytes long.
             return false;
         }
 
-        off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
+        // (data_offset - offset) is either 8 or 16
+        off64_t chunkDataSize = chunkSize - (chunkDataOffset - offset);
+        if (chunkDataSize < 0) {
+            ALOGE("b/23540914");
+            return ERROR_MALFORMED;
+        }
 
         char chunkstring[5];
         MakeFourCCString(chunkType, chunkstring);
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index cd59709..9085ed7 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -572,6 +572,7 @@
 }
 
 status_t MediaCodec::reclaim() {
+    ALOGD("MediaCodec::reclaim(%p) %s", this, mInitName.c_str());
     sp<AMessage> msg = new AMessage(kWhatRelease, this);
     msg->setInt32("reclaimed", 1);
 
@@ -844,33 +845,54 @@
         size_t portIndex, size_t index,
         sp<ABuffer> *buffer, sp<AMessage> *format) {
     // use mutex instead of a context switch
-
     if (mReleasedByResourceManager) {
+        ALOGE("getBufferAndFormat - resource already released");
         return DEAD_OBJECT;
     }
 
+    if (buffer == NULL) {
+        ALOGE("getBufferAndFormat - null ABuffer");
+        return INVALID_OPERATION;
+    }
+
+    if (format == NULL) {
+        ALOGE("getBufferAndFormat - null AMessage");
+        return INVALID_OPERATION;
+    }
+
     buffer->clear();
     format->clear();
+
     if (!isExecuting()) {
+        ALOGE("getBufferAndFormat - not executing");
         return INVALID_OPERATION;
     }
 
     // we do not want mPortBuffers to change during this section
     // we also don't want mOwnedByClient to change during this
     Mutex::Autolock al(mBufferLock);
+
     Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
-    if (index < buffers->size()) {
-        const BufferInfo &info = buffers->itemAt(index);
-        if (info.mOwnedByClient) {
-            // by the time buffers array is initialized, crypto is set
-            if (portIndex == kPortIndexInput && mCrypto != NULL) {
-                *buffer = info.mEncryptedData;
-            } else {
-                *buffer = info.mData;
-            }
-            *format = info.mFormat;
-        }
+    if (index >= buffers->size()) {
+        ALOGE("getBufferAndFormat - trying to get buffer with "
+              "bad index (index=%zu buffer_size=%zu)", index, buffers->size());
+        return INVALID_OPERATION;
     }
+
+    const BufferInfo &info = buffers->itemAt(index);
+    if (!info.mOwnedByClient) {
+        ALOGE("getBufferAndFormat - invalid operation "
+              "(the index %zu is not owned by client)", index);
+        return INVALID_OPERATION;
+    }
+
+    // by the time buffers array is initialized, crypto is set
+    *buffer = (portIndex == kPortIndexInput && mCrypto != NULL) ?
+                  info.mEncryptedData :
+                  info.mData;
+
+    *format = info.mFormat;
+
     return OK;
 }
 
@@ -1154,8 +1176,10 @@
                         resourceType = String8(kResourceNonSecureCodec);
                     }
 
-                    const char *subtype = mIsVideo ? kResourceVideoCodec : kResourceAudioCodec;
-                    addResource(resourceType, String8(subtype), 1);
+                    if (mIsVideo) {
+                        // audio codec is currently ignored.
+                        addResource(resourceType, String8(kResourceVideoCodec), 1);
+                    }
 
                     (new AMessage)->postReply(mReplyID);
                     break;
diff --git a/media/libstagefright/MetaData.cpp b/media/libstagefright/MetaData.cpp
index 7d867b7..7a8bd98 100644
--- a/media/libstagefright/MetaData.cpp
+++ b/media/libstagefright/MetaData.cpp
@@ -107,7 +107,7 @@
 }
 
 bool MetaData::findInt32(uint32_t key, int32_t *value) {
-    uint32_t type;
+    uint32_t type = 0;
     const void *data;
     size_t size;
     if (!findData(key, &type, &data, &size) || type != TYPE_INT32) {
@@ -122,7 +122,7 @@
 }
 
 bool MetaData::findInt64(uint32_t key, int64_t *value) {
-    uint32_t type;
+    uint32_t type = 0;
     const void *data;
     size_t size;
     if (!findData(key, &type, &data, &size) || type != TYPE_INT64) {
@@ -137,7 +137,7 @@
 }
 
 bool MetaData::findFloat(uint32_t key, float *value) {
-    uint32_t type;
+    uint32_t type = 0;
     const void *data;
     size_t size;
     if (!findData(key, &type, &data, &size) || type != TYPE_FLOAT) {
@@ -152,7 +152,7 @@
 }
 
 bool MetaData::findPointer(uint32_t key, void **value) {
-    uint32_t type;
+    uint32_t type = 0;
     const void *data;
     size_t size;
     if (!findData(key, &type, &data, &size) || type != TYPE_POINTER) {
@@ -170,7 +170,7 @@
         uint32_t key,
         int32_t *left, int32_t *top,
         int32_t *right, int32_t *bottom) {
-    uint32_t type;
+    uint32_t type = 0;
     const void *data;
     size_t size;
     if (!findData(key, &type, &data, &size) || type != TYPE_RECT) {
@@ -244,8 +244,11 @@
 MetaData::typed_data::typed_data(const typed_data &from)
     : mType(from.mType),
       mSize(0) {
-    allocateStorage(from.mSize);
-    memcpy(storage(), from.storage(), mSize);
+
+    void *dst = allocateStorage(from.mSize);
+    if (dst) {
+        memcpy(dst, from.storage(), mSize);
+    }
 }
 
 MetaData::typed_data &MetaData::typed_data::operator=(
@@ -253,8 +256,10 @@
     if (this != &from) {
         clear();
         mType = from.mType;
-        allocateStorage(from.mSize);
-        memcpy(storage(), from.storage(), mSize);
+        void *dst = allocateStorage(from.mSize);
+        if (dst) {
+            memcpy(dst, from.storage(), mSize);
+        }
     }
 
     return *this;
@@ -271,13 +276,11 @@
     clear();
 
     mType = type;
-    allocateStorage(size);
-    void *dst = storage();
-    if (!dst) {
-        ALOGE("Couldn't allocate %zu bytes for item", size);
-        return;
+
+    void *dst = allocateStorage(size);
+    if (dst) {
+        memcpy(dst, data, size);
     }
-    memcpy(dst, data, size);
 }
 
 void MetaData::typed_data::getData(
@@ -287,14 +290,19 @@
     *data = storage();
 }
 
-void MetaData::typed_data::allocateStorage(size_t size) {
+void *MetaData::typed_data::allocateStorage(size_t size) {
     mSize = size;
 
     if (usesReservoir()) {
-        return;
+        return &u.reservoir;
     }
 
     u.ext_data = malloc(mSize);
+    if (u.ext_data == NULL) {
+        ALOGE("Couldn't allocate %zu bytes for item", size);
+        mSize = 0;
+    }
+    return u.ext_data;
 }
 
 void MetaData::typed_data::freeStorage() {
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index f82636b..d6255d6 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -224,9 +224,6 @@
     // So whenever we call DataSource::readAt it may end up in a call to
     // IMediaHTTPConnection::readAt and therefore call back into JAVA.
     mLooper->start(false /* runOnCallingThread */, true /* canCallJava */);
-
-    Mutex::Autolock autoLock(mLock);
-    (new AMessage(kWhatFetchMore, mReflector))->post();
 }
 
 NuCachedSource2::~NuCachedSource2() {
@@ -237,6 +234,18 @@
     mCache = NULL;
 }
 
+// static
+sp<NuCachedSource2> NuCachedSource2::Create(
+        const sp<DataSource> &source,
+        const char *cacheConfig,
+        bool disconnectAtHighwatermark) {
+    sp<NuCachedSource2> instance = new NuCachedSource2(
+            source, cacheConfig, disconnectAtHighwatermark);
+    Mutex::Autolock autoLock(instance->mLock);
+    (new AMessage(kWhatFetchMore, instance->mReflector))->post();
+    return instance;
+}
+
 status_t NuCachedSource2::getEstimatedBandwidthKbps(int32_t *kbps) {
     if (mSource->flags() & kIsHTTPBasedSource) {
         HTTPBase* source = static_cast<HTTPBase *>(mSource.get());
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index f24cf3a..962b2de 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -186,6 +186,10 @@
 
     for (size_t i = 0; i < mImpl->countTracks(); ++i) {
         sp<MetaData> meta = mImpl->getTrackMetaData(i);
+        if (meta == NULL) {
+            ALOGW("no metadata for track %zu", i);
+            continue;
+        }
 
         int32_t bitrate;
         if (!meta->findInt32(kKeyBitRate, &bitrate)) {
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 96aa808..f73d800 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -393,7 +393,7 @@
     const uint8_t *ptr = (const uint8_t *)data;
 
     // verify minimum size and configurationVersion == 1.
-    if (size < 7 || ptr[0] != 1) {
+    if (size < 23 || ptr[0] != 1) {
         return ERROR_MALFORMED;
     }
 
@@ -408,6 +408,9 @@
     size -= 1;
     size_t j = 0, i = 0;
     for (i = 0; i < numofArrays; i++) {
+        if (size < 3) {
+            return ERROR_MALFORMED;
+        }
         ptr += 1;
         size -= 1;
 
@@ -1658,6 +1661,9 @@
             def.nBufferCountActual, def.nBufferSize,
             portIndex == kPortIndexInput ? "input" : "output");
 
+    if (def.nBufferSize != 0 && def.nBufferCountActual > SIZE_MAX / def.nBufferSize) {
+        return BAD_VALUE;
+    }
     size_t totalSize = def.nBufferCountActual * def.nBufferSize;
     mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec");
 
@@ -2643,7 +2649,8 @@
 
     status_t stickyErr = OK;
 
-    for (size_t i = buffers->size(); i-- > 0;) {
+    for (size_t i = buffers->size(); i > 0;) {
+        i--;
         BufferInfo *info = &buffers->editItemAt(i);
 
         if (onlyThoseWeOwn && info->mStatus == OWNED_BY_COMPONENT) {
@@ -3529,8 +3536,21 @@
 }
 
 void OMXCodec::addCodecSpecificData(const void *data, size_t size) {
+
+    if (size > SIZE_MAX - (sizeof(CodecSpecificData) - 1)) {
+        // this would require the size to be ~4GB, which should be near impossible
+        // given that it is the size of an in-memory chunk of data
+        ALOGE("b/23540411");
+        return;
+    }
+
     CodecSpecificData *specific =
-        (CodecSpecificData *)malloc(sizeof(CodecSpecificData) + size - 1);
+        (CodecSpecificData *)malloc(sizeof(CodecSpecificData) - 1 + size);
+
+    if (specific == NULL) {
+        ALOGE("b/23540411");
+        return;
+    }
 
     specific->mSize = size;
     memcpy(specific->mData, data, size);
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index 1c663a3..5f565e2 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -23,6 +23,7 @@
 #include <cutils/properties.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/base64.h>
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaBufferGroup.h>
@@ -770,8 +771,13 @@
             return n < 0 ? n : (status_t)ERROR_END_OF_STREAM;
         }
 
-        mCurrentPageSamples =
-            mCurrentPage.mGranulePosition - mPrevGranulePosition;
+        // Prevent a harmless unsigned integer overflow by clamping to 0
+        if (mCurrentPage.mGranulePosition >= mPrevGranulePosition) {
+            mCurrentPageSamples =
+                    mCurrentPage.mGranulePosition - mPrevGranulePosition;
+        } else {
+            mCurrentPageSamples = 0;
+        }
         mFirstPacketInPage = true;
 
         mPrevGranulePosition = mCurrentPage.mGranulePosition;
@@ -1202,83 +1208,18 @@
 
 }
 
-// The returned buffer should be free()d.
-static uint8_t *DecodeBase64(const char *s, size_t size, size_t *outSize) {
-    *outSize = 0;
-
-    if ((size % 4) != 0) {
-        return NULL;
-    }
-
-    size_t n = size;
-    size_t padding = 0;
-    if (n >= 1 && s[n - 1] == '=') {
-        padding = 1;
-
-        if (n >= 2 && s[n - 2] == '=') {
-            padding = 2;
-        }
-    }
-
-    size_t outLen = 3 * size / 4 - padding;
-
-    *outSize = outLen;
-
-    void *buffer = malloc(outLen);
-
-    uint8_t *out = (uint8_t *)buffer;
-    size_t j = 0;
-    uint32_t accum = 0;
-    for (size_t i = 0; i < n; ++i) {
-        char c = s[i];
-        unsigned value;
-        if (c >= 'A' && c <= 'Z') {
-            value = c - 'A';
-        } else if (c >= 'a' && c <= 'z') {
-            value = 26 + c - 'a';
-        } else if (c >= '0' && c <= '9') {
-            value = 52 + c - '0';
-        } else if (c == '+') {
-            value = 62;
-        } else if (c == '/') {
-            value = 63;
-        } else if (c != '=') {
-            return NULL;
-        } else {
-            if (i < n - padding) {
-                return NULL;
-            }
-
-            value = 0;
-        }
-
-        accum = (accum << 6) | value;
-
-        if (((i + 1) % 4) == 0) {
-            out[j++] = (accum >> 16);
-
-            if (j < outLen) { out[j++] = (accum >> 8) & 0xff; }
-            if (j < outLen) { out[j++] = accum & 0xff; }
-
-            accum = 0;
-        }
-    }
-
-    return (uint8_t *)buffer;
-}
-
 static void extractAlbumArt(
         const sp<MetaData> &fileMeta, const void *data, size_t size) {
     ALOGV("extractAlbumArt from '%s'", (const char *)data);
 
-    size_t flacSize;
-    uint8_t *flac = DecodeBase64((const char *)data, size, &flacSize);
-
-    if (flac == NULL) {
+    sp<ABuffer> flacBuffer = decodeBase64(AString((const char *)data, size));
+    if (flacBuffer == NULL) {
         ALOGE("malformed base64 encoded data.");
         return;
     }
 
+    size_t flacSize = flacBuffer->size();
+    uint8_t *flac = flacBuffer->data();
     ALOGV("got flac of size %zu", flacSize);
 
     uint32_t picType;
@@ -1288,23 +1229,24 @@
     char type[128];
 
     if (flacSize < 8) {
-        goto exit;
+        return;
     }
 
     picType = U32_AT(flac);
 
     if (picType != 3) {
         // This is not a front cover.
-        goto exit;
+        return;
     }
 
     typeLen = U32_AT(&flac[4]);
-    if (typeLen + 1 > sizeof(type)) {
-        goto exit;
+    if (typeLen > sizeof(type) - 1) {
+        return;
     }
 
-    if (flacSize < 8 + typeLen) {
-        goto exit;
+    // we've already checked above that flacSize >= 8
+    if (flacSize - 8 < typeLen) {
+        return;
     }
 
     memcpy(type, &flac[8], typeLen);
@@ -1314,19 +1256,23 @@
 
     if (!strcmp(type, "-->")) {
         // This is not inline cover art, but an external url instead.
-        goto exit;
+        return;
+    }
+
+    if (flacSize < 32 || flacSize - 32 < typeLen) {
+        return;
     }
 
     descLen = U32_AT(&flac[8 + typeLen]);
-
-    if (flacSize < 32 + typeLen + descLen) {
-        goto exit;
+    if (flacSize - 32 - typeLen < descLen) {
+        return;
     }
 
     dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
 
-    if (flacSize < 32 + typeLen + descLen + dataLen) {
-        goto exit;
+    // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0
+    if (flacSize - 32 - typeLen - descLen < dataLen) {
+        return;
     }
 
     ALOGV("got image data, %zu trailing bytes",
@@ -1336,10 +1282,6 @@
             kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
 
     fileMeta->setCString(kKeyAlbumArtMIME, type);
-
-exit:
-    free(flac);
-    flac = NULL;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/media/libstagefright/SampleIterator.cpp b/media/libstagefright/SampleIterator.cpp
index 2748349..c5f359e 100644
--- a/media/libstagefright/SampleIterator.cpp
+++ b/media/libstagefright/SampleIterator.cpp
@@ -84,6 +84,11 @@
 
     CHECK(sampleIndex < mStopChunkSampleIndex);
 
+    if (mSamplesPerChunk == 0) {
+        ALOGE("b/22802344");
+        return ERROR_MALFORMED;
+    }
+
     uint32_t chunk =
         (sampleIndex - mFirstChunkSampleIndex) / mSamplesPerChunk
         + mFirstChunk;
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index 40df34d..0d84816 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -27,6 +27,11 @@
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/Utils.h>
 
+/* TODO: remove after being merged into other branches */
+#ifndef UINT32_MAX
+#define UINT32_MAX       (4294967295U)
+#endif
+
 namespace android {
 
 // static
@@ -245,8 +250,11 @@
                 != (ssize_t)sizeof(buffer)) {
             return ERROR_IO;
         }
-
-        CHECK(U32_AT(buffer) >= 1);  // chunk index is 1 based in the spec.
+        // chunk index is 1 based in the spec.
+        if (U32_AT(buffer) < 1) {
+            ALOGE("b/23534160");
+            return ERROR_OUT_OF_RANGE;
+        }
 
         // We want the chunk index to be 0-based.
         mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1;
@@ -284,6 +292,9 @@
 
     mDefaultSampleSize = U32_AT(&header[4]);
     mNumSampleSizes = U32_AT(&header[8]);
+    if (mNumSampleSizes > (UINT32_MAX - 12) / 16) {
+        return ERROR_MALFORMED;
+    }
 
     if (type == kSampleSizeType32) {
         mSampleSizeFieldSize = 32;
@@ -336,7 +347,7 @@
 
     mTimeToSampleCount = U32_AT(&header[4]);
     uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t);
-    if (allocSize > SIZE_MAX) {
+    if (allocSize > UINT32_MAX) {
         return ERROR_OUT_OF_RANGE;
     }
     mTimeToSample = new (std::nothrow) uint32_t[mTimeToSampleCount * 2];
@@ -384,7 +395,7 @@
 
     mNumCompositionTimeDeltaEntries = numEntries;
     uint64_t allocSize = (uint64_t)numEntries * 2 * sizeof(uint32_t);
-    if (allocSize > SIZE_MAX) {
+    if (allocSize > UINT32_MAX) {
         return ERROR_OUT_OF_RANGE;
     }
 
@@ -507,7 +518,7 @@
 void SampleTable::buildSampleEntriesTable() {
     Mutex::Autolock autoLock(mLock);
 
-    if (mSampleTimeEntries != NULL) {
+    if (mSampleTimeEntries != NULL || mNumSampleSizes == 0) {
         return;
     }
 
@@ -552,6 +563,10 @@
         uint32_t *sample_index, uint32_t flags) {
     buildSampleEntriesTable();
 
+    if (mSampleTimeEntries == NULL) {
+        return ERROR_OUT_OF_RANGE;
+    }
+
     uint32_t left = 0;
     uint32_t right_plus_one = mNumSampleSizes;
     while (left < right_plus_one) {
diff --git a/media/libstagefright/SkipCutBuffer.cpp b/media/libstagefright/SkipCutBuffer.cpp
index e2e6d79..1da1e5e 100644
--- a/media/libstagefright/SkipCutBuffer.cpp
+++ b/media/libstagefright/SkipCutBuffer.cpp
@@ -25,6 +25,13 @@
 namespace android {
 
 SkipCutBuffer::SkipCutBuffer(int32_t skip, int32_t cut) {
+
+    if (skip < 0 || cut < 0 || cut > 64 * 1024) {
+        ALOGW("out of range skip/cut: %d/%d, using passthrough instead", skip, cut);
+        skip = 0;
+        cut = 0;
+    }
+
     mFrontPadding = mSkip = skip;
     mBackPadding = cut;
     mWriteHead = 0;
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index f0a7277..f8d9573 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -89,8 +89,14 @@
 
 status_t convertMetaDataToMessage(
         const sp<MetaData> &meta, sp<AMessage> *format) {
+
     format->clear();
 
+    if (meta == NULL) {
+        ALOGE("convertMetaDataToMessage: NULL input");
+        return BAD_VALUE;
+    }
+
     const char *mime;
     CHECK(meta->findCString(kKeyMIMEType, &mime));
 
@@ -211,8 +217,10 @@
 
         const uint8_t *ptr = (const uint8_t *)data;
 
-        CHECK(size >= 7);
-        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
+        if (size < 7 || ptr[0] != 1) {  // configurationVersion == 1
+            ALOGE("b/23680780");
+            return BAD_VALUE;
+        }
         uint8_t profile __unused = ptr[1];
         uint8_t level __unused = ptr[3];
 
@@ -238,7 +246,10 @@
         buffer->setRange(0, 0);
 
         for (size_t i = 0; i < numSeqParameterSets; ++i) {
-            CHECK(size >= 2);
+            if (size < 2) {
+                ALOGE("b/23680780");
+                return BAD_VALUE;
+            }
             size_t length = U16_AT(ptr);
 
             ptr += 2;
@@ -267,13 +278,19 @@
         }
         buffer->setRange(0, 0);
 
-        CHECK(size >= 1);
+        if (size < 1) {
+            ALOGE("b/23680780");
+            return BAD_VALUE;
+        }
         size_t numPictureParameterSets = *ptr;
         ++ptr;
         --size;
 
         for (size_t i = 0; i < numPictureParameterSets; ++i) {
-            CHECK(size >= 2);
+            if (size < 2) {
+                ALOGE("b/23680780");
+                return BAD_VALUE;
+            }
             size_t length = U16_AT(ptr);
 
             ptr += 2;
@@ -297,8 +314,10 @@
     } else if (meta->findData(kKeyHVCC, &type, &data, &size)) {
         const uint8_t *ptr = (const uint8_t *)data;
 
-        CHECK(size >= 7);
-        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
+        if (size < 23 || ptr[0] != 1) {  // configurationVersion == 1
+            ALOGE("b/23680780");
+            return BAD_VALUE;
+        }
         uint8_t profile __unused = ptr[1] & 31;
         uint8_t level __unused = ptr[12];
         ptr += 22;
@@ -317,6 +336,10 @@
         buffer->setRange(0, 0);
 
         for (i = 0; i < numofArrays; i++) {
+            if (size < 3) {
+                ALOGE("b/23680780");
+                return BAD_VALUE;
+            }
             ptr += 1;
             size -= 1;
 
@@ -327,7 +350,10 @@
             size -= 2;
 
             for (j = 0; j < numofNals; j++) {
-                CHECK(size >= 2);
+                if (size < 2) {
+                    ALOGE("b/23680780");
+                    return BAD_VALUE;
+                }
                 size_t length = U16_AT(ptr);
 
                 ptr += 2;
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index 335ac84..b30376d 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -199,7 +199,7 @@
                             mNumChannels);
                 }
             } else {
-                if (mNumChannels < 1 && mNumChannels > 8) {
+                if (mNumChannels < 1 || mNumChannels > 8) {
                     return ERROR_UNSUPPORTED;
                 }
             }
@@ -311,9 +311,17 @@
                         1000000LL * (mDataSize / 65 * 320) / 8000;
                 } else {
                     size_t bytesPerSample = mBitsPerSample >> 3;
+
+                    if (!bytesPerSample || !mNumChannels)
+                        return ERROR_MALFORMED;
+
+                    size_t num_samples = mDataSize / (mNumChannels * bytesPerSample);
+
+                    if (!mSampleRate)
+                        return ERROR_MALFORMED;
+
                     durationUs =
-                        1000000LL * (mDataSize / (mNumChannels * bytesPerSample))
-                            / mSampleRate;
+                        1000000LL * num_samples / mSampleRate;
                 }
 
                 mTrackMeta->setInt64(kKeyDuration, durationUs);
diff --git a/media/libstagefright/codecs/amrnb/dec/Android.mk b/media/libstagefright/codecs/amrnb/dec/Android.mk
index 3750e2e..76a7f40 100644
--- a/media/libstagefright/codecs/amrnb/dec/Android.mk
+++ b/media/libstagefright/codecs/amrnb/dec/Android.mk
@@ -98,7 +98,7 @@
         libstagefright_amrnbdec libsndfile
 
 LOCAL_SHARED_LIBRARIES := \
-        libstagefright_amrnb_common libaudioutils
+        libstagefright_amrnb_common libaudioutils liblog
 
 LOCAL_MODULE := libstagefright_amrnbdec_test
 LOCAL_MODULE_TAGS := optional
diff --git a/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp b/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp
index fb7cff3..696d2da 100644
--- a/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp
@@ -59,6 +59,8 @@
 /*----------------------------------------------------------------------------
 ; INCLUDES
 ----------------------------------------------------------------------------*/
+#include <log/log.h>
+
 #include "a_refl.h"
 #include "typedef.h"
 #include "cnst.h"
@@ -291,7 +293,8 @@
                 {
                     refl[i] = 0;
                 }
-                break;
+                ALOGE("b/23609206");
+                return;
             }
 
             bState[j] = extract_l(L_temp);
diff --git a/media/libstagefright/codecs/amrnb/enc/Android.mk b/media/libstagefright/codecs/amrnb/enc/Android.mk
index bdba8a9..e8b010e 100644
--- a/media/libstagefright/codecs/amrnb/enc/Android.mk
+++ b/media/libstagefright/codecs/amrnb/enc/Android.mk
@@ -103,3 +103,25 @@
 LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_SHARED_LIBRARY)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := \
+    test/amrnb_enc_test.cpp
+
+LOCAL_C_INCLUDES := \
+    $(LOCAL_PATH)/src \
+    $(LOCAL_PATH)/../common/include
+
+
+LOCAL_STATIC_LIBRARIES := \
+    libstagefright_amrnbenc
+
+LOCAL_SHARED_LIBRARIES := \
+    libstagefright_amrnb_common
+
+LOCAL_MODULE := libstagefright_amrnbenc_test
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/media/libstagefright/codecs/amrnb/enc/src/l_negate.cpp b/media/libstagefright/codecs/amrnb/enc/src/l_negate.cpp
index 588abbb..523e482 100644
--- a/media/libstagefright/codecs/amrnb/enc/src/l_negate.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/src/l_negate.cpp
@@ -147,7 +147,7 @@
 /*----------------------------------------------------------------------------
 ; FUNCTION CODE
 ----------------------------------------------------------------------------*/
-Word32 L_negate(register Word32 L_var1)
+Word32 L_negate(Word32 L_var1)
 {
     /*----------------------------------------------------------------------------
     ; Define all local variables
diff --git a/media/libstagefright/codecs/amrnb/enc/test/amrnb_enc_test.cpp b/media/libstagefright/codecs/amrnb/enc/test/amrnb_enc_test.cpp
new file mode 100644
index 0000000..e2d198e
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/test/amrnb_enc_test.cpp
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <stdint.h>
+#include <assert.h>
+#include "gsmamr_enc.h"
+
+enum {
+    kInputSize = 320, // 160 samples * 16-bit per sample.
+    kOutputSize = 1024
+};
+
+struct AmrNbEncState {
+    void *encCtx;
+    void *pidSyncCtx;
+};
+
+void usage(void) {
+    printf("Usage:\n");
+    printf("AMRNBEnc [options] <input file> <output file>\n");
+    printf("\n");
+    printf("Options +M* for setting compression bitrate mode, default is 4.75 kbps\n");
+    printf(" +M0 = 4.75 kbps\n");
+    printf(" +M1 = 5.15 kbps\n");
+    printf(" +M2 = 5.90 kbps\n");
+    printf(" +M3 = 6.70 kbps\n");
+    printf(" +M4 = 7.40 kbps\n");
+    printf(" +M5 = 7.95 kbps\n");
+    printf(" +M6 = 10.2 kbps\n");
+    printf(" +M7 = 12.2 kbps\n");
+    printf("\n");
+}
+
+int encode(int mode, const char *srcFile, const char *dstFile) {
+    int           retVal     = EXIT_SUCCESS;
+    FILE          *fSrc      = NULL;
+    FILE          *fDst      = NULL;
+    int           frameNum   = 0;
+    bool          eofReached = false;
+    uint16_t      *inputBuf  = NULL;
+    uint8_t       *outputBuf = NULL;
+    AmrNbEncState *amr       = NULL;
+
+    clock_t   start, finish;
+    double    duration = 0.0;
+
+    // Open input file.
+    fSrc = fopen(srcFile, "rb");
+    if (fSrc == NULL) {
+        fprintf(stderr, "Error opening input file\n");
+        retVal = EXIT_FAILURE;
+        goto safe_exit;
+    }
+
+    // Open output file.
+    fDst = fopen(dstFile, "wb");
+    if (fDst == NULL) {
+        fprintf(stderr, "Error opening output file\n");
+        retVal = EXIT_FAILURE;
+        goto safe_exit;
+    }
+
+    // Allocate input buffer.
+    inputBuf = (uint16_t*) malloc(kInputSize);
+    assert(inputBuf != NULL);
+
+    // Allocate output buffer.
+    outputBuf = (uint8_t*) malloc(kOutputSize);
+    assert(outputBuf != NULL);
+
+    // Initialize encoder.
+    amr = (AmrNbEncState*) malloc(sizeof(AmrNbEncState));
+    AMREncodeInit(&amr->encCtx, &amr->pidSyncCtx, 0);
+
+    // Write file header.
+    fwrite("#!AMR\n", 1, 6, fDst);
+
+    while (1) {
+        // Read next input frame.
+        int bytesRead;
+        bytesRead = fread(inputBuf, 1, kInputSize, fSrc);
+        if (bytesRead != kInputSize && !feof(fSrc)) {
+            retVal = EXIT_FAILURE; // Invalid magic number.
+            fprintf(stderr, "Error reading input file\n");
+            goto safe_exit;
+        } else if (feof(fSrc) && bytesRead == 0) {
+            eofReached = true;
+            break;
+        }
+
+        start = clock();
+
+        // Encode the frame.
+        Frame_Type_3GPP frame_type = (Frame_Type_3GPP) mode;
+        int bytesGenerated;
+        bytesGenerated = AMREncode(amr->encCtx, amr->pidSyncCtx, (Mode)mode,
+                                   (Word16*)inputBuf, outputBuf, &frame_type,
+                                   AMR_TX_WMF);
+
+        // Convert from WMF to RFC 3267 format.
+        if (bytesGenerated > 0) {
+            outputBuf[0] = ((outputBuf[0] << 3) | 4) & 0x7c;
+        }
+
+        finish = clock();
+        duration += finish - start;
+
+        if (bytesGenerated < 0) {
+            retVal = EXIT_FAILURE;
+            fprintf(stderr, "Encoding error\n");
+            goto safe_exit;
+        }
+
+        frameNum++;
+        printf(" Frames processed: %d\n", frameNum);
+
+        // Write the output.
+        fwrite(outputBuf, 1, bytesGenerated, fDst);
+    }
+
+    // Dump the time taken by encode.
+    printf("\n%2.5lf seconds\n", (double)duration/CLOCKS_PER_SEC);
+
+safe_exit:
+
+    // Free the encoder instance.
+    if (amr) {
+        AMREncodeExit(&amr->encCtx, &amr->pidSyncCtx);
+        free(amr);
+    }
+
+    // Free input and output buffer.
+    free(inputBuf);
+    free(outputBuf);
+
+    // Close the input and output files.
+    if (fSrc) {
+        fclose(fSrc);
+    }
+    if (fDst) {
+        fclose(fDst);
+    }
+
+    return retVal;
+}
+
+int main(int argc, char *argv[]) {
+    Mode  mode = MR475;
+    int   retVal;
+    char  *inFileName = NULL;
+    char  *outFileName = NULL;
+    int   arg, filename = 0;
+
+    if (argc < 3) {
+        usage();
+        return EXIT_FAILURE;
+    } else {
+        for (arg = 1; arg < argc; arg++) {
+            if (argv[arg][0] == '+') {
+                if (argv[arg][1] == 'M') {
+                    switch (argv[arg][2]) {
+                    case '0': mode = MR475;
+                        break;
+                    case '1': mode = MR515;
+                        break;
+                    case '2': mode = MR59;
+                        break;
+                    case '3': mode = MR67;
+                        break;
+                    case '4': mode = MR74;
+                        break;
+                    case '5': mode = MR795;
+                        break;
+                    case '6': mode = MR102;
+                        break;
+                    case '7': mode = MR122;
+                        break;
+                    default:
+                        usage();
+                        fprintf(stderr, "Invalid parameter '%s'.\n", argv[arg]);
+                        return EXIT_FAILURE;
+                        break;
+                    }
+                } else {
+                    usage();
+                    fprintf(stderr, "Invalid parameter '%s'.\n", argv[arg]);
+                    return EXIT_FAILURE;
+                }
+            } else {
+                switch (filename) {
+                case 0:
+                    inFileName  = argv[arg];
+                    break;
+                case 1:
+                    outFileName = argv[arg];
+                    break;
+                default:
+                    usage();
+                    fprintf(stderr, "Invalid parameter '%s'.\n", argv[arg]);
+                    return EXIT_FAILURE;
+                }
+                filename++;
+            }
+        }
+    }
+
+    retVal = encode(mode, inFileName, outFileName);
+    return retVal;
+}
+
diff --git a/media/libstagefright/codecs/amrwb/Android.mk b/media/libstagefright/codecs/amrwb/Android.mk
index 686f7a3..6ce20ca 100644
--- a/media/libstagefright/codecs/amrwb/Android.mk
+++ b/media/libstagefright/codecs/amrwb/Android.mk
@@ -55,3 +55,24 @@
 LOCAL_MODULE := libstagefright_amrwbdec
 
 include $(BUILD_STATIC_LIBRARY)
+
+################################################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := \
+        test/amrwbdec_test.cpp
+
+LOCAL_C_INCLUDES := \
+        $(LOCAL_PATH)/src \
+        $(LOCAL_PATH)/include \
+        $(call include-path-for, audio-utils)
+
+LOCAL_STATIC_LIBRARIES := \
+        libstagefright_amrwbdec libsndfile
+
+LOCAL_SHARED_LIBRARIES := \
+        libaudioutils
+
+LOCAL_MODULE := libstagefright_amrwbdec_test
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/media/libstagefright/codecs/amrwb/test/amrwbdec_test.cpp b/media/libstagefright/codecs/amrwb/test/amrwbdec_test.cpp
new file mode 100644
index 0000000..b04bafd
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/test/amrwbdec_test.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "pvamrwbdecoder.h"
+#include <audio_utils/sndfile.h>
+
+// Constants for AMR-WB.
+enum {
+    kInputBufferSize = 64,
+    kSamplesPerFrame = 320,
+    kBitsPerSample = 16,
+    kOutputBufferSize = kSamplesPerFrame * kBitsPerSample/8,
+    kSampleRate = 16000,
+    kChannels = 1,
+    kFileHeaderSize = 9,
+    kMaxSourceDataUnitSize = 477 * sizeof(int16_t)
+};
+
+const uint32_t kFrameSizes[] = { 17, 23, 32, 36, 40, 46, 50, 58, 60 };
+
+int main(int argc, char *argv[]) {
+
+    if (argc != 3) {
+        fprintf(stderr, "Usage %s <input file> <output file>\n", argv[0]);
+        return EXIT_FAILURE;
+    }
+
+    // Open the input file.
+    FILE* fpInput = fopen(argv[1], "rb");
+    if (fpInput == NULL) {
+        fprintf(stderr, "Could not open %s\n", argv[1]);
+        return EXIT_FAILURE;
+    }
+
+    // Validate the input AMR file.
+    char header[kFileHeaderSize];
+    int bytesRead = fread(header, 1, kFileHeaderSize, fpInput);
+    if ((bytesRead != kFileHeaderSize) ||
+        (memcmp(header, "#!AMR-WB\n", kFileHeaderSize) != 0)) {
+        fprintf(stderr, "Invalid AMR-WB file\n");
+        fclose(fpInput);
+        return EXIT_FAILURE;
+    }
+
+    // Open the output file.
+    SF_INFO sfInfo;
+    memset(&sfInfo, 0, sizeof(SF_INFO));
+    sfInfo.channels = kChannels;
+    sfInfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
+    sfInfo.samplerate = kSampleRate;
+    SNDFILE *handle = sf_open(argv[2], SFM_WRITE, &sfInfo);
+    if (handle == NULL) {
+        fprintf(stderr, "Could not create %s\n", argv[2]);
+        fclose(fpInput);
+        return EXIT_FAILURE;
+    }
+
+    // Allocate the decoder memory.
+    uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
+    void *decoderBuf = malloc(memRequirements);
+    assert(decoderBuf != NULL);
+
+    // Create AMR-WB decoder instance.
+    void *amrHandle;
+    int16_t *decoderCookie;
+    pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
+
+    // Allocate input buffer.
+    uint8_t *inputBuf = (uint8_t*) malloc(kInputBufferSize);
+    assert(inputBuf != NULL);
+
+    // Allocate input sample buffer.
+    int16_t *inputSampleBuf = (int16_t*) malloc(kMaxSourceDataUnitSize);
+    assert(inputSampleBuf != NULL);
+
+    // Allocate output buffer.
+    int16_t *outputBuf = (int16_t*) malloc(kOutputBufferSize);
+    assert(outputBuf != NULL);
+
+    // Decode loop.
+    int retVal = EXIT_SUCCESS;
+    while (1) {
+        // Read mode.
+        uint8_t modeByte;
+        bytesRead = fread(&modeByte, 1, 1, fpInput);
+        if (bytesRead != 1) break;
+        int16 mode = ((modeByte >> 3) & 0x0f);
+
+        // AMR-WB file format cannot have mode 10, 11, 12 and 13.
+        if (mode >= 10 && mode <= 13) {
+            fprintf(stderr, "Encountered illegal frame type %d\n", mode);
+            retVal = EXIT_FAILURE;
+            break;
+        }
+
+        if (mode >= 9) {
+            // Produce silence for comfort noise, speech lost and no data.
+            memset(outputBuf, 0, kOutputBufferSize);
+        } else /* if (mode < 9) */ {
+            // Read rest of the frame.
+            int32_t frameSize = kFrameSizes[mode];
+            bytesRead = fread(inputBuf, 1, frameSize, fpInput);
+            if (bytesRead != frameSize) break;
+
+            int16 frameType, frameMode;
+            RX_State_wb rx_state;
+            frameMode = mode;
+            mime_unsorting(
+                    (uint8_t *)inputBuf,
+                    inputSampleBuf,
+                    &frameType, &frameMode, 1, &rx_state);
+
+            int16_t numSamplesOutput;
+            pvDecoder_AmrWb(
+                    frameMode, inputSampleBuf,
+                    outputBuf,
+                    &numSamplesOutput,
+                    decoderBuf, frameType, decoderCookie);
+
+            if (numSamplesOutput != kSamplesPerFrame) {
+                fprintf(stderr, "Decoder encountered error\n");
+                retVal = EXIT_FAILURE;
+                break;
+            }
+
+            for (int i = 0; i < kSamplesPerFrame; ++i) {
+                outputBuf[i] &= 0xfffC;
+            }
+        }
+
+        // Write output to wav.
+        sf_writef_short(handle, outputBuf, kSamplesPerFrame / kChannels);
+    }
+
+    // Close input and output file.
+    fclose(fpInput);
+    sf_close(handle);
+
+    // Free allocated memory.
+    free(inputBuf);
+    free(inputSampleBuf);
+    free(outputBuf);
+
+    return retVal;
+}
diff --git a/media/libstagefright/codecs/amrwbenc/Android.mk b/media/libstagefright/codecs/amrwbenc/Android.mk
index 64fe8d1..c7692cb 100644
--- a/media/libstagefright/codecs/amrwbenc/Android.mk
+++ b/media/libstagefright/codecs/amrwbenc/Android.mk
@@ -141,3 +141,6 @@
 LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_SHARED_LIBRARY)
+
+################################################################################
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c b/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c
index 4ff5f10..0cb0097 100644
--- a/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c
+++ b/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c
@@ -21,6 +21,7 @@
 
 #include      <stdio.h>
 #include      <stdlib.h>
+#include      <string.h>
 #include      <time.h>
 #include      "voAMRWB.h"
 #include      "cmnMemory.h"
@@ -222,12 +223,12 @@
 					fflush(fdst);
 				}
 			}
-			else if(returnCode == VO_ERR_LICENSE_ERROR)
+			else if((unsigned)returnCode == VO_ERR_LICENSE_ERROR)
 			{
 		        printf("Encoder time reach upper limit......");
 		        goto safe_exit;
 			}
-		} while(returnCode != VO_ERR_INPUT_BUFFER_SMALL);
+		} while((unsigned)returnCode != VO_ERR_INPUT_BUFFER_SMALL);
 
 		finish = clock();
 		duration += finish - start;
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk b/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk
index c203f77..65d69a2 100644
--- a/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk
+++ b/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk
@@ -5,17 +5,20 @@
     AMRWB_E_SAMPLE.c \
     ../../common/cmnMemory.c
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 LOCAL_MODULE := AMRWBEncTest
 
 LOCAL_ARM_MODE := arm
 
-LOCAL_CFLAGS := -DLINUX
+LOCAL_CFLAGS :=
 
 LOCAL_SHARED_LIBRARIES := \
     libstagefright \
     libdl
 
+LOCAL_STATIC_LIBRARIES := \
+    libstagefright_amrwbenc
+
 LOCAL_C_INCLUDES := \
     $(LOCAL_PATH)/ \
     $(LOCAL_PATH)/../../common \
diff --git a/media/libstagefright/codecs/amrwbenc/src/util.c b/media/libstagefright/codecs/amrwbenc/src/util.c
index 0369d78..333140d 100644
--- a/media/libstagefright/codecs/amrwbenc/src/util.c
+++ b/media/libstagefright/codecs/amrwbenc/src/util.c
@@ -35,9 +35,10 @@
 	     )
 {
 	Word32 num = (Word32)L;
-	do{
+	while (num > 0) {
 		*x++ = 0;
-	}while(--num !=0);
+                --num;
+	}
 }
 
 
@@ -54,18 +55,22 @@
 	 )
 {
 	Word32	temp1,temp2,num;
+        if (L <= 0) {
+                return;
+        }
 	if(L&1)
 	{
 		temp1 = *x++;
 		*y++ = temp1;
 	}
 	num = (Word32)(L>>1);
-	do{
+	while (num > 0) {
 		temp1 = *x++;
 		temp2 = *x++;
 		*y++ = temp1;
 		*y++ = temp2;
-	}while(--num!=0);
+                --num;
+	}
 }
 
 
diff --git a/media/libstagefright/codecs/avc/enc/Android.mk b/media/libstagefright/codecs/avc/enc/Android.mk
index 2ceebc8..d5131cb 100644
--- a/media/libstagefright/codecs/avc/enc/Android.mk
+++ b/media/libstagefright/codecs/avc/enc/Android.mk
@@ -74,3 +74,31 @@
 LOCAL_CFLAGS += -Werror
 
 include $(BUILD_SHARED_LIBRARY)
+
+################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+        test/h264_enc_test.cpp
+
+LOCAL_C_INCLUDES := \
+        $(LOCAL_PATH)/src \
+        $(LOCAL_PATH)/include \
+        $(LOCAL_PATH)/../common/include \
+        $(LOCAL_PATH)/../common
+
+LOCAL_CFLAGS := \
+    -DOSCL_IMPORT_REF= -DOSCL_UNUSED_ARG= -DOSCL_EXPORT_REF=
+
+LOCAL_STATIC_LIBRARIES := \
+        libstagefright_avcenc
+
+LOCAL_SHARED_LIBRARIES := \
+        libstagefright_avc_common
+
+LOCAL_MODULE := libstagefright_h264enc_test
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
index 928a74f..fa6ec40 100644
--- a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
+++ b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
@@ -244,6 +244,10 @@
     if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) {
         // Color conversion is needed.
         free(mInputFrameData);
+        if (((uint64_t)mWidth * mHeight) > ((uint64_t)INT32_MAX / 3)) {
+            ALOGE("Buffer size is too big.");
+            return OMX_ErrorUndefined;
+        }
         mInputFrameData =
             (uint8_t *) malloc((mWidth * mHeight * 3 ) >> 1);
         CHECK(mInputFrameData != NULL);
@@ -264,6 +268,10 @@
 
     int32_t nMacroBlocks = divUp(mWidth, 16) * divUp(mHeight, 16);
     CHECK(mSliceGroup == NULL);
+    if ((size_t)nMacroBlocks > SIZE_MAX / sizeof(uint32_t)) {
+        ALOGE("requested memory size is too big.");
+        return OMX_ErrorUndefined;
+    }
     mSliceGroup = (uint32_t *) malloc(sizeof(uint32_t) * nMacroBlocks);
     CHECK(mSliceGroup != NULL);
     for (int ii = 0, idx = 0; ii < nMacroBlocks; ++ii) {
diff --git a/media/libstagefright/codecs/avc/enc/test/h264_enc_test.cpp b/media/libstagefright/codecs/avc/enc/test/h264_enc_test.cpp
new file mode 100644
index 0000000..7a782a8
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/test/h264_enc_test.cpp
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "avcenc_api.h"
+#include "avcenc_int.h"
+
+// Constants.
+enum {
+    kMaxWidth         = 720,
+    kMaxHeight        = 480,
+    kMaxFrameRate     = 30,
+    kMaxBitrate       = 2048, // in kbps.
+    kInputBufferSize  = (kMaxWidth * kMaxHeight * 3) / 2, // For YUV 420 format.
+    kOutputBufferSize = kInputBufferSize,
+    kMaxDpbBuffers    = 17,
+    kIDRFrameRefreshIntervalInSec = 1,
+};
+
+
+static void *MallocCb(void * /*userData*/, int32_t size, int32_t /*attrs*/) {
+    void *ptr = calloc(size, 1);
+    return ptr;
+}
+
+static void FreeCb(void * /*userData*/, void *ptr) {
+    free(ptr);
+}
+
+static int32_t DpbAllocCb(void * /*userData*/,
+        unsigned int sizeInMbs, unsigned int numBuffers) {
+
+    size_t frameSize = (sizeInMbs << 7) * 3;
+    if(numBuffers < kMaxDpbBuffers && frameSize <= kInputBufferSize) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+static int32_t BindFrameCb(void *userData, int32_t index, uint8_t **yuv) {
+     assert(index < kMaxDpbBuffers);
+     uint8_t** dpbBuffer = static_cast<uint8_t**>(userData);
+     *yuv = dpbBuffer[index];
+     return 1;
+}
+
+static void UnbindFrameCb(void * /*userData*/, int32_t /*index*/) {
+}
+
+int main(int argc, char *argv[]) {
+
+    if (argc < 7) {
+        fprintf(stderr, "Usage %s <input yuv> <output file> <width> <height>"
+                        " <frame rate> <bitrate in kbps>\n", argv[0]);
+        fprintf(stderr, "Max width %d\n", kMaxWidth);
+        fprintf(stderr, "Max height %d\n", kMaxHeight);
+        fprintf(stderr, "Max framerate %d\n", kMaxFrameRate);
+        fprintf(stderr, "Max bitrate %d kbps\n", kMaxBitrate);
+        return EXIT_FAILURE;
+    }
+
+    // Read height and width.
+    int32_t width;
+    int32_t height;
+    width = atoi(argv[3]);
+    height = atoi(argv[4]);
+    if (width > kMaxWidth || height > kMaxHeight || width <= 0 || height <= 0) {
+        fprintf(stderr, "Unsupported dimensions %dx%d\n", width, height);
+        return EXIT_FAILURE;
+    }
+
+    if (width % 16 != 0 || height % 16 != 0) {
+        fprintf(stderr, "Video frame size %dx%d must be a multiple of 16\n",
+            width, height);
+        return EXIT_FAILURE;
+    }
+
+    // Read frame rate.
+    int32_t frameRate;
+    frameRate = atoi(argv[5]);
+    if (frameRate > kMaxFrameRate || frameRate <= 0) {
+        fprintf(stderr, "Unsupported frame rate %d\n", frameRate);
+        return EXIT_FAILURE;
+    }
+
+    // Read bit rate.
+    int32_t bitrate;
+    bitrate = atoi(argv[6]);
+    if (bitrate > kMaxBitrate || bitrate <= 0) {
+        fprintf(stderr, "Unsupported bitrate %d\n", bitrate);
+        return EXIT_FAILURE;
+    }
+    bitrate *= 1024; // kbps to bps.
+
+    // Open the input file.
+    FILE *fpInput = fopen(argv[1], "rb");
+    if (!fpInput) {
+        fprintf(stderr, "Could not open %s\n", argv[1]);
+        return EXIT_FAILURE;
+    }
+
+    // Open the output file.
+    FILE *fpOutput = fopen(argv[2], "wb");
+    if (!fpOutput) {
+        fprintf(stderr, "Could not open %s\n", argv[2]);
+        fclose(fpInput);
+        return EXIT_FAILURE;
+    }
+
+    // Allocate input buffer.
+    uint8_t *inputBuf = (uint8_t *)malloc(kInputBufferSize);
+    assert(inputBuf != NULL);
+
+    // Allocate output buffer.
+    uint8_t *outputBuf = (uint8_t *)malloc(kOutputBufferSize);
+    assert(outputBuf != NULL);
+
+    // Allocate dpb buffers.
+    uint8_t * dpbBuffers[kMaxDpbBuffers];
+    for (int i = 0; i < kMaxDpbBuffers; ++i) {
+        dpbBuffers[i] = (uint8_t *)malloc(kInputBufferSize);
+        assert(dpbBuffers[i] != NULL);
+    }
+
+    // Initialize the encoder parameters.
+    tagAVCEncParam encParams;
+    memset(&encParams, 0, sizeof(tagAVCEncParam));
+    encParams.rate_control = AVC_ON;
+    encParams.initQP = 0;
+    encParams.init_CBP_removal_delay = 1600;
+
+    encParams.intramb_refresh = 0;
+    encParams.auto_scd = AVC_ON;
+    encParams.out_of_band_param_set = AVC_ON;
+    encParams.poc_type = 2;
+    encParams.log2_max_poc_lsb_minus_4 = 12;
+    encParams.delta_poc_zero_flag = 0;
+    encParams.offset_poc_non_ref = 0;
+    encParams.offset_top_bottom = 0;
+    encParams.num_ref_in_cycle = 0;
+    encParams.offset_poc_ref = NULL;
+
+    encParams.num_ref_frame = 1;
+    encParams.num_slice_group = 1;
+    encParams.fmo_type = 0;
+
+    encParams.db_filter = AVC_ON;
+    encParams.disable_db_idc = 0;
+
+    encParams.alpha_offset = 0;
+    encParams.beta_offset = 0;
+    encParams.constrained_intra_pred = AVC_OFF;
+
+    encParams.data_par = AVC_OFF;
+    encParams.fullsearch = AVC_OFF;
+    encParams.search_range = 16;
+    encParams.sub_pel = AVC_OFF;
+    encParams.submb_pred = AVC_OFF;
+    encParams.rdopt_mode = AVC_OFF;
+    encParams.bidir_pred = AVC_OFF;
+
+    encParams.use_overrun_buffer = AVC_OFF;
+
+    encParams.width = width;
+    encParams.height = height;
+    encParams.bitrate = bitrate;
+    encParams.frame_rate = 1000 * frameRate;  // In frames/ms.
+    encParams.CPB_size = (uint32_t) (bitrate >> 1);
+
+    int32_t  IDRFrameRefreshIntervalInSec = kIDRFrameRefreshIntervalInSec;
+    if (IDRFrameRefreshIntervalInSec == 0) {
+        encParams.idr_period = 1;  // All I frames.
+    } else {
+        encParams.idr_period = (IDRFrameRefreshIntervalInSec * frameRate);
+    }
+
+    int32_t nMacroBlocks = ((((width + 15) >> 4) << 4) *
+            (((height + 15) >> 4) << 4)) >> 8;
+    uint32_t *sliceGroup = (uint32_t *) malloc(sizeof(uint32_t) * nMacroBlocks);
+    assert(sliceGroup != NULL);
+    for (int i = 0, idx = 0; i < nMacroBlocks; ++i) {
+        sliceGroup[i] = idx++;
+        if (idx >= encParams.num_slice_group) {
+            idx = 0;
+        }
+    }
+    encParams.slice_group = sliceGroup;
+    encParams.profile = AVC_BASELINE;
+    encParams.level = AVC_LEVEL2;
+
+    // Initialize the handle.
+    tagAVCHandle handle;
+    memset(&handle, 0, sizeof(tagAVCHandle));
+    handle.AVCObject = NULL;
+    handle.userData = dpbBuffers;
+    handle.CBAVC_DPBAlloc = DpbAllocCb;
+    handle.CBAVC_FrameBind = BindFrameCb;
+    handle.CBAVC_FrameUnbind = UnbindFrameCb;
+    handle.CBAVC_Malloc = MallocCb;
+    handle.CBAVC_Free = FreeCb;
+
+    // Initialize the encoder.
+    AVCEnc_Status status;
+    status = PVAVCEncInitialize(&handle, &encParams, NULL, NULL);
+    if (status != AVCENC_SUCCESS) {
+        fprintf(stderr, "Failed to initialize the encoder\n");
+
+        // Release resources.
+        fclose(fpInput);
+        fclose(fpOutput);
+        free(sliceGroup);
+        free(inputBuf);
+        free(outputBuf);
+        for (int i = 0; i < kMaxDpbBuffers; ++i) {
+            free(dpbBuffers[i]);
+        }
+        return EXIT_FAILURE;
+    }
+
+    // Encode Sequence Parameter Set.
+    uint32_t dataLength = kOutputBufferSize;
+    int32_t type;
+    status = PVAVCEncodeNAL(&handle, outputBuf, &dataLength, &type);
+    assert(type == AVC_NALTYPE_SPS);
+    fwrite("\x00\x00\x00\x01", 1, 4, fpOutput); // Start Code.
+    fwrite(outputBuf, 1, dataLength, fpOutput); // SPS.
+
+    // Encode Picture Paramater Set.
+    dataLength = kOutputBufferSize;
+    status = PVAVCEncodeNAL(&handle, outputBuf, &dataLength, &type);
+    assert(type == AVC_NALTYPE_PPS);
+    fwrite("\x00\x00\x00\x01", 1, 4, fpOutput); // Start Code.
+    fwrite(outputBuf, 1, dataLength, fpOutput); // PPS.
+
+    // Core loop.
+    int32_t retVal = EXIT_SUCCESS;
+    int32_t frameSize = (width * height * 3) / 2;
+    int32_t numInputFrames = 0;
+    int32_t numNalEncoded = 0;
+    bool readyForNextFrame = true;
+
+    while (1) {
+        if (readyForNextFrame == true) {
+            // Read the input frame.
+            int32_t bytesRead;
+            bytesRead = fread(inputBuf, 1, frameSize, fpInput);
+            if (bytesRead != frameSize) {
+                break; // End of file.
+            }
+
+            // Set the input frame.
+            AVCFrameIO vin;
+            memset(&vin, 0, sizeof(vin));
+            vin.height = ((height + 15) >> 4) << 4;
+            vin.pitch  = ((width  + 15) >> 4) << 4;
+            vin.coding_timestamp = (numInputFrames * 1000) / frameRate;  // in ms
+            vin.YCbCr[0] = inputBuf;
+            vin.YCbCr[1] = vin.YCbCr[0] + vin.height * vin.pitch;
+            vin.YCbCr[2] = vin.YCbCr[1] + ((vin.height * vin.pitch) >> 2);
+            vin.disp_order = numInputFrames;
+
+            status = PVAVCEncSetInput(&handle, &vin);
+            if (status == AVCENC_SUCCESS || status == AVCENC_NEW_IDR) {
+                readyForNextFrame = false;
+                ++numInputFrames;
+            } else if (status < AVCENC_SUCCESS) {
+                fprintf(stderr, "Error %d while setting input frame\n", status);
+                retVal = EXIT_FAILURE;
+                break;
+            } else {
+                fprintf(stderr, "Frame drop\n");
+                readyForNextFrame = true;
+                ++numInputFrames;
+                continue;
+            }
+        }
+
+        // Encode the input frame.
+        dataLength = kOutputBufferSize;
+        status = PVAVCEncodeNAL(&handle, outputBuf, &dataLength, &type);
+        if (status == AVCENC_SUCCESS) {
+            PVAVCEncGetOverrunBuffer(&handle);
+        } else if (status == AVCENC_PICTURE_READY) {
+            PVAVCEncGetOverrunBuffer(&handle);
+            readyForNextFrame = true;
+            AVCFrameIO recon;
+            if (PVAVCEncGetRecon(&handle, &recon) == AVCENC_SUCCESS) {
+                PVAVCEncReleaseRecon(&handle, &recon);
+            }
+        } else {
+            dataLength = 0;
+            readyForNextFrame = true;
+        }
+
+        if (status < AVCENC_SUCCESS) {
+            fprintf(stderr, "Error %d while encoding frame\n", status);
+            retVal = EXIT_FAILURE;
+            break;
+        }
+
+        numNalEncoded++;
+
+        // Write the output.
+        if (dataLength > 0) {
+            fwrite("\x00\x00\x00\x01", 1, 4, fpOutput); // Start Code.
+            fwrite(outputBuf, 1, dataLength, fpOutput); // NAL.
+            printf("NAL %d of size %d written\n", numNalEncoded, dataLength + 4);
+        }
+    }
+
+    // Close input and output file.
+    fclose(fpInput);
+    fclose(fpOutput);
+
+    // Free allocated memory.
+    free(sliceGroup);
+    free(inputBuf);
+    free(outputBuf);
+    for (int i = 0; i < kMaxDpbBuffers; ++i) {
+        free(dpbBuffers[i]);
+    }
+
+    // Close encoder instance.
+    PVAVCCleanUpEncoder(&handle);
+
+    return retVal;
+}
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
index e083315..7c5093e 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
@@ -38,10 +38,10 @@
 
 /** Function and structure definitions to keep code similar for each codec */
 #define ivdec_api_function              ih264d_api_function
-#define ivdext_init_ip_t                ih264d_init_ip_t
-#define ivdext_init_op_t                ih264d_init_op_t
-#define ivdext_fill_mem_rec_ip_t        ih264d_fill_mem_rec_ip_t
-#define ivdext_fill_mem_rec_op_t        ih264d_fill_mem_rec_op_t
+#define ivdext_create_ip_t              ih264d_create_ip_t
+#define ivdext_create_op_t              ih264d_create_op_t
+#define ivdext_delete_ip_t              ih264d_delete_ip_t
+#define ivdext_delete_op_t              ih264d_delete_op_t
 #define ivdext_ctl_set_num_cores_ip_t   ih264d_ctl_set_num_cores_ip_t
 #define ivdext_ctl_set_num_cores_op_t   ih264d_ctl_set_num_cores_op_t
 
@@ -115,15 +115,12 @@
             320 /* width */, 240 /* height */, callbacks,
             appData, component),
       mCodecCtx(NULL),
-      mMemRecords(NULL),
       mFlushOutBuffer(NULL),
       mOmxColorFormat(OMX_COLOR_FormatYUV420Planar),
       mIvColorFormat(IV_YUV_420P),
-      mNewWidth(mWidth),
-      mNewHeight(mHeight),
-      mNewLevel(0),
       mChangingResolution(false),
-      mSignalledError(false) {
+      mSignalledError(false),
+      mStride(mWidth){
     initPorts(
             kNumBuffers, INPUT_BUF_SIZE, kNumBuffers, CODEC_MIME_TYPE);
 
@@ -132,14 +129,23 @@
     // If input dump is enabled, then open create an empty file
     GENERATE_FILE_NAMES();
     CREATE_DUMP_FILE(mInFile);
-
-    CHECK_EQ(initDecoder(mWidth, mHeight), (status_t)OK);
 }
 
 SoftAVC::~SoftAVC() {
     CHECK_EQ(deInitDecoder(), (status_t)OK);
 }
 
+static void *ivd_aligned_malloc(void *ctxt, WORD32 alignment, WORD32 size) {
+    UNUSED(ctxt);
+    return memalign(alignment, size);
+}
+
+static void ivd_aligned_free(void *ctxt, void *buf) {
+    UNUSED(ctxt);
+    free(buf);
+    return;
+}
+
 static size_t GetCPUCoreCount() {
     long cpuCoreCount = 1;
 #if defined(_SC_NPROCESSORS_ONLN)
@@ -149,7 +155,7 @@
     cpuCoreCount = sysconf(_SC_NPROC_ONLN);
 #endif
     CHECK(cpuCoreCount >= 1);
-    ALOGD("Number of CPU cores: %ld", cpuCoreCount);
+    ALOGV("Number of CPU cores: %ld", cpuCoreCount);
     return (size_t)cpuCoreCount;
 }
 
@@ -235,12 +241,10 @@
     }
     mSignalledError = false;
 
-    /* Set the run-time (dynamic) parameters */
-    setParams(outputBufferWidth());
-
     /* Set number of cores/threads to be used by the codec */
     setNumCores();
 
+    mStride = 0;
     return OK;
 }
 
@@ -287,160 +291,41 @@
     return OK;
 }
 
-status_t SoftAVC::initDecoder(uint32_t width, uint32_t height) {
+status_t SoftAVC::initDecoder() {
     IV_API_CALL_STATUS_T status;
 
-    UWORD32 u4_num_reorder_frames;
-    UWORD32 u4_num_ref_frames;
-    UWORD32 u4_share_disp_buf;
-    WORD32 i4_level;
-
     mNumCores = GetCPUCoreCount();
     mCodecCtx = NULL;
 
-    /* Initialize number of ref and reorder modes (for H264) */
-    u4_num_reorder_frames = 16;
-    u4_num_ref_frames = 16;
-    u4_share_disp_buf = 0;
-
-    uint32_t displayStride = mIsAdaptive ? mAdaptiveMaxWidth : width;
-    uint32_t displayHeight = mIsAdaptive ? mAdaptiveMaxHeight : height;
-    uint32_t displaySizeY = displayStride * displayHeight;
-
-    if(mNewLevel == 0){
-        if (displaySizeY > (1920 * 1088)) {
-            i4_level = 50;
-        } else if (displaySizeY > (1280 * 720)) {
-            i4_level = 40;
-        } else if (displaySizeY > (720 * 576)) {
-            i4_level = 31;
-        } else if (displaySizeY > (624 * 320)) {
-            i4_level = 30;
-        } else if (displaySizeY > (352 * 288)) {
-            i4_level = 21;
-        } else {
-            i4_level = 20;
-        }
-    } else {
-        i4_level = mNewLevel;
-    }
-
-    {
-        iv_num_mem_rec_ip_t s_num_mem_rec_ip;
-        iv_num_mem_rec_op_t s_num_mem_rec_op;
-
-        s_num_mem_rec_ip.u4_size = sizeof(s_num_mem_rec_ip);
-        s_num_mem_rec_op.u4_size = sizeof(s_num_mem_rec_op);
-        s_num_mem_rec_ip.e_cmd = IV_CMD_GET_NUM_MEM_REC;
-
-        ALOGV("Get number of mem records");
-        status = ivdec_api_function(
-                mCodecCtx, (void *)&s_num_mem_rec_ip, (void *)&s_num_mem_rec_op);
-        if (IV_SUCCESS != status) {
-            ALOGE("Error in getting mem records: 0x%x",
-                    s_num_mem_rec_op.u4_error_code);
-            return UNKNOWN_ERROR;
-        }
-
-        mNumMemRecords = s_num_mem_rec_op.u4_num_mem_rec;
-    }
-
-    mMemRecords = (iv_mem_rec_t *)ivd_aligned_malloc(
-            128, mNumMemRecords * sizeof(iv_mem_rec_t));
-    if (mMemRecords == NULL) {
-        ALOGE("Allocation failure");
-        return NO_MEMORY;
-    }
-
-    memset(mMemRecords, 0, mNumMemRecords * sizeof(iv_mem_rec_t));
-
-    {
-        size_t i;
-        ivdext_fill_mem_rec_ip_t s_fill_mem_ip;
-        ivdext_fill_mem_rec_op_t s_fill_mem_op;
-        iv_mem_rec_t *ps_mem_rec;
-
-        s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_size =
-            sizeof(ivdext_fill_mem_rec_ip_t);
-        s_fill_mem_ip.i4_level = i4_level;
-        s_fill_mem_ip.u4_num_reorder_frames = u4_num_reorder_frames;
-        s_fill_mem_ip.u4_num_ref_frames = u4_num_ref_frames;
-        s_fill_mem_ip.u4_share_disp_buf = u4_share_disp_buf;
-        s_fill_mem_ip.u4_num_extra_disp_buf = 0;
-        s_fill_mem_ip.e_output_format = mIvColorFormat;
-
-        s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.e_cmd = IV_CMD_FILL_NUM_MEM_REC;
-        s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.pv_mem_rec_location = mMemRecords;
-        s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_wd = displayStride;
-        s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_ht = displayHeight;
-        s_fill_mem_op.s_ivd_fill_mem_rec_op_t.u4_size =
-            sizeof(ivdext_fill_mem_rec_op_t);
-
-        ps_mem_rec = mMemRecords;
-        for (i = 0; i < mNumMemRecords; i++) {
-            ps_mem_rec[i].u4_size = sizeof(iv_mem_rec_t);
-        }
-
-        status = ivdec_api_function(
-                mCodecCtx, (void *)&s_fill_mem_ip, (void *)&s_fill_mem_op);
-
-        if (IV_SUCCESS != status) {
-            ALOGE("Error in filling mem records: 0x%x",
-                    s_fill_mem_op.s_ivd_fill_mem_rec_op_t.u4_error_code);
-            return UNKNOWN_ERROR;
-        }
-        mNumMemRecords =
-            s_fill_mem_op.s_ivd_fill_mem_rec_op_t.u4_num_mem_rec_filled;
-
-        ps_mem_rec = mMemRecords;
-
-        for (i = 0; i < mNumMemRecords; i++) {
-            ps_mem_rec->pv_base = ivd_aligned_malloc(
-                    ps_mem_rec->u4_mem_alignment, ps_mem_rec->u4_mem_size);
-            if (ps_mem_rec->pv_base == NULL) {
-                ALOGE("Allocation failure for memory record #%zu of size %u",
-                        i, ps_mem_rec->u4_mem_size);
-                status = IV_FAIL;
-                return NO_MEMORY;
-            }
-
-            ps_mem_rec++;
-        }
-    }
+    mStride = outputBufferWidth();
 
     /* Initialize the decoder */
     {
-        ivdext_init_ip_t s_init_ip;
-        ivdext_init_op_t s_init_op;
+        ivdext_create_ip_t s_create_ip;
+        ivdext_create_op_t s_create_op;
 
         void *dec_fxns = (void *)ivdec_api_function;
 
-        s_init_ip.s_ivd_init_ip_t.u4_size = sizeof(ivdext_init_ip_t);
-        s_init_ip.s_ivd_init_ip_t.e_cmd = (IVD_API_COMMAND_TYPE_T)IV_CMD_INIT;
-        s_init_ip.s_ivd_init_ip_t.pv_mem_rec_location = mMemRecords;
-        s_init_ip.s_ivd_init_ip_t.u4_frm_max_wd = displayStride;
-        s_init_ip.s_ivd_init_ip_t.u4_frm_max_ht = displayHeight;
+        s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ivdext_create_ip_t);
+        s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE;
+        s_create_ip.s_ivd_create_ip_t.u4_share_disp_buf = 0;
+        s_create_op.s_ivd_create_op_t.u4_size = sizeof(ivdext_create_op_t);
+        s_create_ip.s_ivd_create_ip_t.e_output_format = mIvColorFormat;
+        s_create_ip.s_ivd_create_ip_t.pf_aligned_alloc = ivd_aligned_malloc;
+        s_create_ip.s_ivd_create_ip_t.pf_aligned_free = ivd_aligned_free;
+        s_create_ip.s_ivd_create_ip_t.pv_mem_ctxt = NULL;
 
-        s_init_ip.i4_level = i4_level;
-        s_init_ip.u4_num_reorder_frames = u4_num_reorder_frames;
-        s_init_ip.u4_num_ref_frames = u4_num_ref_frames;
-        s_init_ip.u4_share_disp_buf = u4_share_disp_buf;
-        s_init_ip.u4_num_extra_disp_buf = 0;
+        status = ivdec_api_function(mCodecCtx, (void *)&s_create_ip, (void *)&s_create_op);
 
-        s_init_op.s_ivd_init_op_t.u4_size = sizeof(s_init_op);
-
-        s_init_ip.s_ivd_init_ip_t.u4_num_mem_rec = mNumMemRecords;
-        s_init_ip.s_ivd_init_ip_t.e_output_format = mIvColorFormat;
-
-        mCodecCtx = (iv_obj_t *)mMemRecords[0].pv_base;
+        mCodecCtx = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle;
         mCodecCtx->pv_fxns = dec_fxns;
         mCodecCtx->u4_size = sizeof(iv_obj_t);
 
-        status = ivdec_api_function(mCodecCtx, (void *)&s_init_ip, (void *)&s_init_op);
         if (status != IV_SUCCESS) {
+            ALOGE("Error in create: 0x%x",
+                    s_create_op.s_ivd_create_op_t.u4_error_code);
+            deInitDecoder();
             mCodecCtx = NULL;
-            ALOGE("Error in init: 0x%x",
-                    s_init_op.s_ivd_init_op_t.u4_error_code);
             return UNKNOWN_ERROR;
         }
     }
@@ -449,7 +334,7 @@
     resetPlugin();
 
     /* Set the run time (dynamic) parameters */
-    setParams(displayStride);
+    setParams(mStride);
 
     /* Set number of cores/threads to be used by the codec */
     setNumCores();
@@ -457,61 +342,37 @@
     /* Get codec version */
     logVersion();
 
-    /* Allocate internal picture buffer */
-    uint32_t bufferSize = displaySizeY * 3 / 2;
-    mFlushOutBuffer = (uint8_t *)ivd_aligned_malloc(128, bufferSize);
-    if (NULL == mFlushOutBuffer) {
-        ALOGE("Could not allocate flushOutputBuffer of size %u", bufferSize);
-        return NO_MEMORY;
-    }
-
-    mInitNeeded = false;
     mFlushNeeded = false;
     return OK;
 }
 
 status_t SoftAVC::deInitDecoder() {
     size_t i;
+    IV_API_CALL_STATUS_T status;
 
-    if (mMemRecords) {
-        iv_mem_rec_t *ps_mem_rec;
+    if (mCodecCtx) {
+        ivdext_delete_ip_t s_delete_ip;
+        ivdext_delete_op_t s_delete_op;
 
-        ps_mem_rec = mMemRecords;
-        for (i = 0; i < mNumMemRecords; i++) {
-            if (ps_mem_rec->pv_base) {
-                ivd_aligned_free(ps_mem_rec->pv_base);
-            }
-            ps_mem_rec++;
+        s_delete_ip.s_ivd_delete_ip_t.u4_size = sizeof(ivdext_delete_ip_t);
+        s_delete_ip.s_ivd_delete_ip_t.e_cmd = IVD_CMD_DELETE;
+
+        s_delete_op.s_ivd_delete_op_t.u4_size = sizeof(ivdext_delete_op_t);
+
+        status = ivdec_api_function(mCodecCtx, (void *)&s_delete_ip, (void *)&s_delete_op);
+        if (status != IV_SUCCESS) {
+            ALOGE("Error in delete: 0x%x",
+                    s_delete_op.s_ivd_delete_op_t.u4_error_code);
+            return UNKNOWN_ERROR;
         }
-        ivd_aligned_free(mMemRecords);
-        mMemRecords = NULL;
     }
 
-    if (mFlushOutBuffer) {
-        ivd_aligned_free(mFlushOutBuffer);
-        mFlushOutBuffer = NULL;
-    }
 
-    mInitNeeded = true;
     mChangingResolution = false;
 
     return OK;
 }
 
-status_t SoftAVC::reInitDecoder(uint32_t width, uint32_t height) {
-    status_t ret;
-
-    deInitDecoder();
-
-    ret = initDecoder(width, height);
-    if (OK != ret) {
-        ALOGE("Create failure");
-        deInitDecoder();
-        return NO_MEMORY;
-    }
-    return OK;
-}
-
 void SoftAVC::onReset() {
     SoftVideoDecoderOMXComponent::onReset();
 
@@ -520,23 +381,6 @@
     resetPlugin();
 }
 
-OMX_ERRORTYPE SoftAVC::internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR params) {
-    const uint32_t oldWidth = mWidth;
-    const uint32_t oldHeight = mHeight;
-    OMX_ERRORTYPE ret = SoftVideoDecoderOMXComponent::internalSetParameter(index, params);
-    if (mWidth != oldWidth || mHeight != oldHeight) {
-        mNewWidth = mWidth;
-        mNewHeight = mHeight;
-        status_t err = reInitDecoder(mNewWidth, mNewHeight);
-        if (err != OK) {
-            notify(OMX_EventError, OMX_ErrorUnsupportedSetting, err, NULL);
-            mSignalledError = true;
-            return OMX_ErrorUnsupportedSetting;
-        }
-    }
-    return ret;
-}
-
 void SoftAVC::setDecodeArgs(
         ivd_video_decode_ip_t *ps_dec_ip,
         ivd_video_decode_op_t *ps_dec_op,
@@ -587,6 +431,17 @@
     if (kOutputPortIndex == portIndex) {
         setFlushMode();
 
+        /* Allocate a picture buffer to flushed data */
+        uint32_t displayStride = outputBufferWidth();
+        uint32_t displayHeight = outputBufferHeight();
+
+        uint32_t bufferSize = displayStride * displayHeight * 3 / 2;
+        mFlushOutBuffer = (uint8_t *)memalign(128, bufferSize);
+        if (NULL == mFlushOutBuffer) {
+            ALOGE("Could not allocate flushOutputBuffer of size %zu", bufferSize);
+            return;
+        }
+
         while (true) {
             ivd_video_decode_ip_t s_dec_ip;
             ivd_video_decode_op_t s_dec_op;
@@ -601,6 +456,12 @@
                 break;
             }
         }
+
+        if (mFlushOutBuffer) {
+            free(mFlushOutBuffer);
+            mFlushOutBuffer = NULL;
+        }
+
     }
 }
 
@@ -614,6 +475,17 @@
         return;
     }
 
+    if (NULL == mCodecCtx) {
+        if (OK != initDecoder()) {
+            return;
+        }
+    }
+    if (outputBufferWidth() != mStride) {
+        /* Set the run-time (dynamic) parameters */
+        mStride = outputBufferWidth();
+        setParams(mStride);
+    }
+
     List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
     List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
 
@@ -676,22 +548,6 @@
             }
         }
 
-        // When there is an init required and the decoder is not in flush mode,
-        // update output port's definition and reinitialize decoder.
-        if (mInitNeeded && !mIsInFlush) {
-            bool portWillReset = false;
-
-            status_t err = reInitDecoder(mNewWidth, mNewHeight);
-            if (err != OK) {
-                notify(OMX_EventError, OMX_ErrorUnsupportedSetting, err, NULL);
-                mSignalledError = true;
-                return;
-            }
-
-            handlePortSettingsChange(&portWillReset, mNewWidth, mNewHeight);
-            return;
-        }
-
         /* Get a free slot in timestamp array to hold input timestamp */
         {
             size_t i;
@@ -726,10 +582,7 @@
             IV_API_CALL_STATUS_T status;
             status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
 
-            bool unsupportedDimensions =
-                (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_dec_op.u4_error_code & 0xFF));
             bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & 0xFF));
-            bool unsupportedLevel = (IH264D_UNSUPPORTED_LEVEL == (s_dec_op.u4_error_code & 0xFF));
 
             GETTIME(&mTimeEnd, NULL);
             /* Compute time taken for decode() */
@@ -747,46 +600,6 @@
                 mTimeStampsValid[timeStampIx] = false;
             }
 
-
-            // This is needed to handle CTS DecoderTest testCodecResetsH264WithoutSurface,
-            // which is not sending SPS/PPS after port reconfiguration and flush to the codec.
-            if (unsupportedDimensions && !mFlushNeeded) {
-                bool portWillReset = false;
-                mNewWidth = s_dec_op.u4_pic_wd;
-                mNewHeight = s_dec_op.u4_pic_ht;
-
-                status_t err = reInitDecoder(mNewWidth, mNewHeight);
-                if (err != OK) {
-                    notify(OMX_EventError, OMX_ErrorUnsupportedSetting, err, NULL);
-                    mSignalledError = true;
-                    return;
-                }
-
-                handlePortSettingsChange(&portWillReset, mNewWidth, mNewHeight);
-
-                setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx);
-
-                ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
-                return;
-            }
-
-            if (unsupportedLevel && !mFlushNeeded) {
-
-                mNewLevel = 51;
-
-                status_t err = reInitDecoder(mNewWidth, mNewHeight);
-                if (err != OK) {
-                    notify(OMX_EventError, OMX_ErrorUnsupportedSetting, err, NULL);
-                    mSignalledError = true;
-                    return;
-                }
-
-                setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx);
-
-                ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
-                return;
-            }
-
             // If the decoder is in the changing resolution mode and there is no output present,
             // that means the switching is done and it's ready to reset the decoder and the plugin.
             if (mChangingResolution && !s_dec_op.u4_output_present) {
@@ -796,28 +609,11 @@
                 continue;
             }
 
-            if (unsupportedDimensions || resChanged) {
+            if (resChanged) {
                 mChangingResolution = true;
                 if (mFlushNeeded) {
                     setFlushMode();
                 }
-
-                if (unsupportedDimensions) {
-                    mNewWidth = s_dec_op.u4_pic_wd;
-                    mNewHeight = s_dec_op.u4_pic_ht;
-                    mInitNeeded = true;
-                }
-                continue;
-            }
-
-            if (unsupportedLevel) {
-
-                if (mFlushNeeded) {
-                    setFlushMode();
-                }
-
-                mNewLevel = 51;
-                mInitNeeded = true;
                 continue;
             }
 
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.h b/media/libstagefright/codecs/avcdec/SoftAVCDec.h
index 1ec8991..9dcabb4 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.h
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.h
@@ -23,9 +23,6 @@
 
 namespace android {
 
-#define ivd_aligned_malloc(alignment, size) memalign(alignment, size)
-#define ivd_aligned_free(buf) free(buf)
-
 /** Number of entries in the time-stamp array */
 #define MAX_TIME_STAMPS 64
 
@@ -62,7 +59,6 @@
     virtual void onQueueFilled(OMX_U32 portIndex);
     virtual void onPortFlushCompleted(OMX_U32 portIndex);
     virtual void onReset();
-    virtual OMX_ERRORTYPE internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR params);
 private:
     // Number of input and output buffers
     enum {
@@ -70,8 +66,6 @@
     };
 
     iv_obj_t *mCodecCtx;         // Codec context
-    iv_mem_rec_t *mMemRecords;   // Memory records requested by the codec
-    size_t mNumMemRecords;       // Number of memory records requested by the codec
 
     size_t mNumCores;            // Number of cores to be uesd by the codec
 
@@ -97,17 +91,15 @@
 
     bool mIsInFlush;        // codec is flush mode
     bool mReceivedEOS;      // EOS is receieved on input port
-    bool mInitNeeded;
-    uint32_t mNewWidth;
-    uint32_t mNewHeight;
-    uint32_t mNewLevel;
+
     // The input stream has changed to a different resolution, which is still supported by the
     // codec. So the codec is switching to decode the new resolution.
     bool mChangingResolution;
     bool mFlushNeeded;
     bool mSignalledError;
+    size_t mStride;
 
-    status_t initDecoder(uint32_t width, uint32_t height);
+    status_t initDecoder();
     status_t deInitDecoder();
     status_t setFlushMode();
     status_t setParams(size_t stride);
@@ -115,7 +107,7 @@
     status_t setNumCores();
     status_t resetDecoder();
     status_t resetPlugin();
-    status_t reInitDecoder(uint32_t width, uint32_t height);
+
 
     void setDecodeArgs(
             ivd_video_decode_ip_t *ps_dec_ip,
diff --git a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
index c627be4..387d17d 100644
--- a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
+++ b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
@@ -640,7 +640,7 @@
                 mConversionBuffers[i] = 0;
             }
 
-            if (((uint64_t)mStride * mHeight) > (((uint64_t)INT32_MAX / 3) * 2)) {
+            if (((uint64_t)mStride * mHeight) > ((uint64_t)INT32_MAX / 3)) {
                 ALOGE("Buffer size is too big.");
                 return OMX_ErrorUndefined;
             }
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
index af19bfe..c1720c6 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
@@ -19,6 +19,14 @@
 #include "vlc_decode.h"
 #include "bitstream.h"
 
+#ifndef INT32_MAX
+#define INT32_MAX 0x7fffffff
+#endif
+
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t) -1)
+#endif
+
 #define OSCL_DISABLE_WARNING_CONDITIONAL_IS_CONSTANT
 
 #ifdef DEC_INTERNAL_MEMORY_OPT
@@ -335,7 +343,7 @@
     video->prevVop->uChan = video->prevVop->yChan + size;
     video->prevVop->vChan = video->prevVop->uChan + (size >> 2);
 #else
-    if (size > INT32_MAX / 3 * 2) {
+    if (size > INT32_MAX / 3) {
         return PV_FALSE;
     }
     video->currVop->yChan = (PIXEL *) oscl_malloc(size * 3 / 2); /* Allocate memory for all VOP OKA 3/2/1*/
@@ -365,7 +373,7 @@
         {
             oscl_memset(video->prevEnhcVop, 0, sizeof(Vop));
 #ifndef PV_MEMORY_POOL
-            if (size > INT32_MAX / 3 * 2) {
+            if (size > INT32_MAX / 3) {
                 return PV_FALSE;
             }
 
diff --git a/media/libstagefright/codecs/m4v_h263/enc/Android.mk b/media/libstagefright/codecs/m4v_h263/enc/Android.mk
index 7117692..762e6fe 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/Android.mk
+++ b/media/libstagefright/codecs/m4v_h263/enc/Android.mk
@@ -77,3 +77,23 @@
 LOCAL_CFLAGS += -Werror
 
 include $(BUILD_SHARED_LIBRARY)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := \
+        test/m4v_h263_enc_test.cpp
+
+LOCAL_C_INCLUDES := \
+        $(LOCAL_PATH)/src \
+        $(LOCAL_PATH)/include
+
+LOCAL_CFLAGS := -DOSCL_EXPORT_REF= -DOSCL_IMPORT_REF= -DBX_RC
+
+LOCAL_STATIC_LIBRARIES := \
+        libstagefright_m4vh263enc
+
+LOCAL_MODULE := libstagefright_m4vh263enc_test
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
index da27377..c2b7c8d 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
@@ -21,6 +21,13 @@
 #include "rate_control.h"
 #include "m4venc_oscl.h"
 
+#ifndef INT32_MAX
+#define INT32_MAX 0x7fffffff
+#endif
+
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t) -1)
+#endif
 
 /* Inverse normal zigzag */
 const static Int zigzag_i[NCOEFF_BLOCK] =
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/m4v_h263_enc_test.cpp b/media/libstagefright/codecs/m4v_h263/enc/test/m4v_h263_enc_test.cpp
new file mode 100644
index 0000000..db2c61a
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/m4v_h263_enc_test.cpp
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "mp4enc_api.h"
+
+// Constants.
+enum {
+    kMaxWidth         = 720,
+    kMaxHeight        = 480,
+    kMaxFrameRate     = 30,
+    kMaxBitrate       = 2048, // in kbps.
+    kOutputBufferSize = 250 * 1024,
+    kIDRFrameRefreshIntervalInSec = 1, // in seconds.
+};
+
+int main(int argc, char *argv[]) {
+
+    if (argc < 8) {
+        fprintf(stderr, "Usage %s <input yuv> <output file> <mode> <width> "
+                        "<height> <frame rate> <bitrate in kbps>\n", argv[0]);
+        fprintf(stderr, "mode : h263 or mpeg4\n");
+        fprintf(stderr, "Max width %d\n", kMaxWidth);
+        fprintf(stderr, "Max height %d\n", kMaxHeight);
+        fprintf(stderr, "Max framerate %d\n", kMaxFrameRate);
+        fprintf(stderr, "Max bitrate %d kbps\n", kMaxBitrate);
+        return EXIT_FAILURE;
+    }
+
+    // Read mode.
+    bool isH263mode;
+    if (strcmp(argv[3], "mpeg4") == 0) {
+        isH263mode = false;
+    } else if (strcmp(argv[3], "h263") == 0) {
+        isH263mode = true;
+    } else {
+        fprintf(stderr, "Unsupported mode %s\n", argv[3]);
+        return EXIT_FAILURE;
+    }
+
+    // Read height and width.
+    int32_t width;
+    int32_t height;
+    width = atoi(argv[4]);
+    height = atoi(argv[5]);
+    if (width > kMaxWidth || height > kMaxHeight || width <= 0 || height <= 0) {
+        fprintf(stderr, "Unsupported dimensions %dx%d\n", width, height);
+        return EXIT_FAILURE;
+    }
+
+    if (width % 16 != 0 || height % 16 != 0) {
+        fprintf(stderr, "Video frame size %dx%d must be a multiple of 16\n",
+            width, height);
+        return EXIT_FAILURE;
+    }
+
+    // Read frame rate.
+    int32_t frameRate;
+    frameRate = atoi(argv[6]);
+    if (frameRate > kMaxFrameRate || frameRate <= 0) {
+        fprintf(stderr, "Unsupported frame rate %d\n", frameRate);
+        return EXIT_FAILURE;
+    }
+
+    // Read bitrate.
+    int32_t bitrate;
+    bitrate = atoi(argv[7]);
+    if (bitrate > kMaxBitrate || bitrate <= 0) {
+        fprintf(stderr, "Unsupported bitrate %d\n", bitrate);
+        return EXIT_FAILURE;
+    }
+
+    // Allocate input buffer.
+    uint8_t *inputBuf = (uint8_t *)malloc((width * height * 3) / 2);
+    assert(inputBuf != NULL);
+
+    // Allocate output buffer.
+    uint8_t *outputBuf = (uint8_t *)malloc(kOutputBufferSize);
+    assert(outputBuf != NULL);
+
+    // Open the input file.
+    FILE *fpInput = fopen(argv[1], "rb");
+    if (fpInput == NULL) {
+        fprintf(stderr, "Could not open %s\n", argv[1]);
+        free(inputBuf);
+        free(outputBuf);
+        return EXIT_FAILURE;
+    }
+
+    // Open the output file.
+    FILE *fpOutput = fopen(argv[2], "wb");
+    if (fpOutput == NULL) {
+        fprintf(stderr, "Could not open %s\n", argv[2]);
+        free(inputBuf);
+        free(outputBuf);
+        fclose(fpInput);
+        return EXIT_FAILURE;
+    }
+
+    // Initialize the encoder parameters.
+    tagvideoEncOptions encParams;
+    memset(&encParams, 0, sizeof(tagvideoEncOptions));
+    if (!PVGetDefaultEncOption(&encParams, 0)) {
+        fprintf(stderr, "Failed to get default encoding parameters\n");
+        free(inputBuf);
+        free(outputBuf);
+        fclose(fpInput);
+        fclose(fpOutput);
+        return EXIT_FAILURE;
+    }
+
+    if (isH263mode == false) {
+        encParams.encMode = COMBINE_MODE_WITH_ERR_RES;
+    } else {
+        encParams.encMode = H263_MODE;
+    }
+    encParams.encWidth[0] = width;
+    encParams.encHeight[0] = height;
+    encParams.encFrameRate[0] = frameRate;
+    encParams.rcType = VBR_1;
+    encParams.vbvDelay = 5.0f;
+    encParams.profile_level = CORE_PROFILE_LEVEL2;
+    encParams.packetSize = 32;
+    encParams.rvlcEnable = PV_OFF;
+    encParams.numLayers = 1;
+    encParams.timeIncRes = 1000;
+    encParams.tickPerSrc = encParams.timeIncRes / frameRate;
+
+    encParams.bitRate[0] = bitrate * 1024;
+    encParams.iQuant[0] = 15;
+    encParams.pQuant[0] = 12;
+    encParams.quantType[0] = 0;
+    encParams.noFrameSkipped = PV_OFF;
+
+    int32_t  IDRFrameRefreshIntervalInSec = kIDRFrameRefreshIntervalInSec;
+    if (IDRFrameRefreshIntervalInSec == 0) {
+        encParams.intraPeriod = 1;  // All I frames.
+    } else {
+        encParams.intraPeriod = (IDRFrameRefreshIntervalInSec * frameRate);
+    }
+
+    encParams.numIntraMB = 0;
+    encParams.sceneDetect = PV_ON;
+    encParams.searchRange = 16;
+    encParams.mv8x8Enable = PV_OFF;
+    encParams.gobHeaderInterval = 0;
+    encParams.useACPred = PV_ON;
+    encParams.intraDCVlcTh = 0;
+
+    // Initialize the handle.
+    tagvideoEncControls handle;
+    memset(&handle, 0, sizeof(tagvideoEncControls));
+
+    // Initialize the encoder.
+    if (!PVInitVideoEncoder(&handle, &encParams)) {
+        fprintf(stderr, "Failed to initialize the encoder\n");
+        return EXIT_FAILURE;
+    }
+
+    // Generate the header.
+    int32_t headerLength = kOutputBufferSize;
+    if (!PVGetVolHeader(&handle, outputBuf, &headerLength, 0)) {
+        fprintf(stderr, "Failed to get VOL header\n");
+        return EXIT_FAILURE;
+    }
+    fwrite(outputBuf, 1, headerLength, fpOutput);
+
+    // Core loop.
+    int32_t retVal = EXIT_SUCCESS;
+    int32_t frameSize = (width * height * 3) / 2;
+    int32_t numFramesEncoded = 0;
+
+    while (1) {
+        // Read the input frame.
+        int32_t bytesRead;
+        bytesRead = fread(inputBuf, 1, frameSize, fpInput);
+        if (bytesRead != frameSize) {
+            break; // End of file.
+        }
+
+        // Encode the input frame.
+        VideoEncFrameIO vin, vout;
+        memset(&vin, 0, sizeof(vin));
+        memset(&vout, 0, sizeof(vout));
+        vin.height = height; // height is multiple of 16.
+        vin.pitch = width; // width is multiple of 16.
+        vin.timestamp = (numFramesEncoded * 1000) / frameRate;  // in ms.
+        vin.yChan = inputBuf;
+        vin.uChan = vin.yChan + vin.height * vin.pitch;
+        vin.vChan = vin.uChan + ((vin.height * vin.pitch) >> 2);
+
+        uint32_t modTimeMs = 0;
+        int32_t nLayer = 0;
+        MP4HintTrack hintTrack;
+        int32_t dataLength = kOutputBufferSize;
+        if (!PVEncodeVideoFrame(&handle, &vin, &vout,
+                &modTimeMs, outputBuf, &dataLength, &nLayer) ||
+            !PVGetHintTrack(&handle, &hintTrack)) {
+            fprintf(stderr, "Failed to encode frame or get hink track at "
+                    " frame %d\n", numFramesEncoded);
+            retVal = EXIT_FAILURE;
+            break;
+        }
+        PVGetOverrunBuffer(&handle);
+        numFramesEncoded++;
+
+        // Write the output.
+        fwrite(outputBuf, 1, dataLength, fpOutput);
+    }
+
+    // Close input and output file.
+    fclose(fpInput);
+    fclose(fpOutput);
+
+    // Free allocated memory.
+    free(inputBuf);
+    free(outputBuf);
+
+    // Close encoder instance.
+    PVCleanUpVideoEncoder(&handle);
+    return retVal;
+}
diff --git a/media/libstagefright/codecs/mp3dec/Android.mk b/media/libstagefright/codecs/mp3dec/Android.mk
index 948ae29..e611f68 100644
--- a/media/libstagefright/codecs/mp3dec/Android.mk
+++ b/media/libstagefright/codecs/mp3dec/Android.mk
@@ -83,3 +83,25 @@
 LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_SHARED_LIBRARY)
+
+################################################################################
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := \
+        test/mp3dec_test.cpp  \
+        test/mp3reader.cpp
+
+LOCAL_C_INCLUDES := \
+        $(LOCAL_PATH)/src \
+        $(LOCAL_PATH)/include \
+        $(LOCAL_PATH)/test/include \
+        $(call include-path-for, audio-utils)
+
+LOCAL_STATIC_LIBRARIES := \
+        libstagefright_mp3dec libsndfile
+
+LOCAL_SHARED_LIBRARIES := libaudioutils
+
+LOCAL_MODULE := libstagefright_mp3dec_test
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/media/libstagefright/codecs/mp3dec/test/mp3dec_test.cpp b/media/libstagefright/codecs/mp3dec/test/mp3dec_test.cpp
new file mode 100644
index 0000000..26d62f3
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/test/mp3dec_test.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+#include "pvmp3decoder_api.h"
+#include "mp3reader.h"
+#include <audio_utils/sndfile.h>
+
+using namespace std;
+
+enum {
+    kInputBufferSize = 10 * 1024,
+    kOutputBufferSize = 4608 * 2,
+};
+
+int main(int argc, const char **argv) {
+
+    if (argc != 3) {
+        fprintf(stderr, "Usage %s <input file> <output file>\n", argv[0]);
+        return EXIT_FAILURE;
+    }
+
+    // Initialize the config.
+    tPVMP3DecoderExternal config;
+    config.equalizerType = flat;
+    config.crcEnabled = false;
+
+    // Allocate the decoder memory.
+    uint32_t memRequirements = pvmp3_decoderMemRequirements();
+    void *decoderBuf = malloc(memRequirements);
+    assert(decoderBuf != NULL);
+
+    // Initialize the decoder.
+    pvmp3_InitDecoder(&config, decoderBuf);
+
+    // Open the input file.
+    Mp3Reader mp3Reader;
+    bool success = mp3Reader.init(argv[1]);
+    if (!success) {
+        fprintf(stderr, "Encountered error reading %s\n", argv[1]);
+        free(decoderBuf);
+        return EXIT_FAILURE;
+    }
+
+    // Open the output file.
+    SF_INFO sfInfo;
+    memset(&sfInfo, 0, sizeof(SF_INFO));
+    sfInfo.channels = mp3Reader.getNumChannels();
+    sfInfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
+    sfInfo.samplerate = mp3Reader.getSampleRate();
+    SNDFILE *handle = sf_open(argv[2], SFM_WRITE, &sfInfo);
+    if (handle == NULL) {
+        fprintf(stderr, "Encountered error writing %s\n", argv[2]);
+        mp3Reader.close();
+        free(decoderBuf);
+        return EXIT_FAILURE;
+    }
+
+    // Allocate input buffer.
+    uint8_t *inputBuf = static_cast<uint8_t*>(malloc(kInputBufferSize));
+    assert(inputBuf != NULL);
+
+    // Allocate output buffer.
+    int16_t *outputBuf = static_cast<int16_t*>(malloc(kOutputBufferSize));
+    assert(outputBuf != NULL);
+
+    // Decode loop.
+    int retVal = EXIT_SUCCESS;
+    while (1) {
+        // Read input from the file.
+        uint32_t bytesRead;
+        bool success = mp3Reader.getFrame(inputBuf, &bytesRead);
+        if (!success) break;
+
+        // Set the input config.
+        config.inputBufferCurrentLength = bytesRead;
+        config.inputBufferMaxLength = 0;
+        config.inputBufferUsedLength = 0;
+        config.pInputBuffer = inputBuf;
+        config.pOutputBuffer = outputBuf;
+        config.outputFrameSize = kOutputBufferSize / sizeof(int16_t);
+
+        ERROR_CODE decoderErr;
+        decoderErr = pvmp3_framedecoder(&config, decoderBuf);
+        if (decoderErr != NO_DECODING_ERROR) {
+            fprintf(stderr, "Decoder encountered error\n");
+            retVal = EXIT_FAILURE;
+            break;
+        }
+        sf_writef_short(handle, outputBuf,
+                        config.outputFrameSize / sfInfo.channels);
+    }
+
+    // Close input reader and output writer.
+    mp3Reader.close();
+    sf_close(handle);
+
+    // Free allocated memory.
+    free(inputBuf);
+    free(outputBuf);
+    free(decoderBuf);
+
+    return retVal;
+}
diff --git a/media/libstagefright/codecs/mp3dec/test/mp3reader.cpp b/media/libstagefright/codecs/mp3dec/test/mp3reader.cpp
new file mode 100644
index 0000000..b3138ec
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/test/mp3reader.cpp
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <stdint.h>
+#include "mp3reader.h"
+
+static uint32_t U32_AT(const uint8_t *ptr) {
+    return ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3];
+}
+
+static bool parseHeader(
+        uint32_t header, size_t *frame_size,
+        uint32_t *out_sampling_rate = NULL, uint32_t *out_channels = NULL ,
+        uint32_t *out_bitrate = NULL, uint32_t *out_num_samples = NULL) {
+    *frame_size = 0;
+
+    if (out_sampling_rate) {
+        *out_sampling_rate = 0;
+    }
+
+    if (out_channels) {
+        *out_channels = 0;
+    }
+
+    if (out_bitrate) {
+        *out_bitrate = 0;
+    }
+
+    if (out_num_samples) {
+        *out_num_samples = 1152;
+    }
+
+    if ((header & 0xffe00000) != 0xffe00000) {
+        return false;
+    }
+
+    unsigned version = (header >> 19) & 3;
+
+    if (version == 0x01) {
+        return false;
+    }
+
+    unsigned layer = (header >> 17) & 3;
+
+    if (layer == 0x00) {
+        return false;
+    }
+
+    unsigned bitrate_index = (header >> 12) & 0x0f;
+
+    if (bitrate_index == 0 || bitrate_index == 0x0f) {
+        // Disallow "free" bitrate.
+        return false;
+    }
+
+    unsigned sampling_rate_index = (header >> 10) & 3;
+
+    if (sampling_rate_index == 3) {
+        return false;
+    }
+
+    static const int kSamplingRateV1[] = { 44100, 48000, 32000 };
+    int sampling_rate = kSamplingRateV1[sampling_rate_index];
+    if (version == 2 /* V2 */) {
+        sampling_rate /= 2;
+    } else if (version == 0 /* V2.5 */) {
+        sampling_rate /= 4;
+    }
+
+    unsigned padding = (header >> 9) & 1;
+
+    if (layer == 3) {
+        // layer I
+
+        static const int kBitrateV1[] = {
+            32, 64, 96, 128, 160, 192, 224, 256,
+            288, 320, 352, 384, 416, 448
+        };
+
+        static const int kBitrateV2[] = {
+            32, 48, 56, 64, 80, 96, 112, 128,
+            144, 160, 176, 192, 224, 256
+        };
+
+        int bitrate =
+            (version == 3 /* V1 */)
+                ? kBitrateV1[bitrate_index - 1]
+                : kBitrateV2[bitrate_index - 1];
+
+        if (out_bitrate) {
+            *out_bitrate = bitrate;
+        }
+
+        *frame_size = (12000 * bitrate / sampling_rate + padding) * 4;
+
+        if (out_num_samples) {
+            *out_num_samples = 384;
+        }
+    } else {
+        // layer II or III
+
+        static const int kBitrateV1L2[] = {
+            32, 48, 56, 64, 80, 96, 112, 128,
+            160, 192, 224, 256, 320, 384
+        };
+
+        static const int kBitrateV1L3[] = {
+            32, 40, 48, 56, 64, 80, 96, 112,
+            128, 160, 192, 224, 256, 320
+        };
+
+        static const int kBitrateV2[] = {
+            8, 16, 24, 32, 40, 48, 56, 64,
+            80, 96, 112, 128, 144, 160
+        };
+
+        int bitrate;
+        if (version == 3 /* V1 */) {
+            bitrate = (layer == 2 /* L2 */)
+                ? kBitrateV1L2[bitrate_index - 1]
+                : kBitrateV1L3[bitrate_index - 1];
+
+            if (out_num_samples) {
+                *out_num_samples = 1152;
+            }
+        } else {
+            // V2 (or 2.5)
+
+            bitrate = kBitrateV2[bitrate_index - 1];
+            if (out_num_samples) {
+                *out_num_samples = (layer == 1 /* L3 */) ? 576 : 1152;
+            }
+        }
+
+        if (out_bitrate) {
+            *out_bitrate = bitrate;
+        }
+
+        if (version == 3 /* V1 */) {
+            *frame_size = 144000 * bitrate / sampling_rate + padding;
+        } else {
+            // V2 or V2.5
+            size_t tmp = (layer == 1 /* L3 */) ? 72000 : 144000;
+            *frame_size = tmp * bitrate / sampling_rate + padding;
+        }
+    }
+
+    if (out_sampling_rate) {
+        *out_sampling_rate = sampling_rate;
+    }
+
+    if (out_channels) {
+        int channel_mode = (header >> 6) & 3;
+
+        *out_channels = (channel_mode == 3) ? 1 : 2;
+    }
+
+    return true;
+}
+
+// Mask to extract the version, layer, sampling rate parts of the MP3 header,
+// which should be same for all MP3 frames.
+static const uint32_t kMask = 0xfffe0c00;
+
+static ssize_t sourceReadAt(FILE *fp, off64_t offset, void *data, size_t size) {
+    int retVal = fseek(fp, offset, SEEK_SET);
+    if (retVal != EXIT_SUCCESS) {
+        return 0;
+    } else {
+       return fread(data, 1, size, fp);
+    }
+}
+
+// Resync to next valid MP3 frame in the file.
+static bool resync(
+        FILE *fp, uint32_t match_header,
+        off64_t *inout_pos, uint32_t *out_header) {
+
+    if (*inout_pos == 0) {
+        // Skip an optional ID3 header if syncing at the very beginning
+        // of the datasource.
+
+        for (;;) {
+            uint8_t id3header[10];
+            int retVal = sourceReadAt(fp, *inout_pos, id3header,
+                                      sizeof(id3header));
+            if (retVal < (ssize_t)sizeof(id3header)) {
+                // If we can't even read these 10 bytes, we might as well bail
+                // out, even if there _were_ 10 bytes of valid mp3 audio data...
+                return false;
+            }
+
+            if (memcmp("ID3", id3header, 3)) {
+                break;
+            }
+
+            // Skip the ID3v2 header.
+
+            size_t len =
+                ((id3header[6] & 0x7f) << 21)
+                | ((id3header[7] & 0x7f) << 14)
+                | ((id3header[8] & 0x7f) << 7)
+                | (id3header[9] & 0x7f);
+
+            len += 10;
+
+            *inout_pos += len;
+        }
+
+    }
+
+    off64_t pos = *inout_pos;
+    bool valid = false;
+
+    const int32_t kMaxReadBytes = 1024;
+    const int32_t kMaxBytesChecked = 128 * 1024;
+    uint8_t buf[kMaxReadBytes];
+    ssize_t bytesToRead = kMaxReadBytes;
+    ssize_t totalBytesRead = 0;
+    ssize_t remainingBytes = 0;
+    bool reachEOS = false;
+    uint8_t *tmp = buf;
+
+    do {
+        if (pos >= *inout_pos + kMaxBytesChecked) {
+            // Don't scan forever.
+            break;
+        }
+
+        if (remainingBytes < 4) {
+            if (reachEOS) {
+                break;
+            } else {
+                memcpy(buf, tmp, remainingBytes);
+                bytesToRead = kMaxReadBytes - remainingBytes;
+
+                /*
+                 * The next read position should start from the end of
+                 * the last buffer, and thus should include the remaining
+                 * bytes in the buffer.
+                 */
+                totalBytesRead = sourceReadAt(fp, pos + remainingBytes,
+                                             buf + remainingBytes, bytesToRead);
+
+                if (totalBytesRead <= 0) {
+                    break;
+                }
+                reachEOS = (totalBytesRead != bytesToRead);
+                remainingBytes += totalBytesRead;
+                tmp = buf;
+                continue;
+            }
+        }
+
+        uint32_t header = U32_AT(tmp);
+
+        if (match_header != 0 && (header & kMask) != (match_header & kMask)) {
+            ++pos;
+            ++tmp;
+            --remainingBytes;
+            continue;
+        }
+
+        size_t frame_size;
+        uint32_t sample_rate, num_channels, bitrate;
+        if (!parseHeader(
+                    header, &frame_size,
+                    &sample_rate, &num_channels, &bitrate)) {
+            ++pos;
+            ++tmp;
+            --remainingBytes;
+            continue;
+        }
+
+        // We found what looks like a valid frame,
+        // now find its successors.
+
+        off64_t test_pos = pos + frame_size;
+
+        valid = true;
+        const int FRAME_MATCH_REQUIRED = 3;
+        for (int j = 0; j < FRAME_MATCH_REQUIRED; ++j) {
+            uint8_t tmp[4];
+            ssize_t retval = sourceReadAt(fp, test_pos, tmp, sizeof(tmp));
+            if (retval < (ssize_t)sizeof(tmp)) {
+                valid = false;
+                break;
+            }
+
+            uint32_t test_header = U32_AT(tmp);
+
+            if ((test_header & kMask) != (header & kMask)) {
+                valid = false;
+                break;
+            }
+
+            size_t test_frame_size;
+            if (!parseHeader(test_header, &test_frame_size)) {
+                valid = false;
+                break;
+            }
+
+            test_pos += test_frame_size;
+        }
+
+        if (valid) {
+            *inout_pos = pos;
+
+            if (out_header != NULL) {
+                *out_header = header;
+            }
+        }
+
+        ++pos;
+        ++tmp;
+        --remainingBytes;
+    } while (!valid);
+
+    return valid;
+}
+
+Mp3Reader::Mp3Reader() : mFp(NULL) {
+}
+
+// Initialize the MP3 reader.
+bool Mp3Reader::init(const char *file) {
+
+    // Open the file.
+    mFp = fopen(file, "rb");
+    if (mFp == NULL) return false;
+
+    // Sync to the first valid frame.
+    off64_t pos = 0;
+    uint32_t header;
+    bool success = resync(mFp, 0 /*match_header*/, &pos, &header);
+    if (success == false) return false;
+
+    mCurrentPos  = pos;
+    mFixedHeader = header;
+
+    size_t frame_size;
+    return parseHeader(header, &frame_size, &mSampleRate,
+                       &mNumChannels, &mBitrate);
+}
+
+// Get the next valid MP3 frame.
+bool Mp3Reader::getFrame(void *buffer, uint32_t *size) {
+
+    size_t frame_size;
+    uint32_t bitrate;
+    uint32_t num_samples;
+    uint32_t sample_rate;
+    for (;;) {
+        ssize_t n = sourceReadAt(mFp, mCurrentPos, buffer, 4);
+        if (n < 4) {
+            return false;
+        }
+
+        uint32_t header = U32_AT((const uint8_t *)buffer);
+
+        if ((header & kMask) == (mFixedHeader & kMask)
+            && parseHeader(
+                header, &frame_size, &sample_rate, NULL /*out_channels*/,
+                &bitrate, &num_samples)) {
+            break;
+        }
+
+        // Lost sync.
+        off64_t pos = mCurrentPos;
+        if (!resync(mFp, mFixedHeader, &pos, NULL /*out_header*/)) {
+            // Unable to resync. Signalling end of stream.
+            return false;
+        }
+
+        mCurrentPos = pos;
+
+        // Try again with the new position.
+    }
+    ssize_t n = sourceReadAt(mFp, mCurrentPos, buffer, frame_size);
+    if (n < (ssize_t)frame_size) {
+        return false;
+    }
+
+    *size = frame_size;
+    mCurrentPos += frame_size;
+    return true;
+}
+
+// Close the MP3 reader.
+void Mp3Reader::close() {
+    assert(mFp != NULL);
+    fclose(mFp);
+}
+
+Mp3Reader::~Mp3Reader() {
+}
diff --git a/media/libstagefright/codecs/mp3dec/test/mp3reader.h b/media/libstagefright/codecs/mp3dec/test/mp3reader.h
new file mode 100644
index 0000000..871f664
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/test/mp3reader.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef MP3READER_H_
+#define MP3READER_H_
+
+class Mp3Reader {
+public:
+    Mp3Reader();
+    bool init(const char *file);
+    bool getFrame(void *buffer, uint32_t *size);
+    uint32_t getSampleRate() { return mSampleRate;}
+    uint32_t getNumChannels() { return mNumChannels;}
+    void close();
+    ~Mp3Reader();
+private:
+    FILE    *mFp;
+    uint32_t mFixedHeader;
+    off64_t  mCurrentPos;
+    uint32_t mSampleRate;
+    uint32_t mNumChannels;
+    uint32_t mBitrate;
+};
+
+
+#endif /* MP3READER_H_ */
diff --git a/media/libstagefright/codecs/on2/h264dec/Android.mk b/media/libstagefright/codecs/on2/h264dec/Android.mk
index e63b6b1..bf03ad9 100644
--- a/media/libstagefright/codecs/on2/h264dec/Android.mk
+++ b/media/libstagefright/codecs/on2/h264dec/Android.mk
@@ -94,8 +94,6 @@
     LOCAL_C_INCLUDES += $(LOCAL_PATH)/./omxdl/arm_neon/api \
                         $(LOCAL_PATH)/./omxdl/arm_neon/vc/api \
                         $(LOCAL_PATH)/./omxdl/arm_neon/vc/m4p10/api
-    # h264bsdWriteMacroblock.S does not compile with Clang.
-    LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
   endif
 endif
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM.h
index 91e38b8..1992885 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM.h
@@ -86,7 +86,7 @@
 
 /* Alignment operation */
 
-#define armAlignToBytes(Ptr,N)      (Ptr + ( ((N-(int)Ptr)&(N-1)) / sizeof(*Ptr) ))
+#define armAlignToBytes(Ptr,N)      (Ptr + ( ((N-(intptr_t)Ptr)&(N-1)) / sizeof(*Ptr) ))
 #define armAlignTo2Bytes(Ptr)       armAlignToBytes(Ptr,2)
 #define armAlignTo4Bytes(Ptr)       armAlignToBytes(Ptr,4)
 #define armAlignTo8Bytes(Ptr)       armAlignToBytes(Ptr,8)
@@ -98,8 +98,8 @@
 #define armRetDataErrIf(condition, code) if(condition) { return (code); }
 
 #ifndef ALIGNMENT_DOESNT_MATTER
-#define armIsByteAligned(Ptr,N)     ((((int)(Ptr)) % N)==0)
-#define armNotByteAligned(Ptr,N)    ((((int)(Ptr)) % N)!=0)
+#define armIsByteAligned(Ptr,N)     ((((intptr_t)(Ptr)) % N)==0)
+#define armNotByteAligned(Ptr,N)    ((((intptr_t)(Ptr)) % N)!=0)
 #else
 #define armIsByteAligned(Ptr,N)     (1)
 #define armNotByteAligned(Ptr,N)    (0)
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Average_4x_Align_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Average_4x_Align_unsafe_s.S
index 46e0018..e1ffb09 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Average_4x_Align_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Average_4x_Align_unsafe_s.S
@@ -26,7 +26,6 @@
     .text
 
     .global armVCM4P10_Average_4x4_Align0_unsafe
-    .func   armVCM4P10_Average_4x4_Align0_unsafe
 armVCM4P10_Average_4x4_Align0_unsafe:
     PUSH     {r4-r6,lr}
     LDR      r7, =0x80808080
@@ -55,10 +54,8 @@
     EOR      r4,r4,r7
     STR      r4,[r2],r3
     POP      {r4-r6,pc}
-    .endfunc
 
     .global armVCM4P10_Average_4x4_Align2_unsafe
-    .func   armVCM4P10_Average_4x4_Align2_unsafe
 armVCM4P10_Average_4x4_Align2_unsafe:
     PUSH     {r4-r6,lr}
     LDR      r7, =0x80808080
@@ -99,10 +96,8 @@
     EOR      r4,r4,r7
     STR      r4,[r2],r3
     POP      {r4-r6,pc}
-    .endfunc
 
     .global armVCM4P10_Average_4x4_Align3_unsafe
-    .func   armVCM4P10_Average_4x4_Align3_unsafe
 armVCM4P10_Average_4x4_Align3_unsafe:
     PUSH     {r4-r6,lr}
     LDR      r7, =0x80808080
@@ -143,7 +138,6 @@
     EOR      r4,r4,r7
     STR      r4,[r2],r3
     POP      {r4-r6,pc}
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingChroma_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingChroma_unsafe_s.S
index ca64a02..40ea4a9 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingChroma_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingChroma_unsafe_s.S
@@ -26,7 +26,6 @@
     .text
 
     .global armVCM4P10_DeblockingChromabSLT4_unsafe
-    .func   armVCM4P10_DeblockingChromabSLT4_unsafe
 armVCM4P10_DeblockingChromabSLT4_unsafe:
     VLD1.32  {d18[0]},[r5]!
     VSUBL.U8 q11,d5,d9
@@ -50,10 +49,8 @@
     VQMOVUN.S16 d29,q14
     VQMOVUN.S16 d24,q12
     BX       lr
-    .endfunc
 
     .global armVCM4P10_DeblockingChromabSGE4_unsafe
-    .func   armVCM4P10_DeblockingChromabSGE4_unsafe
 armVCM4P10_DeblockingChromabSGE4_unsafe:
     VHADD.U8 d13,d4,d9
     VHADD.U8 d31,d8,d5
@@ -63,7 +60,6 @@
     VRHADD.U8 d13,d13,d5
     VRHADD.U8 d31,d31,d9
     BX       lr
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingLuma_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingLuma_unsafe_s.S
index 193bc5e..05fb2c5 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingLuma_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingLuma_unsafe_s.S
@@ -26,7 +26,6 @@
     .text
 
     .global armVCM4P10_DeblockingLumabSLT4_unsafe
-    .func   armVCM4P10_DeblockingLumabSLT4_unsafe
 armVCM4P10_DeblockingLumabSLT4_unsafe:
     VSUBL.U8 q11,d5,d9
     VLD1.8   {d18[]},[r5]!
@@ -66,10 +65,8 @@
     VBIF     d24,d8,d16
     VBIF     d25,d9,d12
     BX       lr
-    .endfunc
 
     .global armVCM4P10_DeblockingLumabSGE4_unsafe
-    .func   armVCM4P10_DeblockingLumabSGE4_unsafe
 armVCM4P10_DeblockingLumabSGE4_unsafe:
     VSHR.U8  d19,d0,#2
     VADD.I8  d19,d19,d15
@@ -111,7 +108,6 @@
     VBIF     d24,d8,d16
     VBIF     d28,d10,d12
     BX       lr
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S
index 8e0db37..27c0452 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S
@@ -42,7 +42,6 @@
     .hidden   armVCM4P10_ZigZag_4x4
 
     .global armVCM4P10_DecodeCoeffsToPair
-    .func   armVCM4P10_DecodeCoeffsToPair
 armVCM4P10_DecodeCoeffsToPair:
     PUSH     {r4-r12,lr}
     SUB      sp,sp,#0x40
@@ -302,7 +301,6 @@
 L0x35c:
     ADD      sp,sp,#0x40
     POP      {r4-r12,pc}
-    .endfunc
 
 .LarmVCM4P10_CAVLCCoeffTokenTables:
     .word   armVCM4P10_CAVLCCoeffTokenTables-(P0+8)
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Align_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Align_unsafe_s.S
index 7206d76..1de9004 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Align_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Align_unsafe_s.S
@@ -26,7 +26,6 @@
     .text
 
     .global armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
-    .func   armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
 armVCM4P10_InterpolateLuma_HorAlign9x_unsafe:
     MOV      r12,r8
     AND      r7,r0,#3
@@ -83,10 +82,8 @@
     MOV      r0,r12
     MOV      r1,#0xc
     BX       lr
-    .endfunc
 
     .global armVCM4P10_InterpolateLuma_VerAlign4x_unsafe
-    .func   armVCM4P10_InterpolateLuma_VerAlign4x_unsafe
 armVCM4P10_InterpolateLuma_VerAlign4x_unsafe:
     AND      r7,r0,#3
     BIC      r0,r0,#3
@@ -132,7 +129,6 @@
     SUB      r0,r8,#0x1c
     MOV      r1,#4
     BX       lr
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Copy_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Copy_unsafe_s.S
index e41d662..7ba2890 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Copy_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Copy_unsafe_s.S
@@ -26,7 +26,6 @@
     .text
 
     .global armVCM4P10_InterpolateLuma_Copy4x4_unsafe
-    .func   armVCM4P10_InterpolateLuma_Copy4x4_unsafe
 armVCM4P10_InterpolateLuma_Copy4x4_unsafe:
     PUSH     {r4-r6,lr}
     AND      r12,r0,#3
@@ -114,7 +113,6 @@
     STR      r8,[r2],r3
 Copy4x4End:
     POP      {r4-r6,pc}
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.S
index c8f5cda..8b2c678 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.S
@@ -26,7 +26,6 @@
     .text
 
     .global armVCM4P10_InterpolateLuma_HorDiagCopy_unsafe
-    .func   armVCM4P10_InterpolateLuma_HorDiagCopy_unsafe
 armVCM4P10_InterpolateLuma_HorDiagCopy_unsafe:
     PUSH     {r4-r6,lr}
     MOV      lr,#4
@@ -57,10 +56,8 @@
     SUB      r0,r7,#0x20
     MOV      r1,#8
     POP      {r4-r6,pc}
-    .endfunc
 
     .global armVCM4P10_InterpolateLuma_VerDiagCopy_unsafe
-    .func   armVCM4P10_InterpolateLuma_VerDiagCopy_unsafe
 armVCM4P10_InterpolateLuma_VerDiagCopy_unsafe:
     PUSH     {r4-r6,lr}
     LDR      r6, =0xfe00fe0
@@ -116,7 +113,6 @@
     SUB      r0,r7,#0x18
     MOV      r1,#4
     POP      {r4-r6,pc}
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.S
index f5868c0..77aa927 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.S
@@ -26,7 +26,6 @@
     .text
 
     .global armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe
-    .func   armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe
 armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe:
     PUSH     {r4-r12,lr}
     VLD1.8   {d0,d1},[r0],r1
@@ -173,7 +172,6 @@
     VQMOVN.U16 d4,q2
     VQMOVN.U16 d6,q3
     POP      {r4-r12,pc}
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.S
index 065995d..e5f7f1c 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.S
@@ -26,7 +26,6 @@
     .text
 
     .global armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe
-    .func   armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe
 armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe:
     PUSH     {r4-r12,lr}
     VLD1.8   {d0,d1},[r0],r1
@@ -128,7 +127,6 @@
     VQMOVN.U16 d4,q2
     VQMOVN.U16 d6,q3
     POP      {r4-r12,pc}
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.S
index 1e2d16b..393d385 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.S
@@ -26,7 +26,6 @@
     .text
 
     .global armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
-    .func   armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
 armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe:
     PUSH     {r4-r12,lr}
     VLD1.8   {d22,d23},[r0],r1
@@ -81,7 +80,6 @@
     VQRSHRUN.S16 d26,q13,#5
     VQRSHRUN.S16 d28,q14,#5
     POP      {r4-r12,pc}
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.S
index c7def2a..698e7b5 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.S
@@ -26,7 +26,6 @@
     .text
 
     .global armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
-    .func   armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
 armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe:
     PUSH     {r4-r12,lr}
     VLD1.8   {d7},[r0],r1
@@ -67,7 +66,6 @@
     VQRSHRUN.S16 d4,q2,#5
     VQRSHRUN.S16 d6,q3,#5
     POP      {r4-r12,pc}
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Interpolate_Chroma_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Interpolate_Chroma_s.S
index 2f4293f..e469516 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Interpolate_Chroma_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Interpolate_Chroma_s.S
@@ -38,7 +38,6 @@
     .word   WidthIs8MVIsZero-(P0+8)
 
     .global armVCM4P10_Interpolate_Chroma
-    .func   armVCM4P10_Interpolate_Chroma
 armVCM4P10_Interpolate_Chroma:
     PUSH     {r4-r12,lr}
     VPUSH    {d8-d15}
@@ -183,7 +182,6 @@
     MOV      r0,#0
     VPOP     {d8-d15}
     POP      {r4-r12,pc}
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_TransformResidual4x4_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_TransformResidual4x4_s.S
index d4cedb5..e18bec7 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_TransformResidual4x4_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_TransformResidual4x4_s.S
@@ -26,7 +26,6 @@
     .text
 
     .global armVCM4P10_TransformResidual4x4
-    .func   armVCM4P10_TransformResidual4x4
 armVCM4P10_TransformResidual4x4:
     VPUSH    {d8}
     VLD4.16  {d0,d1,d2,d3},[r1]
@@ -61,7 +60,6 @@
     VST1.16  {d0,d1,d2,d3},[r0]
     VPOP     {d8}
     BX       lr
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_UnpackBlock4x4_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_UnpackBlock4x4_s.S
index 1652dc6..b97efcb 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_UnpackBlock4x4_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_UnpackBlock4x4_s.S
@@ -24,9 +24,9 @@
     .arm
     .fpu neon
     .text
+    .syntax unified
 
     .global armVCM4P10_UnpackBlock4x4
-    .func   armVCM4P10_UnpackBlock4x4
 armVCM4P10_UnpackBlock4x4:
     PUSH     {r4-r8,lr}
     LDR      r2,[r0,#0]
@@ -40,16 +40,15 @@
     STRD     r4,r5,[r1,#0x18]
 unpackLoop:
     TST      r3,#0x10
-    LDRNESB  r5,[r2,#1]
-    LDRNEB   r4,[r2],#2
+    LDRSBNE  r5,[r2,#1]
+    LDRBNE   r4,[r2],#2
     AND      r6,r7,r3,LSL #1
-    LDREQSB  r4,[r2],#1
+    LDRSBEQ  r4,[r2],#1
     ORRNE    r4,r4,r5,LSL #8
     TST      r3,#0x20
-    LDREQB   r3,[r2],#1
+    LDRBEQ   r3,[r2],#1
     STRH     r4,[r1,r6]
     BEQ      unpackLoop
     STR      r2,[r0,#0]
     POP      {r4-r8,pc}
-    .endfunc
     .end
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DeblockLuma_I.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DeblockLuma_I.S
index 90b0947..6a99bde 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DeblockLuma_I.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DeblockLuma_I.S
@@ -26,7 +26,6 @@
     .text
 
     .global omxVCM4P10_DeblockLuma_I
-    .func   omxVCM4P10_DeblockLuma_I
 omxVCM4P10_DeblockLuma_I:
     PUSH     {r4-r9,lr}
     MOVS     r6,r0
@@ -76,7 +75,6 @@
     BL       omxVCM4P10_FilterDeblockingLuma_HorEdge_I
     ADD      sp,sp,#0xc
     POP      {r4-r9,pc}
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.S
index 4a74594..17c5d8b 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.S
@@ -26,7 +26,6 @@
     .text
 
     .global omxVCM4P10_DequantTransformResidualFromPairAndAdd
-    .func   omxVCM4P10_DequantTransformResidualFromPairAndAdd
 omxVCM4P10_DequantTransformResidualFromPairAndAdd:
     PUSH     {r4-r12,lr}
     VPUSH    {d8-d9}
@@ -131,7 +130,6 @@
     ADD      sp,sp,#0x20
     VPOP     {d8-d9}
     POP      {r4-r12,pc}
-    .endfunc
 
 .LarmVCM4P10_QPModuloTable:
     .word   armVCM4P10_QPModuloTable-(P0+8)
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.S
index f20fb78..4a83516 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.S
@@ -26,7 +26,6 @@
     .text
 
     .global omxVCM4P10_FilterDeblockingChroma_HorEdge_I
-    .func   omxVCM4P10_FilterDeblockingChroma_HorEdge_I
 omxVCM4P10_FilterDeblockingChroma_HorEdge_I:
     PUSH     {r4-r10,lr}
     VPUSH    {d8-d15}
@@ -96,7 +95,6 @@
     MOV      r0,#0
     VPOP     {d8-d15}
     POP      {r4-r10,pc}
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.S
index 003526e..fe10931 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.S
@@ -26,7 +26,6 @@
     .text
 
     .global omxVCM4P10_FilterDeblockingChroma_VerEdge_I
-    .func   omxVCM4P10_FilterDeblockingChroma_VerEdge_I
 omxVCM4P10_FilterDeblockingChroma_VerEdge_I:
     PUSH     {r4-r12,lr}
     VPUSH    {d8-d15}
@@ -132,7 +131,6 @@
     MOV      r0,#0
     VPOP     {d8-d15}
     POP      {r4-r12,pc}
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.S
index 7ddc42e..84ffad2 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.S
@@ -26,7 +26,6 @@
     .text
 
     .global omxVCM4P10_FilterDeblockingLuma_HorEdge_I
-    .func   omxVCM4P10_FilterDeblockingLuma_HorEdge_I
 omxVCM4P10_FilterDeblockingLuma_HorEdge_I:
     PUSH     {r4-r12,lr}
     VPUSH    {d8-d15}
@@ -116,7 +115,6 @@
     MOV      r0,#0
     VPOP     {d8-d15}
     POP      {r4-r12,pc}
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.S
index f71aceb..f2a3682 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.S
@@ -26,7 +26,6 @@
     .text
 
     .global omxVCM4P10_FilterDeblockingLuma_VerEdge_I
-    .func   omxVCM4P10_FilterDeblockingLuma_VerEdge_I
 omxVCM4P10_FilterDeblockingLuma_VerEdge_I:
     PUSH     {r4-r12,lr}
     VPUSH    {d8-d15}
@@ -166,7 +165,6 @@
     MOV      r0,#0
     VPOP     {d8-d15}
     POP      {r4-r12,pc}
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_InterpolateLuma_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_InterpolateLuma_s.S
index 000fbeb..314eabd 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_InterpolateLuma_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_InterpolateLuma_s.S
@@ -26,7 +26,6 @@
     .text
 
     .global omxVCM4P10_InterpolateLuma
-    .func   omxVCM4P10_InterpolateLuma
 omxVCM4P10_InterpolateLuma:
     PUSH     {r4-r12,lr}
     VPUSH    {d8-d15}
@@ -332,7 +331,6 @@
     ADD      sp,sp,#0x10
     VPOP     {d8-d15}
     POP      {r4-r12,pc}
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntraChroma_8x8_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntraChroma_8x8_s.S
index 4e2cff6..50d1350 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntraChroma_8x8_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntraChroma_8x8_s.S
@@ -36,7 +36,6 @@
     .hword   1, 2, 3,4
 
     .global omxVCM4P10_PredictIntraChroma_8x8
-    .func   omxVCM4P10_PredictIntraChroma_8x8
 omxVCM4P10_PredictIntraChroma_8x8:
     PUSH     {r4-r10,lr}
     VPUSH    {d8-d15}
@@ -226,7 +225,6 @@
     MOV      r0,#0
     VPOP     {d8-d15}
     POP      {r4-r10,pc}
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_16x16_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_16x16_s.S
index c71c93b..0044636 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_16x16_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_16x16_s.S
@@ -42,7 +42,6 @@
 
 
     .global omxVCM4P10_PredictIntra_16x16
-    .func   omxVCM4P10_PredictIntra_16x16
 omxVCM4P10_PredictIntra_16x16:
     PUSH     {r4-r12,lr}
     VPUSH    {d8-d15}
@@ -246,7 +245,6 @@
     MOV      r0,#0
     VPOP     {d8-d15}
     POP      {r4-r12,pc}
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_4x4_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_4x4_s.S
index cd5d356..d4c8485 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_4x4_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_4x4_s.S
@@ -35,7 +35,6 @@
     .word OMX_VC_4x4_HU-(P0+8)
 
     .global omxVCM4P10_PredictIntra_4x4
-    .func   omxVCM4P10_PredictIntra_4x4
 omxVCM4P10_PredictIntra_4x4:
     PUSH     {r4-r12,lr}
     VPUSH    {d8-d12}
@@ -270,6 +269,5 @@
     MOV      r0,#0
     VPOP     {d8-d12}
     POP      {r4-r12,pc}
-    .endfunc
 
     .end
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantChromaDCFromPair_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantChromaDCFromPair_s.S
index 5570892..74f5103 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantChromaDCFromPair_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantChromaDCFromPair_s.S
@@ -24,9 +24,9 @@
     .arm
     .fpu neon
     .text
+    .syntax unified
 
     .global omxVCM4P10_TransformDequantChromaDCFromPair
-    .func   omxVCM4P10_TransformDequantChromaDCFromPair
 omxVCM4P10_TransformDequantChromaDCFromPair:
     push    {r4-r10, lr}
     ldr     r9, [r0,#0]
@@ -36,13 +36,13 @@
     ldrb    r6, [r9], #1
 unpackLoop:
     tst     r6, #0x10
-    ldrnesb r5, [r9, #1]
-    ldrneb  r4, [r9], #2
+    ldrsbne r5, [r9, #1]
+    ldrbne  r4, [r9], #2
     and     r7, r8, r6, lsl #1
-    ldreqsb r4, [r9], #1
+    ldrsbeq r4, [r9], #1
     orrne   r4, r4, r5, lsl #8
     tst     r6, #0x20
-    ldreqb  r6, [r9], #1
+    ldrbeq  r6, [r9], #1
     strh    r4, [r1, r7]
     beq     unpackLoop
     ldmia   r1, {r3, r4}
@@ -66,7 +66,6 @@
     vst1.16    {d2}, [r1]
     mov     r0, #0
     pop     {r4-r10, pc}
-    .endfunc
 
 .LarmVCM4P10_QPDivTable:
     .word armVCM4P10_QPDivTable-(P0+8)
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantLumaDCFromPair_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantLumaDCFromPair_s.S
index 5b6eee0..a01030a 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantLumaDCFromPair_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantLumaDCFromPair_s.S
@@ -26,7 +26,6 @@
     .text
 
     .global armVCM4P10_InvTransformDequantLumaDC4x4
-    .func   armVCM4P10_InvTransformDequantLumaDC4x4
 armVCM4P10_InvTransformDequantLumaDC4x4:
     PUSH     {r4-r6,lr}
     VPUSH    {d8-d13}
@@ -73,7 +72,6 @@
     VST1.16  {d0,d1,d2,d3},[r0]
     VPOP     {d8-d13}
     POP      {r4-r6,pc}
-    .endfunc
 
 .LarmVCM4P10_QPDivTable:
     .word armVCM4P10_QPDivTable-(P0+8)
@@ -81,7 +79,6 @@
     .word armVCM4P10_VMatrixQPModTable-(P1+8)
 
 .global omxVCM4P10_TransformDequantLumaDCFromPair
-.func   omxVCM4P10_TransformDequantLumaDCFromPair
 omxVCM4P10_TransformDequantLumaDCFromPair:
     PUSH     {r4-r6,lr}
     MOV      r4,r1
@@ -92,7 +89,6 @@
     BL       armVCM4P10_InvTransformDequantLumaDC4x4
     MOV      r0,#0
     POP      {r4-r6,pc}
-    .endfunc
 
     .end
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM.h
index fbb97e2..7304863 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM.h
@@ -86,7 +86,7 @@
 
 /* Alignment operation */
 
-#define armAlignToBytes(Ptr,N)      (Ptr + ( ((N-(int)Ptr)&(N-1)) / sizeof(*Ptr) ))
+#define armAlignToBytes(Ptr,N)      (Ptr + ( ((N-(intptr_t)Ptr)&(N-1)) / sizeof(*Ptr) ))
 #define armAlignTo2Bytes(Ptr)       armAlignToBytes(Ptr,2)
 #define armAlignTo4Bytes(Ptr)       armAlignToBytes(Ptr,4)
 #define armAlignTo8Bytes(Ptr)       armAlignToBytes(Ptr,8)
@@ -98,8 +98,8 @@
 #define armRetDataErrIf(condition, code) if(condition) { return (code); }
 
 #ifndef ALIGNMENT_DOESNT_MATTER
-#define armIsByteAligned(Ptr,N)     ((((int)(Ptr)) % N)==0)
-#define armNotByteAligned(Ptr,N)    ((((int)(Ptr)) % N)!=0)
+#define armIsByteAligned(Ptr,N)     ((((intptr_t)(Ptr)) % N)==0)
+#define armNotByteAligned(Ptr,N)    ((((intptr_t)(Ptr)) % N)!=0)
 #else
 #define armIsByteAligned(Ptr,N)     (1)
 #define armNotByteAligned(Ptr,N)    (0)
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/asm_common.S b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/asm_common.S
index f39f5c4..969a75c 100644
--- a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/asm_common.S
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/asm_common.S
@@ -31,11 +31,9 @@
     .global \name
 .endif
     .type   \name, %function
-    .func   \name
 \name:
     .endm
 
     .macro endfunction
-    .endfunc
     .endm
 
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdClearMbLayer.S b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdClearMbLayer.S
index c8a940e..3c2752f 100644
--- a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdClearMbLayer.S
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdClearMbLayer.S
@@ -16,7 +16,7 @@
 
 #include "asm_common.S"
 
-    preserve8
+    PRESERVE8
 
     .fpu neon
     .text
@@ -29,7 +29,7 @@
 
 /* -- NEON registers -- */
 
-#define qZero   Q0.U8
+#define qZero   Q0
 
 /*------------------------------------------------------------------------------
 
@@ -47,17 +47,17 @@
 
 function h264bsdClearMbLayer, export=1
 
-    VMOV    qZero, #0
+    VMOV.I8 qZero, #0
     ADD     pTmp, pMbLayer, #16
     MOV     step, #32
     SUBS    size, size, #64
 
 loop:
-    VST1    {qZero}, [pMbLayer], step
+    VST1.8  {qZero}, [pMbLayer], step
     SUBS    size, size, #64
-    VST1    {qZero}, [pTmp], step
-    VST1    {qZero}, [pMbLayer], step
-    VST1    {qZero}, [pTmp], step
+    VST1.8  {qZero}, [pTmp], step
+    VST1.8  {qZero}, [pMbLayer], step
+    VST1.8  {qZero}, [pTmp], step
     BCS     loop
 
     BX      lr
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdCountLeadingZeros.S b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdCountLeadingZeros.S
index 05253d0..b1c9f60 100644
--- a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdCountLeadingZeros.S
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdCountLeadingZeros.S
@@ -15,7 +15,7 @@
 @
 #include "asm_common.S"
 
-    preserve8
+    PRESERVE8
     .arm
     .text
 
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFillRow7.S b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFillRow7.S
index 6955b9a..6ed6227 100644
--- a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFillRow7.S
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFillRow7.S
@@ -16,7 +16,7 @@
 
 #include "asm_common.S"
 
-    preserve8
+    PRESERVE8
 
     .fpu neon
     .text
@@ -33,12 +33,12 @@
 
 /* -- NEON registers -- */
 
-#define qTmp0     Q0.U8
-#define qTmp1     Q1.U8
-#define dTmp0     D0.U8
-#define dTmp1     D1.U8
-#define dTmp2     D2.U8
-#define dTmp3     D3.U8
+#define qTmp0     Q0
+#define qTmp1     Q1
+#define dTmp0     D0
+#define dTmp1     D1
+#define dTmp2     D2
+#define dTmp3     D3
 
 /*
 void h264bsdFillRow7(const u8 * ref, u8 * fill, i32 left, i32 center,
@@ -74,40 +74,40 @@
         B        case_8
 
 case_8:
-        VLD1    {qTmp0, qTmp1}, [ref]!
+        VLD1.8  {qTmp0, qTmp1}, [ref]!
         SUB     center, center, #32
-        VST1    {qTmp0}, [fill]!
-        VST1    {qTmp1}, [fill]!
+        VST1.8  {qTmp0}, [fill]!
+        VST1.8  {qTmp1}, [fill]!
         B       loop_center
 case_7:
-        VLD1    {dTmp0,dTmp1,dTmp2}, [ref]!
+        VLD1.8  {dTmp0,dTmp1,dTmp2}, [ref]!
         SUB     center, center, #28
         LDR     tmp2, [ref], #4
-        VST1    {dTmp0,dTmp1,dTmp2}, [fill]!
+        VST1.8  {dTmp0,dTmp1,dTmp2}, [fill]!
         STR     tmp2, [fill],#4
         B       loop_center
 case_6:
-        VLD1    {dTmp0,dTmp1,dTmp2}, [ref]!
+        VLD1.8  {dTmp0,dTmp1,dTmp2}, [ref]!
         SUB     center, center, #24
-        VST1    {dTmp0,dTmp1,dTmp2}, [fill]!
+        VST1.8  {dTmp0,dTmp1,dTmp2}, [fill]!
         B       loop_center
 case_5:
-        VLD1    {qTmp0}, [ref]!
+        VLD1.8  {qTmp0}, [ref]!
         SUB     center, center, #20
         LDR     tmp2, [ref], #4
-        VST1    {qTmp0}, [fill]!
+        VST1.8  {qTmp0}, [fill]!
         STR     tmp2, [fill],#4
         B       loop_center
 case_4:
-        VLD1    {qTmp0}, [ref]!
+        VLD1.8  {qTmp0}, [ref]!
         SUB     center, center, #16
-        VST1    {qTmp0}, [fill]!
+        VST1.8  {qTmp0}, [fill]!
         B       loop_center
 case_3:
-        VLD1    {dTmp0}, [ref]!
+        VLD1.8  {dTmp0}, [ref]!
         SUB     center, center, #12
         LDR     tmp2, [ref], #4
-        VST1    dTmp0, [fill]!
+        VST1.8  dTmp0, [fill]!
         STR     tmp2, [fill],#4
         B       loop_center
 case_2:
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFlushBits.S b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFlushBits.S
index b3f3191..aa88471 100644
--- a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFlushBits.S
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFlushBits.S
@@ -16,7 +16,7 @@
 
 #include "asm_common.S"
 
-    preserve8
+    PRESERVE8
 
     .arm
     .text
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdWriteMacroblock.S b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdWriteMacroblock.S
index 495d560..4093b92 100644
--- a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdWriteMacroblock.S
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdWriteMacroblock.S
@@ -16,8 +16,8 @@
 
 #include "asm_common.S"
 
-    require8
-    preserve8
+    REQUIRE8
+    PRESERVE8
 
     .arm
     .fpu neon
@@ -34,39 +34,39 @@
 
 /* -- NEON registers -- */
 
-#define qRow0     Q0.U8
-#define qRow1     Q1.U8
-#define qRow2     Q2.U8
-#define qRow3     Q3.U8
-#define qRow4     Q4.U8
-#define qRow5     Q5.U8
-#define qRow6     Q6.U8
-#define qRow7     Q7.U8
-#define qRow8     Q8.U8
-#define qRow9     Q9.U8
-#define qRow10    Q10.U8
-#define qRow11    Q11.U8
-#define qRow12    Q12.U8
-#define qRow13    Q13.U8
-#define qRow14    Q14.U8
-#define qRow15    Q15.U8
+#define qRow0     Q0
+#define qRow1     Q1
+#define qRow2     Q2
+#define qRow3     Q3
+#define qRow4     Q4
+#define qRow5     Q5
+#define qRow6     Q6
+#define qRow7     Q7
+#define qRow8     Q8
+#define qRow9     Q9
+#define qRow10    Q10
+#define qRow11    Q11
+#define qRow12    Q12
+#define qRow13    Q13
+#define qRow14    Q14
+#define qRow15    Q15
 
-#define dRow0     D0.U8
-#define dRow1     D1.U8
-#define dRow2     D2.U8
-#define dRow3     D3.U8
-#define dRow4     D4.U8
-#define dRow5     D5.U8
-#define dRow6     D6.U8
-#define dRow7     D7.U8
-#define dRow8     D8.U8
-#define dRow9     D9.U8
-#define dRow10    D10.U8
-#define dRow11    D11.U8
-#define dRow12    D12.U8
-#define dRow13    D13.U8
-#define dRow14    D14.U8
-#define dRow15    D15.U8
+#define dRow0     D0
+#define dRow1     D1
+#define dRow2     D2
+#define dRow3     D3
+#define dRow4     D4
+#define dRow5     D5
+#define dRow6     D6
+#define dRow7     D7
+#define dRow8     D8
+#define dRow9     D9
+#define dRow10    D10
+#define dRow11    D11
+#define dRow12    D12
+#define dRow13    D13
+#define dRow14    D14
+#define dRow15    D15
 
 /*------------------------------------------------------------------------------
 
@@ -99,59 +99,58 @@
 
 
 @   Write luma
-    VLD1    {qRow0, qRow1}, [data]!
+    VLD1.8  {qRow0, qRow1}, [data]!
     LSL     width, width, #4
-    VLD1    {qRow2, qRow3}, [data]!
+    VLD1.8  {qRow2, qRow3}, [data]!
     LSR     cwidth, width, #1
-    VST1    {qRow0}, [luma,:128], width
-    VLD1    {qRow4, qRow5}, [data]!
-    VST1    {qRow1}, [luma,:128], width
-    VLD1    {qRow6, qRow7}, [data]!
-    VST1    {qRow2}, [luma,:128], width
-    VLD1    {qRow8, qRow9}, [data]!
-    VST1    {qRow3}, [luma,:128], width
-    VLD1    {qRow10, qRow11}, [data]!
-    VST1    {qRow4}, [luma,:128], width
-    VLD1    {qRow12, qRow13}, [data]!
-    VST1    {qRow5}, [luma,:128], width
-    VLD1    {qRow14, qRow15}, [data]!
-    VST1    {qRow6}, [luma,:128], width
+    VST1.8  {qRow0}, [luma,:128], width
+    VLD1.8  {qRow4, qRow5}, [data]!
+    VST1.8  {qRow1}, [luma,:128], width
+    VLD1.8  {qRow6, qRow7}, [data]!
+    VST1.8  {qRow2}, [luma,:128], width
+    VLD1.8  {qRow8, qRow9}, [data]!
+    VST1.8  {qRow3}, [luma,:128], width
+    VLD1.8  {qRow10, qRow11}, [data]!
+    VST1.8  {qRow4}, [luma,:128], width
+    VLD1.8  {qRow12, qRow13}, [data]!
+    VST1.8  {qRow5}, [luma,:128], width
+    VLD1.8  {qRow14, qRow15}, [data]!
+    VST1.8  {qRow6}, [luma,:128], width
 
-    VLD1    {qRow0, qRow1}, [data]! ;//cb rows 0,1,2,3
-    VST1    {qRow7}, [luma,:128], width
-    VLD1    {qRow2, qRow3}, [data]! ;//cb rows 4,5,6,7
-    VST1    {qRow8}, [luma,:128], width
-    VLD1    {qRow4, qRow5}, [data]! ;//cr rows 0,1,2,3
-    VST1    {qRow9}, [luma,:128], width
-    VLD1    {qRow6, qRow7}, [data]! ;//cr rows 4,5,6,7
-    VST1    {qRow10}, [luma,:128], width
-    VST1    {dRow0}, [cb,:64], cwidth
-    VST1    {dRow8}, [cr,:64], cwidth
-    VST1    {qRow11}, [luma,:128], width
-    VST1    {dRow1}, [cb,:64], cwidth
-    VST1    {dRow9}, [cr,:64], cwidth
-    VST1    {qRow12}, [luma,:128], width
-    VST1    {dRow2}, [cb,:64], cwidth
-    VST1    {dRow10}, [cr,:64], cwidth
-    VST1    {qRow13}, [luma,:128], width
-    VST1    {dRow3}, [cb,:64], cwidth
-    VST1    {dRow11}, [cr,:64], cwidth
-    VST1    {qRow14}, [luma,:128], width
-    VST1    {dRow4}, [cb,:64], cwidth
-    VST1    {dRow12}, [cr,:64], cwidth
-    VST1    {qRow15}, [luma]
-    VST1    {dRow5}, [cb,:64], cwidth
-    VST1    {dRow13}, [cr,:64], cwidth
-    VST1    {dRow6}, [cb,:64], cwidth
-    VST1    {dRow14}, [cr,:64], cwidth
-    VST1    {dRow7}, [cb,:64]
-    VST1    {dRow15}, [cr,:64]
+    VLD1.8  {qRow0, qRow1}, [data]! ;//cb rows 0,1,2,3
+    VST1.8  {qRow7}, [luma,:128], width
+    VLD1.8  {qRow2, qRow3}, [data]! ;//cb rows 4,5,6,7
+    VST1.8  {qRow8}, [luma,:128], width
+    VLD1.8  {qRow4, qRow5}, [data]! ;//cr rows 0,1,2,3
+    VST1.8  {qRow9}, [luma,:128], width
+    VLD1.8  {qRow6, qRow7}, [data]! ;//cr rows 4,5,6,7
+    VST1.8  {qRow10}, [luma,:128], width
+    VST1.8  {dRow0}, [cb,:64], cwidth
+    VST1.8  {dRow8}, [cr,:64], cwidth
+    VST1.8  {qRow11}, [luma,:128], width
+    VST1.8  {dRow1}, [cb,:64], cwidth
+    VST1.8  {dRow9}, [cr,:64], cwidth
+    VST1.8  {qRow12}, [luma,:128], width
+    VST1.8  {dRow2}, [cb,:64], cwidth
+    VST1.8  {dRow10}, [cr,:64], cwidth
+    VST1.8  {qRow13}, [luma,:128], width
+    VST1.8  {dRow3}, [cb,:64], cwidth
+    VST1.8  {dRow11}, [cr,:64], cwidth
+    VST1.8  {qRow14}, [luma,:128], width
+    VST1.8  {dRow4}, [cb,:64], cwidth
+    VST1.8  {dRow12}, [cr,:64], cwidth
+    VST1.8  {qRow15}, [luma]
+    VST1.8  {dRow5}, [cb,:64], cwidth
+    VST1.8  {dRow13}, [cr,:64], cwidth
+    VST1.8  {dRow6}, [cb,:64], cwidth
+    VST1.8  {dRow14}, [cr,:64], cwidth
+    VST1.8  {dRow7}, [cb,:64]
+    VST1.8  {dRow15}, [cr,:64]
 
     VPOP    {q4-q7}
     POP     {r4-r6,pc}
 @    BX      lr
 
-    .endfunc
 
 
 
diff --git a/media/libstagefright/foundation/ANetworkSession.cpp b/media/libstagefright/foundation/ANetworkSession.cpp
index b230400..4bcb1f6 100644
--- a/media/libstagefright/foundation/ANetworkSession.cpp
+++ b/media/libstagefright/foundation/ANetworkSession.cpp
@@ -1318,7 +1318,8 @@
 
         List<sp<Session> > sessionsToAdd;
 
-        for (size_t i = mSessions.size(); res > 0 && i-- > 0;) {
+        for (size_t i = mSessions.size(); res > 0 && i > 0;) {
+            i--;
             const sp<Session> &session = mSessions.valueAt(i);
 
             int s = session->socket();
@@ -1409,4 +1410,3 @@
 }
 
 }  // namespace android
-
diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk
index c68264c..dc8a685 100644
--- a/media/libstagefright/foundation/Android.mk
+++ b/media/libstagefright/foundation/Android.mk
@@ -31,6 +31,7 @@
 
 LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
 LOCAL_CLANG := true
+LOCAL_SANITIZE := unsigned-integer-overflow
 
 LOCAL_MODULE:= libstagefright_foundation
 
diff --git a/media/libstagefright/foundation/base64.cpp b/media/libstagefright/foundation/base64.cpp
index dcf5bef..7da7db9 100644
--- a/media/libstagefright/foundation/base64.cpp
+++ b/media/libstagefright/foundation/base64.cpp
@@ -22,11 +22,11 @@
 namespace android {
 
 sp<ABuffer> decodeBase64(const AString &s) {
-    if ((s.size() % 4) != 0) {
+    size_t n = s.size();
+    if ((n % 4) != 0) {
         return NULL;
     }
 
-    size_t n = s.size();
     size_t padding = 0;
     if (n >= 1 && s.c_str()[n - 1] == '=') {
         padding = 1;
@@ -40,11 +40,16 @@
         }
     }
 
-    size_t outLen = 3 * s.size() / 4 - padding;
+    // We divide first to avoid overflow. It's OK to do this because we
+    // already made sure that n % 4 == 0.
+    size_t outLen = (n / 4) * 3 - padding;
 
     sp<ABuffer> buffer = new ABuffer(outLen);
 
     uint8_t *out = buffer->data();
+    if (out == NULL || buffer->size() < outLen) {
+        return NULL;
+    }
     size_t j = 0;
     uint32_t accum = 0;
     for (size_t i = 0; i < n; ++i) {
diff --git a/media/libstagefright/httplive/Android.mk b/media/libstagefright/httplive/Android.mk
index fc85835..3b94976 100644
--- a/media/libstagefright/httplive/Android.mk
+++ b/media/libstagefright/httplive/Android.mk
@@ -15,6 +15,7 @@
 
 LOCAL_CFLAGS += -Werror -Wall
 LOCAL_CLANG := true
+LOCAL_SANITIZE := unsigned-integer-overflow
 
 LOCAL_SHARED_LIBRARIES := \
         libbinder \
diff --git a/media/libstagefright/httplive/HTTPDownloader.cpp b/media/libstagefright/httplive/HTTPDownloader.cpp
index 3b44bae..861b85a 100644
--- a/media/libstagefright/httplive/HTTPDownloader.cpp
+++ b/media/libstagefright/httplive/HTTPDownloader.cpp
@@ -31,6 +31,7 @@
 #include <openssl/aes.h>
 #include <openssl/md5.h>
 #include <utils/Mutex.h>
+#include <inttypes.h>
 
 namespace android {
 
@@ -165,7 +166,10 @@
         size_t maxBytesToRead = bufferRemaining;
         if (range_length >= 0) {
             int64_t bytesLeftInRange = range_length - buffer->size();
-            if (bytesLeftInRange < (int64_t)maxBytesToRead) {
+            if (bytesLeftInRange < 0) {
+                ALOGE("range_length %" PRId64 " wrapped around", range_length);
+                return ERROR_OUT_OF_RANGE;
+            } else if (bytesLeftInRange < (int64_t)maxBytesToRead) {
                 maxBytesToRead = bytesLeftInRange;
 
                 if (bytesLeftInRange == 0) {
@@ -237,7 +241,7 @@
     // MD5 functionality is not available on the simulator, treat all
     // playlists as changed.
 
-#if defined(HAVE_ANDROID_OS)
+#if defined(__ANDROID__)
     uint8_t hash[16];
 
     MD5_CTX m;
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 72d832e..37847e3 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -1628,7 +1628,8 @@
 
     if (mSegmentFirstPTS < 0ll) {
         // get the smallest first PTS from all streams present in this parser
-        for (size_t i = mPacketSources.size(); i-- > 0;) {
+        for (size_t i = mPacketSources.size(); i > 0;) {
+            i--;
             const LiveSession::StreamType stream = mPacketSources.keyAt(i);
             if (stream == LiveSession::STREAMTYPE_SUBTITLES) {
                 ALOGE("MPEG2 Transport streams do not contain subtitles.");
@@ -1683,7 +1684,8 @@
     }
 
     status_t err = OK;
-    for (size_t i = mPacketSources.size(); i-- > 0;) {
+    for (size_t i = mPacketSources.size(); i > 0;) {
+        i--;
         sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i);
 
         const LiveSession::StreamType stream = mPacketSources.keyAt(i);
@@ -1807,7 +1809,8 @@
     }
 
     if (err != OK) {
-        for (size_t i = mPacketSources.size(); i-- > 0;) {
+        for (size_t i = mPacketSources.size(); i > 0;) {
+            i--;
             sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i);
             packetSource->clear();
         }
@@ -1902,6 +1905,9 @@
             while (!it.done()) {
                 size_t length;
                 const uint8_t *data = it.getData(&length);
+                if (!data) {
+                    return ERROR_MALFORMED;
+                }
 
                 static const char *kMatchName =
                     "com.apple.streaming.transportStreamTimestamp";
diff --git a/media/libstagefright/id3/Android.mk b/media/libstagefright/id3/Android.mk
index 68bd017..2cfba44 100644
--- a/media/libstagefright/id3/Android.mk
+++ b/media/libstagefright/id3/Android.mk
@@ -6,6 +6,7 @@
 
 LOCAL_CFLAGS += -Werror -Wall
 LOCAL_CLANG := true
+LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow
 
 LOCAL_MODULE := libstagefright_id3
 
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index d9491d6..c164fd8 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -327,7 +327,7 @@
     size_t oldSize = mSize;
 
     size_t offset = 0;
-    while (offset + 10 <= mSize) {
+    while (mSize >= 10 && offset <= mSize - 10) {
         if (!memcmp(&mData[offset], "\0\0\0\0", 4)) {
             break;
         }
@@ -339,7 +339,7 @@
             return false;
         }
 
-        if (offset + dataSize + 10 > mSize) {
+        if (dataSize > mSize - 10 - offset) {
             return false;
         }
 
@@ -349,6 +349,9 @@
         if (flags & 1) {
             // Strip data length indicator
 
+            if (mSize < 14 || mSize - 14 < offset || dataSize < 4) {
+                return false;
+            }
             memmove(&mData[offset + 10], &mData[offset + 14], mSize - offset - 14);
             mSize -= 4;
             dataSize -= 4;
@@ -506,6 +509,9 @@
         return;
     }
 
+    if (mFrameSize < getHeaderLength() + 1) {
+        return;
+    }
     size_t n = mFrameSize - getHeaderLength() - 1;
     if (otherdata) {
         // skip past the encoding, language, and the 0 separator
@@ -595,6 +601,11 @@
         return NULL;
     }
 
+    // Prevent integer underflow
+    if (mFrameSize < getHeaderLength()) {
+        return NULL;
+    }
+
     *length = mFrameSize - getHeaderLength();
 
     return mFrameData;
@@ -635,6 +646,11 @@
             }
             mFrameSize += 6; // add tag id and size field
 
+            // Prevent integer overflow in validation
+            if (SIZE_MAX - mOffset <= mFrameSize) {
+                return;
+            }
+
             if (mOffset + mFrameSize > mParent.mSize) {
                 ALOGV("partial frame at offset %zu (size = %zu, bytes-remaining = %zu)",
                     mOffset, mFrameSize, mParent.mSize - mOffset - (size_t)6);
@@ -664,7 +680,7 @@
                 return;
             }
 
-            size_t baseSize;
+            size_t baseSize = 0;
             if (mParent.mVersion == ID3_V2_4) {
                 if (!ParseSyncsafeInteger(
                             &mParent.mData[mOffset + 4], &baseSize)) {
@@ -678,8 +694,18 @@
                 return;
             }
 
+            // Prevent integer overflow when adding
+            if (SIZE_MAX - 10 <= baseSize) {
+                return;
+            }
+
             mFrameSize = 10 + baseSize; // add tag id, size field and flags
 
+            // Prevent integer overflow in validation
+            if (SIZE_MAX - mOffset <= mFrameSize) {
+                return;
+            }
+
             if (mOffset + mFrameSize > mParent.mSize) {
                 ALOGV("partial frame at offset %zu (size = %zu, bytes-remaining = %zu)",
                     mOffset, mFrameSize, mParent.mSize - mOffset - (size_t)10);
@@ -794,6 +820,9 @@
     while (!it.done()) {
         size_t size;
         const uint8_t *data = it.getData(&size);
+        if (!data) {
+            return NULL;
+        }
 
         if (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) {
             uint8_t encoding = data[0];
@@ -811,6 +840,12 @@
 
             size_t descLen = StringSize(&data[2 + mimeLen], encoding);
 
+            if (size < 2 ||
+                    size - 2 < mimeLen ||
+                    size - 2 - mimeLen < descLen) {
+                ALOGW("bogus album art sizes");
+                return NULL;
+            }
             *length = size - 2 - mimeLen - descLen;
 
             return &data[2 + mimeLen + descLen];
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 758b2c9..32b4f47 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -250,6 +250,7 @@
 
     int64_t mLastVideoTimeUs;
     TimedTextDriver *mTextDriver;
+    int32_t mSelectedTimedTextTrack;
 
     sp<WVMExtractor> mWVMExtractor;
     sp<MediaExtractor> mExtractor;
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index 4252706..a29bdf9 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -28,7 +28,7 @@
 struct PageCache;
 
 struct NuCachedSource2 : public DataSource {
-    NuCachedSource2(
+    static sp<NuCachedSource2> Create(
             const sp<DataSource> &source,
             const char *cacheConfig = NULL,
             bool disconnectAtHighwatermark = false);
@@ -72,6 +72,11 @@
 private:
     friend struct AHandlerReflector<NuCachedSource2>;
 
+    NuCachedSource2(
+            const sp<DataSource> &source,
+            const char *cacheConfig,
+            bool disconnectAtHighwatermark);
+
     enum {
         kPageSize                       = 65536,
         kDefaultHighWaterThreshold      = 20 * 1024 * 1024,
diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h
index d06df7b..460492b 100644
--- a/media/libstagefright/include/SampleTable.h
+++ b/media/libstagefright/include/SampleTable.h
@@ -142,8 +142,9 @@
     // normally we don't round
     inline uint64_t getSampleTime(
             size_t sample_index, uint64_t scale_num, uint64_t scale_den) const {
-        return (mSampleTimeEntries[sample_index].mCompositionTime
-            * scale_num) / scale_den;
+        return (sample_index < (size_t)mNumSampleSizes && mSampleTimeEntries != NULL
+                && scale_den != 0)
+                ? (mSampleTimeEntries[sample_index].mCompositionTime * scale_num) / scale_den : 0;
     }
 
     status_t getSampleSize_l(uint32_t sample_index, size_t *sample_size);
diff --git a/media/libstagefright/matroska/Android.mk b/media/libstagefright/matroska/Android.mk
index 1e8c2b2..216668a 100644
--- a/media/libstagefright/matroska/Android.mk
+++ b/media/libstagefright/matroska/Android.mk
@@ -10,6 +10,7 @@
 
 LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
 LOCAL_CLANG := true
+LOCAL_SANITIZE := unsigned-integer-overflow
 
 LOCAL_MODULE:= libstagefright_matroska
 
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index f9a9c4c..bec99a5 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -1537,6 +1537,7 @@
     return mPrograms.editItemAt(0)->PTSTimeDeltaEstablished();
 }
 
+__attribute__((no_sanitize("integer")))
 void ATSParser::updatePCR(
         unsigned /* PID */, uint64_t PCR, size_t byteOffsetFromStart) {
     ALOGV("PCR 0x%016" PRIx64 " @ %zu", PCR, byteOffsetFromStart);
@@ -1555,6 +1556,7 @@
     ++mNumPCRs;
 
     if (mNumPCRs == 2) {
+        /* Unsigned overflow here */
         double transportRate =
             (mPCRBytes[1] - mPCRBytes[0]) * 27E6 / (mPCR[1] - mPCR[0]);
 
diff --git a/media/libstagefright/mpeg2ts/Android.mk b/media/libstagefright/mpeg2ts/Android.mk
index 16b0160..70afde9 100644
--- a/media/libstagefright/mpeg2ts/Android.mk
+++ b/media/libstagefright/mpeg2ts/Android.mk
@@ -15,6 +15,7 @@
 
 LOCAL_CFLAGS += -Werror -Wall
 LOCAL_CLANG := true
+LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow
 
 LOCAL_MODULE:= libstagefright_mpeg2ts
 
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 36ec367..c967463 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -1121,6 +1121,10 @@
 
         if (mFormat != NULL && currentStartCode == 0xb8) {
             // GOP layer
+            if (offset + 7 >= size) {
+                ALOGE("Size too small");
+                return NULL;
+            }
             gopFound = true;
             isClosedGop = (data[offset + 7] & 0x40) != 0;
             brokenLink = (data[offset + 7] & 0x20) != 0;
diff --git a/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
index 6d9fe9d..0f18fac 100644
--- a/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
+++ b/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
@@ -108,7 +108,8 @@
     }
 
     // Remove all tracks that were unable to determine their format.
-    for (size_t i = mTracks.size(); i-- > 0;) {
+    for (size_t i = mTracks.size(); i > 0;) {
+        i--;
         if (mTracks.valueAt(i)->getFormat() == NULL) {
             mTracks.removeItemsAt(i);
         }
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index 5f0f567..804afe9 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -33,6 +33,7 @@
 LOCAL_MODULE:= libstagefright_omx
 LOCAL_CFLAGS += -Werror -Wall
 LOCAL_CLANG := true
+LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow
 
 include $(BUILD_SHARED_LIBRARY)
 
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index cb7ab5e..eb0c5b2 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -261,6 +261,10 @@
 status_t OMX::freeNode(node_id node) {
     OMXNodeInstance *instance = findInstance(node);
 
+    if (instance == NULL) {
+        return OK;
+    }
+
     {
         Mutex::Autolock autoLock(mLock);
         ssize_t index = mLiveNodes.indexOfKey(IInterface::asBinder(instance->observer()));
@@ -288,14 +292,26 @@
 
 status_t OMX::sendCommand(
         node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
-    return findInstance(node)->sendCommand(cmd, param);
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->sendCommand(cmd, param);
 }
 
 status_t OMX::getParameter(
         node_id node, OMX_INDEXTYPE index,
         void *params, size_t size) {
     ALOGV("getParameter(%u %#x %p %zd)", node, index, params, size);
-    return findInstance(node)->getParameter(
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->getParameter(
             index, params, size);
 }
 
@@ -303,84 +319,162 @@
         node_id node, OMX_INDEXTYPE index,
         const void *params, size_t size) {
     ALOGV("setParameter(%u %#x %p %zd)", node, index, params, size);
-    return findInstance(node)->setParameter(
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->setParameter(
             index, params, size);
 }
 
 status_t OMX::getConfig(
         node_id node, OMX_INDEXTYPE index,
         void *params, size_t size) {
-    return findInstance(node)->getConfig(
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->getConfig(
             index, params, size);
 }
 
 status_t OMX::setConfig(
         node_id node, OMX_INDEXTYPE index,
         const void *params, size_t size) {
-    return findInstance(node)->setConfig(
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->setConfig(
             index, params, size);
 }
 
 status_t OMX::getState(
         node_id node, OMX_STATETYPE* state) {
-    return findInstance(node)->getState(
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->getState(
             state);
 }
 
 status_t OMX::enableGraphicBuffers(
         node_id node, OMX_U32 port_index, OMX_BOOL enable) {
-    return findInstance(node)->enableGraphicBuffers(port_index, enable);
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->enableGraphicBuffers(port_index, enable);
 }
 
 status_t OMX::getGraphicBufferUsage(
         node_id node, OMX_U32 port_index, OMX_U32* usage) {
-    return findInstance(node)->getGraphicBufferUsage(port_index, usage);
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->getGraphicBufferUsage(port_index, usage);
 }
 
 status_t OMX::storeMetaDataInBuffers(
         node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
-    return findInstance(node)->storeMetaDataInBuffers(port_index, enable, type);
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->storeMetaDataInBuffers(port_index, enable, type);
 }
 
 status_t OMX::prepareForAdaptivePlayback(
         node_id node, OMX_U32 portIndex, OMX_BOOL enable,
         OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) {
-    return findInstance(node)->prepareForAdaptivePlayback(
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->prepareForAdaptivePlayback(
             portIndex, enable, maxFrameWidth, maxFrameHeight);
 }
 
 status_t OMX::configureVideoTunnelMode(
         node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
         OMX_U32 audioHwSync, native_handle_t **sidebandHandle) {
-    return findInstance(node)->configureVideoTunnelMode(
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->configureVideoTunnelMode(
             portIndex, tunneled, audioHwSync, sidebandHandle);
 }
 
 status_t OMX::useBuffer(
         node_id node, OMX_U32 port_index, const sp<IMemory> &params,
         buffer_id *buffer, OMX_U32 allottedSize) {
-    return findInstance(node)->useBuffer(
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->useBuffer(
             port_index, params, buffer, allottedSize);
 }
 
 status_t OMX::useGraphicBuffer(
         node_id node, OMX_U32 port_index,
         const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
-    return findInstance(node)->useGraphicBuffer(
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->useGraphicBuffer(
             port_index, graphicBuffer, buffer);
 }
 
 status_t OMX::updateGraphicBufferInMeta(
         node_id node, OMX_U32 port_index,
         const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) {
-    return findInstance(node)->updateGraphicBufferInMeta(
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->updateGraphicBufferInMeta(
             port_index, graphicBuffer, buffer);
 }
 
 status_t OMX::createInputSurface(
         node_id node, OMX_U32 port_index,
         sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
-    return findInstance(node)->createInputSurface(
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->createInputSurface(
             port_index, bufferProducer, type);
 }
 
@@ -394,35 +488,71 @@
 status_t OMX::setInputSurface(
         node_id node, OMX_U32 port_index,
         const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type) {
-    return findInstance(node)->setInputSurface(port_index, bufferConsumer, type);
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->setInputSurface(port_index, bufferConsumer, type);
 }
 
 
 status_t OMX::signalEndOfInputStream(node_id node) {
-    return findInstance(node)->signalEndOfInputStream();
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->signalEndOfInputStream();
 }
 
 status_t OMX::allocateBuffer(
         node_id node, OMX_U32 port_index, size_t size,
         buffer_id *buffer, void **buffer_data) {
-    return findInstance(node)->allocateBuffer(
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->allocateBuffer(
             port_index, size, buffer, buffer_data);
 }
 
 status_t OMX::allocateBufferWithBackup(
         node_id node, OMX_U32 port_index, const sp<IMemory> &params,
         buffer_id *buffer, OMX_U32 allottedSize) {
-    return findInstance(node)->allocateBufferWithBackup(
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->allocateBufferWithBackup(
             port_index, params, buffer, allottedSize);
 }
 
 status_t OMX::freeBuffer(node_id node, OMX_U32 port_index, buffer_id buffer) {
-    return findInstance(node)->freeBuffer(
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->freeBuffer(
             port_index, buffer);
 }
 
 status_t OMX::fillBuffer(node_id node, buffer_id buffer, int fenceFd) {
-    return findInstance(node)->fillBuffer(buffer, fenceFd);
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->fillBuffer(buffer, fenceFd);
 }
 
 status_t OMX::emptyBuffer(
@@ -430,7 +560,13 @@
         buffer_id buffer,
         OMX_U32 range_offset, OMX_U32 range_length,
         OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
-    return findInstance(node)->emptyBuffer(
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->emptyBuffer(
             buffer, range_offset, range_length, flags, timestamp, fenceFd);
 }
 
@@ -438,7 +574,13 @@
         node_id node,
         const char *parameter_name,
         OMX_INDEXTYPE *index) {
-    return findInstance(node)->getExtensionIndex(
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->getExtensionIndex(
             parameter_name, index);
 }
 
@@ -448,7 +590,13 @@
         InternalOptionType type,
         const void *data,
         size_t size) {
-    return findInstance(node)->setInternalOption(port_index, type, data, size);
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return NAME_NOT_FOUND;
+    }
+
+    return instance->setInternalOption(port_index, type, data, size);
 }
 
 OMX_ERRORTYPE OMX::OnEvent(
@@ -458,9 +606,14 @@
         OMX_IN OMX_U32 nData2,
         OMX_IN OMX_PTR pEventData) {
     ALOGV("OnEvent(%d, %" PRIu32", %" PRIu32 ")", eEvent, nData1, nData2);
+    OMXNodeInstance *instance = findInstance(node);
+
+    if (instance == NULL) {
+        return OMX_ErrorComponentNotFound;
+    }
 
     // Forward to OMXNodeInstance.
-    findInstance(node)->onEvent(eEvent, nData1, nData2);
+    instance->onEvent(eEvent, nData1, nData2);
 
     sp<OMX::CallbackDispatcher> dispatcher = findDispatcher(node);
 
diff --git a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
index 8ea7a6e..a770f49 100644
--- a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
@@ -358,6 +358,7 @@
 }
 
 // static
+__attribute__((no_sanitize("integer")))
 void SoftVideoEncoderOMXComponent::ConvertFlexYUVToPlanar(
         uint8_t *dst, size_t dstStride, size_t dstVStride,
         struct android_ycbcr *ycbcr, int32_t width, int32_t height) {
@@ -400,6 +401,7 @@
 }
 
 // static
+__attribute__((no_sanitize("integer")))
 void SoftVideoEncoderOMXComponent::ConvertYUV420SemiPlanarToYUV420Planar(
         const uint8_t *inYVU, uint8_t* outYUV, int32_t width, int32_t height) {
     // TODO: add support for stride
@@ -430,6 +432,7 @@
 }
 
 // static
+__attribute__((no_sanitize("integer")))
 void SoftVideoEncoderOMXComponent::ConvertRGB32ToPlanar(
         uint8_t *dstY, size_t dstStride, size_t dstVStride,
         const uint8_t *src, size_t width, size_t height, size_t srcStride,
diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
index 1f76068..a1a6576 100644
--- a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
@@ -404,8 +404,9 @@
                 break;
             }
         }
-
-        CHECK_LE(offset + payloadLength, buffer->size());
+        
+        CHECK_LT(offset, buffer->size());
+        CHECK_LE(payloadLength, buffer->size() - offset);
 
         memcpy(out->data() + out->size(), &ptr[offset], payloadLength);
         out->setRange(0, out->size() + payloadLength);
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 855ffdc..5620cf8 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -898,11 +898,6 @@
     if (!strncmp(value.c_str(), "Basic", 5)) {
         mAuthType = BASIC;
     } else {
-#if !defined(HAVE_ANDROID_OS)
-        // We don't have access to the MD5 implementation on the simulator,
-        // so we won't support digest authentication.
-        return false;
-#endif
 
         CHECK(!strncmp(value.c_str(), "Digest", 6));
         mAuthType = DIGEST;
@@ -919,7 +914,6 @@
     return true;
 }
 
-#if defined(HAVE_ANDROID_OS)
 static void H(const AString &s, AString *out) {
     out->clear();
 
@@ -948,7 +942,6 @@
         out->append(&nibble, 1);
     }
 }
-#endif
 
 static void GetMethodAndURL(
         const AString &request, AString *method, AString *url) {
@@ -990,7 +983,6 @@
         return;
     }
 
-#if defined(HAVE_ANDROID_OS)
     CHECK_EQ((int)mAuthType, (int)DIGEST);
 
     AString method, url;
@@ -1039,7 +1031,6 @@
     fragment.append("\r\n");
 
     request->insert(fragment, i + 2);
-#endif
 }
 
 void ARTSPConnection::addUserAgent(AString *request) const {
diff --git a/media/libstagefright/rtsp/Android.mk b/media/libstagefright/rtsp/Android.mk
index c5e8c35..8bcb29e 100644
--- a/media/libstagefright/rtsp/Android.mk
+++ b/media/libstagefright/rtsp/Android.mk
@@ -33,6 +33,7 @@
 
 LOCAL_CFLAGS += -Werror -Wall
 LOCAL_CLANG := true
+LOCAL_SANITIZE := unsigned-integer-overflow
 
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
diff --git a/media/libstagefright/timedtext/TextDescriptions.cpp b/media/libstagefright/timedtext/TextDescriptions.cpp
index f9c1fe0..c762a74 100644
--- a/media/libstagefright/timedtext/TextDescriptions.cpp
+++ b/media/libstagefright/timedtext/TextDescriptions.cpp
@@ -30,9 +30,9 @@
 
     if (flags & IN_BAND_TEXT_3GPP) {
         if (flags & GLOBAL_DESCRIPTIONS) {
-            return extract3GPPGlobalDescriptions(data, size, parcel, 0);
+            return extract3GPPGlobalDescriptions(data, size, parcel);
         } else if (flags & LOCAL_DESCRIPTIONS) {
-            return extract3GPPLocalDescriptions(data, size, timeMs, parcel, 0);
+            return extract3GPPLocalDescriptions(data, size, timeMs, parcel);
         }
     } else if (flags & OUT_OF_BAND_TEXT_SRT) {
         if (flags & LOCAL_DESCRIPTIONS) {
@@ -69,49 +69,361 @@
 // styles, and 'krok' box contains karaoke timing and positions.
 status_t TextDescriptions::extract3GPPLocalDescriptions(
         const uint8_t *data, ssize_t size,
-        int timeMs, Parcel *parcel, int depth) {
-    if (depth == 0) {
-        parcel->writeInt32(KEY_LOCAL_SETTING);
+        int timeMs, Parcel *parcel) {
 
-        // write start time to display this text sample
-        parcel->writeInt32(KEY_START_TIME);
-        parcel->writeInt32(timeMs);
+    parcel->writeInt32(KEY_LOCAL_SETTING);
 
-        ssize_t textLen = (*data) << 8 | (*(data + 1));
+    // write start time to display this text sample
+    parcel->writeInt32(KEY_START_TIME);
+    parcel->writeInt32(timeMs);
 
-        // write text sample length and text sample itself
-        parcel->writeInt32(KEY_STRUCT_TEXT);
-        parcel->writeInt32(textLen);
-        parcel->writeInt32(textLen);
-        parcel->write(data + 2, textLen);
-
-        if (size > textLen) {
-            data += (textLen + 2);
-            size -= (textLen + 2);
-        } else {
-            return OK;
-        }
+    if (size < 2) {
+        return OK;
     }
+    ssize_t textLen = (*data) << 8 | (*(data + 1));
 
-    const uint8_t *tmpData = data;
-    ssize_t chunkSize = U32_AT(tmpData);
-    uint32_t chunkType = U32_AT(tmpData + 4);
-
-    if (chunkSize <= 0) {
+    if (size < textLen + 2) {
         return OK;
     }
 
-    tmpData += 8;
+    // write text sample length and text sample itself
+    parcel->writeInt32(KEY_STRUCT_TEXT);
+    parcel->writeInt32(textLen);
+    parcel->writeInt32(textLen);
+    parcel->write(data + 2, textLen);
 
-    switch(chunkType) {
-        // 'styl' box specifies the style of the text.
-        case FOURCC('s', 't', 'y', 'l'):
-        {
-            uint16_t count = U16_AT(tmpData);
+    if (size > textLen + 2) {
+        data += (textLen + 2);
+        size -= (textLen + 2);
+    } else {
+        return OK;
+    }
 
-            tmpData += 2;
+    while (size >= 8) {
+        const uint8_t *tmpData = data;
+        ssize_t chunkSize = U32_AT(tmpData);      // size includes size and type
+        uint32_t chunkType = U32_AT(tmpData + 4);
 
-            for (int i = 0; i < count; i++) {
+        if (chunkSize <= 8 || chunkSize > size) {
+            return OK;
+        }
+
+        size_t remaining = chunkSize - 8;
+
+        tmpData += 8;
+
+        switch(chunkType) {
+            // 'styl' box specifies the style of the text.
+            case FOURCC('s', 't', 'y', 'l'):
+            {
+                if (remaining < 2) {
+                    return OK;
+                }
+                size_t dataPos = parcel->dataPosition();
+                uint16_t count = U16_AT(tmpData);
+
+                tmpData += 2;
+                remaining -= 2;
+
+                for (int i = 0; i < count; i++) {
+                    if (remaining < 12) {
+                        // roll back
+                        parcel->setDataPosition(dataPos);
+                        return OK;
+                    }
+                    parcel->writeInt32(KEY_STRUCT_STYLE_LIST);
+                    parcel->writeInt32(KEY_START_CHAR);
+                    parcel->writeInt32(U16_AT(tmpData));
+
+                    parcel->writeInt32(KEY_END_CHAR);
+                    parcel->writeInt32(U16_AT(tmpData + 2));
+
+                    parcel->writeInt32(KEY_FONT_ID);
+                    parcel->writeInt32(U16_AT(tmpData + 4));
+
+                    parcel->writeInt32(KEY_STYLE_FLAGS);
+                    parcel->writeInt32(*(tmpData + 6));
+
+                    parcel->writeInt32(KEY_FONT_SIZE);
+                    parcel->writeInt32(*(tmpData + 7));
+
+                    parcel->writeInt32(KEY_TEXT_COLOR_RGBA);
+                    uint32_t rgba = *(tmpData + 8) << 24 | *(tmpData + 9) << 16
+                        | *(tmpData + 10) << 8 | *(tmpData + 11);
+                    parcel->writeInt32(rgba);
+
+                    tmpData += 12;
+                    remaining -= 12;
+                }
+
+                break;
+            }
+            // 'krok' box. The number of highlight events is specified, and each
+            // event is specified by a starting and ending char offset and an end
+            // time for the event.
+            case FOURCC('k', 'r', 'o', 'k'):
+            {
+                if (remaining < 6) {
+                    return OK;
+                }
+                size_t dataPos = parcel->dataPosition();
+
+                parcel->writeInt32(KEY_STRUCT_KARAOKE_LIST);
+
+                int startTime = U32_AT(tmpData);
+                uint16_t count = U16_AT(tmpData + 4);
+                parcel->writeInt32(count);
+
+                tmpData += 6;
+                remaining -= 6;
+                int lastEndTime = 0;
+
+                for (int i = 0; i < count; i++) {
+                    if (remaining < 8) {
+                        // roll back
+                        parcel->setDataPosition(dataPos);
+                        return OK;
+                    }
+                    parcel->writeInt32(startTime + lastEndTime);
+
+                    lastEndTime = U32_AT(tmpData);
+                    parcel->writeInt32(lastEndTime);
+
+                    parcel->writeInt32(U16_AT(tmpData + 4));
+                    parcel->writeInt32(U16_AT(tmpData + 6));
+
+                    tmpData += 8;
+                    remaining -= 8;
+                }
+
+                break;
+            }
+            // 'hlit' box specifies highlighted text
+            case FOURCC('h', 'l', 'i', 't'):
+            {
+                if (remaining < 4) {
+                    return OK;
+                }
+
+                parcel->writeInt32(KEY_STRUCT_HIGHLIGHT_LIST);
+
+                // the start char offset to highlight
+                parcel->writeInt32(U16_AT(tmpData));
+                // the last char offset to highlight
+                parcel->writeInt32(U16_AT(tmpData + 2));
+
+                tmpData += 4;
+                remaining -= 4;
+                break;
+            }
+            // 'hclr' box specifies the RGBA color: 8 bits each of
+            // red, green, blue, and an alpha(transparency) value
+            case FOURCC('h', 'c', 'l', 'r'):
+            {
+                if (remaining < 4) {
+                    return OK;
+                }
+                parcel->writeInt32(KEY_HIGHLIGHT_COLOR_RGBA);
+
+                uint32_t rgba = *(tmpData) << 24 | *(tmpData + 1) << 16
+                    | *(tmpData + 2) << 8 | *(tmpData + 3);
+                parcel->writeInt32(rgba);
+
+                tmpData += 4;
+                remaining -= 4;
+                break;
+            }
+            // 'dlay' box specifies a delay after a scroll in and/or
+            // before scroll out.
+            case FOURCC('d', 'l', 'a', 'y'):
+            {
+                if (remaining < 4) {
+                    return OK;
+                }
+                parcel->writeInt32(KEY_SCROLL_DELAY);
+
+                uint32_t delay = *(tmpData) << 24 | *(tmpData + 1) << 16
+                    | *(tmpData + 2) << 8 | *(tmpData + 3);
+                parcel->writeInt32(delay);
+
+                tmpData += 4;
+                remaining -= 4;
+                break;
+            }
+            // 'href' box for hyper text link
+            case FOURCC('h', 'r', 'e', 'f'):
+            {
+                if (remaining < 5) {
+                    return OK;
+                }
+
+                size_t dataPos = parcel->dataPosition();
+
+                parcel->writeInt32(KEY_STRUCT_HYPER_TEXT_LIST);
+
+                // the start offset of the text to be linked
+                parcel->writeInt32(U16_AT(tmpData));
+                // the end offset of the text
+                parcel->writeInt32(U16_AT(tmpData + 2));
+
+                // the number of bytes in the following URL
+                size_t len = *(tmpData + 4);
+                parcel->writeInt32(len);
+
+                remaining -= 5;
+
+                if (remaining  < len) {
+                    parcel->setDataPosition(dataPos);
+                    return OK;
+                }
+                // the linked-to URL
+                parcel->writeInt32(len);
+                parcel->write(tmpData + 5, len);
+
+                tmpData += (5 + len);
+                remaining -= len;
+
+                if (remaining  < 1) {
+                    parcel->setDataPosition(dataPos);
+                    return OK;
+                }
+
+                // the number of bytes in the following "alt" string
+                len = *tmpData;
+                parcel->writeInt32(len);
+
+                tmpData += 1;
+                remaining -= 1;
+                if (remaining  < len) {
+                    parcel->setDataPosition(dataPos);
+                    return OK;
+                }
+
+                // an "alt" string for user display
+                parcel->writeInt32(len);
+                parcel->write(tmpData, len);
+
+                tmpData += 1;
+                remaining -= 1;
+                break;
+            }
+            // 'tbox' box to indicate the position of the text with values
+            // of top, left, bottom and right
+            case FOURCC('t', 'b', 'o', 'x'):
+            {
+                if (remaining < 8) {
+                    return OK;
+                }
+                parcel->writeInt32(KEY_STRUCT_TEXT_POS);
+                parcel->writeInt32(U16_AT(tmpData));
+                parcel->writeInt32(U16_AT(tmpData + 2));
+                parcel->writeInt32(U16_AT(tmpData + 4));
+                parcel->writeInt32(U16_AT(tmpData + 6));
+
+                tmpData += 8;
+                remaining -= 8;
+                break;
+            }
+            // 'blnk' to specify the char range to be blinked
+            case FOURCC('b', 'l', 'n', 'k'):
+            {
+                if (remaining < 4) {
+                    return OK;
+                }
+
+                parcel->writeInt32(KEY_STRUCT_BLINKING_TEXT_LIST);
+
+                // start char offset
+                parcel->writeInt32(U16_AT(tmpData));
+                // end char offset
+                parcel->writeInt32(U16_AT(tmpData + 2));
+
+                tmpData += 4;
+                remaining -= 4;
+                break;
+            }
+            // 'twrp' box specifies text wrap behavior. If the value if 0x00,
+            // then no wrap. If it's 0x01, then automatic 'soft' wrap is enabled.
+            // 0x02-0xff are reserved.
+            case FOURCC('t', 'w', 'r', 'p'):
+            {
+                if (remaining < 1) {
+                    return OK;
+                }
+                parcel->writeInt32(KEY_WRAP_TEXT);
+                parcel->writeInt32(*tmpData);
+
+                tmpData += 1;
+                remaining -= 1;
+                break;
+            }
+            default:
+            {
+                break;
+            }
+        }
+
+        data += chunkSize;
+        size -= chunkSize;
+    }
+
+    return OK;
+}
+
+// To extract box 'tx3g' defined in 3GPP TS 26.245, and store it in a Parcel
+status_t TextDescriptions::extract3GPPGlobalDescriptions(
+        const uint8_t *data, ssize_t size, Parcel *parcel) {
+
+    parcel->writeInt32(KEY_GLOBAL_SETTING);
+
+    while (size >= 8) {
+        ssize_t chunkSize = U32_AT(data);
+        uint32_t chunkType = U32_AT(data + 4);
+        const uint8_t *tmpData = data;
+        tmpData += 8;
+        size_t remaining = size - 8;
+
+        if (size < chunkSize) {
+            return OK;
+        }
+        switch(chunkType) {
+            case FOURCC('t', 'x', '3', 'g'):
+            {
+                if (remaining < 18) { // 8 just below, and another 10 a little further down
+                    return OK;
+                }
+                tmpData += 8; // skip the first 8 bytes
+                remaining -=8;
+                parcel->writeInt32(KEY_DISPLAY_FLAGS);
+                parcel->writeInt32(U32_AT(tmpData));
+
+                parcel->writeInt32(KEY_STRUCT_JUSTIFICATION);
+                parcel->writeInt32(tmpData[4]);
+                parcel->writeInt32(tmpData[5]);
+
+                parcel->writeInt32(KEY_BACKGROUND_COLOR_RGBA);
+                uint32_t rgba = *(tmpData + 6) << 24 | *(tmpData + 7) << 16
+                    | *(tmpData + 8) << 8 | *(tmpData + 9);
+                parcel->writeInt32(rgba);
+
+                tmpData += 10;
+                remaining -= 10;
+
+                if (remaining < 8) {
+                    return OK;
+                }
+                parcel->writeInt32(KEY_STRUCT_TEXT_POS);
+                parcel->writeInt32(U16_AT(tmpData));
+                parcel->writeInt32(U16_AT(tmpData + 2));
+                parcel->writeInt32(U16_AT(tmpData + 4));
+                parcel->writeInt32(U16_AT(tmpData + 6));
+
+                tmpData += 8;
+                remaining -= 8;
+
+                if (remaining < 12) {
+                    return OK;
+                }
                 parcel->writeInt32(KEY_STRUCT_STYLE_LIST);
                 parcel->writeInt32(KEY_START_CHAR);
                 parcel->writeInt32(U16_AT(tmpData));
@@ -129,254 +441,65 @@
                 parcel->writeInt32(*(tmpData + 7));
 
                 parcel->writeInt32(KEY_TEXT_COLOR_RGBA);
-                uint32_t rgba = *(tmpData + 8) << 24 | *(tmpData + 9) << 16
+                rgba = *(tmpData + 8) << 24 | *(tmpData + 9) << 16
                     | *(tmpData + 10) << 8 | *(tmpData + 11);
                 parcel->writeInt32(rgba);
 
                 tmpData += 12;
+                remaining -= 12;
+
+                if (remaining < 2) {
+                    return OK;
+                }
+
+                size_t dataPos = parcel->dataPosition();
+
+                parcel->writeInt32(KEY_STRUCT_FONT_LIST);
+                uint16_t count = U16_AT(tmpData);
+                parcel->writeInt32(count);
+
+                tmpData += 2;
+                remaining -= 2;
+
+                for (int i = 0; i < count; i++) {
+                    if (remaining < 3) {
+                        // roll back
+                        parcel->setDataPosition(dataPos);
+                        return OK;
+                    }
+                    // font ID
+                    parcel->writeInt32(U16_AT(tmpData));
+
+                    // font name length
+                    parcel->writeInt32(*(tmpData + 2));
+
+                    size_t len = *(tmpData + 2);
+
+                    tmpData += 3;
+                    remaining -= 3;
+
+                    if (remaining < len) {
+                        // roll back
+                        parcel->setDataPosition(dataPos);
+                        return OK;
+                    }
+
+                    parcel->write(tmpData, len);
+                    tmpData += len;
+                    remaining -= len;
+                }
+
+                // there is a "DisparityBox" after this according to the spec, but we ignore it
+                break;
             }
-
-            break;
-        }
-        // 'krok' box. The number of highlight events is specified, and each
-        // event is specified by a starting and ending char offset and an end
-        // time for the event.
-        case FOURCC('k', 'r', 'o', 'k'):
-        {
-
-            parcel->writeInt32(KEY_STRUCT_KARAOKE_LIST);
-
-            int startTime = U32_AT(tmpData);
-            uint16_t count = U16_AT(tmpData + 4);
-            parcel->writeInt32(count);
-
-            tmpData += 6;
-            int lastEndTime = 0;
-
-            for (int i = 0; i < count; i++) {
-                parcel->writeInt32(startTime + lastEndTime);
-
-                lastEndTime = U32_AT(tmpData);
-                parcel->writeInt32(lastEndTime);
-
-                parcel->writeInt32(U16_AT(tmpData + 4));
-                parcel->writeInt32(U16_AT(tmpData + 6));
-
-                tmpData += 8;
+            default:
+            {
+                break;
             }
-
-            break;
         }
-        // 'hlit' box specifies highlighted text
-        case FOURCC('h', 'l', 'i', 't'):
-        {
-            parcel->writeInt32(KEY_STRUCT_HIGHLIGHT_LIST);
 
-            // the start char offset to highlight
-            parcel->writeInt32(U16_AT(tmpData));
-            // the last char offset to highlight
-            parcel->writeInt32(U16_AT(tmpData + 2));
-
-            break;
-        }
-        // 'hclr' box specifies the RGBA color: 8 bits each of
-        // red, green, blue, and an alpha(transparency) value
-        case FOURCC('h', 'c', 'l', 'r'):
-        {
-            parcel->writeInt32(KEY_HIGHLIGHT_COLOR_RGBA);
-
-            uint32_t rgba = *(tmpData) << 24 | *(tmpData + 1) << 16
-                | *(tmpData + 2) << 8 | *(tmpData + 3);
-            parcel->writeInt32(rgba);
-
-            break;
-        }
-        // 'dlay' box specifies a delay after a scroll in and/or
-        // before scroll out.
-        case FOURCC('d', 'l', 'a', 'y'):
-        {
-            parcel->writeInt32(KEY_SCROLL_DELAY);
-
-            uint32_t delay = *(tmpData) << 24 | *(tmpData + 1) << 16
-                | *(tmpData + 2) << 8 | *(tmpData + 3);
-            parcel->writeInt32(delay);
-
-            break;
-        }
-        // 'href' box for hyper text link
-        case FOURCC('h', 'r', 'e', 'f'):
-        {
-            parcel->writeInt32(KEY_STRUCT_HYPER_TEXT_LIST);
-
-            // the start offset of the text to be linked
-            parcel->writeInt32(U16_AT(tmpData));
-            // the end offset of the text
-            parcel->writeInt32(U16_AT(tmpData + 2));
-
-            // the number of bytes in the following URL
-            int len = *(tmpData + 4);
-            parcel->writeInt32(len);
-
-            // the linked-to URL
-            parcel->writeInt32(len);
-            parcel->write(tmpData + 5, len);
-
-            tmpData += (5 + len);
-
-            // the number of bytes in the following "alt" string
-            len = *tmpData;
-            parcel->writeInt32(len);
-
-            // an "alt" string for user display
-            parcel->writeInt32(len);
-            parcel->write(tmpData + 1, len);
-
-            break;
-        }
-        // 'tbox' box to indicate the position of the text with values
-        // of top, left, bottom and right
-        case FOURCC('t', 'b', 'o', 'x'):
-        {
-            parcel->writeInt32(KEY_STRUCT_TEXT_POS);
-            parcel->writeInt32(U16_AT(tmpData));
-            parcel->writeInt32(U16_AT(tmpData + 2));
-            parcel->writeInt32(U16_AT(tmpData + 4));
-            parcel->writeInt32(U16_AT(tmpData + 6));
-
-            break;
-        }
-        // 'blnk' to specify the char range to be blinked
-        case FOURCC('b', 'l', 'n', 'k'):
-        {
-            parcel->writeInt32(KEY_STRUCT_BLINKING_TEXT_LIST);
-
-            // start char offset
-            parcel->writeInt32(U16_AT(tmpData));
-            // end char offset
-            parcel->writeInt32(U16_AT(tmpData + 2));
-
-            break;
-        }
-        // 'twrp' box specifies text wrap behavior. If the value if 0x00,
-        // then no wrap. If it's 0x01, then automatic 'soft' wrap is enabled.
-        // 0x02-0xff are reserved.
-        case FOURCC('t', 'w', 'r', 'p'):
-        {
-            parcel->writeInt32(KEY_WRAP_TEXT);
-            parcel->writeInt32(*tmpData);
-
-            break;
-        }
-        default:
-        {
-            break;
-        }
-    }
-
-    if (size > chunkSize) {
         data += chunkSize;
         size -= chunkSize;
-        // continue to parse next box
-        return extract3GPPLocalDescriptions(data, size, 0, parcel, 1);
-    }
-
-    return OK;
-}
-
-// To extract box 'tx3g' defined in 3GPP TS 26.245, and store it in a Parcel
-status_t TextDescriptions::extract3GPPGlobalDescriptions(
-        const uint8_t *data, ssize_t size, Parcel *parcel, int depth) {
-
-    ssize_t chunkSize = U32_AT(data);
-    uint32_t chunkType = U32_AT(data + 4);
-    const uint8_t *tmpData = data;
-    tmpData += 8;
-
-    if (size < chunkSize) {
-        return OK;
-    }
-
-    if (depth == 0) {
-        parcel->writeInt32(KEY_GLOBAL_SETTING);
-    }
-    switch(chunkType) {
-        case FOURCC('t', 'x', '3', 'g'):
-        {
-            tmpData += 8; // skip the first 8 bytes
-            parcel->writeInt32(KEY_DISPLAY_FLAGS);
-            parcel->writeInt32(U32_AT(tmpData));
-
-            parcel->writeInt32(KEY_STRUCT_JUSTIFICATION);
-            parcel->writeInt32(tmpData[4]);
-            parcel->writeInt32(tmpData[5]);
-
-            parcel->writeInt32(KEY_BACKGROUND_COLOR_RGBA);
-            uint32_t rgba = *(tmpData + 6) << 24 | *(tmpData + 7) << 16
-                | *(tmpData + 8) << 8 | *(tmpData + 9);
-            parcel->writeInt32(rgba);
-
-            tmpData += 10;
-            parcel->writeInt32(KEY_STRUCT_TEXT_POS);
-            parcel->writeInt32(U16_AT(tmpData));
-            parcel->writeInt32(U16_AT(tmpData + 2));
-            parcel->writeInt32(U16_AT(tmpData + 4));
-            parcel->writeInt32(U16_AT(tmpData + 6));
-
-            tmpData += 8;
-            parcel->writeInt32(KEY_STRUCT_STYLE_LIST);
-            parcel->writeInt32(KEY_START_CHAR);
-            parcel->writeInt32(U16_AT(tmpData));
-
-            parcel->writeInt32(KEY_END_CHAR);
-            parcel->writeInt32(U16_AT(tmpData + 2));
-
-            parcel->writeInt32(KEY_FONT_ID);
-            parcel->writeInt32(U16_AT(tmpData + 4));
-
-            parcel->writeInt32(KEY_STYLE_FLAGS);
-            parcel->writeInt32(*(tmpData + 6));
-
-            parcel->writeInt32(KEY_FONT_SIZE);
-            parcel->writeInt32(*(tmpData + 7));
-
-            parcel->writeInt32(KEY_TEXT_COLOR_RGBA);
-            rgba = *(tmpData + 8) << 24 | *(tmpData + 9) << 16
-                | *(tmpData + 10) << 8 | *(tmpData + 11);
-            parcel->writeInt32(rgba);
-
-            tmpData += 12;
-            parcel->writeInt32(KEY_STRUCT_FONT_LIST);
-            uint16_t count = U16_AT(tmpData);
-            parcel->writeInt32(count);
-
-            tmpData += 2;
-            for (int i = 0; i < count; i++) {
-                // font ID
-                parcel->writeInt32(U16_AT(tmpData));
-
-                // font name length
-                parcel->writeInt32(*(tmpData + 2));
-
-                int len = *(tmpData + 2);
-
-                parcel->write(tmpData + 3, len);
-                tmpData += 3 + len;
-            }
-
-            break;
-        }
-        default:
-        {
-            break;
-        }
-    }
-
-    data += chunkSize;
-    size -= chunkSize;
-
-    if (size > 0) {
-        // continue to extract next 'tx3g'
-        return extract3GPPGlobalDescriptions(data, size, parcel, 1);
     }
 
     return OK;
diff --git a/media/libstagefright/timedtext/TextDescriptions.h b/media/libstagefright/timedtext/TextDescriptions.h
index 0144917..bf67f3f 100644
--- a/media/libstagefright/timedtext/TextDescriptions.h
+++ b/media/libstagefright/timedtext/TextDescriptions.h
@@ -72,10 +72,10 @@
             int timeMs, Parcel *parcel);
     static status_t extract3GPPGlobalDescriptions(
             const uint8_t *data, ssize_t size,
-            Parcel *parcel, int depth);
+            Parcel *parcel);
     static status_t extract3GPPLocalDescriptions(
             const uint8_t *data, ssize_t size,
-            int timeMs, Parcel *parcel, int depth);
+            int timeMs, Parcel *parcel);
 
     DISALLOW_EVIL_CONSTRUCTORS(TextDescriptions);
 };
diff --git a/media/libstagefright/webm/Android.mk b/media/libstagefright/webm/Android.mk
index bc53c56..ce580ae 100644
--- a/media/libstagefright/webm/Android.mk
+++ b/media/libstagefright/webm/Android.mk
@@ -5,6 +5,7 @@
 
 LOCAL_CFLAGS += -Werror -Wall
 LOCAL_CLANG := true
+LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow
 
 LOCAL_SRC_FILES:= EbmlUtil.cpp        \
                   WebmElement.cpp     \
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
index b6de0d9..580d8c1 100644
--- a/media/mediaserver/Android.mk
+++ b/media/mediaserver/Android.mk
@@ -53,4 +53,6 @@
 LOCAL_MODULE:= mediaserver
 LOCAL_32_BIT_ONLY := true
 
+LOCAL_INIT_RC := mediaserver.rc
+
 include $(BUILD_EXECUTABLE)
diff --git a/media/mediaserver/mediaserver.rc b/media/mediaserver/mediaserver.rc
new file mode 100644
index 0000000..89c3896
--- /dev/null
+++ b/media/mediaserver/mediaserver.rc
@@ -0,0 +1,5 @@
+service media /system/bin/mediaserver
+    class main
+    user media
+    group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
+    ioprio rt 4
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index 052b700..d0ec2a6 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -25,8 +25,6 @@
 #include "MtpDataPacket.h"
 #include "MtpStringBuffer.h"
 
-#define MTP_BUFFER_SIZE 16384
-
 namespace android {
 
 MtpDataPacket::MtpDataPacket()
@@ -525,16 +523,9 @@
 int MtpDataPacket::write(struct usb_request *request) {
     MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
     MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
-
-    // send header separately from data
     request->buffer = mBuffer;
-    request->buffer_length = MTP_CONTAINER_HEADER_SIZE;
+    request->buffer_length = mPacketSize;
     int ret = transfer(request);
-    if (ret == MTP_CONTAINER_HEADER_SIZE) {
-        request->buffer = mBuffer + MTP_CONTAINER_HEADER_SIZE;
-        request->buffer_length = mPacketSize - MTP_CONTAINER_HEADER_SIZE;
-        ret = transfer(request);
-    }
     return (ret < 0 ? ret : 0);
 }
 
@@ -547,17 +538,17 @@
 
 #endif // MTP_HOST
 
-void* MtpDataPacket::getData(int& outLength) const {
+void* MtpDataPacket::getData(int* outLength) const {
     int length = mPacketSize - MTP_CONTAINER_HEADER_SIZE;
     if (length > 0) {
         void* result = malloc(length);
         if (result) {
             memcpy(result, mBuffer + MTP_CONTAINER_HEADER_SIZE, length);
-            outLength = length;
+            *outLength = length;
             return result;
         }
     }
-    outLength = 0;
+    *outLength = 0;
     return NULL;
 }
 
diff --git a/media/mtp/MtpDataPacket.h b/media/mtp/MtpDataPacket.h
index 13d3bd9..6240f28 100644
--- a/media/mtp/MtpDataPacket.h
+++ b/media/mtp/MtpDataPacket.h
@@ -117,7 +117,7 @@
 
     inline bool         hasData() const { return mPacketSize > MTP_CONTAINER_HEADER_SIZE; }
     inline uint32_t     getContainerLength() const { return MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET); }
-    void*               getData(int& outLength) const;
+    void*               getData(int* outLength) const;
 };
 
 }; // namespace android
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index 3eafd6f..9878f90 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -19,6 +19,7 @@
 #include "MtpDebug.h"
 #include "MtpDevice.h"
 #include "MtpDeviceInfo.h"
+#include "MtpEventPacket.h"
 #include "MtpObjectInfo.h"
 #include "MtpProperty.h"
 #include "MtpStorageInfo.h"
@@ -50,6 +51,15 @@
 }
 #endif
 
+namespace {
+
+bool writeToFd(void* data, int /* unused_offset */, int length, void* clientData) {
+    const int fd = *static_cast<int*>(clientData);
+    return write(fd, data, length) == length;
+}
+
+}
+
 MtpDevice* MtpDevice::open(const char* deviceName, int fd) {
     struct usb_device *device = usb_device_new(deviceName, fd);
     if (!device) {
@@ -414,7 +424,7 @@
     if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) {
         MtpResponseCode ret = readResponse();
         if (ret == MTP_RESPONSE_OK) {
-            return mData.getData(outLength);
+            return mData.getData(&outLength);
         }
     }
     outLength = 0;
@@ -430,8 +440,9 @@
         parent = MTP_PARENT_ROOT;
 
     mRequest.setParameter(1, info->mStorageID);
-    mRequest.setParameter(2, info->mParent);
+    mRequest.setParameter(2, parent);
 
+    mData.reset();
     mData.putUInt32(info->mStorageID);
     mData.putUInt16(info->mFormat);
     mData.putUInt16(info->mProtectionStatus);
@@ -472,17 +483,18 @@
     return (MtpObjectHandle)-1;
 }
 
-bool MtpDevice::sendObject(MtpObjectInfo* info, int srcFD) {
+bool MtpDevice::sendObject(MtpObjectHandle handle, int size, int srcFD) {
     Mutex::Autolock autoLock(mMutex);
 
-    int remaining = info->mCompressedSize;
+    int remaining = size;
     mRequest.reset();
-    mRequest.setParameter(1, info->mHandle);
+    mRequest.setParameter(1, handle);
     if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
         // send data header
         writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining);
 
-        char buffer[65536];
+        // USB writes greater than 16K don't work
+        char buffer[MTP_BUFFER_SIZE];
         while (remaining > 0) {
             int count = read(srcFD, buffer, sizeof(buffer));
             if (count > 0) {
@@ -592,97 +604,12 @@
 }
 
 bool MtpDevice::readObject(MtpObjectHandle handle,
-        bool (* callback)(void* data, int offset, int length, void* clientData),
-        size_t objectSize, void* clientData) {
-    Mutex::Autolock autoLock(mMutex);
-    bool result = false;
-
-    mRequest.reset();
-    mRequest.setParameter(1, handle);
-    if (sendRequest(MTP_OPERATION_GET_OBJECT)
-            && mData.readDataHeader(mRequestIn1)) {
-        uint32_t length = mData.getContainerLength();
-        if (length - MTP_CONTAINER_HEADER_SIZE != objectSize) {
-            ALOGE("readObject error objectSize: %d, length: %d",
-                    objectSize, length);
-            goto fail;
-        }
-        length -= MTP_CONTAINER_HEADER_SIZE;
-        uint32_t remaining = length;
-        int offset = 0;
-
-        int initialDataLength = 0;
-        void* initialData = mData.getData(initialDataLength);
-        if (initialData) {
-            if (initialDataLength > 0) {
-                if (!callback(initialData, 0, initialDataLength, clientData))
-                    goto fail;
-                remaining -= initialDataLength;
-                offset += initialDataLength;
-            }
-            free(initialData);
-        }
-
-        // USB reads greater than 16K don't work
-        char buffer1[16384], buffer2[16384];
-        mRequestIn1->buffer = buffer1;
-        mRequestIn2->buffer = buffer2;
-        struct usb_request* req = mRequestIn1;
-        void* writeBuffer = NULL;
-        int writeLength = 0;
-
-        while (remaining > 0 || writeBuffer) {
-            if (remaining > 0) {
-                // queue up a read request
-                req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
-                if (mData.readDataAsync(req)) {
-                    ALOGE("readDataAsync failed");
-                    goto fail;
-                }
-            } else {
-                req = NULL;
-            }
-
-            if (writeBuffer) {
-                // write previous buffer
-                if (!callback(writeBuffer, offset, writeLength, clientData)) {
-                    ALOGE("write failed");
-                    // wait for pending read before failing
-                    if (req)
-                        mData.readDataWait(mDevice);
-                    goto fail;
-                }
-                offset += writeLength;
-                writeBuffer = NULL;
-            }
-
-            // wait for read to complete
-            if (req) {
-                int read = mData.readDataWait(mDevice);
-                if (read < 0)
-                    goto fail;
-
-                if (read > 0) {
-                    writeBuffer = req->buffer;
-                    writeLength = read;
-                    remaining -= read;
-                    req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
-                } else {
-                    writeBuffer = NULL;
-                }
-            }
-        }
-
-        MtpResponseCode response = readResponse();
-        if (response == MTP_RESPONSE_OK)
-            result = true;
-    }
-
-fail:
-    return result;
+                           ReadObjectCallback callback,
+                           size_t expectedLength,
+                           void* clientData) {
+    return readObjectInternal(handle, callback, &expectedLength, clientData);
 }
 
-
 // reads the object's data and writes it to the specified file path
 bool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) {
     ALOGD("readObject: %s", destPath);
@@ -698,89 +625,105 @@
     fchmod(fd, perm);
     umask(mask);
 
+    bool result = readObject(handle, fd);
+    ::close(fd);
+    return result;
+}
+
+bool MtpDevice::readObject(MtpObjectHandle handle, int fd) {
+    ALOGD("readObject: %d", fd);
+    return readObjectInternal(handle, writeToFd, NULL /* expected size */, &fd);
+}
+
+bool MtpDevice::readObjectInternal(MtpObjectHandle handle,
+                                   ReadObjectCallback callback,
+                                   const size_t* expectedLength,
+                                   void* clientData) {
     Mutex::Autolock autoLock(mMutex);
-    bool result = false;
 
     mRequest.reset();
     mRequest.setParameter(1, handle);
-    if (sendRequest(MTP_OPERATION_GET_OBJECT)
-            && mData.readDataHeader(mRequestIn1)) {
-        uint32_t length = mData.getContainerLength();
-        if (length < MTP_CONTAINER_HEADER_SIZE)
-            goto fail;
-        length -= MTP_CONTAINER_HEADER_SIZE;
-        uint32_t remaining = length;
+    if (!sendRequest(MTP_OPERATION_GET_OBJECT)) {
+        ALOGE("Failed to send a read request.");
+        return false;
+    }
 
+    if (!mData.readDataHeader(mRequestIn1)) {
+        ALOGE("Failed to read header.");
+        return false;
+    }
+
+    const uint32_t fullLength = mData.getContainerLength();
+    if ((!expectedLength && fullLength < MTP_CONTAINER_HEADER_SIZE) ||
+        (expectedLength && *expectedLength + MTP_CONTAINER_HEADER_SIZE != fullLength)) {
+        ALOGE("readObject error length: %d", fullLength);
+        return false;
+    }
+
+    const uint32_t length = fullLength - MTP_CONTAINER_HEADER_SIZE;
+    uint32_t offset = 0;
+    bool writingError = false;
+
+    {
         int initialDataLength = 0;
-        void* initialData = mData.getData(initialDataLength);
+        void* const initialData = mData.getData(&initialDataLength);
         if (initialData) {
             if (initialDataLength > 0) {
-                if (write(fd, initialData, initialDataLength) != initialDataLength) {
-                    free(initialData);
-                    goto fail;
+                if (!callback(initialData, offset, initialDataLength, clientData)) {
+                    ALOGE("Failed to write initial data.");
+                    writingError = true;
                 }
-                remaining -= initialDataLength;
+                offset += initialDataLength;
             }
             free(initialData);
         }
+    }
 
-        // USB reads greater than 16K don't work
-        char buffer1[16384], buffer2[16384];
-        mRequestIn1->buffer = buffer1;
-        mRequestIn2->buffer = buffer2;
-        struct usb_request* req = mRequestIn1;
+    // USB reads greater than 16K don't work.
+    char buffer1[MTP_BUFFER_SIZE], buffer2[MTP_BUFFER_SIZE];
+    mRequestIn1->buffer = buffer1;
+    mRequestIn2->buffer = buffer2;
+    struct usb_request* req = NULL;
+
+    while (offset < length) {
+        // Wait for previous read to complete.
         void* writeBuffer = NULL;
         int writeLength = 0;
-
-        while (remaining > 0 || writeBuffer) {
-            if (remaining > 0) {
-                // queue up a read request
-                req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
-                if (mData.readDataAsync(req)) {
-                    ALOGE("readDataAsync failed");
-                    goto fail;
-                }
-            } else {
-                req = NULL;
+        if (req) {
+            const int read = mData.readDataWait(mDevice);
+            if (read < 0) {
+                ALOGE("readDataWait failed.");
+                return false;
             }
+            writeBuffer = req->buffer;
+            writeLength = read;
+        }
 
-            if (writeBuffer) {
-                // write previous buffer
-                if (write(fd, writeBuffer, writeLength) != writeLength) {
-                    ALOGE("write failed");
-                    // wait for pending read before failing
-                    if (req)
-                        mData.readDataWait(mDevice);
-                    goto fail;
-                }
-                writeBuffer = NULL;
-            }
-
-            // wait for read to complete
-            if (req) {
-                int read = mData.readDataWait(mDevice);
-                if (read < 0)
-                    goto fail;
-
-                if (read > 0) {
-                    writeBuffer = req->buffer;
-                    writeLength = read;
-                    remaining -= read;
-                    req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
-                } else {
-                    writeBuffer = NULL;
-                }
+        // Request to read next chunk.
+        const uint32_t nextOffset = offset + writeLength;
+        if (nextOffset < length) {
+            // Queue up a read request.
+            const size_t remaining = length - nextOffset;
+            req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
+            req->buffer_length =
+                    remaining > MTP_BUFFER_SIZE ? static_cast<size_t>(MTP_BUFFER_SIZE) : remaining;
+            if (mData.readDataAsync(req) != 0) {
+                ALOGE("readDataAsync failed");
+                return false;
             }
         }
 
-        MtpResponseCode response = readResponse();
-        if (response == MTP_RESPONSE_OK)
-            result = true;
+        // Write previous buffer.
+        if (writeBuffer && !writingError) {
+            if (!callback(writeBuffer, offset, writeLength, clientData)) {
+                ALOGE("write failed");
+                writingError = true;
+            }
+        }
+        offset = nextOffset;
     }
 
-fail:
-    ::close(fd);
-    return result;
+    return readResponse() == MTP_RESPONSE_OK && !writingError;
 }
 
 bool MtpDevice::sendRequest(MtpOperationCode operation) {
@@ -800,7 +743,7 @@
     mData.setTransactionID(mRequest.getTransactionID());
     int ret = mData.write(mRequestOut);
     mData.dump();
-    return (ret > 0);
+    return (ret >= 0);
 }
 
 bool MtpDevice::readData() {
diff --git a/media/mtp/MtpDevice.h b/media/mtp/MtpDevice.h
index 9b0acbf..d2c6d67 100644
--- a/media/mtp/MtpDevice.h
+++ b/media/mtp/MtpDevice.h
@@ -60,6 +60,7 @@
     Mutex                   mMutex;
 
 public:
+    typedef bool (*ReadObjectCallback)(void* data, int offset, int length, void* clientData);
                             MtpDevice(struct usb_device* device, int interface,
                                     const struct usb_endpoint_descriptor *ep_in,
                                     const struct usb_endpoint_descriptor *ep_out,
@@ -85,7 +86,7 @@
     MtpObjectInfo*          getObjectInfo(MtpObjectHandle handle);
     void*                   getThumbnail(MtpObjectHandle handle, int& outLength);
     MtpObjectHandle         sendObjectInfo(MtpObjectInfo* info);
-    bool                    sendObject(MtpObjectInfo* info, int srcFD);
+    bool                    sendObject(MtpObjectHandle handle, int size, int srcFD);
     bool                    deleteObject(MtpObjectHandle handle);
     MtpObjectHandle         getParent(MtpObjectHandle handle);
     MtpObjectHandle         getStorageID(MtpObjectHandle handle);
@@ -95,14 +96,16 @@
     MtpProperty*            getDevicePropDesc(MtpDeviceProperty code);
     MtpProperty*            getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format);
 
-    bool                    readObject(MtpObjectHandle handle,
-                                    bool (* callback)(void* data, int offset,
-                                            int length, void* clientData),
+    bool                    readObject(MtpObjectHandle handle, ReadObjectCallback callback,
                                     size_t objectSize, void* clientData);
     bool                    readObject(MtpObjectHandle handle, const char* destPath, int group,
                                     int perm);
+    bool                    readObject(MtpObjectHandle handle, int fd);
 
 private:
+    // If |objectSize| is not NULL, it checks object size before reading data bytes.
+    bool                    readObjectInternal(MtpObjectHandle handle, ReadObjectCallback callback,
+                                     const size_t* objectSize, void* clientData);
     bool                    sendRequest(MtpOperationCode operation);
     bool                    sendData();
     bool                    readData();
diff --git a/media/mtp/mtp.h b/media/mtp/mtp.h
index d270df5..7b80d2e 100644
--- a/media/mtp/mtp.h
+++ b/media/mtp/mtp.h
@@ -37,6 +37,9 @@
 #define MTP_CONTAINER_PARAMETER_OFFSET          12
 #define MTP_CONTAINER_HEADER_SIZE               12
 
+// Maximum buffer size for a MTP packet.
+#define MTP_BUFFER_SIZE 16384
+
 // MTP Data Types
 #define MTP_TYPE_UNDEFINED      0x0000          // Undefined
 #define MTP_TYPE_INT8           0x0001          // Signed 8-bit integer
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index a354d58..5598d5d 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -46,6 +46,10 @@
     ALOGV("private ctor");
     AMediaFormat* mData = new AMediaFormat();
     mData->mFormat = *((sp<AMessage>*)data);
+    if (mData->mFormat == NULL) {
+        ALOGW("got NULL format");
+        mData->mFormat = new AMessage;
+    }
     return mData;
 }
 
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 9ec5802..fab1ef5 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1352,12 +1352,16 @@
 AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
     :   RefBase(),
         mAudioFlinger(audioFlinger),
-        // FIXME should be a "k" constant not hard-coded, in .h or ro. property, see 4 lines below
-        mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
         mPid(pid),
         mTimedTrackCount(0)
 {
-    // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
+    size_t heapSize = kClientSharedHeapSizeBytes;
+    // Increase heap size on non low ram devices to limit risk of reconnection failure for
+    // invalidated tracks
+    if (!audioFlinger->isLowRamDevice()) {
+        heapSize *= kClientSharedHeapSizeMultiplier;
+    }
+    mMemoryDealer = new MemoryDealer(heapSize, "AudioFlinger::Client");
 }
 
 // Client destructor must be called with AudioFlinger::mClientLock held
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 20c34ef..08fa70d 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -88,6 +88,12 @@
 
 static const nsecs_t kDefaultStandbyTimeInNsecs = seconds(3);
 
+
+// Max shared memory size for audio tracks and audio records per client process
+static const size_t kClientSharedHeapSizeBytes = 1024*1024;
+// Shared memory size multiplier for non low ram devices
+static const size_t kClientSharedHeapSizeMultiplier = 4;
+
 #define INCLUDING_FROM_AUDIOFLINGER_H
 
 class AudioFlinger :
@@ -423,7 +429,7 @@
                             Client(const Client&);
                             Client& operator = (const Client&);
         const sp<AudioFlinger> mAudioFlinger;
-        const sp<MemoryDealer> mMemoryDealer;
+              sp<MemoryDealer> mMemoryDealer;
         const pid_t         mPid;
 
         Mutex               mTimedTrackLock;
diff --git a/services/audioflinger/BufferProviders.cpp b/services/audioflinger/BufferProviders.cpp
index 3566ee2..a8be206 100644
--- a/services/audioflinger/BufferProviders.cpp
+++ b/services/audioflinger/BufferProviders.cpp
@@ -386,34 +386,37 @@
 
     // need to fetch more data
     const size_t outputDesired = pBuffer->frameCount - mRemaining;
-    mBuffer.frameCount = mPlaybackRate.mSpeed == AUDIO_TIMESTRETCH_SPEED_NORMAL
-            ? outputDesired : outputDesired * mPlaybackRate.mSpeed + 1;
+    size_t dstAvailable;
+    do {
+        mBuffer.frameCount = mPlaybackRate.mSpeed == AUDIO_TIMESTRETCH_SPEED_NORMAL
+                ? outputDesired : outputDesired * mPlaybackRate.mSpeed + 1;
 
-    status_t res = mTrackBufferProvider->getNextBuffer(&mBuffer, pts);
+        status_t res = mTrackBufferProvider->getNextBuffer(&mBuffer, pts);
 
-    ALOG_ASSERT(res == OK || mBuffer.frameCount == 0);
-    if (res != OK || mBuffer.frameCount == 0) { // not needed by API spec, but to be safe.
-        ALOGD("buffer error");
-        if (mRemaining == 0) {
-            pBuffer->raw = NULL;
-            pBuffer->frameCount = 0;
-            return res;
-        } else { // return partial count
-            pBuffer->raw = mLocalBufferData;
-            pBuffer->frameCount = mRemaining;
-            return OK;
+        ALOG_ASSERT(res == OK || mBuffer.frameCount == 0);
+        if (res != OK || mBuffer.frameCount == 0) { // not needed by API spec, but to be safe.
+            ALOGV("upstream provider cannot provide data");
+            if (mRemaining == 0) {
+                pBuffer->raw = NULL;
+                pBuffer->frameCount = 0;
+                return res;
+            } else { // return partial count
+                pBuffer->raw = mLocalBufferData;
+                pBuffer->frameCount = mRemaining;
+                return OK;
+            }
         }
-    }
 
-    // time-stretch the data
-    size_t dstAvailable = min(mLocalBufferFrameCount - mRemaining, outputDesired);
-    size_t srcAvailable = mBuffer.frameCount;
-    processFrames((uint8_t*)mLocalBufferData + mRemaining * mFrameSize, &dstAvailable,
-            mBuffer.raw, &srcAvailable);
+        // time-stretch the data
+        dstAvailable = min(mLocalBufferFrameCount - mRemaining, outputDesired);
+        size_t srcAvailable = mBuffer.frameCount;
+        processFrames((uint8_t*)mLocalBufferData + mRemaining * mFrameSize, &dstAvailable,
+                mBuffer.raw, &srcAvailable);
 
-    // release all data consumed
-    mBuffer.frameCount = srcAvailable;
-    mTrackBufferProvider->releaseBuffer(&mBuffer);
+        // release all data consumed
+        mBuffer.frameCount = srcAvailable;
+        mTrackBufferProvider->releaseBuffer(&mBuffer);
+    } while (dstAvailable == 0); // try until we get output data or upstream provider fails.
 
     // update buffer vars with the actual data processed and return with buffer
     mRemaining += dstAvailable;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 0a7d4a2..151f662 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -832,8 +832,8 @@
     dprintf(fd, "  Channel count: %u\n", mChannelCount);
     dprintf(fd, "  Channel mask: 0x%08x (%s)\n", mChannelMask,
             channelMaskToString(mChannelMask, mType != RECORD).string());
-    dprintf(fd, "  Format: 0x%x (%s)\n", mFormat, formatToString(mFormat));
-    dprintf(fd, "  Frame size: %zu bytes\n", mFrameSize);
+    dprintf(fd, "  Processing format: 0x%x (%s)\n", mFormat, formatToString(mFormat));
+    dprintf(fd, "  Processing frame size: %zu bytes\n", mFrameSize);
     dprintf(fd, "  Pending config events:");
     size_t numConfig = mConfigEvents.size();
     if (numConfig) {
@@ -3479,6 +3479,12 @@
         if (state->mCommand != FastMixerState::MIX_WRITE &&
                 (kUseFastMixer != FastMixer_Dynamic || state->mTrackMask > 1)) {
             if (state->mCommand == FastMixerState::COLD_IDLE) {
+
+                // FIXME workaround for first HAL write being CPU bound on some devices
+                ATRACE_BEGIN("write");
+                mOutput->write((char *)mSinkBuffer, 0);
+                ATRACE_END();
+
                 int32_t old = android_atomic_inc(&mFastMixerFutex);
                 if (old == -1) {
                     (void) syscall(__NR_futex, &mFastMixerFutex, FUTEX_WAKE_PRIVATE, 1);
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index f7da209..b3fac0b 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -432,7 +432,10 @@
     }
     // only allocate a fast track index if we were able to allocate a normal track name
     if (flags & IAudioFlinger::TRACK_FAST) {
-        mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
+        // FIXME: Not calling framesReadyIsCalledByMultipleThreads() exposes a potential
+        // race with setSyncEvent(). However, if we call it, we cannot properly start
+        // static fast tracks (SoundPool) immediately after stopping.
+        //mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
         ALOG_ASSERT(thread->mFastTrackAvailMask != 0);
         int i = __builtin_ctz(thread->mFastTrackAvailMask);
         ALOG_ASSERT(0 < i && i < (int)FastMixerState::kMaxFastTracks);
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 8523fc5..c1e7bc0 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -64,6 +64,7 @@
         API_INPUT_MIX_EXT_POLICY_REROUTE,// used for platform audio rerouting, where mixes are
                                          // handled by external and dynamically installed
                                          // policies which reroute audio mixes
+        API_INPUT_TELEPHONY_RX, // used for capture from telephony RX path
     } input_type_t;
 
 public:
diff --git a/services/audiopolicy/enginedefault/src/Gains.cpp b/services/audiopolicy/enginedefault/src/Gains.cpp
index 78f2909..d06365c 100644
--- a/services/audiopolicy/enginedefault/src/Gains.cpp
+++ b/services/audiopolicy/enginedefault/src/Gains.cpp
@@ -171,10 +171,10 @@
     },
     { // AUDIO_STREAM_TTS
       // "Transmitted Through Speaker": always silent except on DEVICE_CATEGORY_SPEAKER
-        Gains::sSilentVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        Gains::sLinearVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        Gains::sSilentVolumeCurve, // DEVICE_CATEGORY_EARPIECE
-        Gains::sSilentVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+        Gains::sSilentVolumeCurve,    // DEVICE_CATEGORY_HEADSET
+        Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        Gains::sSilentVolumeCurve,    // DEVICE_CATEGORY_EARPIECE
+        Gains::sSilentVolumeCurve     // DEVICE_CATEGORY_EXT_MEDIA
     },
     { // AUDIO_STREAM_ACCESSIBILITY
         Gains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 7530dcc..be648bc 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1066,7 +1066,7 @@
     *delayMs = 0;
     if (stream == AUDIO_STREAM_TTS) {
         ALOGV("\t found BEACON stream");
-        if (mOutputs.isAnyOutputActive(AUDIO_STREAM_TTS /*streamToIgnore*/)) {
+        if (!mTtsOutputAvailable && mOutputs.isAnyOutputActive(AUDIO_STREAM_TTS /*streamToIgnore*/)) {
             return INVALID_OPERATION;
         } else {
             beaconMuteLatency = handleEventForBeacon(STARTING_BEACON);
@@ -1351,23 +1351,12 @@
         } else if (audio_is_remote_submix_device(device)) {
             address = String8("0");
             *inputType = API_INPUT_MIX_CAPTURE;
+        } else if (device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
+            *inputType = API_INPUT_TELEPHONY_RX;
         } else {
             *inputType = API_INPUT_LEGACY;
         }
-        // adapt channel selection to input source
-        switch (inputSource) {
-        case AUDIO_SOURCE_VOICE_UPLINK:
-            channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK;
-            break;
-        case AUDIO_SOURCE_VOICE_DOWNLINK:
-            channelMask = AUDIO_CHANNEL_IN_VOICE_DNLINK;
-            break;
-        case AUDIO_SOURCE_VOICE_CALL:
-            channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK;
-            break;
-        default:
-            break;
-        }
+
         if (inputSource == AUDIO_SOURCE_HOTWORD) {
             ssize_t index = mSoundTriggerSessions.indexOfKey(session);
             if (index >= 0) {
@@ -1998,6 +1987,9 @@
     snprintf(buffer, SIZE, " Force use for hdmi system audio %d\n",
             mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO));
     result.append(buffer);
+    snprintf(buffer, SIZE, " TTS output %s\n", mTtsOutputAvailable ? "available" : "not available");
+    result.append(buffer);
+
     write(fd, result.string(), result.size());
 
     mAvailableOutputDevices.dump(fd, String8("output"));
@@ -2678,7 +2670,8 @@
     mAudioPortGeneration(1),
     mBeaconMuteRefCount(0),
     mBeaconPlayingRefCount(0),
-    mBeaconMuted(false)
+    mBeaconMuted(false),
+    mTtsOutputAvailable(false)
 {
     audio_policy::EngineInstance *engineInstance = audio_policy::EngineInstance::getInstance();
     if (!engineInstance) {
@@ -2735,6 +2728,9 @@
                 ALOGW("Output profile contains no device on module %s", mHwModules[i]->mName);
                 continue;
             }
+            if ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_TTS) != 0) {
+                mTtsOutputAvailable = true;
+            }
 
             if ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
                 continue;
@@ -2854,8 +2850,12 @@
                     ssize_t index =
                             mAvailableInputDevices.indexOf(inProfile->mSupportedDevices[k]);
                     // give a valid ID to an attached device once confirmed it is reachable
-                    if (index >= 0 && !mAvailableInputDevices[index]->isAttached()) {
-                        mAvailableInputDevices[index]->attach(mHwModules[i]);
+                    if (index >= 0) {
+                        sp<DeviceDescriptor> devDesc = mAvailableInputDevices[index];
+                        if (!devDesc->isAttached()) {
+                            devDesc->attach(mHwModules[i]);
+                            devDesc->importAudioPort(inProfile);
+                        }
                     }
                 }
                 mpClientInterface->closeInput(input);
@@ -4030,6 +4030,12 @@
 }
 
 uint32_t AudioPolicyManager::handleEventForBeacon(int event) {
+
+    // skip beacon mute management if a dedicated TTS output is available
+    if (mTtsOutputAvailable) {
+        return 0;
+    }
+
     switch(event) {
     case STARTING_OUTPUT:
         mBeaconMuteRefCount++;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index bf3ae4a..bbdf396 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -548,6 +548,7 @@
         uint32_t mBeaconMuteRefCount;   // ref count for stream that would mute beacon
         uint32_t mBeaconPlayingRefCount;// ref count for the playing beacon streams
         bool mBeaconMuted;              // has STREAM_TTS been muted
+        bool mTtsOutputAvailable;       // true if a dedicated output for TTS stream is available
 
         AudioPolicyMixCollection mPolicyMixes; // list of registered mixes
 
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 65639c3..793c26a 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -303,6 +303,8 @@
             switch (inputType) {
             case AudioPolicyInterface::API_INPUT_LEGACY:
                 break;
+            case AudioPolicyInterface::API_INPUT_TELEPHONY_RX:
+                // FIXME: use the same permission as for remote submix for now.
             case AudioPolicyInterface::API_INPUT_MIX_CAPTURE:
                 if (!captureAudioOutputAllowed()) {
                     ALOGE("getInputForAttr() permission denied: capture not allowed");
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index eefff3d..619e5c1 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -149,7 +149,10 @@
 // connects to AudioPolicyService.
 void AudioPolicyService::registerClient(const sp<IAudioPolicyServiceClient>& client)
 {
-
+    if (client == 0) {
+        ALOGW("%s got NULL client", __FUNCTION__);
+        return;
+    }
     Mutex::Autolock _l(mNotificationClientsLock);
 
     uid_t uid = IPCThreadState::self()->getCallingUid();
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 92df4e3..2aaefe9 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -15,6 +15,7 @@
  */
 
 #define LOG_TAG "CameraService"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
 //#define LOG_NDEBUG 0
 
 #include <algorithm>
@@ -33,7 +34,6 @@
 #include <binder/MemoryBase.h>
 #include <binder/MemoryHeapBase.h>
 #include <binder/ProcessInfoService.h>
-#include <camera/ICameraServiceProxy.h>
 #include <cutils/atomic.h>
 #include <cutils/properties.h>
 #include <gui/Surface.h>
@@ -157,7 +157,6 @@
     }
 
     mModule = new CameraModule(rawModule);
-    ALOGI("Loaded \"%s\" camera module", mModule->getModuleName());
     err = mModule->init();
     if (err != OK) {
         ALOGE("Could not initialize camera HAL module: %d (%s)", err,
@@ -169,8 +168,10 @@
         mModule = nullptr;
         return;
     }
+    ALOGI("Loaded \"%s\" camera module", mModule->getModuleName());
 
     mNumberOfCameras = mModule->getNumberOfCameras();
+    mNumberOfNormalCameras = mNumberOfCameras;
 
     mFlashlight = new CameraFlashlight(*mModule, *this);
     status_t res = mFlashlight->findFlashUnits();
@@ -179,27 +180,41 @@
         ALOGE("Failed to find flash units.");
     }
 
+    int latestStrangeCameraId = INT_MAX;
     for (int i = 0; i < mNumberOfCameras; i++) {
         String8 cameraId = String8::format("%d", i);
 
+        // Get camera info
+
+        struct camera_info info;
+        bool haveInfo = true;
+        status_t rc = mModule->getCameraInfo(i, &info);
+        if (rc != NO_ERROR) {
+            ALOGE("%s: Received error loading camera info for device %d, cost and"
+                    " conflicting devices fields set to defaults for this device.",
+                    __FUNCTION__, i);
+            haveInfo = false;
+        }
+
+        // Check for backwards-compatibility support
+        if (haveInfo) {
+            if (checkCameraCapabilities(i, info, &latestStrangeCameraId) != OK) {
+                delete mModule;
+                mModule = nullptr;
+                return;
+            }
+        }
+
         // Defaults to use for cost and conflicting devices
         int cost = 100;
         char** conflicting_devices = nullptr;
         size_t conflicting_devices_length = 0;
 
         // If using post-2.4 module version, query the cost + conflicting devices from the HAL
-        if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4) {
-            struct camera_info info;
-            status_t rc = mModule->getCameraInfo(i, &info);
-            if (rc == NO_ERROR) {
-                cost = info.resource_cost;
-                conflicting_devices = info.conflicting_devices;
-                conflicting_devices_length = info.conflicting_devices_length;
-            } else {
-                ALOGE("%s: Received error loading camera info for device %d, cost and"
-                        " conflicting devices fields set to defaults for this device.",
-                        __FUNCTION__, i);
-            }
+        if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 && haveInfo) {
+            cost = info.resource_cost;
+            conflicting_devices = info.conflicting_devices;
+            conflicting_devices_length = info.conflicting_devices_length;
         }
 
         std::set<String8> conflicting;
@@ -235,13 +250,19 @@
     CameraService::pingCameraServiceProxy();
 }
 
-void CameraService::pingCameraServiceProxy() {
+sp<ICameraServiceProxy> CameraService::getCameraServiceProxy() {
     sp<IServiceManager> sm = defaultServiceManager();
     sp<IBinder> binder = sm->getService(String16("media.camera.proxy"));
     if (binder == nullptr) {
-        return;
+        return nullptr;
     }
     sp<ICameraServiceProxy> proxyBinder = interface_cast<ICameraServiceProxy>(binder);
+    return proxyBinder;
+}
+
+void CameraService::pingCameraServiceProxy() {
+    sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
+    if (proxyBinder == nullptr) return;
     proxyBinder->pingForUserUpdate();
 }
 
@@ -348,7 +369,7 @@
 
     {
         // Update battery life logging for flashlight
-        Mutex::Autolock al(mTorchClientMapMutex);
+        Mutex::Autolock al(mTorchUidMapMutex);
         auto iter = mTorchUidMap.find(cameraId);
         if (iter != mTorchUidMap.end()) {
             int oldUid = iter->second.second;
@@ -382,13 +403,28 @@
     }
 }
 
-
 int32_t CameraService::getNumberOfCameras() {
-    return mNumberOfCameras;
+    ATRACE_CALL();
+    return getNumberOfCameras(CAMERA_TYPE_BACKWARD_COMPATIBLE);
+}
+
+int32_t CameraService::getNumberOfCameras(int type) {
+    ATRACE_CALL();
+    switch (type) {
+        case CAMERA_TYPE_BACKWARD_COMPATIBLE:
+            return mNumberOfNormalCameras;
+        case CAMERA_TYPE_ALL:
+            return mNumberOfCameras;
+        default:
+            ALOGW("%s: Unknown camera type %d, returning 0",
+                    __FUNCTION__, type);
+            return 0;
+    }
 }
 
 status_t CameraService::getCameraInfo(int cameraId,
                                       struct CameraInfo* cameraInfo) {
+    ATRACE_CALL();
     if (!mModule) {
         return -ENODEV;
     }
@@ -416,6 +452,7 @@
 }
 
 status_t CameraService::generateShimMetadata(int cameraId, /*out*/CameraMetadata* cameraInfo) {
+    ATRACE_CALL();
     status_t ret = OK;
     struct CameraInfo info;
     if ((ret = getCameraInfo(cameraId, &info)) != OK) {
@@ -502,6 +539,7 @@
 
 status_t CameraService::getCameraCharacteristics(int cameraId,
                                                 CameraMetadata* cameraInfo) {
+    ATRACE_CALL();
     if (!cameraInfo) {
         ALOGE("%s: cameraInfo is NULL", __FUNCTION__);
         return BAD_VALUE;
@@ -570,10 +608,16 @@
                 procState);
         return -1;
     }
+    // Treat sleeping TOP processes the same as regular TOP processes, for
+    // access priority.  This is important for lock-screen camera launch scenarios
+    if (procState == PROCESS_STATE_TOP_SLEEPING) {
+        procState = PROCESS_STATE_TOP;
+    }
     return INT_MAX - procState;
 }
 
 status_t CameraService::getCameraVendorTagDescriptor(/*out*/sp<VendorTagDescriptor>& desc) {
+    ATRACE_CALL();
     if (!mModule) {
         ALOGE("%s: camera hardware module doesn't exist", __FUNCTION__);
         return -ENODEV;
@@ -584,6 +628,7 @@
 }
 
 int CameraService::getDeviceVersion(int cameraId, int* facing) {
+    ATRACE_CALL();
     struct camera_info info;
     if (mModule->getCameraInfo(cameraId, &info) != OK) {
         return -1;
@@ -615,6 +660,7 @@
 }
 
 bool CameraService::setUpVendorTags() {
+    ATRACE_CALL();
     vendor_tag_ops_t vOps = vendor_tag_ops_t();
 
     // Check if vendor operations have been implemented
@@ -623,9 +669,7 @@
         return false;
     }
 
-    ATRACE_BEGIN("camera3->get_metadata_vendor_tag_ops");
     mModule->getVendorTagOps(&vOps);
-    ATRACE_END();
 
     // Ensure all vendor operations are present
     if (vOps.get_tag_count == NULL || vOps.get_all_tags == NULL ||
@@ -908,6 +952,16 @@
         LOG_ALWAYS_FATAL("%s: Invalid state for CameraService, clients not evicted properly",
                 __FUNCTION__);
     }
+
+    // And register a death notification for the client callback. Do
+    // this last to avoid Binder policy where a nested Binder
+    // transaction might be pre-empted to service the client death
+    // notification if the client process dies before linkToDeath is
+    // invoked.
+    sp<IBinder> remoteCallback = client->getRemote();
+    if (remoteCallback != nullptr) {
+        remoteCallback->linkToDeath(this);
+    }
 }
 
 status_t CameraService::handleEvictionsLocked(const String8& cameraId, int clientPid,
@@ -915,7 +969,7 @@
         /*out*/
         sp<BasicClient>* client,
         std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>* partial) {
-
+    ATRACE_CALL();
     status_t ret = NO_ERROR;
     std::vector<DescriptorPtr> evictedClients;
     DescriptorPtr clientDescriptor;
@@ -1104,6 +1158,7 @@
         /*out*/
         sp<ICamera>& device) {
 
+    ATRACE_CALL();
     status_t ret = NO_ERROR;
     String8 id = String8::format("%d", cameraId);
     sp<Client> client = nullptr;
@@ -1128,6 +1183,7 @@
         /*out*/
         sp<ICamera>& device) {
 
+    ATRACE_CALL();
     String8 id = String8::format("%d", cameraId);
     int apiVersion = mModule->getModuleApiVersion();
     if (halVersion != CAMERA_HAL_API_VERSION_UNSPECIFIED &&
@@ -1168,6 +1224,7 @@
         /*out*/
         sp<ICameraDeviceUser>& device) {
 
+    ATRACE_CALL();
     status_t ret = NO_ERROR;
     String8 id = String8::format("%d", cameraId);
     sp<CameraDeviceClient> client = nullptr;
@@ -1187,6 +1244,8 @@
 
 status_t CameraService::setTorchMode(const String16& cameraId, bool enabled,
         const sp<IBinder>& clientBinder) {
+
+    ATRACE_CALL();
     if (enabled && clientBinder == nullptr) {
         ALOGE("%s: torch client binder is NULL", __FUNCTION__);
         return -EINVAL;
@@ -1235,7 +1294,7 @@
     {
         // Update UID map - this is used in the torch status changed callbacks, so must be done
         // before setTorchMode
-        Mutex::Autolock al(mTorchClientMapMutex);
+        Mutex::Autolock al(mTorchUidMapMutex);
         if (mTorchUidMap.find(id) == mTorchUidMap.end()) {
             mTorchUidMap[id].first = uid;
             mTorchUidMap[id].second = uid;
@@ -1275,6 +1334,8 @@
 }
 
 void CameraService::notifySystemEvent(int32_t eventId, const int32_t* args, size_t length) {
+    ATRACE_CALL();
+
     switch(eventId) {
         case ICameraService::USER_SWITCHED: {
             doUserSwitch(/*newUserIds*/args, /*length*/length);
@@ -1290,6 +1351,8 @@
 }
 
 status_t CameraService::addListener(const sp<ICameraServiceListener>& listener) {
+    ATRACE_CALL();
+
     ALOGV("%s: Add listener %p", __FUNCTION__, listener.get());
 
     if (listener == nullptr) {
@@ -1338,6 +1401,8 @@
 }
 
 status_t CameraService::removeListener(const sp<ICameraServiceListener>& listener) {
+    ATRACE_CALL();
+
     ALOGV("%s: Remove listener %p", __FUNCTION__, listener.get());
 
     if (listener == 0) {
@@ -1364,6 +1429,8 @@
 }
 
 status_t CameraService::getLegacyParameters(int cameraId, /*out*/String16* parameters) {
+
+    ATRACE_CALL();
     ALOGV("%s: for camera ID = %d", __FUNCTION__, cameraId);
 
     if (parameters == NULL) {
@@ -1388,6 +1455,8 @@
 }
 
 status_t CameraService::supportsCameraApi(int cameraId, int apiVersion) {
+    ATRACE_CALL();
+
     ALOGV("%s: for camera ID = %d", __FUNCTION__, cameraId);
 
     switch (apiVersion) {
@@ -1494,6 +1563,53 @@
 }
 
 
+/**
+ * Check camera capabilities, such as support for basic color operation
+ */
+int CameraService::checkCameraCapabilities(int id, camera_info info, int *latestStrangeCameraId) {
+
+    // Assume all devices pre-v3.3 are backward-compatible
+    bool isBackwardCompatible = true;
+    if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_0
+            && info.device_version >= CAMERA_DEVICE_API_VERSION_3_3) {
+        isBackwardCompatible = false;
+        status_t res;
+        camera_metadata_ro_entry_t caps;
+        res = find_camera_metadata_ro_entry(
+            info.static_camera_characteristics,
+            ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
+            &caps);
+        if (res != 0) {
+            ALOGW("%s: Unable to find camera capabilities for camera device %d",
+                    __FUNCTION__, id);
+            caps.count = 0;
+        }
+        for (size_t i = 0; i < caps.count; i++) {
+            if (caps.data.u8[i] ==
+                    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) {
+                isBackwardCompatible = true;
+                break;
+            }
+        }
+    }
+
+    if (!isBackwardCompatible) {
+        mNumberOfNormalCameras--;
+        *latestStrangeCameraId = id;
+    } else {
+        if (id > *latestStrangeCameraId) {
+            ALOGE("%s: Normal camera ID %d higher than strange camera ID %d. "
+                    "This is not allowed due backward-compatibility requirements",
+                    __FUNCTION__, id, *latestStrangeCameraId);
+            logServiceError("Invalid order of camera devices", ENODEV);
+            mNumberOfCameras = 0;
+            mNumberOfNormalCameras = 0;
+            return INVALID_OPERATION;
+        }
+    }
+    return OK;
+}
+
 std::shared_ptr<CameraService::CameraState> CameraService::getCameraState(
         const String8& cameraId) const {
     std::shared_ptr<CameraState> state;
@@ -1708,6 +1824,8 @@
 }
 
 void CameraService::loadSound() {
+    ATRACE_CALL();
+
     Mutex::Autolock lock(mSoundLock);
     LOG1("CameraService::loadSound ref=%d", mSoundRef);
     if (mSoundRef++) return;
@@ -1730,6 +1848,8 @@
 }
 
 void CameraService::playSound(sound_kind kind) {
+    ATRACE_CALL();
+
     LOG1("playSound(%d)", kind);
     Mutex::Autolock lock(mSoundLock);
     sp<MediaPlayer> player = mSoundPlayer[kind];
@@ -1800,11 +1920,9 @@
 
 void CameraService::BasicClient::disconnect() {
     if (mDisconnected) {
-        ALOGE("%s: Disconnect called on already disconnected client for device %d", __FUNCTION__,
-                mCameraId);
         return;
     }
-    mDisconnected = true;;
+    mDisconnected = true;
 
     mCameraService->removeByClient(this);
     mCameraService->logDisconnected(String8::format("%d", mCameraId), mClientPid,
@@ -1841,6 +1959,8 @@
 }
 
 status_t CameraService::BasicClient::startCameraOps() {
+    ATRACE_CALL();
+
     int32_t res;
     // Notify app ops that the camera is not available
     mOpsCallback = new OpsCallback(this);
@@ -1874,10 +1994,16 @@
     mCameraService->updateStatus(ICameraServiceListener::STATUS_NOT_AVAILABLE,
             String8::format("%d", mCameraId));
 
+    // Transition device state to OPEN
+    mCameraService->updateProxyDeviceState(ICameraServiceProxy::CAMERA_STATE_OPEN,
+            String8::format("%d", mCameraId));
+
     return OK;
 }
 
 status_t CameraService::BasicClient::finishCameraOps() {
+    ATRACE_CALL();
+
     // Check if startCameraOps succeeded, and if so, finish the camera op
     if (mOpsActive) {
         // Notify app ops that the camera is available again
@@ -1892,6 +2018,10 @@
         mCameraService->updateStatus(ICameraServiceListener::STATUS_PRESENT,
                 String8::format("%d", mCameraId), rejected);
 
+        // Transition device state to CLOSED
+        mCameraService->updateProxyDeviceState(ICameraServiceProxy::CAMERA_STATE_CLOSED,
+                String8::format("%d", mCameraId));
+
         // Notify flashlight that a camera device is closed.
         mCameraService->mFlashlight->deviceClosed(
                 String8::format("%d", mCameraId));
@@ -1906,6 +2036,8 @@
 }
 
 void CameraService::BasicClient::opChanged(int32_t op, const String16& packageName) {
+    ATRACE_CALL();
+
     String8 name(packageName);
     String8 myName(mClientPackageName);
 
@@ -2129,9 +2261,11 @@
 }
 
 status_t CameraService::dump(int fd, const Vector<String16>& args) {
+    ATRACE_CALL();
+
     String8 result("Dump of the Camera Service:\n");
     if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
-        result.appendFormat("Permission Denial: "
+        result = result.format("Permission Denial: "
                 "can't dump CameraService from pid=%d, uid=%d\n",
                 getCallingPid(),
                 getCallingUid());
@@ -2392,6 +2526,14 @@
         });
 }
 
+void CameraService::updateProxyDeviceState(ICameraServiceProxy::CameraState newState,
+        const String8& cameraId) {
+    sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
+    if (proxyBinder == nullptr) return;
+    String16 id(cameraId);
+    proxyBinder->notifyCameraState(id, newState);
+}
+
 status_t CameraService::getTorchStatusLocked(
         const String8& cameraId,
         ICameraServiceListener::TorchStatus *status) const {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 3298772..cd97b08 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -24,6 +24,7 @@
 #include <binder/BinderService.h>
 #include <binder/IAppOpsCallback.h>
 #include <camera/ICameraService.h>
+#include <camera/ICameraServiceProxy.h>
 #include <hardware/camera.h>
 
 #include <camera/ICamera.h>
@@ -74,6 +75,8 @@
 
     // Process state (mirrors frameworks/base/core/java/android/app/ActivityManager.java)
     static const int PROCESS_STATE_NONEXISTENT = -1;
+    static const int PROCESS_STATE_TOP = 2;
+    static const int PROCESS_STATE_TOP_SLEEPING = 5;
 
     // 3 second busy timeout when other clients are connecting
     static const nsecs_t DEFAULT_CONNECT_TIMEOUT_NS = 3000000000;
@@ -100,7 +103,9 @@
 
     /////////////////////////////////////////////////////////////////////
     // ICameraService
+    virtual int32_t     getNumberOfCameras(int type);
     virtual int32_t     getNumberOfCameras();
+
     virtual status_t    getCameraInfo(int cameraId,
                                       struct CameraInfo* cameraInfo);
     virtual status_t    getCameraCharacteristics(int cameraId,
@@ -162,6 +167,14 @@
     void                playSound(sound_kind kind);
     void                releaseSound();
 
+    /**
+     * Update the state of a given camera device (open/close/active/idle) with
+     * the camera proxy service in the system service
+     */
+    static void         updateProxyDeviceState(
+            ICameraServiceProxy::CameraState newState,
+            const String8& cameraId);
+
     /////////////////////////////////////////////////////////////////////
     // CameraDeviceFactory functionality
     int                 getDeviceVersion(int cameraId, int* facing = NULL);
@@ -509,6 +522,11 @@
     std::set<userid_t> mAllowedUsers;
 
     /**
+     * Check camera capabilities, such as support for basic color operation
+     */
+    int checkCameraCapabilities(int id, camera_info info, int *latestStrangeCameraId);
+
+    /**
      * Get the camera state for a given camera id.
      *
      * This acquires mCameraStatesLock.
@@ -610,6 +628,7 @@
     void dumpEventLog(int fd);
 
     int                 mNumberOfCameras;
+    int                 mNumberOfNormalCameras;
 
     // sounds
     MediaPlayer*        newMediaPlayer(const char *file);
@@ -640,8 +659,10 @@
     sp<CameraFlashlight> mFlashlight;
     // guard mTorchStatusMap
     Mutex                mTorchStatusMutex;
-    // guard mTorchClientMap, mTorchUidMap
+    // guard mTorchClientMap
     Mutex                mTorchClientMapMutex;
+    // guard mTorchUidMap
+    Mutex                mTorchUidMapMutex;
     // camera id -> torch status
     KeyedVector<String8, ICameraServiceListener::TorchStatus> mTorchStatusMap;
     // camera id -> torch client binder
@@ -720,6 +741,7 @@
 
     static String8 toString(std::set<userid_t> intSet);
 
+    static sp<ICameraServiceProxy> getCameraServiceProxy();
     static void pingCameraServiceProxy();
 
 };
@@ -851,11 +873,6 @@
             return ret;
         }
 
-        sp<IBinder> remoteCallback = client->getRemote();
-        if (remoteCallback != nullptr) {
-            remoteCallback->linkToDeath(this);
-        }
-
         // Update shim paremeters for legacy clients
         if (effectiveApiLevel == API_1) {
             // Assume we have always received a Client subclass for API1
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 36e99dd..48b5a26 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -1912,6 +1912,8 @@
     ALOGV("%s: Shutter notification for request id %" PRId32 " at time %" PRId64,
             __FUNCTION__, resultExtras.requestId, timestamp);
     mCaptureSequencer->notifyShutter(resultExtras, timestamp);
+
+    Camera2ClientBase::notifyShutter(resultExtras, timestamp);
 }
 
 camera2::SharedParameters& Camera2Client::getParameters() {
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index e552633..38e35cd 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -251,6 +251,9 @@
     // Turn off all messages.
     disableMsgType(CAMERA_MSG_ALL_MSGS);
     mHardware->stopPreview();
+    mCameraService->updateProxyDeviceState(
+        ICameraServiceProxy::CAMERA_STATE_IDLE,
+        String8::format("%d", mCameraId));
     mHardware->cancelPicture();
     // Release the hardware resources.
     mHardware->release();
@@ -409,7 +412,11 @@
     }
     mHardware->setPreviewWindow(mPreviewWindow);
     result = mHardware->startPreview();
-
+    if (result == NO_ERROR) {
+        mCameraService->updateProxyDeviceState(
+            ICameraServiceProxy::CAMERA_STATE_ACTIVE,
+            String8::format("%d", mCameraId));
+    }
     return result;
 }
 
@@ -449,7 +456,9 @@
 
     disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
     mHardware->stopPreview();
-
+    mCameraService->updateProxyDeviceState(
+        ICameraServiceProxy::CAMERA_STATE_IDLE,
+        String8::format("%d", mCameraId));
     mPreviewBuffer.clear();
 }
 
@@ -790,6 +799,12 @@
     }
     disableMsgType(CAMERA_MSG_SHUTTER);
 
+    // Shutters only happen in response to takePicture, so mark device as
+    // idle now, until preview is restarted
+    mCameraService->updateProxyDeviceState(
+        ICameraServiceProxy::CAMERA_STATE_IDLE,
+        String8::format("%d", mCameraId));
+
     mLock.unlock();
 }
 
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index c717a56..0c531c3 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -719,6 +719,43 @@
     return res;
 }
 
+status_t CameraDeviceClient::prepare2(int maxCount, int streamId) {
+    ATRACE_CALL();
+    ALOGV("%s", __FUNCTION__);
+
+    status_t res = OK;
+    if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
+
+    Mutex::Autolock icl(mBinderSerializationLock);
+
+    // Guard against trying to prepare non-created streams
+    ssize_t index = NAME_NOT_FOUND;
+    for (size_t i = 0; i < mStreamMap.size(); ++i) {
+        if (streamId == mStreamMap.valueAt(i)) {
+            index = i;
+            break;
+        }
+    }
+
+    if (index == NAME_NOT_FOUND) {
+        ALOGW("%s: Camera %d: Invalid stream ID (%d) specified, no stream created yet",
+                __FUNCTION__, mCameraId, streamId);
+        return BAD_VALUE;
+    }
+
+    if (maxCount <= 0) {
+        ALOGE("%s: Camera %d: Invalid maxCount (%d) specified, must be greater than 0.",
+                __FUNCTION__, mCameraId, maxCount);
+        return BAD_VALUE;
+    }
+
+    // Also returns BAD_VALUE if stream ID was not valid, or stream already
+    // has been used
+    res = mDevice->prepare(maxCount, streamId);
+
+    return res;
+}
+
 status_t CameraDeviceClient::tearDown(int streamId) {
     ATRACE_CALL();
     ALOGV("%s", __FUNCTION__);
@@ -799,6 +836,7 @@
     if (remoteCb != 0) {
         remoteCb->onDeviceIdle();
     }
+    Camera2ClientBase::notifyIdle();
 }
 
 void CameraDeviceClient::notifyShutter(const CaptureResultExtras& resultExtras,
@@ -808,6 +846,7 @@
     if (remoteCb != 0) {
         remoteCb->onCaptureStarted(resultExtras, timestamp);
     }
+    Camera2ClientBase::notifyShutter(resultExtras, timestamp);
 }
 
 void CameraDeviceClient::notifyPrepared(int streamId) {
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 1f8b39d..d1e692c 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -114,6 +114,9 @@
     // Tear down stream resources by freeing its unused buffers
     virtual status_t      tearDown(int streamId);
 
+    // Prepare stream by preallocating up to maxCount of its buffers
+    virtual status_t      prepare2(int maxCount, int streamId);
+
     /**
      * Interface used by CameraService
      */
@@ -189,6 +192,7 @@
     Vector<int> mStreamingRequestList;
 
     int32_t mRequestIdCounter;
+
 };
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index ba0b264..5732f80 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -55,7 +55,8 @@
         TClientBase(cameraService, remoteCallback, clientPackageName,
                 cameraId, cameraFacing, clientPid, clientUid, servicePid),
         mSharedCameraCallbacks(remoteCallback),
-        mDeviceVersion(cameraService->getDeviceVersion(cameraId))
+        mDeviceVersion(cameraService->getDeviceVersion(cameraId)),
+        mDeviceActive(false)
 {
     ALOGI("Camera %d: Opened. Client: %s (PID %d, UID %d)", cameraId,
             String8(clientPackageName).string(), clientPid, clientUid);
@@ -235,6 +236,13 @@
 
 template <typename TClientBase>
 void Camera2ClientBase<TClientBase>::notifyIdle() {
+    if (mDeviceActive) {
+        getCameraService()->updateProxyDeviceState(
+            ICameraServiceProxy::CAMERA_STATE_IDLE,
+            String8::format("%d", TClientBase::mCameraId));
+    }
+    mDeviceActive = false;
+
     ALOGV("Camera device is now idle");
 }
 
@@ -244,6 +252,13 @@
     (void)resultExtras;
     (void)timestamp;
 
+    if (!mDeviceActive) {
+        getCameraService()->updateProxyDeviceState(
+            ICameraServiceProxy::CAMERA_STATE_ACTIVE,
+            String8::format("%d", TClientBase::mCameraId));
+    }
+    mDeviceActive = true;
+
     ALOGV("%s: Shutter notification for request id %" PRId32 " at time %" PRId64,
             __FUNCTION__, resultExtras.requestId, timestamp);
 }
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index f1cacdf..220c5ad 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -136,6 +136,8 @@
     status_t              checkPid(const char *checkLocation) const;
 
     virtual void          detachDevice();
+
+    bool                  mDeviceActive;
 };
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index cd25949..7b083a3 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -294,6 +294,12 @@
     virtual status_t tearDown(int streamId) = 0;
 
     /**
+     * Prepare stream by preallocating up to maxCount buffers for it asynchronously.
+     * Calls notifyPrepared() once allocation is complete.
+     */
+    virtual status_t prepare(int maxCount, int streamId) = 0;
+
+    /**
      * Get the HAL device version.
      */
     virtual uint32_t getDeviceVersion() = 0;
diff --git a/services/camera/libcameraservice/common/CameraModule.cpp b/services/camera/libcameraservice/common/CameraModule.cpp
index 6a4dfe0..16b8aba 100644
--- a/services/camera/libcameraservice/common/CameraModule.cpp
+++ b/services/camera/libcameraservice/common/CameraModule.cpp
@@ -15,14 +15,18 @@
  */
 
 #define LOG_TAG "CameraModule"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
 //#define LOG_NDEBUG 0
 
+#include <utils/Trace.h>
+
 #include "CameraModule.h"
 
 namespace android {
 
 void CameraModule::deriveCameraCharacteristicsKeys(
         uint32_t deviceVersion, CameraMetadata &chars) {
+    ATRACE_CALL();
     // HAL1 devices should not reach here
     if (deviceVersion < CAMERA_DEVICE_API_VERSION_2_0) {
         ALOGV("%s: Cannot derive keys for HAL version < 2.0");
@@ -150,9 +154,7 @@
         ALOGE("%s: camera hardware module must not be null", __FUNCTION__);
         assert(0);
     }
-
     mModule = module;
-    mCameraInfoMap.setCapacity(getNumberOfCameras());
 }
 
 CameraModule::~CameraModule()
@@ -168,14 +170,20 @@
 }
 
 int CameraModule::init() {
+    ATRACE_CALL();
+    int res = OK;
     if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 &&
             mModule->init != NULL) {
-        return mModule->init();
+        ATRACE_BEGIN("camera_module->init");
+        res = mModule->init();
+        ATRACE_END();
     }
-    return OK;
+    mCameraInfoMap.setCapacity(getNumberOfCameras());
+    return res;
 }
 
 int CameraModule::getCameraInfo(int cameraId, struct camera_info *info) {
+    ATRACE_CALL();
     Mutex::Autolock lock(mCameraInfoLock);
     if (cameraId < 0) {
         ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
@@ -185,14 +193,20 @@
     // Only override static_camera_characteristics for API2 devices
     int apiVersion = mModule->common.module_api_version;
     if (apiVersion < CAMERA_MODULE_API_VERSION_2_0) {
-        return mModule->get_camera_info(cameraId, info);
+        int ret;
+        ATRACE_BEGIN("camera_module->get_camera_info");
+        ret = mModule->get_camera_info(cameraId, info);
+        ATRACE_END();
+        return ret;
     }
 
     ssize_t index = mCameraInfoMap.indexOfKey(cameraId);
     if (index == NAME_NOT_FOUND) {
         // Get camera info from raw module and cache it
         camera_info rawInfo, cameraInfo;
+        ATRACE_BEGIN("camera_module->get_camera_info");
         int ret = mModule->get_camera_info(cameraId, &rawInfo);
+        ATRACE_END();
         if (ret != 0) {
             return ret;
         }
@@ -217,20 +231,36 @@
 }
 
 int CameraModule::open(const char* id, struct hw_device_t** device) {
-    return filterOpenErrorCode(mModule->common.methods->open(&mModule->common, id, device));
+    int res;
+    ATRACE_BEGIN("camera_module->open");
+    res = filterOpenErrorCode(mModule->common.methods->open(&mModule->common, id, device));
+    ATRACE_END();
+    return res;
 }
 
 int CameraModule::openLegacy(
         const char* id, uint32_t halVersion, struct hw_device_t** device) {
-    return mModule->open_legacy(&mModule->common, id, halVersion, device);
+    int res;
+    ATRACE_BEGIN("camera_module->open_legacy");
+    res = mModule->open_legacy(&mModule->common, id, halVersion, device);
+    ATRACE_END();
+    return res;
 }
 
 int CameraModule::getNumberOfCameras() {
-    return mModule->get_number_of_cameras();
+    int numCameras;
+    ATRACE_BEGIN("camera_module->get_number_of_cameras");
+    numCameras = mModule->get_number_of_cameras();
+    ATRACE_END();
+    return numCameras;
 }
 
 int CameraModule::setCallbacks(const camera_module_callbacks_t *callbacks) {
-    return mModule->set_callbacks(callbacks);
+    int res;
+    ATRACE_BEGIN("camera_module->set_callbacks");
+    res = mModule->set_callbacks(callbacks);
+    ATRACE_END();
+    return res;
 }
 
 bool CameraModule::isVendorTagDefined() {
@@ -239,12 +269,18 @@
 
 void CameraModule::getVendorTagOps(vendor_tag_ops_t* ops) {
     if (mModule->get_vendor_tag_ops) {
+        ATRACE_BEGIN("camera_module->get_vendor_tag_ops");
         mModule->get_vendor_tag_ops(ops);
+        ATRACE_END();
     }
 }
 
 int CameraModule::setTorchMode(const char* camera_id, bool enable) {
-    return mModule->set_torch_mode(camera_id, enable);
+    int res;
+    ATRACE_BEGIN("camera_module->set_torch_mode");
+    res = mModule->set_torch_mode(camera_id, enable);
+    ATRACE_END();
+    return res;
 }
 
 status_t CameraModule::filterOpenErrorCode(status_t err) {
diff --git a/services/camera/libcameraservice/device2/Camera2Device.cpp b/services/camera/libcameraservice/device2/Camera2Device.cpp
index c9c990c..d74f976 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.cpp
+++ b/services/camera/libcameraservice/device2/Camera2Device.cpp
@@ -632,6 +632,12 @@
     return NO_INIT;
 }
 
+status_t Camera2Device::prepare(int maxCount, int streamId) {
+    ATRACE_CALL();
+    ALOGE("%s: Camera %d: unimplemented", __FUNCTION__, mId);
+    return NO_INIT;
+}
+
 uint32_t Camera2Device::getDeviceVersion() {
     ATRACE_CALL();
     return mDeviceVersion;
diff --git a/services/camera/libcameraservice/device2/Camera2Device.h b/services/camera/libcameraservice/device2/Camera2Device.h
index 34c1ded..b4d343c 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.h
+++ b/services/camera/libcameraservice/device2/Camera2Device.h
@@ -88,6 +88,7 @@
     // Prepare and tearDown are no-ops
     virtual status_t prepare(int streamId);
     virtual status_t tearDown(int streamId);
+    virtual status_t prepare(int maxCount, int streamId);
 
     virtual uint32_t getDeviceVersion();
     virtual ssize_t getJpegBufferSize(uint32_t width, uint32_t height) const;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 3afbd89..433a745 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -60,6 +60,7 @@
         mIsConstrainedHighSpeedConfiguration(false),
         mHal3Device(NULL),
         mStatus(STATUS_UNINITIALIZED),
+        mStatusWaiters(0),
         mUsePartialResult(false),
         mNumPartialResults(1),
         mNextResultFrameNumber(0),
@@ -191,7 +192,8 @@
     mDeviceVersion = device->common.version;
     mDeviceInfo = info.static_camera_characteristics;
     mHal3Device = device;
-    mStatus = STATUS_UNCONFIGURED;
+
+    internalUpdateStatusLocked(STATUS_UNCONFIGURED);
     mNextStreamId = 0;
     mDummyStreamId = NO_STREAM;
     mNeedConfig = true;
@@ -283,20 +285,28 @@
         mStatusTracker->join();
     }
 
+    camera3_device_t *hal3Device;
     {
         Mutex::Autolock l(mLock);
 
         mRequestThread.clear();
         mStatusTracker.clear();
 
-        if (mHal3Device != NULL) {
-            ATRACE_BEGIN("camera3->close");
-            mHal3Device->common.close(&mHal3Device->common);
-            ATRACE_END();
-            mHal3Device = NULL;
-        }
+        hal3Device = mHal3Device;
+    }
 
-        mStatus = STATUS_UNINITIALIZED;
+    // Call close without internal mutex held, as the HAL close may need to
+    // wait on assorted callbacks,etc, to complete before it can return.
+    if (hal3Device != NULL) {
+        ATRACE_BEGIN("camera3->close");
+        hal3Device->common.close(&hal3Device->common);
+        ATRACE_END();
+    }
+
+    {
+        Mutex::Autolock l(mLock);
+        mHal3Device = NULL;
+        internalUpdateStatusLocked(STATUS_UNINITIALIZED);
     }
 
     ALOGV("%s: X", __FUNCTION__);
@@ -370,7 +380,7 @@
     // Get max jpeg size (area-wise).
     Size maxJpegResolution = getMaxJpegResolution();
     if (maxJpegResolution.width == 0) {
-        ALOGE("%s: Camera %d: Can't find find valid available jpeg sizes in static metadata!",
+        ALOGE("%s: Camera %d: Can't find valid available jpeg sizes in static metadata!",
                 __FUNCTION__, mId);
         return BAD_VALUE;
     }
@@ -397,6 +407,21 @@
     return jpegBufferSize;
 }
 
+ssize_t Camera3Device::getPointCloudBufferSize() const {
+    const int FLOATS_PER_POINT=4;
+    camera_metadata_ro_entry maxPointCount = mDeviceInfo.find(ANDROID_DEPTH_MAX_DEPTH_SAMPLES);
+    if (maxPointCount.count == 0) {
+        ALOGE("%s: Camera %d: Can't find maximum depth point cloud size in static metadata!",
+                __FUNCTION__, mId);
+        return BAD_VALUE;
+    }
+    ssize_t maxBytesForPointCloud = sizeof(android_depth_points) +
+            maxPointCount.data.i32[0] * sizeof(float) * FLOATS_PER_POINT;
+    return maxBytesForPointCloud;
+}
+
+
+
 status_t Camera3Device::dump(int fd, const Vector<String16> &args) {
     ATRACE_CALL();
     (void)args;
@@ -540,6 +565,18 @@
 
         ALOGV("%s: requestId = %" PRId32, __FUNCTION__, newRequest->mResultExtras.requestId);
     }
+
+    // Setup batch size if this is a high speed video recording request.
+    if (mIsConstrainedHighSpeedConfiguration && requestList->size() > 0) {
+        auto firstRequest = requestList->begin();
+        for (auto& outputStream : (*firstRequest)->mOutputStreams) {
+            if (outputStream->isVideoStream()) {
+                (*firstRequest)->mBatchSize = requestList->size();
+                break;
+            }
+        }
+    }
+
     return OK;
 }
 
@@ -865,14 +902,22 @@
 
     sp<Camera3OutputStream> newStream;
     if (format == HAL_PIXEL_FORMAT_BLOB) {
-        ssize_t jpegBufferSize = getJpegBufferSize(width, height);
-        if (jpegBufferSize <= 0) {
-            SET_ERR_L("Invalid jpeg buffer size %zd", jpegBufferSize);
-            return BAD_VALUE;
+        ssize_t blobBufferSize;
+        if (dataSpace != HAL_DATASPACE_DEPTH) {
+            blobBufferSize = getJpegBufferSize(width, height);
+            if (blobBufferSize <= 0) {
+                SET_ERR_L("Invalid jpeg buffer size %zd", blobBufferSize);
+                return BAD_VALUE;
+            }
+        } else {
+            blobBufferSize = getPointCloudBufferSize();
+            if (blobBufferSize <= 0) {
+                SET_ERR_L("Invalid point cloud buffer size %zd", blobBufferSize);
+                return BAD_VALUE;
+            }
         }
-
         newStream = new Camera3OutputStream(mNextStreamId, consumer,
-                width, height, jpegBufferSize, format, dataSpace, rotation);
+                width, height, blobBufferSize, format, dataSpace, rotation);
     } else {
         newStream = new Camera3OutputStream(mNextStreamId, consumer,
                 width, height, format, dataSpace, rotation);
@@ -1143,6 +1188,13 @@
     return res;
 }
 
+
+void Camera3Device::internalUpdateStatusLocked(Status status) {
+    mStatus = status;
+    mRecentStatusUpdates.add(mStatus);
+    mStatusChanged.broadcast();
+}
+
 // Pause to reconfigure
 status_t Camera3Device::internalPauseAndWaitLocked() {
     mRequestThread->setPaused(true);
@@ -1173,23 +1225,40 @@
     return OK;
 }
 
-status_t Camera3Device::waitUntilStateThenRelock(bool active,
-        nsecs_t timeout) {
+status_t Camera3Device::waitUntilStateThenRelock(bool active, nsecs_t timeout) {
     status_t res = OK;
-    if (active == (mStatus == STATUS_ACTIVE)) {
-        // Desired state already reached
-        return res;
+
+    size_t startIndex = 0;
+    if (mStatusWaiters == 0) {
+        // Clear the list of recent statuses if there are no existing threads waiting on updates to
+        // this status list
+        mRecentStatusUpdates.clear();
+    } else {
+        // If other threads are waiting on updates to this status list, set the position of the
+        // first element that this list will check rather than clearing the list.
+        startIndex = mRecentStatusUpdates.size();
     }
 
+    mStatusWaiters++;
+
     bool stateSeen = false;
     do {
-        mRecentStatusUpdates.clear();
+        if (active == (mStatus == STATUS_ACTIVE)) {
+            // Desired state is current
+            break;
+        }
 
         res = mStatusChanged.waitRelative(mLock, timeout);
         if (res != OK) break;
 
-        // Check state change history during wait
-        for (size_t i = 0; i < mRecentStatusUpdates.size(); i++) {
+        // This is impossible, but if not, could result in subtle deadlocks and invalid state
+        // transitions.
+        LOG_ALWAYS_FATAL_IF(startIndex > mRecentStatusUpdates.size(),
+                "%s: Skipping status updates in Camera3Device, may result in deadlock.",
+                __FUNCTION__);
+
+        // Encountered desired state since we began waiting
+        for (size_t i = startIndex; i < mRecentStatusUpdates.size(); i++) {
             if (active == (mRecentStatusUpdates[i] == STATUS_ACTIVE) ) {
                 stateSeen = true;
                 break;
@@ -1197,6 +1266,8 @@
         }
     } while (!stateSeen);
 
+    mStatusWaiters--;
+
     return res;
 }
 
@@ -1347,7 +1418,7 @@
 
     status_t res;
     if (mHal3Device->common.version >= CAMERA_DEVICE_API_VERSION_3_1) {
-        res = mHal3Device->ops->flush(mHal3Device);
+        res = mRequestThread->flush();
     } else {
         Mutex::Autolock l(mLock);
         res = waitUntilDrainedLocked();
@@ -1357,6 +1428,10 @@
 }
 
 status_t Camera3Device::prepare(int streamId) {
+    return prepare(camera3::Camera3StreamInterface::ALLOCATE_PIPELINE_MAX, streamId);
+}
+
+status_t Camera3Device::prepare(int maxCount, int streamId) {
     ATRACE_CALL();
     ALOGV("%s: Camera %d: Preparing stream %d", __FUNCTION__, mId, streamId);
     Mutex::Autolock il(mInterfaceLock);
@@ -1381,7 +1456,7 @@
         return BAD_VALUE;
     }
 
-    return mPreparerThread->prepare(stream);
+    return mPreparerThread->prepare(maxCount, stream);
 }
 
 status_t Camera3Device::tearDown(int streamId) {
@@ -1438,9 +1513,7 @@
         }
         ALOGV("%s: Camera %d: Now %s", __FUNCTION__, mId,
                 idle ? "idle" : "active");
-        mStatus = idle ? STATUS_CONFIGURED : STATUS_ACTIVE;
-        mRecentStatusUpdates.add(mStatus);
-        mStatusChanged.signal();
+        internalUpdateStatusLocked(idle ? STATUS_CONFIGURED : STATUS_ACTIVE);
 
         // Skip notifying listener if we're doing some user-transparent
         // state changes
@@ -1534,6 +1607,7 @@
         newRequest->mOutputStreams.push(stream);
     }
     newRequest->mSettings.erase(ANDROID_REQUEST_OUTPUT_STREAMS);
+    newRequest->mBatchSize = 1;
 
     return newRequest;
 }
@@ -1649,7 +1723,7 @@
 
         // Return state to that at start of call, so that future configures
         // properly clean things up
-        mStatus = STATUS_UNCONFIGURED;
+        internalUpdateStatusLocked(STATUS_UNCONFIGURED);
         mNeedConfig = true;
 
         ALOGV("%s: Camera %d: Stream configuration failed", __FUNCTION__, mId);
@@ -1696,11 +1770,8 @@
 
     mNeedConfig = false;
 
-    if (mDummyStreamId == NO_STREAM) {
-        mStatus = STATUS_CONFIGURED;
-    } else {
-        mStatus = STATUS_UNCONFIGURED;
-    }
+    internalUpdateStatusLocked((mDummyStreamId == NO_STREAM) ?
+            STATUS_CONFIGURED : STATUS_UNCONFIGURED);
 
     ALOGV("%s: Camera %d: Stream configuration complete", __FUNCTION__, mId);
 
@@ -1808,7 +1879,7 @@
     mErrorCause = errorCause;
 
     mRequestThread->setPaused(true);
-    mStatus = STATUS_ERROR;
+    internalUpdateStatusLocked(STATUS_ERROR);
 
     // Notify upstream about a device error
     if (mListener != NULL) {
@@ -2067,8 +2138,12 @@
 
     // Sanity check - if we have too many in-flight frames, something has
     // likely gone wrong
-    if (mInFlightMap.size() > kInFlightWarnLimit) {
+    if (!mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() > kInFlightWarnLimit) {
         CLOGE("In-flight list too large: %zu", mInFlightMap.size());
+    } else if (mIsConstrainedHighSpeedConfiguration && mInFlightMap.size() >
+            kInFlightWarnLimitHighSpeed) {
+        CLOGE("In-flight list too large for high speed configuration: %zu",
+                mInFlightMap.size());
     }
 }
 
@@ -2704,6 +2779,17 @@
     return OK;
 }
 
+status_t Camera3Device::RequestThread::flush() {
+    ATRACE_CALL();
+    Mutex::Autolock l(mFlushLock);
+
+    if (mHal3Device->common.version >= CAMERA_DEVICE_API_VERSION_3_1) {
+        return mHal3Device->ops->flush(mHal3Device);
+    }
+
+    return -ENOTSUP;
+}
+
 void Camera3Device::RequestThread::setPaused(bool paused) {
     Mutex::Autolock l(mPauseLock);
     mDoPause = paused;
@@ -2794,7 +2880,7 @@
 }
 
 bool Camera3Device::RequestThread::threadLoop() {
-
+    ATRACE_CALL();
     status_t res;
 
     // Handle paused state.
@@ -2802,147 +2888,31 @@
         return true;
     }
 
-    // Get work to do
-
-    sp<CaptureRequest> nextRequest = waitForNextRequest();
-    if (nextRequest == NULL) {
+    // Wait for the next batch of requests.
+    waitForNextRequestBatch();
+    if (mNextRequests.size() == 0) {
         return true;
     }
 
-    // Create request to HAL
-    camera3_capture_request_t request = camera3_capture_request_t();
-    request.frame_number = nextRequest->mResultExtras.frameNumber;
-    Vector<camera3_stream_buffer_t> outputBuffers;
-
-    // Get the request ID, if any
-    int requestId;
-    camera_metadata_entry_t requestIdEntry =
-            nextRequest->mSettings.find(ANDROID_REQUEST_ID);
+    // Get the latest request ID, if any
+    int latestRequestId;
+    camera_metadata_entry_t requestIdEntry = mNextRequests[mNextRequests.size() - 1].
+            captureRequest->mSettings.find(ANDROID_REQUEST_ID);
     if (requestIdEntry.count > 0) {
-        requestId = requestIdEntry.data.i32[0];
+        latestRequestId = requestIdEntry.data.i32[0];
     } else {
-        ALOGW("%s: Did not have android.request.id set in the request",
-                __FUNCTION__);
-        requestId = NAME_NOT_FOUND;
+        ALOGW("%s: Did not have android.request.id set in the request.", __FUNCTION__);
+        latestRequestId = NAME_NOT_FOUND;
     }
 
-    // Insert any queued triggers (before metadata is locked)
-    int32_t triggerCount;
-    res = insertTriggers(nextRequest);
-    if (res < 0) {
-        SET_ERR("RequestThread: Unable to insert triggers "
-                "(capture request %d, HAL device: %s (%d)",
-                request.frame_number, strerror(-res), res);
-        cleanUpFailedRequest(request, nextRequest, outputBuffers);
-        return false;
-    }
-    triggerCount = res;
-
-    bool triggersMixedIn = (triggerCount > 0 || mPrevTriggers > 0);
-
-    // If the request is the same as last, or we had triggers last time
-    if (mPrevRequest != nextRequest || triggersMixedIn) {
-        /**
-         * HAL workaround:
-         * Insert a dummy trigger ID if a trigger is set but no trigger ID is
-         */
-        res = addDummyTriggerIds(nextRequest);
-        if (res != OK) {
-            SET_ERR("RequestThread: Unable to insert dummy trigger IDs "
-                    "(capture request %d, HAL device: %s (%d)",
-                    request.frame_number, strerror(-res), res);
-            cleanUpFailedRequest(request, nextRequest, outputBuffers);
-            return false;
-        }
-
-        /**
-         * The request should be presorted so accesses in HAL
-         *   are O(logn). Sidenote, sorting a sorted metadata is nop.
-         */
-        nextRequest->mSettings.sort();
-        request.settings = nextRequest->mSettings.getAndLock();
-        mPrevRequest = nextRequest;
-        ALOGVV("%s: Request settings are NEW", __FUNCTION__);
-
-        IF_ALOGV() {
-            camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
-            find_camera_metadata_ro_entry(
-                    request.settings,
-                    ANDROID_CONTROL_AF_TRIGGER,
-                    &e
-            );
-            if (e.count > 0) {
-                ALOGV("%s: Request (frame num %d) had AF trigger 0x%x",
-                      __FUNCTION__,
-                      request.frame_number,
-                      e.data.u8[0]);
-            }
-        }
-    } else {
-        // leave request.settings NULL to indicate 'reuse latest given'
-        ALOGVV("%s: Request settings are REUSED",
-               __FUNCTION__);
-    }
-
-    uint32_t totalNumBuffers = 0;
-
-    // Fill in buffers
-    if (nextRequest->mInputStream != NULL) {
-        request.input_buffer = &nextRequest->mInputBuffer;
-        totalNumBuffers += 1;
-    } else {
-        request.input_buffer = NULL;
-    }
-
-    outputBuffers.insertAt(camera3_stream_buffer_t(), 0,
-            nextRequest->mOutputStreams.size());
-    request.output_buffers = outputBuffers.array();
-    for (size_t i = 0; i < nextRequest->mOutputStreams.size(); i++) {
-        res = nextRequest->mOutputStreams.editItemAt(i)->
-                getBuffer(&outputBuffers.editItemAt(i));
-        if (res != OK) {
-            // Can't get output buffer from gralloc queue - this could be due to
-            // abandoned queue or other consumer misbehavior, so not a fatal
-            // error
-            ALOGE("RequestThread: Can't get output buffer, skipping request:"
-                    " %s (%d)", strerror(-res), res);
-            {
-                Mutex::Autolock l(mRequestLock);
-                if (mListener != NULL) {
-                    mListener->notifyError(
-                            ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
-                            nextRequest->mResultExtras);
-                }
-            }
-            cleanUpFailedRequest(request, nextRequest, outputBuffers);
-            return true;
-        }
-        request.num_output_buffers++;
-    }
-    totalNumBuffers += request.num_output_buffers;
-
-    // Log request in the in-flight queue
-    sp<Camera3Device> parent = mParent.promote();
-    if (parent == NULL) {
-        // Should not happen, and nowhere to send errors to, so just log it
-        CLOGE("RequestThread: Parent is gone");
-        cleanUpFailedRequest(request, nextRequest, outputBuffers);
-        return false;
-    }
-
-    res = parent->registerInFlight(request.frame_number,
-            totalNumBuffers, nextRequest->mResultExtras,
-            /*hasInput*/request.input_buffer != NULL,
-            nextRequest->mAeTriggerCancelOverride);
-    ALOGVV("%s: registered in flight requestId = %" PRId32 ", frameNumber = %" PRId64
-           ", burstId = %" PRId32 ".",
-            __FUNCTION__,
-            nextRequest->mResultExtras.requestId, nextRequest->mResultExtras.frameNumber,
-            nextRequest->mResultExtras.burstId);
-    if (res != OK) {
-        SET_ERR("RequestThread: Unable to register new in-flight request:"
-                " %s (%d)", strerror(-res), res);
-        cleanUpFailedRequest(request, nextRequest, outputBuffers);
+    // Prepare a batch of HAL requests and output buffers.
+    res = prepareHalRequests();
+    if (res == TIMED_OUT) {
+        // Not a fatal error if getting output buffers time out.
+        cleanUpFailedRequests(/*sendRequestError*/ true);
+        return true;
+    } else if (res != OK) {
+        cleanUpFailedRequests(/*sendRequestError*/ false);
         return false;
     }
 
@@ -2950,57 +2920,210 @@
     {
         Mutex::Autolock al(mLatestRequestMutex);
 
-        mLatestRequestId = requestId;
+        mLatestRequestId = latestRequestId;
         mLatestRequestSignal.signal();
     }
 
-    // Submit request and block until ready for next one
-    ATRACE_ASYNC_BEGIN("frame capture", request.frame_number);
-    ATRACE_BEGIN("camera3->process_capture_request");
-    res = mHal3Device->ops->process_capture_request(mHal3Device, &request);
-    ATRACE_END();
+    // Submit a batch of requests to HAL.
+    // Use flush lock only when submitting multilple requests in a batch.
+    // TODO: The problem with flush lock is flush() will be blocked by process_capture_request()
+    // which may take a long time to finish so synchronizing flush() and
+    // process_capture_request() defeats the purpose of cancelling requests ASAP with flush().
+    // For now, only synchronize for high speed recording and we should figure something out for
+    // removing the synchronization.
+    bool useFlushLock = mNextRequests.size() > 1;
 
-    if (res != OK) {
-        // Should only get a failure here for malformed requests or device-level
-        // errors, so consider all errors fatal.  Bad metadata failures should
-        // come through notify.
-        SET_ERR("RequestThread: Unable to submit capture request %d to HAL"
-                " device: %s (%d)", request.frame_number, strerror(-res), res);
-        cleanUpFailedRequest(request, nextRequest, outputBuffers);
-        return false;
+    if (useFlushLock) {
+        mFlushLock.lock();
     }
 
-    // Update the latest request sent to HAL
-    if (request.settings != NULL) { // Don't update them if they were unchanged
-        Mutex::Autolock al(mLatestRequestMutex);
+    ALOGVV("%s: %d: submitting %d requests in a batch.", __FUNCTION__, __LINE__,
+            mNextRequests.size());
+    for (auto& nextRequest : mNextRequests) {
+        // Submit request and block until ready for next one
+        ATRACE_ASYNC_BEGIN("frame capture", nextRequest.halRequest.frame_number);
+        ATRACE_BEGIN("camera3->process_capture_request");
+        res = mHal3Device->ops->process_capture_request(mHal3Device, &nextRequest.halRequest);
+        ATRACE_END();
 
-        camera_metadata_t* cloned = clone_camera_metadata(request.settings);
-        mLatestRequest.acquire(cloned);
+        if (res != OK) {
+            // Should only get a failure here for malformed requests or device-level
+            // errors, so consider all errors fatal.  Bad metadata failures should
+            // come through notify.
+            SET_ERR("RequestThread: Unable to submit capture request %d to HAL"
+                    " device: %s (%d)", nextRequest.halRequest.frame_number, strerror(-res),
+                    res);
+            cleanUpFailedRequests(/*sendRequestError*/ false);
+            if (useFlushLock) {
+                mFlushLock.unlock();
+            }
+            return false;
+        }
+
+        // Mark that the request has be submitted successfully.
+        nextRequest.submitted = true;
+
+        // Update the latest request sent to HAL
+        if (nextRequest.halRequest.settings != NULL) { // Don't update if they were unchanged
+            Mutex::Autolock al(mLatestRequestMutex);
+
+            camera_metadata_t* cloned = clone_camera_metadata(nextRequest.halRequest.settings);
+            mLatestRequest.acquire(cloned);
+        }
+
+        if (nextRequest.halRequest.settings != NULL) {
+            nextRequest.captureRequest->mSettings.unlock(nextRequest.halRequest.settings);
+        }
+
+        // Remove any previously queued triggers (after unlock)
+        res = removeTriggers(mPrevRequest);
+        if (res != OK) {
+            SET_ERR("RequestThread: Unable to remove triggers "
+                  "(capture request %d, HAL device: %s (%d)",
+                  nextRequest.halRequest.frame_number, strerror(-res), res);
+            cleanUpFailedRequests(/*sendRequestError*/ false);
+            if (useFlushLock) {
+                mFlushLock.unlock();
+            }
+            return false;
+        }
     }
 
-    if (request.settings != NULL) {
-        nextRequest->mSettings.unlock(request.settings);
+    if (useFlushLock) {
+        mFlushLock.unlock();
     }
 
     // Unset as current request
     {
         Mutex::Autolock l(mRequestLock);
-        mNextRequest.clear();
+        mNextRequests.clear();
     }
 
-    // Remove any previously queued triggers (after unlock)
-    res = removeTriggers(mPrevRequest);
-    if (res != OK) {
-        SET_ERR("RequestThread: Unable to remove triggers "
-              "(capture request %d, HAL device: %s (%d)",
-              request.frame_number, strerror(-res), res);
-        return false;
-    }
-    mPrevTriggers = triggerCount;
-
     return true;
 }
 
+status_t Camera3Device::RequestThread::prepareHalRequests() {
+    ATRACE_CALL();
+
+    for (auto& nextRequest : mNextRequests) {
+        sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
+        camera3_capture_request_t* halRequest = &nextRequest.halRequest;
+        Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
+
+        // Prepare a request to HAL
+        halRequest->frame_number = captureRequest->mResultExtras.frameNumber;
+
+        // Insert any queued triggers (before metadata is locked)
+        status_t res = insertTriggers(captureRequest);
+
+        if (res < 0) {
+            SET_ERR("RequestThread: Unable to insert triggers "
+                    "(capture request %d, HAL device: %s (%d)",
+                    halRequest->frame_number, strerror(-res), res);
+            return INVALID_OPERATION;
+        }
+        int triggerCount = res;
+        bool triggersMixedIn = (triggerCount > 0 || mPrevTriggers > 0);
+        mPrevTriggers = triggerCount;
+
+        // If the request is the same as last, or we had triggers last time
+        if (mPrevRequest != captureRequest || triggersMixedIn) {
+            /**
+             * HAL workaround:
+             * Insert a dummy trigger ID if a trigger is set but no trigger ID is
+             */
+            res = addDummyTriggerIds(captureRequest);
+            if (res != OK) {
+                SET_ERR("RequestThread: Unable to insert dummy trigger IDs "
+                        "(capture request %d, HAL device: %s (%d)",
+                        halRequest->frame_number, strerror(-res), res);
+                return INVALID_OPERATION;
+            }
+
+            /**
+             * The request should be presorted so accesses in HAL
+             *   are O(logn). Sidenote, sorting a sorted metadata is nop.
+             */
+            captureRequest->mSettings.sort();
+            halRequest->settings = captureRequest->mSettings.getAndLock();
+            mPrevRequest = captureRequest;
+            ALOGVV("%s: Request settings are NEW", __FUNCTION__);
+
+            IF_ALOGV() {
+                camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
+                find_camera_metadata_ro_entry(
+                        halRequest->settings,
+                        ANDROID_CONTROL_AF_TRIGGER,
+                        &e
+                );
+                if (e.count > 0) {
+                    ALOGV("%s: Request (frame num %d) had AF trigger 0x%x",
+                          __FUNCTION__,
+                          halRequest->frame_number,
+                          e.data.u8[0]);
+                }
+            }
+        } else {
+            // leave request.settings NULL to indicate 'reuse latest given'
+            ALOGVV("%s: Request settings are REUSED",
+                   __FUNCTION__);
+        }
+
+        uint32_t totalNumBuffers = 0;
+
+        // Fill in buffers
+        if (captureRequest->mInputStream != NULL) {
+            halRequest->input_buffer = &captureRequest->mInputBuffer;
+            totalNumBuffers += 1;
+        } else {
+            halRequest->input_buffer = NULL;
+        }
+
+        outputBuffers->insertAt(camera3_stream_buffer_t(), 0,
+                captureRequest->mOutputStreams.size());
+        halRequest->output_buffers = outputBuffers->array();
+        for (size_t i = 0; i < captureRequest->mOutputStreams.size(); i++) {
+            res = captureRequest->mOutputStreams.editItemAt(i)->
+                    getBuffer(&outputBuffers->editItemAt(i));
+            if (res != OK) {
+                // Can't get output buffer from gralloc queue - this could be due to
+                // abandoned queue or other consumer misbehavior, so not a fatal
+                // error
+                ALOGE("RequestThread: Can't get output buffer, skipping request:"
+                        " %s (%d)", strerror(-res), res);
+
+                return TIMED_OUT;
+            }
+            halRequest->num_output_buffers++;
+        }
+        totalNumBuffers += halRequest->num_output_buffers;
+
+        // Log request in the in-flight queue
+        sp<Camera3Device> parent = mParent.promote();
+        if (parent == NULL) {
+            // Should not happen, and nowhere to send errors to, so just log it
+            CLOGE("RequestThread: Parent is gone");
+            return INVALID_OPERATION;
+        }
+        res = parent->registerInFlight(halRequest->frame_number,
+                totalNumBuffers, captureRequest->mResultExtras,
+                /*hasInput*/halRequest->input_buffer != NULL,
+                captureRequest->mAeTriggerCancelOverride);
+        ALOGVV("%s: registered in flight requestId = %" PRId32 ", frameNumber = %" PRId64
+               ", burstId = %" PRId32 ".",
+                __FUNCTION__,
+                captureRequest->mResultExtras.requestId, captureRequest->mResultExtras.frameNumber,
+                captureRequest->mResultExtras.burstId);
+        if (res != OK) {
+            SET_ERR("RequestThread: Unable to register new in-flight request:"
+                    " %s (%d)", strerror(-res), res);
+            return INVALID_OPERATION;
+        }
+    }
+
+    return OK;
+}
+
 CameraMetadata Camera3Device::RequestThread::getLatestRequest() const {
     Mutex::Autolock al(mLatestRequestMutex);
 
@@ -3013,11 +3136,13 @@
         sp<Camera3StreamInterface>& stream) {
     Mutex::Autolock l(mRequestLock);
 
-    if (mNextRequest != nullptr) {
-        for (const auto& s : mNextRequest->mOutputStreams) {
-            if (stream == s) return true;
+    for (const auto& nextRequest : mNextRequests) {
+        if (!nextRequest.submitted) {
+            for (const auto& s : nextRequest.captureRequest->mOutputStreams) {
+                if (stream == s) return true;
+            }
+            if (stream == nextRequest.captureRequest->mInputStream) return true;
         }
-        if (stream == mNextRequest->mInputStream) return true;
     }
 
     for (const auto& request : mRequestQueue) {
@@ -3037,37 +3162,95 @@
     return false;
 }
 
-void Camera3Device::RequestThread::cleanUpFailedRequest(
-        camera3_capture_request_t &request,
-        sp<CaptureRequest> &nextRequest,
-        Vector<camera3_stream_buffer_t> &outputBuffers) {
+void Camera3Device::RequestThread::cleanUpFailedRequests(bool sendRequestError) {
+    if (mNextRequests.empty()) {
+        return;
+    }
 
-    if (request.settings != NULL) {
-        nextRequest->mSettings.unlock(request.settings);
-    }
-    if (nextRequest->mInputStream != NULL) {
-        nextRequest->mInputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
-        nextRequest->mInputStream->returnInputBuffer(nextRequest->mInputBuffer);
-    }
-    for (size_t i = 0; i < request.num_output_buffers; i++) {
-        outputBuffers.editItemAt(i).status = CAMERA3_BUFFER_STATUS_ERROR;
-        nextRequest->mOutputStreams.editItemAt(i)->returnBuffer(
-            outputBuffers[i], 0);
+    for (auto& nextRequest : mNextRequests) {
+        // Skip the ones that have been submitted successfully.
+        if (nextRequest.submitted) {
+            continue;
+        }
+
+        sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
+        camera3_capture_request_t* halRequest = &nextRequest.halRequest;
+        Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
+
+        if (halRequest->settings != NULL) {
+            captureRequest->mSettings.unlock(halRequest->settings);
+        }
+
+        if (captureRequest->mInputStream != NULL) {
+            captureRequest->mInputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
+            captureRequest->mInputStream->returnInputBuffer(captureRequest->mInputBuffer);
+        }
+
+        for (size_t i = 0; i < halRequest->num_output_buffers; i++) {
+            outputBuffers->editItemAt(i).status = CAMERA3_BUFFER_STATUS_ERROR;
+            captureRequest->mOutputStreams.editItemAt(i)->returnBuffer((*outputBuffers)[i], 0);
+        }
+
+        if (sendRequestError) {
+            Mutex::Autolock l(mRequestLock);
+            if (mListener != NULL) {
+                mListener->notifyError(
+                        ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
+                        captureRequest->mResultExtras);
+            }
+        }
     }
 
     Mutex::Autolock l(mRequestLock);
-    mNextRequest.clear();
+    mNextRequests.clear();
 }
 
-sp<Camera3Device::CaptureRequest>
-        Camera3Device::RequestThread::waitForNextRequest() {
-    status_t res;
-    sp<CaptureRequest> nextRequest;
-
+void Camera3Device::RequestThread::waitForNextRequestBatch() {
     // Optimized a bit for the simple steady-state case (single repeating
     // request), to avoid putting that request in the queue temporarily.
     Mutex::Autolock l(mRequestLock);
 
+    assert(mNextRequests.empty());
+
+    NextRequest nextRequest;
+    nextRequest.captureRequest = waitForNextRequestLocked();
+    if (nextRequest.captureRequest == nullptr) {
+        return;
+    }
+
+    nextRequest.halRequest = camera3_capture_request_t();
+    nextRequest.submitted = false;
+    mNextRequests.add(nextRequest);
+
+    // Wait for additional requests
+    const size_t batchSize = nextRequest.captureRequest->mBatchSize;
+
+    for (size_t i = 1; i < batchSize; i++) {
+        NextRequest additionalRequest;
+        additionalRequest.captureRequest = waitForNextRequestLocked();
+        if (additionalRequest.captureRequest == nullptr) {
+            break;
+        }
+
+        additionalRequest.halRequest = camera3_capture_request_t();
+        additionalRequest.submitted = false;
+        mNextRequests.add(additionalRequest);
+    }
+
+    if (mNextRequests.size() < batchSize) {
+        ALOGE("RequestThread: only get %d out of %d requests. Skipping requests.",
+                mNextRequests.size(), batchSize);
+        cleanUpFailedRequests(/*sendRequestError*/true);
+    }
+
+    return;
+}
+
+sp<Camera3Device::CaptureRequest>
+        Camera3Device::RequestThread::waitForNextRequestLocked() {
+    status_t res;
+    sp<CaptureRequest> nextRequest;
+
     while (mRequestQueue.empty()) {
         if (!mRepeatingRequests.empty()) {
             // Always atomically enqueue all requests in a repeating request
@@ -3162,8 +3345,6 @@
 
     handleAePrecaptureCancelRequest(nextRequest);
 
-    mNextRequest = nextRequest;
-
     return nextRequest;
 }
 
@@ -3428,12 +3609,12 @@
     clear();
 }
 
-status_t Camera3Device::PreparerThread::prepare(sp<Camera3StreamInterface>& stream) {
+status_t Camera3Device::PreparerThread::prepare(int maxCount, sp<Camera3StreamInterface>& stream) {
     status_t res;
 
     Mutex::Autolock l(mLock);
 
-    res = stream->startPrepare();
+    res = stream->startPrepare(maxCount);
     if (res == OK) {
         // No preparation needed, fire listener right off
         ALOGV("%s: Stream %d already prepared", __FUNCTION__, stream->getId());
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 140da98..9d3c533 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -62,6 +62,7 @@
             public CameraDeviceBase,
             private camera3_callback_ops {
   public:
+
     Camera3Device(int id);
 
     virtual ~Camera3Device();
@@ -143,9 +144,12 @@
 
     virtual status_t tearDown(int streamId);
 
+    virtual status_t prepare(int maxCount, int streamId);
+
     virtual uint32_t getDeviceVersion();
 
     virtual ssize_t getJpegBufferSize(uint32_t width, uint32_t height) const;
+    ssize_t getPointCloudBufferSize() const;
 
     // Methods called by subclasses
     void             notifyStatus(bool idle); // updates from StatusTracker
@@ -153,9 +157,11 @@
   private:
     static const size_t        kDumpLockAttempts  = 10;
     static const size_t        kDumpSleepDuration = 100000; // 0.10 sec
-    static const size_t        kInFlightWarnLimit = 20;
     static const nsecs_t       kShutdownTimeout   = 5000000000; // 5 sec
     static const nsecs_t       kActiveTimeout     = 500000000;  // 500 ms
+    static const size_t        kInFlightWarnLimit = 20;
+    static const size_t        kInFlightWarnLimitHighSpeed = 256; // batch size 32 * pipe depth 8
+
     struct                     RequestTrigger;
     // minimal jpeg buffer size: 256KB + blob header
     static const ssize_t       kMinJpegBufferSize = 256 * 1024 + sizeof(camera3_jpeg_blob);
@@ -204,7 +210,11 @@
         STATUS_CONFIGURED,
         STATUS_ACTIVE
     }                          mStatus;
+
+    // Only clear mRecentStatusUpdates, mStatusWaiters from waitUntilStateThenRelock
     Vector<Status>             mRecentStatusUpdates;
+    int                        mStatusWaiters;
+
     Condition                  mStatusChanged;
 
     // Tracking cause of fatal errors when in STATUS_ERROR
@@ -254,6 +264,11 @@
         // Used to cancel AE precapture trigger for devices doesn't support
         // CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL
         AeTriggerCancelOverride_t           mAeTriggerCancelOverride;
+        // The number of requests that should be submitted to HAL at a time.
+        // For example, if batch size is 8, this request and the following 7
+        // requests will be submitted to HAL at a time. The batch size for
+        // the following 7 requests will be ignored by the request thread.
+        int                                 mBatchSize;
     };
     typedef List<sp<CaptureRequest> > RequestList;
 
@@ -275,6 +290,13 @@
     virtual CameraMetadata getLatestRequestLocked();
 
     /**
+     * Update the current device status and wake all waiting threads.
+     *
+     * Must be called with mLock held.
+     */
+    void internalUpdateStatusLocked(Status status);
+
+    /**
      * Pause processing and flush everything, but don't tell the clients.
      * This is for reconfiguring outputs transparently when according to the
      * CameraDeviceBase interface we shouldn't need to.
@@ -424,6 +446,11 @@
                        int64_t *lastFrameNumber = NULL);
 
         /**
+         * Flush all pending requests in HAL.
+         */
+        status_t flush();
+
+        /**
          * Queue a trigger to be dispatched with the next outgoing
          * process_capture_request. The settings for that request only
          * will be temporarily rewritten to add the trigger tag/value.
@@ -484,16 +511,30 @@
 
         static const nsecs_t kRequestTimeout = 50e6; // 50 ms
 
-        // Waits for a request, or returns NULL if times out.
-        sp<CaptureRequest> waitForNextRequest();
+        // Used to prepare a batch of requests.
+        struct NextRequest {
+            sp<CaptureRequest>              captureRequest;
+            camera3_capture_request_t       halRequest;
+            Vector<camera3_stream_buffer_t> outputBuffers;
+            bool                            submitted;
+        };
 
-        // Return buffers, etc, for a request that couldn't be fully
-        // constructed. The buffers will be returned in the ERROR state
-        // to mark them as not having valid data.
-        // All arguments will be modified.
-        void cleanUpFailedRequest(camera3_capture_request_t &request,
-                sp<CaptureRequest> &nextRequest,
-                Vector<camera3_stream_buffer_t> &outputBuffers);
+        // Wait for the next batch of requests and put them in mNextRequests. mNextRequests will
+        // be empty if it times out.
+        void waitForNextRequestBatch();
+
+        // Waits for a request, or returns NULL if times out. Must be called with mRequestLock hold.
+        sp<CaptureRequest> waitForNextRequestLocked();
+
+        // Prepare HAL requests and output buffers in mNextRequests. Return TIMED_OUT if getting any
+        // output buffer timed out. If an error is returned, the caller should clean up the pending
+        // request batch.
+        status_t prepareHalRequests();
+
+        // Return buffers, etc, for requests in mNextRequests that couldn't be fully constructed and
+        // send request errors if sendRequestError is true. The buffers will be returned in the
+        // ERROR state to mark them as not having valid data. mNextRequests will be cleared.
+        void cleanUpFailedRequests(bool sendRequestError);
 
         // Pause handling
         bool               waitIfPaused();
@@ -522,10 +563,13 @@
         Condition          mRequestSignal;
         RequestList        mRequestQueue;
         RequestList        mRepeatingRequests;
-        // The next request being prepped for submission to the HAL, no longer
+        // The next batch of requests being prepped for submission to the HAL, no longer
         // on the request queue. Read-only even with mRequestLock held, outside
         // of threadLoop
-        sp<const CaptureRequest> mNextRequest;
+        Vector<NextRequest> mNextRequests;
+
+        // To protect flush() and sending a request batch to HAL.
+        Mutex              mFlushLock;
 
         bool               mReconfigured;
 
@@ -684,10 +728,11 @@
         void setNotificationListener(NotificationListener *listener);
 
         /**
-         * Queue up a stream to be prepared. Streams are processed by
-         * a background thread in FIFO order
+         * Queue up a stream to be prepared. Streams are processed by a background thread in FIFO
+         * order.  Pre-allocate up to maxCount buffers for the stream, or the maximum number needed
+         * for the pipeline if maxCount is ALLOCATE_PIPELINE_MAX.
          */
-        status_t prepare(sp<camera3::Camera3StreamInterface>& stream);
+        status_t prepare(int maxCount, sp<camera3::Camera3StreamInterface>& stream);
 
         /**
          * Cancel all current and pending stream preparation
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
index ecb8ac8..1d9d04f 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
@@ -92,6 +92,10 @@
     return OK;
 }
 
+bool Camera3DummyStream::isVideoStream() const {
+    return false;
+}
+
 }; // namespace camera3
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.h b/services/camera/libcameraservice/device3/Camera3DummyStream.h
index 3a3dbf4..97c0c96 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.h
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.h
@@ -54,6 +54,11 @@
 
     status_t         setTransform(int transform);
 
+    /**
+     * Return if this output stream is for video encoding.
+     */
+    bool isVideoStream() const;
+
   protected:
 
     /**
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 8c611d5..3f0a736 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -426,6 +426,17 @@
     return res;
 }
 
+bool Camera3OutputStream::isVideoStream() const {
+    uint32_t usage = 0;
+    status_t res = getEndpointUsage(&usage);
+    if (res != OK) {
+        ALOGE("%s: getting end point usage failed: %s (%d).", __FUNCTION__, strerror(-res), res);
+        return false;
+    }
+
+    return (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) != 0;
+}
+
 }; // namespace camera3
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 941d693..3c083ec 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -64,6 +64,11 @@
      */
     status_t         setTransform(int transform);
 
+    /**
+     * Return if this output stream is for video encoding.
+     */
+    bool isVideoStream() const;
+
   protected:
     Camera3OutputStream(int id, camera3_stream_type_t type,
             uint32_t width, uint32_t height, int format,
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
index aae72cf..df89b34 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
@@ -34,6 +34,11 @@
      * HAL_TRANSFORM_* / NATIVE_WINDOW_TRANSFORM_* constants.
      */
     virtual status_t setTransform(int transform) = 0;
+
+    /**
+     * Return if this output stream is for video encoding.
+     */
+    virtual bool isVideoStream() const = 0;
 };
 
 } // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 2527fd6..96299b3 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -53,7 +53,8 @@
     mName(String8::format("Camera3Stream[%d]", id)),
     mMaxSize(maxSize),
     mState(STATE_CONSTRUCTED),
-    mStatusId(StatusTracker::NO_STATUS_ID) {
+    mStatusId(StatusTracker::NO_STATUS_ID),
+    mLastMaxCount(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX) {
 
     camera3_stream::stream_type = type;
     camera3_stream::width = width;
@@ -252,12 +253,18 @@
     return mStreamUnpreparable;
 }
 
-status_t Camera3Stream::startPrepare() {
+status_t Camera3Stream::startPrepare(int maxCount) {
     ATRACE_CALL();
 
     Mutex::Autolock l(mLock);
     status_t res = OK;
 
+    if (maxCount < 0) {
+        ALOGE("%s: Stream %d: Can't prepare stream if max buffer count (%d) is < 0",
+                __FUNCTION__, mId, maxCount);
+        return BAD_VALUE;
+    }
+
     // This function should be only called when the stream is configured already.
     if (mState != STATE_CONFIGURED) {
         ALOGE("%s: Stream %d: Can't prepare stream if stream is not in CONFIGURED "
@@ -279,9 +286,19 @@
         return INVALID_OPERATION;
     }
 
+
+
+    size_t pipelineMax = getBufferCountLocked();
+    size_t clampedCount = (pipelineMax < static_cast<size_t>(maxCount)) ?
+            pipelineMax : static_cast<size_t>(maxCount);
+    size_t bufferCount = (maxCount == Camera3StreamInterface::ALLOCATE_PIPELINE_MAX) ?
+            pipelineMax : clampedCount;
+
+    mPrepared = bufferCount <= mLastMaxCount;
+
     if (mPrepared) return OK;
 
-    size_t bufferCount = getBufferCountLocked();
+    mLastMaxCount = bufferCount;
 
     mPreparedBuffers.insertAt(camera3_stream_buffer_t(), /*index*/0, bufferCount);
     mPreparedBufferIdx = 0;
@@ -438,8 +455,9 @@
         res = mOutputBufferReturnedSignal.waitRelative(mLock, kWaitForBufferDuration);
         if (res != OK) {
             if (res == TIMED_OUT) {
-                ALOGE("%s: wait for output buffer return timed out after %lldms", __FUNCTION__,
-                        kWaitForBufferDuration / 1000000LL);
+                ALOGE("%s: wait for output buffer return timed out after %lldms (max_buffers %d)",
+                        __FUNCTION__, kWaitForBufferDuration / 1000000LL,
+                        camera3_stream::max_buffers);
             }
             return res;
         }
@@ -469,9 +487,12 @@
     status_t res = returnBufferLocked(buffer, timestamp);
     if (res == OK) {
         fireBufferListenersLocked(buffer, /*acquired*/false, /*output*/true);
-        mOutputBufferReturnedSignal.signal();
     }
 
+    // Even if returning the buffer failed, we still want to signal whoever is waiting for the
+    // buffer to be returned.
+    mOutputBufferReturnedSignal.signal();
+
     return res;
 }
 
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index bab2177..753280b 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -188,7 +188,9 @@
 
     /**
      * Start stream preparation. May only be called in the CONFIGURED state,
-     * when no valid buffers have yet been returned to this stream.
+     * when no valid buffers have yet been returned to this stream. Prepares
+     * up to maxCount buffers, or the maximum number of buffers needed by the
+     * pipeline if maxCount is ALLOCATE_PIPELINE_MAX.
      *
      * If no prepartion is necessary, returns OK and does not transition to
      * PREPARING state. Otherwise, returns NOT_ENOUGH_DATA and transitions
@@ -204,7 +206,7 @@
      *    INVALID_OPERATION if called when not in CONFIGURED state, or a
      *        valid buffer has already been returned to this stream.
      */
-    status_t         startPrepare();
+    status_t         startPrepare(int maxCount);
 
     /**
      * Check if the stream is mid-preparing.
@@ -444,6 +446,9 @@
     Vector<camera3_stream_buffer_t> mPreparedBuffers;
     size_t mPreparedBufferIdx;
 
+    // Number of buffers allocated on last prepare call.
+    int mLastMaxCount;
+
 }; // class Camera3Stream
 
 }; // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index c086eaf..54009ae 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -34,6 +34,11 @@
  */
 class Camera3StreamInterface : public virtual RefBase {
   public:
+
+    enum {
+        ALLOCATE_PIPELINE_MAX = 0, // Allocate max buffers used by a given surface
+    };
+
     /**
      * Get the stream's ID
      */
@@ -98,7 +103,9 @@
 
     /**
      * Start stream preparation. May only be called in the CONFIGURED state,
-     * when no valid buffers have yet been returned to this stream.
+     * when no valid buffers have yet been returned to this stream. Prepares
+     * up to maxCount buffers, or the maximum number of buffers needed by the
+     * pipeline if maxCount is ALLOCATE_PIPELINE_MAX.
      *
      * If no prepartion is necessary, returns OK and does not transition to
      * PREPARING state. Otherwise, returns NOT_ENOUGH_DATA and transitions
@@ -112,7 +119,7 @@
      *    INVALID_OPERATION if called when not in CONFIGURED state, or a
      *        valid buffer has already been returned to this stream.
      */
-    virtual status_t startPrepare() = 0;
+    virtual status_t startPrepare(int maxCount) = 0;
 
     /**
      * Check if the stream is mid-preparing.
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index e54cc5a..4790754 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -96,6 +96,15 @@
     const size_t SIZE = 256;
     char buffer[SIZE];
 
+    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
+        result.format("Permission Denial: "
+                "can't dump ResourceManagerService from pid=%d, uid=%d\n",
+                IPCThreadState::self()->getCallingPid(),
+                IPCThreadState::self()->getCallingUid());
+        write(fd, result.string(), result.size());
+        return PERMISSION_DENIED;
+    }
+
     snprintf(buffer, SIZE, "ResourceManagerService: %p\n", this);
     result.append(buffer);
     result.append("  Policies:\n");