Merge "Rename audio_utils/conversion.h to mono_blend.h"
diff --git a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
index 3512730..0771fc8 100644
--- a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -54,6 +54,22 @@
     void beginConfigure();
 
     /**
+     * The standard operating mode for a camera device; all API guarantees are in force
+     */
+    const int NORMAL_MODE = 0;
+
+    /**
+     * High-speed recording mode; only two outputs targeting preview and video recording may be
+     * used, and requests must be batched.
+     */
+    const int CONSTRAINED_HIGH_SPEED_MODE = 1;
+
+    /**
+     * Start of custom vendor modes
+     */
+    const int VENDOR_MODE_START = 0x8000;
+
+    /**
      * End the device configuration.
      *
      * <p>
@@ -61,8 +77,10 @@
      * a call to beginConfigure and subsequent createStream/deleteStream calls).  This
      * must be called before any requests can be submitted.
      * <p>
+     * @param operatingMode The kind of session to create; either NORMAL_MODE or
+     *     CONSTRAINED_HIGH_SPEED_MODE. Must be a non-negative value.
      */
-    void endConfigure(boolean isConstrainedHighSpeed);
+    void endConfigure(int operatingMode);
 
     void deleteStream(int streamId);
 
diff --git a/cmds/screenrecord/EglWindow.cpp b/cmds/screenrecord/EglWindow.cpp
index c16f2ad..5ea0706 100644
--- a/cmds/screenrecord/EglWindow.cpp
+++ b/cmds/screenrecord/EglWindow.cpp
@@ -21,7 +21,6 @@
 #define EGL_EGLEXT_PROTOTYPES
 
 #include <gui/BufferQueue.h>
-#include <gui/GraphicBufferAlloc.h>
 #include <gui/Surface.h>
 
 #include "EglWindow.h"
diff --git a/cmds/screenrecord/Overlay.cpp b/cmds/screenrecord/Overlay.cpp
index be993e0..aa800d8 100644
--- a/cmds/screenrecord/Overlay.cpp
+++ b/cmds/screenrecord/Overlay.cpp
@@ -23,7 +23,6 @@
 #include <utils/Log.h>
 
 #include <gui/BufferQueue.h>
-#include <gui/GraphicBufferAlloc.h>
 #include <gui/Surface.h>
 #include <cutils/properties.h>
 #include <utils/misc.h>
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index 1fda06c..e77a8ea 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -112,7 +112,7 @@
 Vector<sp<ICryptoFactory>> CryptoHal::makeCryptoFactories() {
     Vector<sp<ICryptoFactory>> factories;
 
-    auto manager = ::IServiceManager::getService("manager");
+    auto manager = ::IServiceManager::getService();
     if (manager != NULL) {
         manager->listByInterface(ICryptoFactory::descriptor,
                 [&factories](const hidl_vec<hidl_string> &registered) {
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 595b895..16035c0 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -200,7 +200,7 @@
 Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
     Vector<sp<IDrmFactory>> factories;
 
-    auto manager = ::IServiceManager::getService("manager");
+    auto manager = ::IServiceManager::getService();
 
     if (manager != NULL) {
         manager->listByInterface(IDrmFactory::descriptor,
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
deleted file mode 120000
index 310fd0d..0000000
--- a/include/media/IAudioFlinger.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libaudioclient/include/IAudioFlinger.h
\ No newline at end of file
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
new file mode 100644
index 0000000..0ad4231
--- /dev/null
+++ b/include/media/IAudioFlinger.h
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_IAUDIOFLINGER_H
+#define ANDROID_IAUDIOFLINGER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+#include <media/IAudioTrack.h>
+#include <media/IAudioRecord.h>
+#include <media/IAudioFlingerClient.h>
+#include <system/audio.h>
+#include <system/audio_effect.h>
+#include <system/audio_policy.h>
+#include <media/IEffect.h>
+#include <media/IEffectClient.h>
+#include <utils/String8.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class IAudioFlinger : public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(AudioFlinger);
+
+
+    // invariant on exit for all APIs that return an sp<>:
+    //   (return value != 0) == (*status == NO_ERROR)
+
+    /* create an audio track and registers it with AudioFlinger.
+     * return null if the track cannot be created.
+     */
+    virtual sp<IAudioTrack> createTrack(
+                                audio_stream_type_t streamType,
+                                uint32_t sampleRate,
+                                audio_format_t format,
+                                audio_channel_mask_t channelMask,
+                                size_t *pFrameCount,
+                                audio_output_flags_t *flags,
+                                const sp<IMemory>& sharedBuffer,
+                                // On successful return, AudioFlinger takes over the handle
+                                // reference and will release it when the track is destroyed.
+                                // However on failure, the client is responsible for release.
+                                audio_io_handle_t output,
+                                pid_t pid,
+                                pid_t tid,  // -1 means unused, otherwise must be valid non-0
+                                audio_session_t *sessionId,
+                                int clientUid,
+                                status_t *status,
+                                audio_port_handle_t portId) = 0;
+
+    virtual sp<IAudioRecord> openRecord(
+                                // On successful return, AudioFlinger takes over the handle
+                                // reference and will release it when the track is destroyed.
+                                // However on failure, the client is responsible for release.
+                                audio_io_handle_t input,
+                                uint32_t sampleRate,
+                                audio_format_t format,
+                                audio_channel_mask_t channelMask,
+                                const String16& callingPackage,
+                                size_t *pFrameCount,
+                                audio_input_flags_t *flags,
+                                pid_t pid,
+                                pid_t tid,  // -1 means unused, otherwise must be valid non-0
+                                int clientUid,
+                                audio_session_t *sessionId,
+                                size_t *notificationFrames,
+                                sp<IMemory>& cblk,
+                                sp<IMemory>& buffers,   // return value 0 means it follows cblk
+                                status_t *status,
+                                audio_port_handle_t portId) = 0;
+
+    // FIXME Surprisingly, format/latency don't work for input handles
+
+    /* query the audio hardware state. This state never changes,
+     * and therefore can be cached.
+     */
+    virtual     uint32_t    sampleRate(audio_io_handle_t ioHandle) const = 0;
+
+    // reserved; formerly channelCount()
+
+    virtual     audio_format_t format(audio_io_handle_t output) const = 0;
+    virtual     size_t      frameCount(audio_io_handle_t ioHandle) const = 0;
+
+    // return estimated latency in milliseconds
+    virtual     uint32_t    latency(audio_io_handle_t output) const = 0;
+
+    /* set/get the audio hardware state. This will probably be used by
+     * the preference panel, mostly.
+     */
+    virtual     status_t    setMasterVolume(float value) = 0;
+    virtual     status_t    setMasterMute(bool muted) = 0;
+
+    virtual     float       masterVolume() const = 0;
+    virtual     bool        masterMute() const = 0;
+
+    /* set/get stream type state. This will probably be used by
+     * the preference panel, mostly.
+     */
+    virtual     status_t    setStreamVolume(audio_stream_type_t stream, float value,
+                                    audio_io_handle_t output) = 0;
+    virtual     status_t    setStreamMute(audio_stream_type_t stream, bool muted) = 0;
+
+    virtual     float       streamVolume(audio_stream_type_t stream,
+                                    audio_io_handle_t output) const = 0;
+    virtual     bool        streamMute(audio_stream_type_t stream) const = 0;
+
+    // set audio mode
+    virtual     status_t    setMode(audio_mode_t mode) = 0;
+
+    // mic mute/state
+    virtual     status_t    setMicMute(bool state) = 0;
+    virtual     bool        getMicMute() const = 0;
+
+    virtual     status_t    setParameters(audio_io_handle_t ioHandle,
+                                    const String8& keyValuePairs) = 0;
+    virtual     String8     getParameters(audio_io_handle_t ioHandle, const String8& keys)
+                                    const = 0;
+
+    // Register an object to receive audio input/output change and track notifications.
+    // For a given calling pid, AudioFlinger disregards any registrations after the first.
+    // Thus the IAudioFlingerClient must be a singleton per process.
+    virtual void registerClient(const sp<IAudioFlingerClient>& client) = 0;
+
+    // retrieve the audio recording buffer size
+    // FIXME This API assumes a route, and so should be deprecated.
+    virtual size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
+            audio_channel_mask_t channelMask) const = 0;
+
+    virtual status_t openOutput(audio_module_handle_t module,
+                                audio_io_handle_t *output,
+                                audio_config_t *config,
+                                audio_devices_t *devices,
+                                const String8& address,
+                                uint32_t *latencyMs,
+                                audio_output_flags_t flags) = 0;
+    virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
+                                    audio_io_handle_t output2) = 0;
+    virtual status_t closeOutput(audio_io_handle_t output) = 0;
+    virtual status_t suspendOutput(audio_io_handle_t output) = 0;
+    virtual status_t restoreOutput(audio_io_handle_t output) = 0;
+
+    virtual status_t openInput(audio_module_handle_t module,
+                               audio_io_handle_t *input,
+                               audio_config_t *config,
+                               audio_devices_t *device,
+                               const String8& address,
+                               audio_source_t source,
+                               audio_input_flags_t flags) = 0;
+    virtual status_t closeInput(audio_io_handle_t input) = 0;
+
+    virtual status_t invalidateStream(audio_stream_type_t stream) = 0;
+
+    virtual status_t setVoiceVolume(float volume) = 0;
+
+    virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
+                                    audio_io_handle_t output) const = 0;
+
+    virtual uint32_t getInputFramesLost(audio_io_handle_t ioHandle) const = 0;
+
+    virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use) = 0;
+
+    virtual void acquireAudioSessionId(audio_session_t audioSession, pid_t pid) = 0;
+    virtual void releaseAudioSessionId(audio_session_t audioSession, pid_t pid) = 0;
+
+    virtual status_t queryNumberEffects(uint32_t *numEffects) const = 0;
+
+    virtual status_t queryEffect(uint32_t index, effect_descriptor_t *pDescriptor) const = 0;
+
+    virtual status_t getEffectDescriptor(const effect_uuid_t *pEffectUUID,
+                                        effect_descriptor_t *pDescriptor) const = 0;
+
+    virtual sp<IEffect> createEffect(
+                                    effect_descriptor_t *pDesc,
+                                    const sp<IEffectClient>& client,
+                                    int32_t priority,
+                                    // AudioFlinger doesn't take over handle reference from client
+                                    audio_io_handle_t output,
+                                    audio_session_t sessionId,
+                                    const String16& callingPackage,
+                                    pid_t pid,
+                                    status_t *status,
+                                    int *id,
+                                    int *enabled) = 0;
+
+    virtual status_t moveEffects(audio_session_t session, audio_io_handle_t srcOutput,
+                                    audio_io_handle_t dstOutput) = 0;
+
+    virtual audio_module_handle_t loadHwModule(const char *name) = 0;
+
+    // helpers for android.media.AudioManager.getProperty(), see description there for meaning
+    // FIXME move these APIs to AudioPolicy to permit a more accurate implementation
+    // that looks on primary device for a stream with fast flag, primary flag, or first one.
+    virtual uint32_t getPrimaryOutputSamplingRate() = 0;
+    virtual size_t getPrimaryOutputFrameCount() = 0;
+
+    // Intended for AudioService to inform AudioFlinger of device's low RAM attribute,
+    // and should be called at most once.  For a definition of what "low RAM" means, see
+    // android.app.ActivityManager.isLowRamDevice().
+    virtual status_t setLowRamDevice(bool isLowRamDevice) = 0;
+
+    /* List available audio ports and their attributes */
+    virtual status_t listAudioPorts(unsigned int *num_ports,
+                                    struct audio_port *ports) = 0;
+
+    /* Get attributes for a given audio port */
+    virtual status_t getAudioPort(struct audio_port *port) = 0;
+
+    /* Create an audio patch between several source and sink ports */
+    virtual status_t createAudioPatch(const struct audio_patch *patch,
+                                       audio_patch_handle_t *handle) = 0;
+
+    /* Release an audio patch */
+    virtual status_t releaseAudioPatch(audio_patch_handle_t handle) = 0;
+
+    /* List existing audio patches */
+    virtual status_t listAudioPatches(unsigned int *num_patches,
+                                      struct audio_patch *patches) = 0;
+    /* Set audio port configuration */
+    virtual status_t setAudioPortConfig(const struct audio_port_config *config) = 0;
+
+    /* Get the HW synchronization source used for an audio session */
+    virtual audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId) = 0;
+
+    /* Indicate JAVA services are ready (scheduling, power management ...) */
+    virtual status_t systemReady() = 0;
+
+    // Returns the number of frames per audio HAL buffer.
+    virtual size_t frameCountHAL(audio_io_handle_t ioHandle) const = 0;
+};
+
+
+// ----------------------------------------------------------------------------
+
+class BnAudioFlinger : public BnInterface<IAudioFlinger>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+
+    // Requests media.log to start merging log buffers
+    virtual void requestLogMerge() = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IAUDIOFLINGER_H
diff --git a/include/media/IMediaLogService.h b/include/media/IMediaLogService.h
deleted file mode 120000
index 7a822dd..0000000
--- a/include/media/IMediaLogService.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/IMediaLogService.h
\ No newline at end of file
diff --git a/include/media/IMediaLogService.h b/include/media/IMediaLogService.h
new file mode 100644
index 0000000..0f09e0d
--- /dev/null
+++ b/include/media/IMediaLogService.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_IMEDIALOGSERVICE_H
+#define ANDROID_IMEDIALOGSERVICE_H
+
+#include <binder/IInterface.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+class IMediaLogService: public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(MediaLogService);
+
+    virtual void    registerWriter(const sp<IMemory>& shared, size_t size, const char *name) = 0;
+    virtual void    unregisterWriter(const sp<IMemory>& shared) = 0;
+    virtual void    requestMergeWakeup() = 0;
+
+};
+
+class BnMediaLogService: public BnInterface<IMediaLogService>
+{
+public:
+    virtual status_t    onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                uint32_t flags = 0);
+};
+
+}   // namespace android
+
+#endif  // ANDROID_IMEDIALOGSERVICE_H
diff --git a/include/media/MmapStreamInterface.h b/include/media/MmapStreamInterface.h
index 9f3731e..7dbc19e 100644
--- a/include/media/MmapStreamInterface.h
+++ b/include/media/MmapStreamInterface.h
@@ -75,6 +75,7 @@
 
     /**
      * Retrieve information on the mmap buffer used for audio samples transfer.
+     * Must be called before any other method after opening the stream or entering standby.
      *
      * \param[in] min_size_frames minimum buffer size requested. The actual buffer
      *        size returned in struct audio_mmap_buffer_info can be larger.
@@ -94,6 +95,7 @@
      * \param[out] position address at which the mmap read/write position should be returned.
      *
      * \return OK if the position is successfully returned.
+     *         NO_INIT in case of initialization error
      *         NOT_ENOUGH_DATA if the position cannot be retrieved
      *         INVALID_OPERATION if called before createMmapBuffer()
      */
@@ -106,6 +108,7 @@
      * \param[in] client a Client struct describing the client starting on this stream.
      * \param[out] handle unique handle for this instance. Used with stop().
      * \return OK in case of success.
+     *         NO_INIT in case of initialization error
      *         INVALID_OPERATION if called out of sequence
      */
     virtual status_t start(const Client& client, audio_port_handle_t *handle) = 0;
@@ -116,10 +119,23 @@
      *
      * \param[in] handle unique handle allocated by start().
      * \return OK in case of success.
+     *         NO_INIT in case of initialization error
      *         INVALID_OPERATION if called out of sequence
      */
     virtual status_t stop(audio_port_handle_t handle) = 0;
 
+    /**
+     * Put a stream operating in mmap mode into standby.
+     * Must be called after createMmapBuffer(). Cannot be called if any client is active.
+     * It is recommended to place a mmap stream into standby as often as possible when no client is
+     * active to save power.
+     *
+     * \return OK in case of success.
+     *         NO_INIT in case of initialization error
+     *         INVALID_OPERATION if called out of sequence
+     */
+    virtual status_t standby() = 0;
+
   protected:
     // Subclasses can not be constructed directly by clients.
     MmapStreamInterface() {}
diff --git a/include/media/omx/1.0/Conversion.h b/include/media/omx/1.0/Conversion.h
index ee83713..f3f8441 100644
--- a/include/media/omx/1.0/Conversion.h
+++ b/include/media/omx/1.0/Conversion.h
@@ -191,6 +191,19 @@
 }
 
 /**
+ * \brief Convert `Return<Status>` to `binder::Status`.
+ *
+ * \param[in] t The source `Return<Status>`.
+ * \return The corresponding `binder::Status`.
+ */
+// convert: Return<Status> -> ::android::binder::Status
+inline ::android::binder::Status toBinderStatus(
+        Return<Status> const& t) {
+    return ::android::binder::Status::fromStatusT(
+            t.isOk() ? static_cast<status_t>(static_cast<Status>(t)) : UNKNOWN_ERROR);
+}
+
+/**
  * \brief Convert `Return<Status>` to `status_t`. This is for legacy binder
  * calls.
  *
diff --git a/include/media/omx/1.0/WGraphicBufferSource.h b/include/media/omx/1.0/WGraphicBufferSource.h
index 7c80c2e..0ca5f44 100644
--- a/include/media/omx/1.0/WGraphicBufferSource.h
+++ b/include/media/omx/1.0/WGraphicBufferSource.h
@@ -48,7 +48,6 @@
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::sp;
-
 using ::android::IOMXNode;
 
 /**
@@ -60,7 +59,7 @@
  * - TW = Treble Wrapper --- It wraps a legacy object inside a Treble object.
  */
 
-typedef ::android::IGraphicBufferSource LGraphicBufferSource;
+typedef ::android::binder::Status BnStatus;
 typedef ::android::BnGraphicBufferSource BnGraphicBufferSource;
 typedef ::android::hardware::media::omx::V1_0::IGraphicBufferSource
         TGraphicBufferSource;
@@ -68,36 +67,19 @@
 struct LWGraphicBufferSource : public BnGraphicBufferSource {
     sp<TGraphicBufferSource> mBase;
     LWGraphicBufferSource(sp<TGraphicBufferSource> const& base);
-    ::android::binder::Status configure(
+    BnStatus configure(
             const sp<IOMXNode>& omxNode, int32_t dataSpace) override;
-    ::android::binder::Status setSuspend(bool suspend, int64_t timeUs) override;
-    ::android::binder::Status setRepeatPreviousFrameDelayUs(
+    BnStatus setSuspend(bool suspend, int64_t timeUs) override;
+    BnStatus setRepeatPreviousFrameDelayUs(
             int64_t repeatAfterUs) override;
-    ::android::binder::Status setMaxFps(float maxFps) override;
-    ::android::binder::Status setTimeLapseConfig(
+    BnStatus setMaxFps(float maxFps) override;
+    BnStatus setTimeLapseConfig(
             int64_t timePerFrameUs, int64_t timePerCaptureUs) override;
-    ::android::binder::Status setStartTimeUs(int64_t startTimeUs) override;
-    ::android::binder::Status setStopTimeUs(int64_t stopTimeUs) override;
-    ::android::binder::Status setColorAspects(int32_t aspects) override;
-    ::android::binder::Status setTimeOffsetUs(int64_t timeOffsetsUs) override;
-    ::android::binder::Status signalEndOfInputStream() override;
-};
-
-struct TWGraphicBufferSource : public TGraphicBufferSource {
-    sp<LGraphicBufferSource> mBase;
-    TWGraphicBufferSource(sp<LGraphicBufferSource> const& base);
-    Return<void> configure(
-            const sp<IOmxNode>& omxNode, Dataspace dataspace) override;
-    Return<void> setSuspend(bool suspend, int64_t timeUs) override;
-    Return<void> setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) override;
-    Return<void> setMaxFps(float maxFps) override;
-    Return<void> setTimeLapseConfig(
-            int64_t timePerFrameUs, int64_t timePerCaptureUs) override;
-    Return<void> setStartTimeUs(int64_t startTimeUs) override;
-    Return<void> setStopTimeUs(int64_t stopTimeUs) override;
-    Return<void> setColorAspects(const ColorAspects& aspects) override;
-    Return<void> setTimeOffsetUs(int64_t timeOffsetUs) override;
-    Return<void> signalEndOfInputStream() override;
+    BnStatus setStartTimeUs(int64_t startTimeUs) override;
+    BnStatus setStopTimeUs(int64_t stopTimeUs) override;
+    BnStatus setColorAspects(int32_t aspects) override;
+    BnStatus setTimeOffsetUs(int64_t timeOffsetsUs) override;
+    BnStatus signalEndOfInputStream() override;
 };
 
 }  // namespace utils
diff --git a/include/media/omx/1.0/WOmx.h b/include/media/omx/1.0/WOmx.h
index 4aaf470..9268bd6 100644
--- a/include/media/omx/1.0/WOmx.h
+++ b/include/media/omx/1.0/WOmx.h
@@ -70,18 +70,6 @@
             sp<::android::IGraphicBufferSource>* bufferSource) override;
 };
 
-struct TWOmx : public IOmx {
-    sp<IOMX> mBase;
-    TWOmx(sp<IOMX> const& base);
-    Return<void> listNodes(listNodes_cb _hidl_cb) override;
-    Return<void> allocateNode(
-            const hidl_string& name,
-            const sp<IOmxObserver>& observer,
-            allocateNode_cb _hidl_cb) override;
-    Return<void> createInputSurface(createInputSurface_cb _hidl_cb) override;
-
-};
-
 }  // namespace utils
 }  // namespace V1_0
 }  // namespace omx
diff --git a/media/libaaudio/include/aaudio/AAudioDefinitions.h b/media/libaaudio/include/aaudio/AAudioDefinitions.h
index 5b7b819..e5b7d7a 100644
--- a/media/libaaudio/include/aaudio/AAudioDefinitions.h
+++ b/media/libaaudio/include/aaudio/AAudioDefinitions.h
@@ -23,8 +23,6 @@
 extern "C" {
 #endif
 
-typedef int32_t  aaudio_result_t;
-
 /**
  * This is used to represent a value that has not been specified.
  * For example, an application could use AAUDIO_UNSPECIFIED to indicate
@@ -34,12 +32,13 @@
 #define AAUDIO_UNSPECIFIED           0
 #define AAUDIO_DEVICE_UNSPECIFIED    ((int32_t) -1)
 
-enum aaudio_direction_t {
+enum {
     AAUDIO_DIRECTION_OUTPUT,
     AAUDIO_DIRECTION_INPUT
 };
+typedef int32_t aaudio_direction_t;
 
-enum aaudio_audio_format_t {
+enum {
     AAUDIO_FORMAT_INVALID = -1,
     AAUDIO_FORMAT_UNSPECIFIED = 0,
     AAUDIO_FORMAT_PCM_I16,
@@ -47,6 +46,7 @@
     AAUDIO_FORMAT_PCM_I8_24,
     AAUDIO_FORMAT_PCM_I32
 };
+typedef int32_t aaudio_audio_format_t;
 
 enum {
     AAUDIO_OK,
@@ -71,8 +71,9 @@
     AAUDIO_ERROR_OUT_OF_RANGE,
     AAUDIO_ERROR_NO_SERVICE
 };
+typedef int32_t  aaudio_result_t;
 
-typedef enum
+enum
 {
     AAUDIO_STREAM_STATE_UNINITIALIZED = 0,
     AAUDIO_STREAM_STATE_UNKNOWN,
@@ -87,9 +88,10 @@
     AAUDIO_STREAM_STATE_STOPPED,
     AAUDIO_STREAM_STATE_CLOSING,
     AAUDIO_STREAM_STATE_CLOSED,
-} aaudio_stream_state_t;
+};
+typedef int32_t aaudio_stream_state_t;
 
-typedef enum {
+enum {
     /**
      * This will be the only stream using a particular source or sink.
      * This mode will provide the lowest possible latency.
@@ -101,7 +103,8 @@
      * This will have higher latency than the EXCLUSIVE mode.
      */
     AAUDIO_SHARING_MODE_SHARED
-} aaudio_sharing_mode_t;
+};
+typedef int32_t aaudio_sharing_mode_t;
 
 #ifdef __cplusplus
 }
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 255e350..4e2a0d5 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -935,7 +935,6 @@
         }
         return reply.readInt64();
     }
-
 };
 
 IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
@@ -945,6 +944,29 @@
 status_t BnAudioFlinger::onTransact(
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
+    // Whitelist of relevant events to trigger log merging.
+    // Log merging should activate during audio activity of any kind. This are considered the
+    // most relevant events.
+    // TODO should select more wisely the items from the list
+    switch (code) {
+        case CREATE_TRACK:
+        case OPEN_RECORD:
+        case SET_MASTER_VOLUME:
+        case SET_MASTER_MUTE:
+        case SET_STREAM_VOLUME:
+        case SET_STREAM_MUTE:
+        case SET_MIC_MUTE:
+        case SET_PARAMETERS:
+        case OPEN_INPUT:
+        case SET_VOICE_VOLUME:
+        case CREATE_EFFECT:
+        case SYSTEM_READY: {
+            requestLogMerge();
+            break;
+        }
+        default:
+            break;
+    }
     switch (code) {
         case CREATE_TRACK: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
diff --git a/media/libaudiohal/ConversionHelperHidl.h b/media/libaudiohal/ConversionHelperHidl.h
index a991baf..c356f37 100644
--- a/media/libaudiohal/ConversionHelperHidl.h
+++ b/media/libaudiohal/ConversionHelperHidl.h
@@ -23,7 +23,6 @@
 
 using ::android::hardware::audio::V2_0::ParameterValue;
 using ::android::hardware::Return;
-using ::android::hardware::Status;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
 
diff --git a/media/libaudiohal/DevicesFactoryHalHidl.cpp b/media/libaudiohal/DevicesFactoryHalHidl.cpp
index 9cbe018..6d73e2d 100644
--- a/media/libaudiohal/DevicesFactoryHalHidl.cpp
+++ b/media/libaudiohal/DevicesFactoryHalHidl.cpp
@@ -30,7 +30,6 @@
 using ::android::hardware::audio::V2_0::IDevice;
 using ::android::hardware::audio::V2_0::Result;
 using ::android::hardware::Return;
-using ::android::hardware::Status;
 
 namespace android {
 
diff --git a/media/libaudiohal/EffectBufferHalHidl.cpp b/media/libaudiohal/EffectBufferHalHidl.cpp
index ce581f2..d6a41a2 100644
--- a/media/libaudiohal/EffectBufferHalHidl.cpp
+++ b/media/libaudiohal/EffectBufferHalHidl.cpp
@@ -27,7 +27,6 @@
 #include "EffectBufferHalHidl.h"
 
 using ::android::hardware::Return;
-using ::android::hardware::Status;
 using ::android::hidl::allocator::V1_0::IAllocator;
 
 namespace android {
diff --git a/media/libaudiohal/EffectHalHidl.cpp b/media/libaudiohal/EffectHalHidl.cpp
index 539558d..0babfda 100644
--- a/media/libaudiohal/EffectHalHidl.cpp
+++ b/media/libaudiohal/EffectHalHidl.cpp
@@ -36,7 +36,6 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::MQDescriptorSync;
 using ::android::hardware::Return;
-using ::android::hardware::Status;
 
 namespace android {
 
diff --git a/media/libaudiohal/EffectsFactoryHalHidl.cpp b/media/libaudiohal/EffectsFactoryHalHidl.cpp
index 950f9dc..fd3e207 100644
--- a/media/libaudiohal/EffectsFactoryHalHidl.cpp
+++ b/media/libaudiohal/EffectsFactoryHalHidl.cpp
@@ -29,7 +29,6 @@
 using ::android::hardware::audio::effect::V2_0::IEffect;
 using ::android::hardware::audio::effect::V2_0::Result;
 using ::android::hardware::Return;
-using ::android::hardware::Status;
 
 namespace android {
 
diff --git a/media/libmedia/omx/1.0/WGraphicBufferSource.cpp b/media/libmedia/omx/1.0/WGraphicBufferSource.cpp
index 247c540..b4e2975 100644
--- a/media/libmedia/omx/1.0/WGraphicBufferSource.cpp
+++ b/media/libmedia/omx/1.0/WGraphicBufferSource.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#include <stagefright/foundation/ColorUtils.h>
-
 #include <media/omx/1.0/WGraphicBufferSource.h>
 #include <media/omx/1.0/WOmxNode.h>
 #include <media/omx/1.0/Conversion.h>
@@ -27,14 +25,12 @@
 namespace V1_0 {
 namespace utils {
 
-using android::ColorUtils;
-
 // LWGraphicBufferSource
 LWGraphicBufferSource::LWGraphicBufferSource(
         sp<TGraphicBufferSource> const& base) : mBase(base) {
 }
 
-::android::binder::Status LWGraphicBufferSource::configure(
+BnStatus LWGraphicBufferSource::configure(
         const sp<IOMXNode>& omxNode, int32_t dataSpace) {
     sp<IOmxNode> hOmxNode = omxNode->getHalInterface();
     return toBinderStatus(mBase->configure(
@@ -42,111 +38,51 @@
             toHardwareDataspace(dataSpace)));
 }
 
-::android::binder::Status LWGraphicBufferSource::setSuspend(
+BnStatus LWGraphicBufferSource::setSuspend(
         bool suspend, int64_t timeUs) {
     return toBinderStatus(mBase->setSuspend(suspend, timeUs));
 }
 
-::android::binder::Status LWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
+BnStatus LWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
         int64_t repeatAfterUs) {
     return toBinderStatus(mBase->setRepeatPreviousFrameDelayUs(repeatAfterUs));
 }
 
-::android::binder::Status LWGraphicBufferSource::setMaxFps(float maxFps) {
+BnStatus LWGraphicBufferSource::setMaxFps(float maxFps) {
     return toBinderStatus(mBase->setMaxFps(maxFps));
 }
 
-::android::binder::Status LWGraphicBufferSource::setTimeLapseConfig(
+BnStatus LWGraphicBufferSource::setTimeLapseConfig(
         int64_t timePerFrameUs, int64_t timePerCaptureUs) {
     return toBinderStatus(mBase->setTimeLapseConfig(
             timePerFrameUs, timePerCaptureUs));
 }
 
-::android::binder::Status LWGraphicBufferSource::setStartTimeUs(
+BnStatus LWGraphicBufferSource::setStartTimeUs(
         int64_t startTimeUs) {
     return toBinderStatus(mBase->setStartTimeUs(startTimeUs));
 }
 
-::android::binder::Status LWGraphicBufferSource::setStopTimeUs(
+BnStatus LWGraphicBufferSource::setStopTimeUs(
         int64_t stopTimeUs) {
     return toBinderStatus(mBase->setStopTimeUs(stopTimeUs));
 }
 
-::android::binder::Status LWGraphicBufferSource::setColorAspects(
+BnStatus LWGraphicBufferSource::setColorAspects(
         int32_t aspects) {
     return toBinderStatus(mBase->setColorAspects(
             toHardwareColorAspects(aspects)));
 }
 
-::android::binder::Status LWGraphicBufferSource::setTimeOffsetUs(
+BnStatus LWGraphicBufferSource::setTimeOffsetUs(
         int64_t timeOffsetsUs) {
     return toBinderStatus(mBase->setTimeOffsetUs(timeOffsetsUs));
 }
 
-::android::binder::Status LWGraphicBufferSource::signalEndOfInputStream() {
+BnStatus LWGraphicBufferSource::signalEndOfInputStream() {
     return toBinderStatus(mBase->signalEndOfInputStream());
 }
 
-// TWGraphicBufferSource
-TWGraphicBufferSource::TWGraphicBufferSource(
-        sp<LGraphicBufferSource> const& base) : mBase(base) {
-}
-
-Return<void> TWGraphicBufferSource::configure(
-        const sp<IOmxNode>& omxNode, Dataspace dataspace) {
-    mBase->configure(new LWOmxNode(omxNode), toRawDataspace(dataspace));
-    return Void();
-}
-
-Return<void> TWGraphicBufferSource::setSuspend(
-        bool suspend, int64_t timeUs) {
-    mBase->setSuspend(suspend, timeUs);
-    return Void();
-}
-
-Return<void> TWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
-        int64_t repeatAfterUs) {
-    mBase->setRepeatPreviousFrameDelayUs(repeatAfterUs);
-    return Void();
-}
-
-Return<void> TWGraphicBufferSource::setMaxFps(float maxFps) {
-    mBase->setMaxFps(maxFps);
-    return Void();
-}
-
-Return<void> TWGraphicBufferSource::setTimeLapseConfig(
-        int64_t timePerFrameUs, int64_t timePerCaptureUs) {
-    mBase->setTimeLapseConfig(timePerFrameUs, timePerCaptureUs);
-    return Void();
-}
-
-Return<void> TWGraphicBufferSource::setStartTimeUs(int64_t startTimeUs) {
-    mBase->setStartTimeUs(startTimeUs);
-    return Void();
-}
-
-Return<void> TWGraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) {
-    mBase->setStopTimeUs(stopTimeUs);
-    return Void();
-}
-
-Return<void> TWGraphicBufferSource::setColorAspects(
-        const ColorAspects& aspects) {
-    mBase->setColorAspects(toCompactColorAspects(aspects));
-    return Void();
-}
-
-Return<void> TWGraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
-    mBase->setTimeOffsetUs(timeOffsetUs);
-    return Void();
-}
-
-Return<void> TWGraphicBufferSource::signalEndOfInputStream() {
-    mBase->signalEndOfInputStream();
-    return Void();
-}
-
 }  // namespace utils
 }  // namespace V1_0
 }  // namespace omx
diff --git a/media/libmedia/omx/1.0/WOmx.cpp b/media/libmedia/omx/1.0/WOmx.cpp
index 39871f8..8e4e147 100644
--- a/media/libmedia/omx/1.0/WOmx.cpp
+++ b/media/libmedia/omx/1.0/WOmx.cpp
@@ -79,45 +79,6 @@
     return transStatus == NO_ERROR ? fnStatus : transStatus;
 }
 
-// TWOmx
-TWOmx::TWOmx(sp<IOMX> const& base) : mBase(base) {
-}
-
-Return<void> TWOmx::listNodes(listNodes_cb _hidl_cb) {
-    List<IOMX::ComponentInfo> lList;
-    Status status = toStatus(mBase->listNodes(&lList));
-
-    hidl_vec<IOmx::ComponentInfo> tList;
-    tList.resize(lList.size());
-    size_t i = 0;
-    for (auto const& lInfo : lList) {
-        convertTo(&(tList[i++]), lInfo);
-    }
-    _hidl_cb(status, tList);
-    return Void();
-}
-
-Return<void> TWOmx::allocateNode(
-        const hidl_string& name,
-        const sp<IOmxObserver>& observer,
-        allocateNode_cb _hidl_cb) {
-    sp<IOMXNode> omxNode;
-    Status status = toStatus(mBase->allocateNode(
-            name, new LWOmxObserver(observer), &omxNode));
-    _hidl_cb(status, new TWOmxNode(omxNode));
-    return Void();
-}
-
-Return<void> TWOmx::createInputSurface(createInputSurface_cb _hidl_cb) {
-    sp<::android::IGraphicBufferProducer> lProducer;
-    sp<::android::IGraphicBufferSource> lSource;
-    status_t status = mBase->createInputSurface(&lProducer, &lSource);
-    _hidl_cb(toStatus(status),
-             new TWOmxBufferProducer(lProducer),
-             new TWGraphicBufferSource(lSource));
-    return Void();
-}
-
 }  // namespace utils
 }  // namespace V1_0
 }  // namespace omx
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 3b2a8a1..19c4d85 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -49,6 +49,7 @@
       mSeekInProgress(false),
       mPlayingTimeUs(0),
       mLooper(new ALooper),
+      mPlayer(new NuPlayer(pid)),
       mPlayerFlags(0),
       mAnalyticsItem(NULL),
       mAtEOS(false),
@@ -66,7 +67,6 @@
             true,  /* canCallJava */
             PRIORITY_AUDIO);
 
-    mPlayer = new NuPlayer(pid);
     mLooper->registerHandler(mPlayer);
 
     mPlayer->setDriver(this);
@@ -998,8 +998,6 @@
 {
     ALOGV("prepareDrm(%p) state: %d", this, mState);
 
-    Mutex::Autolock autoLock(mLock);
-
     // leaving the state verification for mediaplayer.cpp
     status_t ret = mPlayer->prepareDrm(uuid, drmSessionId);
 
@@ -1012,8 +1010,6 @@
 {
     ALOGV("releaseDrm(%p) state: %d", this, mState);
 
-    Mutex::Autolock autoLock(mLock);
-
     // leaving the state verification for mediaplayer.cpp
     status_t ret = mPlayer->releaseDrm();
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 972a348..082f71a 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -127,7 +127,7 @@
     // <<<
 
     sp<ALooper> mLooper;
-    sp<NuPlayer> mPlayer;
+    const sp<NuPlayer> mPlayer;
     sp<AudioSink> mAudioSink;
     uint32_t mPlayerFlags;
 
diff --git a/media/libnbaio/NBLog.cpp b/media/libnbaio/NBLog.cpp
index f480c16..7936ad2 100644
--- a/media/libnbaio/NBLog.cpp
+++ b/media/libnbaio/NBLog.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "NBLog"
 //#define LOG_NDEBUG 0
 
+#include <climits>
 #include <stdarg.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -90,8 +91,9 @@
     return -1;
 }
 
-size_t NBLog::FormatEntry::copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst, int author) const {
-    auto it = this->begin();
+NBLog::FormatEntry::iterator NBLog::FormatEntry::copyWithAuthor(
+        std::unique_ptr<audio_utils_fifo_writer> &dst, int author) const {
+    auto it = begin();
     // copy fmt start entry
     it.copyTo(dst);
     // insert author entry
@@ -109,7 +111,7 @@
     }
     it.copyTo(dst);
     ++it;
-    return it - this->begin();
+    return it;
 }
 
 void NBLog::FormatEntry::iterator::copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst) const {
@@ -125,6 +127,9 @@
     return iterator(mEntry);
 }
 
+NBLog::FormatEntry::iterator::iterator()
+    : ptr(nullptr) {}
+
 NBLog::FormatEntry::iterator::iterator(const uint8_t *entry)
     : ptr(entry) {}
 
@@ -149,6 +154,16 @@
     return *this;
 }
 
+NBLog::FormatEntry::iterator NBLog::FormatEntry::iterator::next() const {
+    iterator aux(*this);
+    return ++aux;
+}
+
+NBLog::FormatEntry::iterator NBLog::FormatEntry::iterator::prev() const {
+    iterator aux(*this);
+    return --aux;
+}
+
 int NBLog::FormatEntry::iterator::operator-(const NBLog::FormatEntry::iterator &other) const {
     return ptr - other.ptr;
 }
@@ -579,6 +594,23 @@
     delete mFifo;
 }
 
+uint8_t *NBLog::Reader::findLastEntryOfType(uint8_t *front, uint8_t *back, uint8_t type) {
+    while (back + Entry::kPreviousLengthOffset >= front) {
+        uint8_t *prev = back - back[Entry::kPreviousLengthOffset] - Entry::kOverhead;
+        if (prev < front || prev + prev[offsetof(FormatEntry::entry, length)] +
+                            Entry::kOverhead != back) {
+
+            // prev points to an out of limits or inconsistent entry
+            return nullptr;
+        }
+        if (prev[offsetof(FormatEntry::entry, type)] == type) {
+            return prev;
+        }
+        back = prev;
+    }
+    return nullptr; // no entry found
+}
+
 std::unique_ptr<NBLog::Reader::Snapshot> NBLog::Reader::getSnapshot()
 {
     if (mFifoReader == NULL) {
@@ -587,22 +619,66 @@
     // make a copy to avoid race condition with writer
     size_t capacity = mFifo->capacity();
 
-    std::unique_ptr<Snapshot> snapshot(new Snapshot(capacity));
+    // This emulates the behaviour of audio_utils_fifo_reader::read, but without incrementing the
+    // reader index. The index is incremented after handling corruption, to after the last complete
+    // entry of the buffer
+    size_t lost;
+    audio_utils_iovec iovec[2];
+    ssize_t availToRead = mFifoReader->obtain(iovec, capacity, NULL /*timeout*/, &lost);
+    if (availToRead <= 0) {
+        return std::unique_ptr<NBLog::Reader::Snapshot>(new Snapshot());
+    }
 
-    ssize_t actual = mFifoReader->read((void*) snapshot->mData, capacity, NULL /*timeout*/,
-                                       &(snapshot->mLost));
-    ALOG_ASSERT(actual <= capacity);
-    snapshot->mAvail = actual > 0 ? (size_t) actual : 0;
+    std::unique_ptr<Snapshot> snapshot(new Snapshot(availToRead));
+    memcpy(snapshot->mData, (const char *) mFifo->buffer() + iovec[0].mOffset, iovec[0].mLength);
+    if (iovec[1].mLength > 0) {
+        memcpy(snapshot->mData + (iovec[0].mLength),
+            (const char *) mFifo->buffer() + iovec[1].mOffset, iovec[1].mLength);
+    }
+
+    // Handle corrupted buffer
+    // Potentially, a buffer has corrupted data on both beginning (due to overflow) and end
+    // (due to incomplete format entry). But even if the end format entry is incomplete,
+    // it ends in a complete entry (which is not an END_FMT). So is safe to traverse backwards.
+    // TODO: handle client corruption (in the middle of a buffer)
+
+    uint8_t *back = snapshot->mData + availToRead;
+    uint8_t *front = snapshot->mData;
+
+    // Find last END_FMT. <back> is sitting on an entry which might be the middle of a FormatEntry.
+    // We go backwards until we find an EVENT_END_FMT.
+    uint8_t *lastEnd = findLastEntryOfType(front, back, EVENT_END_FMT);
+    if (lastEnd == nullptr) {
+        snapshot->mEnd = snapshot->mBegin = FormatEntry::iterator(front);
+    } else {
+        // end of snapshot points to after last END_FMT entry
+        snapshot->mEnd = FormatEntry::iterator(lastEnd + Entry::kOverhead);
+        // find first START_FMT
+        uint8_t *firstStart = nullptr;
+        uint8_t *firstStartTmp = lastEnd;
+        while ((firstStartTmp = findLastEntryOfType(front, firstStartTmp, EVENT_START_FMT))
+                != nullptr) {
+            firstStart = firstStartTmp;
+        }
+        // firstStart is null if no START_FMT entry was found before lastEnd
+        if (firstStart == nullptr) {
+            snapshot->mBegin = snapshot->mEnd;
+        } else {
+            snapshot->mBegin = FormatEntry::iterator(firstStart);
+        }
+    }
+
+    // advance fifo reader index to after last entry read.
+    mFifoReader->release(snapshot->mEnd - front);
+
+    snapshot->mLost = lost;
     return snapshot;
+
 }
 
 void NBLog::Reader::dump(int fd, size_t indent, NBLog::Reader::Snapshot &snapshot)
 {
-    NBLog::FormatEntry::iterator entry(snapshot.data() + snapshot.available());
-    NBLog::FormatEntry::iterator prevEntry = entry;
-    --prevEntry;
-    NBLog::FormatEntry::iterator start(snapshot.data());
-
+#if 0
     struct timespec ts;
     time_t maxSec = -1;
     while (entry - start >= (int) Entry::kOverhead) {
@@ -622,16 +698,18 @@
         --entry;
         --prevEntry;
     }
+#endif
     mFd = fd;
     mIndent = indent;
     String8 timestamp, body;
-    size_t lost = snapshot.lost() + (entry - start);
+    size_t lost = snapshot.lost() + (snapshot.begin() - FormatEntry::iterator(snapshot.data()));
     if (lost > 0) {
         body.appendFormat("warning: lost %zu bytes worth of events", lost);
         // TODO timestamp empty here, only other choice to wait for the first timestamp event in the
         //      log to push it out.  Consider keeping the timestamp/body between calls to readAt().
         dumpLine(timestamp, body);
     }
+#if 0
     size_t width = 1;
     while (maxSec >= 10) {
         ++width;
@@ -641,9 +719,8 @@
         timestamp.appendFormat("[%*s]", (int) width + 4, "");
     }
     bool deferredTimestamp = false;
-    NBLog::FormatEntry::iterator end(snapshot.data() + snapshot.available());
-
-    while (entry != end) {
+#endif
+    for (auto entry = snapshot.begin(); entry != snapshot.end();) {
         switch (entry->type) {
 #if 0
         case EVENT_STRING:
@@ -716,21 +793,23 @@
             break;
         case EVENT_END_FMT:
             body.appendFormat("warning: got to end format event");
+            ++entry;
             break;
         case EVENT_RESERVED:
         default:
-            body.appendFormat("warning: unknown event %d", entry->type);
+            body.appendFormat("warning: unexpected event %d", entry->type);
+            ++entry;
             break;
         }
 
         if (!body.isEmpty()) {
             dumpLine(timestamp, body);
-            deferredTimestamp = false;
+            // deferredTimestamp = false;
         }
     }
-    if (deferredTimestamp) {
-        dumpLine(timestamp, body);
-    }
+    // if (deferredTimestamp) {
+    //     dumpLine(timestamp, body);
+    // }
 }
 
 void NBLog::Reader::dump(int fd, size_t indent)
@@ -816,12 +895,6 @@
         size_t length = arg->length;
 
         // TODO check length for event type is correct
-        if (!arg.hasConsistentLength()) {
-            // TODO: corrupt, resync buffer
-            body->append("<invalid entry>");
-            ++fmt_offset;
-            continue;
-        }
 
         if (event == EVENT_END_FMT) {
             break;
@@ -909,37 +982,33 @@
 void NBLog::Merger::merge() {
     int nLogs = mNamedReaders.size();
     std::vector<std::unique_ptr<NBLog::Reader::Snapshot>> snapshots(nLogs);
+    std::vector<NBLog::FormatEntry::iterator> offsets(nLogs);
     for (int i = 0; i < nLogs; ++i) {
         snapshots[i] = mNamedReaders[i].reader()->getSnapshot();
+        offsets[i] = snapshots[i]->begin();
     }
     // initialize offsets
-    std::vector<size_t> offsets(nLogs, 0);
     // TODO custom heap implementation could allow to update top, improving performance
     // for bursty buffers
     std::priority_queue<MergeItem, std::vector<MergeItem>, std::greater<MergeItem>> timestamps;
     for (int i = 0; i < nLogs; ++i)
     {
-        if (snapshots[i]->available() > 0) {
-            timespec ts = FormatEntry(snapshots[i]->data()).timestamp();
-            MergeItem item(ts, i);
-            timestamps.push(item);
+        if (offsets[i] != snapshots[i]->end()) {
+            timespec ts = FormatEntry(offsets[i]).timestamp();
+            timestamps.emplace(ts, i);
         }
     }
 
     while (!timestamps.empty()) {
         // find minimum timestamp
         int index = timestamps.top().index;
-        // copy it to the log
-        size_t length = FormatEntry(snapshots[index]->data() + offsets[index]).copyTo(
-            mFifoWriter, index);
+        // copy it to the log, increasing offset
+        offsets[index] = FormatEntry(offsets[index]).copyWithAuthor(mFifoWriter, index);
         // update data structures
-        offsets[index] += length;
-        ALOGW_IF(offsets[index] > snapshots[index]->available(), "Overflown snapshot capacity");
         timestamps.pop();
-        if (offsets[index] != snapshots[index]->available()) {
-            timespec ts = FormatEntry(snapshots[index]->data() + offsets[index]).timestamp();
-            MergeItem item(ts, index);
-            timestamps.emplace(item);
+        if (offsets[index] != snapshots[index]->end()) {
+            timespec ts = FormatEntry(offsets[index]).timestamp();
+            timestamps.emplace(ts, index);
         }
     }
 }
@@ -958,4 +1027,42 @@
     return NBLog::Entry::kOverhead + sizeof(author);
 }
 
+NBLog::MergeThread::MergeThread(NBLog::Merger &merger)
+    : mMerger(merger),
+      mTimeoutUs(0) {}
+
+NBLog::MergeThread::~MergeThread() {
+    // set exit flag, set timeout to 0 to force threadLoop to exit and wait for the thread to join
+    requestExit();
+    setTimeoutUs(0);
+    join();
+}
+
+bool NBLog::MergeThread::threadLoop() {
+    bool doMerge;
+    {
+        AutoMutex _l(mMutex);
+        // If mTimeoutUs is negative, wait on the condition variable until it's positive.
+        // If it's positive, wait kThreadSleepPeriodUs and then merge
+        nsecs_t waitTime = mTimeoutUs > 0 ? kThreadSleepPeriodUs * 1000 : LLONG_MAX;
+        mCond.waitRelative(mMutex, waitTime);
+        doMerge = mTimeoutUs > 0;
+        mTimeoutUs -= kThreadSleepPeriodUs;
+    }
+    if (doMerge) {
+        mMerger.merge();
+    }
+    return true;
+}
+
+void NBLog::MergeThread::wakeup() {
+    setTimeoutUs(kThreadWakeupPeriodUs);
+}
+
+void NBLog::MergeThread::setTimeoutUs(int time) {
+    AutoMutex _l(mMutex);
+    mTimeoutUs = time;
+    mCond.signal();
+}
+
 }   // namespace android
diff --git a/media/libnbaio/include/NBLog.h b/media/libnbaio/include/NBLog.h
index 043f15e..7aaf298 100644
--- a/media/libnbaio/include/NBLog.h
+++ b/media/libnbaio/include/NBLog.h
@@ -20,8 +20,9 @@
 #define ANDROID_MEDIA_NBLOG_H
 
 #include <binder/IMemory.h>
-#include <utils/Mutex.h>
 #include <audio_utils/fifo.h>
+#include <utils/Mutex.h>
+#include <utils/threads.h>
 
 #include <vector>
 
@@ -41,6 +42,7 @@
 enum Event {
     EVENT_RESERVED,
     EVENT_STRING,               // ASCII string, not NUL-terminated
+    // TODO: make timestamp optional
     EVENT_TIMESTAMP,            // clock_gettime(CLOCK_MONOTONIC)
     EVENT_INTEGER,              // integer value entry
     EVENT_FLOAT,                // floating point value entry
@@ -87,6 +89,7 @@
     // entry iterator
     class iterator {
     public:
+        iterator();
         iterator(const uint8_t *entry);
         iterator(const iterator &other);
 
@@ -97,6 +100,8 @@
         iterator&       operator++(); // ++i
         // back to previous entry
         iterator&       operator--(); // --i
+        iterator        next() const;
+        iterator        prev() const;
         bool            operator!=(const iterator &other) const;
         int             operator-(const iterator &other) const;
 
@@ -106,7 +111,7 @@
 
         template<typename T>
         inline const T& payload() {
-            return *reinterpret_cast<const T *>(ptr + 2);
+            return *reinterpret_cast<const T *>(ptr + offsetof(entry, data));
         }
 
     private:
@@ -132,7 +137,7 @@
     int         author() const;
 
     // copy entry, adding author before timestamp, returns size of original entry
-    size_t      copyTo(std::unique_ptr<audio_utils_fifo_writer> &dst, int author) const;
+    iterator    copyWithAuthor(std::unique_ptr<audio_utils_fifo_writer> &dst, int author) const;
 
     iterator    begin() const;
 
@@ -315,26 +320,32 @@
     // A snapshot of a readers buffer
     class Snapshot {
     public:
-        Snapshot() : mData(NULL), mAvail(0), mLost(0) {}
+        Snapshot() : mData(NULL), mLost(0) {}
 
         Snapshot(size_t bufferSize) : mData(new uint8_t[bufferSize]) {}
 
         ~Snapshot() { delete[] mData; }
 
         // copy of the buffer
-        const uint8_t *data() const { return mData; }
-
-        // amount of data available (given by audio_utils_fifo_reader)
-        size_t   available() const { return mAvail; }
+        uint8_t *data() const { return mData; }
 
         // amount of data lost (given by audio_utils_fifo_reader)
         size_t   lost() const { return mLost; }
 
+        // iterator to beginning of readable segment of snapshot
+        // data between begin and end has valid entries
+        FormatEntry::iterator begin() { return mBegin; }
+
+        // iterator to end of readable segment of snapshot
+        FormatEntry::iterator end() { return mEnd; }
+
+
     private:
         friend class Reader;
-        const uint8_t *mData;
-        size_t         mAvail;
-        size_t         mLost;
+        uint8_t              *mData;
+        size_t                mLost;
+        FormatEntry::iterator mBegin;
+        FormatEntry::iterator mEnd;
     };
 
     // Input parameter 'size' is the desired size of the timeline in byte units.
@@ -371,6 +382,10 @@
     // dummy method for handling absent author entry
     virtual size_t handleAuthor(const FormatEntry &fmtEntry, String8 *body) { return 0; }
 
+    // Searches for the last entry of type <type> in the range [front, back)
+    // back has to be entry-aligned. Returns nullptr if none enconuntered.
+    static uint8_t *findLastEntryOfType(uint8_t *front, uint8_t *back, uint8_t type);
+
     static const size_t kSquashTimestamp = 5; // squash this many or more adjacent timestamps
 };
 
@@ -425,6 +440,43 @@
     size_t handleAuthor(const FormatEntry &fmtEntry, String8 *body);
 };
 
+// MergeThread is a thread that contains a Merger. It works as a retriggerable one-shot:
+// when triggered, it awakes for a lapse of time, during which it periodically merges; if
+// retriggered, the timeout is reset.
+// The thread is triggered on AudioFlinger binder activity.
+class MergeThread : public Thread {
+public:
+    MergeThread(Merger &merger);
+    virtual ~MergeThread() override;
+
+    // Reset timeout and activate thread to merge periodically if it's idle
+    void wakeup();
+
+    // Set timeout period until the merging thread goes idle again
+    void setTimeoutUs(int time);
+
+private:
+    virtual bool threadLoop() override;
+
+    // the merger who actually does the work of merging the logs
+    Merger&     mMerger;
+
+    // mutex for the condition variable
+    Mutex       mMutex;
+
+    // condition variable to activate merging on timeout >= 0
+    Condition   mCond;
+
+    // time left until the thread blocks again (in microseconds)
+    int         mTimeoutUs;
+
+    // merging period when the thread is awake
+    static const int  kThreadSleepPeriodUs = 1000000 /*1s*/;
+
+    // initial timeout value when triggered
+    static const int  kThreadWakeupPeriodUs = 3000000 /*3s*/;
+};
+
 };  // class NBLog
 
 }   // namespace android
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index de5ea9c..1d2a931 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -701,7 +701,13 @@
             }
 
             ++sampleIndex;
-            sampleTime += delta;
+            if (sampleTime > UINT32_MAX - delta) {
+                ALOGE("%u + %u would overflow, clamping",
+                    sampleTime, delta);
+                sampleTime = UINT32_MAX;
+            } else {
+                sampleTime += delta;
+            }
         }
     }
 
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index 4f1ef30..d0d82b3 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -29,7 +29,6 @@
 #include <ui/GraphicBuffer.h>
 #include <gui/BufferItem.h>
 #include <gui/ISurfaceComposer.h>
-#include <gui/IGraphicBufferAlloc.h>
 #include <OMX_Component.h>
 
 #include <utils/Log.h>
diff --git a/media/libstagefright/include/SurfaceMediaSource.h b/media/libstagefright/include/SurfaceMediaSource.h
index ca3a3bf..ae19a75 100644
--- a/media/libstagefright/include/SurfaceMediaSource.h
+++ b/media/libstagefright/include/SurfaceMediaSource.h
@@ -32,7 +32,6 @@
 namespace android {
 // ----------------------------------------------------------------------------
 
-class IGraphicBufferAlloc;
 class String8;
 class GraphicBuffer;
 
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index f70f13b..9cba3d0 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -4,6 +4,7 @@
 LOCAL_SRC_FILES:=                     \
         FrameDropper.cpp              \
         GraphicBufferSource.cpp       \
+        BWGraphicBufferSource.cpp      \
         OMX.cpp                       \
         OMXMaster.cpp                 \
         OMXNodeInstance.cpp           \
diff --git a/media/libstagefright/omx/BWGraphicBufferSource.cpp b/media/libstagefright/omx/BWGraphicBufferSource.cpp
new file mode 100644
index 0000000..4e0f6dd
--- /dev/null
+++ b/media/libstagefright/omx/BWGraphicBufferSource.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "BWGraphicBufferSource"
+
+#include <OMX_Component.h>
+#include <OMX_IndexExt.h>
+
+#include <media/OMXBuffer.h>
+#include <IOMX.h>
+
+#include "OMXUtils.h"
+#include "BWGraphicBufferSource.h"
+
+namespace android {
+
+static const OMX_U32 kPortIndexInput = 0;
+
+struct BWGraphicBufferSource::BWOmxNodeWrapper : public IOmxNodeWrapper {
+    sp<IOMXNode> mOMXNode;
+
+    BWOmxNodeWrapper(const sp<IOMXNode> &omxNode): mOMXNode(omxNode) {
+    }
+
+    virtual status_t emptyBuffer(
+            int32_t bufferId, uint32_t flags,
+            const sp<GraphicBuffer> &buffer,
+            int64_t timestamp, int fenceFd) override {
+        return mOMXNode->emptyBuffer(bufferId, buffer, flags, timestamp, fenceFd);
+    }
+
+    virtual void dispatchDataSpaceChanged(
+            int32_t dataSpace, int32_t aspects, int32_t pixelFormat) override {
+        omx_message msg;
+        msg.type = omx_message::EVENT;
+        msg.fenceFd = -1;
+        msg.u.event_data.event = OMX_EventDataSpaceChanged;
+        msg.u.event_data.data1 = dataSpace;
+        msg.u.event_data.data2 = aspects;
+        msg.u.event_data.data3 = pixelFormat;
+        mOMXNode->dispatchMessage(msg);
+    }
+};
+
+struct BWGraphicBufferSource::BWOMXBufferSource : public BnOMXBufferSource {
+    sp<GraphicBufferSource> mSource;
+
+    BWOMXBufferSource(const sp<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.get());
+    }
+};
+
+BWGraphicBufferSource::BWGraphicBufferSource(
+        sp<GraphicBufferSource> const& base) :
+    mBase(base),
+    mOMXBufferSource(new BWOMXBufferSource(base)) {
+}
+
+::android::binder::Status BWGraphicBufferSource::configure(
+        const sp<IOMXNode>& omxNode, int32_t dataSpace) {
+    // 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(mOMXBufferSource);
+    if (err != NO_ERROR) {
+        ALOGE("Unable to set input surface: %d", err);
+        return Status::fromStatusT(err);
+    }
+
+    // use consumer usage bits queried from encoder, but always add
+    // HW_VIDEO_ENCODER for backward compatibility.
+    uint32_t consumerUsage;
+    if (omxNode->getParameter(
+            (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
+            &consumerUsage, sizeof(consumerUsage)) != OK) {
+        consumerUsage = 0;
+    }
+
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    InitOMXParams(&def);
+    def.nPortIndex = kPortIndexInput;
+
+    err = omxNode->getParameter(
+            OMX_IndexParamPortDefinition, &def, sizeof(def));
+    if (err != NO_ERROR) {
+        ALOGE("Failed to get port definition: %d", err);
+        return Status::fromStatusT(UNKNOWN_ERROR);
+    }
+
+    return Status::fromStatusT(mBase->configure(
+              new BWOmxNodeWrapper(omxNode),
+              dataSpace,
+              def.nBufferCountActual,
+              def.format.video.nFrameWidth,
+              def.format.video.nFrameHeight,
+              consumerUsage));
+}
+
+::android::binder::Status BWGraphicBufferSource::setSuspend(
+        bool suspend, int64_t timeUs) {
+    return Status::fromStatusT(mBase->setSuspend(suspend, timeUs));
+}
+
+::android::binder::Status BWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
+        int64_t repeatAfterUs) {
+    return Status::fromStatusT(mBase->setRepeatPreviousFrameDelayUs(repeatAfterUs));
+}
+
+::android::binder::Status BWGraphicBufferSource::setMaxFps(float maxFps) {
+    return Status::fromStatusT(mBase->setMaxFps(maxFps));
+}
+
+::android::binder::Status BWGraphicBufferSource::setTimeLapseConfig(
+        int64_t timePerFrameUs, int64_t timePerCaptureUs) {
+    return Status::fromStatusT(mBase->setTimeLapseConfig(
+            timePerFrameUs, timePerCaptureUs));
+}
+
+::android::binder::Status BWGraphicBufferSource::setStartTimeUs(
+        int64_t startTimeUs) {
+    return Status::fromStatusT(mBase->setStartTimeUs(startTimeUs));
+}
+
+::android::binder::Status BWGraphicBufferSource::setStopTimeUs(
+        int64_t stopTimeUs) {
+    return Status::fromStatusT(mBase->setStopTimeUs(stopTimeUs));
+}
+
+::android::binder::Status BWGraphicBufferSource::setColorAspects(
+        int32_t aspects) {
+    return Status::fromStatusT(mBase->setColorAspects(aspects));
+}
+
+::android::binder::Status BWGraphicBufferSource::setTimeOffsetUs(
+        int64_t timeOffsetsUs) {
+    return Status::fromStatusT(mBase->setTimeOffsetUs(timeOffsetsUs));
+}
+
+::android::binder::Status BWGraphicBufferSource::signalEndOfInputStream() {
+    return Status::fromStatusT(mBase->signalEndOfInputStream());
+}
+
+}  // namespace android
diff --git a/media/libstagefright/omx/BWGraphicBufferSource.h b/media/libstagefright/omx/BWGraphicBufferSource.h
new file mode 100644
index 0000000..f1ce2af
--- /dev/null
+++ b/media/libstagefright/omx/BWGraphicBufferSource.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BWGRAPHIC_BUFFER_SOURCE_H_
+#define BWGRAPHIC_BUFFER_SOURCE_H_
+
+#include <binder/Binder.h>
+#include <binder/Status.h>
+#include <android/BnGraphicBufferSource.h>
+#include <android/BnOMXBufferSource.h>
+#include <IOMX.h>
+
+#include "GraphicBufferSource.h"
+#include "IOmxNodeWrapper.h"
+
+namespace android {
+
+using ::android::binder::Status;
+using ::android::BnGraphicBufferSource;
+using ::android::GraphicBufferSource;
+using ::android::IOMXNode;
+using ::android::sp;
+
+struct BWGraphicBufferSource : public BnGraphicBufferSource {
+    struct BWOMXBufferSource;
+    struct BWOmxNodeWrapper;
+
+    sp<GraphicBufferSource> mBase;
+    sp<IOMXBufferSource> mOMXBufferSource;
+
+    BWGraphicBufferSource(sp<GraphicBufferSource> const &base);
+
+    Status configure(
+            const sp<IOMXNode>& omxNode, int32_t dataSpace) override;
+    Status setSuspend(bool suspend, int64_t timeUs) override;
+    Status setRepeatPreviousFrameDelayUs(
+            int64_t repeatAfterUs) override;
+    Status setMaxFps(float maxFps) override;
+    Status setTimeLapseConfig(
+            int64_t timePerFrameUs, int64_t timePerCaptureUs) override;
+    Status setStartTimeUs(int64_t startTimeUs) override;
+    Status setStopTimeUs(int64_t stopTimeUs) override;
+    Status setColorAspects(int32_t aspects) override;
+    Status setTimeOffsetUs(int64_t timeOffsetsUs) override;
+    Status signalEndOfInputStream() override;
+};
+
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_MEDIA_OMX_V1_0_WGRAPHICBUFFERSOURCE_H
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 2f457ac..793ecb8 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -41,37 +41,6 @@
 
 namespace android {
 
-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),
@@ -97,8 +66,7 @@
     mTimePerFrameUs(-1ll),
     mPrevCaptureUs(-1ll),
     mPrevFrameUs(-1ll),
-    mInputBufferTimeOffsetUs(0ll),
-    mOmxBufferSource(new OmxBufferSource(this)) {
+    mInputBufferTimeOffsetUs(0ll) {
     ALOGV("GraphicBufferSource");
 
     String8 name("GraphicBufferSource");
@@ -122,7 +90,7 @@
         return;
     }
 
-    memset(&mColorAspects, 0, sizeof(mColorAspects));
+    memset(&mColorAspectsPacked, 0, sizeof(mColorAspectsPacked));
 
     CHECK(mInitCheck == NO_ERROR);
 }
@@ -273,9 +241,7 @@
 }
 
 Status GraphicBufferSource::onInputBufferEmptied(
-        int32_t bufferID, const OMXFenceParcelable &fenceParcel) {
-    int fenceFd = fenceParcel.get();
-
+        int32_t bufferID, int fenceFd) {
     Mutex::Autolock autoLock(mMutex);
     if (!mExecuting) {
         if (fenceFd >= 0) {
@@ -374,15 +340,7 @@
     mLastDataSpace = dataSpace;
 
     if (ColorUtils::convertDataSpaceToV0(dataSpace)) {
-        omx_message msg;
-        msg.type = omx_message::EVENT;
-        msg.fenceFd = -1;
-        msg.u.event_data.event = OMX_EventDataSpaceChanged;
-        msg.u.event_data.data1 = mLastDataSpace;
-        msg.u.event_data.data2 = ColorUtils::packToU32(mColorAspects);
-        msg.u.event_data.data3 = pixelFormat;
-
-        mOMXNode->dispatchMessage(msg);
+        mOMXNode->dispatchDataSpaceChanged(mLastDataSpace, mColorAspectsPacked, pixelFormat);
     }
 }
 
@@ -689,7 +647,7 @@
     int fenceID = item.mFence->isValid() ? item.mFence->dup() : -1;
 
     status_t err = mOMXNode->emptyBuffer(
-            bufferID, buffer, OMX_BUFFERFLAG_ENDOFFRAME, codecTimeUs, fenceID);
+            bufferID, OMX_BUFFERFLAG_ENDOFFRAME, buffer, codecTimeUs, fenceID);
 
     if (err != OK) {
         ALOGW("WARNING: emptyGraphicBuffer failed: 0x%x", err);
@@ -721,10 +679,8 @@
     CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
     IOMX::buffer_id bufferID = codecBuffer.mBufferID;
 
-    status_t err = mOMXNode->emptyBuffer(
-            bufferID, (sp<GraphicBuffer>)NULL,
-            OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS,
-            0 /* timestamp */, -1 /* fenceFd */);
+    status_t err = mOMXNode->emptyBuffer(bufferID,
+            OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS);
     if (err != OK) {
         ALOGW("emptyDirectBuffer EOS failed: 0x%x", err);
     } else {
@@ -865,65 +821,38 @@
     ALOG_ASSERT(false, "GraphicBufferSource can't consume sideband streams");
 }
 
-Status GraphicBufferSource::configure(
-        const sp<IOMXNode>& omxNode, int32_t dataSpace) {
+status_t GraphicBufferSource::configure(
+        const sp<IOmxNodeWrapper>& omxNode,
+        int32_t dataSpace,
+        int32_t bufferCount,
+        uint32_t frameWidth,
+        uint32_t frameHeight,
+        uint32_t consumerUsage) {
     if (omxNode == NULL) {
-        return Status::fromServiceSpecificError(BAD_VALUE);
+        return BAD_VALUE;
     }
 
-    // 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(mOmxBufferSource);
-    if (err != NO_ERROR) {
-        ALOGE("Unable to set input surface: %d", err);
-        return Status::fromServiceSpecificError(err);
-    }
-
-    // use consumer usage bits queried from encoder, but always add
-    // HW_VIDEO_ENCODER for backward compatibility.
-    uint32_t consumerUsage;
-    if (omxNode->getParameter(
-            (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
-            &consumerUsage, sizeof(consumerUsage)) != OK) {
-        consumerUsage = 0;
-    }
-
-    OMX_PARAM_PORTDEFINITIONTYPE def;
-    InitOMXParams(&def);
-    def.nPortIndex = kPortIndexInput;
-
-    err = omxNode->getParameter(
-            OMX_IndexParamPortDefinition, &def, sizeof(def));
-    if (err != NO_ERROR) {
-        ALOGE("Failed to get port definition: %d", err);
-        return Status::fromServiceSpecificError(UNKNOWN_ERROR);
-    }
 
     // Call setMaxAcquiredBufferCount without lock.
     // setMaxAcquiredBufferCount could call back to onBuffersReleased
     // if the buffer count change results in releasing of existing buffers,
     // which would lead to deadlock.
-    err = mConsumer->setMaxAcquiredBufferCount(def.nBufferCountActual);
+    status_t err = mConsumer->setMaxAcquiredBufferCount(bufferCount);
     if (err != NO_ERROR) {
         ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
-                def.nBufferCountActual, err);
-        return Status::fromServiceSpecificError(err);
+                bufferCount, err);
+        return err;
     }
 
     {
         Mutex::Autolock autoLock(mMutex);
         mOMXNode = omxNode;
 
-        err = mConsumer->setDefaultBufferSize(
-                def.format.video.nFrameWidth,
-                def.format.video.nFrameHeight);
+        err = mConsumer->setDefaultBufferSize(frameWidth, frameHeight);
         if (err != NO_ERROR) {
             ALOGE("Unable to set BQ default buffer size to %ux%u: %d",
-                    def.format.video.nFrameWidth,
-                    def.format.video.nFrameHeight,
-                    err);
-            return Status::fromServiceSpecificError(err);
+                    frameWidth, frameHeight, err);
+            return err;
         }
 
         consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
@@ -957,17 +886,17 @@
         mActionQueue.clear();
     }
 
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::setSuspend(bool suspend, int64_t suspendStartTimeUs) {
+status_t GraphicBufferSource::setSuspend(bool suspend, int64_t suspendStartTimeUs) {
     ALOGV("setSuspend=%d at time %lld us", suspend, (long long)suspendStartTimeUs);
 
     Mutex::Autolock autoLock(mMutex);
 
     if (mStopTimeUs != -1) {
         ALOGE("setSuspend failed as STOP action is pending");
-        return Status::fromServiceSpecificError(INVALID_OPERATION);
+        return INVALID_OPERATION;
     }
 
     // Push the action to the queue.
@@ -977,12 +906,12 @@
         if (suspendStartTimeUs > currentSystemTimeUs) {
             ALOGE("setSuspend failed. %lld is larger than current system time %lld us",
                     (long long)suspendStartTimeUs, (long long)currentSystemTimeUs);
-            return Status::fromServiceSpecificError(INVALID_OPERATION);
+            return INVALID_OPERATION;
         }
         if (mLastActionTimeUs != -1 && suspendStartTimeUs < mLastActionTimeUs) {
             ALOGE("setSuspend failed. %lld is smaller than last action time %lld us",
                     (long long)suspendStartTimeUs, (long long)mLastActionTimeUs);
-            return Status::fromServiceSpecificError(INVALID_OPERATION);
+            return INVALID_OPERATION;
         }
         mLastActionTimeUs = suspendStartTimeUs;
         ActionItem action;
@@ -1007,7 +936,7 @@
 
                 releaseBuffer(item.mSlot, item.mFrameNumber, item.mFence);
             }
-            return Status::ok();
+            return OK;
         } else {
 
             mSuspended = false;
@@ -1023,54 +952,54 @@
             }
         }
     }
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) {
+status_t GraphicBufferSource::setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) {
     ALOGV("setRepeatPreviousFrameDelayUs: delayUs=%lld", (long long)repeatAfterUs);
 
     Mutex::Autolock autoLock(mMutex);
 
     if (mExecuting || repeatAfterUs <= 0ll) {
-        return Status::fromServiceSpecificError(INVALID_OPERATION);
+        return INVALID_OPERATION;
     }
 
     mRepeatAfterUs = repeatAfterUs;
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
+status_t GraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
     Mutex::Autolock autoLock(mMutex);
 
     // timeOffsetUs must be negative for adjustment.
     if (timeOffsetUs >= 0ll) {
-        return Status::fromServiceSpecificError(INVALID_OPERATION);
+        return INVALID_OPERATION;
     }
 
     mInputBufferTimeOffsetUs = timeOffsetUs;
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::setMaxFps(float maxFps) {
+status_t GraphicBufferSource::setMaxFps(float maxFps) {
     ALOGV("setMaxFps: maxFps=%lld", (long long)maxFps);
 
     Mutex::Autolock autoLock(mMutex);
 
     if (mExecuting) {
-        return Status::fromServiceSpecificError(INVALID_OPERATION);
+        return INVALID_OPERATION;
     }
 
     mFrameDropper = new FrameDropper();
     status_t err = mFrameDropper->setMaxFrameRate(maxFps);
     if (err != OK) {
         mFrameDropper.clear();
-        return Status::fromServiceSpecificError(err);
+        return err;
     }
 
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::setStartTimeUs(int64_t skipFramesBeforeUs) {
+status_t GraphicBufferSource::setStartTimeUs(int64_t skipFramesBeforeUs) {
     ALOGV("setStartTimeUs: skipFramesBeforeUs=%lld", (long long)skipFramesBeforeUs);
 
     Mutex::Autolock autoLock(mMutex);
@@ -1078,16 +1007,16 @@
     mSkipFramesBeforeNs =
             (skipFramesBeforeUs > 0) ? (skipFramesBeforeUs * 1000) : -1ll;
 
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) {
+status_t GraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) {
     ALOGV("setStopTimeUs: %lld us", (long long)stopTimeUs);
     Mutex::Autolock autoLock(mMutex);
 
     if (mStopTimeUs != -1) {
         // Ignore if stop time has already been set
-        return Status::ok();
+        return OK;
     }
 
     // stopTimeUs must be smaller or equal to current systemTime.
@@ -1095,12 +1024,12 @@
     if (stopTimeUs > currentSystemTimeUs) {
         ALOGE("setStopTimeUs failed. %lld is larger than current system time %lld us",
             (long long)stopTimeUs, (long long)currentSystemTimeUs);
-        return Status::fromServiceSpecificError(INVALID_OPERATION);
+        return INVALID_OPERATION;
     }
     if (mLastActionTimeUs != -1 && stopTimeUs < mLastActionTimeUs) {
         ALOGE("setSuspend failed. %lld is smaller than last action time %lld us",
             (long long)stopTimeUs, (long long)mLastActionTimeUs);
-        return Status::fromServiceSpecificError(INVALID_OPERATION);
+        return INVALID_OPERATION;
     }
     mLastActionTimeUs = stopTimeUs;
     ActionItem action;
@@ -1108,45 +1037,46 @@
     action.mActionTimeUs = stopTimeUs;
     mActionQueue.push_back(action);
     mStopTimeUs = stopTimeUs;
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::setTimeLapseConfig(int64_t timePerFrameUs, int64_t timePerCaptureUs) {
+status_t GraphicBufferSource::setTimeLapseConfig(int64_t timePerFrameUs, int64_t timePerCaptureUs) {
     ALOGV("setTimeLapseConfig: timePerFrameUs=%lld, timePerCaptureUs=%lld",
             (long long)timePerFrameUs, (long long)timePerCaptureUs);
 
     Mutex::Autolock autoLock(mMutex);
 
     if (mExecuting || timePerFrameUs <= 0ll || timePerCaptureUs <= 0ll) {
-        return Status::fromServiceSpecificError(INVALID_OPERATION);
+        return INVALID_OPERATION;
     }
 
     mTimePerFrameUs = timePerFrameUs;
     mTimePerCaptureUs = timePerCaptureUs;
 
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::setColorAspects(int32_t aspectsPacked) {
+status_t GraphicBufferSource::setColorAspects(int32_t aspectsPacked) {
     Mutex::Autolock autoLock(mMutex);
-    mColorAspects = ColorUtils::unpackToColorAspects(aspectsPacked);
+    mColorAspectsPacked = aspectsPacked;
+    ColorAspects colorAspects = ColorUtils::unpackToColorAspects(aspectsPacked);
     ALOGD("requesting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s))",
-            mColorAspects.mRange, asString(mColorAspects.mRange),
-            mColorAspects.mPrimaries, asString(mColorAspects.mPrimaries),
-            mColorAspects.mMatrixCoeffs, asString(mColorAspects.mMatrixCoeffs),
-            mColorAspects.mTransfer, asString(mColorAspects.mTransfer));
+            colorAspects.mRange, asString(colorAspects.mRange),
+            colorAspects.mPrimaries, asString(colorAspects.mPrimaries),
+            colorAspects.mMatrixCoeffs, asString(colorAspects.mMatrixCoeffs),
+            colorAspects.mTransfer, asString(colorAspects.mTransfer));
 
-    return Status::ok();
+    return OK;
 }
 
-Status GraphicBufferSource::signalEndOfInputStream() {
+status_t GraphicBufferSource::signalEndOfInputStream() {
     Mutex::Autolock autoLock(mMutex);
     ALOGV("signalEndOfInputStream: exec=%d avail=%zu eos=%d",
             mExecuting, mNumFramesAvailable, mEndOfStream);
 
     if (mEndOfStream) {
         ALOGE("EOS was already signaled");
-        return Status::fromStatusT(INVALID_OPERATION);
+        return INVALID_OPERATION;
     }
 
     // Set the end-of-stream flag.  If no frames are pending from the
@@ -1163,7 +1093,7 @@
         submitEndOfInputStream_l();
     }
 
-    return Status::ok();
+    return OK;
 }
 
 void GraphicBufferSource::onMessageReceived(const sp<AMessage> &msg) {
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h
index 475548e..371c5ed 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/GraphicBufferSource.h
@@ -32,6 +32,8 @@
 #include <android/BnGraphicBufferSource.h>
 #include <android/BnOMXBufferSource.h>
 
+#include "IOmxNodeWrapper.h"
+
 namespace android {
 
 using ::android::binder::Status;
@@ -54,8 +56,7 @@
  * before the codec is in the "executing" state, so we need to queue
  * things up until we're ready to go.
  */
-class GraphicBufferSource : public BnGraphicBufferSource,
-                            public BufferQueue::ConsumerListener {
+class GraphicBufferSource : public BufferQueue::ConsumerListener {
 public:
     GraphicBufferSource();
 
@@ -95,24 +96,30 @@
     // 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);
+            int32_t bufferID, int fenceFd);
 
     // Configure the buffer source to be used with an OMX node with the default
     // data space.
-    Status configure(const sp<IOMXNode>& omxNode, int32_t dataSpace) override;
+    status_t configure(
+        const sp<IOmxNodeWrapper> &omxNode,
+        int32_t dataSpace,
+        int32_t bufferCount,
+        uint32_t frameWidth,
+        uint32_t frameHeight,
+        uint32_t consumerUsage);
 
     // This is called after the last input frame has been submitted or buffer
     // timestamp is greater or equal than stopTimeUs. We need to submit an empty
     // buffer with the EOS flag set.  If we don't have a codec buffer ready,
     // we just set the mEndOfStream flag.
-    Status signalEndOfInputStream() override;
+    status_t signalEndOfInputStream();
 
     // If suspend is true, all incoming buffers (including those currently
     // in the BufferQueue) with timestamp larger than timeUs will be discarded
     // until the suspension is lifted. If suspend is false, all incoming buffers
     // including those currently in the BufferQueue) with timestamp larger than
     // timeUs will be processed. timeUs uses SYSTEM_TIME_MONOTONIC time base.
-    Status setSuspend(bool suspend, int64_t timeUs) override;
+    status_t setSuspend(bool suspend, int64_t timeUs);
 
     // Specifies the interval after which we requeue the buffer previously
     // queued to the encoder. This is useful in the case of surface flinger
@@ -121,30 +128,30 @@
     // the decoder on the remote end would be unable to decode the latest frame.
     // This API must be called before transitioning the encoder to "executing"
     // state and once this behaviour is specified it cannot be reset.
-    Status setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) override;
+    status_t setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs);
 
     // Sets the input buffer timestamp offset.
     // When set, the sample's timestamp will be adjusted with the timeOffsetUs.
-    Status setTimeOffsetUs(int64_t timeOffsetUs) override;
+    status_t setTimeOffsetUs(int64_t timeOffsetUs);
 
     // When set, the max frame rate fed to the encoder will be capped at maxFps.
-    Status setMaxFps(float maxFps) override;
+    status_t setMaxFps(float maxFps);
 
     // Sets the time lapse (or slow motion) parameters.
     // When set, the sample's timestamp will be modified to playback framerate,
     // and capture timestamp will be modified to capture rate.
-    Status setTimeLapseConfig(int64_t timePerFrameUs, int64_t timePerCaptureUs) override;
+    status_t setTimeLapseConfig(int64_t timePerFrameUs, int64_t timePerCaptureUs);
 
     // Sets the start time us (in system time), samples before which should
     // be dropped and not submitted to encoder
-    Status setStartTimeUs(int64_t startTimeUs) override;
+    status_t setStartTimeUs(int64_t startTimeUs);
 
     // Sets the stop time us (in system time), samples after which should be dropped
     // and not submitted to encoder. timeUs uses SYSTEM_TIME_MONOTONIC time base.
-    Status setStopTimeUs(int64_t stopTimeUs) override;
+    status_t setStopTimeUs(int64_t stopTimeUs);
 
     // Sets the desired color aspects, e.g. to be used when producer does not specify a dataspace.
-    Status setColorAspects(int32_t aspectsPacked) override;
+    status_t setColorAspects(int32_t aspectsPacked);
 
 protected:
     // BufferQueue::ConsumerListener interface, called when a new frame of
@@ -229,8 +236,8 @@
     // Used to report constructor failure.
     status_t mInitCheck;
 
-    // Pointer back to the IOMXNode that created us.  We send buffers here.
-    sp<IOMXNode> mOMXNode;
+    // Pointer back to the Omx node that created us.  We send buffers here.
+    sp<IOmxNodeWrapper> mOMXNode;
 
     // Set by omxExecuting() / omxIdling().
     bool mExecuting;
@@ -328,10 +335,7 @@
 
     int64_t mInputBufferTimeOffsetUs;
 
-    ColorAspects mColorAspects;
-
-    class OmxBufferSource;
-    sp<OmxBufferSource> mOmxBufferSource;
+    int32_t mColorAspectsPacked;
 
     void onMessageReceived(const sp<AMessage> &msg);
 
diff --git a/media/libstagefright/omx/IOmxNodeWrapper.h b/media/libstagefright/omx/IOmxNodeWrapper.h
new file mode 100644
index 0000000..cd44e67
--- /dev/null
+++ b/media/libstagefright/omx/IOmxNodeWrapper.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IOMX_NODE_WRAPPER_SOURCE_H_
+#define IOMX_NODE_WRAPPER_SOURCE_H_
+
+#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
+#include <ui/GraphicBuffer.h>
+
+#include <stdint.h>
+
+namespace android {
+
+struct IOmxNodeWrapper : public RefBase {
+    virtual status_t emptyBuffer(
+            int32_t bufferId, uint32_t flags,
+            const sp<GraphicBuffer> &buffer = nullptr,
+            int64_t timestamp = 0, int fenceFd = -1) = 0;
+    virtual void dispatchDataSpaceChanged(
+            int32_t dataSpace, int32_t aspects, int32_t pixelFormat) = 0;
+};
+
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_MEDIA_OMX_V1_0_WGRAPHICBUFFERSOURCE_H
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 80c125c..bf1418f 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -27,7 +27,7 @@
 #include "../include/OMXNodeInstance.h"
 
 #include <media/stagefright/foundation/ADebug.h>
-#include "GraphicBufferSource.h"
+#include "BWGraphicBufferSource.h"
 
 #include "OMXMaster.h"
 #include "OMXUtils.h"
@@ -174,7 +174,7 @@
     }
 
     *bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
-    *bufferSource = graphicBufferSource;
+    *bufferSource = new BWGraphicBufferSource(graphicBufferSource);
 
     return OK;
 }
diff --git a/media/libstagefright/omx/hal/1.0/impl/Android.mk b/media/libstagefright/omx/hal/1.0/impl/Android.mk
index 09424b5..79cb1fa 100644
--- a/media/libstagefright/omx/hal/1.0/impl/Android.mk
+++ b/media/libstagefright/omx/hal/1.0/impl/Android.mk
@@ -4,7 +4,6 @@
 LOCAL_MODULE := android.hardware.media.omx@1.0-impl
 LOCAL_SRC_FILES := \
     WGraphicBufferSource.cpp \
-    WOmx.cpp \
     WOmxBufferProducer.cpp \
     WOmxBufferSource.cpp \
     WOmxNode.cpp \
diff --git a/media/libstagefright/omx/hal/1.0/impl/Conversion.h b/media/libstagefright/omx/hal/1.0/impl/Conversion.h
index 117d1c8..a6fed2e 100644
--- a/media/libstagefright/omx/hal/1.0/impl/Conversion.h
+++ b/media/libstagefright/omx/hal/1.0/impl/Conversion.h
@@ -611,6 +611,37 @@
 }
 
 /**
+ * \brief Wrap `GraphicBuffer` in `CodecBuffer`.
+ *
+ * \param[out] t The wrapper of type `CodecBuffer`.
+ * \param[in] l The source `GraphicBuffer`.
+ */
+// wrap: OMXBuffer -> CodecBuffer
+inline CodecBuffer *wrapAs(CodecBuffer *t, sp<GraphicBuffer> const& graphicBuffer) {
+    t->sharedMemory = hidl_memory();
+    t->nativeHandle = hidl_handle();
+    t->type = CodecBuffer::Type::ANW_BUFFER;
+    if (graphicBuffer == 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;
+        return t;
+    }
+    t->attr.anwBuffer.width = graphicBuffer->getWidth();
+    t->attr.anwBuffer.height = graphicBuffer->getHeight();
+    t->attr.anwBuffer.stride = graphicBuffer->getStride();
+    t->attr.anwBuffer.format = static_cast<PixelFormat>(
+            graphicBuffer->getPixelFormat());
+    t->attr.anwBuffer.layerCount = graphicBuffer->getLayerCount();
+    t->attr.anwBuffer.usage = graphicBuffer->getUsage();
+    t->nativeHandle = graphicBuffer->handle;
+    return t;
+}
+
+/**
  * \brief Wrap `OMXBuffer` in `CodecBuffer`.
  *
  * \param[out] t The wrapper of type `CodecBuffer`.
@@ -642,24 +673,7 @@
             return false;
         }
         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;
-                return true;
-            }
-            t->attr.anwBuffer.width = l.mGraphicBuffer->getWidth();
-            t->attr.anwBuffer.height = l.mGraphicBuffer->getHeight();
-            t->attr.anwBuffer.stride = l.mGraphicBuffer->getStride();
-            t->attr.anwBuffer.format = static_cast<PixelFormat>(
-                    l.mGraphicBuffer->getPixelFormat());
-            t->attr.anwBuffer.layerCount = l.mGraphicBuffer->getLayerCount();
-            t->attr.anwBuffer.usage = l.mGraphicBuffer->getUsage();
-            t->nativeHandle = l.mGraphicBuffer->handle;
+            wrapAs(t, l.mGraphicBuffer);
             return true;
         }
         case OMXBuffer::kBufferTypeNativeHandle: {
diff --git a/media/libstagefright/omx/hal/1.0/impl/Omx.cpp b/media/libstagefright/omx/hal/1.0/impl/Omx.cpp
index a9f29e9..0ef7c8c 100644
--- a/media/libstagefright/omx/hal/1.0/impl/Omx.cpp
+++ b/media/libstagefright/omx/hal/1.0/impl/Omx.cpp
@@ -123,7 +123,6 @@
 
 Return<void> Omx::createInputSurface(createInputSurface_cb _hidl_cb) {
     sp<::android::IGraphicBufferProducer> bufferProducer;
-    sp<::android::IGraphicBufferSource> bufferSource;
 
     sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource();
     status_t err = graphicBufferSource->initCheck();
@@ -135,11 +134,10 @@
         return Void();
     }
     bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
-    bufferSource = graphicBufferSource;
 
     _hidl_cb(toStatus(OK),
             new TWOmxBufferProducer(bufferProducer),
-            new TWGraphicBufferSource(bufferSource));
+            new TWGraphicBufferSource(graphicBufferSource));
     return Void();
 }
 
diff --git a/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.cpp b/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.cpp
index 884e87b..3c2face 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.cpp
+++ b/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.cpp
@@ -14,8 +14,15 @@
  * limitations under the License.
  */
 
-#include <stagefright/foundation/ColorUtils.h>
+//#define LOG_NDEBUG 0
+#define LOG_TAG "TWGraphicBufferSource"
 
+#include <android/hardware/media/omx/1.0/IOmxBufferSource.h>
+#include <android/hardware/media/omx/1.0/IOmxNode.h>
+#include <OMX_Component.h>
+#include <OMX_IndexExt.h>
+
+#include "omx/OMXUtils.h"
 #include "WGraphicBufferSource.h"
 #include "WOmxNode.h"
 #include "Conversion.h"
@@ -27,122 +34,187 @@
 namespace V1_0 {
 namespace implementation {
 
-using android::ColorUtils;
+static const OMX_U32 kPortIndexInput = 0;
 
-// LWGraphicBufferSource
-LWGraphicBufferSource::LWGraphicBufferSource(
-        sp<TGraphicBufferSource> const& base) : mBase(base) {
-}
+struct TWGraphicBufferSource::TWOmxNodeWrapper : public IOmxNodeWrapper {
+    sp<IOmxNode> mOmxNode;
 
-::android::binder::Status LWGraphicBufferSource::configure(
-        const sp<IOMXNode>& omxNode, int32_t dataSpace) {
-    return toBinderStatus(mBase->configure(
-            new TWOmxNode(omxNode), toHardwareDataspace(dataSpace)));
-}
+    TWOmxNodeWrapper(const sp<IOmxNode> &omxNode): mOmxNode(omxNode) {
+    }
 
-::android::binder::Status LWGraphicBufferSource::setSuspend(
-        bool suspend, int64_t timeUs) {
-    return toBinderStatus(mBase->setSuspend(suspend, timeUs));
-}
+    virtual status_t emptyBuffer(
+            int32_t bufferId, uint32_t flags,
+            const sp<GraphicBuffer> &buffer,
+            int64_t timestamp, int fenceFd) override {
+        CodecBuffer tBuffer;
+        native_handle_t* fenceNh = native_handle_create_from_fd(fenceFd);
+        status_t err = toStatusT(mOmxNode->emptyBuffer(
+              bufferId,
+              *wrapAs(&tBuffer, buffer),
+              flags,
+              toRawTicks(timestamp),
+              fenceNh));
+        native_handle_close(fenceNh);
+        native_handle_delete(fenceNh);
+        return err;
+    }
 
-::android::binder::Status LWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
-        int64_t repeatAfterUs) {
-    return toBinderStatus(mBase->setRepeatPreviousFrameDelayUs(repeatAfterUs));
-}
+    virtual void dispatchDataSpaceChanged(
+            int32_t dataSpace, int32_t aspects, int32_t pixelFormat) override {
+        Message tMsg;
+        tMsg.type = Message::Type::EVENT;
+        tMsg.fence = native_handle_create(0, 0);
+        tMsg.data.eventData.event = uint32_t(OMX_EventDataSpaceChanged);
+        tMsg.data.eventData.data1 = dataSpace;
+        tMsg.data.eventData.data2 = aspects;
+        tMsg.data.eventData.data3 = pixelFormat;
+        mOmxNode->dispatchMessage(tMsg);
+    }
+};
 
-::android::binder::Status LWGraphicBufferSource::setMaxFps(float maxFps) {
-    return toBinderStatus(mBase->setMaxFps(maxFps));
-}
+struct TWGraphicBufferSource::TWOmxBufferSource : public IOmxBufferSource {
+    sp<GraphicBufferSource> mSource;
 
-::android::binder::Status LWGraphicBufferSource::setTimeLapseConfig(
-        int64_t timePerFrameUs, int64_t timePerCaptureUs) {
-    return toBinderStatus(mBase->setTimeLapseConfig(
-            timePerFrameUs, timePerCaptureUs));
-}
+    TWOmxBufferSource(const sp<GraphicBufferSource> &source): mSource(source) {
+    }
 
-::android::binder::Status LWGraphicBufferSource::setStartTimeUs(
-        int64_t startTimeUs) {
-    return toBinderStatus(mBase->setStartTimeUs(startTimeUs));
-}
+    Return<void> onOmxExecuting() override {
+        mSource->onOmxExecuting();
+        return Void();
+    }
 
-::android::binder::Status LWGraphicBufferSource::setStopTimeUs(
-        int64_t stopTimeUs) {
-    return toBinderStatus(mBase->setStopTimeUs(stopTimeUs));
-}
+    Return<void> onOmxIdle() override {
+        mSource->onOmxIdle();
+        return Void();
+    }
 
-::android::binder::Status LWGraphicBufferSource::setColorAspects(
-        int32_t aspects) {
-    return toBinderStatus(mBase->setColorAspects(
-            toHardwareColorAspects(aspects)));
-}
+    Return<void> onOmxLoaded() override {
+        mSource->onOmxLoaded();
+        return Void();
+    }
 
-::android::binder::Status LWGraphicBufferSource::setTimeOffsetUs(
-        int64_t timeOffsetsUs) {
-    return toBinderStatus(mBase->setTimeOffsetUs(timeOffsetsUs));
-}
+    Return<void> onInputBufferAdded(uint32_t bufferId) override {
+        mSource->onInputBufferAdded(static_cast<int32_t>(bufferId));
+        return Void();
+    }
 
-::android::binder::Status LWGraphicBufferSource::signalEndOfInputStream() {
-    return toBinderStatus(mBase->signalEndOfInputStream());
-}
+    Return<void> onInputBufferEmptied(
+            uint32_t bufferId, hidl_handle const& tFence) override {
+        mSource->onInputBufferEmptied(
+                static_cast<int32_t>(bufferId),
+                native_handle_read_fd(tFence));
+        return Void();
+    }
+};
 
 // TWGraphicBufferSource
 TWGraphicBufferSource::TWGraphicBufferSource(
-        sp<LGraphicBufferSource> const& base) : mBase(base) {
+        sp<GraphicBufferSource> const& base) :
+    mBase(base),
+    mOmxBufferSource(new TWOmxBufferSource(base)) {
 }
 
-Return<void> TWGraphicBufferSource::configure(
+Return<Status> TWGraphicBufferSource::configure(
         const sp<IOmxNode>& omxNode, Dataspace dataspace) {
-    mBase->configure(new LWOmxNode(omxNode), toRawDataspace(dataspace));
-    return Void();
+    if (omxNode == NULL) {
+        return toStatus(BAD_VALUE);
+    }
+
+    // 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.
+    Return<Status> err(omxNode->setInputSurface(mOmxBufferSource));
+    status_t fnStatus = toStatusT(err);
+    if (fnStatus != NO_ERROR) {
+        ALOGE("Unable to set input surface: %d", fnStatus);
+        return err;
+    }
+
+    // use consumer usage bits queried from encoder, but always add
+    // HW_VIDEO_ENCODER for backward compatibility.
+    uint32_t  consumerUsage;
+    void *_params = &consumerUsage;
+    uint8_t *params = static_cast<uint8_t*>(_params);
+    fnStatus = UNKNOWN_ERROR;
+    IOmxNode::getParameter_cb _hidl_cb(
+            [&fnStatus, &params](Status status, hidl_vec<uint8_t> const& outParams) {
+                fnStatus = toStatusT(status);
+                std::copy(
+                        outParams.data(),
+                        outParams.data() + outParams.size(),
+                        params);
+            });
+    omxNode->getParameter(
+            static_cast<uint32_t>(OMX_IndexParamConsumerUsageBits),
+            inHidlBytes(&consumerUsage, sizeof(consumerUsage)),
+            _hidl_cb);
+    if (fnStatus != OK) {
+        consumerUsage = 0;
+    }
+
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    InitOMXParams(&def);
+    def.nPortIndex = kPortIndexInput;
+
+    _params = &def;
+    params = static_cast<uint8_t*>(_params);
+    omxNode->getParameter(
+            static_cast<uint32_t>(OMX_IndexParamPortDefinition),
+            inHidlBytes(&def, sizeof(def)),
+            _hidl_cb);
+    if (fnStatus != NO_ERROR) {
+        ALOGE("Failed to get port definition: %d", fnStatus);
+        return toStatus(fnStatus);
+    }
+
+
+    return toStatus(mBase->configure(
+            new TWOmxNodeWrapper(omxNode),
+            toRawDataspace(dataspace),
+            def.nBufferCountActual,
+            def.format.video.nFrameWidth,
+            def.format.video.nFrameHeight,
+            consumerUsage));
 }
 
-Return<void> TWGraphicBufferSource::setSuspend(
+Return<Status> TWGraphicBufferSource::setSuspend(
         bool suspend, int64_t timeUs) {
-    mBase->setSuspend(suspend, timeUs);
-    return Void();
+    return toStatus(mBase->setSuspend(suspend, timeUs));
 }
 
-Return<void> TWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
+Return<Status> TWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
         int64_t repeatAfterUs) {
-    mBase->setRepeatPreviousFrameDelayUs(repeatAfterUs);
-    return Void();
+    return toStatus(mBase->setRepeatPreviousFrameDelayUs(repeatAfterUs));
 }
 
-Return<void> TWGraphicBufferSource::setMaxFps(float maxFps) {
-    mBase->setMaxFps(maxFps);
-    return Void();
+Return<Status> TWGraphicBufferSource::setMaxFps(float maxFps) {
+    return toStatus(mBase->setMaxFps(maxFps));
 }
 
-Return<void> TWGraphicBufferSource::setTimeLapseConfig(
+Return<Status> TWGraphicBufferSource::setTimeLapseConfig(
         int64_t timePerFrameUs, int64_t timePerCaptureUs) {
-    mBase->setTimeLapseConfig(timePerFrameUs, timePerCaptureUs);
-    return Void();
+    return toStatus(mBase->setTimeLapseConfig(timePerFrameUs, timePerCaptureUs));
 }
 
-Return<void> TWGraphicBufferSource::setStartTimeUs(int64_t startTimeUs) {
-    mBase->setStartTimeUs(startTimeUs);
-    return Void();
+Return<Status> TWGraphicBufferSource::setStartTimeUs(int64_t startTimeUs) {
+    return toStatus(mBase->setStartTimeUs(startTimeUs));
 }
 
-Return<void> TWGraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) {
-    mBase->setStopTimeUs(stopTimeUs);
-    return Void();
+Return<Status> TWGraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) {
+    return toStatus(mBase->setStopTimeUs(stopTimeUs));
 }
 
-Return<void> TWGraphicBufferSource::setColorAspects(
+Return<Status> TWGraphicBufferSource::setColorAspects(
         const ColorAspects& aspects) {
-    mBase->setColorAspects(toCompactColorAspects(aspects));
-    return Void();
+    return toStatus(mBase->setColorAspects(toCompactColorAspects(aspects)));
 }
 
-Return<void> TWGraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
-    mBase->setTimeOffsetUs(timeOffsetUs);
-    return Void();
+Return<Status> TWGraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
+    return toStatus(mBase->setTimeOffsetUs(timeOffsetUs));
 }
 
-Return<void> TWGraphicBufferSource::signalEndOfInputStream() {
-    mBase->signalEndOfInputStream();
-    return Void();
+Return<Status> TWGraphicBufferSource::signalEndOfInputStream() {
+    return toStatus(mBase->signalEndOfInputStream());
 }
 
 }  // 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 bd60c46..8cf11ca 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.h
+++ b/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.h
@@ -20,15 +20,16 @@
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
 
-#include <media/IOMX.h>
-#include <binder/Binder.h>
-
+#include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
+#include <android/hardware/media/omx/1.0/IOmxNode.h>
 #include <android/hardware/graphics/common/1.0/types.h>
 #include <android/hardware/media/omx/1.0/IOmxNode.h>
 #include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
 
 #include <android/BnGraphicBufferSource.h>
 
+#include "../../../GraphicBufferSource.h"
+
 namespace android {
 namespace hardware {
 namespace media {
@@ -36,10 +37,12 @@
 namespace V1_0 {
 namespace implementation {
 
+using ::android::GraphicBufferSource;
 using ::android::hardware::graphics::common::V1_0::Dataspace;
 using ::android::hardware::media::omx::V1_0::ColorAspects;
 using ::android::hardware::media::omx::V1_0::IGraphicBufferSource;
 using ::android::hardware::media::omx::V1_0::IOmxNode;
+using ::android::hardware::media::omx::V1_0::Status;
 using ::android::hidl::base::V1_0::IBase;
 using ::android::hardware::hidl_array;
 using ::android::hardware::hidl_memory;
@@ -60,44 +63,28 @@
  * - TW = Treble Wrapper --- It wraps a legacy object inside a Treble object.
  */
 
-typedef ::android::IGraphicBufferSource LGraphicBufferSource;
-typedef ::android::BnGraphicBufferSource BnGraphicBufferSource;
 typedef ::android::hardware::media::omx::V1_0::IGraphicBufferSource
         TGraphicBufferSource;
 
-struct LWGraphicBufferSource : public BnGraphicBufferSource {
-    sp<TGraphicBufferSource> mBase;
-    LWGraphicBufferSource(sp<TGraphicBufferSource> const& base);
-    ::android::binder::Status configure(
-            const sp<IOMXNode>& omxNode, int32_t dataSpace) override;
-    ::android::binder::Status setSuspend(bool suspend, int64_t timeUs) override;
-    ::android::binder::Status setRepeatPreviousFrameDelayUs(
-            int64_t repeatAfterUs) override;
-    ::android::binder::Status setMaxFps(float maxFps) override;
-    ::android::binder::Status setTimeLapseConfig(
-            int64_t timePerFrameUs, int64_t timePerCaptureUs) override;
-    ::android::binder::Status setStartTimeUs(int64_t startTimeUs) override;
-    ::android::binder::Status setStopTimeUs(int64_t stopTimeUs) override;
-    ::android::binder::Status setColorAspects(int32_t aspects) override;
-    ::android::binder::Status setTimeOffsetUs(int64_t timeOffsetsUs) override;
-    ::android::binder::Status signalEndOfInputStream() override;
-};
-
 struct TWGraphicBufferSource : public TGraphicBufferSource {
-    sp<LGraphicBufferSource> mBase;
-    TWGraphicBufferSource(sp<LGraphicBufferSource> const& base);
-    Return<void> configure(
+    struct TWOmxNodeWrapper;
+    struct TWOmxBufferSource;
+    sp<GraphicBufferSource> mBase;
+    sp<IOmxBufferSource> mOmxBufferSource;
+
+    TWGraphicBufferSource(sp<GraphicBufferSource> const& base);
+    Return<Status> configure(
             const sp<IOmxNode>& omxNode, Dataspace dataspace) override;
-    Return<void> setSuspend(bool suspend, int64_t timeUs) override;
-    Return<void> setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) override;
-    Return<void> setMaxFps(float maxFps) override;
-    Return<void> setTimeLapseConfig(
+    Return<Status> setSuspend(bool suspend, int64_t timeUs) override;
+    Return<Status> setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) override;
+    Return<Status> setMaxFps(float maxFps) override;
+    Return<Status> setTimeLapseConfig(
             int64_t timePerFrameUs, int64_t timePerCaptureUs) override;
-    Return<void> setStartTimeUs(int64_t startTimeUs) override;
-    Return<void> setStopTimeUs(int64_t stopTimeUs) override;
-    Return<void> setColorAspects(const ColorAspects& aspects) override;
-    Return<void> setTimeOffsetUs(int64_t timeOffsetUs) override;
-    Return<void> signalEndOfInputStream() override;
+    Return<Status> setStartTimeUs(int64_t startTimeUs) override;
+    Return<Status> setStopTimeUs(int64_t stopTimeUs) override;
+    Return<Status> setColorAspects(const ColorAspects& aspects) override;
+    Return<Status> setTimeOffsetUs(int64_t timeOffsetUs) override;
+    Return<Status> signalEndOfInputStream() override;
 };
 
 }  // namespace implementation
diff --git a/media/libstagefright/omx/hal/1.0/impl/WOmx.cpp b/media/libstagefright/omx/hal/1.0/impl/WOmx.cpp
deleted file mode 100644
index da1c23d..0000000
--- a/media/libstagefright/omx/hal/1.0/impl/WOmx.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "WOmx.h"
-#include "WOmxNode.h"
-#include "WOmxObserver.h"
-#include "WOmxBufferProducer.h"
-#include "WGraphicBufferSource.h"
-#include "Conversion.h"
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace omx {
-namespace V1_0 {
-namespace implementation {
-
-// LWOmx
-LWOmx::LWOmx(sp<IOmx> const& base) : mBase(base) {
-}
-
-status_t LWOmx::listNodes(List<IOMX::ComponentInfo>* list) {
-    status_t fnStatus;
-    status_t transStatus = toStatusT(mBase->listNodes(
-            [&fnStatus, list](
-                    Status status,
-                    hidl_vec<IOmx::ComponentInfo> const& nodeList) {
-                fnStatus = toStatusT(status);
-                list->clear();
-                for (size_t i = 0; i < nodeList.size(); ++i) {
-                    auto newInfo = list->insert(
-                            list->end(), IOMX::ComponentInfo());
-                    convertTo(&*newInfo, nodeList[i]);
-                }
-            }));
-    return transStatus == NO_ERROR ? fnStatus : transStatus;
-}
-
-status_t LWOmx::allocateNode(
-        char const* name,
-        sp<IOMXObserver> const& observer,
-        sp<IOMXNode>* omxNode) {
-    status_t fnStatus;
-    status_t transStatus = toStatusT(mBase->allocateNode(
-            name, new TWOmxObserver(observer),
-            [&fnStatus, omxNode](Status status, sp<IOmxNode> const& node) {
-                fnStatus = toStatusT(status);
-                *omxNode = new LWOmxNode(node);
-            }));
-    return transStatus == NO_ERROR ? fnStatus : transStatus;
-}
-
-status_t LWOmx::createInputSurface(
-        sp<::android::IGraphicBufferProducer>* bufferProducer,
-        sp<::android::IGraphicBufferSource>* bufferSource) {
-    status_t fnStatus;
-    status_t transStatus = toStatusT(mBase->createInputSurface(
-            [&fnStatus, bufferProducer, bufferSource] (
-                    Status status,
-                    sp<IOmxBufferProducer> const& tProducer,
-                    sp<IGraphicBufferSource> const& tSource) {
-                fnStatus = toStatusT(status);
-                *bufferProducer = new LWOmxBufferProducer(tProducer);
-                *bufferSource = new LWGraphicBufferSource(tSource);
-            }));
-    return transStatus == NO_ERROR ? fnStatus : transStatus;
-}
-
-// TWOmx
-TWOmx::TWOmx(sp<IOMX> const& base) : mBase(base) {
-}
-
-Return<void> TWOmx::listNodes(listNodes_cb _hidl_cb) {
-    List<IOMX::ComponentInfo> lList;
-    Status status = toStatus(mBase->listNodes(&lList));
-
-    hidl_vec<IOmx::ComponentInfo> tList;
-    tList.resize(lList.size());
-    size_t i = 0;
-    for (auto const& lInfo : lList) {
-        convertTo(&(tList[i++]), lInfo);
-    }
-    _hidl_cb(status, tList);
-    return Void();
-}
-
-Return<void> TWOmx::allocateNode(
-        const hidl_string& name,
-        const sp<IOmxObserver>& observer,
-        allocateNode_cb _hidl_cb) {
-    sp<IOMXNode> omxNode;
-    Status status = toStatus(mBase->allocateNode(
-            name, new LWOmxObserver(observer), &omxNode));
-    _hidl_cb(status, new TWOmxNode(omxNode));
-    return Void();
-}
-
-Return<void> TWOmx::createInputSurface(createInputSurface_cb _hidl_cb) {
-    sp<::android::IGraphicBufferProducer> lProducer;
-    sp<::android::IGraphicBufferSource> lSource;
-    status_t status = mBase->createInputSurface(&lProducer, &lSource);
-    _hidl_cb(toStatus(status),
-             new TWOmxBufferProducer(lProducer),
-             new TWGraphicBufferSource(lSource));
-    return Void();
-}
-
-}  // namespace implementation
-}  // namespace V1_0
-}  // namespace omx
-}  // namespace media
-}  // namespace hardware
-}  // namespace android
diff --git a/media/libstagefright/omx/hal/1.0/impl/WOmx.h b/media/libstagefright/omx/hal/1.0/impl/WOmx.h
deleted file mode 100644
index 3cb002e..0000000
--- a/media/libstagefright/omx/hal/1.0/impl/WOmx.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0_WOMX_H
-#define ANDROID_HARDWARE_MEDIA_OMX_V1_0_WOMX_H
-
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-
-#include "../../../../include/OMXNodeInstance.h"
-
-#include <android/hardware/media/omx/1.0/IOmx.h>
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace omx {
-namespace V1_0 {
-namespace implementation {
-
-using ::android::hardware::media::omx::V1_0::IOmx;
-using ::android::hardware::media::omx::V1_0::IOmxNode;
-using ::android::hardware::media::omx::V1_0::IOmxObserver;
-using ::android::hardware::media::omx::V1_0::Status;
-using ::android::hidl::base::V1_0::IBase;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
-
-using ::android::List;
-using ::android::IOMX;
-using ::android::BnOMX;
-
-/**
- * Wrapper classes for conversion
- * ==============================
- *
- * Naming convention:
- * - LW = Legacy Wrapper --- It wraps a Treble object inside a legacy object.
- * - TW = Treble Wrapper --- It wraps a legacy object inside a Treble object.
- */
-
-struct LWOmx : public BnOMX {
-    sp<IOmx> mBase;
-    LWOmx(sp<IOmx> const& base);
-    status_t listNodes(List<IOMX::ComponentInfo>* list) override;
-    status_t allocateNode(
-            char const* name,
-            sp<IOMXObserver> const& observer,
-            sp<IOMXNode>* omxNode) override;
-    status_t createInputSurface(
-            sp<::android::IGraphicBufferProducer>* bufferProducer,
-            sp<::android::IGraphicBufferSource>* bufferSource) override;
-};
-
-struct TWOmx : public IOmx {
-    sp<IOMX> mBase;
-    TWOmx(sp<IOMX> const& base);
-    Return<void> listNodes(listNodes_cb _hidl_cb) override;
-    Return<void> allocateNode(
-            const hidl_string& name,
-            const sp<IOmxObserver>& observer,
-            allocateNode_cb _hidl_cb) override;
-    Return<void> createInputSurface(createInputSurface_cb _hidl_cb) override;
-
-};
-
-}  // namespace implementation
-}  // namespace V1_0
-}  // namespace omx
-}  // namespace media
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_MEDIA_OMX_V1_0_WOMX_H
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 5a1d6dc..88dabff 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -54,7 +54,7 @@
     MTP_OPERATION_SEND_OBJECT,
 //    MTP_OPERATION_INITIATE_CAPTURE,
 //    MTP_OPERATION_FORMAT_STORE,
-//    MTP_OPERATION_RESET_DEVICE,
+    MTP_OPERATION_RESET_DEVICE,
 //    MTP_OPERATION_SELF_TEST,
 //    MTP_OPERATION_SET_OBJECT_PROTECTION,
 //    MTP_OPERATION_POWER_DOWN,
@@ -362,6 +362,7 @@
         case MTP_OPERATION_OPEN_SESSION:
             response = doOpenSession();
             break;
+        case MTP_OPERATION_RESET_DEVICE:
         case MTP_OPERATION_CLOSE_SESSION:
             response = doCloseSession();
             break;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 3d1f268..c0918d4 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -129,6 +129,7 @@
 
 AudioFlinger::AudioFlinger()
     : BnAudioFlinger(),
+      mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
       mPrimaryHardwareDev(NULL),
       mAudioHwDevs(NULL),
       mHardwareStatus(AUDIO_HW_IDLE),
@@ -163,6 +164,8 @@
     mDevicesFactoryHal = DevicesFactoryHalInterface::create();
     mEffectsFactoryHal = EffectsFactoryHalInterface::create();
 
+    mMediaLogNotifier->run("MediaLogNotifier");
+
 #ifdef TEE_SINK
     char value[PROPERTY_VALUE_MAX];
     (void) property_get("ro.debuggable", value, "0");
@@ -1528,6 +1531,41 @@
     mAudioFlinger->removeNotificationClient(mPid);
 }
 
+// ----------------------------------------------------------------------------
+AudioFlinger::MediaLogNotifier::MediaLogNotifier()
+    : mPendingRequests(false) {}
+
+
+void AudioFlinger::MediaLogNotifier::requestMerge() {
+    AutoMutex _l(mMutex);
+    mPendingRequests = true;
+    mCond.signal();
+}
+
+bool AudioFlinger::MediaLogNotifier::threadLoop() {
+    // Wait until there are pending requests
+    {
+        AutoMutex _l(mMutex);
+        mPendingRequests = false; // to ignore past requests
+        while (!mPendingRequests) {
+            mCond.wait(mMutex);
+            // TODO may also need an exitPending check
+        }
+        mPendingRequests = false;
+    }
+    // Execute the actual MediaLogService binder call and ignore extra requests for a while
+    sp<IBinder> binder = defaultServiceManager()->getService(String16("media.log"));
+    if (binder != 0) {
+        sp<IMediaLogService> mediaLogService(interface_cast<IMediaLogService>(binder));
+        mediaLogService->requestMergeWakeup();
+    }
+    usleep(kPostTriggerSleepPeriod);
+    return true;
+}
+
+void AudioFlinger::requestLogMerge() {
+    mMediaLogNotifier->requestMerge();
+}
 
 // ----------------------------------------------------------------------------
 
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 44fd512..b79f09e 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -472,6 +472,38 @@
         const sp<IAudioFlingerClient> mAudioFlingerClient;
     };
 
+    // --- MediaLogNotifier ---
+    // Thread in charge of notifying MediaLogService to start merging.
+    // Receives requests from AudioFlinger's binder activity. It is used to reduce the amount of
+    // binder calls to MediaLogService in case of bursts of AudioFlinger binder calls.
+    class MediaLogNotifier : public Thread {
+    public:
+        MediaLogNotifier();
+
+        // Requests a MediaLogService notification. It's ignored if there has recently been another
+        void requestMerge();
+    private:
+        // Every iteration blocks waiting for a request, then interacts with MediaLogService to
+        // start merging.
+        // As every MediaLogService binder call is expensive, once it gets a request it ignores the
+        // following ones for a period of time.
+        virtual bool threadLoop() override;
+
+        bool mPendingRequests;
+
+        // Mutex and condition variable around mPendingRequests' value
+        Mutex       mMutex;
+        Condition   mCond;
+
+        // Duration of the sleep period after a processed request
+        static const int kPostTriggerSleepPeriod = 1000000;
+    };
+
+    const sp<MediaLogNotifier> mMediaLogNotifier;
+
+    // This is a helper that is called during incoming binder calls.
+    void requestLogMerge();
+
     class TrackHandle;
     class RecordHandle;
     class RecordThread;
@@ -563,6 +595,7 @@
         virtual status_t getMmapPosition(struct audio_mmap_position *position);
         virtual status_t start(const MmapStreamInterface::Client& client, audio_port_handle_t *handle);
         virtual status_t stop(audio_port_handle_t handle);
+        virtual status_t standby();
 
     private:
         sp<MmapThread> mThread;
diff --git a/services/audioflinger/FastMixerState.cpp b/services/audioflinger/FastMixerState.cpp
index ad471fb..36d8eef 100644
--- a/services/audioflinger/FastMixerState.cpp
+++ b/services/audioflinger/FastMixerState.cpp
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "FastMixerState"
+//#define LOG_NDEBUG 0
+
 #include <cutils/properties.h>
 #include "FastMixerState.h"
 
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index b3134eb..fb1428e 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2953,6 +2953,10 @@
 #endif
     while (!exitPending())
     {
+        // Log merge requests are performed during AudioFlinger binder transactions, but
+        // that does not cover audio playback. It's requested here for that reason.
+        mAudioFlinger->requestLogMerge();
+
         cpuStats.sample(myName);
 
         Vector< sp<EffectChain> > effectChains;
@@ -7434,7 +7438,7 @@
 {
     MmapThread *thread = mThread.get();
     // clear our strong reference before disconnecting the thread: the last strong reference
-    // will be removed when closeInput/closeOutput is executed upono call from audio policy manager
+    // will be removed when closeInput/closeOutput is executed upon call from audio policy manager
     // and the thread removed from mMMapThreads list causing the thread destruction.
     mThread.clear();
     if (thread != nullptr) {
@@ -7476,6 +7480,14 @@
     return mThread->stop(handle);
 }
 
+status_t AudioFlinger::MmapThreadHandle::standby()
+{
+    if (mThread == 0) {
+        return NO_INIT;
+    }
+    return mThread->standby();
+}
+
 
 AudioFlinger::MmapThread::MmapThread(
         const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
@@ -7484,11 +7496,13 @@
     : ThreadBase(audioFlinger, id, outDevice, inDevice, MMAP, systemReady),
       mHalStream(stream), mHalDevice(hwDev->hwDevice()), mAudioHwDev(hwDev)
 {
+    mStandby = true;
     readHalParameters_l();
 }
 
 AudioFlinger::MmapThread::~MmapThread()
 {
+    releaseWakeLock_l();
 }
 
 void AudioFlinger::MmapThread::onFirstRef()
@@ -7528,6 +7542,8 @@
     if (mHalStream == 0) {
         return NO_INIT;
     }
+    mStandby = true;
+    acquireWakeLock();
     return mHalStream->createMmapBuffer(minSizeFrames, info);
 }
 
@@ -7542,7 +7558,7 @@
 status_t AudioFlinger::MmapThread::start(const MmapStreamInterface::Client& client,
                                          audio_port_handle_t *handle)
 {
-    ALOGV("%s clientUid %d", __FUNCTION__, client.clientUid);
+    ALOGV("%s clientUid %d mStandby %d", __FUNCTION__, client.clientUid, mStandby);
     if (mHalStream == 0) {
         return NO_INIT;
     }
@@ -7556,6 +7572,7 @@
         mHalStream->start();
         portId = mPortId;
         sessionId = mSessionId;
+        mStandby = false;
     } else {
         // for other tracks than first one, get a new port ID from APM.
         sessionId = (audio_session_t)mAudioFlinger->newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
@@ -7613,6 +7630,8 @@
             } else {
                 AudioSystem::releaseInput(mId, sessionId);
             }
+        } else {
+            mHalStream->stop();
         }
         return PERMISSION_DENIED;
     }
@@ -7632,14 +7651,13 @@
 
     broadcast_l();
 
-    ALOGV("%s DONE handle %d", __FUNCTION__, portId);
+    ALOGV("%s DONE handle %d stream %p", __FUNCTION__, portId, mHalStream.get());
 
     return NO_ERROR;
 }
 
 status_t AudioFlinger::MmapThread::stop(audio_port_handle_t handle)
 {
-
     ALOGV("%s handle %d", __FUNCTION__, handle);
 
     if (mHalStream == 0) {
@@ -7685,6 +7703,22 @@
     return NO_ERROR;
 }
 
+status_t AudioFlinger::MmapThread::standby()
+{
+    ALOGV("%s", __FUNCTION__);
+
+    if (mHalStream == 0) {
+        return NO_INIT;
+    }
+    if (mActiveTracks.size() != 0) {
+        return INVALID_OPERATION;
+    }
+    mHalStream->standby();
+    mStandby = true;
+    releaseWakeLock();
+    return NO_ERROR;
+}
+
 
 void AudioFlinger::MmapThread::readHalParameters_l()
 {
@@ -7701,8 +7735,6 @@
 
 bool AudioFlinger::MmapThread::threadLoop()
 {
-    acquireWakeLock();
-
     checkSilentMode_l();
 
     const String8 myName(String8::format("thread %p type %d TID %d", this, mType, gettid()));
@@ -7724,18 +7756,10 @@
                     break;
                 }
 
-                bool wakelockReleased = false;
-                if (mActiveTracks.size() == 0) {
-                    releaseWakeLock_l();
-                    wakelockReleased = true;
-                }
                 // wait until we have something to do...
                 ALOGV("%s going to sleep", myName.string());
                 mWaitWorkCV.wait(mLock);
                 ALOGV("%s waking up", myName.string());
-                if (wakelockReleased) {
-                    acquireWakeLock_l();
-                }
 
                 checkSilentMode_l();
 
@@ -7768,8 +7792,6 @@
         mStandby = true;
     }
 
-    releaseWakeLock();
-
     ALOGV("Thread %p type %d exiting", this, mType);
     return false;
 }
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 0a17a8e..422eeb5 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1540,6 +1540,7 @@
     status_t getMmapPosition(struct audio_mmap_position *position);
     status_t start(const MmapStreamInterface::Client& client, audio_port_handle_t *handle);
     status_t stop(audio_port_handle_t handle);
+    status_t standby();
 
     // RefBase
     virtual     void        onFirstRef();
@@ -1549,6 +1550,7 @@
 
     virtual     void        threadLoop_exit();
     virtual     void        threadLoop_standby();
+    virtual     bool        shouldStandby_l() { return false; }
 
     virtual     status_t    initCheck() const { return (mHalStream == 0) ? NO_INIT : NO_ERROR; }
     virtual     size_t      frameCount() const { return mFrameCount; }
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 7133709..702c92d 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -622,7 +622,7 @@
         }
     } else {
         status_t res = mCameraProviderManager->getCameraCharacteristics(
-                String16::std_string(cameraId), cameraInfo);
+                String8(cameraId).string(), cameraInfo);
         if (res != OK) {
             return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera "
                     "characteristics for device %s: %s (%d)", String8(cameraId).string(),
@@ -689,14 +689,14 @@
     } else {
         status_t res;
         hardware::hidl_version maxVersion{0,0};
-        res = mCameraProviderManager->getHighestSupportedVersion(String8::std_string(cameraId),
+        res = mCameraProviderManager->getHighestSupportedVersion(cameraId.string(),
                 &maxVersion);
         if (res != OK) return -1;
         deviceVersion = HARDWARE_DEVICE_API_VERSION(maxVersion.get_major(), maxVersion.get_minor());
 
         hardware::CameraInfo info;
         if (facing) {
-            res = mCameraProviderManager->getCameraInfo(String8::std_string(cameraId), &info);
+            res = mCameraProviderManager->getCameraInfo(cameraId.string(), &info);
             if (res != OK) return -1;
             *facing = info.facing;
         }
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 79e7ff0..4428f75 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -321,7 +321,7 @@
     return binder::Status::ok();
 }
 
-binder::Status CameraDeviceClient::endConfigure(bool isConstrainedHighSpeed) {
+binder::Status CameraDeviceClient::endConfigure(int operatingMode) {
     ALOGV("%s: ending configure (%d input stream, %zu output surfaces)",
             __FUNCTION__, mInputStream.configured ? 1 : 0,
             mStreamMap.size());
@@ -335,7 +335,16 @@
         return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
     }
 
+    if (operatingMode < 0) {
+        String8 msg = String8::format(
+            "Camera %s: Invalid operating mode %d requested", mCameraIdStr.string(), operatingMode);
+        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                msg.string());
+    }
+
     // Sanitize the high speed session against necessary capability bit.
+    bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
     if (isConstrainedHighSpeed) {
         CameraMetadata staticInfo = mDevice->info();
         camera_metadata_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
@@ -357,7 +366,7 @@
         }
     }
 
-    status_t err = mDevice->configureStreams(isConstrainedHighSpeed);
+    status_t err = mDevice->configureStreams(operatingMode);
     if (err == BAD_VALUE) {
         String8 msg = String8::format("Camera %s: Unsupported set of inputs/outputs provided",
                 mCameraIdStr.string());
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 012beb4..2a95c88 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -70,70 +70,70 @@
             const hardware::camera2::CaptureRequest& request,
             bool streaming = false,
             /*out*/
-            hardware::camera2::utils::SubmitInfo *submitInfo = nullptr);
+            hardware::camera2::utils::SubmitInfo *submitInfo = nullptr) override;
     // List of requests are copied.
     virtual binder::Status submitRequestList(
             const std::vector<hardware::camera2::CaptureRequest>& requests,
             bool streaming = false,
             /*out*/
-            hardware::camera2::utils::SubmitInfo *submitInfo = nullptr);
+            hardware::camera2::utils::SubmitInfo *submitInfo = nullptr) override;
     virtual binder::Status cancelRequest(int requestId,
             /*out*/
-            int64_t* lastFrameNumber = NULL);
+            int64_t* lastFrameNumber = NULL) override;
 
-    virtual binder::Status beginConfigure();
+    virtual binder::Status beginConfigure() override;
 
-    virtual binder::Status endConfigure(bool isConstrainedHighSpeed = false);
+    virtual binder::Status endConfigure(int operatingMode) override;
 
     // Returns -EBUSY if device is not idle
-    virtual binder::Status deleteStream(int streamId);
+    virtual binder::Status deleteStream(int streamId) override;
 
     virtual binder::Status createStream(
             const hardware::camera2::params::OutputConfiguration &outputConfiguration,
             /*out*/
-            int32_t* newStreamId = NULL);
+            int32_t* newStreamId = NULL) override;
 
     // Create an input stream of width, height, and format.
     virtual binder::Status createInputStream(int width, int height, int format,
             /*out*/
-            int32_t* newStreamId = NULL);
+            int32_t* newStreamId = NULL) override;
 
     // Get the buffer producer of the input stream
     virtual binder::Status getInputSurface(
             /*out*/
-            view::Surface *inputSurface);
+            view::Surface *inputSurface) override;
 
     // Create a request object from a template.
     virtual binder::Status createDefaultRequest(int templateId,
             /*out*/
-            hardware::camera2::impl::CameraMetadataNative* request);
+            hardware::camera2::impl::CameraMetadataNative* request) override;
 
     // Get the static metadata for the camera
     // -- Caller owns the newly allocated metadata
     virtual binder::Status getCameraInfo(
             /*out*/
-            hardware::camera2::impl::CameraMetadataNative* cameraCharacteristics);
+            hardware::camera2::impl::CameraMetadataNative* cameraCharacteristics) override;
 
     // Wait until all the submitted requests have finished processing
-    virtual binder::Status waitUntilIdle();
+    virtual binder::Status waitUntilIdle() override;
 
     // Flush all active and pending requests as fast as possible
     virtual binder::Status flush(
             /*out*/
-            int64_t* lastFrameNumber = NULL);
+            int64_t* lastFrameNumber = NULL) override;
 
     // Prepare stream by preallocating its buffers
-    virtual binder::Status prepare(int32_t streamId);
+    virtual binder::Status prepare(int32_t streamId) override;
 
     // Tear down stream resources by freeing its unused buffers
-    virtual binder::Status tearDown(int32_t streamId);
+    virtual binder::Status tearDown(int32_t streamId) override;
 
     // Prepare stream by preallocating up to maxCount of its buffers
-    virtual binder::Status prepare2(int32_t maxCount, int32_t streamId);
+    virtual binder::Status prepare2(int32_t maxCount, int32_t streamId) override;
 
     // Finalize the output configurations with surfaces not added before.
     virtual binder::Status finalizeOutputConfigurations(int32_t streamId,
-            const hardware::camera2::params::OutputConfiguration &outputConfiguration);
+            const hardware::camera2::params::OutputConfiguration &outputConfiguration) override;
 
     /**
      * Interface used by CameraService
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 98a3fcc..f9b062a 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -184,7 +184,7 @@
      * - BAD_VALUE if the set of streams was invalid (e.g. fmts or sizes)
      * - INVALID_OPERATION if the device was in the wrong state
      */
-    virtual status_t configureStreams(bool isConstrainedHighSpeed = false) = 0;
+    virtual status_t configureStreams(int operatingMode = 0) = 0;
 
     // get the buffer producer of the input stream
     virtual status_t getInputBufferProducer(
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
index 3e4e631..b52c0d8 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
@@ -80,7 +80,7 @@
 
     ALOGI("Opening camera %s", mName.string());
 
-    status_t ret = manager->openSession(String8::std_string(mName), this, &mHidlDevice);
+    status_t ret = manager->openSession(mName.string(), this, &mHidlDevice);
     if (ret != OK) {
         ALOGE("%s: openSession failed! %s (%d)", __FUNCTION__, strerror(-ret), ret);
     }
diff --git a/services/camera/libcameraservice/device3/Camera3BufferManager.cpp b/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
index d45891f..d93b331 100644
--- a/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
+++ b/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
@@ -19,7 +19,6 @@
 #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>
@@ -30,15 +29,7 @@
 
 namespace camera3 {
 
-Camera3BufferManager::Camera3BufferManager(const sp<IGraphicBufferAlloc>& allocator) :
-        mAllocator(allocator) {
-    if (allocator == NULL) {
-        sp<ISurfaceComposer> composer(ComposerService::getComposerService());
-        mAllocator = composer->createGraphicBufferAlloc();
-        if (mAllocator == NULL) {
-            ALOGE("createGraphicBufferAlloc failed");
-        }
-    }
+Camera3BufferManager::Camera3BufferManager() {
 }
 
 Camera3BufferManager::~Camera3BufferManager() {
@@ -79,10 +70,6 @@
     }
 
     Mutex::Autolock l(mLock);
-    if (mAllocator == NULL) {
-        ALOGE("%s: allocator is NULL, buffer manager is bad state.", __FUNCTION__);
-        return INVALID_OPERATION;
-    }
 
     // Check if this stream was registered with different stream set ID, if so, error out.
     for (size_t i = 0; i < mStreamSetMap.size(); i++) {
@@ -132,10 +119,6 @@
     Mutex::Autolock l(mLock);
     ALOGV("%s: unregister stream %d with stream set %d", __FUNCTION__,
             streamId, streamSetId);
-    if (mAllocator == NULL) {
-        ALOGE("%s: allocator is NULL, buffer manager is bad state.", __FUNCTION__);
-        return INVALID_OPERATION;
-    }
 
     if (!checkIfStreamRegisteredLocked(streamId, streamSetId)){
         ALOGE("%s: stream %d with set id %d wasn't properly registered to this buffer manager!",
@@ -182,10 +165,6 @@
     Mutex::Autolock l(mLock);
     ALOGV("%s: get buffer for stream %d with stream set %d", __FUNCTION__,
             streamId, streamSetId);
-    if (mAllocator == NULL) {
-        ALOGE("%s: allocator is NULL, buffer manager is bad state.", __FUNCTION__);
-        return INVALID_OPERATION;
-    }
 
     if (!checkIfStreamRegisteredLocked(streamId, streamSetId)) {
         ALOGE("%s: stream %d is not registered with stream set %d yet!!!",
@@ -219,15 +198,18 @@
         // Allocate one if there is no free buffer available.
         if (buffer.graphicBuffer == nullptr) {
             const StreamInfo& info = streamSet.streamInfoMap.valueFor(streamId);
-            status_t res = OK;
             buffer.fenceFd = -1;
-            buffer.graphicBuffer = mAllocator->createGraphicBuffer(
-                    info.width, info.height, info.format, 1 /* layerCount */,
-                    info.combinedUsage, &res);
+
+            buffer.graphicBuffer = new GraphicBuffer(
+                    info.width, info.height, PixelFormat(info.format), info.combinedUsage,
+                    std::string("Camera3BufferManager pid [") +
+                            std::to_string(getpid()) + "]");
+            status_t res = buffer.graphicBuffer->initCheck();
+
             ALOGV("%s: allocating a new graphic buffer (%dx%d, format 0x%x) %p with handle %p",
                     __FUNCTION__, info.width, info.height, info.format,
                     buffer.graphicBuffer.get(), buffer.graphicBuffer->handle);
-            if (res != OK) {
+            if (res < 0) {
                 ALOGE("%s: graphic buffer allocation failed: (error %d %s) ",
                         __FUNCTION__, res, strerror(-res));
                 return res;
@@ -331,10 +313,6 @@
     Mutex::Autolock l(mLock);
 
     ALOGV("Stream %d set %d: Buffer released", streamId, streamSetId);
-    if (mAllocator == NULL) {
-        ALOGE("%s: allocator is NULL, buffer manager is bad state.", __FUNCTION__);
-        return INVALID_OPERATION;
-    }
 
     if (!checkIfStreamRegisteredLocked(streamId, streamSetId)){
         ALOGV("%s: signaling buffer release for an already unregistered stream "
@@ -363,10 +341,6 @@
     Mutex::Autolock l(mLock);
     ALOGV_IF(buffer != 0, "%s: return buffer (%p) with handle (%p) for stream %d and stream set %d",
             __FUNCTION__, buffer.get(), buffer->handle, streamId, streamSetId);
-    if (mAllocator == NULL) {
-        ALOGE("%s: allocator is NULL, buffer manager is bad state.", __FUNCTION__);
-        return INVALID_OPERATION;
-    }
 
     if (!checkIfStreamRegisteredLocked(streamId, streamSetId)){
         ALOGV("%s: returning buffer for an already unregistered stream (stream %d with set id %d),"
diff --git a/services/camera/libcameraservice/device3/Camera3BufferManager.h b/services/camera/libcameraservice/device3/Camera3BufferManager.h
index f44c4a3..d1d7a6f 100644
--- a/services/camera/libcameraservice/device3/Camera3BufferManager.h
+++ b/services/camera/libcameraservice/device3/Camera3BufferManager.h
@@ -26,8 +26,6 @@
 
 namespace android {
 
-class IGraphicBufferAlloc;
-
 namespace camera3 {
 
 struct StreamInfo;
@@ -46,7 +44,7 @@
  */
 class Camera3BufferManager: public virtual RefBase {
 public:
-    explicit Camera3BufferManager(const sp<IGraphicBufferAlloc>& allocator = NULL);
+    explicit Camera3BufferManager();
 
     virtual ~Camera3BufferManager();
 
@@ -188,12 +186,6 @@
 
     static const size_t kMaxBufferCount = BufferQueueDefs::NUM_BUFFER_SLOTS;
 
-    /**
-     * mAllocator is the connection to SurfaceFlinger that is used to allocate new GraphicBuffer
-     * objects.
-     */
-    sp<IGraphicBufferAlloc> mAllocator;
-
     struct GraphicBufferEntry {
         sp<GraphicBuffer> graphicBuffer;
         int fenceFd;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index f20556d..60c716f 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -63,6 +63,7 @@
 
 Camera3Device::Camera3Device(const String8 &id):
         mId(id),
+        mOperatingMode(NO_MODE),
         mIsConstrainedHighSpeedConfiguration(false),
         mStatus(STATUS_UNINITIALIZED),
         mStatusWaiters(0),
@@ -182,7 +183,7 @@
 
     sp<ICameraDeviceSession> session;
     ATRACE_BEGIN("CameraHal::openSession");
-    status_t res = manager->openSession(String8::std_string(mId), this,
+    status_t res = manager->openSession(mId.string(), this,
             /*out*/ &session);
     ATRACE_END();
     if (res != OK) {
@@ -190,7 +191,7 @@
         return res;
     }
 
-    res = manager->getCameraCharacteristics(String8::std_string(mId), &mDeviceInfo);
+    res = manager->getCameraCharacteristics(mId.string(), &mDeviceInfo);
     if (res != OK) {
         SET_ERR_L("Could not retrive camera characteristics: %s (%d)", strerror(-res), res);
         session->close();
@@ -514,19 +515,25 @@
     return StreamRotation::ROTATION_0;
 }
 
-StreamConfigurationMode Camera3Device::mapToStreamConfigurationMode(
-        camera3_stream_configuration_mode_t operationMode) {
-    switch(operationMode) {
-        case CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE:
-            return StreamConfigurationMode::NORMAL_MODE;
-        case CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
-            return StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE;
-        case CAMERA3_VENDOR_STREAM_CONFIGURATION_MODE_START:
-            // Needs to be mapped by vendor extensions
-            break;
+status_t Camera3Device::mapToStreamConfigurationMode(
+        camera3_stream_configuration_mode_t operationMode, StreamConfigurationMode *mode) {
+    if (mode == nullptr) return BAD_VALUE;
+    if (operationMode < CAMERA3_VENDOR_STREAM_CONFIGURATION_MODE_START) {
+        switch(operationMode) {
+            case CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE:
+                *mode = StreamConfigurationMode::NORMAL_MODE;
+                break;
+            case CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
+                *mode = StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE;
+                break;
+            default:
+                ALOGE("%s: Unknown stream configuration mode %d", __FUNCTION__, operationMode);
+                return BAD_VALUE;
+        }
+    } else {
+        *mode = static_cast<StreamConfigurationMode>(operationMode);
     }
-    ALOGE("%s: Unknown stream configuration mode %d", __FUNCTION__, operationMode);
-    return StreamConfigurationMode::NORMAL_MODE;
+    return OK;
 }
 
 camera3_buffer_status_t Camera3Device::mapHidlBufferStatus(BufferStatus status) {
@@ -677,8 +684,12 @@
         lines.appendFormat("    Error cause: %s\n", mErrorCause.string());
     }
     lines.appendFormat("    Stream configuration:\n");
-    lines.appendFormat("    Operation mode: %s \n", mIsConstrainedHighSpeedConfiguration ?
-            "CONSTRAINED HIGH SPEED VIDEO" : "NORMAL");
+    const char *mode =
+            mOperatingMode == static_cast<int>(StreamConfigurationMode::NORMAL_MODE) ? "NORMAL" :
+            mOperatingMode == static_cast<int>(
+                StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE) ? "CONSTRAINED_HIGH_SPEED" :
+            "CUSTOM";
+    lines.appendFormat("    Operation mode: %s (%d) \n", mode, mOperatingMode);
 
     if (mInputStream != NULL) {
         write(fd, lines.string(), lines.size());
@@ -1093,7 +1104,9 @@
     status_t res;
 
     if (mStatus == STATUS_UNCONFIGURED || mNeedConfig) {
-        res = configureStreamsLocked();
+        // This point should only be reached via API1 (API2 must explicitly call configureStreams)
+        // so unilaterally select normal operating mode.
+        res = configureStreamsLocked(CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE);
         // Stream configuration failed. Client might try other configuraitons.
         if (res != OK) {
             CLOGE("Can't set up streams: %s (%d)", strerror(-res), res);
@@ -1195,7 +1208,8 @@
     // Continue captures if active at start
     if (wasActive) {
         ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
-        res = configureStreamsLocked();
+        // Reuse current operating mode for new stream config
+        res = configureStreamsLocked(mOperatingMode);
         if (res != OK) {
             ALOGE("%s: Can't reconfigure device for new stream %d: %s (%d)",
                     __FUNCTION__, mNextStreamId, strerror(-res), res);
@@ -1357,7 +1371,8 @@
     // Continue captures if active at start
     if (wasActive) {
         ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
-        res = configureStreamsLocked();
+        // Reuse current operating mode for new stream config
+        res = configureStreamsLocked(mOperatingMode);
         if (res != OK) {
             CLOGE("Can't reconfigure device for new stream %d: %s (%d)",
                     mNextStreamId, strerror(-res), res);
@@ -1501,19 +1516,14 @@
     return INVALID_OPERATION;
 }
 
-status_t Camera3Device::configureStreams(bool isConstrainedHighSpeed) {
+status_t Camera3Device::configureStreams(int operatingMode) {
     ATRACE_CALL();
     ALOGV("%s: E", __FUNCTION__);
 
     Mutex::Autolock il(mInterfaceLock);
     Mutex::Autolock l(mLock);
 
-    if (mIsConstrainedHighSpeedConfiguration != isConstrainedHighSpeed) {
-        mNeedConfig = true;
-        mIsConstrainedHighSpeedConfiguration = isConstrainedHighSpeed;
-    }
-
-    return configureStreamsLocked();
+    return configureStreamsLocked(operatingMode);
 }
 
 status_t Camera3Device::getInputBufferProducer(
@@ -2161,7 +2171,7 @@
     mNeedConfig = true;
 }
 
-status_t Camera3Device::configureStreamsLocked() {
+status_t Camera3Device::configureStreamsLocked(int operatingMode) {
     ATRACE_CALL();
     status_t res;
 
@@ -2170,6 +2180,21 @@
         return INVALID_OPERATION;
     }
 
+    if (operatingMode < 0) {
+        CLOGE("Invalid operating mode: %d", operatingMode);
+        return BAD_VALUE;
+    }
+
+    bool isConstrainedHighSpeed =
+            static_cast<int>(StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE) ==
+            operatingMode;
+
+    if (mOperatingMode != operatingMode) {
+        mNeedConfig = true;
+        mIsConstrainedHighSpeedConfiguration = isConstrainedHighSpeed;
+        mOperatingMode = operatingMode;
+    }
+
     if (!mNeedConfig) {
         ALOGV("%s: Skipping config, no stream changes", __FUNCTION__);
         return OK;
@@ -2188,9 +2213,7 @@
     ALOGV("%s: Camera %s: Starting stream configuration", __FUNCTION__, mId.string());
 
     camera3_stream_configuration config;
-    config.operation_mode = mIsConstrainedHighSpeedConfiguration ?
-            CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE :
-            CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE;
+    config.operation_mode = mOperatingMode;
     config.num_streams = (mInputStream != NULL) + mOutputStreams.size();
 
     Vector<camera3_stream_t*> streams;
@@ -3149,8 +3172,12 @@
             }
         }
 
-        requestedConfiguration.operationMode = mapToStreamConfigurationMode(
-                (camera3_stream_configuration_mode_t) config->operation_mode);
+        res = mapToStreamConfigurationMode(
+                (camera3_stream_configuration_mode_t) config->operation_mode,
+                /*out*/ &requestedConfiguration.operationMode);
+        if (res != OK) {
+            return res;
+        }
 
         // Invoke configureStreams
 
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index e19b62e..998cc0b 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -135,7 +135,9 @@
     status_t deleteStream(int id) override;
     status_t deleteReprocessStream(int id) override;
 
-    status_t configureStreams(bool isConstraiedHighSpeed = false) override;
+    status_t configureStreams(int operatingMode =
+            static_cast<int>(hardware::camera::device::V3_2::StreamConfigurationMode::NORMAL_MODE))
+            override;
     status_t getInputBufferProducer(
             sp<IGraphicBufferProducer> *producer) override;
 
@@ -212,6 +214,11 @@
     // Camera device ID
     const String8              mId;
 
+    // Current stream configuration mode;
+    int                        mOperatingMode;
+    // Constant to use for no set operating mode
+    static const int           NO_MODE = -1;
+
     // Flag indicating is the current active stream configuration is constrained high speed.
     bool                       mIsConstrainedHighSpeedConfiguration;
 
@@ -508,7 +515,7 @@
      * Take the currently-defined set of streams and configure the HAL to use
      * them. This is a long-running operation (may be several hundered ms).
      */
-    status_t           configureStreamsLocked();
+    status_t           configureStreamsLocked(int operatingMode);
 
     /**
      * Cancel stream configuration that did not finish successfully.
@@ -574,8 +581,9 @@
     static hardware::camera::device::V3_2::ConsumerUsageFlags mapToConsumerUsage(uint32_t usage);
     static hardware::camera::device::V3_2::StreamRotation mapToStreamRotation(
             camera3_stream_rotation_t rotation);
-    static hardware::camera::device::V3_2::StreamConfigurationMode mapToStreamConfigurationMode(
-            camera3_stream_configuration_mode_t operationMode);
+    // Returns a negative error code if the passed-in operation mode is not valid.
+    static status_t mapToStreamConfigurationMode(camera3_stream_configuration_mode_t operationMode,
+            /*out*/ hardware::camera::device::V3_2::StreamConfigurationMode *mode);
     static camera3_buffer_status_t mapHidlBufferStatus(hardware::camera::device::V3_2::BufferStatus status);
     static int mapToFrameworkFormat(hardware::graphics::common::V1_0::PixelFormat pixelFormat);
     static uint32_t mapConsumerToFrameworkUsage(
diff --git a/services/mediacodec/seccomp_policy/mediacodec-arm.policy b/services/mediacodec/seccomp_policy/mediacodec-arm.policy
index 081caf0..890d777 100644
--- a/services/mediacodec/seccomp_policy/mediacodec-arm.policy
+++ b/services/mediacodec/seccomp_policy/mediacodec-arm.policy
@@ -63,3 +63,4 @@
 getgid32: 1
 getegid32: 1
 getgroups32: 1
+recvmsg: 1
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy b/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy
index 72a1edb..96840a0 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy
@@ -43,9 +43,13 @@
 tgkill: 1
 socket: 1
 connect: 1
+recvmsg: 1
 fcntl64: 1
 rt_tgsigqueueinfo: 1
 geteuid32: 1
 getgid32: 1
 getegid32: 1
 getgroups32: 1
+getdents64: 1
+pipe2: 1
+ppoll: 1
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy b/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy
index 6f2d33f..c95ddb7 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy
@@ -34,9 +34,13 @@
 # socket: arg0 == AF_LOCAL
 socket: arg0 == 1
 connect: 1
+recvmsg: 1
 rt_tgsigqueueinfo: 1
 writev: 1
 geteuid: 1
 getgid: 1
 getegid: 1
 getgroups: 1
+getdents64: 1
+pipe2: 1
+ppoll: 1
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy b/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy
index 4a06e5a..19016cd 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy
@@ -48,3 +48,6 @@
 getgid32: 1
 getegid32: 1
 getgroups32: 1
+getdents64: 1
+pipe2: 1
+ppoll: 1
diff --git a/services/medialog/IMediaLogService.cpp b/services/medialog/IMediaLogService.cpp
index bc445ff..0e9b01e 100644
--- a/services/medialog/IMediaLogService.cpp
+++ b/services/medialog/IMediaLogService.cpp
@@ -29,6 +29,7 @@
 enum {
     REGISTER_WRITER = IBinder::FIRST_CALL_TRANSACTION,
     UNREGISTER_WRITER,
+    REQUEST_MERGE_WAKEUP,
 };
 
 class BpMediaLogService : public BpInterface<IMediaLogService>
@@ -57,6 +58,13 @@
         // FIXME ignores status
     }
 
+    virtual void    requestMergeWakeup() {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaLogService::getInterfaceDescriptor());
+        status_t status __unused = remote()->transact(REQUEST_MERGE_WAKEUP, data, &reply);
+        // FIXME ignores status
+    }
+
 };
 
 IMPLEMENT_META_INTERFACE(MediaLogService, "android.media.IMediaLogService");
@@ -84,6 +92,12 @@
             return NO_ERROR;
         }
 
+        case REQUEST_MERGE_WAKEUP: {
+            CHECK_INTERFACE(IMediaLogService, data, reply);
+            requestMergeWakeup();
+            return NO_ERROR;
+        }
+
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/services/medialog/MediaLogService.cpp b/services/medialog/MediaLogService.cpp
index 4c81436..aaf1018 100644
--- a/services/medialog/MediaLogService.cpp
+++ b/services/medialog/MediaLogService.cpp
@@ -27,6 +27,23 @@
 namespace android {
 
 // static const char kDeadlockedString[] = "MediaLogService may be deadlocked\n";
+MediaLogService::MediaLogService() :
+    BnMediaLogService(),
+    mMergerShared((NBLog::Shared*) malloc(NBLog::Timeline::sharedSize(kMergeBufferSize))),
+    mMerger(mMergerShared, kMergeBufferSize),
+    mMergeReader(mMergerShared, kMergeBufferSize, mMerger),
+    mMergeThread(new NBLog::MergeThread(mMerger))
+{
+    mMergeThread->run("MergeThread");
+}
+
+MediaLogService::~MediaLogService()
+{
+    mMergeThread->requestExit();
+    mMergeThread->setTimeoutUs(0);
+    mMergeThread->join();
+    free(mMergerShared);
+}
 
 void MediaLogService::registerWriter(const sp<IMemory>& shared, size_t size, const char *name)
 {
@@ -111,8 +128,7 @@
         mLock.unlock();
     }
 #endif
-
-    mMerger.merge();
+    // FIXME request merge to make sure log is up to date
     mMergeReader.dump(fd);
     return NO_ERROR;
 }
@@ -123,4 +139,8 @@
     return BnMediaLogService::onTransact(code, data, reply, flags);
 }
 
+void MediaLogService::requestMergeWakeup() {
+    mMergeThread->wakeup();
+}
+
 }   // namespace android
diff --git a/services/medialog/MediaLogService.h b/services/medialog/MediaLogService.h
index e934844..c6b99f1 100644
--- a/services/medialog/MediaLogService.h
+++ b/services/medialog/MediaLogService.h
@@ -27,13 +27,8 @@
 {
     friend class BinderService<MediaLogService>;    // for MediaLogService()
 public:
-    MediaLogService() :
-        BnMediaLogService(),
-        mMergerShared((NBLog::Shared*) malloc(NBLog::Timeline::sharedSize(kMergeBufferSize))),
-        mMerger(mMergerShared, kMergeBufferSize),
-        mMergeReader(mMergerShared, kMergeBufferSize, mMerger)
-    {ALOGI("Nico creating MergeReader");}
-    virtual ~MediaLogService() { free(mMergerShared); }
+    MediaLogService();
+    virtual ~MediaLogService() override;
     virtual void onFirstRef() { }
 
     static const char*  getServiceName() { return "media.log"; }
@@ -47,6 +42,8 @@
     virtual status_t    onTransact(uint32_t code, const Parcel& data, Parcel* reply,
                                 uint32_t flags);
 
+    virtual void        requestMergeWakeup() override;
+
 private:
 
     // Internal dump
@@ -58,10 +55,10 @@
     Mutex               mLock;
 
     Vector<NBLog::NamedReader> mNamedReaders;
-
     NBLog::Shared *mMergerShared;
     NBLog::Merger mMerger;
     NBLog::MergeReader mMergeReader;
+    const sp<NBLog::MergeThread> mMergeThread;
 };
 
 }   // namespace android
diff --git a/services/radio/RadioHalHidl.h b/services/radio/RadioHalHidl.h
index 38e181a..f98420d 100644
--- a/services/radio/RadioHalHidl.h
+++ b/services/radio/RadioHalHidl.h
@@ -29,7 +29,6 @@
 
 namespace android {
 
-using android::hardware::Status;
 using android::hardware::Return;
 using android::hardware::broadcastradio::V1_0::Result;
 using android::hardware::broadcastradio::V1_0::IBroadcastRadio;