Merge changes Ia529bf53,I10888d0b into mnc-dev

* changes:
  Enable building with clang/llvm.
  Enable clang compilation.
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
index 51a775b..a02dbe2 100644
--- a/camera/ICameraService.cpp
+++ b/camera/ICameraService.cpp
@@ -20,6 +20,7 @@
 #include <utils/Errors.h>
 #include <utils/String16.h>
 
+#include <inttypes.h>
 #include <stdint.h>
 #include <sys/types.h>
 
@@ -303,10 +304,10 @@
         return res;
     }
 
-    virtual void notifySystemEvent(int eventId, int arg0) {
+    virtual void notifySystemEvent(int32_t eventId, const int32_t* args, size_t len) {
         Parcel data, reply;
         data.writeInt32(eventId);
-        data.writeInt32(arg0);
+        data.writeInt32Array(len, args);
         remote()->transact(BnCameraService::NOTIFY_SYSTEM_EVENT, data, &reply,
                 IBinder::FLAG_ONEWAY);
     }
@@ -481,9 +482,26 @@
         } break;
         case NOTIFY_SYSTEM_EVENT: {
             CHECK_INTERFACE(ICameraService, data, reply);
-            int eventId = data.readInt32();
-            int arg0 = data.readInt32();
-            notifySystemEvent(eventId, arg0);
+            int32_t eventId = data.readInt32();
+            int32_t len = data.readInt32();
+            if (len < 0) {
+                ALOGE("%s: Received poorly formatted length in binder request: notifySystemEvent.",
+                        __FUNCTION__);
+                return FAILED_TRANSACTION;
+            }
+            if (len > 512) {
+                ALOGE("%s: Length %" PRIi32 " too long in binder request: notifySystemEvent.",
+                        __FUNCTION__, len);
+                return FAILED_TRANSACTION;
+            }
+            int32_t events[len] = {};
+            status_t status = data.read(events, sizeof(int32_t) * len);
+            if (status != NO_ERROR) {
+                ALOGE("%s: Received poorly formatted binder request: notifySystemEvent.",
+                        __FUNCTION__);
+                return FAILED_TRANSACTION;
+            }
+            notifySystemEvent(eventId, events, len);
             return NO_ERROR;
         } break;
         default:
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c
index 9d15835..6a0b3c0 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c
@@ -19,6 +19,7 @@
 #include <fcntl.h>
 #include <limits.h>
 #include <pthread.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
 #include <unistd.h>
diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h
index cad275e..5f85635 100644
--- a/include/camera/ICameraService.h
+++ b/include/camera/ICameraService.h
@@ -164,7 +164,7 @@
     /**
      * Notify the camera service of a system event.  Should only be called from system_server.
      */
-    virtual void notifySystemEvent(int eventId, int arg0) = 0;
+    virtual void notifySystemEvent(int32_t eventId, const int32_t* args, size_t length) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 47de0ca..77ed5d3 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -56,7 +56,7 @@
     virtual status_t init() = 0;
     virtual status_t close() = 0;
     virtual status_t release() = 0;
-    virtual status_t usePersistentSurface(const sp<IGraphicBufferConsumer>& surface) = 0;
+    virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface) = 0;
     virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() = 0;
 };
 
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index df3aeca..d33d142 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -118,7 +118,7 @@
             sp<IGraphicBufferProducer> *bufferProducer,
             sp<IGraphicBufferConsumer> *bufferConsumer) = 0;
 
-    virtual status_t usePersistentInputSurface(
+    virtual status_t setInputSurface(
             node_id node, OMX_U32 port_index,
             const sp<IGraphicBufferConsumer> &bufferConsumer) = 0;
 
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index 9947309..d6cc4bb 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -57,7 +57,7 @@
     virtual status_t reset() = 0;
     virtual status_t getMaxAmplitude(int *max) = 0;
     virtual status_t dump(int fd, const Vector<String16>& args) const = 0;
-    virtual status_t usePersistentSurface(const sp<IGraphicBufferConsumer>& surface) = 0;
+    virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface) = 0;
     virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() const = 0;
 
 
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index 9210feb..15ff82d 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -237,7 +237,7 @@
     status_t    close();
     status_t    release();
     void        notify(int msg, int ext1, int ext2);
-    status_t    usePersistentSurface(const sp<PersistentSurface>& surface);
+    status_t    setInputSurface(const sp<PersistentSurface>& surface);
     sp<IGraphicBufferProducer>     querySurfaceMediaSourceFromMediaServer();
 
 private:
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index b8327a3..4ed97e5 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -44,8 +44,7 @@
     virtual void initiateAllocateComponent(const sp<AMessage> &msg);
     virtual void initiateConfigureComponent(const sp<AMessage> &msg);
     virtual void initiateCreateInputSurface();
-    virtual void initiateUsePersistentInputSurface(
-            const sp<PersistentSurface> &surface);
+    virtual void initiateSetInputSurface(const sp<PersistentSurface> &surface);
     virtual void initiateStart();
     virtual void initiateShutdown(bool keepComponentAllocated = false);
 
@@ -119,7 +118,7 @@
         kWhatConfigureComponent      = 'conf',
         kWhatSetSurface              = 'setS',
         kWhatCreateInputSurface      = 'cisf',
-        kWhatUsePersistentInputSurface = 'pisf',
+        kWhatSetInputSurface         = 'sisf',
         kWhatSignalEndOfInputStream  = 'eois',
         kWhatStart                   = 'star',
         kWhatRequestIDRFrame         = 'ridr',
@@ -147,8 +146,13 @@
             OWNED_BY_UPSTREAM,
             OWNED_BY_DOWNSTREAM,
             OWNED_BY_NATIVE_WINDOW,
+            UNRECOGNIZED,            // not a tracked buffer
         };
 
+        static inline Status getSafeStatus(BufferInfo *info) {
+            return info == NULL ? UNRECOGNIZED : info->mStatus;
+        }
+
         IOMX::buffer_id mBufferID;
         Status mStatus;
         unsigned mDequeuedAt;
@@ -157,6 +161,9 @@
         sp<GraphicBuffer> mGraphicBuffer;
     };
 
+    static const char *_asString(BufferInfo::Status s);
+    void dumpBuffers(OMX_U32 portIndex);
+
 #if TRACK_BUFFER_TIMING
     struct BufferStats {
         int64_t mEmptyBufferTimeUs;
diff --git a/include/media/stagefright/CodecBase.h b/include/media/stagefright/CodecBase.h
index 51213b6..989df4f 100644
--- a/include/media/stagefright/CodecBase.h
+++ b/include/media/stagefright/CodecBase.h
@@ -50,7 +50,7 @@
     virtual void initiateAllocateComponent(const sp<AMessage> &msg) = 0;
     virtual void initiateConfigureComponent(const sp<AMessage> &msg) = 0;
     virtual void initiateCreateInputSurface() = 0;
-    virtual void initiateUsePersistentInputSurface(
+    virtual void initiateSetInputSurface(
             const sp<PersistentSurface> &surface) = 0;
     virtual void initiateStart() = 0;
     virtual void initiateShutdown(bool keepComponentAllocated = false) = 0;
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index 82c768d..6e14fc5 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -80,7 +80,7 @@
 
     status_t createInputSurface(sp<IGraphicBufferProducer>* bufferProducer);
 
-    status_t usePersistentInputSurface(const sp<PersistentSurface> &surface);
+    status_t setInputSurface(const sp<PersistentSurface> &surface);
 
     status_t start();
 
@@ -193,7 +193,7 @@
         kWhatConfigure                      = 'conf',
         kWhatSetSurface                     = 'sSur',
         kWhatCreateInputSurface             = 'cisf',
-        kWhatUsePersistentInputSurface      = 'pisf',
+        kWhatSetInputSurface                = 'sisf',
         kWhatStart                          = 'strt',
         kWhatStop                           = 'stop',
         kWhatRelease                        = 'rele',
diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h
index 3b58122..21eb04a 100644
--- a/include/media/stagefright/MediaDefs.h
+++ b/include/media/stagefright/MediaDefs.h
@@ -64,7 +64,7 @@
 extern const char *MEDIA_MIMETYPE_TEXT_SUBRIP;
 extern const char *MEDIA_MIMETYPE_TEXT_VTT;
 extern const char *MEDIA_MIMETYPE_TEXT_CEA_608;
-extern const char *MEDIA_MIMETYPE_DATA_METADATA;
+extern const char *MEDIA_MIMETYPE_DATA_TIMED_ID3;
 
 }  // namespace android
 
diff --git a/include/media/stagefright/MediaFilter.h b/include/media/stagefright/MediaFilter.h
index fdd2a34..d0a572c 100644
--- a/include/media/stagefright/MediaFilter.h
+++ b/include/media/stagefright/MediaFilter.h
@@ -34,8 +34,7 @@
     virtual void initiateAllocateComponent(const sp<AMessage> &msg);
     virtual void initiateConfigureComponent(const sp<AMessage> &msg);
     virtual void initiateCreateInputSurface();
-    virtual void initiateUsePersistentInputSurface(
-            const sp<PersistentSurface> &surface);
+    virtual void initiateSetInputSurface(const sp<PersistentSurface> &surface);
 
     virtual void initiateStart();
     virtual void initiateShutdown(bool keepComponentAllocated = false);
diff --git a/include/media/stagefright/MediaSync.h b/include/media/stagefright/MediaSync.h
index d1d634d..1eef211 100644
--- a/include/media/stagefright/MediaSync.h
+++ b/include/media/stagefright/MediaSync.h
@@ -169,7 +169,7 @@
     class OutputListener : public BnProducerListener,
                            public IBinder::DeathRecipient {
     public:
-        OutputListener(const sp<MediaSync> &sync);
+        OutputListener(const sp<MediaSync> &sync, const sp<IGraphicBufferProducer> &output);
         virtual ~OutputListener();
 
         // From IProducerListener
@@ -180,6 +180,7 @@
 
     private:
         sp<MediaSync> mSync;
+        sp<IGraphicBufferProducer> mOutput;
     };
 
     // mIsAbandoned is set to true when the input or output dies.
@@ -192,6 +193,7 @@
     size_t mNumOutstandingBuffers;
     sp<IGraphicBufferConsumer> mInput;
     sp<IGraphicBufferProducer> mOutput;
+    int mUsageFlagsFromOutput;
 
     sp<AudioTrack> mAudioTrack;
     uint32_t mNativeSampleRateInHz;
@@ -207,6 +209,12 @@
     // and that could cause problem if the producer of |mInput| only
     // supports pre-registered buffers.
     KeyedVector<uint64_t, sp<GraphicBuffer> > mBuffersFromInput;
+
+    // Keep track of buffers sent to |mOutput|. When a new output surface comes
+    // in, those buffers will be returned to input and old output surface will
+    // be disconnected immediately.
+    KeyedVector<uint64_t, sp<GraphicBuffer> > mBuffersSentToOutput;
+
     sp<ALooper> mLooper;
     float mPlaybackRate;
 
@@ -241,7 +249,7 @@
     // It gets called from an OutputListener.
     // During this callback, we detach the buffer from the output, and release
     // it to the input. A blocked onFrameAvailable call will be allowed to proceed.
-    void onBufferReleasedByOutput();
+    void onBufferReleasedByOutput(sp<IGraphicBufferProducer> &output);
 
     // Return |buffer| back to the input.
     void returnBufferToInput_l(const sp<GraphicBuffer> &buffer, const sp<Fence> &fence);
diff --git a/include/media/stagefright/foundation/AUtils.h b/include/media/stagefright/foundation/AUtils.h
index d7ecf50..47444c1 100644
--- a/include/media/stagefright/foundation/AUtils.h
+++ b/include/media/stagefright/foundation/AUtils.h
@@ -61,6 +61,28 @@
     return a > b ? a : b;
 }
 
+template<class T>
+void ENSURE_UNSIGNED_TYPE() {
+    T TYPE_MUST_BE_UNSIGNED[(T)-1 < 0 ? -1 : 0] __unused;
+}
+
+// needle is in range [hayStart, hayStart + haySize)
+template<class T, class U>
+inline static bool isInRange(const T &hayStart, const U &haySize, const T &needle) {
+    ENSURE_UNSIGNED_TYPE<U>();
+    return (T)(hayStart + haySize) >= hayStart && needle >= hayStart && (U)(needle - hayStart) < haySize;
+}
+
+// [needleStart, needleStart + needleSize) is in range [hayStart, hayStart + haySize)
+template<class T, class U>
+inline static bool isInRange(
+        const T &hayStart, const U &haySize, const T &needleStart, const U &needleSize) {
+    ENSURE_UNSIGNED_TYPE<U>();
+    return isInRange(hayStart, haySize, needleStart)
+            && (T)(needleStart + needleSize) >= needleStart
+            && (U)(needleStart + needleSize - hayStart) <= haySize;
+}
+
 /* T must be integer type, period must be positive */
 template<class T>
 inline static T periodicError(const T &val, const T &period) {
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index c7a1394..ee3b584 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -35,7 +35,7 @@
     RELEASE = IBinder::FIRST_CALL_TRANSACTION,
     INIT,
     CLOSE,
-    USE_PERSISTENT_SURFACE,
+    SET_INPUT_SURFACE,
     QUERY_SURFACE_MEDIASOURCE,
     RESET,
     STOP,
@@ -76,13 +76,13 @@
         return reply.readInt32();
     }
 
-    status_t usePersistentSurface(const sp<IGraphicBufferConsumer>& surface)
+    status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface)
     {
-        ALOGV("usePersistentSurface(%p)", surface.get());
+        ALOGV("setInputSurface(%p)", surface.get());
         Parcel data, reply;
         data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
         data.writeStrongBinder(IInterface::asBinder(surface));
-        remote()->transact(USE_PERSISTENT_SURFACE, data, &reply);
+        remote()->transact(SET_INPUT_SURFACE, data, &reply);
         return reply.readInt32();
     }
 
@@ -453,12 +453,12 @@
             reply->writeInt32(setCamera(camera, proxy));
             return NO_ERROR;
         } break;
-        case USE_PERSISTENT_SURFACE: {
-            ALOGV("USE_PERSISTENT_SURFACE");
+        case SET_INPUT_SURFACE: {
+            ALOGV("SET_INPUT_SURFACE");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
             sp<IGraphicBufferConsumer> surface = interface_cast<IGraphicBufferConsumer>(
                     data.readStrongBinder());
-            reply->writeInt32(usePersistentSurface(surface));
+            reply->writeInt32(setInputSurface(surface));
             return NO_ERROR;
         } break;
         case QUERY_SURFACE_MEDIASOURCE: {
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 39b135b..c14debf 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -42,7 +42,7 @@
     USE_GRAPHIC_BUFFER,
     CREATE_INPUT_SURFACE,
     CREATE_PERSISTENT_INPUT_SURFACE,
-    USE_PERSISTENT_INPUT_SURFACE,
+    SET_INPUT_SURFACE,
     SIGNAL_END_OF_INPUT_STREAM,
     STORE_META_DATA_IN_BUFFERS,
     PREPARE_FOR_ADAPTIVE_PLAYBACK,
@@ -353,7 +353,7 @@
         return err;
     }
 
-    virtual status_t usePersistentInputSurface(
+    virtual status_t setInputSurface(
             node_id node, OMX_U32 port_index,
             const sp<IGraphicBufferConsumer> &bufferConsumer) {
         Parcel data, reply;
@@ -363,7 +363,7 @@
         data.writeInt32(port_index);
         data.writeStrongBinder(IInterface::asBinder(bufferConsumer));
 
-        err = remote()->transact(USE_PERSISTENT_INPUT_SURFACE, data, &reply);
+        err = remote()->transact(SET_INPUT_SURFACE, data, &reply);
 
         if (err != OK) {
             ALOGW("binder transaction failed: %d", err);
@@ -372,7 +372,6 @@
         return reply.readInt32();
     }
 
-
     virtual status_t signalEndOfInputStream(node_id node) {
         Parcel data, reply;
         status_t err;
@@ -847,7 +846,7 @@
             return NO_ERROR;
         }
 
-        case USE_PERSISTENT_INPUT_SURFACE:
+        case SET_INPUT_SURFACE:
         {
             CHECK_OMX_INTERFACE(IOMX, data, reply);
 
@@ -857,8 +856,7 @@
             sp<IGraphicBufferConsumer> bufferConsumer =
                     interface_cast<IGraphicBufferConsumer>(data.readStrongBinder());
 
-            status_t err = usePersistentInputSurface(
-                    node, port_index, bufferConsumer);
+            status_t err = setInputSurface(node, port_index, bufferConsumer);
 
             reply->writeInt32(err);
             return NO_ERROR;
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 1f8b1d3..8bbd8f1 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -345,9 +345,9 @@
 
 
 
-status_t MediaRecorder::usePersistentSurface(const sp<PersistentSurface>& surface)
+status_t MediaRecorder::setInputSurface(const sp<PersistentSurface>& surface)
 {
-    ALOGV("usePersistentSurface");
+    ALOGV("setInputSurface");
     if (mMediaRecorder == NULL) {
         ALOGE("media recorder is not initialized yet");
         return INVALID_OPERATION;
@@ -356,11 +356,11 @@
                            (MEDIA_RECORDER_PREPARED |
                             MEDIA_RECORDER_RECORDING));
     if (isInvalidState) {
-        ALOGE("usePersistentSurface is called in an invalid state: %d", mCurrentState);
+        ALOGE("setInputSurface is called in an invalid state: %d", mCurrentState);
         return INVALID_OPERATION;
     }
 
-    return mMediaRecorder->usePersistentSurface(surface->getBufferConsumer());
+    return mMediaRecorder->setInputSurface(surface->getBufferConsumer());
 }
 
 status_t MediaRecorder::setVideoFrameRate(int frames_per_second)
diff --git a/media/libmediaplayerservice/Drm.cpp b/media/libmediaplayerservice/Drm.cpp
index d55482d..a7f6f8b 100644
--- a/media/libmediaplayerservice/Drm.cpp
+++ b/media/libmediaplayerservice/Drm.cpp
@@ -358,7 +358,18 @@
     status_t err = mPlugin->openSession(sessionId);
     if (err == ERROR_DRM_RESOURCE_BUSY) {
         bool retry = false;
+        mLock.unlock();
+        // reclaimSession may call back to closeSession, since mLock is shared between Drm
+        // instances, we should unlock here to avoid deadlock.
         retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
+        mLock.lock();
+        if (mInitCheck != OK) {
+            return mInitCheck;
+        }
+
+        if (mPlugin == NULL) {
+            return -EINVAL;
+        }
         if (retry) {
             err = mPlugin->openSession(sessionId);
         }
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index ed442e3..f761dec 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -55,15 +55,15 @@
     return ok;
 }
 
-status_t MediaRecorderClient::usePersistentSurface(const sp<IGraphicBufferConsumer>& surface)
+status_t MediaRecorderClient::setInputSurface(const sp<IGraphicBufferConsumer>& surface)
 {
-    ALOGV("usePersistentSurface");
+    ALOGV("setInputSurface");
     Mutex::Autolock lock(mLock);
     if (mRecorder == NULL) {
         ALOGE("recorder is not initialized");
         return NO_INIT;
     }
-    return mRecorder->usePersistentSurface(surface);
+    return mRecorder->setInputSurface(surface);
 }
 
 sp<IGraphicBufferProducer> MediaRecorderClient::querySurfaceMediaSource()
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 7ac88cb..05130d4 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -55,7 +55,7 @@
     virtual     status_t   close();
     virtual     status_t   release();
     virtual     status_t   dump(int fd, const Vector<String16>& args);
-    virtual     status_t   usePersistentSurface(const sp<IGraphicBufferConsumer>& surface);
+    virtual     status_t   setInputSurface(const sp<IGraphicBufferConsumer>& surface);
     virtual     sp<IGraphicBufferProducer> querySurfaceMediaSource();
 
 private:
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 509a592..e16a4b5 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -243,7 +243,7 @@
     return OK;
 }
 
-status_t StagefrightRecorder::usePersistentSurface(
+status_t StagefrightRecorder::setInputSurface(
         const sp<IGraphicBufferConsumer>& surface) {
     mPersistentSurface = surface;
 
@@ -1752,6 +1752,7 @@
     }
 
     mGraphicBufferProducer.clear();
+    mPersistentSurface.clear();
 
     if (mOutputFd >= 0) {
         ::close(mOutputFd);
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 1a7b720..7473f42 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -54,7 +54,7 @@
     virtual status_t setVideoFrameRate(int frames_per_second);
     virtual status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);
     virtual status_t setPreviewSurface(const sp<IGraphicBufferProducer>& surface);
-    virtual status_t usePersistentSurface(const sp<IGraphicBufferConsumer>& surface);
+    virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface);
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
     virtual status_t setParameters(const String8& params);
     virtual status_t setListener(const sp<IMediaRecorderClient>& listener);
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
index 39b8d09..126625a 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -161,24 +161,22 @@
 
     status_t err = INVALID_OPERATION;
     bool postFetchMsg = false, isSub = false;
-    if (trackIndex != mLiveSession->getTrackCount() - 1) {
+    if (!mHasMetadata || trackIndex != mLiveSession->getTrackCount() - 1) {
         err = mLiveSession->selectTrack(trackIndex, select);
         postFetchMsg = select;
         isSub = true;
     } else {
-        // metadata track
-        if (mHasMetadata) {
-            if (mMetadataSelected && !select) {
-                err = OK;
-            } else if (!mMetadataSelected && select) {
-                postFetchMsg = true;
-                err = OK;
-            } else {
-                err = BAD_VALUE; // behave as LiveSession::selectTrack
-            }
-
-            mMetadataSelected = select;
+        // metadata track; i.e. (mHasMetadata && trackIndex == mLiveSession->getTrackCount() - 1)
+        if (mMetadataSelected && !select) {
+            err = OK;
+        } else if (!mMetadataSelected && select) {
+            postFetchMsg = true;
+            err = OK;
+        } else {
+            err = BAD_VALUE; // behave as LiveSession::selectTrack
         }
+
+        mMetadataSelected = select;
     }
 
     if (err == OK) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 6b8f99c..007a335 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -146,7 +146,7 @@
         return OK;
     }
 
-    if (mAudioSink != NULL) {
+    if (mAudioSink != NULL && mAudioSink->ready()) {
         status_t err = mAudioSink->setPlaybackRate(rate);
         if (err != OK) {
             return err;
@@ -172,7 +172,7 @@
 }
 
 status_t NuPlayer::Renderer::onGetPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
-    if (mAudioSink != NULL) {
+    if (mAudioSink != NULL && mAudioSink->ready()) {
         status_t err = mAudioSink->getPlaybackRate(rate);
         if (err == OK) {
             if (!isAudioPlaybackRateEqual(*rate, mPlaybackSettings)) {
@@ -1378,7 +1378,7 @@
         mPaused = false;
 
         // configure audiosink as we did not do it when pausing
-        if (mAudioSink != NULL) {
+        if (mAudioSink != NULL && mAudioSink->ready()) {
             mAudioSink->setPlaybackRate(mPlaybackSettings);
         }
 
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index b9ae125..34bd4c7 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -49,6 +49,7 @@
 #include <OMX_VideoExt.h>
 #include <OMX_Component.h>
 #include <OMX_IndexExt.h>
+#include <OMX_AsString.h>
 
 #include "include/avc_utils.h"
 
@@ -154,7 +155,7 @@
             }
 
             default:
-                TRESPASS();
+                ALOGE("Unrecognized message type: %d", omx_msg.type);
                 break;
         }
 
@@ -261,7 +262,7 @@
 
     bool onConfigureComponent(const sp<AMessage> &msg);
     void onCreateInputSurface(const sp<AMessage> &msg);
-    void onUsePersistentInputSurface(const sp<AMessage> &msg);
+    void onSetInputSurface(const sp<AMessage> &msg);
     void onStart();
     void onShutdown(bool keepComponentAllocated);
 
@@ -498,9 +499,9 @@
     (new AMessage(kWhatCreateInputSurface, this))->post();
 }
 
-void ACodec::initiateUsePersistentInputSurface(
+void ACodec::initiateSetInputSurface(
         const sp<PersistentSurface> &surface) {
-    sp<AMessage> msg = new AMessage(kWhatUsePersistentInputSurface, this);
+    sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
     msg->setObject("input-surface", surface);
     msg->post();
 }
@@ -697,7 +698,9 @@
 
             for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
                 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
-                CHECK(mem.get() != NULL);
+                if (mem == NULL || mem->pointer() == NULL) {
+                    return NO_MEMORY;
+                }
 
                 BufferInfo info;
                 info.mStatus = BufferInfo::OWNED_BY_US;
@@ -987,7 +990,9 @@
 
         sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate(
                 sizeof(struct VideoDecoderOutputMetaData));
-        CHECK(mem.get() != NULL);
+        if (mem == NULL || mem->pointer() == NULL) {
+            return NO_MEMORY;
+        }
         info.mData = new ABuffer(mem->pointer(), mem->size());
 
         // we use useBuffer for metadata regardless of quirks
@@ -1049,18 +1054,46 @@
         return OK;
 
     BufferInfo *info = dequeueBufferFromNativeWindow();
-    if (info == NULL)
+    if (info == NULL) {
         return ERROR_IO;
+    }
 
     ALOGV("[%s] submitting output meta buffer ID %u for graphic buffer %p",
           mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer.get());
 
     --mMetaDataBuffersToSubmit;
-    CHECK_EQ(mOMX->fillBuffer(mNode, info->mBufferID),
-             (status_t)OK);
+    status_t err = mOMX->fillBuffer(mNode, info->mBufferID);
+    if (err == OK) {
+        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
+    }
 
-    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
-    return OK;
+    return err;
+}
+
+// static
+const char *ACodec::_asString(BufferInfo::Status s) {
+    switch (s) {
+        case BufferInfo::OWNED_BY_US:            return "OUR";
+        case BufferInfo::OWNED_BY_COMPONENT:     return "COMPONENT";
+        case BufferInfo::OWNED_BY_UPSTREAM:      return "UPSTREAM";
+        case BufferInfo::OWNED_BY_DOWNSTREAM:    return "DOWNSTREAM";
+        case BufferInfo::OWNED_BY_NATIVE_WINDOW: return "SURFACE";
+        case BufferInfo::UNRECOGNIZED:           return "UNRECOGNIZED";
+        default:                                 return "?";
+    }
+}
+
+void ACodec::dumpBuffers(OMX_U32 portIndex) {
+    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
+    ALOGI("[%s] %s port has %zu buffers:", mComponentName.c_str(),
+            portIndex == kPortIndexInput ? "input" : "output", mBuffers[portIndex].size());
+    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
+        const BufferInfo &info = mBuffers[portIndex][i];
+        ALOGI("  slot %2zu: #%8u %p/%p %s(%d) dequeued:%u",
+                i, info.mBufferID, info.mGraphicBuffer.get(),
+                info.mGraphicBuffer == NULL ? NULL : info.mGraphicBuffer->getNativeBuffer(),
+                _asString(info.mStatus), info.mStatus, info.mDequeuedAt);
+    }
 }
 
 status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
@@ -1074,7 +1107,7 @@
 
     ALOGW_IF(err != 0, "[%s] can not return buffer %u to native window",
             mComponentName.c_str(), info->mBufferID);
-
+    // change ownership even if cancelBuffer fails
     info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
 
     return err;
@@ -1150,47 +1183,50 @@
         }
     }
 
-    if (oldest) {
-        CHECK(mStoreMetaDataInOutputBuffers);
+    // it is impossible dequeue a buffer when there are no buffers with ANW
+    CHECK(oldest != NULL);
+    // it is impossible to dequeue an unknown buffer in non-meta mode, as the
+    // while loop above does not complete
+    CHECK(mStoreMetaDataInOutputBuffers);
 
-        // discard buffer in LRU info and replace with new buffer
-        oldest->mGraphicBuffer = new GraphicBuffer(buf, false);
-        oldest->mStatus = BufferInfo::OWNED_BY_US;
+    // discard buffer in LRU info and replace with new buffer
+    oldest->mGraphicBuffer = new GraphicBuffer(buf, false);
+    oldest->mStatus = BufferInfo::OWNED_BY_US;
 
-        mOMX->updateGraphicBufferInMeta(
-                mNode, kPortIndexOutput, oldest->mGraphicBuffer,
-                oldest->mBufferID);
+    mOMX->updateGraphicBufferInMeta(
+            mNode, kPortIndexOutput, oldest->mGraphicBuffer,
+            oldest->mBufferID);
 
-        VideoDecoderOutputMetaData *metaData =
-            reinterpret_cast<VideoDecoderOutputMetaData *>(
-                    oldest->mData->base());
-        CHECK_EQ(metaData->eType, kMetadataBufferTypeGrallocSource);
+    VideoDecoderOutputMetaData *metaData =
+        reinterpret_cast<VideoDecoderOutputMetaData *>(
+                oldest->mData->base());
+    CHECK_EQ(metaData->eType, kMetadataBufferTypeGrallocSource);
 
-        ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
-                (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
-                mDequeueCounter - oldest->mDequeuedAt,
-                metaData->pHandle,
-                oldest->mGraphicBuffer->handle, oldest->mData->base());
+    ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
+            (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
+            mDequeueCounter - oldest->mDequeuedAt,
+            metaData->pHandle,
+            oldest->mGraphicBuffer->handle, oldest->mData->base());
 
-        return oldest;
-    }
-
-    TRESPASS();
-
-    return NULL;
+    return oldest;
 }
 
 status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
+    status_t err = OK;
     for (size_t i = mBuffers[portIndex].size(); i-- > 0;) {
-        CHECK_EQ((status_t)OK, freeBuffer(portIndex, i));
+        status_t err2 = freeBuffer(portIndex, i);
+        if (err == OK) {
+            err = err2;
+        }
     }
 
+    // clear mDealer even on an error
     mDealer[portIndex].clear();
-
-    return OK;
+    return err;
 }
 
 status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
+    status_t err = OK;
     for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
         BufferInfo *info =
             &mBuffers[kPortIndexOutput].editItemAt(i);
@@ -1199,36 +1235,45 @@
         // or being drained.
         if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT &&
             info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) {
-            CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i));
+            status_t err2 = freeBuffer(kPortIndexOutput, i);
+            if (err == OK) {
+                err = err2;
+            }
         }
     }
 
-    return OK;
+    return err;
 }
 
 status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
     BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
+    status_t err = OK;
 
-    CHECK(info->mStatus == BufferInfo::OWNED_BY_US
-            || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
+    switch (info->mStatus) {
+        case BufferInfo::OWNED_BY_US:
+            if (portIndex == kPortIndexOutput && mNativeWindow != NULL) {
+                (void)cancelBufferToNativeWindow(info);
+            }
+            // fall through
 
-    if (portIndex == kPortIndexOutput && mNativeWindow != NULL
-            && info->mStatus == BufferInfo::OWNED_BY_US) {
-        cancelBufferToNativeWindow(info);
+        case BufferInfo::OWNED_BY_NATIVE_WINDOW:
+            err = mOMX->freeBuffer(mNode, portIndex, info->mBufferID);
+            break;
+
+        default:
+            ALOGE("trying to free buffer not owned by us or ANW (%d)", info->mStatus);
+            err = FAILED_TRANSACTION;
+            break;
     }
 
-    CHECK_EQ(mOMX->freeBuffer(
-                mNode, portIndex, info->mBufferID),
-             (status_t)OK);
-
+    // remove buffer even if mOMX->freeBuffer fails
     mBuffers[portIndex].removeAt(i);
 
-    return OK;
+    return err;
 }
 
 ACodec::BufferInfo *ACodec::findBufferByID(
-        uint32_t portIndex, IOMX::buffer_id bufferID,
-        ssize_t *index) {
+        uint32_t portIndex, IOMX::buffer_id bufferID, ssize_t *index) {
     for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
         BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
 
@@ -1240,8 +1285,7 @@
         }
     }
 
-    TRESPASS();
-
+    ALOGE("Could not find buffer with ID %u", bufferID);
     return NULL;
 }
 
@@ -1638,22 +1682,30 @@
 
         if (haveNativeWindow) {
             mNativeWindow = static_cast<Surface *>(obj.get());
-            CHECK(mNativeWindow != NULL);
         }
 
         // initialize native window now to get actual output format
         // TODO: this is needed for some encoders even though they don't use native window
-        CHECK_EQ((status_t)OK, initNativeWindow());
+        err = initNativeWindow();
+        if (err != OK) {
+            return err;
+        }
 
         // fallback for devices that do not handle flex-YUV for native buffers
         if (haveNativeWindow) {
             int32_t requestedColorFormat = OMX_COLOR_FormatUnused;
             if (msg->findInt32("color-format", &requestedColorFormat) &&
                     requestedColorFormat == OMX_COLOR_FormatYUV420Flexible) {
-                CHECK_EQ(getPortFormat(kPortIndexOutput, outputFormat), (status_t)OK);
+                status_t err = getPortFormat(kPortIndexOutput, outputFormat);
+                if (err != OK) {
+                    return err;
+                }
                 int32_t colorFormat = OMX_COLOR_FormatUnused;
                 OMX_U32 flexibleEquivalent = OMX_COLOR_FormatUnused;
-                CHECK(outputFormat->findInt32("color-format", &colorFormat));
+                if (!outputFormat->findInt32("color-format", &colorFormat)) {
+                    ALOGE("ouptut port did not have a color format (wrong domain?)");
+                    return BAD_VALUE;
+                }
                 ALOGD("[%s] Requested output format %#x and got %#x.",
                         mComponentName.c_str(), requestedColorFormat, colorFormat);
                 if (!isFlexibleColorFormat(
@@ -1874,11 +1926,14 @@
 
     mBaseOutputFormat = outputFormat;
 
-    CHECK_EQ(getPortFormat(kPortIndexInput, inputFormat), (status_t)OK);
-    CHECK_EQ(getPortFormat(kPortIndexOutput, outputFormat), (status_t)OK);
-    mInputFormat = inputFormat;
-    mOutputFormat = outputFormat;
-
+    err = getPortFormat(kPortIndexInput, inputFormat);
+    if (err == OK) {
+        err = getPortFormat(kPortIndexOutput, outputFormat);
+        if (err == OK) {
+            mInputFormat = inputFormat;
+            mOutputFormat = outputFormat;
+        }
+    }
     return err;
 }
 
@@ -1958,7 +2013,10 @@
         return err;
     }
 
-    CHECK(def.nBufferSize >= size);
+    if (def.nBufferSize < size) {
+        ALOGE("failed to set min buffer size to %zu (is still %u)", size, def.nBufferSize);
+        return FAILED_TRANSACTION;
+    }
 
     return OK;
 }
@@ -2286,7 +2344,9 @@
 }
 
 status_t ACodec::setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels) {
-    CHECK(!encoder);  // XXX TODO
+    if (encoder) {
+        return INVALID_OPERATION;
+    }
 
     return setupRawAudioFormat(
             kPortIndexInput, sampleRate, numChannels);
@@ -3395,8 +3455,9 @@
 
     status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
-
-    CHECK_EQ(err, (status_t)OK);
+    if (err != OK) {
+        return err;
+    }
 
     if (portIndex == kPortIndexInput) {
         // XXX Need a (much) better heuristic to compute input buffer sizes.
@@ -3406,7 +3467,10 @@
         }
     }
 
-    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
+    if (def.eDomain != OMX_PortDomainVideo) {
+        ALOGE("expected video port, got %s(%d)", asString(def.eDomain), def.eDomain);
+        return FAILED_TRANSACTION;
+    }
 
     video_def->nFrameWidth = width;
     video_def->nFrameHeight = height;
@@ -3683,17 +3747,20 @@
 }
 
 status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
-    // TODO: catch errors an return them instead of using CHECK
+    const char *niceIndex = portIndex == kPortIndexInput ? "input" : "output";
     OMX_PARAM_PORTDEFINITIONTYPE def;
     InitOMXParams(&def);
     def.nPortIndex = portIndex;
 
-    CHECK_EQ(mOMX->getParameter(
-                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
-             (status_t)OK);
+    status_t err = mOMX->getParameter(mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    if (err != OK) {
+        return err;
+    }
 
-    CHECK_EQ((int)def.eDir,
-            (int)(portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput));
+    if (def.eDir != (portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)) {
+        ALOGE("unexpected dir: %s(%d) on %s port", asString(def.eDir), def.eDir, niceIndex);
+        return BAD_VALUE;
+    }
 
     switch (def.eDomain) {
         case OMX_PortDomainVideo:
@@ -3756,12 +3823,16 @@
                         rect.nHeight = videoDef->nFrameHeight;
                     }
 
-                    CHECK_GE(rect.nLeft, 0);
-                    CHECK_GE(rect.nTop, 0);
-                    CHECK_GE(rect.nWidth, 0u);
-                    CHECK_GE(rect.nHeight, 0u);
-                    CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
-                    CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
+                    if (rect.nLeft < 0 ||
+                        rect.nTop < 0 ||
+                        rect.nLeft + rect.nWidth > videoDef->nFrameWidth ||
+                        rect.nTop + rect.nHeight > videoDef->nFrameHeight) {
+                        ALOGE("Wrong cropped rect (%d, %d) - (%u, %u) vs. frame (%u, %u)",
+                                rect.nLeft, rect.nTop,
+                                rect.nLeft + rect.nWidth, rect.nTop + rect.nHeight,
+                                videoDef->nFrameWidth, videoDef->nFrameHeight);
+                        return BAD_VALUE;
+                    }
 
                     notify->setRect(
                             "crop",
@@ -3818,7 +3889,13 @@
 
                 default:
                 {
-                    CHECK(mIsEncoder ^ (portIndex == kPortIndexInput));
+                    if (mIsEncoder ^ (portIndex == kPortIndexOutput)) {
+                        // should be CodingUnused
+                        ALOGE("Raw port video compression format is %s(%d)",
+                                asString(videoDef->eCompressionFormat),
+                                videoDef->eCompressionFormat);
+                        return BAD_VALUE;
+                    }
                     AString mime;
                     if (GetMimeTypeForVideoCoding(
                         videoDef->eCompressionFormat, &mime) != OK) {
@@ -3849,20 +3926,25 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    CHECK_EQ(mOMX->getParameter(
-                                mNode, OMX_IndexParamAudioPcm,
-                                &params, sizeof(params)),
-                             (status_t)OK);
+                    err = mOMX->getParameter(
+                            mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
+                    if (err != OK) {
+                        return err;
+                    }
 
-                    CHECK_GT(params.nChannels, 0);
-                    CHECK(params.nChannels == 1 || params.bInterleaved);
-                    CHECK_EQ(params.nBitPerSample, 16u);
-
-                    CHECK_EQ((int)params.eNumData,
-                             (int)OMX_NumericalDataSigned);
-
-                    CHECK_EQ((int)params.ePCMMode,
-                             (int)OMX_AUDIO_PCMModeLinear);
+                    if (params.nChannels <= 0
+                            || (params.nChannels != 1 && !params.bInterleaved)
+                            || params.nBitPerSample != 16u
+                            || params.eNumData != OMX_NumericalDataSigned
+                            || params.ePCMMode != OMX_AUDIO_PCMModeLinear) {
+                        ALOGE("unsupported PCM port: %u channels%s, %u-bit, %s(%d), %s(%d) mode ",
+                                params.nChannels,
+                                params.bInterleaved ? " interleaved" : "",
+                                params.nBitPerSample,
+                                asString(params.eNumData), params.eNumData,
+                                asString(params.ePCMMode), params.ePCMMode);
+                        return FAILED_TRANSACTION;
+                    }
 
                     notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
                     notify->setInt32("channel-count", params.nChannels);
@@ -3880,10 +3962,11 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    CHECK_EQ(mOMX->getParameter(
-                                mNode, OMX_IndexParamAudioAac,
-                                &params, sizeof(params)),
-                             (status_t)OK);
+                    err = mOMX->getParameter(
+                            mNode, OMX_IndexParamAudioAac, &params, sizeof(params));
+                    if (err != OK) {
+                        return err;
+                    }
 
                     notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
                     notify->setInt32("channel-count", params.nChannels);
@@ -3897,21 +3980,18 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    CHECK_EQ(mOMX->getParameter(
-                                mNode, OMX_IndexParamAudioAmr,
-                                &params, sizeof(params)),
-                             (status_t)OK);
+                    err = mOMX->getParameter(
+                            mNode, OMX_IndexParamAudioAmr, &params, sizeof(params));
+                    if (err != OK) {
+                        return err;
+                    }
 
                     notify->setInt32("channel-count", 1);
                     if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
-                        notify->setString(
-                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
-
+                        notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
                         notify->setInt32("sample-rate", 16000);
                     } else {
-                        notify->setString(
-                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
-
+                        notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
                         notify->setInt32("sample-rate", 8000);
                     }
                     break;
@@ -3923,10 +4003,11 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    CHECK_EQ(mOMX->getParameter(
-                                mNode, OMX_IndexParamAudioFlac,
-                                &params, sizeof(params)),
-                             (status_t)OK);
+                    err = mOMX->getParameter(
+                            mNode, OMX_IndexParamAudioFlac, &params, sizeof(params));
+                    if (err != OK) {
+                        return err;
+                    }
 
                     notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
                     notify->setInt32("channel-count", params.nChannels);
@@ -3940,10 +4021,11 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    CHECK_EQ(mOMX->getParameter(
-                                mNode, OMX_IndexParamAudioMp3,
-                                &params, sizeof(params)),
-                             (status_t)OK);
+                    err = mOMX->getParameter(
+                            mNode, OMX_IndexParamAudioMp3, &params, sizeof(params));
+                    if (err != OK) {
+                        return err;
+                    }
 
                     notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG);
                     notify->setInt32("channel-count", params.nChannels);
@@ -3957,10 +4039,11 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    CHECK_EQ(mOMX->getParameter(
-                                mNode, OMX_IndexParamAudioVorbis,
-                                &params, sizeof(params)),
-                             (status_t)OK);
+                    err = mOMX->getParameter(
+                            mNode, OMX_IndexParamAudioVorbis, &params, sizeof(params));
+                    if (err != OK) {
+                        return err;
+                    }
 
                     notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS);
                     notify->setInt32("channel-count", params.nChannels);
@@ -3974,11 +4057,12 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    CHECK_EQ((status_t)OK, mOMX->getParameter(
-                            mNode,
-                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
-                            &params,
-                            sizeof(params)));
+                    err = mOMX->getParameter(
+                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
+                            &params, sizeof(params));
+                    if (err != OK) {
+                        return err;
+                    }
 
                     notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
                     notify->setInt32("channel-count", params.nChannels);
@@ -3992,11 +4076,12 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    CHECK_EQ((status_t)OK, mOMX->getParameter(
-                            mNode,
-                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
-                            &params,
-                            sizeof(params)));
+                    err = mOMX->getParameter(
+                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
+                            &params, sizeof(params));
+                    if (err != OK) {
+                        return err;
+                    }
 
                     notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3);
                     notify->setInt32("channel-count", params.nChannels);
@@ -4010,11 +4095,12 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    CHECK_EQ((status_t)OK, mOMX->getParameter(
-                            mNode,
-                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
-                            &params,
-                            sizeof(params)));
+                    err = mOMX->getParameter(
+                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
+                            &params, sizeof(params));
+                    if (err != OK) {
+                        return err;
+                    }
 
                     notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS);
                     notify->setInt32("channel-count", params.nChannels);
@@ -4028,11 +4114,11 @@
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    CHECK_EQ((status_t)OK, mOMX->getParameter(
-                            mNode,
-                            (OMX_INDEXTYPE)OMX_IndexParamAudioPcm,
-                            &params,
-                            sizeof(params)));
+                    err = mOMX->getParameter(
+                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, &params, sizeof(params));
+                    if (err != OK) {
+                        return err;
+                    }
 
                     const char *mime = NULL;
                     if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) {
@@ -4050,30 +4136,33 @@
 
                 case OMX_AUDIO_CodingGSMFR:
                 {
-                    OMX_AUDIO_PARAM_MP3TYPE params;
+                    OMX_AUDIO_PARAM_PCMMODETYPE params;
                     InitOMXParams(&params);
                     params.nPortIndex = portIndex;
 
-                    CHECK_EQ(mOMX->getParameter(
-                                mNode, OMX_IndexParamAudioPcm,
-                                &params, sizeof(params)),
-                             (status_t)OK);
+                    err = mOMX->getParameter(
+                                mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
+                    if (err != OK) {
+                        return err;
+                    }
 
                     notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM);
                     notify->setInt32("channel-count", params.nChannels);
-                    notify->setInt32("sample-rate", params.nSampleRate);
+                    notify->setInt32("sample-rate", params.nSamplingRate);
                     break;
                 }
 
                 default:
-                    ALOGE("UNKNOWN AUDIO CODING: %d\n", audioDef->eEncoding);
-                    TRESPASS();
+                    ALOGE("Unsupported audio coding: %s(%d)\n",
+                            asString(audioDef->eEncoding), audioDef->eEncoding);
+                    return BAD_TYPE;
             }
             break;
         }
 
         default:
-            TRESPASS();
+            ALOGE("Unsupported domain: %s(%d)", asString(def.eDomain), def.eDomain);
+            return BAD_TYPE;
     }
 
     return OK;
@@ -4083,7 +4172,10 @@
     sp<AMessage> notify = mBaseOutputFormat->dup();
     notify->setInt32("what", kWhatOutputFormatChanged);
 
-    CHECK_EQ(getPortFormat(kPortIndexOutput, notify), (status_t)OK);
+    if (getPortFormat(kPortIndexOutput, notify) != OK) {
+        ALOGE("[%s] Failed to get port format to send format change", mComponentName.c_str());
+        return;
+    }
 
     AString mime;
     CHECK(notify->findString("mime", &mime));
@@ -4225,7 +4317,7 @@
         }
 
         case ACodec::kWhatCreateInputSurface:
-        case ACodec::kWhatUsePersistentInputSurface:
+        case ACodec::kWhatSetInputSurface:
         case ACodec::kWhatSignalEndOfInputStream:
         {
             // This may result in an app illegal state exception.
@@ -4276,7 +4368,10 @@
 
     IOMX::node_id nodeID;
     CHECK(msg->findInt32("node", (int32_t*)&nodeID));
-    CHECK_EQ(nodeID, mCodec->mNode);
+    if (nodeID != mCodec->mNode) {
+        ALOGE("Unexpected message for nodeID: %u, should have been %u", nodeID, mCodec->mNode);
+        return false;
+    }
 
     switch (type) {
         case omx_message::EVENT:
@@ -4332,8 +4427,8 @@
         }
 
         default:
-            TRESPASS();
-            break;
+            ALOGE("Unexpected message type: %d", type);
+            return false;
     }
 }
 
@@ -4363,10 +4458,13 @@
     ALOGV("[%s] onOMXEmptyBufferDone %u",
          mCodec->mComponentName.c_str(), bufferID);
 
-    BufferInfo *info =
-        mCodec->findBufferByID(kPortIndexInput, bufferID);
-
-    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
+    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
+    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
+    if (status != BufferInfo::OWNED_BY_COMPONENT) {
+        ALOGE("Wrong ownership in EBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
+        mCodec->dumpBuffers(kPortIndexInput);
+        return false;
+    }
     info->mStatus = BufferInfo::OWNED_BY_US;
 
     // We're in "store-metadata-in-buffers" mode, the underlying
@@ -4386,12 +4484,10 @@
             postFillThisBuffer(info);
             break;
 
+        case FREE_BUFFERS:
         default:
-        {
-            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
-            TRESPASS();  // Not currently used
-            break;
-        }
+            ALOGE("SHOULD NOT REACH HERE: cannot free empty output buffers");
+            return false;
     }
 
     return true;
@@ -4452,7 +4548,13 @@
     }
 
     BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
-    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
+    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
+    if (status != BufferInfo::OWNED_BY_UPSTREAM) {
+        ALOGE("Wrong ownership in IBF: %s(%d) buffer #%u", _asString(status), status, bufferID);
+        mCodec->dumpBuffers(kPortIndexInput);
+        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+        return;
+    }
 
     info->mStatus = BufferInfo::OWNED_BY_US;
 
@@ -4491,7 +4593,13 @@
                          bufferID,
                          buffer.get(), info->mData.get());
 
-                    CHECK_LE(buffer->size(), info->mData->capacity());
+                    if (buffer->size() > info->mData->capacity()) {
+                        ALOGE("data size (%zu) is greated than buffer capacity (%zu)",
+                                buffer->size(),           // this is the data received
+                                info->mData->capacity()); // this is out buffer size
+                        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+                        return;
+                    }
                     memcpy(info->mData->data(), buffer->data(), buffer->size());
                 }
 
@@ -4530,31 +4638,31 @@
                         mCodec->submitOutputMetaDataBuffer();
                     }
                 }
-
-                CHECK_EQ(mCodec->mOMX->emptyBuffer(
-                            mCodec->mNode,
-                            bufferID,
-                            0,
-                            buffer->size(),
-                            flags,
-                            timeUs),
-                         (status_t)OK);
-
+                status_t err2 = mCodec->mOMX->emptyBuffer(
+                    mCodec->mNode,
+                    bufferID,
+                    0,
+                    buffer->size(),
+                    flags,
+                    timeUs);
+                if (err2 != OK) {
+                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
+                    return;
+                }
                 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
 
-                if (!eos) {
+                if (!eos && err == OK) {
                     getMoreInputDataIfPossible();
                 } else {
-                    ALOGV("[%s] Signalled EOS on the input port",
-                         mCodec->mComponentName.c_str());
+                    ALOGV("[%s] Signalled EOS (%d) on the input port",
+                         mCodec->mComponentName.c_str(), err);
 
                     mCodec->mPortEOS[kPortIndexInput] = true;
                     mCodec->mInputEOSResult = err;
                 }
             } else if (!mCodec->mPortEOS[kPortIndexInput]) {
-                if (err != ERROR_END_OF_STREAM) {
-                    ALOGV("[%s] Signalling EOS on the input port "
-                         "due to error %d",
+                if (err != OK && err != ERROR_END_OF_STREAM) {
+                    ALOGV("[%s] Signalling EOS on the input port due to error %d",
                          mCodec->mComponentName.c_str(), err);
                 } else {
                     ALOGV("[%s] Signalling EOS on the input port",
@@ -4564,15 +4672,17 @@
                 ALOGV("[%s] calling emptyBuffer %u signalling EOS",
                      mCodec->mComponentName.c_str(), bufferID);
 
-                CHECK_EQ(mCodec->mOMX->emptyBuffer(
-                            mCodec->mNode,
-                            bufferID,
-                            0,
-                            0,
-                            OMX_BUFFERFLAG_EOS,
-                            0),
-                         (status_t)OK);
-
+                status_t err2 = mCodec->mOMX->emptyBuffer(
+                        mCodec->mNode,
+                        bufferID,
+                        0,
+                        0,
+                        OMX_BUFFERFLAG_EOS,
+                        0);
+                if (err2 != OK) {
+                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
+                    return;
+                }
                 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
 
                 mCodec->mPortEOS[kPortIndexInput] = true;
@@ -4581,8 +4691,11 @@
             break;
         }
 
+        case FREE_BUFFERS:
+            break;
+
         default:
-            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
+            ALOGE("invalid port mode: %d", mode);
             break;
     }
 }
@@ -4625,6 +4738,7 @@
          mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
 
     ssize_t index;
+    status_t err= OK;
 
 #if TRACK_BUFFER_TIMING
     index = mCodec->mBufferStats.indexOfKey(timeUs);
@@ -4643,8 +4757,13 @@
 
     BufferInfo *info =
         mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
-
-    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
+    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
+    if (status != BufferInfo::OWNED_BY_COMPONENT) {
+        ALOGE("Wrong ownership in FBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
+        mCodec->dumpBuffers(kPortIndexOutput);
+        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+        return true;
+    }
 
     info->mDequeuedAt = ++mCodec->mDequeueCounter;
     info->mStatus = BufferInfo::OWNED_BY_US;
@@ -4662,9 +4781,11 @@
                 ALOGV("[%s] calling fillBuffer %u",
                      mCodec->mComponentName.c_str(), info->mBufferID);
 
-                CHECK_EQ(mCodec->mOMX->fillBuffer(
-                            mCodec->mNode, info->mBufferID),
-                         (status_t)OK);
+                err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID);
+                if (err != OK) {
+                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
+                    return true;
+                }
 
                 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
                 break;
@@ -4726,14 +4847,17 @@
             break;
         }
 
-        default:
-        {
-            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
-
-            CHECK_EQ((status_t)OK,
-                     mCodec->freeBuffer(kPortIndexOutput, index));
+        case FREE_BUFFERS:
+            err = mCodec->freeBuffer(kPortIndexOutput, index);
+            if (err != OK) {
+                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
+                return true;
+            }
             break;
-        }
+
+        default:
+            ALOGE("Invalid port mode: %d", mode);
+            return false;
     }
 
     return true;
@@ -4743,15 +4867,19 @@
     IOMX::buffer_id bufferID;
     CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
     ssize_t index;
-    BufferInfo *info =
-        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
-    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
+    BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
+    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
+    if (status != BufferInfo::OWNED_BY_DOWNSTREAM) {
+        ALOGE("Wrong ownership in OBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
+        mCodec->dumpBuffers(kPortIndexOutput);
+        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+        return;
+    }
 
     android_native_rect_t crop;
-    if (msg->findRect("crop",
-            &crop.left, &crop.top, &crop.right, &crop.bottom)) {
-        CHECK_EQ(0, native_window_set_crop(
-                mCodec->mNativeWindow.get(), &crop));
+    if (msg->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)) {
+        status_t err = native_window_set_crop(mCodec->mNativeWindow.get(), &crop);
+        ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err);
     }
 
     int32_t render;
@@ -4777,13 +4905,11 @@
 
         status_t err;
         err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
-        if (err != OK) {
-            ALOGW("failed to set buffer timestamp: %d", err);
-        }
+        ALOGW_IF(err != NO_ERROR, "failed to set buffer timestamp: %d", err);
 
-        if ((err = mCodec->mNativeWindow->queueBuffer(
-                    mCodec->mNativeWindow.get(),
-                    info->mGraphicBuffer.get(), -1)) == OK) {
+        err = mCodec->mNativeWindow->queueBuffer(
+                    mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), -1);
+        if (err == OK) {
             info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
         } else {
             mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
@@ -4826,24 +4952,29 @@
                 if (info != NULL) {
                     ALOGV("[%s] calling fillBuffer %u",
                          mCodec->mComponentName.c_str(), info->mBufferID);
-
-                    CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
-                             (status_t)OK);
-
-                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
+                    status_t err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID);
+                    if (err == OK) {
+                        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
+                    } else {
+                        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
+                    }
                 }
             }
             break;
         }
 
-        default:
+        case FREE_BUFFERS:
         {
-            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
-
-            CHECK_EQ((status_t)OK,
-                     mCodec->freeBuffer(kPortIndexOutput, index));
+            status_t err = mCodec->freeBuffer(kPortIndexOutput, index);
+            if (err != OK) {
+                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
+            }
             break;
         }
+
+        default:
+            ALOGE("Invalid port mode: %d", mode);
+            return;
     }
 }
 
@@ -5090,7 +5221,7 @@
 
 void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
     if (!keepComponentAllocated) {
-        CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
+        (void)mCodec->mOMX->freeNode(mCodec->mNode);
 
         mCodec->changeState(mCodec->mUninitializedState);
     }
@@ -5121,9 +5252,9 @@
             break;
         }
 
-        case ACodec::kWhatUsePersistentInputSurface:
+        case ACodec::kWhatSetInputSurface:
         {
-            onUsePersistentInputSurface(msg);
+            onSetInputSurface(msg);
             handled = true;
             break;
         }
@@ -5171,11 +5302,13 @@
 
     CHECK(mCodec->mNode != 0);
 
+    status_t err = OK;
     AString mime;
-    CHECK(msg->findString("mime", &mime));
-
-    status_t err = mCodec->configureCodec(mime.c_str(), msg);
-
+    if (!msg->findString("mime", &mime)) {
+        err = BAD_VALUE;
+    } else {
+        err = mCodec->configureCodec(mime.c_str(), msg);
+    }
     if (err != OK) {
         ALOGE("[%s] configureCodec returning error %d",
               mCodec->mComponentName.c_str(), err);
@@ -5316,9 +5449,9 @@
     notify->post();
 }
 
-void ACodec::LoadedState::onUsePersistentInputSurface(
+void ACodec::LoadedState::onSetInputSurface(
         const sp<AMessage> &msg) {
-    ALOGV("onUsePersistentInputSurface");
+    ALOGV("onSetInputSurface");
 
     sp<AMessage> notify = mCodec->mNotify->dup();
     notify->setInt32("what", CodecBase::kWhatInputSurfaceAccepted);
@@ -5327,7 +5460,7 @@
     CHECK(msg->findObject("input-surface", &obj));
     sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get());
 
-    status_t err = mCodec->mOMX->usePersistentInputSurface(
+    status_t err = mCodec->mOMX->setInputSurface(
             mCodec->mNode, kPortIndexInput, surface->getBufferConsumer());
 
     if (err == OK) {
@@ -5338,7 +5471,7 @@
         // Can't use mCodec->signalError() here -- MediaCodec won't forward
         // the error through because it's in the "configured" state.  We
         // send a kWhatInputSurfaceAccepted with an error value instead.
-        ALOGE("[%s] onUsePersistentInputSurface returning error %d",
+        ALOGE("[%s] onSetInputSurface returning error %d",
                 mCodec->mComponentName.c_str(), err);
         notify->setInt32("err", err);
     }
@@ -5348,11 +5481,12 @@
 void ACodec::LoadedState::onStart() {
     ALOGV("onStart");
 
-    CHECK_EQ(mCodec->mOMX->sendCommand(
-                mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
-             (status_t)OK);
-
-    mCodec->changeState(mCodec->mLoadedToIdleState);
+    status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle);
+    if (err != OK) {
+        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
+    } else {
+        mCodec->changeState(mCodec->mLoadedToIdleState);
+    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -5426,14 +5560,25 @@
     switch (event) {
         case OMX_EventCmdComplete:
         {
-            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
-            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
+            status_t err = OK;
+            if (data1 != (OMX_U32)OMX_CommandStateSet
+                    || data2 != (OMX_U32)OMX_StateIdle) {
+                ALOGE("Unexpected command completion in LoadedToIdleState: %s(%u) %s(%u)",
+                        asString((OMX_COMMANDTYPE)data1), data1,
+                        asString((OMX_STATETYPE)data2), data2);
+                err = FAILED_TRANSACTION;
+            }
 
-            CHECK_EQ(mCodec->mOMX->sendCommand(
-                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
-                     (status_t)OK);
+            if (err == OK) {
+                err = mCodec->mOMX->sendCommand(
+                    mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting);
+            }
 
-            mCodec->changeState(mCodec->mIdleToExecutingState);
+            if (err != OK) {
+                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
+            } else {
+                mCodec->changeState(mCodec->mIdleToExecutingState);
+            }
 
             return true;
         }
@@ -5494,8 +5639,14 @@
     switch (event) {
         case OMX_EventCmdComplete:
         {
-            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
-            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
+            if (data1 != (OMX_U32)OMX_CommandStateSet
+                    || data2 != (OMX_U32)OMX_StateExecuting) {
+                ALOGE("Unexpected command completion in IdleToExecutingState: %s(%u) %s(%u)",
+                        asString((OMX_COMMANDTYPE)data1), data1,
+                        asString((OMX_STATETYPE)data2), data2);
+                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+                return true;
+            }
 
             mCodec->mExecutingState->resume();
             mCodec->changeState(mCodec->mExecutingState);
@@ -5537,28 +5688,43 @@
 }
 
 void ACodec::ExecutingState::submitRegularOutputBuffers() {
+    bool failed = false;
     for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
         BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
 
         if (mCodec->mNativeWindow != NULL) {
-            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
-                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
+            if (info->mStatus != BufferInfo::OWNED_BY_US
+                    && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
+                ALOGE("buffers should be owned by us or the surface");
+                failed = true;
+                break;
+            }
 
             if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
                 continue;
             }
         } else {
-            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
+            if (info->mStatus != BufferInfo::OWNED_BY_US) {
+                ALOGE("buffers should be owned by us");
+                failed = true;
+                break;
+            }
         }
 
-        ALOGV("[%s] calling fillBuffer %u",
-             mCodec->mComponentName.c_str(), info->mBufferID);
+        ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID);
 
-        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
-                 (status_t)OK);
+        status_t err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID);
+        if (err != OK) {
+            failed = true;
+            break;
+        }
 
         info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
     }
+
+    if (failed) {
+        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+    }
 }
 
 void ACodec::ExecutingState::submitOutputBuffers() {
@@ -5570,16 +5736,17 @@
 
 void ACodec::ExecutingState::resume() {
     if (mActive) {
-        ALOGV("[%s] We're already active, no need to resume.",
-             mCodec->mComponentName.c_str());
-
+        ALOGV("[%s] We're already active, no need to resume.", mCodec->mComponentName.c_str());
         return;
     }
 
     submitOutputBuffers();
 
     // Post all available input buffers
-    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
+    if (mCodec->mBuffers[kPortIndexInput].size() == 0u) {
+        ALOGW("[%s] we don't have any input buffers to resume", mCodec->mComponentName.c_str());
+    }
+
     for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
         BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
         if (info->mStatus == BufferInfo::OWNED_BY_US) {
@@ -5612,11 +5779,16 @@
 
             mActive = false;
 
-            CHECK_EQ(mCodec->mOMX->sendCommand(
-                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
-                     (status_t)OK);
-
-            mCodec->changeState(mCodec->mExecutingToIdleState);
+            status_t err = mCodec->mOMX->sendCommand(
+                    mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle);
+            if (err != OK) {
+                if (keepComponentAllocated) {
+                    mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+                }
+                // TODO: do some recovery here.
+            } else {
+                mCodec->changeState(mCodec->mExecutingToIdleState);
+            }
 
             handled = true;
             break;
@@ -5634,11 +5806,13 @@
 
             mActive = false;
 
-            CHECK_EQ(mCodec->mOMX->sendCommand(
-                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
-                     (status_t)OK);
+            status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandFlush, OMX_ALL);
+            if (err != OK) {
+                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+            } else {
+                mCodec->changeState(mCodec->mFlushingState);
+            }
 
-            mCodec->changeState(mCodec->mFlushingState);
             handled = true;
             break;
         }
@@ -5889,25 +6063,34 @@
         case OMX_EventCmdComplete:
         {
             if (data1 == (OMX_U32)OMX_CommandPortDisable) {
-                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
+                if (data2 != (OMX_U32)kPortIndexOutput) {
+                    ALOGW("ignoring EventCmdComplete CommandPortDisable for port %u", data2);
+                    return false;
+                }
 
-                ALOGV("[%s] Output port now disabled.",
-                        mCodec->mComponentName.c_str());
+                ALOGV("[%s] Output port now disabled.", mCodec->mComponentName.c_str());
 
-                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
-                mCodec->mDealer[kPortIndexOutput].clear();
+                status_t err = OK;
+                if (!mCodec->mBuffers[kPortIndexOutput].isEmpty()) {
+                    ALOGE("disabled port should be empty, but has %zu buffers",
+                            mCodec->mBuffers[kPortIndexOutput].size());
+                    err = FAILED_TRANSACTION;
+                } else {
+                    mCodec->mDealer[kPortIndexOutput].clear();
+                }
 
-                CHECK_EQ(mCodec->mOMX->sendCommand(
-                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
-                         (status_t)OK);
+                if (err == OK) {
+                    err = mCodec->mOMX->sendCommand(
+                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput);
+                }
 
-                status_t err;
-                if ((err = mCodec->allocateBuffersOnPort(
-                                kPortIndexOutput)) != OK) {
-                    ALOGE("Failed to allocate output port buffers after "
-                         "port reconfiguration (error 0x%08x)",
-                         err);
+                if (err == OK) {
+                    err = mCodec->allocateBuffersOnPort(kPortIndexOutput);
+                    ALOGE_IF(err != OK, "Failed to allocate output port buffers after port "
+                            "reconfiguration: (%d)", err);
+                }
 
+                if (err != OK) {
                     mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
 
                     // This is technically not correct, but appears to be
@@ -5922,12 +6105,14 @@
 
                 return true;
             } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
-                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
+                if (data2 != (OMX_U32)kPortIndexOutput) {
+                    ALOGW("ignoring EventCmdComplete OMX_CommandPortEnable for port %u", data2);
+                    return false;
+                }
 
                 mCodec->mSentFormat = false;
 
-                ALOGV("[%s] Output port now reenabled.",
-                        mCodec->mComponentName.c_str());
+                ALOGV("[%s] Output port now reenabled.", mCodec->mComponentName.c_str());
 
                 if (mCodec->mExecutingState->active()) {
                     mCodec->mExecutingState->submitOutputBuffers();
@@ -5961,7 +6146,7 @@
         {
             // Don't send me a flush request if you previously wanted me
             // to shutdown.
-            TRESPASS();
+            ALOGW("Ignoring flush request in ExecutingToIdleState");
             break;
         }
 
@@ -5993,8 +6178,14 @@
     switch (event) {
         case OMX_EventCmdComplete:
         {
-            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
-            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
+            if (data1 != (OMX_U32)OMX_CommandStateSet
+                    || data2 != (OMX_U32)OMX_StateIdle) {
+                ALOGE("Unexpected command completion in ExecutingToIdleState: %s(%u) %s(%u)",
+                        asString((OMX_COMMANDTYPE)data1), data1,
+                        asString((OMX_STATETYPE)data2), data2);
+                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+                return true;
+            }
 
             mComponentNowIdle = true;
 
@@ -6017,12 +6208,15 @@
 
 void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
     if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
-        CHECK_EQ(mCodec->mOMX->sendCommand(
-                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
-                 (status_t)OK);
-
-        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
-        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
+        status_t err = mCodec->mOMX->sendCommand(
+                mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded);
+        if (err == OK) {
+            err = mCodec->freeBuffersOnPort(kPortIndexInput);
+            status_t err2 = mCodec->freeBuffersOnPort(kPortIndexOutput);
+            if (err == OK) {
+                err = err2;
+            }
+        }
 
         if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
                 && mCodec->mNativeWindow != NULL) {
@@ -6033,6 +6227,11 @@
             pushBlankBuffersToNativeWindow(mCodec->mNativeWindow.get());
         }
 
+        if (err != OK) {
+            mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+            return;
+        }
+
         mCodec->changeState(mCodec->mIdleToLoadedState);
     }
 }
@@ -6073,7 +6272,7 @@
         {
             // Don't send me a flush request if you previously wanted me
             // to shutdown.
-            TRESPASS();
+            ALOGE("Got flush request in IdleToLoadedState");
             break;
         }
 
@@ -6094,8 +6293,14 @@
     switch (event) {
         case OMX_EventCmdComplete:
         {
-            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
-            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
+            if (data1 != (OMX_U32)OMX_CommandStateSet
+                    || data2 != (OMX_U32)OMX_StateLoaded) {
+                ALOGE("Unexpected command completion in IdleToLoadedState: %s(%u) %s(%u)",
+                        asString((OMX_COMMANDTYPE)data1), data1,
+                        asString((OMX_STATETYPE)data2), data2);
+                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+                return true;
+            }
 
             mCodec->changeState(mCodec->mLoadedState);
 
@@ -6152,22 +6357,35 @@
     switch (event) {
         case OMX_EventCmdComplete:
         {
-            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
+            if (data1 != (OMX_U32)OMX_CommandFlush) {
+                ALOGE("unexpected EventCmdComplete %s(%d) data2:%d in FlushingState",
+                        asString((OMX_COMMANDTYPE)data1), data1, data2);
+                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+                return true;
+            }
 
             if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
-                CHECK(!mFlushComplete[data2]);
+                if (mFlushComplete[data2]) {
+                    ALOGW("Flush already completed for %s port",
+                            data2 == kPortIndexInput ? "input" : "output");
+                    return true;
+                }
                 mFlushComplete[data2] = true;
 
-                if (mFlushComplete[kPortIndexInput]
-                        && mFlushComplete[kPortIndexOutput]) {
+                if (mFlushComplete[kPortIndexInput] && mFlushComplete[kPortIndexOutput]) {
                     changeStateIfWeOwnAllBuffers();
                 }
-            } else {
-                CHECK_EQ(data2, OMX_ALL);
-                CHECK(mFlushComplete[kPortIndexInput]);
-                CHECK(mFlushComplete[kPortIndexOutput]);
+            } else if (data2 == OMX_ALL) {
+                if (!mFlushComplete[kPortIndexInput] || !mFlushComplete[kPortIndexOutput]) {
+                    ALOGW("received flush complete event for OMX_ALL before ports have been"
+                            "flushed (%d/%d)",
+                            mFlushComplete[kPortIndexInput], mFlushComplete[kPortIndexOutput]);
+                    return false;
+                }
 
                 changeStateIfWeOwnAllBuffers();
+            } else {
+                ALOGW("data2 not OMX_ALL but %u in EventCmdComplete CommandFlush", data2);
             }
 
             return true;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 5c0afa9..65d8a04 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -33,6 +33,7 @@
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
@@ -221,8 +222,7 @@
 ssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
     Mutex::Autolock autoLock(mLock);
 
-    if (offset >= mCachedOffset
-            && offset + size <= mCachedOffset + mCachedSize) {
+    if (isInRange(mCachedOffset, mCachedSize, offset, size)) {
         memcpy(data, &mCache[offset - mCachedOffset], size);
         return size;
     }
@@ -4120,12 +4120,12 @@
             size_t dstOffset = 0;
 
             while (srcOffset < size) {
-                bool isMalFormed = (srcOffset + mNALLengthSize > size);
+                bool isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
                 size_t nalLength = 0;
                 if (!isMalFormed) {
                     nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
                     srcOffset += mNALLengthSize;
-                    isMalFormed = srcOffset + nalLength > size;
+                    isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength);
                 }
 
                 if (isMalFormed) {
@@ -4397,12 +4397,12 @@
             size_t dstOffset = 0;
 
             while (srcOffset < size) {
-                bool isMalFormed = (srcOffset + mNALLengthSize > size);
+                bool isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
                 size_t nalLength = 0;
                 if (!isMalFormed) {
                     nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
                     srcOffset += mNALLengthSize;
-                    isMalFormed = srcOffset + nalLength > size;
+                    isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength);
                 }
 
                 if (isMalFormed) {
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 3bc22f2..95f361e 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -369,9 +369,16 @@
       mWriterThreadStarted(false),
       mOffset(0),
       mMdatOffset(0),
+      mMoovBoxBuffer(NULL),
+      mMoovBoxBufferOffset(0),
+      mWriteMoovBoxToMemory(false),
+      mFreeBoxOffset(0),
+      mStreamableFile(false),
       mEstimatedMoovBoxSize(0),
       mMoovExtraSize(0),
       mInterleaveDurationUs(1000000),
+      mTimeScale(-1),
+      mStartTimestampUs(-1ll),
       mLatitudex10000(0),
       mLongitudex10000(0),
       mAreGeoTagsAvailable(false),
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 4080391..46c154d 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -554,9 +554,9 @@
     return err;
 }
 
-status_t MediaCodec::usePersistentInputSurface(
+status_t MediaCodec::setInputSurface(
         const sp<PersistentSurface> &surface) {
-    sp<AMessage> msg = new AMessage(kWhatUsePersistentInputSurface, this);
+    sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
     msg->setObject("input-surface", surface.get());
 
     sp<AMessage> response;
@@ -1290,7 +1290,7 @@
 
                 case CodecBase::kWhatInputSurfaceAccepted:
                 {
-                    // response to initiateUsePersistentInputSurface()
+                    // response to initiateSetInputSurface()
                     status_t err = NO_ERROR;
                     sp<AMessage> response = new AMessage();
                     if (!msg->findInt32("err", &err)) {
@@ -1776,7 +1776,7 @@
         }
 
         case kWhatCreateInputSurface:
-        case kWhatUsePersistentInputSurface:
+        case kWhatSetInputSurface:
         {
             sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
@@ -1794,7 +1794,7 @@
                 sp<RefBase> obj;
                 CHECK(msg->findObject("input-surface", &obj));
 
-                mCodec->initiateUsePersistentInputSurface(
+                mCodec->initiateSetInputSurface(
                         static_cast<PersistentSurface *>(obj.get()));
             }
             break;
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 9b57733..e089c46 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -427,7 +427,7 @@
             // When using persistent surface, we are only interested in the
             // consumer, but have to use PersistentSurface as a wrapper to
             // pass consumer over messages (similar to BufferProducerWrapper)
-            err = mEncoder->usePersistentInputSurface(
+            err = mEncoder->setInputSurface(
                     new PersistentSurface(NULL, mGraphicBufferConsumer));
         } else {
             err = mEncoder->createInputSurface(&mGraphicBufferProducer);
diff --git a/media/libstagefright/MediaDefs.cpp b/media/libstagefright/MediaDefs.cpp
index b0a65d2..2a50692 100644
--- a/media/libstagefright/MediaDefs.cpp
+++ b/media/libstagefright/MediaDefs.cpp
@@ -62,6 +62,6 @@
 const char *MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
 const char *MEDIA_MIMETYPE_TEXT_VTT = "text/vtt";
 const char *MEDIA_MIMETYPE_TEXT_CEA_608 = "text/cea-608";
-const char *MEDIA_MIMETYPE_DATA_METADATA = "application/octet-stream";
+const char *MEDIA_MIMETYPE_DATA_TIMED_ID3 = "application/x-id3v4";
 
 }  // namespace android
diff --git a/media/libstagefright/MediaSync.cpp b/media/libstagefright/MediaSync.cpp
index 97264fb..b402e48 100644
--- a/media/libstagefright/MediaSync.cpp
+++ b/media/libstagefright/MediaSync.cpp
@@ -49,6 +49,7 @@
         mMutex(),
         mReleaseCondition(),
         mNumOutstandingBuffers(0),
+        mUsageFlagsFromOutput(0),
         mNativeSampleRateInHz(0),
         mNumFramesWritten(0),
         mHasAudio(false),
@@ -82,10 +83,8 @@
 status_t MediaSync::setSurface(const sp<IGraphicBufferProducer> &output) {
     Mutex::Autolock lock(mMutex);
 
-    // TODO: support suface change.
-    if (mOutput != NULL) {
-        ALOGE("setSurface: output surface has already been configured.");
-        return INVALID_OPERATION;
+    if (output == mOutput) {
+        return NO_ERROR;  // same output surface.
     }
 
     if (output == NULL && mSyncSettings.mSource == AVSYNC_SOURCE_VSYNC) {
@@ -94,8 +93,24 @@
     }
 
     if (output != NULL) {
+        int newUsage = 0;
+        output->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &newUsage);
+
+        // Check usage flags only when current output surface has been used to create input surface.
+        if (mOutput != NULL && mInput != NULL) {
+            int ignoredFlags = (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER
+                    | GRALLOC_USAGE_EXTERNAL_DISP);
+            // New output surface is not allowed to add new usage flag except ignored ones.
+            if ((newUsage & ~(mUsageFlagsFromOutput | ignoredFlags)) != 0) {
+                ALOGE("setSurface: new output surface has new usage flag not used by current one.");
+                return BAD_VALUE;
+            }
+        }
+
+        // Try to connect to new output surface. If failed, current output surface will not
+        // be changed.
         IGraphicBufferProducer::QueueBufferOutput queueBufferOutput;
-        sp<OutputListener> listener(new OutputListener(this));
+        sp<OutputListener> listener(new OutputListener(this, output));
         IInterface::asBinder(output)->linkToDeath(listener);
         status_t status =
             output->connect(listener,
@@ -106,10 +121,18 @@
             ALOGE("setSurface: failed to connect (%d)", status);
             return status;
         }
-
-        mOutput = output;
     }
 
+    if (mOutput != NULL) {
+        mOutput->disconnect(NATIVE_WINDOW_API_MEDIA);
+        while (!mBuffersSentToOutput.isEmpty()) {
+            returnBufferToInput_l(mBuffersSentToOutput.valueAt(0), Fence::NO_FENCE);
+            mBuffersSentToOutput.removeItemsAt(0);
+        }
+    }
+
+    mOutput = output;
+
     return NO_ERROR;
 }
 
@@ -181,9 +204,9 @@
     if (status == NO_ERROR) {
         bufferConsumer->setConsumerName(String8("MediaSync"));
         // propagate usage bits from output surface
-        int usage = 0;
-        mOutput->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage);
-        bufferConsumer->setConsumerUsageBits(usage);
+        mUsageFlagsFromOutput = 0;
+        mOutput->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &mUsageFlagsFromOutput);
+        bufferConsumer->setConsumerUsageBits(mUsageFlagsFromOutput);
         *outBufferProducer = bufferProducer;
         mInput = bufferConsumer;
     }
@@ -602,12 +625,24 @@
         return;
     }
 
+    if (mBuffersSentToOutput.indexOfKey(bufferItem.mGraphicBuffer->getId()) >= 0) {
+        // Something is wrong since this buffer should be held by output now, bail.
+        mInput->consumerDisconnect();
+        onAbandoned_l(true /* isInput */);
+        return;
+    }
+    mBuffersSentToOutput.add(bufferItem.mGraphicBuffer->getId(), bufferItem.mGraphicBuffer);
+
     ALOGV("queued buffer %#llx to output", (long long)bufferItem.mGraphicBuffer->getId());
 }
 
-void MediaSync::onBufferReleasedByOutput() {
+void MediaSync::onBufferReleasedByOutput(sp<IGraphicBufferProducer> &output) {
     Mutex::Autolock lock(mMutex);
 
+    if (output != mOutput) {
+        return;  // This is not the current output, ignore.
+    }
+
     sp<GraphicBuffer> buffer;
     sp<Fence> fence;
     status_t status = mOutput->detachNextBuffer(&buffer, &fence);
@@ -628,6 +663,13 @@
         return;
     }
 
+    ssize_t ix = mBuffersSentToOutput.indexOfKey(buffer->getId());
+    if (ix < 0) {
+        // The buffer is unknown, maybe leftover, ignore.
+        return;
+    }
+    mBuffersSentToOutput.removeItemsAt(ix);
+
     returnBufferToInput_l(buffer, fence);
 }
 
@@ -727,13 +769,15 @@
     mSync->onAbandoned_l(true /* isInput */);
 }
 
-MediaSync::OutputListener::OutputListener(const sp<MediaSync> &sync)
-      : mSync(sync) {}
+MediaSync::OutputListener::OutputListener(const sp<MediaSync> &sync,
+        const sp<IGraphicBufferProducer> &output)
+      : mSync(sync),
+        mOutput(output) {}
 
 MediaSync::OutputListener::~OutputListener() {}
 
 void MediaSync::OutputListener::onBufferReleased() {
-    mSync->onBufferReleasedByOutput();
+    mSync->onBufferReleasedByOutput(mOutput);
 }
 
 void MediaSync::OutputListener::binderDied(const wp<IBinder> &/* who */) {
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index 44695ce..f1ebea2 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -108,7 +108,7 @@
             sp<IGraphicBufferProducer> *bufferProducer,
             sp<IGraphicBufferConsumer> *bufferConsumer);
 
-    virtual status_t usePersistentInputSurface(
+    virtual status_t setInputSurface(
             node_id node, OMX_U32 port_index,
             const sp<IGraphicBufferConsumer> &bufferConsumer);
 
@@ -356,11 +356,10 @@
             bufferProducer, bufferConsumer);
 }
 
-status_t MuxOMX::usePersistentInputSurface(
+status_t MuxOMX::setInputSurface(
         node_id node, OMX_U32 port_index,
         const sp<IGraphicBufferConsumer> &bufferConsumer) {
-    return getOMX(node)->usePersistentInputSurface(
-            node, port_index, bufferConsumer);
+    return getOMX(node)->setInputSurface(node, port_index, bufferConsumer);
 }
 
 status_t MuxOMX::signalEndOfInputStream(node_id node) {
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 10937ec..965c55e 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -75,7 +75,7 @@
 
 SoftAAC2::~SoftAAC2() {
     aacDecoder_Close(mAACDecoder);
-    delete mOutputDelayRingBuffer;
+    delete[] mOutputDelayRingBuffer;
 }
 
 void SoftAAC2::initPorts() {
diff --git a/media/libstagefright/filters/MediaFilter.cpp b/media/libstagefright/filters/MediaFilter.cpp
index fa9d630..0cf6b06 100644
--- a/media/libstagefright/filters/MediaFilter.cpp
+++ b/media/libstagefright/filters/MediaFilter.cpp
@@ -76,9 +76,9 @@
     (new AMessage(kWhatCreateInputSurface, this))->post();
 }
 
-void MediaFilter::initiateUsePersistentInputSurface(
+void MediaFilter::initiateSetInputSurface(
         const sp<PersistentSurface> & /* surface */) {
-    ALOGW("initiateUsePersistentInputSurface() unsupported");
+    ALOGW("initiateSetInputSurface() unsupported");
 }
 
 void MediaFilter::initiateStart() {
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 64a8532..27509cb 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -1406,7 +1406,7 @@
             sp<AMessage> format = new AMessage();
             format->setInt32("type", MEDIA_TRACK_TYPE_METADATA);
             format->setString("language", "und");
-            format->setString("mime", MEDIA_MIMETYPE_DATA_METADATA);
+            format->setString("mime", MEDIA_MIMETYPE_DATA_TIMED_ID3);
             return format;
         }
         return mPlaylist->getTrackInfo(trackIndex);
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index b1ee628..c183208 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -99,7 +99,7 @@
             sp<IGraphicBufferProducer> *bufferProducer,
             sp<IGraphicBufferConsumer> *bufferConsumer);
 
-    virtual status_t usePersistentInputSurface(
+    virtual status_t setInputSurface(
             node_id node, OMX_U32 port_index,
             const sp<IGraphicBufferConsumer> &bufferConsumer);
 
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index 03c9a8a..ad1e181 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -87,7 +87,7 @@
             sp<IGraphicBufferProducer> *bufferProducer,
             sp<IGraphicBufferConsumer> *bufferConsumer);
 
-    status_t usePersistentInputSurface(
+    status_t setInputSurface(
             OMX_U32 portIndex, const sp<IGraphicBufferConsumer> &bufferConsumer);
 
     status_t signalEndOfInputStream();
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index baf3b15..36ec367 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -1393,7 +1393,7 @@
 
     if (mFormat == NULL) {
         mFormat = new MetaData;
-        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_DATA_METADATA);
+        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_DATA_TIMED_ID3);
     }
 
     return accessUnit;
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 876abb8..a1ceb2e 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -385,11 +385,10 @@
             bufferProducer, bufferConsumer);
 }
 
-status_t OMX::usePersistentInputSurface(
+status_t OMX::setInputSurface(
         node_id node, OMX_U32 port_index,
         const sp<IGraphicBufferConsumer> &bufferConsumer) {
-    return findInstance(node)->usePersistentInputSurface(
-            port_index, bufferConsumer);
+    return findInstance(node)->setInputSurface(port_index, bufferConsumer);
 }
 
 
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 04293d6..91cee73 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -891,7 +891,7 @@
     return OK;
 }
 
-status_t OMXNodeInstance::usePersistentInputSurface(
+status_t OMXNodeInstance::setInputSurface(
         OMX_U32 portIndex, const sp<IGraphicBufferConsumer> &bufferConsumer) {
     Mutex::Autolock autolock(mLock);
     return createGraphicBufferSource(portIndex, bufferConsumer);
diff --git a/media/libstagefright/tests/Utils_test.cpp b/media/libstagefright/tests/Utils_test.cpp
index 5c323c1..c1e663c 100644
--- a/media/libstagefright/tests/Utils_test.cpp
+++ b/media/libstagefright/tests/Utils_test.cpp
@@ -192,6 +192,87 @@
     ASSERT_EQ(max(-4.3, 8.6), 8.6);
     ASSERT_EQ(max(8.6, -4.3), 8.6);
 
+    ASSERT_FALSE(isInRange(-43, 86u, -44));
+    ASSERT_TRUE(isInRange(-43, 87u, -43));
+    ASSERT_TRUE(isInRange(-43, 88u, -1));
+    ASSERT_TRUE(isInRange(-43, 89u, 0));
+    ASSERT_TRUE(isInRange(-43, 90u, 46));
+    ASSERT_FALSE(isInRange(-43, 91u, 48));
+    ASSERT_FALSE(isInRange(-43, 92u, 50));
+
+    ASSERT_FALSE(isInRange(43, 86u, 42));
+    ASSERT_TRUE(isInRange(43, 87u, 43));
+    ASSERT_TRUE(isInRange(43, 88u, 44));
+    ASSERT_TRUE(isInRange(43, 89u, 131));
+    ASSERT_FALSE(isInRange(43, 90u, 133));
+    ASSERT_FALSE(isInRange(43, 91u, 135));
+
+    ASSERT_FALSE(isInRange(43u, 86u, 42u));
+    ASSERT_TRUE(isInRange(43u, 85u, 43u));
+    ASSERT_TRUE(isInRange(43u, 84u, 44u));
+    ASSERT_TRUE(isInRange(43u, 83u, 125u));
+    ASSERT_FALSE(isInRange(43u, 82u, 125u));
+    ASSERT_FALSE(isInRange(43u, 81u, 125u));
+
+    ASSERT_FALSE(isInRange(-43, ~0u, 43));
+    ASSERT_FALSE(isInRange(-43, ~0u, 44));
+    ASSERT_FALSE(isInRange(-43, ~0u, ~0));
+    ASSERT_FALSE(isInRange(-43, ~0u, 41));
+    ASSERT_FALSE(isInRange(-43, ~0u, 40));
+
+    ASSERT_FALSE(isInRange(43u, ~0u, 43u));
+    ASSERT_FALSE(isInRange(43u, ~0u, 41u));
+    ASSERT_FALSE(isInRange(43u, ~0u, 40u));
+    ASSERT_FALSE(isInRange(43u, ~0u, ~0u));
+
+    ASSERT_FALSE(isInRange(-43, 86u, -44, 0u));
+    ASSERT_FALSE(isInRange(-43, 86u, -44, 1u));
+    ASSERT_FALSE(isInRange(-43, 86u, -44, 2u));
+    ASSERT_FALSE(isInRange(-43, 86u, -44, ~0u));
+    ASSERT_TRUE(isInRange(-43, 87u, -43, 0u));
+    ASSERT_TRUE(isInRange(-43, 87u, -43, 1u));
+    ASSERT_TRUE(isInRange(-43, 87u, -43, 86u));
+    ASSERT_TRUE(isInRange(-43, 87u, -43, 87u));
+    ASSERT_FALSE(isInRange(-43, 87u, -43, 88u));
+    ASSERT_FALSE(isInRange(-43, 87u, -43, ~0u));
+    ASSERT_TRUE(isInRange(-43, 88u, -1, 0u));
+    ASSERT_TRUE(isInRange(-43, 88u, -1, 45u));
+    ASSERT_TRUE(isInRange(-43, 88u, -1, 46u));
+    ASSERT_FALSE(isInRange(-43, 88u, -1, 47u));
+    ASSERT_FALSE(isInRange(-43, 88u, -1, ~3u));
+    ASSERT_TRUE(isInRange(-43, 90u, 46, 0u));
+    ASSERT_TRUE(isInRange(-43, 90u, 46, 1u));
+    ASSERT_FALSE(isInRange(-43, 90u, 46, 2u));
+    ASSERT_FALSE(isInRange(-43, 91u, 48, 0u));
+    ASSERT_FALSE(isInRange(-43, 91u, 48, 2u));
+    ASSERT_FALSE(isInRange(-43, 91u, 48, ~6u));
+    ASSERT_FALSE(isInRange(-43, 92u, 50, 0u));
+    ASSERT_FALSE(isInRange(-43, 92u, 50, 1u));
+
+    ASSERT_FALSE(isInRange(43u, 86u, 42u, 0u));
+    ASSERT_FALSE(isInRange(43u, 86u, 42u, 1u));
+    ASSERT_FALSE(isInRange(43u, 86u, 42u, 2u));
+    ASSERT_FALSE(isInRange(43u, 86u, 42u, ~0u));
+    ASSERT_TRUE(isInRange(43u, 87u, 43u, 0u));
+    ASSERT_TRUE(isInRange(43u, 87u, 43u, 1u));
+    ASSERT_TRUE(isInRange(43u, 87u, 43u, 86u));
+    ASSERT_TRUE(isInRange(43u, 87u, 43u, 87u));
+    ASSERT_FALSE(isInRange(43u, 87u, 43u, 88u));
+    ASSERT_FALSE(isInRange(43u, 87u, 43u, ~0u));
+    ASSERT_TRUE(isInRange(43u, 88u, 60u, 0u));
+    ASSERT_TRUE(isInRange(43u, 88u, 60u, 70u));
+    ASSERT_TRUE(isInRange(43u, 88u, 60u, 71u));
+    ASSERT_FALSE(isInRange(43u, 88u, 60u, 72u));
+    ASSERT_FALSE(isInRange(43u, 88u, 60u, ~3u));
+    ASSERT_TRUE(isInRange(43u, 90u, 132u, 0u));
+    ASSERT_TRUE(isInRange(43u, 90u, 132u, 1u));
+    ASSERT_FALSE(isInRange(43u, 90u, 132u, 2u));
+    ASSERT_FALSE(isInRange(43u, 91u, 134u, 0u));
+    ASSERT_FALSE(isInRange(43u, 91u, 134u, 2u));
+    ASSERT_FALSE(isInRange(43u, 91u, 134u, ~6u));
+    ASSERT_FALSE(isInRange(43u, 92u, 136u, 0u));
+    ASSERT_FALSE(isInRange(43u, 92u, 136u, 1u));
+
     ASSERT_EQ(periodicError(124, 100), 24);
     ASSERT_EQ(periodicError(288, 100), 12);
     ASSERT_EQ(periodicError(-345, 100), 45);
diff --git a/services/audioflinger/ServiceUtilities.cpp b/services/audioflinger/ServiceUtilities.cpp
index 0a718fb..33bd416 100644
--- a/services/audioflinger/ServiceUtilities.cpp
+++ b/services/audioflinger/ServiceUtilities.cpp
@@ -83,7 +83,7 @@
     }
 
     AppOpsManager appOps;
-    if (appOps.noteOp(AppOpsManager::OP_RECORD_AUDIO, uid, opPackageName)
+    if (appOps.noteOp(AppOpsManager::OP_RECORD_AUDIO, uid, checkedOpPackageName)
             != AppOpsManager::MODE_ALLOWED) {
         ALOGE("Request denied by app op OP_RECORD_AUDIO");
         return false;
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 8de8930..fc9a332 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -122,8 +122,8 @@
 // should be ok for now.
 static CameraService *gCameraService;
 
-CameraService::CameraService() : mEventLog(DEFAULT_EVENT_LOG_LENGTH),
-        mLastUserId(DEFAULT_LAST_USER_ID), mSoundRef(0), mModule(0), mFlashlight(0) {
+CameraService::CameraService() : mEventLog(DEFAULT_EVENT_LOG_LENGTH), mAllowedUsers(),
+        mSoundRef(0), mModule(0), mFlashlight(0) {
     ALOGI("CameraService started (pid=%d)", getpid());
     gCameraService = this;
 
@@ -519,34 +519,12 @@
 int CameraService::getCameraPriorityFromProcState(int procState) {
     // Find the priority for the camera usage based on the process state.  Higher priority clients
     // win for evictions.
-    // Note: Unlike the ordering for ActivityManager, persistent system processes will always lose
-    //       the camera to the top/foreground applications.
-    switch(procState) {
-        case PROCESS_STATE_TOP: // User visible
-            return 100;
-        case PROCESS_STATE_IMPORTANT_FOREGROUND: // Foreground
-            return 90;
-        case PROCESS_STATE_PERSISTENT: // Persistent system services
-        case PROCESS_STATE_PERSISTENT_UI:
-            return 80;
-        case PROCESS_STATE_IMPORTANT_BACKGROUND: // "Important" background processes
-            return 70;
-        case PROCESS_STATE_BACKUP: // Everything else
-        case PROCESS_STATE_HEAVY_WEIGHT:
-        case PROCESS_STATE_SERVICE:
-        case PROCESS_STATE_RECEIVER:
-        case PROCESS_STATE_HOME:
-        case PROCESS_STATE_LAST_ACTIVITY:
-        case PROCESS_STATE_CACHED_ACTIVITY:
-        case PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
-        case PROCESS_STATE_CACHED_EMPTY:
-            return 1;
-        case PROCESS_STATE_NONEXISTENT:
-            return -1;
-        default:
-            ALOGE("%s: Received unknown process state from ActivityManagerService!", __FUNCTION__);
-            return -1;
+    if (procState < 0) {
+        ALOGE("%s: Received invalid process state %d from ActivityManagerService!", __FUNCTION__,
+                procState);
+        return -1;
     }
+    return INT_MAX - procState;
 }
 
 status_t CameraService::getCameraVendorTagDescriptor(/*out*/sp<VendorTagDescriptor>& desc) {
@@ -698,6 +676,20 @@
     return NO_ERROR;
 }
 
+String8 CameraService::toString(std::set<userid_t> intSet) {
+    String8 s("");
+    bool first = true;
+    for (userid_t i : intSet) {
+        if (first) {
+            s.appendFormat("%d", i);
+            first = false;
+        } else {
+            s.appendFormat(", %d", i);
+        }
+    }
+    return s;
+}
+
 status_t CameraService::initializeShimMetadata(int cameraId) {
     int uid = getCallingUid();
 
@@ -805,7 +797,7 @@
     // Check device policy for this camera
     char value[PROPERTY_VALUE_MAX];
     char key[PROPERTY_KEY_MAX];
-    int clientUserId = multiuser_get_user_id(clientUid);
+    userid_t clientUserId = multiuser_get_user_id(clientUid);
     snprintf(key, PROPERTY_KEY_MAX, "sys.secpolicy.camera.off_%d", clientUserId);
     property_get(key, value, "0");
     if (strcmp(value, "1") == 0) {
@@ -817,10 +809,10 @@
 
     // Only allow clients who are being used by the current foreground device user, unless calling
     // from our own process.
-    if (callingPid != getpid() &&
-            (mLastUserId != clientUserId && mLastUserId != DEFAULT_LAST_USER_ID)) {
-        ALOGE("CameraService::connect X (PID %d) rejected (cannot connect from previous "
-                "device user %d, current device user %d)", callingPid, clientUserId, mLastUserId);
+    if (callingPid != getpid() && (mAllowedUsers.find(clientUserId) == mAllowedUsers.end())) {
+        ALOGE("CameraService::connect X (PID %d) rejected (cannot connect from "
+                "device user %d, currently allowed device users: %s)", callingPid, clientUserId,
+                toString(mAllowedUsers).string());
         return PERMISSION_DENIED;
     }
 
@@ -1219,10 +1211,10 @@
     return OK;
 }
 
-void CameraService::notifySystemEvent(int eventId, int arg0) {
+void CameraService::notifySystemEvent(int32_t eventId, const int32_t* args, size_t length) {
     switch(eventId) {
         case ICameraService::USER_SWITCHED: {
-            doUserSwitch(/*newUserId*/arg0);
+            doUserSwitch(/*newUserIds*/args, /*length*/length);
             break;
         }
         case ICameraService::NO_EVENT:
@@ -1465,20 +1457,30 @@
     return clientDescriptorPtr->getValue();
 }
 
-void CameraService::doUserSwitch(int newUserId) {
+void CameraService::doUserSwitch(const int32_t* newUserId, size_t length) {
     // Acquire mServiceLock and prevent other clients from connecting
     std::unique_ptr<AutoConditionLock> lock =
             AutoConditionLock::waitAndAcquire(mServiceLockWrapper);
 
-    if (newUserId <= 0) {
-        ALOGW("%s: Bad user ID %d given during user switch, resetting to default.", __FUNCTION__,
-                newUserId);
-        newUserId = DEFAULT_LAST_USER_ID;
+    std::set<userid_t> newAllowedUsers;
+    for (size_t i = 0; i < length; i++) {
+        if (newUserId[i] < 0) {
+            ALOGE("%s: Bad user ID %d given during user switch, ignoring.",
+                    __FUNCTION__, newUserId[i]);
+            return;
+        }
+        newAllowedUsers.insert(static_cast<userid_t>(newUserId[i]));
     }
 
-    logUserSwitch(mLastUserId, newUserId);
 
-    mLastUserId = newUserId;
+    if (newAllowedUsers == mAllowedUsers) {
+        ALOGW("%s: Received notification of user switch with no updated user IDs.", __FUNCTION__);
+        return;
+    }
+
+    logUserSwitch(mAllowedUsers, newAllowedUsers);
+
+    mAllowedUsers = std::move(newAllowedUsers);
 
     // Current user has switched, evict all current clients.
     std::vector<sp<BasicClient>> evicted;
@@ -1490,6 +1492,13 @@
             continue;
         }
 
+        // Don't evict clients that are still allowed.
+        uid_t clientUid = clientSp->getClientUid();
+        userid_t clientUserId = multiuser_get_user_id(clientUid);
+        if (mAllowedUsers.find(clientUserId) != mAllowedUsers.end()) {
+            continue;
+        }
+
         evicted.push_back(clientSp);
 
         String8 curTime = getFormattedCurrentTime();
@@ -1549,10 +1558,13 @@
             cameraId, clientPackage, clientPid, reason));
 }
 
-void CameraService::logUserSwitch(int oldUserId, int newUserId) {
+void CameraService::logUserSwitch(const std::set<userid_t>& oldUserIds,
+        const std::set<userid_t>& newUserIds) {
+    String8 newUsers = toString(newUserIds);
+    String8 oldUsers = toString(oldUserIds);
     // Log the new and old users
-    logEvent(String8::format("USER_SWITCH from old user: %d , to new user: %d", oldUserId,
-            newUserId));
+    logEvent(String8::format("USER_SWITCH previous allowed users: %s , current allowed users: %s",
+            oldUsers.string(), newUsers.string()));
 }
 
 void CameraService::logDeviceRemoved(const char* cameraId, const char* reason) {
@@ -1757,6 +1769,10 @@
     return mClientPid;
 }
 
+uid_t CameraService::BasicClient::getClientUid() const {
+    return mClientUid;
+}
+
 bool CameraService::BasicClient::canCastToApiClient(apiLevel level) const {
     // Defaults to API2.
     return level == API_2;
@@ -1959,12 +1975,18 @@
         auto conflicting = i->getConflicting();
         auto clientSp = i->getValue();
         String8 packageName;
+        userid_t clientUserId;
         if (clientSp.get() != nullptr) {
             packageName = String8{clientSp->getPackageName()};
+            uid_t clientUid = clientSp->getClientUid();
+            clientUserId = multiuser_get_user_id(clientUid);
         }
         ret.appendFormat("\n(Camera ID: %s, Cost: %" PRId32 ", PID: %" PRId32 ", Priority: %"
                 PRId32 ", ", key.string(), cost, pid, priority);
 
+        if (clientSp.get() != nullptr) {
+            ret.appendFormat("User Id: %d, ", clientUserId);
+        }
         if (packageName.size() != 0) {
             ret.appendFormat("Client Package Name: %s", packageName.string());
         }
@@ -2047,6 +2069,7 @@
         result.appendFormat("Number of camera devices: %d\n", mNumberOfCameras);
         String8 activeClientString = mActiveClientManager.toString();
         result.appendFormat("Active Camera Clients:\n%s", activeClientString.string());
+        result.appendFormat("Allowed users:\n%s\n", toString(mAllowedUsers).string());
 
         sp<VendorTagDescriptor> desc = VendorTagDescriptor::getGlobalVendorTagDescriptor();
         if (desc == NULL) {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 8df746a..9b7163a 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -71,22 +71,8 @@
         API_2 = 2
     };
 
-    // Process States (mirrors frameworks/base/core/java/android/app/ActivityManager.java)
+    // Process state (mirrors frameworks/base/core/java/android/app/ActivityManager.java)
     static const int PROCESS_STATE_NONEXISTENT = -1;
-    static const int PROCESS_STATE_PERSISTENT = 0;
-    static const int PROCESS_STATE_PERSISTENT_UI = 1;
-    static const int PROCESS_STATE_TOP = 2;
-    static const int PROCESS_STATE_IMPORTANT_FOREGROUND = 3;
-    static const int PROCESS_STATE_IMPORTANT_BACKGROUND = 4;
-    static const int PROCESS_STATE_BACKUP = 5;
-    static const int PROCESS_STATE_HEAVY_WEIGHT = 6;
-    static const int PROCESS_STATE_SERVICE = 7;
-    static const int PROCESS_STATE_RECEIVER = 8;
-    static const int PROCESS_STATE_HOME = 9;
-    static const int PROCESS_STATE_LAST_ACTIVITY = 10;
-    static const int PROCESS_STATE_CACHED_ACTIVITY = 11;
-    static const int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 12;
-    static const int PROCESS_STATE_CACHED_EMPTY = 13;
 
     // 3 second busy timeout when other clients are connecting
     static const nsecs_t DEFAULT_CONNECT_TIMEOUT_NS = 3000000000;
@@ -97,11 +83,6 @@
     // Default number of messages to store in eviction log
     static const size_t DEFAULT_EVENT_LOG_LENGTH = 100;
 
-    enum {
-        // Default last user id
-        DEFAULT_LAST_USER_ID = 0,
-    };
-
     // Implementation of BinderService<T>
     static char const* getServiceName() { return "media.camera"; }
 
@@ -155,7 +136,7 @@
     virtual status_t    setTorchMode(const String16& cameraId, bool enabled,
             const sp<IBinder>& clientBinder);
 
-    virtual void notifySystemEvent(int eventId, int arg0);
+    virtual void notifySystemEvent(int32_t eventId, const int32_t* args, size_t length);
 
     // OK = supports api of that version, -EOPNOTSUPP = does not support
     virtual status_t    supportsCameraApi(
@@ -214,6 +195,9 @@
         virtual void notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
                 const CaptureResultExtras& resultExtras) = 0;
 
+        // Get the UID of the application client using this
+        virtual uid_t getClientUid() const;
+
         // Get the PID of the application client using this
         virtual int getClientPid() const;
 
@@ -483,7 +467,6 @@
             const String16& clientPackageName, int clientUid, apiLevel effectiveApiLevel,
             bool legacyMode, bool shimUpdateOnly, /*out*/sp<CLIENT>& device);
 
-
     // Lock guarding camera service state
     Mutex               mServiceLock;
 
@@ -506,8 +489,8 @@
     RingBuffer<String8> mEventLog;
     Mutex mLogLock;
 
-    // UID of last user.
-    int mLastUserId;
+    // Currently allowed user IDs
+    std::set<userid_t> mAllowedUsers;
 
     /**
      * Get the camera state for a given camera id.
@@ -556,7 +539,7 @@
     /**
      * Handle a notification that the current device user has changed.
      */
-    void doUserSwitch(int newUserId);
+    void doUserSwitch(const int32_t* newUserId, size_t length);
 
     /**
      * Add an event log message.
@@ -582,7 +565,8 @@
     /**
      * Add an event log message that the current device user has been switched.
      */
-    void logUserSwitch(int oldUserId, int newUserId);
+    void logUserSwitch(const std::set<userid_t>& oldUserIds,
+        const std::set<userid_t>& newUserIds);
 
     /**
      * Add an event log message that a device has been removed by the HAL
@@ -713,6 +697,11 @@
             int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
             int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
             /*out*/sp<BasicClient>* client);
+
+    status_t checkCameraAccess(const String16& opPackageName);
+
+    static String8 toString(std::set<userid_t> intSet);
+
 };
 
 template<class Func>
@@ -789,15 +778,6 @@
         if((ret = validateConnectLocked(cameraId, /*inout*/clientUid)) != NO_ERROR) {
             return ret;
         }
-        int userId = multiuser_get_user_id(clientUid);
-
-        if (userId != mLastUserId && clientPid != getpid() ) {
-            // If no previous user ID had been set, set to the user of the caller.
-            logUserSwitch(mLastUserId, userId);
-            LOG_ALWAYS_FATAL_IF(mLastUserId != DEFAULT_LAST_USER_ID,
-                    "Invalid state: Should never update user ID here unless was default");
-            mLastUserId = userId;
-        }
 
         // Check the shim parameters after acquiring lock, if they have already been updated and
         // we were doing a shim update, return immediately
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 9c4f9cd..b6f6677 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -691,15 +691,10 @@
         return BAD_VALUE;
     }
 
-    // Also returns BAD_VALUE if stream ID was not valid
+    // Also returns BAD_VALUE if stream ID was not valid, or stream already
+    // has been used
     res = mDevice->prepare(streamId);
 
-    if (res == BAD_VALUE) {
-        ALOGE("%s: Camera %d: Unexpected BAD_VALUE when preparing stream, but we"
-              " already checked and the stream ID (%d) should be valid.",
-              __FUNCTION__, mCameraId, streamId);
-    }
-
     return res;
 }
 
diff --git a/services/camera/libcameraservice/common/CameraModule.cpp b/services/camera/libcameraservice/common/CameraModule.cpp
index 064ff71..c662853 100644
--- a/services/camera/libcameraservice/common/CameraModule.cpp
+++ b/services/camera/libcameraservice/common/CameraModule.cpp
@@ -31,6 +31,7 @@
 
     // Keys added in HAL3.3
     if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_3) {
+        const size_t NUM_DERIVED_KEYS_HAL3_3 = 3;
         Vector<uint8_t> controlModes;
         uint8_t data = ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE;
         chars.update(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &data, /*count*/1);
@@ -78,6 +79,17 @@
         }
 
         chars.update(ANDROID_CONTROL_AVAILABLE_MODES, controlModes);
+
+        entry = chars.find(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
+        Vector<int32_t> availableCharsKeys;
+        availableCharsKeys.setCapacity(entry.count + NUM_DERIVED_KEYS_HAL3_3);
+        for (size_t i = 0; i < entry.count; i++) {
+            availableCharsKeys.push(entry.data.i32[i]);
+        }
+        availableCharsKeys.push(ANDROID_CONTROL_AE_LOCK_AVAILABLE);
+        availableCharsKeys.push(ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE);
+        availableCharsKeys.push(ANDROID_CONTROL_AVAILABLE_MODES);
+        chars.update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, availableCharsKeys);
     }
     return;
 }
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index d2c2482..445c9c2 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1342,6 +1342,8 @@
 status_t Camera3Device::prepare(int streamId) {
     ATRACE_CALL();
     ALOGV("%s: Camera %d: Preparing stream %d", __FUNCTION__, mId, streamId);
+    Mutex::Autolock il(mInterfaceLock);
+    Mutex::Autolock l(mLock);
 
     sp<Camera3StreamInterface> stream;
     ssize_t outputStreamIdx = mOutputStreams.indexOfKey(streamId);
@@ -1353,14 +1355,12 @@
     stream = mOutputStreams.editValueAt(outputStreamIdx);
 
     if (stream->isUnpreparable() || stream->hasOutstandingBuffers() ) {
-        ALOGE("%s: Camera %d: Stream %d has already been a request target",
-                __FUNCTION__, mId, streamId);
+        CLOGE("Stream %d has already been a request target", streamId);
         return BAD_VALUE;
     }
 
     if (mRequestThread->isStreamPending(stream)) {
-        ALOGE("%s: Camera %d: Stream %d is already a target in a pending request",
-                __FUNCTION__, mId, streamId);
+        CLOGE("Stream %d is already a target in a pending request", streamId);
         return BAD_VALUE;
     }
 
diff --git a/services/camera/libcameraservice/utils/ClientManager.h b/services/camera/libcameraservice/utils/ClientManager.h
index aa40a2d..5afb7a3 100644
--- a/services/camera/libcameraservice/utils/ClientManager.h
+++ b/services/camera/libcameraservice/utils/ClientManager.h
@@ -432,15 +432,17 @@
 
     auto iter = evicted.cbegin();
 
-    // Remove evicted clients from list
-    mClients.erase(std::remove_if(mClients.begin(), mClients.end(),
-        [&iter] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
-            if (curClientPtr->getKey() == (*iter)->getKey()) {
-                iter++;
-                return true;
-            }
-            return false;
-        }), mClients.end());
+    if (iter != evicted.cend()) {
+        // Remove evicted clients from list
+        mClients.erase(std::remove_if(mClients.begin(), mClients.end(),
+            [&iter] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
+                if (curClientPtr->getKey() == (*iter)->getKey()) {
+                    iter++;
+                    return true;
+                }
+                return false;
+            }), mClients.end());
+    }
 
     mClients.push_back(client);
     mRemovedCondition.broadcast();