Merge "Camera: Check for invalid camera during API version calls"
diff --git a/include/media/IMediaExtractor.h b/include/media/IMediaExtractor.h
index e0a81f1..06db359 100644
--- a/include/media/IMediaExtractor.h
+++ b/include/media/IMediaExtractor.h
@@ -42,6 +42,8 @@
     // returns an empty metadata object.
     virtual sp<MetaData> getMetaData() = 0;
 
+    virtual status_t getMetrics(Parcel *reply) = 0;
+
     enum Flags {
         CAN_SEEK_BACKWARD  = 1,  // the "seek 10secs back button"
         CAN_SEEK_FORWARD   = 2,  // the "seek 10secs forward button"
diff --git a/include/media/stagefright/MediaExtractor.h b/include/media/stagefright/MediaExtractor.h
index 211f794..9ce6cc5 100644
--- a/include/media/stagefright/MediaExtractor.h
+++ b/include/media/stagefright/MediaExtractor.h
@@ -48,6 +48,8 @@
     // returns an empty metadata object.
     virtual sp<MetaData> getMetaData();
 
+    status_t getMetrics(Parcel *reply);
+
     enum Flags {
         CAN_SEEK_BACKWARD  = 1,  // the "seek 10secs back button"
         CAN_SEEK_FORWARD   = 2,  // the "seek 10secs forward button"
@@ -74,6 +76,8 @@
 
     MediaAnalyticsItem *mAnalyticsItem;
 
+    virtual void populateMetrics();
+
 private:
 
     typedef bool (*SnifferFunc)(
diff --git a/include/media/stagefright/NuMediaExtractor.h b/include/media/stagefright/NuMediaExtractor.h
index e414757..ad0d37b 100644
--- a/include/media/stagefright/NuMediaExtractor.h
+++ b/include/media/stagefright/NuMediaExtractor.h
@@ -78,6 +78,7 @@
     status_t getSampleTrackIndex(size_t *trackIndex);
     status_t getSampleTime(int64_t *sampleTimeUs);
     status_t getSampleMeta(sp<MetaData> *sampleMeta);
+    status_t getMetrics(Parcel *reply);
 
     bool getCachedDuration(int64_t *durationUs, bool *eos) const;
 
diff --git a/media/libaudiohal/StreamHalHidl.cpp b/media/libaudiohal/StreamHalHidl.cpp
index 9ee8fa8..36ea1be 100644
--- a/media/libaudiohal/StreamHalHidl.cpp
+++ b/media/libaudiohal/StreamHalHidl.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#include <time.h>
-
 #define LOG_TAG "StreamHalHidl"
 //#define LOG_NDEBUG 0
 
@@ -40,6 +38,7 @@
 using ::android::hardware::MQDescriptorSync;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
+using ReadCommand = ::android::hardware::audio::V2_0::IStreamIn::ReadCommand;
 
 namespace android {
 
@@ -241,8 +240,7 @@
 }  // namespace
 
 StreamOutHalHidl::StreamOutHalHidl(const sp<IStreamOut>& stream)
-        : StreamHalHidl(stream.get()), mStream(stream), mEfGroup(nullptr),
-          mGetPresentationPositionNotSupported(false), mPPosFromWrite{ 0, OK, 0, { 0, 0 } } {
+        : StreamHalHidl(stream.get()), mStream(stream), mWriterClient(0), mEfGroup(nullptr) {
 }
 
 StreamOutHalHidl::~StreamOutHalHidl() {
@@ -265,7 +263,15 @@
 
 status_t StreamOutHalHidl::getLatency(uint32_t *latency) {
     if (mStream == 0) return NO_INIT;
-    return processReturn("getLatency", mStream->getLatency(), latency);
+    if (mWriterClient == gettid() && mCommandMQ) {
+        return callWriterThread(
+                WriteCommand::GET_LATENCY, "getLatency", nullptr, 0,
+                [&](const WriteStatus& writeStatus) {
+                    *latency = writeStatus.reply.latencyMs;
+                });
+    } else {
+        return processReturn("getLatency", mStream->getLatency(), latency);
+    }
 }
 
 status_t StreamOutHalHidl::setVolume(float left, float right) {
@@ -288,10 +294,30 @@
         return status;
     }
 
-    const size_t availBytes = mDataMQ->availableToWrite();
-    if (bytes > availBytes) { bytes = availBytes; }
-    if (!mDataMQ->write(static_cast<const uint8_t*>(buffer), bytes)) {
-        ALOGW("data message queue write failed");
+    return callWriterThread(
+            WriteCommand::WRITE, "write", static_cast<const uint8_t*>(buffer), bytes,
+            [&] (const WriteStatus& writeStatus) {
+                *written = writeStatus.reply.written;
+            });
+}
+
+status_t StreamOutHalHidl::callWriterThread(
+        WriteCommand cmd, const char* cmdName,
+        const uint8_t* data, size_t dataSize, StreamOutHalHidl::WriterCallback callback) {
+    if (!mCommandMQ->write(&cmd)) {
+        ALOGE("command message queue write failed for \"%s\"", cmdName);
+        return -EAGAIN;
+    }
+    if (data != nullptr) {
+        size_t availableToWrite = mDataMQ->availableToWrite();
+        if (dataSize > availableToWrite) {
+            ALOGW("truncating write data from %d to %d due to insufficient data queue space",
+                    (int32_t)dataSize, (int32_t)availableToWrite);
+            dataSize = availableToWrite;
+        }
+        if (!mDataMQ->write(data, dataSize)) {
+            ALOGE("data message queue write failed for \"%s\"", cmdName);
+        }
     }
     mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
 
@@ -301,24 +327,18 @@
     status_t ret = mEfGroup->wait(
             static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState, NS_PER_SEC);
     if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL)) {
-        WriteStatus writeStatus =
-                { Result::NOT_INITIALIZED, 0, Result::NOT_INITIALIZED, 0, { 0, 0 } };
-        mStatusMQ->read(&writeStatus);
-        if (writeStatus.writeRetval == Result::OK) {
-            status = OK;
-            *written = writeStatus.written;
-            mPPosFromWrite.status = processReturn(
-                    "get_presentation_position", writeStatus.presentationPositionRetval);
-            if (mPPosFromWrite.status == OK) {
-                mPPosFromWrite.frames = writeStatus.frames;
-                mPPosFromWrite.ts.tv_sec = writeStatus.timeStamp.tvSec;
-                mPPosFromWrite.ts.tv_nsec = writeStatus.timeStamp.tvNSec;
-            }
-            mPPosFromWrite.obtained = getCurrentTimeMs();
-        } else {
-            status = processReturn("write", writeStatus.writeRetval);
+        WriteStatus writeStatus;
+        writeStatus.retval = Result::NOT_INITIALIZED;
+        if (!mStatusMQ->read(&writeStatus)) {
+            ALOGE("status message read failed for \"%s\"", cmdName);
         }
-        return status;
+        if (writeStatus.retval == Result::OK) {
+            ret = OK;
+            callback(writeStatus);
+        } else {
+            ret = processReturn(cmdName, writeStatus.retval);
+        }
+        return ret;
     }
     if (ret == -EAGAIN) {
         // This normally retries no more than once.
@@ -327,23 +347,20 @@
     return ret;
 }
 
-uint64_t StreamOutHalHidl::getCurrentTimeMs() {
-    struct timespec timeNow;
-    clock_gettime(CLOCK_MONOTONIC, &timeNow);
-    return timeNow.tv_sec * 1000000 + timeNow.tv_nsec / 1000;
-}
-
 status_t StreamOutHalHidl::prepareForWriting(size_t bufferSize) {
+    std::unique_ptr<CommandMQ> tempCommandMQ;
     std::unique_ptr<DataMQ> tempDataMQ;
     std::unique_ptr<StatusMQ> tempStatusMQ;
     Result retval;
     Return<void> ret = mStream->prepareForWriting(
             1, bufferSize, ThreadPriority(mHalThreadPriority),
             [&](Result r,
+                    const CommandMQ::Descriptor& commandMQ,
                     const DataMQ::Descriptor& dataMQ,
                     const StatusMQ::Descriptor& statusMQ) {
                 retval = r;
                 if (retval == Result::OK) {
+                    tempCommandMQ.reset(new CommandMQ(commandMQ));
                     tempDataMQ.reset(new DataMQ(dataMQ));
                     tempStatusMQ.reset(new StatusMQ(statusMQ));
                     if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
@@ -354,8 +371,13 @@
     if (!ret.isOk() || retval != Result::OK) {
         return processReturn("prepareForWriting", ret, retval);
     }
-    if (!tempDataMQ || !tempDataMQ->isValid() || !tempStatusMQ || !tempStatusMQ->isValid()
-        || !mEfGroup) {
+    if (!tempCommandMQ || !tempCommandMQ->isValid() ||
+            !tempDataMQ || !tempDataMQ->isValid() ||
+            !tempStatusMQ || !tempStatusMQ->isValid() ||
+            !mEfGroup) {
+        ALOGE_IF(!tempCommandMQ, "Failed to obtain command message queue for writing");
+        ALOGE_IF(tempCommandMQ && !tempCommandMQ->isValid(),
+                "Command message queue for writing is invalid");
         ALOGE_IF(!tempDataMQ, "Failed to obtain data message queue for writing");
         ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "Data message queue for writing is invalid");
         ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for writing");
@@ -364,8 +386,10 @@
         ALOGE_IF(!mEfGroup, "Event flag creation for writing failed");
         return NO_INIT;
     }
+    mCommandMQ = std::move(tempCommandMQ);
     mDataMQ = std::move(tempDataMQ);
     mStatusMQ = std::move(tempStatusMQ);
+    mWriterClient = gettid();
     return OK;
 }
 
@@ -443,31 +467,27 @@
 
 status_t StreamOutHalHidl::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
     if (mStream == 0) return NO_INIT;
-    if (mGetPresentationPositionNotSupported) return INVALID_OPERATION;
-    if (getCurrentTimeMs() - mPPosFromWrite.obtained <= 1000) {
-        // No more than 1 ms passed since the last write, use cached result to avoid binder calls.
-        if (mPPosFromWrite.status == OK) {
-            *frames = mPPosFromWrite.frames;
-            timestamp->tv_sec = mPPosFromWrite.ts.tv_sec;
-            timestamp->tv_nsec = mPPosFromWrite.ts.tv_nsec;
-        }
-        return mPPosFromWrite.status;
+    if (mWriterClient == gettid() && mCommandMQ) {
+        return callWriterThread(
+                WriteCommand::GET_PRESENTATION_POSITION, "getPresentationPosition", nullptr, 0,
+                [&](const WriteStatus& writeStatus) {
+                    *frames = writeStatus.reply.presentationPosition.frames;
+                    timestamp->tv_sec = writeStatus.reply.presentationPosition.timeStamp.tvSec;
+                    timestamp->tv_nsec = writeStatus.reply.presentationPosition.timeStamp.tvNSec;
+                });
+    } else {
+        Result retval;
+        Return<void> ret = mStream->getPresentationPosition(
+                [&](Result r, uint64_t hidlFrames, const TimeSpec& hidlTimeStamp) {
+                    retval = r;
+                    if (retval == Result::OK) {
+                        *frames = hidlFrames;
+                        timestamp->tv_sec = hidlTimeStamp.tvSec;
+                        timestamp->tv_nsec = hidlTimeStamp.tvNSec;
+                    }
+                });
+        return processReturn("getPresentationPosition", ret, retval);
     }
-
-    Result retval;
-    Return<void> ret = mStream->getPresentationPosition(
-            [&](Result r, uint64_t hidlFrames, const TimeSpec& hidlTimeStamp) {
-                retval = r;
-                if (retval == Result::OK) {
-                    *frames = hidlFrames;
-                    timestamp->tv_sec = hidlTimeStamp.tvSec;
-                    timestamp->tv_nsec = hidlTimeStamp.tvNSec;
-                }
-            });
-    if (ret.isOk() && retval == Result::NOT_SUPPORTED) {
-        mGetPresentationPositionNotSupported = true;
-    }
-    return processReturn("getPresentationPosition", ret, retval);
 }
 
 void StreamOutHalHidl::onWriteReady() {
@@ -493,7 +513,7 @@
 
 
 StreamInHalHidl::StreamInHalHidl(const sp<IStreamIn>& stream)
-        : StreamHalHidl(stream.get()), mStream(stream), mEfGroup(nullptr) {
+        : StreamHalHidl(stream.get()), mStream(stream), mReaderClient(0), mEfGroup(nullptr) {
 }
 
 StreamInHalHidl::~StreamInHalHidl() {
@@ -525,33 +545,53 @@
     }
 
     status_t status;
-    if (!mDataMQ) {
-        if ((status = prepareForReading(bytes)) != OK) return status;
-        // Trigger the first read.
-        mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
+    if (!mDataMQ && (status = prepareForReading(bytes)) != OK) {
+        return status;
     }
 
+    ReadParameters params;
+    params.command = ReadCommand::READ;
+    params.params.read = bytes;
+    return callReaderThread(params, "read",
+            [&](const ReadStatus& readStatus) {
+                const size_t availToRead = mDataMQ->availableToRead();
+                if (!mDataMQ->read(static_cast<uint8_t*>(buffer), std::min(bytes, availToRead))) {
+                    ALOGE("data message queue read failed for \"read\"");
+                }
+                ALOGW_IF(availToRead != readStatus.reply.read,
+                        "HAL read report inconsistent: mq = %d, status = %d",
+                        (int32_t)availToRead, (int32_t)readStatus.reply.read);
+                *read = readStatus.reply.read;
+            });
+}
+
+status_t StreamInHalHidl::callReaderThread(
+        const ReadParameters& params, const char* cmdName,
+        StreamInHalHidl::ReaderCallback callback) {
+    if (!mCommandMQ->write(&params)) {
+        ALOGW("command message queue write failed");
+        return -EAGAIN;
+    }
+    mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
+
     // TODO: Remove manual event flag handling once blocking MQ is implemented. b/33815422
     uint32_t efState = 0;
 retry:
     status_t ret = mEfGroup->wait(
             static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState, NS_PER_SEC);
     if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY)) {
-        ReadStatus readStatus = { Result::NOT_INITIALIZED, 0 };
-        const size_t availToRead = mDataMQ->availableToRead();
-        if (bytes > availToRead) { bytes = availToRead; }
-        mDataMQ->read(static_cast<uint8_t*>(buffer), bytes);
-        mStatusMQ->read(&readStatus);
-        mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
-        if (readStatus.retval == Result::OK) {
-            ALOGW_IF(availToRead != readStatus.read,
-                    "HAL read report inconsistent: mq = %d, status = %d",
-                    (int32_t)availToRead, (int32_t)readStatus.read);
-            *read = readStatus.read;
-        } else {
-            status = processReturn("read", readStatus.retval);
+        ReadStatus readStatus;
+        readStatus.retval = Result::NOT_INITIALIZED;
+        if (!mStatusMQ->read(&readStatus)) {
+            ALOGE("status message read failed for \"%s\"", cmdName);
         }
-        return status;
+         if (readStatus.retval == Result::OK) {
+            ret = OK;
+            callback(readStatus);
+        } else {
+            ret = processReturn(cmdName, readStatus.retval);
+        }
+        return ret;
     }
     if (ret == -EAGAIN) {
         // This normally retries no more than once.
@@ -561,16 +601,19 @@
 }
 
 status_t StreamInHalHidl::prepareForReading(size_t bufferSize) {
+    std::unique_ptr<CommandMQ> tempCommandMQ;
     std::unique_ptr<DataMQ> tempDataMQ;
     std::unique_ptr<StatusMQ> tempStatusMQ;
     Result retval;
     Return<void> ret = mStream->prepareForReading(
             1, bufferSize, ThreadPriority(mHalThreadPriority),
             [&](Result r,
+                    const CommandMQ::Descriptor& commandMQ,
                     const DataMQ::Descriptor& dataMQ,
                     const StatusMQ::Descriptor& statusMQ) {
                 retval = r;
                 if (retval == Result::OK) {
+                    tempCommandMQ.reset(new CommandMQ(commandMQ));
                     tempDataMQ.reset(new DataMQ(dataMQ));
                     tempStatusMQ.reset(new StatusMQ(statusMQ));
                     if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
@@ -581,8 +624,13 @@
     if (!ret.isOk() || retval != Result::OK) {
         return processReturn("prepareForReading", ret, retval);
     }
-    if (!tempDataMQ || !tempDataMQ->isValid() || !tempStatusMQ || !tempStatusMQ->isValid()
-        || !mEfGroup) {
+    if (!tempCommandMQ || !tempCommandMQ->isValid() ||
+            !tempDataMQ || !tempDataMQ->isValid() ||
+            !tempStatusMQ || !tempStatusMQ->isValid() ||
+            !mEfGroup) {
+        ALOGE_IF(!tempCommandMQ, "Failed to obtain command message queue for writing");
+        ALOGE_IF(tempCommandMQ && !tempCommandMQ->isValid(),
+                "Command message queue for writing is invalid");
         ALOGE_IF(!tempDataMQ, "Failed to obtain data message queue for reading");
         ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "Data message queue for reading is invalid");
         ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for reading");
@@ -591,8 +639,10 @@
         ALOGE_IF(!mEfGroup, "Event flag creation for reading failed");
         return NO_INIT;
     }
+    mCommandMQ = std::move(tempCommandMQ);
     mDataMQ = std::move(tempDataMQ);
     mStatusMQ = std::move(tempStatusMQ);
+    mReaderClient = gettid();
     return OK;
 }
 
@@ -603,16 +653,26 @@
 
 status_t StreamInHalHidl::getCapturePosition(int64_t *frames, int64_t *time) {
     if (mStream == 0) return NO_INIT;
-    Result retval;
-    Return<void> ret = mStream->getCapturePosition(
-            [&](Result r, uint64_t hidlFrames, uint64_t hidlTime) {
-                retval = r;
-                if (retval == Result::OK) {
-                    *frames = hidlFrames;
-                    *time = hidlTime;
-                }
-            });
-    return processReturn("getCapturePosition", ret, retval);
+    if (mReaderClient == gettid() && mCommandMQ) {
+        ReadParameters params;
+        params.command = ReadCommand::GET_CAPTURE_POSITION;
+        return callReaderThread(params, "getCapturePosition",
+                [&](const ReadStatus& readStatus) {
+                    *frames = readStatus.reply.capturePosition.frames;
+                    *time = readStatus.reply.capturePosition.time;
+                });
+    } else {
+        Result retval;
+        Return<void> ret = mStream->getCapturePosition(
+                [&](Result r, uint64_t hidlFrames, uint64_t hidlTime) {
+                    retval = r;
+                    if (retval == Result::OK) {
+                        *frames = hidlFrames;
+                        *time = hidlTime;
+                    }
+                });
+        return processReturn("getCapturePosition", ret, retval);
+    }
 }
 
 } // namespace android
diff --git a/media/libaudiohal/StreamHalHidl.h b/media/libaudiohal/StreamHalHidl.h
index 8b5867e..db217a8 100644
--- a/media/libaudiohal/StreamHalHidl.h
+++ b/media/libaudiohal/StreamHalHidl.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_HARDWARE_STREAM_HAL_HIDL_H
 #define ANDROID_HARDWARE_STREAM_HAL_HIDL_H
 
+#include <atomic>
+
 #include <android/hardware/audio/2.0/IStream.h>
 #include <android/hardware/audio/2.0/IStreamIn.h>
 #include <android/hardware/audio/2.0/IStreamOut.h>
@@ -32,7 +34,9 @@
 using ::android::hardware::EventFlag;
 using ::android::hardware::MessageQueue;
 using ::android::hardware::Return;
+using ReadParameters = ::android::hardware::audio::V2_0::IStreamIn::ReadParameters;
 using ReadStatus = ::android::hardware::audio::V2_0::IStreamIn::ReadStatus;
+using WriteCommand = ::android::hardware::audio::V2_0::IStreamOut::WriteCommand;
 using WriteStatus = ::android::hardware::audio::V2_0::IStreamOut::WriteStatus;
 
 namespace android {
@@ -155,28 +159,27 @@
 
   private:
     friend class DeviceHalHidl;
+    typedef MessageQueue<WriteCommand, hardware::kSynchronizedReadWrite> CommandMQ;
     typedef MessageQueue<uint8_t, hardware::kSynchronizedReadWrite> DataMQ;
     typedef MessageQueue<WriteStatus, hardware::kSynchronizedReadWrite> StatusMQ;
 
     wp<StreamOutHalInterfaceCallback> mCallback;
     sp<IStreamOut> mStream;
+    std::unique_ptr<CommandMQ> mCommandMQ;
     std::unique_ptr<DataMQ> mDataMQ;
     std::unique_ptr<StatusMQ> mStatusMQ;
+    std::atomic<pid_t> mWriterClient;
     EventFlag* mEfGroup;
-    bool mGetPresentationPositionNotSupported;
-    struct {
-        uint64_t obtained;
-        status_t status;
-        uint64_t frames;
-        struct timespec ts;
-    } mPPosFromWrite;
 
     // Can not be constructed directly by clients.
     StreamOutHalHidl(const sp<IStreamOut>& stream);
 
     virtual ~StreamOutHalHidl();
 
-    uint64_t getCurrentTimeMs();
+    using WriterCallback = std::function<void(const WriteStatus& writeStatus)>;
+    status_t callWriterThread(
+            WriteCommand cmd, const char* cmdName,
+            const uint8_t* data, size_t dataSize, WriterCallback callback);
     status_t prepareForWriting(size_t bufferSize);
 };
 
@@ -200,12 +203,15 @@
 
   private:
     friend class DeviceHalHidl;
+    typedef MessageQueue<ReadParameters, hardware::kSynchronizedReadWrite> CommandMQ;
     typedef MessageQueue<uint8_t, hardware::kSynchronizedReadWrite> DataMQ;
     typedef MessageQueue<ReadStatus, hardware::kSynchronizedReadWrite> StatusMQ;
 
     sp<IStreamIn> mStream;
+    std::unique_ptr<CommandMQ> mCommandMQ;
     std::unique_ptr<DataMQ> mDataMQ;
     std::unique_ptr<StatusMQ> mStatusMQ;
+    std::atomic<pid_t> mReaderClient;
     EventFlag* mEfGroup;
 
     // Can not be constructed directly by clients.
@@ -213,6 +219,9 @@
 
     virtual ~StreamInHalHidl();
 
+    using ReaderCallback = std::function<void(const ReadStatus& readStatus)>;
+    status_t callReaderThread(
+            const ReadParameters& params, const char* cmdName, ReaderCallback callback);
     status_t prepareForReading(size_t bufferSize);
 };
 
diff --git a/media/libmedia/IMediaExtractor.cpp b/media/libmedia/IMediaExtractor.cpp
index 0f4f092..bfc43a6 100644
--- a/media/libmedia/IMediaExtractor.cpp
+++ b/media/libmedia/IMediaExtractor.cpp
@@ -36,7 +36,8 @@
     FLAGS,
     GETDRMTRACKINFO,
     SETUID,
-    NAME
+    NAME,
+    GETMETRICS
 };
 
 class BpMediaExtractor : public BpInterface<IMediaExtractor> {
@@ -94,6 +95,16 @@
         return NULL;
     }
 
+    virtual status_t getMetrics(Parcel * reply) {
+        Parcel data;
+        data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
+        status_t ret = remote()->transact(GETMETRICS, data, reply);
+        if (ret == NO_ERROR) {
+            return OK;
+        }
+        return UNKNOWN_ERROR;
+    }
+
     virtual uint32_t flags() const {
         ALOGV("flags NOT IMPLEMENTED");
         return 0;
@@ -169,6 +180,11 @@
             }
             return UNKNOWN_ERROR;
         }
+        case GETMETRICS: {
+            CHECK_INTERFACE(IMediaExtractor, data, reply);
+            status_t ret = getMetrics(reply);
+            return ret;
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/OMXBuffer.cpp b/media/libmedia/OMXBuffer.cpp
index 71d2908..6d54a13 100644
--- a/media/libmedia/OMXBuffer.cpp
+++ b/media/libmedia/OMXBuffer.cpp
@@ -90,6 +90,13 @@
 
         case kBufferTypeANWBuffer:
         {
+            if (mGraphicBuffer == NULL) {
+                return parcel->writeBool(false);
+            }
+            status_t err = parcel->writeBool(true);
+            if (err != OK) {
+                return err;
+            }
             return parcel->write(*mGraphicBuffer);
         }
 
@@ -130,15 +137,21 @@
 
         case kBufferTypeANWBuffer:
         {
-            sp<GraphicBuffer> buffer = new GraphicBuffer();
-
-            status_t err = parcel->read(*buffer);
-
+            bool notNull;
+            status_t err = parcel->readBool(&notNull);
             if (err != OK) {
                 return err;
             }
-
-            mGraphicBuffer = buffer;
+            if (notNull) {
+                sp<GraphicBuffer> buffer = new GraphicBuffer();
+                status_t err = parcel->read(*buffer);
+                if (err != OK) {
+                    return err;
+                }
+                mGraphicBuffer = buffer;
+            } else {
+                mGraphicBuffer = nullptr;
+            }
             break;
         }
 
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 9ce65c4..d00e377 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -275,6 +275,7 @@
 }
 
 status_t StagefrightRecorder::setNextOutputFile(int fd) {
+    Mutex::Autolock autolock(mLock);
     // Only support MPEG4
     if (mOutputFormat != OUTPUT_FORMAT_MPEG_4) {
         ALOGE("Only MP4 file format supports setting next output file");
@@ -290,6 +291,10 @@
     // start with a clean, empty file
     ftruncate(fd, 0);
     int nextFd = dup(fd);
+    if (mWriter == NULL) {
+        ALOGE("setNextOutputFile failed. Writer has been freed");
+        return INVALID_OPERATION;
+    }
     return mWriter->setNextFd(nextFd);
 }
 
@@ -851,6 +856,8 @@
 }
 
 status_t StagefrightRecorder::prepare() {
+    ALOGV("prepare");
+    Mutex::Autolock autolock(mLock);
     if (mVideoSource == VIDEO_SOURCE_SURFACE) {
         return prepareInternal();
     }
@@ -859,6 +866,7 @@
 
 status_t StagefrightRecorder::start() {
     ALOGV("start");
+    Mutex::Autolock autolock(mLock);
     if (mOutputFd < 0) {
         ALOGE("Output file descriptor is invalid");
         return INVALID_OPERATION;
@@ -1867,6 +1875,7 @@
 
 status_t StagefrightRecorder::stop() {
     ALOGV("stop");
+    Mutex::Autolock autolock(mLock);
     status_t err = OK;
 
     if (mCaptureFpsEnable && mCameraSourceTimeLapse != NULL) {
@@ -1984,6 +1993,7 @@
 status_t StagefrightRecorder::dump(
         int fd, const Vector<String16>& args) const {
     ALOGV("dump");
+    Mutex::Autolock autolock(mLock);
     const size_t SIZE = 256;
     char buffer[SIZE];
     String8 result;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 870c5d0..b7d0b0e 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -43,7 +43,6 @@
 struct StagefrightRecorder : public MediaRecorderBase {
     explicit StagefrightRecorder(const String16 &opPackageName);
     virtual ~StagefrightRecorder();
-
     virtual status_t init();
     virtual status_t setAudioSource(audio_source_t as);
     virtual status_t setVideoSource(video_source vs);
@@ -73,6 +72,7 @@
     virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() const;
 
 private:
+    mutable Mutex mLock;
     sp<hardware::ICamera> mCamera;
     sp<ICameraRecordingProxy> mCameraProxy;
     sp<IGraphicBufferProducer> mPreviewSurface;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 1d62498..0a0a8aa 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -634,6 +634,11 @@
     sp<MediaCodecBuffer> buffer;
     mCodec->getOutputBuffer(index, &buffer);
 
+    if (buffer == NULL) {
+        handleError(UNKNOWN_ERROR);
+        return false;
+    }
+
     if (index >= mOutputBuffers.size()) {
         for (size_t i = mOutputBuffers.size(); i <= index; ++i) {
             mOutputBuffers.add();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 42e95da..9350440 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -405,10 +405,10 @@
     msg->setInt32("flags", flags);
 
     sp<AMessage> response;
-    msg->postAndAwaitResponse(&response);
+    status_t postStatus = msg->postAndAwaitResponse(&response);
 
     int32_t err;
-    if (!response->findInt32("err", &err)) {
+    if (postStatus != OK || response.get() == nullptr || !response->findInt32("err", &err)) {
         err = INVALID_OPERATION;
     } else if (err == OK && isOffloaded != NULL) {
         int32_t offload;
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 4a965ba..ded79f3 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -130,7 +130,7 @@
         }
 
         String8 cacheConfig;
-        bool disconnectAtHighwatermark;
+        bool disconnectAtHighwatermark = false;
         KeyedVector<String8, String8> nonCacheSpecificHeaders;
         if (headers != NULL) {
             nonCacheSpecificHeaders = *headers;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 87d7d3c..0dd3e88 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -4515,8 +4515,8 @@
         // fall through
     }
 
-    off64_t offset;
-    size_t size;
+    off64_t offset = 0;
+    size_t size = 0;
     uint32_t cts, stts;
     bool isSyncSample;
     bool newBuffer = false;
@@ -5066,6 +5066,10 @@
     return NULL;
 }
 
+void MPEG4Extractor::populateMetrics() {
+    ALOGV("MPEG4Extractor::populateMetrics");
+}
+
 static bool LegacySniffMPEG4(
         const sp<DataSource> &source, String8 *mimeType, float *confidence) {
     uint8_t header[8];
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 677d43e..62c0d8a 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -55,7 +55,7 @@
 namespace android {
 
 // key for media statistics
-static const char *KeyName_Extractor = "extractor";
+static const char *kKeyExtractor = "extractor";
 // attrs for media statistics
 
 MediaExtractor::MediaExtractor() {
@@ -67,7 +67,7 @@
 
     mAnalyticsItem = NULL;
     if (MEDIA_LOG) {
-        mAnalyticsItem = new MediaAnalyticsItem(KeyName_Extractor);
+        mAnalyticsItem = new MediaAnalyticsItem(kKeyExtractor);
         (void) mAnalyticsItem->generateSessionID();
     }
 }
@@ -93,6 +93,23 @@
     return new MetaData;
 }
 
+status_t MediaExtractor::getMetrics(Parcel *reply) {
+
+    if (mAnalyticsItem == NULL || reply == NULL) {
+        return UNKNOWN_ERROR;
+    }
+
+    populateMetrics();
+    mAnalyticsItem->writeToParcel(reply);
+
+    return OK;
+}
+
+void MediaExtractor::populateMetrics() {
+    ALOGV("MediaExtractor::populateMetrics");
+    // normally overridden in subclasses
+}
+
 uint32_t MediaExtractor::flags() const {
     return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_PAUSE | CAN_SEEK;
 }
@@ -247,24 +264,23 @@
        // track the container format (mpeg, aac, wvm, etc)
        if (MEDIA_LOG) {
           if (ret->mAnalyticsItem != NULL) {
+              size_t ntracks = ret->countTracks();
               ret->mAnalyticsItem->setCString("fmt",  ret->name());
               // tracks (size_t)
-              ret->mAnalyticsItem->setInt32("ntrk",  ret->countTracks());
+              ret->mAnalyticsItem->setInt32("ntrk",  ntracks);
               // metadata
               sp<MetaData> pMetaData = ret->getMetaData();
               if (pMetaData != NULL) {
                 String8 xx = pMetaData->toString();
-                ALOGD("metadata says: %s", xx.string());
-                // can grab various fields like:
                 // 'titl' -- but this verges into PII
                 // 'mime'
                 const char *mime = NULL;
                 if (pMetaData->findCString(kKeyMIMEType, &mime)) {
                     ret->mAnalyticsItem->setCString("mime",  mime);
                 }
-                // what else is interesting here?
+                // what else is interesting and not already available?
               }
-          }
+	  }
        }
     }
 
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index d25ce6c..1c1acb0 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -569,6 +569,11 @@
     return OK;
 }
 
+status_t NuMediaExtractor::getMetrics(Parcel *reply) {
+    status_t status = mImpl->getMetrics(reply);
+    return status;
+}
+
 bool NuMediaExtractor::getTotalBitrate(int64_t *bitrate) const {
     if (mTotalBitrate >= 0) {
         *bitrate = mTotalBitrate;
diff --git a/media/libstagefright/SampleIterator.cpp b/media/libstagefright/SampleIterator.cpp
index 54c9fa3..4134698 100644
--- a/media/libstagefright/SampleIterator.cpp
+++ b/media/libstagefright/SampleIterator.cpp
@@ -305,8 +305,16 @@
         return ERROR_OUT_OF_RANGE;
     }
 
-    while (sampleIndex >= mTTSSampleIndex + mTTSCount) {
-        if (mTimeToSampleIndex == mTable->mTimeToSampleCount) {
+    while (true) {
+        if (mTTSSampleIndex > UINT32_MAX - mTTSCount) {
+            return ERROR_OUT_OF_RANGE;
+        }
+        if(sampleIndex < mTTSSampleIndex + mTTSCount) {
+            break;
+        }
+        if (mTimeToSampleIndex == mTable->mTimeToSampleCount ||
+            (mTTSDuration != 0 && mTTSCount > UINT32_MAX / mTTSDuration) ||
+            mTTSSampleTime > UINT32_MAX - (mTTSCount * mTTSDuration)) {
             return ERROR_OUT_OF_RANGE;
         }
 
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index fa05886..f847119 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -66,6 +66,8 @@
 protected:
     virtual ~MPEG4Extractor();
 
+    virtual void populateMetrics();
+
 private:
 
     struct PsshInfo {
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 4909100..a0ddc28 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -43,6 +43,35 @@
 
 static const OMX_U32 kPortIndexInput = 0;
 
+class GraphicBufferSource::OmxBufferSource : public BnOMXBufferSource {
+public:
+    GraphicBufferSource* mSource;
+
+    OmxBufferSource(GraphicBufferSource* source): mSource(source) {
+    }
+
+    Status onOmxExecuting() override {
+        return mSource->onOmxExecuting();
+    }
+
+    Status onOmxIdle() override {
+        return mSource->onOmxIdle();
+    }
+
+    Status onOmxLoaded() override {
+        return mSource->onOmxLoaded();
+    }
+
+    Status onInputBufferAdded(int bufferId) override {
+        return mSource->onInputBufferAdded(bufferId);
+    }
+
+    Status onInputBufferEmptied(
+            int bufferId, const OMXFenceParcelable& fenceParcel) override {
+        return mSource->onInputBufferEmptied(bufferId, fenceParcel);
+    }
+};
+
 GraphicBufferSource::GraphicBufferSource() :
     mInitCheck(UNKNOWN_ERROR),
     mExecuting(false),
@@ -66,7 +95,8 @@
     mTimePerFrameUs(-1ll),
     mPrevCaptureUs(-1ll),
     mPrevFrameUs(-1ll),
-    mInputBufferTimeOffsetUs(0ll) {
+    mInputBufferTimeOffsetUs(0ll),
+    mOmxBufferSource(new OmxBufferSource(this)) {
     ALOGV("GraphicBufferSource");
 
     String8 name("GraphicBufferSource");
@@ -766,7 +796,7 @@
     // Do setInputSurface() first, the node will try to enable metadata
     // mode on input, and does necessary error checking. If this fails,
     // we can't use this input surface on the node.
-    status_t err = omxNode->setInputSurface(this);
+    status_t err = omxNode->setInputSurface(mOmxBufferSource);
     if (err != NO_ERROR) {
         ALOGE("Unable to set input surface: %d", err);
         return Status::fromServiceSpecificError(err);
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h
index 80fe078..153a035 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/GraphicBufferSource.h
@@ -55,7 +55,6 @@
  * things up until we're ready to go.
  */
 class GraphicBufferSource : public BnGraphicBufferSource,
-                            public BnOMXBufferSource,
                             public BufferQueue::ConsumerListener {
 public:
     GraphicBufferSource();
@@ -77,26 +76,26 @@
     // This is called when OMX transitions to OMX_StateExecuting, which means
     // we can start handing it buffers.  If we already have buffers of data
     // sitting in the BufferQueue, this will send them to the codec.
-    Status onOmxExecuting() override;
+    Status onOmxExecuting();
 
     // This is called when OMX transitions to OMX_StateIdle, indicating that
     // the codec is meant to return all buffers back to the client for them
     // to be freed. Do NOT submit any more buffers to the component.
-    Status onOmxIdle() override;
+    Status onOmxIdle();
 
     // This is called when OMX transitions to OMX_StateLoaded, indicating that
     // we are shutting down.
-    Status onOmxLoaded() override;
+    Status onOmxLoaded();
 
     // A "codec buffer", i.e. a buffer that can be used to pass data into
     // the encoder, has been allocated.  (This call does not call back into
     // OMXNodeInstance.)
-    Status onInputBufferAdded(int32_t bufferID) override;
+    Status onInputBufferAdded(int32_t bufferID);
 
     // Called from OnEmptyBufferDone.  If we have a BQ buffer available,
     // fill it with a new frame of data; otherwise, just mark it as available.
     Status onInputBufferEmptied(
-            int32_t bufferID, const OMXFenceParcelable& fenceParcel) override;
+            int32_t bufferID, const OMXFenceParcelable& fenceParcel);
 
     // Configure the buffer source to be used with an OMX node with the default
     // data space.
@@ -301,6 +300,9 @@
 
     ColorAspects mColorAspects;
 
+    class OmxBufferSource;
+    sp<OmxBufferSource> mOmxBufferSource;
+
     void onMessageReceived(const sp<AMessage> &msg);
 
     DISALLOW_EVIL_CONSTRUCTORS(GraphicBufferSource);
diff --git a/media/libstagefright/omx/hal/1.0/impl/Conversion.h b/media/libstagefright/omx/hal/1.0/impl/Conversion.h
index d27a496..68a3ed2 100644
--- a/media/libstagefright/omx/hal/1.0/impl/Conversion.h
+++ b/media/libstagefright/omx/hal/1.0/impl/Conversion.h
@@ -294,7 +294,7 @@
     if (!*nh) {
         return false;
     }
-    t->fence = inHidlHandle(*nh);
+    t->fence = *nh;
     switch (l.type) {
         case omx_message::EVENT:
             t->type = Message::Type::EVENT;
@@ -592,6 +592,16 @@
         }
         case OMXBuffer::kBufferTypeANWBuffer: {
             t->type = CodecBuffer::Type::ANW_BUFFER;
+            if (l.mGraphicBuffer == nullptr) {
+                t->attr.anwBuffer.width = 0;
+                t->attr.anwBuffer.height = 0;
+                t->attr.anwBuffer.stride = 0;
+                t->attr.anwBuffer.format = static_cast<PixelFormat>(1);
+                t->attr.anwBuffer.layerCount = 0;
+                t->attr.anwBuffer.usage = 0;
+                t->nativeHandle = hidl_handle();
+                return true;
+            }
             t->attr.anwBuffer.width = l.mGraphicBuffer->getWidth();
             t->attr.anwBuffer.height = l.mGraphicBuffer->getHeight();
             t->attr.anwBuffer.stride = l.mGraphicBuffer->getStride();
@@ -636,6 +646,10 @@
             return true;
         }
         case CodecBuffer::Type::ANW_BUFFER: {
+            if (t.nativeHandle.getNativeHandle() == nullptr) {
+                *l = OMXBuffer(sp<GraphicBuffer>(nullptr));
+                return true;
+            }
             *l = OMXBuffer(sp<GraphicBuffer>(new GraphicBuffer(
                     t.attr.anwBuffer.width,
                     t.attr.anwBuffer.height,
@@ -2082,6 +2096,7 @@
     t->transformHint = l.transformHint;
     t->numPendingBuffers = l.numPendingBuffers;
     t->nextFrameNumber = l.nextFrameNumber;
+    t->bufferReplaced = l.bufferReplaced;
     return true;
 }
 
@@ -2107,6 +2122,7 @@
     l->transformHint = t.transformHint;
     l->numPendingBuffers = t.numPendingBuffers;
     l->nextFrameNumber = t.nextFrameNumber;
+    l->bufferReplaced = t.bufferReplaced;
     return true;
 }
 
diff --git a/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.cpp b/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.cpp
index 9de8e3e..8ba2924 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.cpp
+++ b/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.cpp
@@ -78,10 +78,6 @@
     return toBinderStatus(mBase->signalEndOfInputStream());
 }
 
-::android::IBinder* LWGraphicBufferSource::onAsBinder() {
-    return nullptr;
-}
-
 // TWGraphicBufferSource
 TWGraphicBufferSource::TWGraphicBufferSource(
         sp<LGraphicBufferSource> const& base) : mBase(base) {
@@ -89,47 +85,51 @@
 
 Return<void> TWGraphicBufferSource::configure(
         const sp<IOmxNode>& omxNode, Dataspace dataspace) {
-    return toHardwareStatus(mBase->configure(
-            new LWOmxNode(omxNode),
-            toRawDataspace(dataspace)));
+    mBase->configure(new LWOmxNode(omxNode), toRawDataspace(dataspace));
+    return Void();
 }
 
 Return<void> TWGraphicBufferSource::setSuspend(bool suspend) {
-    return toHardwareStatus(mBase->setSuspend(suspend));
+    mBase->setSuspend(suspend);
+    return Void();
 }
 
 Return<void> TWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
         int64_t repeatAfterUs) {
-    return toHardwareStatus(mBase->setRepeatPreviousFrameDelayUs(
-            repeatAfterUs));
+    mBase->setRepeatPreviousFrameDelayUs(repeatAfterUs);
+    return Void();
 }
 
 Return<void> TWGraphicBufferSource::setMaxFps(float maxFps) {
-    return toHardwareStatus(mBase->setMaxFps(maxFps));
+    mBase->setMaxFps(maxFps);
+    return Void();
 }
 
 Return<void> TWGraphicBufferSource::setTimeLapseConfig(
         int64_t timePerFrameUs, int64_t timePerCaptureUs) {
-    return toHardwareStatus(mBase->setTimeLapseConfig(
-            timePerFrameUs, timePerCaptureUs));
+    mBase->setTimeLapseConfig(timePerFrameUs, timePerCaptureUs);
+    return Void();
 }
 
 Return<void> TWGraphicBufferSource::setStartTimeUs(int64_t startTimeUs) {
-    return toHardwareStatus(mBase->setStartTimeUs(startTimeUs));
+    mBase->setStartTimeUs(startTimeUs);
+    return Void();
 }
 
 Return<void> TWGraphicBufferSource::setColorAspects(
         const ColorAspects& aspects) {
-    return toHardwareStatus(mBase->setColorAspects(toCompactColorAspects(
-            aspects)));
+    mBase->setColorAspects(toCompactColorAspects(aspects));
+    return Void();
 }
 
 Return<void> TWGraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
-    return toHardwareStatus(mBase->setTimeOffsetUs(timeOffsetUs));
+    mBase->setTimeOffsetUs(timeOffsetUs);
+    return Void();
 }
 
 Return<void> TWGraphicBufferSource::signalEndOfInputStream() {
-    return toHardwareStatus(mBase->signalEndOfInputStream());
+    mBase->signalEndOfInputStream();
+    return Void();
 }
 
 }  // namespace implementation
diff --git a/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.h b/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.h
index 0b9f2ed..69efdde 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.h
+++ b/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.h
@@ -23,7 +23,7 @@
 
 #include <frameworks/native/include/binder/Binder.h>
 #include <IOMX.h>
-#include <android/IGraphicBufferSource.h>
+#include <android/BnGraphicBufferSource.h>
 #include <android/hardware/media/omx/1.0/IOmxNode.h>
 
 #include <android/hardware/graphics/common/1.0/types.h>
@@ -60,10 +60,11 @@
  */
 
 typedef ::android::IGraphicBufferSource LGraphicBufferSource;
+typedef ::android::BnGraphicBufferSource BnGraphicBufferSource;
 typedef ::android::hardware::media::omx::V1_0::IGraphicBufferSource
         TGraphicBufferSource;
 
-struct LWGraphicBufferSource : public LGraphicBufferSource {
+struct LWGraphicBufferSource : public BnGraphicBufferSource {
     sp<TGraphicBufferSource> mBase;
     LWGraphicBufferSource(sp<TGraphicBufferSource> const& base);
     ::android::binder::Status configure(
@@ -78,8 +79,6 @@
     ::android::binder::Status setColorAspects(int32_t aspects) override;
     ::android::binder::Status setTimeOffsetUs(int64_t timeOffsetsUs) override;
     ::android::binder::Status signalEndOfInputStream() override;
-protected:
-    ::android::IBinder* onAsBinder() override;
 };
 
 struct TWGraphicBufferSource : public TGraphicBufferSource {
diff --git a/media/libstagefright/omx/hal/1.0/impl/WOmx.cpp b/media/libstagefright/omx/hal/1.0/impl/WOmx.cpp
index 0fa8c4c..da1c23d 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WOmx.cpp
+++ b/media/libstagefright/omx/hal/1.0/impl/WOmx.cpp
@@ -79,10 +79,6 @@
     return transStatus == NO_ERROR ? fnStatus : transStatus;
 }
 
-::android::IBinder* LWOmx::onAsBinder() {
-    return nullptr;
-}
-
 // TWOmx
 TWOmx::TWOmx(sp<IOMX> const& base) : mBase(base) {
 }
diff --git a/media/libstagefright/omx/hal/1.0/impl/WOmx.h b/media/libstagefright/omx/hal/1.0/impl/WOmx.h
index 5618d27..ab11c6a 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WOmx.h
+++ b/media/libstagefright/omx/hal/1.0/impl/WOmx.h
@@ -45,6 +45,7 @@
 
 using ::android::List;
 using ::android::IOMX;
+using ::android::BnOMX;
 
 /**
  * Wrapper classes for conversion
@@ -55,7 +56,7 @@
  * - TW = Treble Wrapper --- It wraps a legacy object inside a Treble object.
  */
 
-struct LWOmx : public IOMX {
+struct LWOmx : public BnOMX {
     sp<IOmx> mBase;
     LWOmx(sp<IOmx> const& base);
     status_t listNodes(List<IOMX::ComponentInfo>* list) override;
@@ -66,8 +67,6 @@
     status_t createInputSurface(
             sp<::android::IGraphicBufferProducer>* bufferProducer,
             sp<::android::IGraphicBufferSource>* bufferSource) override;
-protected:
-    ::android::IBinder* onAsBinder() override;
 };
 
 struct TWOmx : public IOmx {
diff --git a/media/libstagefright/omx/hal/1.0/impl/WOmxBufferProducer.cpp b/media/libstagefright/omx/hal/1.0/impl/WOmxBufferProducer.cpp
index a459c9f..3bd6c6e 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WOmxBufferProducer.cpp
+++ b/media/libstagefright/omx/hal/1.0/impl/WOmxBufferProducer.cpp
@@ -203,7 +203,8 @@
 Return<void> TWOmxBufferProducer::connect(
         const sp<IOmxProducerListener>& listener,
         int32_t api, bool producerControlledByApp, connect_cb _hidl_cb) {
-    sp<IProducerListener> lListener = new LWOmxProducerListener(listener);
+    sp<IProducerListener> lListener = listener == nullptr ?
+            nullptr : new LWOmxProducerListener(listener);
     IGraphicBufferProducer::QueueBufferOutput lOutput;
     status_t status = mBase->connect(lListener,
             static_cast<int>(api),
@@ -479,7 +480,8 @@
 status_t LWOmxBufferProducer::connect(
         const sp<IProducerListener>& listener, int api,
         bool producerControlledByApp, QueueBufferOutput* output) {
-    sp<IOmxProducerListener> tListener = new TWOmxProducerListener(listener);
+    sp<IOmxProducerListener> tListener = listener == nullptr ?
+            nullptr : new TWOmxProducerListener(listener);
     status_t fnStatus;
     status_t transStatus = toStatusT(mBase->connect(
             tListener, static_cast<int32_t>(api), producerControlledByApp,
@@ -582,10 +584,6 @@
     return transStatus == NO_ERROR ? fnStatus : transStatus;
 }
 
-::android::IBinder* LWOmxBufferProducer::onAsBinder() {
-    return nullptr;
-}
-
 }  // namespace implementation
 }  // namespace V1_0
 }  // namespace omx
diff --git a/media/libstagefright/omx/hal/1.0/impl/WOmxBufferProducer.h b/media/libstagefright/omx/hal/1.0/impl/WOmxBufferProducer.h
index a991f49..65b093c 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WOmxBufferProducer.h
+++ b/media/libstagefright/omx/hal/1.0/impl/WOmxBufferProducer.h
@@ -47,6 +47,7 @@
 using ::android::sp;
 
 using ::android::IGraphicBufferProducer;
+using ::android::BnGraphicBufferProducer;
 using ::android::IProducerListener;
 
 struct TWOmxBufferProducer : public IOmxBufferProducer {
@@ -91,7 +92,7 @@
     Return<void> getUniqueId(getUniqueId_cb _hidl_cb) override;
 };
 
-struct LWOmxBufferProducer : public IGraphicBufferProducer {
+struct LWOmxBufferProducer : public BnGraphicBufferProducer {
     sp<IOmxBufferProducer> mBase;
     LWOmxBufferProducer(sp<IOmxBufferProducer> const& base);
 
@@ -128,8 +129,6 @@
           sp<Fence>* outFence, float outTransformMatrix[16]) override;
     void getFrameTimestamps(FrameEventHistoryDelta* outDelta) override;
     status_t getUniqueId(uint64_t* outId) const override;
-protected:
-    ::android::IBinder* onAsBinder() override;
 };
 
 }  // namespace implementation
diff --git a/media/libstagefright/omx/hal/1.0/impl/WOmxBufferSource.cpp b/media/libstagefright/omx/hal/1.0/impl/WOmxBufferSource.cpp
index 2e00894..97bcee0 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WOmxBufferSource.cpp
+++ b/media/libstagefright/omx/hal/1.0/impl/WOmxBufferSource.cpp
@@ -61,38 +61,34 @@
     ::android::binder::Status status = toBinderStatus(
             mBase->onInputBufferEmptied(
             static_cast<uint32_t>(bufferId), fence));
-    if (native_handle_delete(fenceNh) != 0) {
-        return ::android::binder::Status::fromExceptionCode(
-                ::android::binder::Status::EX_NULL_POINTER,
-                "Cannot delete native handle");
-    }
+    native_handle_close(fenceNh);
+    native_handle_delete(fenceNh);
     return status;
 }
 
-::android::IBinder* LWOmxBufferSource::onAsBinder() {
-    return nullptr;
-}
-
 // TWOmxBufferSource
 TWOmxBufferSource::TWOmxBufferSource(sp<IOMXBufferSource> const& base) :
     mBase(base) {
 }
 
 Return<void> TWOmxBufferSource::onOmxExecuting() {
-    return toHardwareStatus(mBase->onOmxExecuting());
+    mBase->onOmxExecuting();
+    return Void();
 }
 
 Return<void> TWOmxBufferSource::onOmxIdle() {
-    return toHardwareStatus(mBase->onOmxIdle());
+    mBase->onOmxIdle();
+    return Void();
 }
 
 Return<void> TWOmxBufferSource::onOmxLoaded() {
-    return toHardwareStatus(mBase->onOmxLoaded());
+    mBase->onOmxLoaded();
+    return Void();
 }
 
 Return<void> TWOmxBufferSource::onInputBufferAdded(uint32_t buffer) {
-    return toHardwareStatus(mBase->onInputBufferAdded(
-            static_cast<int32_t>(buffer)));
+    mBase->onInputBufferAdded(int32_t(buffer));
+    return Void();
 }
 
 Return<void> TWOmxBufferSource::onInputBufferEmptied(
@@ -102,8 +98,8 @@
       return ::android::hardware::Status::fromExceptionCode(
               ::android::hardware::Status::EX_BAD_PARCELABLE);
     }
-    return toHardwareStatus(mBase->onInputBufferEmptied(
-            static_cast<int32_t>(buffer), fenceParcelable));
+    mBase->onInputBufferEmptied(int32_t(buffer), fenceParcelable);
+    return Void();
 }
 
 }  // namespace implementation
diff --git a/media/libstagefright/omx/hal/1.0/impl/WOmxBufferSource.h b/media/libstagefright/omx/hal/1.0/impl/WOmxBufferSource.h
index a2e940f..83bf46f 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WOmxBufferSource.h
+++ b/media/libstagefright/omx/hal/1.0/impl/WOmxBufferSource.h
@@ -22,7 +22,7 @@
 #include <hidl/Status.h>
 
 #include <frameworks/native/include/binder/Binder.h>
-#include <android/IOMXBufferSource.h>
+#include <android/BnOMXBufferSource.h>
 #include <OMXFenceParcelable.h>
 
 namespace android {
@@ -45,6 +45,7 @@
 
 using ::android::OMXFenceParcelable;
 using ::android::IOMXBufferSource;
+using ::android::BnOMXBufferSource;
 
 /**
  * Wrapper classes for conversion
@@ -55,7 +56,7 @@
  * - TW = Treble Wrapper --- It wraps a legacy object inside a Treble object.
  */
 
-struct LWOmxBufferSource : public IOMXBufferSource {
+struct LWOmxBufferSource : public BnOMXBufferSource {
     sp<IOmxBufferSource> mBase;
     LWOmxBufferSource(sp<IOmxBufferSource> const& base);
     ::android::binder::Status onOmxExecuting() override;
@@ -64,8 +65,6 @@
     ::android::binder::Status onInputBufferAdded(int32_t bufferID) override;
     ::android::binder::Status onInputBufferEmptied(
             int32_t bufferID, OMXFenceParcelable const& fenceParcel) override;
-protected:
-    ::android::IBinder* onAsBinder() override;
 };
 
 struct TWOmxBufferSource : public IOmxBufferSource {
diff --git a/media/libstagefright/omx/hal/1.0/impl/WOmxNode.cpp b/media/libstagefright/omx/hal/1.0/impl/WOmxNode.cpp
index 6b21138..26617aa 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WOmxNode.cpp
+++ b/media/libstagefright/omx/hal/1.0/impl/WOmxNode.cpp
@@ -252,10 +252,6 @@
     return toStatusT(mBase->setQuirks(static_cast<uint32_t>(quirks)));;
 }
 
-::android::IBinder* LWOmxNode::onAsBinder() {
-    return nullptr;
-}
-
 // TWOmxNode
 TWOmxNode::TWOmxNode(sp<IOMXNode> const& base) : mBase(base) {
 }
@@ -281,7 +277,8 @@
 }
 
 Return<Status> TWOmxNode::setParameter(
-        uint32_t index, hidl_vec<uint8_t> const& params) {
+        uint32_t index, hidl_vec<uint8_t> const& inParams) {
+    hidl_vec<uint8_t> params(inParams);
     return toStatus(mBase->setParameter(
             toEnumIndexType(index),
             static_cast<void const*>(params.data()),
@@ -301,7 +298,8 @@
 }
 
 Return<Status> TWOmxNode::setConfig(
-        uint32_t index, const hidl_vec<uint8_t>& config) {
+        uint32_t index, const hidl_vec<uint8_t>& inConfig) {
+    hidl_vec<uint8_t> config(inConfig);
     return toStatus(mBase->setConfig(
             toEnumIndexType(index),
             static_cast<void const*>(config.data()),
diff --git a/media/libstagefright/omx/hal/1.0/impl/WOmxNode.h b/media/libstagefright/omx/hal/1.0/impl/WOmxNode.h
index d606f3a..12c2f04 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WOmxNode.h
+++ b/media/libstagefright/omx/hal/1.0/impl/WOmxNode.h
@@ -56,7 +56,7 @@
  * - TW = Treble Wrapper --- It wraps a legacy object inside a Treble object.
  */
 
-struct LWOmxNode : public IOMXNode {
+struct LWOmxNode : public BnOMXNode {
     sp<IOmxNode> mBase;
     LWOmxNode(sp<IOmxNode> const& base);
     status_t freeNode() override;
@@ -103,8 +103,6 @@
 
     // TODO: this is temporary, will be removed when quirks move to OMX side.
     status_t setQuirks(OMX_U32 quirks) override;
-protected:
-    ::android::IBinder* onAsBinder() override;
 };
 
 struct TWOmxNode : public IOmxNode {
diff --git a/media/libstagefright/omx/hal/1.0/impl/WOmxObserver.cpp b/media/libstagefright/omx/hal/1.0/impl/WOmxObserver.cpp
index d5549fb..ecd1db5 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WOmxObserver.cpp
+++ b/media/libstagefright/omx/hal/1.0/impl/WOmxObserver.cpp
@@ -50,10 +50,6 @@
     }
 }
 
-::android::IBinder* LWOmxObserver::onAsBinder() {
-    return nullptr;
-}
-
 // TWOmxObserver
 TWOmxObserver::TWOmxObserver(sp<IOMXObserver> const& base) : mBase(base) {
 }
diff --git a/media/libstagefright/omx/hal/1.0/impl/WOmxObserver.h b/media/libstagefright/omx/hal/1.0/impl/WOmxObserver.h
index 85593c3..cfe4281 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WOmxObserver.h
+++ b/media/libstagefright/omx/hal/1.0/impl/WOmxObserver.h
@@ -43,6 +43,7 @@
 using ::android::sp;
 
 using ::android::IOMXObserver;
+using ::android::BnOMXObserver;
 using ::android::omx_message;
 
 /**
@@ -54,12 +55,10 @@
  * - TW = Treble Wrapper --- It wraps a legacy object inside a Treble object.
  */
 
-struct LWOmxObserver : public IOMXObserver {
+struct LWOmxObserver : public BnOMXObserver {
     sp<IOmxObserver> mBase;
     LWOmxObserver(sp<IOmxObserver> const& base);
     void onMessages(std::list<omx_message> const& lMessages) override;
-protected:
-    ::android::IBinder* onAsBinder() override;
 };
 
 struct TWOmxObserver : public IOmxObserver {
diff --git a/media/libstagefright/omx/hal/1.0/impl/WOmxProducerListener.cpp b/media/libstagefright/omx/hal/1.0/impl/WOmxProducerListener.cpp
index fa6e9aa..a5eed35 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WOmxProducerListener.cpp
+++ b/media/libstagefright/omx/hal/1.0/impl/WOmxProducerListener.cpp
@@ -52,11 +52,6 @@
     return static_cast<bool>(mBase->needsReleaseNotify());
 }
 
-::android::IBinder* LWOmxProducerListener::onAsBinder() {
-    return nullptr;
-}
-
-
 }  // namespace implementation
 }  // namespace V1_0
 }  // namespace omx
diff --git a/media/libstagefright/omx/hal/1.0/impl/WOmxProducerListener.h b/media/libstagefright/omx/hal/1.0/impl/WOmxProducerListener.h
index b93a555..86656ca 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WOmxProducerListener.h
+++ b/media/libstagefright/omx/hal/1.0/impl/WOmxProducerListener.h
@@ -42,6 +42,7 @@
 using ::android::sp;
 
 using ::android::IProducerListener;
+using ::android::BnProducerListener;
 
 struct TWOmxProducerListener : public IOmxProducerListener {
     sp<IProducerListener> mBase;
@@ -50,14 +51,12 @@
     Return<bool> needsReleaseNotify() override;
 };
 
-class LWOmxProducerListener : public IProducerListener {
+class LWOmxProducerListener : public BnProducerListener {
 public:
     sp<IOmxProducerListener> mBase;
     LWOmxProducerListener(sp<IOmxProducerListener> const& base);
     void onBufferReleased() override;
     bool needsReleaseNotify() override;
-protected:
-    ::android::IBinder* onAsBinder() override;
 };
 
 }  // namespace implementation
diff --git a/media/libstagefright/omx/hal/1.0/utils/Conversion.h b/media/libstagefright/omx/hal/1.0/utils/Conversion.h
index 6f4d864..05f0c78 100644
--- a/media/libstagefright/omx/hal/1.0/utils/Conversion.h
+++ b/media/libstagefright/omx/hal/1.0/utils/Conversion.h
@@ -294,7 +294,7 @@
     if (!*nh) {
         return false;
     }
-    t->fence = inHidlHandle(*nh);
+    t->fence = *nh;
     switch (l.type) {
         case omx_message::EVENT:
             t->type = Message::Type::EVENT;
@@ -592,6 +592,16 @@
         }
         case OMXBuffer::kBufferTypeANWBuffer: {
             t->type = CodecBuffer::Type::ANW_BUFFER;
+            if (l.mGraphicBuffer == nullptr) {
+                t->attr.anwBuffer.width = 0;
+                t->attr.anwBuffer.height = 0;
+                t->attr.anwBuffer.stride = 0;
+                t->attr.anwBuffer.format = static_cast<PixelFormat>(1);
+                t->attr.anwBuffer.layerCount = 0;
+                t->attr.anwBuffer.usage = 0;
+                t->nativeHandle = hidl_handle();
+                return true;
+            }
             t->attr.anwBuffer.width = l.mGraphicBuffer->getWidth();
             t->attr.anwBuffer.height = l.mGraphicBuffer->getHeight();
             t->attr.anwBuffer.stride = l.mGraphicBuffer->getStride();
@@ -636,6 +646,10 @@
             return true;
         }
         case CodecBuffer::Type::ANW_BUFFER: {
+            if (t.nativeHandle.getNativeHandle() == nullptr) {
+                *l = OMXBuffer(sp<GraphicBuffer>(nullptr));
+                return true;
+            }
             *l = OMXBuffer(sp<GraphicBuffer>(new GraphicBuffer(
                     t.attr.anwBuffer.width,
                     t.attr.anwBuffer.height,
@@ -2082,6 +2096,7 @@
     t->transformHint = l.transformHint;
     t->numPendingBuffers = l.numPendingBuffers;
     t->nextFrameNumber = l.nextFrameNumber;
+    t->bufferReplaced = l.bufferReplaced;
     return true;
 }
 
@@ -2107,6 +2122,7 @@
     l->transformHint = t.transformHint;
     l->numPendingBuffers = t.numPendingBuffers;
     l->nextFrameNumber = t.nextFrameNumber;
+    l->bufferReplaced = t.bufferReplaced;
     return true;
 }
 
diff --git a/media/libstagefright/omx/hal/1.0/utils/WGraphicBufferSource.cpp b/media/libstagefright/omx/hal/1.0/utils/WGraphicBufferSource.cpp
index 037e9b2..a23b48a 100644
--- a/media/libstagefright/omx/hal/1.0/utils/WGraphicBufferSource.cpp
+++ b/media/libstagefright/omx/hal/1.0/utils/WGraphicBufferSource.cpp
@@ -78,10 +78,6 @@
     return toBinderStatus(mBase->signalEndOfInputStream());
 }
 
-::android::IBinder* LWGraphicBufferSource::onAsBinder() {
-    return nullptr;
-}
-
 // TWGraphicBufferSource
 TWGraphicBufferSource::TWGraphicBufferSource(
         sp<LGraphicBufferSource> const& base) : mBase(base) {
@@ -89,47 +85,51 @@
 
 Return<void> TWGraphicBufferSource::configure(
         const sp<IOmxNode>& omxNode, Dataspace dataspace) {
-    return toHardwareStatus(mBase->configure(
-            new LWOmxNode(omxNode),
-            toRawDataspace(dataspace)));
+    mBase->configure(new LWOmxNode(omxNode), toRawDataspace(dataspace));
+    return Void();
 }
 
 Return<void> TWGraphicBufferSource::setSuspend(bool suspend) {
-    return toHardwareStatus(mBase->setSuspend(suspend));
+    mBase->setSuspend(suspend);
+    return Void();
 }
 
 Return<void> TWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
         int64_t repeatAfterUs) {
-    return toHardwareStatus(mBase->setRepeatPreviousFrameDelayUs(
-            repeatAfterUs));
+    mBase->setRepeatPreviousFrameDelayUs(repeatAfterUs);
+    return Void();
 }
 
 Return<void> TWGraphicBufferSource::setMaxFps(float maxFps) {
-    return toHardwareStatus(mBase->setMaxFps(maxFps));
+    mBase->setMaxFps(maxFps);
+    return Void();
 }
 
 Return<void> TWGraphicBufferSource::setTimeLapseConfig(
         int64_t timePerFrameUs, int64_t timePerCaptureUs) {
-    return toHardwareStatus(mBase->setTimeLapseConfig(
-            timePerFrameUs, timePerCaptureUs));
+    mBase->setTimeLapseConfig(timePerFrameUs, timePerCaptureUs);
+    return Void();
 }
 
 Return<void> TWGraphicBufferSource::setStartTimeUs(int64_t startTimeUs) {
-    return toHardwareStatus(mBase->setStartTimeUs(startTimeUs));
+    mBase->setStartTimeUs(startTimeUs);
+    return Void();
 }
 
 Return<void> TWGraphicBufferSource::setColorAspects(
         const ColorAspects& aspects) {
-    return toHardwareStatus(mBase->setColorAspects(toCompactColorAspects(
-            aspects)));
+    mBase->setColorAspects(toCompactColorAspects(aspects));
+    return Void();
 }
 
 Return<void> TWGraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
-    return toHardwareStatus(mBase->setTimeOffsetUs(timeOffsetUs));
+    mBase->setTimeOffsetUs(timeOffsetUs);
+    return Void();
 }
 
 Return<void> TWGraphicBufferSource::signalEndOfInputStream() {
-    return toHardwareStatus(mBase->signalEndOfInputStream());
+    mBase->signalEndOfInputStream();
+    return Void();
 }
 
 }  // namespace utils
diff --git a/media/libstagefright/omx/hal/1.0/utils/WGraphicBufferSource.h b/media/libstagefright/omx/hal/1.0/utils/WGraphicBufferSource.h
index 17a4486..d21de42 100644
--- a/media/libstagefright/omx/hal/1.0/utils/WGraphicBufferSource.h
+++ b/media/libstagefright/omx/hal/1.0/utils/WGraphicBufferSource.h
@@ -23,7 +23,7 @@
 
 #include <frameworks/native/include/binder/Binder.h>
 #include <IOMX.h>
-#include <android/IGraphicBufferSource.h>
+#include <android/BnGraphicBufferSource.h>
 #include <android/hardware/media/omx/1.0/IOmxNode.h>
 
 #include <android/hardware/graphics/common/1.0/types.h>
@@ -60,10 +60,11 @@
  */
 
 typedef ::android::IGraphicBufferSource LGraphicBufferSource;
+typedef ::android::BnGraphicBufferSource BnGraphicBufferSource;
 typedef ::android::hardware::media::omx::V1_0::IGraphicBufferSource
         TGraphicBufferSource;
 
-struct LWGraphicBufferSource : public LGraphicBufferSource {
+struct LWGraphicBufferSource : public BnGraphicBufferSource {
     sp<TGraphicBufferSource> mBase;
     LWGraphicBufferSource(sp<TGraphicBufferSource> const& base);
     ::android::binder::Status configure(
@@ -78,8 +79,6 @@
     ::android::binder::Status setColorAspects(int32_t aspects) override;
     ::android::binder::Status setTimeOffsetUs(int64_t timeOffsetsUs) override;
     ::android::binder::Status signalEndOfInputStream() override;
-protected:
-    ::android::IBinder* onAsBinder() override;
 };
 
 struct TWGraphicBufferSource : public TGraphicBufferSource {
diff --git a/media/libstagefright/omx/hal/1.0/utils/WOmx.cpp b/media/libstagefright/omx/hal/1.0/utils/WOmx.cpp
index 07c9255..00f40cd 100644
--- a/media/libstagefright/omx/hal/1.0/utils/WOmx.cpp
+++ b/media/libstagefright/omx/hal/1.0/utils/WOmx.cpp
@@ -79,10 +79,6 @@
     return transStatus == NO_ERROR ? fnStatus : transStatus;
 }
 
-::android::IBinder* LWOmx::onAsBinder() {
-    return nullptr;
-}
-
 // TWOmx
 TWOmx::TWOmx(sp<IOMX> const& base) : mBase(base) {
 }
diff --git a/media/libstagefright/omx/hal/1.0/utils/WOmx.h b/media/libstagefright/omx/hal/1.0/utils/WOmx.h
index 26affad..73adc55 100644
--- a/media/libstagefright/omx/hal/1.0/utils/WOmx.h
+++ b/media/libstagefright/omx/hal/1.0/utils/WOmx.h
@@ -45,6 +45,7 @@
 
 using ::android::List;
 using ::android::IOMX;
+using ::android::BnOMX;
 
 /**
  * Wrapper classes for conversion
@@ -55,7 +56,7 @@
  * - TW = Treble Wrapper --- It wraps a legacy object inside a Treble object.
  */
 
-struct LWOmx : public IOMX {
+struct LWOmx : public BnOMX {
     sp<IOmx> mBase;
     LWOmx(sp<IOmx> const& base);
     status_t listNodes(List<IOMX::ComponentInfo>* list) override;
@@ -66,8 +67,6 @@
     status_t createInputSurface(
             sp<::android::IGraphicBufferProducer>* bufferProducer,
             sp<::android::IGraphicBufferSource>* bufferSource) override;
-protected:
-    ::android::IBinder* onAsBinder() override;
 };
 
 struct TWOmx : public IOmx {
diff --git a/media/libstagefright/omx/hal/1.0/utils/WOmxBufferProducer.cpp b/media/libstagefright/omx/hal/1.0/utils/WOmxBufferProducer.cpp
index 49f2706..cfb0cce 100644
--- a/media/libstagefright/omx/hal/1.0/utils/WOmxBufferProducer.cpp
+++ b/media/libstagefright/omx/hal/1.0/utils/WOmxBufferProducer.cpp
@@ -203,7 +203,8 @@
 Return<void> TWOmxBufferProducer::connect(
         const sp<IOmxProducerListener>& listener,
         int32_t api, bool producerControlledByApp, connect_cb _hidl_cb) {
-    sp<IProducerListener> lListener = new LWOmxProducerListener(listener);
+    sp<IProducerListener> lListener = listener == nullptr ?
+            nullptr : new LWOmxProducerListener(listener);
     IGraphicBufferProducer::QueueBufferOutput lOutput;
     status_t status = mBase->connect(lListener,
             static_cast<int>(api),
@@ -479,7 +480,8 @@
 status_t LWOmxBufferProducer::connect(
         const sp<IProducerListener>& listener, int api,
         bool producerControlledByApp, QueueBufferOutput* output) {
-    sp<IOmxProducerListener> tListener = new TWOmxProducerListener(listener);
+    sp<IOmxProducerListener> tListener = listener == nullptr ?
+            nullptr : new TWOmxProducerListener(listener);
     status_t fnStatus;
     status_t transStatus = toStatusT(mBase->connect(
             tListener, static_cast<int32_t>(api), producerControlledByApp,
@@ -582,10 +584,6 @@
     return transStatus == NO_ERROR ? fnStatus : transStatus;
 }
 
-::android::IBinder* LWOmxBufferProducer::onAsBinder() {
-    return nullptr;
-}
-
 }  // namespace utils
 }  // namespace V1_0
 }  // namespace omx
diff --git a/media/libstagefright/omx/hal/1.0/utils/WOmxBufferProducer.h b/media/libstagefright/omx/hal/1.0/utils/WOmxBufferProducer.h
index 46abd27..a5d2961 100644
--- a/media/libstagefright/omx/hal/1.0/utils/WOmxBufferProducer.h
+++ b/media/libstagefright/omx/hal/1.0/utils/WOmxBufferProducer.h
@@ -47,6 +47,7 @@
 using ::android::sp;
 
 using ::android::IGraphicBufferProducer;
+using ::android::BnGraphicBufferProducer;
 using ::android::IProducerListener;
 
 struct TWOmxBufferProducer : public IOmxBufferProducer {
@@ -91,7 +92,7 @@
     Return<void> getUniqueId(getUniqueId_cb _hidl_cb) override;
 };
 
-struct LWOmxBufferProducer : public IGraphicBufferProducer {
+struct LWOmxBufferProducer : public BnGraphicBufferProducer {
     sp<IOmxBufferProducer> mBase;
     LWOmxBufferProducer(sp<IOmxBufferProducer> const& base);
 
@@ -128,8 +129,6 @@
           sp<Fence>* outFence, float outTransformMatrix[16]) override;
     void getFrameTimestamps(FrameEventHistoryDelta* outDelta) override;
     status_t getUniqueId(uint64_t* outId) const override;
-protected:
-    ::android::IBinder* onAsBinder() override;
 };
 
 }  // namespace utils
diff --git a/media/libstagefright/omx/hal/1.0/utils/WOmxBufferSource.cpp b/media/libstagefright/omx/hal/1.0/utils/WOmxBufferSource.cpp
index 1ebd9a7..f3f5b9d 100644
--- a/media/libstagefright/omx/hal/1.0/utils/WOmxBufferSource.cpp
+++ b/media/libstagefright/omx/hal/1.0/utils/WOmxBufferSource.cpp
@@ -61,38 +61,34 @@
     ::android::binder::Status status = toBinderStatus(
             mBase->onInputBufferEmptied(
             static_cast<uint32_t>(bufferId), fence));
-    if (native_handle_delete(fenceNh) != 0) {
-        return ::android::binder::Status::fromExceptionCode(
-                ::android::binder::Status::EX_NULL_POINTER,
-                "Cannot delete native handle");
-    }
+    native_handle_close(fenceNh);
+    native_handle_delete(fenceNh);
     return status;
 }
 
-::android::IBinder* LWOmxBufferSource::onAsBinder() {
-    return nullptr;
-}
-
 // TWOmxBufferSource
 TWOmxBufferSource::TWOmxBufferSource(sp<IOMXBufferSource> const& base) :
     mBase(base) {
 }
 
 Return<void> TWOmxBufferSource::onOmxExecuting() {
-    return toHardwareStatus(mBase->onOmxExecuting());
+    mBase->onOmxExecuting();
+    return Void();
 }
 
 Return<void> TWOmxBufferSource::onOmxIdle() {
-    return toHardwareStatus(mBase->onOmxIdle());
+    mBase->onOmxIdle();
+    return Void();
 }
 
 Return<void> TWOmxBufferSource::onOmxLoaded() {
-    return toHardwareStatus(mBase->onOmxLoaded());
+    mBase->onOmxLoaded();
+    return Void();
 }
 
 Return<void> TWOmxBufferSource::onInputBufferAdded(uint32_t buffer) {
-    return toHardwareStatus(mBase->onInputBufferAdded(
-            static_cast<int32_t>(buffer)));
+    mBase->onInputBufferAdded(int32_t(buffer));
+    return Void();
 }
 
 Return<void> TWOmxBufferSource::onInputBufferEmptied(
@@ -102,8 +98,8 @@
       return ::android::hardware::Status::fromExceptionCode(
               ::android::hardware::Status::EX_BAD_PARCELABLE);
     }
-    return toHardwareStatus(mBase->onInputBufferEmptied(
-            static_cast<int32_t>(buffer), fenceParcelable));
+    mBase->onInputBufferEmptied(int32_t(buffer), fenceParcelable);
+    return Void();
 }
 
 }  // namespace utils
diff --git a/media/libstagefright/omx/hal/1.0/utils/WOmxBufferSource.h b/media/libstagefright/omx/hal/1.0/utils/WOmxBufferSource.h
index 3bf35c5..1214300 100644
--- a/media/libstagefright/omx/hal/1.0/utils/WOmxBufferSource.h
+++ b/media/libstagefright/omx/hal/1.0/utils/WOmxBufferSource.h
@@ -22,7 +22,7 @@
 #include <hidl/Status.h>
 
 #include <frameworks/native/include/binder/Binder.h>
-#include <android/IOMXBufferSource.h>
+#include <android/BnOMXBufferSource.h>
 #include <OMXFenceParcelable.h>
 
 namespace android {
@@ -45,6 +45,7 @@
 
 using ::android::OMXFenceParcelable;
 using ::android::IOMXBufferSource;
+using ::android::BnOMXBufferSource;
 
 /**
  * Wrapper classes for conversion
@@ -55,7 +56,7 @@
  * - TW = Treble Wrapper --- It wraps a legacy object inside a Treble object.
  */
 
-struct LWOmxBufferSource : public IOMXBufferSource {
+struct LWOmxBufferSource : public BnOMXBufferSource {
     sp<IOmxBufferSource> mBase;
     LWOmxBufferSource(sp<IOmxBufferSource> const& base);
     ::android::binder::Status onOmxExecuting() override;
@@ -64,8 +65,6 @@
     ::android::binder::Status onInputBufferAdded(int32_t bufferID) override;
     ::android::binder::Status onInputBufferEmptied(
             int32_t bufferID, OMXFenceParcelable const& fenceParcel) override;
-protected:
-    ::android::IBinder* onAsBinder() override;
 };
 
 struct TWOmxBufferSource : public IOmxBufferSource {
diff --git a/media/libstagefright/omx/hal/1.0/utils/WOmxNode.cpp b/media/libstagefright/omx/hal/1.0/utils/WOmxNode.cpp
index 6764ba8..3bb7a99 100644
--- a/media/libstagefright/omx/hal/1.0/utils/WOmxNode.cpp
+++ b/media/libstagefright/omx/hal/1.0/utils/WOmxNode.cpp
@@ -252,10 +252,6 @@
     return toStatusT(mBase->setQuirks(static_cast<uint32_t>(quirks)));;
 }
 
-::android::IBinder* LWOmxNode::onAsBinder() {
-    return nullptr;
-}
-
 // TWOmxNode
 TWOmxNode::TWOmxNode(sp<IOMXNode> const& base) : mBase(base) {
 }
@@ -281,7 +277,8 @@
 }
 
 Return<Status> TWOmxNode::setParameter(
-        uint32_t index, hidl_vec<uint8_t> const& params) {
+        uint32_t index, hidl_vec<uint8_t> const& inParams) {
+    hidl_vec<uint8_t> params(inParams);
     return toStatus(mBase->setParameter(
             toEnumIndexType(index),
             static_cast<void const*>(params.data()),
@@ -301,7 +298,8 @@
 }
 
 Return<Status> TWOmxNode::setConfig(
-        uint32_t index, const hidl_vec<uint8_t>& config) {
+        uint32_t index, const hidl_vec<uint8_t>& inConfig) {
+    hidl_vec<uint8_t> config(inConfig);
     return toStatus(mBase->setConfig(
             toEnumIndexType(index),
             static_cast<void const*>(config.data()),
diff --git a/media/libstagefright/omx/hal/1.0/utils/WOmxNode.h b/media/libstagefright/omx/hal/1.0/utils/WOmxNode.h
index cb0b1a7..9c4bb4a 100644
--- a/media/libstagefright/omx/hal/1.0/utils/WOmxNode.h
+++ b/media/libstagefright/omx/hal/1.0/utils/WOmxNode.h
@@ -56,7 +56,7 @@
  * - TW = Treble Wrapper --- It wraps a legacy object inside a Treble object.
  */
 
-struct LWOmxNode : public IOMXNode {
+struct LWOmxNode : public BnOMXNode {
     sp<IOmxNode> mBase;
     LWOmxNode(sp<IOmxNode> const& base);
     status_t freeNode() override;
@@ -103,8 +103,6 @@
 
     // TODO: this is temporary, will be removed when quirks move to OMX side.
     status_t setQuirks(OMX_U32 quirks) override;
-protected:
-    ::android::IBinder* onAsBinder() override;
 };
 
 struct TWOmxNode : public IOmxNode {
diff --git a/media/libstagefright/omx/hal/1.0/utils/WOmxObserver.cpp b/media/libstagefright/omx/hal/1.0/utils/WOmxObserver.cpp
index fea5a9a..db971f8 100644
--- a/media/libstagefright/omx/hal/1.0/utils/WOmxObserver.cpp
+++ b/media/libstagefright/omx/hal/1.0/utils/WOmxObserver.cpp
@@ -50,10 +50,6 @@
     }
 }
 
-::android::IBinder* LWOmxObserver::onAsBinder() {
-    return nullptr;
-}
-
 // TWOmxObserver
 TWOmxObserver::TWOmxObserver(sp<IOMXObserver> const& base) : mBase(base) {
 }
diff --git a/media/libstagefright/omx/hal/1.0/utils/WOmxObserver.h b/media/libstagefright/omx/hal/1.0/utils/WOmxObserver.h
index b1e2eb1..b9eb412 100644
--- a/media/libstagefright/omx/hal/1.0/utils/WOmxObserver.h
+++ b/media/libstagefright/omx/hal/1.0/utils/WOmxObserver.h
@@ -43,6 +43,7 @@
 using ::android::sp;
 
 using ::android::IOMXObserver;
+using ::android::BnOMXObserver;
 using ::android::omx_message;
 
 /**
@@ -54,12 +55,10 @@
  * - TW = Treble Wrapper --- It wraps a legacy object inside a Treble object.
  */
 
-struct LWOmxObserver : public IOMXObserver {
+struct LWOmxObserver : public BnOMXObserver {
     sp<IOmxObserver> mBase;
     LWOmxObserver(sp<IOmxObserver> const& base);
     void onMessages(std::list<omx_message> const& lMessages) override;
-protected:
-    ::android::IBinder* onAsBinder() override;
 };
 
 struct TWOmxObserver : public IOmxObserver {
diff --git a/media/libstagefright/omx/hal/1.0/utils/WOmxProducerListener.cpp b/media/libstagefright/omx/hal/1.0/utils/WOmxProducerListener.cpp
index d43215d..80b0f71 100644
--- a/media/libstagefright/omx/hal/1.0/utils/WOmxProducerListener.cpp
+++ b/media/libstagefright/omx/hal/1.0/utils/WOmxProducerListener.cpp
@@ -52,11 +52,6 @@
     return static_cast<bool>(mBase->needsReleaseNotify());
 }
 
-::android::IBinder* LWOmxProducerListener::onAsBinder() {
-    return nullptr;
-}
-
-
 }  // namespace utils
 }  // namespace V1_0
 }  // namespace omx
diff --git a/media/libstagefright/omx/hal/1.0/utils/WOmxProducerListener.h b/media/libstagefright/omx/hal/1.0/utils/WOmxProducerListener.h
index 5b5e830..2be077b 100644
--- a/media/libstagefright/omx/hal/1.0/utils/WOmxProducerListener.h
+++ b/media/libstagefright/omx/hal/1.0/utils/WOmxProducerListener.h
@@ -42,6 +42,7 @@
 using ::android::sp;
 
 using ::android::IProducerListener;
+using ::android::BnProducerListener;
 
 struct TWOmxProducerListener : public IOmxProducerListener {
     sp<IProducerListener> mBase;
@@ -50,14 +51,12 @@
     Return<bool> needsReleaseNotify() override;
 };
 
-class LWOmxProducerListener : public IProducerListener {
+class LWOmxProducerListener : public BnProducerListener {
 public:
     sp<IOmxProducerListener> mBase;
     LWOmxProducerListener(sp<IOmxProducerListener> const& base);
     void onBufferReleased() override;
     bool needsReleaseNotify() override;
-protected:
-    ::android::IBinder* onAsBinder() override;
 };
 
 }  // namespace utils
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index 6df2065..1583218 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -62,8 +62,13 @@
 constexpr int USB_FFS_MAX_WRITE = MTP_BUFFER_SIZE;
 constexpr int USB_FFS_MAX_READ = MTP_BUFFER_SIZE;
 
+static_assert(USB_FFS_MAX_WRITE > 0, "Max r/w values must be > 0!");
+static_assert(USB_FFS_MAX_READ > 0, "Max r/w values must be > 0!");
+
 constexpr unsigned int MAX_MTP_FILE_SIZE = 0xFFFFFFFF;
 
+constexpr size_t ENDPOINT_ALLOC_RETRIES = 10;
+
 struct func_desc {
     struct usb_interface_descriptor intf;
     struct usb_endpoint_descriptor_no_audio sink;
@@ -459,19 +464,28 @@
     mMaxWrite = android::base::GetIntProperty("sys.usb.ffs.max_write", USB_FFS_MAX_WRITE);
     mMaxRead = android::base::GetIntProperty("sys.usb.ffs.max_read", USB_FFS_MAX_READ);
 
-    while (mMaxWrite > USB_FFS_MAX_WRITE && mMaxRead > USB_FFS_MAX_READ) {
+    size_t attempts = 0;
+    while (mMaxWrite >= USB_FFS_MAX_WRITE && mMaxRead >= USB_FFS_MAX_READ &&
+            attempts < ENDPOINT_ALLOC_RETRIES) {
         // If larger contiguous chunks of memory aren't available, attempt to try
         // smaller allocations.
         if (ioctl(mBulkIn, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(mMaxWrite)) ||
             ioctl(mBulkOut, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(mMaxRead))) {
+            if (errno == ENODEV) {
+                // Driver hasn't enabled endpoints yet.
+                std::this_thread::sleep_for(std::chrono::milliseconds(100));
+                attempts += 1;
+                continue;
+            }
             mMaxWrite /= 2;
             mMaxRead /=2;
         } else {
             return 0;
         }
     }
+    // Try to start MtpServer anyway, with the smallest max r/w values
     PLOG(ERROR) << "Functionfs could not allocate any memory!";
-    return -1;
+    return 0;
 }
 
 int MtpFfsHandle::configure(bool usePtp) {
@@ -583,7 +597,7 @@
     uint64_t file_length = mfr.length;
     uint32_t given_length = std::min(static_cast<uint64_t>(MAX_MTP_FILE_SIZE),
             file_length + sizeof(mtp_data_header));
-    uint64_t offset = 0;
+    uint64_t offset = mfr.offset;
     struct usb_endpoint_descriptor mBulkIn_desc;
     int packet_size;
 
@@ -594,7 +608,10 @@
         packet_size = mBulkIn_desc.wMaxPacketSize;
     }
 
-    int init_read_len = packet_size - sizeof(mtp_data_header);
+    // If file_length is larger than a size_t, truncating would produce the wrong comparison.
+    // Instead, promote the left side to 64 bits, then truncate the small result.
+    int init_read_len = std::min(
+            static_cast<uint64_t>(packet_size - sizeof(mtp_data_header)), file_length);
 
     char *data = mBuffer1.data();
     char *data2 = mBuffer2.data();
@@ -620,10 +637,10 @@
     if (TEMP_FAILURE_RETRY(pread(mfr.fd, reinterpret_cast<char*>(data) +
                     sizeof(mtp_data_header), init_read_len, offset))
             != init_read_len) return -1;
+    if (writeHandle(mBulkIn, data, sizeof(mtp_data_header) + init_read_len) == -1) return -1;
+    if (file_length == static_cast<unsigned>(init_read_len)) return 0;
     file_length -= init_read_len;
     offset += init_read_len;
-    if (writeHandle(mBulkIn, data, packet_size) == -1) return -1;
-    if (file_length == 0) return 0;
 
     // Break down the file into pieces that fit in buffers
     while(file_length > 0) {
diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h
index 44ff0f3..b4d5a97 100644
--- a/media/mtp/MtpFfsHandle.h
+++ b/media/mtp/MtpFfsHandle.h
@@ -59,6 +59,10 @@
     int sendFile(mtp_file_range mfr);
     int sendEvent(mtp_event me);
 
+    /**
+     * Open ffs endpoints and allocate necessary kernel and user memory.
+     * Will sleep until endpoints are enabled, for up to 1 second.
+     */
     int start();
     void close();
 
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 17f6b5a..0547a69 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -651,22 +651,6 @@
     return String8(formattedTime);
 }
 
-int CameraService::getCameraPriorityFromProcState(int procState) {
-    // Find the priority for the camera usage based on the process state.  Higher priority clients
-    // win for evictions.
-    if (procState < 0) {
-        ALOGE("%s: Received invalid process state %d from ActivityManagerService!", __FUNCTION__,
-                procState);
-        return -1;
-    }
-    // Treat sleeping TOP processes the same as regular TOP processes, for
-    // access priority.  This is important for lock-screen camera launch scenarios
-    if (procState == PROCESS_STATE_TOP_SLEEPING) {
-        procState = PROCESS_STATE_TOP;
-    }
-    return INT_MAX - procState;
-}
-
 Status CameraService::getCameraVendorTagDescriptor(
         /*out*/
         hardware::camera2::params::VendorTagDescriptor* desc) {
@@ -1212,20 +1196,24 @@
         std::vector<int> ownerPids(mActiveClientManager.getAllOwners());
         ownerPids.push_back(clientPid);
 
-        // Use the value +PROCESS_STATE_NONEXISTENT, to avoid taking
-        // address of PROCESS_STATE_NONEXISTENT as a reference argument
-        // for the vector constructor. PROCESS_STATE_NONEXISTENT does
-        // not have an out-of-class definition.
-        std::vector<int> priorities(ownerPids.size(), +PROCESS_STATE_NONEXISTENT);
+        std::vector<int> priorityScores(ownerPids.size());
+        std::vector<int> states(ownerPids.size());
 
-        // Get priorites of all active PIDs
-        ProcessInfoService::getProcessStatesFromPids(ownerPids.size(), &ownerPids[0],
-                /*out*/&priorities[0]);
+        // Get priority scores of all active PIDs
+        status_t err = ProcessInfoService::getProcessStatesScoresFromPids(
+                ownerPids.size(), &ownerPids[0], /*out*/&states[0],
+                /*out*/&priorityScores[0]);
+        if (err != OK) {
+            ALOGE("%s: Priority score query failed: %d",
+                  __FUNCTION__, err);
+            return err;
+        }
 
         // Update all active clients' priorities
-        std::map<int,int> pidToPriorityMap;
+        std::map<int,resource_policy::ClientPriority> pidToPriorityMap;
         for (size_t i = 0; i < ownerPids.size() - 1; i++) {
-            pidToPriorityMap.emplace(ownerPids[i], getCameraPriorityFromProcState(priorities[i]));
+            pidToPriorityMap.emplace(ownerPids[i],
+                    resource_policy::ClientPriority(priorityScores[i], states[i]));
         }
         mActiveClientManager.updatePriorities(pidToPriorityMap);
 
@@ -1242,7 +1230,9 @@
         clientDescriptor = CameraClientManager::makeClientDescriptor(cameraId,
                 sp<BasicClient>{nullptr}, static_cast<int32_t>(state->getCost()),
                 state->getConflicting(),
-                getCameraPriorityFromProcState(priorities[priorities.size() - 1]), clientPid);
+                priorityScores[priorityScores.size() - 1],
+                clientPid,
+                states[states.size() - 1]);
 
         // Find clients that would be evicted
         auto evicted = mActiveClientManager.wouldEvict(clientDescriptor);
@@ -1259,19 +1249,22 @@
                     mActiveClientManager.getIncompatibleClients(clientDescriptor);
 
             String8 msg = String8::format("%s : DENIED connect device %s client for package %s "
-                    "(PID %d, priority %d) due to eviction policy", curTime.string(),
+                    "(PID %d, score %d state %d) due to eviction policy", curTime.string(),
                     cameraId.string(), packageName.string(), clientPid,
-                    getCameraPriorityFromProcState(priorities[priorities.size() - 1]));
+                    priorityScores[priorityScores.size() - 1],
+                    states[states.size() - 1]);
 
             for (auto& i : incompatibleClients) {
                 msg.appendFormat("\n   - Blocked by existing device %s client for package %s"
-                        "(PID %" PRId32 ", priority %" PRId32 ")", i->getKey().string(),
-                        String8{i->getValue()->getPackageName()}.string(), i->getOwnerId(),
-                        i->getPriority());
+                        "(PID %" PRId32 ", score %" PRId32 ", state %" PRId32 ")",
+                        i->getKey().string(),
+                        String8{i->getValue()->getPackageName()}.string(),
+                        i->getOwnerId(), i->getPriority().getScore(),
+                        i->getPriority().getState());
                 ALOGE("   Conflicts with: Device %s, client package %s (PID %"
-                        PRId32 ", priority %" PRId32 ")", i->getKey().string(),
+                        PRId32 ", score %" PRId32 ", state %" PRId32 ")", i->getKey().string(),
                         String8{i->getValue()->getPackageName()}.string(), i->getOwnerId(),
-                        i->getPriority());
+                        i->getPriority().getScore(), i->getPriority().getState());
             }
 
             // Log the client's attempt
@@ -1299,12 +1292,14 @@
 
             // Log the clients evicted
             logEvent(String8::format("EVICT device %s client held by package %s (PID"
-                    " %" PRId32 ", priority %" PRId32 ")\n   - Evicted by device %s client for"
-                    " package %s (PID %d, priority %" PRId32 ")",
+                    " %" PRId32 ", score %" PRId32 ", state %" PRId32 ")\n - Evicted by device %s client for"
+                    " package %s (PID %d, score %" PRId32 ", state %" PRId32 ")",
                     i->getKey().string(), String8{clientSp->getPackageName()}.string(),
-                    i->getOwnerId(), i->getPriority(), cameraId.string(),
+                    i->getOwnerId(), i->getPriority().getScore(),
+                    i->getPriority().getState(), cameraId.string(),
                     packageName.string(), clientPid,
-                    getCameraPriorityFromProcState(priorities[priorities.size() - 1])));
+                    priorityScores[priorityScores.size() - 1],
+                    states[states.size() - 1]));
 
             // Notify the client of disconnection
             clientSp->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISCONNECTED,
@@ -2135,9 +2130,11 @@
 
         // Log the clients evicted
         logEvent(String8::format("EVICT device %s client held by package %s (PID %"
-                PRId32 ", priority %" PRId32 ")\n   - Evicted due to user switch.",
-                i->getKey().string(), String8{clientSp->getPackageName()}.string(),
-                i->getOwnerId(), i->getPriority()));
+                PRId32 ", score %" PRId32 ", state %" PRId32 ")\n   - Evicted due"
+                " to user switch.", i->getKey().string(),
+                String8{clientSp->getPackageName()}.string(),
+                i->getOwnerId(), i->getPriority().getScore(),
+                i->getPriority().getState()));
 
     }
 
@@ -2673,7 +2670,8 @@
         String8 key = i->getKey();
         int32_t cost = i->getCost();
         int32_t pid = i->getOwnerId();
-        int32_t priority = i->getPriority();
+        int32_t score = i->getPriority().getScore();
+        int32_t state = i->getPriority().getState();
         auto conflicting = i->getConflicting();
         auto clientSp = i->getValue();
         String8 packageName;
@@ -2683,8 +2681,8 @@
             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);
+        ret.appendFormat("\n(Camera ID: %s, Cost: %" PRId32 ", PID: %" PRId32 ", Score: %"
+                PRId32 ", State: %" PRId32, key.string(), cost, pid, score, state);
 
         if (clientSp.get() != nullptr) {
             ret.appendFormat("User Id: %d, ", clientUserId);
@@ -2706,16 +2704,18 @@
 
 CameraService::DescriptorPtr CameraService::CameraClientManager::makeClientDescriptor(
         const String8& key, const sp<BasicClient>& value, int32_t cost,
-        const std::set<String8>& conflictingKeys, int32_t priority, int32_t ownerId) {
+        const std::set<String8>& conflictingKeys, int32_t score, int32_t ownerId,
+        int32_t state) {
 
     return std::make_shared<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>(
-            key, value, cost, conflictingKeys, priority, ownerId);
+            key, value, cost, conflictingKeys, score, ownerId, state);
 }
 
 CameraService::DescriptorPtr CameraService::CameraClientManager::makeClientDescriptor(
         const sp<BasicClient>& value, const CameraService::DescriptorPtr& partial) {
     return makeClientDescriptor(partial->getKey(), value, partial->getCost(),
-            partial->getConflicting(), partial->getPriority(), partial->getOwnerId());
+            partial->getConflicting(), partial->getPriority().getScore(),
+            partial->getOwnerId(), partial->getPriority().getState());
 }
 
 // ----------------------------------------------------------------------------
@@ -2786,21 +2786,23 @@
         }
 
         auto clientDescriptor = mActiveClientManager.get(cameraId);
-        if (clientDescriptor == nullptr) {
+        if (clientDescriptor != nullptr) {
+            dprintf(fd, "  Device %s is open. Client instance dump:\n",
+                    cameraId.string());
+            dprintf(fd, "    Client priority score: %d state: %d\n",
+                    clientDescriptor->getPriority().getScore(),
+                    clientDescriptor->getPriority().getState());
+            dprintf(fd, "    Client PID: %d\n", clientDescriptor->getOwnerId());
+
+            auto client = clientDescriptor->getValue();
+            dprintf(fd, "    Client package: %s\n",
+                    String8(client->getPackageName()).string());
+
+            client->dumpClient(fd, args);
+        } else {
             dprintf(fd, "  Device %s is closed, no client instance\n",
                     cameraId.string());
-            continue;
         }
-        dprintf(fd, "  Device %s is open. Client instance dump:\n",
-                cameraId.string());
-        dprintf(fd, "    Client priority level: %d\n", clientDescriptor->getPriority());
-        dprintf(fd, "    Client PID: %d\n", clientDescriptor->getOwnerId());
-
-        auto client = clientDescriptor->getValue();
-        dprintf(fd, "    Client package: %s\n",
-                String8(client->getPackageName()).string());
-
-        client->dumpClient(fd, args);
 
         if (mModule != nullptr) {
             dprintf(fd, "== Camera HAL device %s static information: ==\n", cameraId.string());
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index d463b59..c7acdc9 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -75,11 +75,6 @@
         API_2 = 2
     };
 
-    // Process state (mirrors frameworks/base/core/java/android/app/ActivityManager.java)
-    static const int PROCESS_STATE_NONEXISTENT = -1;
-    static const int PROCESS_STATE_TOP = 2;
-    static const int PROCESS_STATE_TOP_SLEEPING = 5;
-
     // 3 second busy timeout when other clients are connecting
     static const nsecs_t DEFAULT_CONNECT_TIMEOUT_NS = 3000000000;
 
@@ -402,8 +397,8 @@
          * Make a ClientDescriptor object wrapping the given BasicClient strong pointer.
          */
         static DescriptorPtr makeClientDescriptor(const String8& key, const sp<BasicClient>& value,
-                int32_t cost, const std::set<String8>& conflictingKeys, int32_t priority,
-                int32_t ownerId);
+                int32_t cost, const std::set<String8>& conflictingKeys, int32_t score,
+                int32_t ownerId, int32_t state);
 
         /**
          * Make a ClientDescriptor object wrapping the given BasicClient strong pointer with
@@ -775,11 +770,6 @@
      */
     static String8 getFormattedCurrentTime();
 
-    /**
-     * Get the camera eviction priority from the current process state given by ActivityManager.
-     */
-    static int getCameraPriorityFromProcState(int procState);
-
     static binder::Status makeClient(const sp<CameraService>& cameraService,
             const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
             int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
diff --git a/services/camera/libcameraservice/device3/Camera3BufferManager.cpp b/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
index 5a5d7b7..d45891f 100644
--- a/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
+++ b/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
@@ -19,6 +19,7 @@
 #define ATRACE_TAG ATRACE_TAG_CAMERA
 
 #include <gui/ISurfaceComposer.h>
+#include <gui/IGraphicBufferAlloc.h>
 #include <private/gui/ComposerService.h>
 #include <utils/Log.h>
 #include <utils/Trace.h>
diff --git a/services/camera/libcameraservice/device3/Camera3BufferManager.h b/services/camera/libcameraservice/device3/Camera3BufferManager.h
index b5b86a3..f44c4a3 100644
--- a/services/camera/libcameraservice/device3/Camera3BufferManager.h
+++ b/services/camera/libcameraservice/device3/Camera3BufferManager.h
@@ -26,6 +26,8 @@
 
 namespace android {
 
+class IGraphicBufferAlloc;
+
 namespace camera3 {
 
 struct StreamInfo;
diff --git a/services/camera/libcameraservice/utils/ClientManager.h b/services/camera/libcameraservice/utils/ClientManager.h
index 830c50b..d7135f1 100644
--- a/services/camera/libcameraservice/utils/ClientManager.h
+++ b/services/camera/libcameraservice/utils/ClientManager.h
@@ -31,6 +31,43 @@
 namespace android {
 namespace resource_policy {
 
+class ClientPriority {
+public:
+    ClientPriority(int32_t score, int32_t state) :
+        mScore(score), mState(state) {}
+
+    int32_t getScore() const { return mScore; }
+    int32_t getState() const { return mState; }
+
+    bool operator==(const ClientPriority& rhs) const {
+        return (this->mScore == rhs.mScore) && (this->mState == rhs.mState);
+    }
+
+    bool operator< (const ClientPriority& rhs)  const {
+        if (this->mScore == rhs.mScore) {
+            return this->mState < rhs.mState;
+        } else {
+            return this->mScore < rhs.mScore;
+        }
+    }
+
+    bool operator> (const ClientPriority& rhs) const {
+        return rhs < *this;
+    }
+
+    bool operator<=(const ClientPriority& rhs) const {
+        return !(*this > rhs);
+    }
+
+    bool operator>=(const ClientPriority& rhs) const {
+        return !(*this < rhs);
+    }
+
+private:
+        int32_t mScore;
+        int32_t mState;
+};
+
 // --------------------------------------------------------------------------------
 
 /**
@@ -45,9 +82,9 @@
 class ClientDescriptor final {
 public:
     ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
-            const std::set<KEY>& conflictingKeys, int32_t priority, int32_t ownerId);
+            const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state);
     ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost, std::set<KEY>&& conflictingKeys,
-            int32_t priority, int32_t ownerId);
+            int32_t score, int32_t ownerId, int32_t state);
 
     ~ClientDescriptor();
 
@@ -69,7 +106,7 @@
     /**
      * Return the priority for this descriptor.
      */
-    int32_t getPriority() const;
+    const ClientPriority &getPriority() const;
 
     /**
      * Return the owner ID for this descriptor.
@@ -89,7 +126,7 @@
     /**
      * Set the proirity for this descriptor.
      */
-    void setPriority(int32_t priority);
+    void setPriority(const ClientPriority& priority);
 
     // This class is ordered by key
     template<class K, class V>
@@ -100,7 +137,7 @@
     VALUE mValue;
     int32_t mCost;
     std::set<KEY> mConflicting;
-    int32_t mPriority;
+    ClientPriority mPriority;
     int32_t mOwnerId;
 }; // class ClientDescriptor
 
@@ -111,16 +148,17 @@
 
 template<class KEY, class VALUE>
 ClientDescriptor<KEY, VALUE>::ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
-        const std::set<KEY>& conflictingKeys, int32_t priority, int32_t ownerId) : mKey{key},
-        mValue{value}, mCost{cost}, mConflicting{conflictingKeys}, mPriority{priority},
+        const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state) :
+        mKey{key}, mValue{value}, mCost{cost}, mConflicting{conflictingKeys},
+        mPriority(score, state),
         mOwnerId{ownerId} {}
 
 template<class KEY, class VALUE>
 ClientDescriptor<KEY, VALUE>::ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost,
-        std::set<KEY>&& conflictingKeys, int32_t priority, int32_t ownerId) :
+        std::set<KEY>&& conflictingKeys, int32_t score, int32_t ownerId, int32_t state) :
         mKey{std::forward<KEY>(key)}, mValue{std::forward<VALUE>(value)}, mCost{cost},
-        mConflicting{std::forward<std::set<KEY>>(conflictingKeys)}, mPriority{priority},
-        mOwnerId{ownerId} {}
+        mConflicting{std::forward<std::set<KEY>>(conflictingKeys)},
+        mPriority(score, state), mOwnerId{ownerId} {}
 
 template<class KEY, class VALUE>
 ClientDescriptor<KEY, VALUE>::~ClientDescriptor() {}
@@ -141,7 +179,7 @@
 }
 
 template<class KEY, class VALUE>
-int32_t ClientDescriptor<KEY, VALUE>::getPriority() const {
+const ClientPriority& ClientDescriptor<KEY, VALUE>::getPriority() const {
     return mPriority;
 }
 
@@ -165,7 +203,7 @@
 }
 
 template<class KEY, class VALUE>
-void ClientDescriptor<KEY, VALUE>::setPriority(int32_t priority) {
+void ClientDescriptor<KEY, VALUE>::setPriority(const ClientPriority& priority) {
     mPriority = priority;
 }
 
@@ -231,7 +269,7 @@
      * Given a map containing owner (pid) -> priority mappings, update the priority of each
      * ClientDescriptor with an owner in this mapping.
      */
-    void updatePriorities(const std::map<int32_t,int32_t>& ownerPriorityList);
+    void updatePriorities(const std::map<int32_t,ClientPriority>& ownerPriorityList);
 
     /**
      * Remove all ClientDescriptors.
@@ -383,17 +421,17 @@
 
     const KEY& key = client->getKey();
     int32_t cost = client->getCost();
-    int32_t priority = client->getPriority();
+    ClientPriority priority = client->getPriority();
     int32_t owner = client->getOwnerId();
 
     int64_t totalCost = getCurrentCostLocked() + cost;
 
     // Determine the MRU of the owners tied for having the highest priority
     int32_t highestPriorityOwner = owner;
-    int32_t highestPriority = priority;
+    ClientPriority highestPriority = priority;
     for (const auto& i : mClients) {
-        int32_t curPriority = i->getPriority();
-        if (curPriority >= highestPriority) {
+        ClientPriority curPriority = i->getPriority();
+        if (curPriority <= highestPriority) {
             highestPriority = curPriority;
             highestPriorityOwner = i->getOwnerId();
         }
@@ -408,7 +446,7 @@
     for (const auto& i : mClients) {
         const KEY& curKey = i->getKey();
         int32_t curCost = i->getCost();
-        int32_t curPriority = i->getPriority();
+        ClientPriority curPriority = i->getPriority();
         int32_t curOwner = i->getOwnerId();
 
         bool conflicting = (curKey == key || i->isConflicting(key) ||
@@ -417,13 +455,13 @@
         if (!returnIncompatibleClients) {
             // Find evicted clients
 
-            if (conflicting && curPriority > priority) {
+            if (conflicting && curPriority < priority) {
                 // Pre-existing conflicting client with higher priority exists
                 evictList.clear();
                 evictList.push_back(client);
                 return evictList;
             } else if (conflicting || ((totalCost > mMaxCost && curCost > 0) &&
-                    (curPriority <= priority) &&
+                    (curPriority >= priority) &&
                     !(highestPriorityOwner == owner && owner == curOwner))) {
                 // Add a pre-existing client to the eviction list if:
                 // - We are adding a client with higher priority that conflicts with this one.
@@ -437,7 +475,7 @@
         } else {
             // Find clients preventing the incoming client from being added
 
-            if (curPriority > priority && (conflicting || (totalCost > mMaxCost && curCost > 0))) {
+            if (curPriority < priority && (conflicting || (totalCost > mMaxCost && curCost > 0))) {
                 // Pre-existing conflicting client with higher priority exists
                 evictList.push_back(i);
             }
@@ -524,7 +562,7 @@
 
 template<class KEY, class VALUE, class LISTENER>
 void ClientManager<KEY, VALUE, LISTENER>::updatePriorities(
-        const std::map<int32_t,int32_t>& ownerPriorityList) {
+        const std::map<int32_t,ClientPriority>& ownerPriorityList) {
     Mutex::Autolock lock(mLock);
     for (auto& i : mClients) {
         auto j = ownerPriorityList.find(i->getOwnerId());
diff --git a/services/mediadrm/Android.mk b/services/mediadrm/Android.mk
index 2bf2201..a49d715 100644
--- a/services/mediadrm/Android.mk
+++ b/services/mediadrm/Android.mk
@@ -24,6 +24,7 @@
     libbinder \
     liblog \
     libmediadrm \
+    libhidltransport \
     libutils
 ifeq ($(ENABLE_TREBLE), true)
 LOCAL_SHARED_LIBRARIES += \
diff --git a/services/radio/RadioService.cpp b/services/radio/RadioService.cpp
index a73ed8f..f7a73c3 100644
--- a/services/radio/RadioService.cpp
+++ b/services/radio/RadioService.cpp
@@ -68,10 +68,11 @@
     radio_properties_t properties;
     properties.handle =
             (radio_handle_t)android_atomic_inc(&mNextUniqueId);
-
-    ALOGI("loaded default module %s, handle %d", properties.product, properties.handle);
-
     convertProperties(&properties, &halProperties);
+
+    ALOGI("loaded default module %s, ver %s, handle %d", properties.product,
+        properties.version, properties.handle);
+
     sp<Module> module = new Module(dev, properties);
     mModules.add(properties.handle, module);
 }
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
index 54f9b95..78845b7 100644
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -923,7 +923,10 @@
 
 void SoundTriggerHwService::ModuleClient::onFirstRef()
 {
-    IInterface::asBinder(mClient)->linkToDeath(this);
+    sp<IBinder> binder = IInterface::asBinder(mClient);
+    if (binder != 0) {
+        binder->linkToDeath(this);
+    }
 }
 
 SoundTriggerHwService::ModuleClient::~ModuleClient()