Merge "Camera: add OFFLINE_PROCESSING APIs"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 76594fb..1eca2a1 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -84,3 +84,4 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.cas@1.1*)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.cas@1.1*)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/vintf/manifest/android.hardware.cas@1.1*)
+$(call add-clean-step, rm -rf $(OUT_DIR)/soong/.intermediates/hardware/interfaces/wifi/1.4/android.hardware.wifi@1.4-adapter_genc++/)
diff --git a/audio/6.0/IDevice.hal b/audio/6.0/IDevice.hal
index 122c550..c2e310c 100644
--- a/audio/6.0/IDevice.hal
+++ b/audio/6.0/IDevice.hal
@@ -168,6 +168,25 @@
             generates (Result retval, AudioPatchHandle patch);
 
     /**
+     * Updates an audio patch.
+     *
+     * Use of this function is preferred to releasing and re-creating a patch
+     * as the HAL module can figure out a way of switching the route without
+     * causing audio disruption.
+     *
+     * @param previousPatch handle of the previous patch to update.
+     * @param sources new patch sources.
+     * @param sinks new patch sinks.
+     * @return retval operation completion status.
+     * @return patch updated patch handle.
+     */
+    updateAudioPatch(
+            AudioPatchHandle previousPatch,
+            vec<AudioPortConfig> sources,
+            vec<AudioPortConfig> sinks) generates (
+                    Result retval, AudioPatchHandle patch);
+
+    /**
      * Release an audio patch.
      *
      * @param patch patch handle.
@@ -295,4 +314,28 @@
      */
     @exit
     close() generates (Result retval);
+
+    /**
+     * Applies an audio effect to an audio device.
+     *
+     * @param device identifies the sink or source device this effect must be applied to.
+     *               "device" is the AudioPortHandle indicated for the device when the audio
+     *                patch connecting that device was created.
+     * @param effectId effect ID (obtained from IEffectsFactory.createEffect) of
+     *                 the effect to add.
+     * @return retval operation completion status.
+     */
+    addDeviceEffect(AudioPortHandle device, uint64_t effectId) generates (Result retval);
+
+    /**
+     * Stops applying an audio effect to an audio device.
+     *
+     * @param device identifies the sink or source device this effect was applied to.
+     *               "device" is the AudioPortHandle indicated for the device when the audio
+     *               patch is created at the audio HAL.
+     * @param effectId effect ID (obtained from IEffectsFactory.createEffect) of
+     *                 the effect.
+     * @return retval operation completion status.
+     */
+    removeDeviceEffect(AudioPortHandle device, uint64_t effectId) generates (Result retval);
 };
diff --git a/audio/common/all-versions/default/service/Android.bp b/audio/common/all-versions/default/service/Android.bp
index 4565730..f58a599 100644
--- a/audio/common/all-versions/default/service/Android.bp
+++ b/audio/common/all-versions/default/service/Android.bp
@@ -41,6 +41,7 @@
         "android.hardware.soundtrigger@2.0",
         "android.hardware.soundtrigger@2.1",
         "android.hardware.soundtrigger@2.2",
+        "android.hardware.soundtrigger@2.3",
     ],
 }
 
diff --git a/audio/common/all-versions/default/service/service.cpp b/audio/common/all-versions/default/service/service.cpp
index 2730f3b..00bcb19 100644
--- a/audio/common/all-versions/default/service/service.cpp
+++ b/audio/common/all-versions/default/service/service.cpp
@@ -29,6 +29,7 @@
 #include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
 #include <android/hardware/soundtrigger/2.1/ISoundTriggerHw.h>
 #include <android/hardware/soundtrigger/2.2/ISoundTriggerHw.h>
+#include <android/hardware/soundtrigger/2.3/ISoundTriggerHw.h>
 #include <binder/ProcessState.h>
 #include <cutils/properties.h>
 #include <hidl/HidlTransportSupport.h>
@@ -78,9 +79,9 @@
                         "Could not register audio effect API");
     // clang-format on
 
-    ALOGW_IF((registerPassthroughServiceImplementations<soundtrigger::V2_2::ISoundTriggerHw,
-                                                        soundtrigger::V2_1::ISoundTriggerHw,
-                                                        soundtrigger::V2_0::ISoundTriggerHw>()),
+    ALOGW_IF((registerPassthroughServiceImplementations<
+                     soundtrigger::V2_3::ISoundTriggerHw, soundtrigger::V2_2::ISoundTriggerHw,
+                     soundtrigger::V2_1::ISoundTriggerHw, soundtrigger::V2_0::ISoundTriggerHw>()),
              "Could not register soundtrigger API");
 
     ALOGW_IF(registerPassthroughServiceImplementations<
diff --git a/audio/core/all-versions/default/Device.cpp b/audio/core/all-versions/default/Device.cpp
index 21dab00..47e31c1 100644
--- a/audio/core/all-versions/default/Device.cpp
+++ b/audio/core/all-versions/default/Device.cpp
@@ -18,6 +18,7 @@
 
 #include "core/default/Device.h"
 #include <HidlUtils.h>
+#include "common/all-versions/default/EffectMap.h"
 #include "core/default/Conversions.h"
 #include "core/default/StreamIn.h"
 #include "core/default/StreamOut.h"
@@ -25,6 +26,7 @@
 
 //#define LOG_NDEBUG 0
 
+#include <inttypes.h>
 #include <memory.h>
 #include <string.h>
 #include <algorithm>
@@ -84,26 +86,29 @@
         ALOGW("Can not set a master volume (%f) outside [0,1]", volume);
         return Result::INVALID_ARGUMENTS;
     }
-    return analyzeStatus("set_master_volume", mDevice->set_master_volume(mDevice, volume));
+    return analyzeStatus("set_master_volume", mDevice->set_master_volume(mDevice, volume),
+                         {ENOSYS} /*ignore*/);
 }
 
 Return<void> Device::getMasterVolume(getMasterVolume_cb _hidl_cb) {
     Result retval(Result::NOT_SUPPORTED);
     float volume = 0;
     if (mDevice->get_master_volume != NULL) {
-        retval = analyzeStatus("get_master_volume", mDevice->get_master_volume(mDevice, &volume));
+        retval = analyzeStatus("get_master_volume", mDevice->get_master_volume(mDevice, &volume),
+                               {ENOSYS} /*ignore*/);
     }
     _hidl_cb(retval, volume);
     return Void();
 }
 
 Return<Result> Device::setMicMute(bool mute) {
-    return analyzeStatus("set_mic_mute", mDevice->set_mic_mute(mDevice, mute));
+    return analyzeStatus("set_mic_mute", mDevice->set_mic_mute(mDevice, mute), {ENOSYS} /*ignore*/);
 }
 
 Return<void> Device::getMicMute(getMicMute_cb _hidl_cb) {
     bool mute = false;
-    Result retval = analyzeStatus("get_mic_mute", mDevice->get_mic_mute(mDevice, &mute));
+    Result retval = analyzeStatus("get_mic_mute", mDevice->get_mic_mute(mDevice, &mute),
+                                  {ENOSYS} /*ignore*/);
     _hidl_cb(retval, mute);
     return Void();
 }
@@ -111,7 +116,8 @@
 Return<Result> Device::setMasterMute(bool mute) {
     Result retval(Result::NOT_SUPPORTED);
     if (mDevice->set_master_mute != NULL) {
-        retval = analyzeStatus("set_master_mute", mDevice->set_master_mute(mDevice, mute));
+        retval = analyzeStatus("set_master_mute", mDevice->set_master_mute(mDevice, mute),
+                               {ENOSYS} /*ignore*/);
     }
     return retval;
 }
@@ -120,7 +126,8 @@
     Result retval(Result::NOT_SUPPORTED);
     bool mute = false;
     if (mDevice->get_master_mute != NULL) {
-        retval = analyzeStatus("get_master_mute", mDevice->get_master_mute(mDevice, &mute));
+        retval = analyzeStatus("get_master_mute", mDevice->get_master_mute(mDevice, &mute),
+                               {ENOSYS} /*ignore*/);
     }
     _hidl_cb(retval, mute);
     return Void();
@@ -262,12 +269,21 @@
 Return<void> Device::createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
                                       const hidl_vec<AudioPortConfig>& sinks,
                                       createAudioPatch_cb _hidl_cb) {
+    auto [retval, patch] = createOrUpdateAudioPatch(
+            static_cast<AudioPatchHandle>(AudioHandleConsts::AUDIO_PATCH_HANDLE_NONE), sources,
+            sinks);
+    _hidl_cb(retval, patch);
+    return Void();
+}
+
+std::tuple<Result, AudioPatchHandle> Device::createOrUpdateAudioPatch(
+        AudioPatchHandle patch, const hidl_vec<AudioPortConfig>& sources,
+        const hidl_vec<AudioPortConfig>& sinks) {
     Result retval(Result::NOT_SUPPORTED);
-    AudioPatchHandle patch = 0;
     if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
         std::unique_ptr<audio_port_config[]> halSources(HidlUtils::audioPortConfigsToHal(sources));
         std::unique_ptr<audio_port_config[]> halSinks(HidlUtils::audioPortConfigsToHal(sinks));
-        audio_patch_handle_t halPatch = AUDIO_PATCH_HANDLE_NONE;
+        audio_patch_handle_t halPatch = static_cast<audio_patch_handle_t>(patch);
         retval = analyzeStatus("create_audio_patch",
                                mDevice->create_audio_patch(mDevice, sources.size(), &halSources[0],
                                                            sinks.size(), &halSinks[0], &halPatch));
@@ -275,8 +291,7 @@
             patch = static_cast<AudioPatchHandle>(halPatch);
         }
     }
-    _hidl_cb(retval, patch);
-    return Void();
+    return {retval, patch};
 }
 
 Return<Result> Device::releaseAudioPatch(int32_t patch) {
@@ -398,6 +413,52 @@
 Return<Result> Device::close() {
     return doClose();
 }
+
+Return<Result> Device::addDeviceEffect(AudioPortHandle device, uint64_t effectId) {
+    if (version() < AUDIO_DEVICE_API_VERSION_3_1 || mDevice->add_device_effect == nullptr) {
+        return Result::NOT_SUPPORTED;
+    }
+
+    effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
+    if (halEffect != NULL) {
+        return analyzeStatus("add_device_effect",
+                             mDevice->add_device_effect(
+                                     mDevice, static_cast<audio_port_handle_t>(device), halEffect));
+    } else {
+        ALOGW("%s Invalid effect ID passed from client: %" PRIu64 "", __func__, effectId);
+        return Result::INVALID_ARGUMENTS;
+    }
+}
+
+Return<Result> Device::removeDeviceEffect(AudioPortHandle device, uint64_t effectId) {
+    if (version() < AUDIO_DEVICE_API_VERSION_3_1 || mDevice->remove_device_effect == nullptr) {
+        return Result::NOT_SUPPORTED;
+    }
+
+    effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
+    if (halEffect != NULL) {
+        return analyzeStatus("remove_device_effect",
+                             mDevice->remove_device_effect(
+                                     mDevice, static_cast<audio_port_handle_t>(device), halEffect));
+    } else {
+        ALOGW("%s Invalid effect ID passed from client: %" PRIu64 "", __func__, effectId);
+        return Result::INVALID_ARGUMENTS;
+    }
+}
+
+Return<void> Device::updateAudioPatch(int32_t previousPatch,
+                                      const hidl_vec<AudioPortConfig>& sources,
+                                      const hidl_vec<AudioPortConfig>& sinks,
+                                      createAudioPatch_cb _hidl_cb) {
+    if (previousPatch != static_cast<int32_t>(AudioHandleConsts::AUDIO_PATCH_HANDLE_NONE)) {
+        auto [retval, patch] = createOrUpdateAudioPatch(previousPatch, sources, sinks);
+        _hidl_cb(retval, patch);
+    } else {
+        _hidl_cb(Result::INVALID_ARGUMENTS, previousPatch);
+    }
+    return Void();
+}
+
 #endif
 
 }  // namespace implementation
diff --git a/audio/core/all-versions/default/PrimaryDevice.cpp b/audio/core/all-versions/default/PrimaryDevice.cpp
index 3cf0932..679f85d 100644
--- a/audio/core/all-versions/default/PrimaryDevice.cpp
+++ b/audio/core/all-versions/default/PrimaryDevice.cpp
@@ -168,6 +168,21 @@
 Return<Result> PrimaryDevice::close() {
     return mDevice->close();
 }
+
+Return<Result> PrimaryDevice::addDeviceEffect(AudioPortHandle device, uint64_t effectId) {
+    return mDevice->addDeviceEffect(device, effectId);
+}
+
+Return<Result> PrimaryDevice::removeDeviceEffect(AudioPortHandle device, uint64_t effectId) {
+    return mDevice->removeDeviceEffect(device, effectId);
+}
+
+Return<void> PrimaryDevice::updateAudioPatch(int32_t previousPatch,
+                                             const hidl_vec<AudioPortConfig>& sources,
+                                             const hidl_vec<AudioPortConfig>& sinks,
+                                             updateAudioPatch_cb _hidl_cb) {
+    return mDevice->updateAudioPatch(previousPatch, sources, sinks, _hidl_cb);
+}
 #endif
 
 // Methods from ::android::hardware::audio::CPP_VERSION::IPrimaryDevice follow.
diff --git a/audio/core/all-versions/default/StreamOut.cpp b/audio/core/all-versions/default/StreamOut.cpp
index 396d354..1a2a764 100644
--- a/audio/core/all-versions/default/StreamOut.cpp
+++ b/audio/core/all-versions/default/StreamOut.cpp
@@ -318,7 +318,8 @@
         ALOGW("Can not set a stream output volume {%f, %f} outside [0,1]", left, right);
         return Result::INVALID_ARGUMENTS;
     }
-    return Stream::analyzeStatus("set_volume", mStream->set_volume(mStream, left, right));
+    return Stream::analyzeStatus("set_volume", mStream->set_volume(mStream, left, right),
+                                 {ENOSYS} /*ignore*/);
 }
 
 Return<void> StreamOut::prepareForWriting(uint32_t frameSize, uint32_t framesCount,
@@ -403,7 +404,8 @@
 Return<void> StreamOut::getRenderPosition(getRenderPosition_cb _hidl_cb) {
     uint32_t halDspFrames;
     Result retval = Stream::analyzeStatus("get_render_position",
-                                          mStream->get_render_position(mStream, &halDspFrames));
+                                          mStream->get_render_position(mStream, &halDspFrames),
+                                          {ENOSYS} /*ignore*/);
     _hidl_cb(retval, halDspFrames);
     return Void();
 }
@@ -413,7 +415,8 @@
     int64_t timestampUs = 0;
     if (mStream->get_next_write_timestamp != NULL) {
         retval = Stream::analyzeStatus("get_next_write_timestamp",
-                                       mStream->get_next_write_timestamp(mStream, &timestampUs));
+                                       mStream->get_next_write_timestamp(mStream, &timestampUs),
+                                       {ENOSYS} /*ignore*/);
     }
     _hidl_cb(retval, timestampUs);
     return Void();
@@ -427,7 +430,7 @@
     if (result == 0) {
         mCallback = callback;
     }
-    return Stream::analyzeStatus("set_callback", result);
+    return Stream::analyzeStatus("set_callback", result, {ENOSYS} /*ignore*/);
 }
 
 Return<Result> StreamOut::clearCallback() {
@@ -473,13 +476,15 @@
 }
 
 Return<Result> StreamOut::pause() {
-    return mStream->pause != NULL ? Stream::analyzeStatus("pause", mStream->pause(mStream))
-                                  : Result::NOT_SUPPORTED;
+    return mStream->pause != NULL
+                   ? Stream::analyzeStatus("pause", mStream->pause(mStream), {ENOSYS} /*ignore*/)
+                   : Result::NOT_SUPPORTED;
 }
 
 Return<Result> StreamOut::resume() {
-    return mStream->resume != NULL ? Stream::analyzeStatus("resume", mStream->resume(mStream))
-                                   : Result::NOT_SUPPORTED;
+    return mStream->resume != NULL
+                   ? Stream::analyzeStatus("resume", mStream->resume(mStream), {ENOSYS} /*ignore*/)
+                   : Result::NOT_SUPPORTED;
 }
 
 Return<bool> StreamOut::supportsDrain() {
@@ -488,14 +493,17 @@
 
 Return<Result> StreamOut::drain(AudioDrain type) {
     return mStream->drain != NULL
-               ? Stream::analyzeStatus(
-                     "drain", mStream->drain(mStream, static_cast<audio_drain_type_t>(type)))
-               : Result::NOT_SUPPORTED;
+                   ? Stream::analyzeStatus(
+                             "drain",
+                             mStream->drain(mStream, static_cast<audio_drain_type_t>(type)),
+                             {ENOSYS} /*ignore*/)
+                   : Result::NOT_SUPPORTED;
 }
 
 Return<Result> StreamOut::flush() {
-    return mStream->flush != NULL ? Stream::analyzeStatus("flush", mStream->flush(mStream))
-                                  : Result::NOT_SUPPORTED;
+    return mStream->flush != NULL
+                   ? Stream::analyzeStatus("flush", mStream->flush(mStream), {ENOSYS} /*ignore*/)
+                   : Result::NOT_SUPPORTED;
 }
 
 // static
@@ -505,7 +513,7 @@
     // to return it sometimes. EAGAIN may be returned by A2DP audio HAL
     // implementation. ENODATA can also be reported while the writer is
     // continuously querying it, but the stream has been stopped.
-    static const std::vector<int> ignoredErrors{EINVAL, EAGAIN, ENODATA};
+    static const std::vector<int> ignoredErrors{EINVAL, EAGAIN, ENODATA, ENOSYS};
     Result retval(Result::NOT_SUPPORTED);
     if (stream->get_presentation_position == NULL) return retval;
     struct timespec halTimeStamp;
diff --git a/audio/core/all-versions/default/include/core/default/Device.h b/audio/core/all-versions/default/include/core/default/Device.h
index 11ab607..b0e72d9 100644
--- a/audio/core/all-versions/default/include/core/default/Device.h
+++ b/audio/core/all-versions/default/include/core/default/Device.h
@@ -116,8 +116,12 @@
 #endif
 #if MAJOR_VERSION >= 6
     Return<Result> close() override;
+    Return<Result> addDeviceEffect(AudioPortHandle device, uint64_t effectId) override;
+    Return<Result> removeDeviceEffect(AudioPortHandle device, uint64_t effectId) override;
+    Return<void> updateAudioPatch(int32_t previousPatch, const hidl_vec<AudioPortConfig>& sources,
+                                  const hidl_vec<AudioPortConfig>& sinks,
+                                  createAudioPatch_cb _hidl_cb) override;
 #endif
-
     Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
 
     // Utility methods for extending interfaces.
@@ -135,6 +139,9 @@
     virtual ~Device();
 
     Result doClose();
+    std::tuple<Result, AudioPatchHandle> createOrUpdateAudioPatch(
+            AudioPatchHandle patch, const hidl_vec<AudioPortConfig>& sources,
+            const hidl_vec<AudioPortConfig>& sinks);
 
     // Methods from ParametersUtil.
     char* halGetParameters(const char* keys) override;
diff --git a/audio/core/all-versions/default/include/core/default/PrimaryDevice.h b/audio/core/all-versions/default/include/core/default/PrimaryDevice.h
index f5f3848..ccdb7b2 100644
--- a/audio/core/all-versions/default/include/core/default/PrimaryDevice.h
+++ b/audio/core/all-versions/default/include/core/default/PrimaryDevice.h
@@ -98,6 +98,11 @@
 #endif
 #if MAJOR_VERSION >= 6
     Return<Result> close() override;
+    Return<Result> addDeviceEffect(AudioPortHandle device, uint64_t effectId) override;
+    Return<Result> removeDeviceEffect(AudioPortHandle device, uint64_t effectId) override;
+    Return<void> updateAudioPatch(int32_t previousPatch, const hidl_vec<AudioPortConfig>& sources,
+                                  const hidl_vec<AudioPortConfig>& sinks,
+                                  updateAudioPatch_cb _hidl_cb) override;
 #endif
 
     Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
diff --git a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
index 2afbbb8..09ef330 100644
--- a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
@@ -181,3 +181,12 @@
     ASSERT_OK(getDevice()->close());
     ASSERT_TRUE(resetDevice());
 }
+
+TEST_P(AudioPatchHidlTest, UpdatePatchInvalidHandle) {
+    doc::test("Verify that passing an invalid handle to updateAudioPatch is checked");
+    AudioPatchHandle ignored;
+    ASSERT_OK(getDevice()->updateAudioPatch(
+            static_cast<int32_t>(AudioHandleConsts::AUDIO_PATCH_HANDLE_NONE),
+            hidl_vec<AudioPortConfig>(), hidl_vec<AudioPortConfig>(), returnIn(res, ignored)));
+    ASSERT_RESULT(Result::INVALID_ARGUMENTS, res);
+}
diff --git a/automotive/can/1.0/default/CanBus.cpp b/automotive/can/1.0/default/CanBus.cpp
index 42d2e3c..86df5dc 100644
--- a/automotive/can/1.0/default/CanBus.cpp
+++ b/automotive/can/1.0/default/CanBus.cpp
@@ -22,6 +22,8 @@
 #include <libnetdevice/can.h>
 #include <libnetdevice/libnetdevice.h>
 #include <linux/can.h>
+#include <linux/can/error.h>
+#include <linux/can/raw.h>
 
 namespace android {
 namespace hardware {
@@ -220,6 +222,21 @@
 }
 
 /**
+ * Helper function to determine if a flag meets the requirements of a
+ * FilterFlag. See definition of FilterFlag in types.hal
+ *
+ * \param filterFlag FilterFlag object to match flag against
+ * \param flag bool object from CanMessage object
+ */
+static bool satisfiesFilterFlag(FilterFlag filterFlag, bool flag) {
+    // TODO(b/144458917) add testing for this to VTS tests
+    if (filterFlag == FilterFlag::DONT_CARE) return true;
+    if (filterFlag == FilterFlag::REQUIRE) return flag;
+    if (filterFlag == FilterFlag::EXCLUDE) return !flag;
+    return false;
+}
+
+/**
  * Match the filter set against message id.
  *
  * For details on the filters syntax, please see CanMessageFilter at
@@ -229,13 +246,16 @@
  * \param id Message id to filter
  * \return true if the message id matches the filter, false otherwise
  */
-static bool match(const hidl_vec<CanMessageFilter>& filter, CanMessageId id) {
+static bool match(const hidl_vec<CanMessageFilter>& filter, CanMessageId id, bool isExtendedId,
+                  bool isRtr) {
     if (filter.size() == 0) return true;
 
     bool anyNonInvertedPresent = false;
     bool anyNonInvertedSatisfied = false;
     for (auto& rule : filter) {
-        const bool satisfied = ((id & rule.mask) == rule.id) == !rule.inverted;
+        const bool satisfied = ((id & rule.mask) == rule.id) == !rule.inverted &&
+                               satisfiesFilterFlag(rule.rtr, isRtr) &&
+                               satisfiesFilterFlag(rule.extendedFormat, isExtendedId);
         if (rule.inverted) {
             // Any inverted (blacklist) rule not being satisfied invalidates the whole filter set.
             if (!satisfied) return false;
@@ -247,11 +267,54 @@
     return !anyNonInvertedPresent || anyNonInvertedSatisfied;
 }
 
+void CanBus::notifyErrorListeners(ErrorEvent err, bool isFatal) {
+    std::lock_guard<std::mutex> lck(mErrListenersGuard);
+    for (auto& listener : mErrListeners) {
+        if (!listener->onError(err, isFatal).isOk()) {
+            LOG(WARNING) << "Failed to notify listener about error";
+        }
+    }
+}
+
+static ErrorEvent parseErrorFrame(const struct canfd_frame& frame) {
+    // decode error frame (to a degree)
+    if ((frame.can_id & (CAN_ERR_BUSERROR | CAN_ERR_BUSOFF)) != 0) {
+        return ErrorEvent::BUS_ERROR;
+    }
+    if ((frame.data[1] & CAN_ERR_CRTL_TX_OVERFLOW) != 0) {
+        return ErrorEvent::TX_OVERFLOW;
+    }
+    if ((frame.data[1] & CAN_ERR_CRTL_RX_OVERFLOW) != 0) {
+        return ErrorEvent::RX_OVERFLOW;
+    }
+    if ((frame.data[2] & CAN_ERR_PROT_OVERLOAD) != 0) {
+        return ErrorEvent::BUS_OVERLOAD;
+    }
+    if ((frame.can_id & CAN_ERR_PROT) != 0) {
+        return ErrorEvent::MALFORMED_INPUT;
+    }
+    if ((frame.can_id & (CAN_ERR_CRTL | CAN_ERR_TRX | CAN_ERR_RESTARTED)) != 0) {
+        // "controller restarted" constitutes a HARDWARE_ERROR imo
+        return ErrorEvent::HARDWARE_ERROR;
+    }
+    return ErrorEvent::UNKNOWN_ERROR;
+}
+
 void CanBus::onRead(const struct canfd_frame& frame, std::chrono::nanoseconds timestamp) {
+    if ((frame.can_id & CAN_ERR_FLAG) != 0) {
+        // error bit is set
+        LOG(WARNING) << "CAN Error frame received";
+        // TODO(b/144458917) consider providing different values for isFatal, depending on error
+        notifyErrorListeners(parseErrorFrame(frame), false);
+        return;
+    }
+
     CanMessage message = {};
-    message.id = frame.can_id;
+    message.id = frame.can_id & CAN_EFF_MASK;  // mask out eff/rtr/err flags
     message.payload = hidl_vec<uint8_t>(frame.data, frame.data + frame.len);
     message.timestamp = timestamp.count();
+    message.isExtendedId = (frame.can_id & CAN_EFF_FLAG) != 0;
+    message.remoteTransmissionRequest = (frame.can_id & CAN_RTR_FLAG) != 0;
 
     if (UNLIKELY(kSuperVerbose)) {
         LOG(VERBOSE) << "Got message " << toString(message);
@@ -259,7 +322,9 @@
 
     std::lock_guard<std::mutex> lck(mMsgListenersGuard);
     for (auto& listener : mMsgListeners) {
-        if (!match(listener.filter, message.id)) continue;
+        if (!match(listener.filter, message.id, message.remoteTransmissionRequest,
+                   message.isExtendedId))
+            continue;
         if (!listener.callback->onReceive(message).isOk() && !listener.failedOnce) {
             listener.failedOnce = true;
             LOG(WARNING) << "Failed to notify listener about message";
@@ -274,15 +339,7 @@
         mDownAfterUse = false;
         eventType = ErrorEvent::INTERFACE_DOWN;
     }
-
-    {
-        std::lock_guard<std::mutex> lck(mErrListenersGuard);
-        for (auto& listener : mErrListeners) {
-            if (!listener->onError(eventType, true).isOk()) {
-                LOG(WARNING) << "Failed to notify listener about error";
-            }
-        }
-    }
+    notifyErrorListeners(eventType, true);
 
     const auto errcb = mErrCb;
     if (errcb != nullptr) errcb();
diff --git a/automotive/can/1.0/default/CanBus.h b/automotive/can/1.0/default/CanBus.h
index 365e90c..da3fc5a 100644
--- a/automotive/can/1.0/default/CanBus.h
+++ b/automotive/can/1.0/default/CanBus.h
@@ -89,6 +89,8 @@
     void clearMsgListeners();
     void clearErrListeners();
 
+    void notifyErrorListeners(ErrorEvent err, bool isFatal);
+
     void onRead(const struct canfd_frame& frame, std::chrono::nanoseconds timestamp);
     void onError(int errnoVal);
 
diff --git a/automotive/can/1.0/default/libnetdevice/can.cpp b/automotive/can/1.0/default/libnetdevice/can.cpp
index 87617dd..6452d9b 100644
--- a/automotive/can/1.0/default/libnetdevice/can.cpp
+++ b/automotive/can/1.0/default/libnetdevice/can.cpp
@@ -24,12 +24,16 @@
 #include <android-base/unique_fd.h>
 
 #include <linux/can.h>
+#include <linux/can/error.h>
 #include <linux/can/netlink.h>
+#include <linux/can/raw.h>
 
 namespace android {
 namespace netdevice {
 namespace can {
 
+static constexpr can_err_mask_t kErrMask = CAN_ERR_MASK;
+
 base::unique_fd socket(const std::string& ifname) {
     struct sockaddr_can addr = {};
     addr.can_family = AF_CAN;
@@ -45,6 +49,11 @@
         return {};
     }
 
+    if (setsockopt(sock.get(), SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &kErrMask, sizeof(kErrMask)) < 0) {
+        LOG(ERROR) << "Can't receive error frames, CAN setsockpt failed: " << strerror(errno);
+        return {};
+    }
+
     if (0 != fcntl(sock.get(), F_SETFL, O_RDWR | O_NONBLOCK)) {
         LOG(ERROR) << "Couldn't put CAN socket in non-blocking mode";
         return {};
diff --git a/automotive/can/1.0/tools/canhaldump.cpp b/automotive/can/1.0/tools/canhaldump.cpp
index 99fd14a..55b2a34 100644
--- a/automotive/can/1.0/tools/canhaldump.cpp
+++ b/automotive/can/1.0/tools/canhaldump.cpp
@@ -20,6 +20,7 @@
 #include <android/hidl/manager/1.2/IServiceManager.h>
 #include <hidl-utils/hidl-utils.h>
 
+#include <linux/can.h>
 #include <chrono>
 #include <iomanip>
 #include <iostream>
@@ -42,12 +43,14 @@
     CanMessageListener(std::string name) : name(name) {}
 
     virtual Return<void> onReceive(const V1_0::CanMessage& message) {
-        std::cout << "  " << name << "  " << std::hex << std::uppercase << std::setw(3)
+        int msgIdWidth = 3;
+        if (message.isExtendedId) msgIdWidth = 8;
+        std::cout << "  " << name << "  " << std::hex << std::uppercase << std::setw(msgIdWidth)
                   << std::setfill('0') << message.id << std::setw(0);
+        std::cout << "   [" << message.payload.size() << "] ";
         if (message.remoteTransmissionRequest) {
-            std::cout << " RTR";
+            std::cout << "remote request";
         } else {
-            std::cout << "   [" << message.payload.size() << "] ";
             for (const auto byte : message.payload) {
                 std::cout << " " << std::setfill('0') << std::setw(2) << unsigned(byte);
             }
diff --git a/automotive/can/1.0/types.hal b/automotive/can/1.0/types.hal
index 6f690f7..f09c940 100644
--- a/automotive/can/1.0/types.hal
+++ b/automotive/can/1.0/types.hal
@@ -58,6 +58,15 @@
      * If this flag is set, payload must be empty.
      */
     bool remoteTransmissionRequest;
+
+    /**
+     * Flag indicating if the message has an extended ID.
+     *
+     * Extended ID's are 29 bits long, as opposed to the standard 11 bit ID.
+     * It can not simply be inferred from the length of the ID itself, as the
+     * message ID 0x00000123 !=  message ID 0x123.
+     */
+    bool isExtendedId;
 };
 
 /**
@@ -70,11 +79,30 @@
  * one) and all inverted filters must match. In other words:
  *  - a single matching non-inverted filter makes the whole set matching;
  *  - a single non-matching inverted filter makes the whole set non-matching.
+ *
+ * Additional less common options for filtering include:
+ * rtr - Remote Transmission Request; another ECU requests DLC bytes of data on this message ID
+ * extendedFormat - 29 bit message ID is used instead of 11 bits
  */
 struct CanMessageFilter {
     CanMessageId id;
     uint32_t mask;
     bool inverted;
+    FilterFlag rtr;
+    FilterFlag extendedFormat;
+};
+
+
+/**
+ * Types of filter that can be applied to a CanMessageFilter
+ */
+enum FilterFlag : uint8_t {
+    /** Default, FilterFlag doesn't effect what messages filtered */
+    DONT_CARE = 0,
+    /** This FilterFlag MUST be present in received messages to pass though the filter */
+    REQUIRE,
+    /** This FilterFlag must NOT be present in received messages to pass though the filter */
+    EXCLUDE,
 };
 
 enum Result : uint8_t {
diff --git a/automotive/can/1.0/vts/functional/VtsHalCanBusV1_0TargetTest.cpp b/automotive/can/1.0/vts/functional/VtsHalCanBusV1_0TargetTest.cpp
index 1a05716..250caf2 100644
--- a/automotive/can/1.0/vts/functional/VtsHalCanBusV1_0TargetTest.cpp
+++ b/automotive/can/1.0/vts/functional/VtsHalCanBusV1_0TargetTest.cpp
@@ -123,9 +123,9 @@
 
 TEST_F(CanBusHalTest, ListenSomeFilter) {
     hidl_vec<CanMessageFilter> filters = {
-            {0x123, 0x1FF, false},
-            {0x001, 0x00F, true},
-            {0x200, 0x100, false},
+            {0x123, 0x1FF, false, FilterFlag::DONT_CARE, FilterFlag::DONT_CARE},
+            {0x001, 0x00F, true, FilterFlag::DONT_CARE, FilterFlag::DONT_CARE},
+            {0x200, 0x100, false, FilterFlag::DONT_CARE, FilterFlag::DONT_CARE},
     };
 
     const auto [result, closeHandle] = listen(filters, new CanMessageListener());
diff --git a/automotive/can/1.0/vts/functional/VtsHalCanBusVirtualV1_0TargetTest.cpp b/automotive/can/1.0/vts/functional/VtsHalCanBusVirtualV1_0TargetTest.cpp
index 225984d..695b9fb 100644
--- a/automotive/can/1.0/vts/functional/VtsHalCanBusVirtualV1_0TargetTest.cpp
+++ b/automotive/can/1.0/vts/functional/VtsHalCanBusVirtualV1_0TargetTest.cpp
@@ -244,14 +244,14 @@
     auto bus2 = makeBus();
 
     hidl_vec<CanMessageFilter> filterPositive = {
-            {0x101, 0x100, false},
-            {0x010, 0x0F0, false},
+            {0x101, 0x100, false, FilterFlag::DONT_CARE, FilterFlag::DONT_CARE},
+            {0x010, 0x0F0, false, FilterFlag::DONT_CARE, FilterFlag::DONT_CARE},
     };
     auto listenerPositive = bus2.listen(filterPositive);
 
     hidl_vec<CanMessageFilter> filterNegative = {
-            {0x123, 0x0FF, true},
-            {0x004, 0x00F, true},
+            {0x123, 0x0FF, true, FilterFlag::DONT_CARE, FilterFlag::DONT_CARE},
+            {0x004, 0x00F, true, FilterFlag::DONT_CARE, FilterFlag::DONT_CARE},
     };
     auto listenerNegative = bus2.listen(filterNegative);
 
diff --git a/automotive/evs/common/utils/default/Android.bp b/automotive/evs/common/utils/default/Android.bp
index 7734f5c..776ef81 100644
--- a/automotive/evs/common/utils/default/Android.bp
+++ b/automotive/evs/common/utils/default/Android.bp
@@ -15,6 +15,7 @@
 //
 
 cc_library_static {
+    host_supported: true,
     name: "android.hardware.automotive.evs@common-default-lib",
     vendor_available: true,
     relative_install_path: "hw",
diff --git a/automotive/evs/common/utils/default/test/fuzz/Android.bp b/automotive/evs/common/utils/default/test/fuzz/Android.bp
new file mode 100644
index 0000000..105ec68
--- /dev/null
+++ b/automotive/evs/common/utils/default/test/fuzz/Android.bp
@@ -0,0 +1,99 @@
+//
+// Copyright (C) 2019 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.
+//
+
+cc_fuzz {
+    host_supported: true,
+    name : "FormatConvertFuzzer_copyNV21toRGB32",
+    srcs: [
+        "FormatConvertFuzzer.cpp",
+    ],
+    static_libs: [
+        "android.hardware.automotive.evs@common-default-lib"
+    ],
+    cflags: [
+        "-DCOPY_NV21_TO_RGB32",
+    ],
+}
+
+cc_fuzz {
+    host_supported: true,
+    name : "FormatConvertFuzzer_copyNV21toBGR32",
+    srcs: [
+        "FormatConvertFuzzer.cpp",
+    ],
+    static_libs: [
+        "android.hardware.automotive.evs@common-default-lib"
+    ],
+    cflags: [
+        "-DCOPY_NV21_TO_BGR32",
+    ],
+}
+
+cc_fuzz {
+    host_supported: true,
+    name : "FormatConvertFuzzer_copyYV12toRGB32",
+    srcs: [
+        "FormatConvertFuzzer.cpp",
+    ],
+    static_libs: [
+        "android.hardware.automotive.evs@common-default-lib"
+    ],
+    cflags: [
+        "-DCOPY_YV12_TO_RGB32",
+    ],
+}
+
+cc_fuzz {
+    host_supported: true,
+    name : "FormatConvertFuzzer_copyYV12toBGR32",
+    srcs: [
+        "FormatConvertFuzzer.cpp",
+    ],
+    static_libs: [
+        "android.hardware.automotive.evs@common-default-lib"
+    ],
+    cflags: [
+        "-DCOPY_YV12_TO_BGR32",
+    ],
+}
+
+cc_fuzz {
+    host_supported: true,
+    name : "FormatConvertFuzzer_copyYUYVtoRGB32",
+    srcs: [
+        "FormatConvertFuzzer.cpp",
+    ],
+    static_libs: [
+        "android.hardware.automotive.evs@common-default-lib"
+    ],
+    cflags: [
+        "-DCOPY_YUYV_TO_RGB32",
+    ],
+}
+
+cc_fuzz {
+    host_supported: true,
+    name : "FormatConvertFuzzer_copyYUYVtoBGR32",
+    srcs: [
+        "FormatConvertFuzzer.cpp",
+    ],
+    static_libs: [
+        "android.hardware.automotive.evs@common-default-lib"
+    ],
+    cflags: [
+        "-DCOPY_YUYV_TO_BGR32",
+    ],
+}
diff --git a/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp b/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
new file mode 100644
index 0000000..583a455
--- /dev/null
+++ b/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2019 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 <cmath>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include "FormatConvert.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, std::size_t size) {
+    if (size < 256) {
+        return 0;
+    }
+
+    std::srand(std::time(nullptr));  // use current time as seed for random generator
+    int random_variable = std::rand() % 10;
+    int width = (int)sqrt(size);
+    int height = width * ((float)random_variable / 10.0);
+
+    uint8_t* src = (uint8_t*)malloc(sizeof(uint8_t) * size);
+    memcpy(src, data, sizeof(uint8_t) * (size));
+    uint32_t* tgt = (uint32_t*)malloc(sizeof(uint32_t) * size);
+
+#ifdef COPY_NV21_TO_RGB32
+    android::hardware::automotive::evs::common::Utils::copyNV21toRGB32(width, height, src, tgt, 0);
+#elif COPY_NV21_TO_BGR32
+    android::hardware::automotive::evs::common::Utils::copyNV21toBGR32(width, height, src, tgt, 0);
+#elif COPY_YV12_TO_RGB32
+    android::hardware::automotive::evs::common::Utils::copyYV12toRGB32(width, height, src, tgt, 0);
+#elif COPY_YV12_TO_BGR32
+    android::hardware::automotive::evs::common::Utils::copyYV12toBGR32(width, height, src, tgt, 0);
+#elif COPY_YUYV_TO_RGB32
+    android::hardware::automotive::evs::common::Utils::copyYUYVtoRGB32(width, height, src, 0, tgt,
+                                                                       0);
+#elif COPY_YUYV_TO_BGR32
+    android::hardware::automotive::evs::common::Utils::copyYUYVtoBGR32(width, height, src, 0, tgt,
+                                                                       0);
+#endif
+
+    free(src);
+    free(tgt);
+
+    return 0;
+}
diff --git a/broadcastradio/2.0/vts/OWNERS b/broadcastradio/2.0/vts/OWNERS
index 12adf57..1ff7407 100644
--- a/broadcastradio/2.0/vts/OWNERS
+++ b/broadcastradio/2.0/vts/OWNERS
@@ -3,5 +3,4 @@
 twasilczyk@google.com
 
 # VTS team
-yuexima@google.com
-yim@google.com
+dshi@google.com
diff --git a/broadcastradio/2.0/vts/functional/Android.bp b/broadcastradio/2.0/vts/functional/Android.bp
index 3e18a54..49bb665 100644
--- a/broadcastradio/2.0/vts/functional/Android.bp
+++ b/broadcastradio/2.0/vts/functional/Android.bp
@@ -17,9 +17,6 @@
 cc_test {
     name: "VtsHalBroadcastradioV2_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
-    cppflags: [
-        "-std=c++1z",
-    ],
     srcs: ["VtsHalBroadcastradioV2_0TargetTest.cpp"],
     static_libs: [
         "android.hardware.broadcastradio@2.0",
@@ -28,5 +25,8 @@
         "android.hardware.broadcastradio@vts-utils-lib",
         "libgmock",
     ],
-    test_suites: ["general-tests"],
+    test_suites: [
+        "general-tests",
+        "vts-core",
+    ],
 }
diff --git a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
index e36f4d9..d170a6d 100644
--- a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
+++ b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
@@ -16,7 +16,6 @@
 
 #define EGMOCK_VERBOSE 1
 
-#include <VtsHalHidlTargetTestBase.h>
 #include <android-base/logging.h>
 #include <android-base/strings.h>
 #include <android/hardware/broadcastradio/2.0/IBroadcastRadio.h>
@@ -25,11 +24,13 @@
 #include <android/hardware/broadcastradio/2.0/types.h>
 #include <broadcastradio-utils-2x/Utils.h>
 #include <broadcastradio-vts-utils/call-barrier.h>
-#include <broadcastradio-vts-utils/environment-utils.h>
 #include <broadcastradio-vts-utils/mock-timeout.h>
 #include <broadcastradio-vts-utils/pointer-utils.h>
 #include <cutils/bitops.h>
 #include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include <chrono>
 #include <optional>
@@ -52,7 +53,6 @@
 using testing::Invoke;
 using testing::SaveArg;
 
-using broadcastradio::vts::BroadcastRadioHidlEnvironment;
 using broadcastradio::vts::CallBarrier;
 using broadcastradio::vts::clearAndWait;
 using utils::make_identifier;
@@ -100,10 +100,8 @@
     MOCK_METHOD1(onListUpdated, Return<void>(const hidl_vec<Announcement>&));
 };
 
-static BroadcastRadioHidlEnvironment<IBroadcastRadio>* gEnv = nullptr;
-
-class BroadcastRadioHalTest : public ::testing::VtsHalHidlTargetTestBase {
-   protected:
+class BroadcastRadioHalTest : public ::testing::TestWithParam<std::string> {
+  protected:
     virtual void SetUp() override;
     virtual void TearDown() override;
 
@@ -185,7 +183,7 @@
     EXPECT_EQ(nullptr, mModule.get()) << "Module is already open";
 
     // lookup HIDL service (radio module)
-    mModule = getService<IBroadcastRadio>(gEnv->getServiceName<IBroadcastRadio>());
+    mModule = IBroadcastRadio::getService(GetParam());
     ASSERT_NE(nullptr, mModule.get()) << "Couldn't find broadcast radio HAL implementation";
 
     // get module properties
@@ -243,10 +241,10 @@
     auto startResult = mSession->startProgramListUpdates({});
     if (startResult == Result::NOT_SUPPORTED) {
         printSkipped("Program list not supported");
-        return nullopt;
+        return std::nullopt;
     }
     EXPECT_EQ(Result::OK, startResult);
-    if (startResult != Result::OK) return nullopt;
+    if (startResult != Result::OK) return std::nullopt;
 
     EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onProgramListReady, timeout::programListScan);
 
@@ -264,7 +262,7 @@
  *  - the method succeeds when called for the second time without
  *    closing previous session.
  */
-TEST_F(BroadcastRadioHalTest, OpenSession) {
+TEST_P(BroadcastRadioHalTest, OpenSession) {
     // simply open session for the first time
     ASSERT_TRUE(openSession());
 
@@ -308,7 +306,7 @@
  *  - all channel grids (frequency ranges and spacings) are valid;
  *  - seek spacing is a multiple of the manual spacing value.
  */
-TEST_F(BroadcastRadioHalTest, GetAmFmRegionConfig) {
+TEST_P(BroadcastRadioHalTest, GetAmFmRegionConfig) {
     AmFmRegionConfig config;
     bool supported = getAmFmRegionConfig(false, &config);
     if (!supported) {
@@ -341,7 +339,7 @@
  *  - all channel grids (frequency ranges and spacings) are valid;
  *  - seek spacing is not set.
  */
-TEST_F(BroadcastRadioHalTest, GetAmFmRegionConfigCapabilities) {
+TEST_P(BroadcastRadioHalTest, GetAmFmRegionConfigCapabilities) {
     AmFmRegionConfig config;
     bool supported = getAmFmRegionConfig(true, &config);
     if (!supported) {
@@ -369,7 +367,7 @@
  *  - all channel labels match correct format;
  *  - all channel frequencies are in correct range.
  */
-TEST_F(BroadcastRadioHalTest, GetDabRegionConfig) {
+TEST_P(BroadcastRadioHalTest, GetDabRegionConfig) {
     Result halResult;
     hidl_vec<DabTableEntry> config;
     auto cb = [&](Result result, hidl_vec<DabTableEntry> configCb) {
@@ -411,7 +409,7 @@
  *    invoked carrying a proper selector;
  *  - program changes exactly to what was requested.
  */
-TEST_F(BroadcastRadioHalTest, FmTune) {
+TEST_P(BroadcastRadioHalTest, FmTune) {
     ASSERT_TRUE(openSession());
 
     uint64_t freq = 100100;  // 100.1 FM
@@ -458,7 +456,7 @@
  *  - if the selector is not supported, it's ignored;
  *  - if it is supported, an invalid value results with INVALID_ARGUMENTS;
  */
-TEST_F(BroadcastRadioHalTest, TuneFailsWithInvalid) {
+TEST_P(BroadcastRadioHalTest, TuneFailsWithInvalid) {
     ASSERT_TRUE(openSession());
 
     vector<ProgramIdentifier> invalid = {
@@ -489,7 +487,7 @@
  * Verifies that:
  *  - tune fails with NOT_SUPPORTED when program selector is not initialized.
  */
-TEST_F(BroadcastRadioHalTest, TuneFailsWithEmpty) {
+TEST_P(BroadcastRadioHalTest, TuneFailsWithEmpty) {
     ASSERT_TRUE(openSession());
 
     // Program type is 1-based, so 0 will always be invalid.
@@ -506,7 +504,7 @@
  *  - the program info is changed within timeout::tune;
  *  - works both directions and with or without skipping sub-channel.
  */
-TEST_F(BroadcastRadioHalTest, Seek) {
+TEST_P(BroadcastRadioHalTest, Seek) {
     ASSERT_TRUE(openSession());
 
     // TODO(b/69958777): see FmTune workaround
@@ -531,7 +529,7 @@
  *  - the program info is changed within timeout::tune if the method succeeded;
  *  - works both directions.
  */
-TEST_F(BroadcastRadioHalTest, Step) {
+TEST_P(BroadcastRadioHalTest, Step) {
     ASSERT_TRUE(openSession());
 
     // TODO(b/69958777): see FmTune workaround
@@ -558,7 +556,7 @@
  * Verifies that:
  *  - the method does not crash after being invoked multiple times.
  */
-TEST_F(BroadcastRadioHalTest, Cancel) {
+TEST_P(BroadcastRadioHalTest, Cancel) {
     ASSERT_TRUE(openSession());
 
     for (int i = 0; i < 10; i++) {
@@ -576,7 +574,7 @@
  * Verifies that:
  *  - callback is called for empty parameters set.
  */
-TEST_F(BroadcastRadioHalTest, NoParameters) {
+TEST_P(BroadcastRadioHalTest, NoParameters) {
     ASSERT_TRUE(openSession());
 
     hidl_vec<VendorKeyValue> halResults = {};
@@ -605,7 +603,7 @@
  *  - unknown parameters are ignored;
  *  - callback is called also for empty results set.
  */
-TEST_F(BroadcastRadioHalTest, UnknownParameters) {
+TEST_P(BroadcastRadioHalTest, UnknownParameters) {
     ASSERT_TRUE(openSession());
 
     hidl_vec<VendorKeyValue> halResults = {};
@@ -633,7 +631,7 @@
  * Verifies that:
  *  - the method does not crash after being invoked multiple times.
  */
-TEST_F(BroadcastRadioHalTest, Close) {
+TEST_P(BroadcastRadioHalTest, Close) {
     ASSERT_TRUE(openSession());
 
     for (int i = 0; i < 10; i++) {
@@ -648,7 +646,7 @@
  * Verifies that:
  * - getImage call handles argument 0 gracefully.
  */
-TEST_F(BroadcastRadioHalTest, GetNoImage) {
+TEST_P(BroadcastRadioHalTest, GetNoImage) {
     size_t len = 0;
     auto result = mModule->getImage(0, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
 
@@ -663,7 +661,7 @@
  * - isConfigFlagSet either succeeds or ends with NOT_SUPPORTED or INVALID_STATE;
  * - call success or failure is consistent with setConfigFlag.
  */
-TEST_F(BroadcastRadioHalTest, FetchConfigFlags) {
+TEST_P(BroadcastRadioHalTest, FetchConfigFlags) {
     ASSERT_TRUE(openSession());
 
     for (auto flag : gConfigFlagValues) {
@@ -691,7 +689,7 @@
  * - setConfigFlag either succeeds or ends with NOT_SUPPORTED or INVALID_STATE;
  * - isConfigFlagSet reflects the state requested immediately after the set call.
  */
-TEST_F(BroadcastRadioHalTest, SetConfigFlags) {
+TEST_P(BroadcastRadioHalTest, SetConfigFlags) {
     ASSERT_TRUE(openSession());
 
     auto get = [&](ConfigFlag flag) {
@@ -743,7 +741,7 @@
  * - the complete list is fetched within timeout::programListScan;
  * - stopProgramListUpdates does not crash.
  */
-TEST_F(BroadcastRadioHalTest, GetProgramList) {
+TEST_P(BroadcastRadioHalTest, GetProgramList) {
     ASSERT_TRUE(openSession());
 
     getProgramList();
@@ -757,7 +755,7 @@
  *  - the identifier matches the name;
  *  - there is only one identifier of that type.
  */
-TEST_F(BroadcastRadioHalTest, HdRadioStationNameId) {
+TEST_P(BroadcastRadioHalTest, HdRadioStationNameId) {
     ASSERT_TRUE(openSession());
 
     auto list = getProgramList();
@@ -785,7 +783,7 @@
  *  - if it succeeds, it returns a valid close handle (which is a nullptr otherwise);
  *  - closing handle does not crash.
  */
-TEST_F(BroadcastRadioHalTest, AnnouncementListenerRegistration) {
+TEST_P(BroadcastRadioHalTest, AnnouncementListenerRegistration) {
     sp<AnnouncementListenerMock> listener = new AnnouncementListenerMock();
 
     Result halResult = Result::UNKNOWN_ERROR;
@@ -811,6 +809,11 @@
     closeHandle->close();
 }
 
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, BroadcastRadioHalTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IBroadcastRadio::descriptor)),
+        android::hardware::PrintInstanceNameToString);
+
 }  // namespace vts
 }  // namespace V2_0
 }  // namespace broadcastradio
@@ -818,14 +821,8 @@
 }  // namespace android
 
 int main(int argc, char** argv) {
-    using android::hardware::broadcastradio::V2_0::vts::gEnv;
-    using android::hardware::broadcastradio::V2_0::IBroadcastRadio;
-    using android::hardware::broadcastradio::vts::BroadcastRadioHidlEnvironment;
     android::base::SetDefaultTag("BcRadio.vts");
     android::base::SetMinimumLogSeverity(android::base::VERBOSE);
-    gEnv = new BroadcastRadioHidlEnvironment<IBroadcastRadio>;
-    ::testing::AddGlobalTestEnvironment(gEnv);
     ::testing::InitGoogleTest(&argc, argv);
-    gEnv->init(&argc, argv);
     return RUN_ALL_TESTS();
 }
diff --git a/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/pointer-utils.h b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/pointer-utils.h
index 0b6f5eb..1d76008 100644
--- a/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/pointer-utils.h
+++ b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/pointer-utils.h
@@ -19,6 +19,8 @@
 #include <chrono>
 #include <thread>
 
+using namespace std::chrono_literals;
+
 namespace android {
 namespace hardware {
 namespace broadcastradio {
diff --git a/common/aidl/Android.bp b/common/aidl/Android.bp
new file mode 100644
index 0000000..6f2d292
--- /dev/null
+++ b/common/aidl/Android.bp
@@ -0,0 +1,21 @@
+aidl_interface {
+    name: "vintf-common",
+    host_supported: true,
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
+    srcs: [
+        "android/hardware/common/*.aidl",
+    ],
+    stability: "vintf",
+    backend: {
+        java: {
+            enabled: false,
+        },
+        cpp: {
+            enabled: false,
+        },
+    },
+}
diff --git a/common/aidl/android/hardware/common/NativeHandle.aidl b/common/aidl/android/hardware/common/NativeHandle.aidl
new file mode 100644
index 0000000..2c250a2
--- /dev/null
+++ b/common/aidl/android/hardware/common/NativeHandle.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2019 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.
+ */
+
+package android.hardware.common;
+
+/**
+ * Representation of a native handle.
+ */
+@VintfStability
+parcelable NativeHandle {
+    ParcelFileDescriptor[] fds;
+    int[] ints;
+}
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index b0a82a5..f5acdd4 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -408,7 +408,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.soundtrigger</name>
-        <version>2.0-2</version>
+        <version>2.0-3</version>
         <interface>
             <name>ISoundTriggerHw</name>
             <instance>default</instance>
diff --git a/contexthub/1.0/vts/functional/Android.bp b/contexthub/1.0/vts/functional/Android.bp
index aef0340..9e99c33 100644
--- a/contexthub/1.0/vts/functional/Android.bp
+++ b/contexthub/1.0/vts/functional/Android.bp
@@ -19,6 +19,8 @@
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalContexthubV1_0TargetTest.cpp"],
     static_libs: ["android.hardware.contexthub@1.0"],
-    test_suites: ["general-tests"],
+    test_suites: [
+        "general-tests",
+        "vts-core",
+    ],
 }
-
diff --git a/contexthub/1.0/vts/functional/OWNERS b/contexthub/1.0/vts/functional/OWNERS
index 045cc4e..161b2f0 100644
--- a/contexthub/1.0/vts/functional/OWNERS
+++ b/contexthub/1.0/vts/functional/OWNERS
@@ -4,5 +4,5 @@
 stange@google.com
 
 #VTS team
-yim@google.com
+dshi@google.com
 trong@google.com
diff --git a/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp b/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp
index 629477a..a1d173b 100644
--- a/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp
+++ b/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp
@@ -16,13 +16,14 @@
 
 #define LOG_TAG "contexthub_hidl_hal_test"
 
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
 #include <android-base/logging.h>
 #include <android/hardware/contexthub/1.0/IContexthub.h>
 #include <android/hardware/contexthub/1.0/IContexthubCallback.h>
 #include <android/hardware/contexthub/1.0/types.h>
 #include <android/log.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 #include <log/log.h>
 
 #include <cinttypes>
@@ -76,69 +77,44 @@
 }
 
 // Gets a list of valid hub IDs in the system
-std::vector<uint32_t> getHubIds() {
-  static std::vector<uint32_t> hubIds;
+std::vector<std::string> getHubIds(const std::string& service_name) {
+    std::vector<std::string> hubIds;
 
-  if (hubIds.size() == 0) {
-    sp<IContexthub> hubApi = ::testing::VtsHalHidlTargetTestBase::getService<IContexthub>();
+    sp<IContexthub> hubApi = IContexthub::getService(service_name);
 
     if (hubApi != nullptr) {
-      for (const ContextHub& hub : getHubsSync(hubApi)) {
-        hubIds.push_back(hub.hubId);
-      }
+        for (const ContextHub& hub : getHubsSync(hubApi)) {
+            hubIds.push_back(std::to_string(hub.hubId));
+        }
     }
-  }
 
-  ALOGD("Running tests against all %zu reported hubs", hubIds.size());
-  return hubIds;
+    ALOGD("Running tests against all %zu reported hubs for service %s", hubIds.size(),
+          service_name.c_str());
+    return hubIds;
 }
 
-// Test environment for Contexthub HIDL HAL.
-class ContexthubHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
-  // get the test environment singleton
-  static ContexthubHidlEnvironment* Instance() {
-    static ContexthubHidlEnvironment* instance = new ContexthubHidlEnvironment;
-    return instance;
-  }
+// Test fixture parameterized by hub ID, initializes the HAL and makes the context hub API handle
+// available.
+class ContexthubHidlTest : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
+  public:
+    virtual void SetUp() override {
+        hubApi = IContexthub::getService(std::get<0>(GetParam()));
+        ASSERT_NE(hubApi, nullptr);
 
-  virtual void registerTestServices() override { registerTestService<IContexthub>(); }
- private:
-  ContexthubHidlEnvironment() {}
-};
+        // getHubs() must be called at least once for proper initialization of the
+        // HAL implementation
+        getHubsSync(hubApi);
+    }
 
-// Base test fixture that initializes the HAL and makes the context hub API
-// handle available
-class ContexthubHidlTestBase : public ::testing::VtsHalHidlTargetTestBase {
- public:
-  virtual void SetUp() override {
-    hubApi = ::testing::VtsHalHidlTargetTestBase::getService<IContexthub>(
-        ContexthubHidlEnvironment::Instance()->getServiceName<IContexthub>());
-    ASSERT_NE(hubApi, nullptr);
+    uint32_t getHubId() { return std::stoi(std::get<1>(GetParam())); }
 
-    // getHubs() must be called at least once for proper initialization of the
-    // HAL implementation
-    getHubsSync(hubApi);
-  }
+    Result registerCallback(sp<IContexthubCallback> cb) {
+        Result result = hubApi->registerCallback(getHubId(), cb);
+        ALOGD("Registered callback, result %" PRIu32, result);
+        return result;
+    }
 
-  virtual void TearDown() override {}
-
-  sp<IContexthub> hubApi;
-};
-
-// Test fixture parameterized by hub ID
-class ContexthubHidlTest : public ContexthubHidlTestBase,
-                           public ::testing::WithParamInterface<uint32_t> {
- public:
-  uint32_t getHubId() {
-    return GetParam();
-  }
-
-  Result registerCallback(sp<IContexthubCallback> cb) {
-    Result result = hubApi->registerCallback(getHubId(), cb);
-    ALOGD("Registered callback, result %" PRIu32, result);
-    return result;
-  }
+    sp<IContexthub> hubApi;
 };
 
 // Base callback implementation that just logs all callbacks by default
@@ -202,24 +178,24 @@
 }
 
 // Ensures that the metadata reported in getHubs() is sane
-TEST_F(ContexthubHidlTestBase, TestGetHubs) {
-  hidl_vec<ContextHub> hubs = getHubsSync(hubApi);
-  ALOGD("System reports %zu hubs", hubs.size());
+TEST_P(ContexthubHidlTest, TestGetHubs) {
+    hidl_vec<ContextHub> hubs = getHubsSync(hubApi);
+    ALOGD("System reports %zu hubs", hubs.size());
 
-  for (const ContextHub& hub : hubs) {
-    ALOGD("Checking hub ID %" PRIu32, hub.hubId);
+    for (const ContextHub& hub : hubs) {
+        ALOGD("Checking hub ID %" PRIu32, hub.hubId);
 
-    EXPECT_FALSE(hub.name.empty());
-    EXPECT_FALSE(hub.vendor.empty());
-    EXPECT_FALSE(hub.toolchain.empty());
-    EXPECT_GT(hub.peakMips, 0);
-    EXPECT_GE(hub.stoppedPowerDrawMw, 0);
-    EXPECT_GE(hub.sleepPowerDrawMw, 0);
-    EXPECT_GT(hub.peakPowerDrawMw, 0);
+        EXPECT_FALSE(hub.name.empty());
+        EXPECT_FALSE(hub.vendor.empty());
+        EXPECT_FALSE(hub.toolchain.empty());
+        EXPECT_GT(hub.peakMips, 0);
+        EXPECT_GE(hub.stoppedPowerDrawMw, 0);
+        EXPECT_GE(hub.sleepPowerDrawMw, 0);
+        EXPECT_GT(hub.peakPowerDrawMw, 0);
 
-    // Minimum 128 byte MTU as required by CHRE API v1.0
-    EXPECT_GE(hub.maxSupportedMsgLen, UINT32_C(128));
-  }
+        // Minimum 128 byte MTU as required by CHRE API v1.0
+        EXPECT_GE(hub.maxSupportedMsgLen, UINT32_C(128));
+    }
 }
 
 TEST_P(ContexthubHidlTest, TestRegisterCallback) {
@@ -388,20 +364,28 @@
                                       cb->promise.get_future()));
 }
 
-// Parameterize all SingleContexthubTest tests against each valid hub ID
-INSTANTIATE_TEST_CASE_P(HubIdSpecificTests, ContexthubHidlTest,
-                        ::testing::ValuesIn(getHubIds()));
-INSTANTIATE_TEST_CASE_P(HubIdSpecificTests, ContexthubTxnTest,
-                        ::testing::ValuesIn(getHubIds()));
+// Return the test parameters of a vecter of tuples for all IContexthub services and each of its hub
+// id: <service name of IContexthub, hub id of the IContexthub service>
+static std::vector<std::tuple<std::string, std::string>> get_parameters() {
+    std::vector<std::tuple<std::string, std::string>> parameters;
+    std::vector<std::string> service_names =
+            android::hardware::getAllHalInstanceNames(IContexthub::descriptor);
+    for (const std::string& service_name : service_names) {
+        std::vector<std::string> ids = getHubIds(service_name);
+        for (const std::string& id : ids) {
+            parameters.push_back(std::make_tuple(service_name, id));
+        }
+    }
 
-} // anonymous namespace
-
-int main(int argc, char **argv) {
-  ::testing::AddGlobalTestEnvironment(ContexthubHidlEnvironment::Instance());
-  ::testing::InitGoogleTest(&argc, argv);
-  ContexthubHidlEnvironment::Instance()->init(&argc, argv);
-  int status = RUN_ALL_TESTS();
-  ALOGI ("Test result = %d", status);
-  return status;
+    return parameters;
 }
 
+static std::vector<std::tuple<std::string, std::string>> kTestParameters = get_parameters();
+
+INSTANTIATE_TEST_SUITE_P(HubIdSpecificTests, ContexthubHidlTest, testing::ValuesIn(kTestParameters),
+                         android::hardware::PrintInstanceTupleNameToString<>);
+
+INSTANTIATE_TEST_SUITE_P(HubIdSpecificTests, ContexthubTxnTest, testing::ValuesIn(kTestParameters),
+                         android::hardware::PrintInstanceTupleNameToString<>);
+
+}  // anonymous namespace
diff --git a/current.txt b/current.txt
index 03b4da8..5a3ed77 100644
--- a/current.txt
+++ b/current.txt
@@ -600,7 +600,7 @@
 
 # HALs released in Android R
 e966a3437d6a98d9d9e14e9d672088771716031900c0deb55a0946c751a03a44 android.hardware.audio@6.0::types
-2736c59abaccacac407ebe80c5e48d446edf015051d05632fb679ba471779e6e android.hardware.audio@6.0::IDevice
+dd3e9280be60a5e042331c1046d13938e2cc323dc4b267cc74d544bf62fc0314 android.hardware.audio@6.0::IDevice
 2402876cbc23c0de3690a665eca84fd3857d1808dba5cad25ce272f81ecef8c9 android.hardware.audio@6.0::IDevicesFactory
 bca5379d5065e2e08b6ad7308ffc8a71a972fc0698bec678ea32eea786d01cb5 android.hardware.audio@6.0::IPrimaryDevice
 fd1f1b29f26b42e886220f04a08086c00e5ade9d7b53f095438e578ab9d42a93 android.hardware.audio@6.0::IStream
@@ -666,3 +666,5 @@
 b27ab0cd40b0b078cdcd024bfe1061c4c4c065f3519eeb9347fa359a3268a5ae android.hardware.radio.config@1.3::IRadioConfig
 742360c775313438b0f82256eac62fb5bbc76a6ae6f388573f3aa142fb2c1eea android.hardware.radio.config@1.3::IRadioConfigIndication
 7683fed9d253956071f18b152e6be657719536f98d9b534433d5e411bcde5061 android.hardware.radio.config@1.3::IRadioConfigResponse
+c411dc16855fcb786cd5e08fe2889acbd72fd54217bd27fe0373813de230ce5f android.hardware.soundtrigger@2.3::types
+5abad7b54d3400fab633cb7a36ffc1747e037bf805d3d9e3517cb6aabf26b002 android.hardware.soundtrigger@2.3::ISoundTriggerHw
diff --git a/gnss/2.1/default/Gnss.cpp b/gnss/2.1/default/Gnss.cpp
index 384fd49..fd7a9df 100644
--- a/gnss/2.1/default/Gnss.cpp
+++ b/gnss/2.1/default/Gnss.cpp
@@ -31,6 +31,7 @@
 namespace implementation {
 
 sp<V2_1::IGnssCallback> Gnss::sGnssCallback_2_1 = nullptr;
+sp<V2_0::IGnssCallback> Gnss::sGnssCallback_2_0 = nullptr;
 
 Gnss::Gnss() : mMinIntervalMs(1000), mGnssConfiguration{new GnssConfiguration()} {}
 
@@ -190,14 +191,42 @@
 }
 
 // Methods from V2_0::IGnss follow.
-Return<bool> Gnss::setCallback_2_0(const sp<V2_0::IGnssCallback>&) {
-    // TODO implement
-    return bool{};
+Return<bool> Gnss::setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) {
+    ALOGD("Gnss::setCallback_2_0");
+    if (callback == nullptr) {
+        ALOGE("%s: Null callback ignored", __func__);
+        return false;
+    }
+
+    sGnssCallback_2_0 = callback;
+
+    using Capabilities = V2_0::IGnssCallback::Capabilities;
+    const auto capabilities = Capabilities::MEASUREMENTS | Capabilities::MEASUREMENT_CORRECTIONS |
+                              Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST;
+    auto ret = sGnssCallback_2_0->gnssSetCapabilitiesCb_2_0(capabilities);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    V1_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2019};
+
+    ret = sGnssCallback_2_0->gnssSetSystemInfoCb(gnssInfo);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    auto gnssName = "Google Mock GNSS Implementation v2.0";
+    ret = sGnssCallback_2_0->gnssNameCb(gnssName);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    return true;
 }
 
 Return<sp<V2_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_0() {
-    // TODO implement
-    return ::android::sp<V2_0::IGnssConfiguration>{};
+    ALOGD("Gnss::getExtensionGnssConfiguration_2_0");
+    return mGnssConfiguration;
 }
 
 Return<sp<V2_0::IGnssDebug>> Gnss::getExtensionGnssDebug_2_0() {
@@ -216,8 +245,8 @@
 }
 
 Return<sp<V2_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_0() {
-    // TODO implement
-    return ::android::sp<V2_0::IGnssMeasurement>{};
+    ALOGD("Gnss::getExtensionGnssMeasurement_2_0");
+    return new GnssMeasurement();
 }
 
 Return<sp<measurement_corrections::V1_0::IMeasurementCorrections>>
@@ -281,6 +310,7 @@
 }
 
 Return<sp<V2_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_1() {
+    ALOGD("Gnss::getExtensionGnssConfiguration_2_1");
     return mGnssConfiguration;
 }
 
diff --git a/gnss/2.1/default/Gnss.h b/gnss/2.1/default/Gnss.h
index 674b070..7917bbd 100644
--- a/gnss/2.1/default/Gnss.h
+++ b/gnss/2.1/default/Gnss.h
@@ -95,6 +95,7 @@
     void reportSvStatus(const hidl_vec<GnssSvInfo>&) const;
 
     static sp<V2_1::IGnssCallback> sGnssCallback_2_1;
+    static sp<V2_0::IGnssCallback> sGnssCallback_2_0;
     std::atomic<long> mMinIntervalMs;
     sp<GnssConfiguration> mGnssConfiguration;
     std::atomic<bool> mIsActive;
diff --git a/graphics/allocator/4.0/IAllocator.hal b/graphics/allocator/4.0/IAllocator.hal
index 9931685..7934867 100644
--- a/graphics/allocator/4.0/IAllocator.hal
+++ b/graphics/allocator/4.0/IAllocator.hal
@@ -20,14 +20,6 @@
 
 interface IAllocator {
     /**
-     * Retrieves implementation-defined debug information, which will be
-     * displayed during, for example, `dumpsys SurfaceFlinger`.
-     *
-     * @return debugInfo is a string of debug information.
-     */
-    dumpDebugInfo() generates (string debugInfo);
-
-    /**
      * Allocates buffers with the properties specified by the descriptor.
      *
      * Allocations should be optimized for usage bits provided in the
diff --git a/graphics/common/aidl/Android.bp b/graphics/common/aidl/Android.bp
index e0c7674..fcd4efc 100644
--- a/graphics/common/aidl/Android.bp
+++ b/graphics/common/aidl/Android.bp
@@ -10,6 +10,9 @@
         "android/hardware/graphics/common/*.aidl",
     ],
     stability: "vintf",
+    imports: [
+        "vintf-common"
+    ],
     backend: {
         java: {
             enabled: false,
diff --git a/graphics/common/aidl/android/hardware/graphics/common/BufferUsage.aidl b/graphics/common/aidl/android/hardware/graphics/common/BufferUsage.aidl
new file mode 100644
index 0000000..5f9888a
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/BufferUsage.aidl
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2019 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.
+ */
+
+package android.hardware.graphics.common;
+
+/**
+ * Buffer usage definitions.
+ */
+@VintfStability
+@Backing(type="long")
+enum BufferUsage {
+    /** bit 0-3 is an enum */
+    CPU_READ_MASK                      = 0xf,
+    /** buffer is never read by CPU */
+    CPU_READ_NEVER                     = 0,
+    /** buffer is rarely read by CPU */
+    CPU_READ_RARELY                    = 2,
+    /** buffer is often read by CPU */
+    CPU_READ_OFTEN                     = 3,
+
+    /** bit 4-7 is an enum */
+    CPU_WRITE_MASK                     = 0xf << 4,
+    /** buffer is never written by CPU */
+    CPU_WRITE_NEVER                    = 0 << 4,
+    /** buffer is rarely written by CPU */
+    CPU_WRITE_RARELY                   = 2 << 4,
+    /** buffer is often written by CPU */
+    CPU_WRITE_OFTEN                    = 3 << 4,
+
+    /** buffer is used as a GPU texture */
+    GPU_TEXTURE                        = 1 << 8,
+
+    /** buffer is used as a GPU render target */
+    GPU_RENDER_TARGET                  = 1 << 9,
+
+    /** bit 10 must be zero */
+
+    /** buffer is used as a composer HAL overlay layer */
+    COMPOSER_OVERLAY                   = 1 << 11,
+    /** buffer is used as a composer HAL client target */
+    COMPOSER_CLIENT_TARGET             = 1 << 12,
+
+    /** bit 13 must be zero */
+
+    /**
+     * Buffer is allocated with hardware-level protection against copying the
+     * contents (or information derived from the contents) into unprotected
+     * memory.
+     */
+    PROTECTED                          = 1 << 14,
+
+    /** buffer is used as a hwcomposer HAL cursor layer */
+    COMPOSER_CURSOR                    = 1 << 15,
+
+    /** buffer is used as a video encoder input */
+    VIDEO_ENCODER                      = 1 << 16,
+
+    /** buffer is used as a camera HAL output */
+    CAMERA_OUTPUT                      = 1 << 17,
+
+    /** buffer is used as a camera HAL input */
+    CAMERA_INPUT                       = 1 << 18,
+
+    /** bit 19 must be zero */
+
+    /** buffer is used as a renderscript allocation */
+    RENDERSCRIPT                       = 1 << 20,
+
+    /** bit 21 must be zero */
+
+    /** buffer is used as a video decoder output */
+    VIDEO_DECODER                      = 1 << 22,
+
+    /** buffer is used as a sensor direct report output */
+    SENSOR_DIRECT_DATA                 = 1 << 23,
+
+    /** buffer is used as a cube map texture */
+    GPU_CUBE_MAP                       = 1 << 25,
+
+    /** buffer contains a complete mipmap hierarchy */
+    GPU_MIPMAP_COMPLETE                = 1 << 26,
+
+    /**
+     * Buffer is used as input for HEIC encoder.
+     */
+    HW_IMAGE_ENCODER                   = 1 << 27,
+
+    /**
+     * buffer is used as as an OpenGL shader storage or uniform
+     * buffer object
+     */
+    GPU_DATA_BUFFER                    = 1 << 24,
+
+    /** bits 25-27 must be zero and are reserved for future versions */
+    /** bits 28-31 are reserved for vendor extensions */
+    VENDOR_MASK                        = 0xf << 28,
+
+    /** bits 32-47 must be zero and are reserved for future versions */
+    /** bits 48-63 are reserved for vendor extensions */
+    VENDOR_MASK_HI                     = 0xffff << 48,
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/HardwareBuffer.aidl b/graphics/common/aidl/android/hardware/graphics/common/HardwareBuffer.aidl
new file mode 100644
index 0000000..5a22c0f
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/HardwareBuffer.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2019 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.
+ */
+
+package android.hardware.graphics.common;
+
+import android.hardware.common.NativeHandle;
+import android.hardware.graphics.common.HardwareBufferDescription;
+
+/**
+ * Stable AIDL counterpart of AHardwareBuffer.
+ *
+ * @note This is different from the public HardwareBuffer.
+ * @sa +ndk libnativewindow#AHardwareBuffer
+ */
+@VintfStability
+parcelable HardwareBuffer {
+    HardwareBufferDescription description;
+    NativeHandle handle;
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/HardwareBufferDescription.aidl b/graphics/common/aidl/android/hardware/graphics/common/HardwareBufferDescription.aidl
new file mode 100644
index 0000000..e1e3492
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/HardwareBufferDescription.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2019 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.
+ */
+
+package android.hardware.graphics.common;
+
+import android.hardware.graphics.common.BufferUsage;
+import android.hardware.graphics.common.PixelFormat;
+
+/**
+ * Stable AIDL counterpart of AHardwareBuffer_Desc.
+ *
+ * @sa +ndk libnativewindow#AHardwareBuffer_Desc
+ */
+@VintfStability
+parcelable HardwareBufferDescription {
+    int width;
+    int height;
+    int layers;
+    PixelFormat format;
+    BufferUsage usage;
+    int stride;
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl b/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
new file mode 100644
index 0000000..4942462
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
@@ -0,0 +1,516 @@
+/*
+ * Copyright 2019 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.
+ */
+
+package android.hardware.graphics.common;
+
+/**
+ * Pixel formats for graphics buffers.
+ */
+@VintfStability
+@Backing(type="int")
+enum PixelFormat {
+    /**
+     * This value may be used in an operation where the format is optional.
+     */
+    UNSPECIFIED                        = 0,
+    /**
+     * 32-bit format that has 8-bit R, G, B, and A components, in that order,
+     * from the lowest memory address to the highest memory address.
+     *
+     * The component values are unsigned normalized to the range [0, 1], whose
+     * interpretation is defined by the dataspace.
+     */
+    RGBA_8888                          = 0x1,
+
+    /**
+     * 32-bit format that has 8-bit R, G, B, and unused components, in that
+     * order, from the lowest memory address to the highest memory address.
+     *
+     * The component values are unsigned normalized to the range [0, 1], whose
+     * interpretation is defined by the dataspace.
+     */
+    RGBX_8888                          = 0x2,
+
+    /**
+     * 24-bit format that has 8-bit R, G, and B components, in that order,
+     * from the lowest memory address to the highest memory address.
+     *
+     * The component values are unsigned normalized to the range [0, 1], whose
+     * interpretation is defined by the dataspace.
+     */
+    RGB_888                            = 0x3,
+
+    /**
+     * 16-bit packed format that has 5-bit R, 6-bit G, and 5-bit B components,
+     * in that order, from the most-sigfinicant bits to the least-significant
+     * bits.
+     *
+     * The component values are unsigned normalized to the range [0, 1], whose
+     * interpretation is defined by the dataspace.
+     */
+    RGB_565                            = 0x4,
+
+    /**
+     * 32-bit format that has 8-bit B, G, R, and A components, in that order,
+     * from the lowest memory address to the highest memory address.
+     *
+     * The component values are unsigned normalized to the range [0, 1], whose
+     * interpretation is defined by the dataspace.
+     */
+    BGRA_8888                          = 0x5,
+
+    /**
+     * Legacy formats deprecated in favor of YCBCR_420_888.
+     */
+    YCBCR_422_SP                       = 0x10,  // NV16
+    YCRCB_420_SP                       = 0x11,  // NV21
+    YCBCR_422_I                        = 0x14,  // YUY2
+
+    /**
+     * 64-bit format that has 16-bit R, G, B, and A components, in that order,
+     * from the lowest memory address to the highest memory address.
+     *
+     * The component values are signed floats, whose interpretation is defined
+     * by the dataspace.
+     */
+    RGBA_FP16                          = 0x16,
+
+    /**
+     * RAW16 is a single-channel, 16-bit, little endian format, typically
+     * representing raw Bayer-pattern images from an image sensor, with minimal
+     * processing.
+     *
+     * The exact pixel layout of the data in the buffer is sensor-dependent, and
+     * needs to be queried from the camera device.
+     *
+     * Generally, not all 16 bits are used; more common values are 10 or 12
+     * bits. If not all bits are used, the lower-order bits are filled first.
+     * All parameters to interpret the raw data (black and white points,
+     * color space, etc) must be queried from the camera device.
+     *
+     * This format assumes
+     * - an even width
+     * - an even height
+     * - a horizontal stride multiple of 16 pixels
+     * - a vertical stride equal to the height
+     * - strides are specified in pixels, not in bytes
+     *
+     *   size = stride * height * 2
+     *
+     * This format must be accepted by the allocator when used with the
+     * following usage flags:
+     *
+     *    - BufferUsage::CAMERA_*
+     *    - BufferUsage::CPU_*
+     *    - BufferUsage::RENDERSCRIPT
+     *
+     * The mapping of the dataspace to buffer contents for RAW16 is as
+     * follows:
+     *
+     *  Dataspace value               | Buffer contents
+     * -------------------------------+-----------------------------------------
+     *  Dataspace::ARBITRARY          | Raw image sensor data, layout is as
+     *                                | defined above.
+     *  Dataspace::DEPTH              | Unprocessed implementation-dependent raw
+     *                                | depth measurements, opaque with 16 bit
+     *                                | samples.
+     *  Other                         | Unsupported
+     */
+    RAW16                              = 0x20,
+
+    /**
+     * BLOB is used to carry task-specific data which does not have a standard
+     * image structure. The details of the format are left to the two
+     * endpoints.
+     *
+     * A typical use case is for transporting JPEG-compressed images from the
+     * Camera HAL to the framework or to applications.
+     *
+     * Buffers of this format must have a height of 1, and width equal to their
+     * size in bytes.
+     *
+     * The mapping of the dataspace to buffer contents for BLOB is as
+     * follows:
+     *
+     *  Dataspace value               | Buffer contents
+     * -------------------------------+-----------------------------------------
+     *  Dataspace::JFIF               | An encoded JPEG image
+     *  Dataspace::DEPTH              | An android_depth_points buffer
+     *  Dataspace::SENSOR             | Sensor event data.
+     *  Other                         | Unsupported
+     */
+    BLOB                               = 0x21,
+
+    /**
+     * A format indicating that the choice of format is entirely up to the
+     * allocator.
+     *
+     * The allocator should examine the usage bits passed in when allocating a
+     * buffer with this format, and it should derive the pixel format from
+     * those usage flags. This format must never be used with any of the
+     * BufferUsage::CPU_* usage flags.
+     *
+     * Even when the internally chosen format has an alpha component, the
+     * clients must assume the alpha vlaue to be 1.0.
+     *
+     * The interpretation of the component values is defined by the dataspace.
+     */
+    IMPLEMENTATION_DEFINED             = 0x22,
+
+    /**
+     * This format allows platforms to use an efficient YCbCr/YCrCb 4:2:0
+     * buffer layout, while still describing the general format in a
+     * layout-independent manner. While called YCbCr, it can be used to
+     * describe formats with either chromatic ordering, as well as
+     * whole planar or semiplanar layouts.
+     *
+     * This format must be accepted by the allocator when BufferUsage::CPU_*
+     * are set.
+     *
+     * Buffers with this format must be locked with IMapper::lockYCbCr.
+     * Locking with IMapper::lock must return an error.
+     *
+     * The interpretation of the component values is defined by the dataspace.
+     */
+    YCBCR_420_888                      = 0x23,
+
+    /**
+     * RAW_OPAQUE is a format for unprocessed raw image buffers coming from an
+     * image sensor. The actual structure of buffers of this format is
+     * implementation-dependent.
+     *
+     * This format must be accepted by the allocator when used with the
+     * following usage flags:
+     *
+     *    - BufferUsage::CAMERA_*
+     *    - BufferUsage::CPU_*
+     *    - BufferUsage::RENDERSCRIPT
+     *
+     * The mapping of the dataspace to buffer contents for RAW_OPAQUE is as
+     * follows:
+     *
+     *  Dataspace value               | Buffer contents
+     * -------------------------------+-----------------------------------------
+     *  Dataspace::ARBITRARY          | Raw image sensor data.
+     *  Other                         | Unsupported
+     */
+    RAW_OPAQUE                         = 0x24,
+
+    /**
+     * RAW10 is a single-channel, 10-bit per pixel, densely packed in each row,
+     * unprocessed format, usually representing raw Bayer-pattern images coming from
+     * an image sensor.
+     *
+     * In an image buffer with this format, starting from the first pixel of each
+     * row, each 4 consecutive pixels are packed into 5 bytes (40 bits). Each one
+     * of the first 4 bytes contains the top 8 bits of each pixel, The fifth byte
+     * contains the 2 least significant bits of the 4 pixels, the exact layout data
+     * for each 4 consecutive pixels is illustrated below (Pi[j] stands for the jth
+     * bit of the ith pixel):
+     *
+     *          bit 7                                     bit 0
+     *          =====|=====|=====|=====|=====|=====|=====|=====|
+     * Byte 0: |P0[9]|P0[8]|P0[7]|P0[6]|P0[5]|P0[4]|P0[3]|P0[2]|
+     *         |-----|-----|-----|-----|-----|-----|-----|-----|
+     * Byte 1: |P1[9]|P1[8]|P1[7]|P1[6]|P1[5]|P1[4]|P1[3]|P1[2]|
+     *         |-----|-----|-----|-----|-----|-----|-----|-----|
+     * Byte 2: |P2[9]|P2[8]|P2[7]|P2[6]|P2[5]|P2[4]|P2[3]|P2[2]|
+     *         |-----|-----|-----|-----|-----|-----|-----|-----|
+     * Byte 3: |P3[9]|P3[8]|P3[7]|P3[6]|P3[5]|P3[4]|P3[3]|P3[2]|
+     *         |-----|-----|-----|-----|-----|-----|-----|-----|
+     * Byte 4: |P3[1]|P3[0]|P2[1]|P2[0]|P1[1]|P1[0]|P0[1]|P0[0]|
+     *          ===============================================
+     *
+     * This format assumes
+     * - a width multiple of 4 pixels
+     * - an even height
+     * - a vertical stride equal to the height
+     * - strides are specified in bytes, not in pixels
+     *
+     *   size = stride * height
+     *
+     * When stride is equal to width * (10 / 8), there will be no padding bytes at
+     * the end of each row, the entire image data is densely packed. When stride is
+     * larger than width * (10 / 8), padding bytes will be present at the end of each
+     * row (including the last row).
+     *
+     * This format must be accepted by the allocator when used with the
+     * following usage flags:
+     *
+     *    - BufferUsage::CAMERA_*
+     *    - BufferUsage::CPU_*
+     *    - BufferUsage::RENDERSCRIPT
+     *
+     * The mapping of the dataspace to buffer contents for RAW10 is as
+     * follows:
+     *
+     *  Dataspace value               | Buffer contents
+     * -------------------------------+-----------------------------------------
+     *  Dataspace::ARBITRARY          | Raw image sensor data.
+     *  Other                         | Unsupported
+     */
+    RAW10                              = 0x25,
+
+    /**
+     * RAW12 is a single-channel, 12-bit per pixel, densely packed in each row,
+     * unprocessed format, usually representing raw Bayer-pattern images coming from
+     * an image sensor.
+     *
+     * In an image buffer with this format, starting from the first pixel of each
+     * row, each two consecutive pixels are packed into 3 bytes (24 bits). The first
+     * and second byte contains the top 8 bits of first and second pixel. The third
+     * byte contains the 4 least significant bits of the two pixels, the exact layout
+     * data for each two consecutive pixels is illustrated below (Pi[j] stands for
+     * the jth bit of the ith pixel):
+     *
+     *           bit 7                                            bit 0
+     *          ======|======|======|======|======|======|======|======|
+     * Byte 0: |P0[11]|P0[10]|P0[ 9]|P0[ 8]|P0[ 7]|P0[ 6]|P0[ 5]|P0[ 4]|
+     *         |------|------|------|------|------|------|------|------|
+     * Byte 1: |P1[11]|P1[10]|P1[ 9]|P1[ 8]|P1[ 7]|P1[ 6]|P1[ 5]|P1[ 4]|
+     *         |------|------|------|------|------|------|------|------|
+     * Byte 2: |P1[ 3]|P1[ 2]|P1[ 1]|P1[ 0]|P0[ 3]|P0[ 2]|P0[ 1]|P0[ 0]|
+     *          =======================================================
+     *
+     * This format assumes:
+     * - a width multiple of 4 pixels
+     * - an even height
+     * - a vertical stride equal to the height
+     * - strides are specified in bytes, not in pixels
+     *
+     *   size = stride * height
+     *
+     * When stride is equal to width * (12 / 8), there will be no padding bytes at
+     * the end of each row, the entire image data is densely packed. When stride is
+     * larger than width * (12 / 8), padding bytes will be present at the end of
+     * each row (including the last row).
+     *
+     * This format must be accepted by the allocator when used with the
+     * following usage flags:
+     *
+     *    - BufferUsage::CAMERA_*
+     *    - BufferUsage::CPU_*
+     *    - BufferUsage::RENDERSCRIPT
+     *
+     * The mapping of the dataspace to buffer contents for RAW12 is as
+     * follows:
+     *
+     *  Dataspace value               | Buffer contents
+     * -------------------------------+-----------------------------------------
+     *  Dataspace::ARBITRARY          | Raw image sensor data.
+     *  Other                         | Unsupported
+     */
+    RAW12                              = 0x26,
+
+    /** 0x27 to 0x2A are reserved for flexible formats */
+
+    /**
+     * 32-bit packed format that has 2-bit A, 10-bit B, G, and R components,
+     * in that order, from the most-sigfinicant bits to the least-significant
+     * bits.
+     *
+     * The component values are unsigned normalized to the range [0, 1], whose
+     * interpretation is defined by the dataspace.
+     */
+    RGBA_1010102                       = 0x2B,
+
+    /**
+     * 0x100 - 0x1FF
+     *
+     * This range is reserved for vendor extensions. Formats in this range
+     * must support BufferUsage::GPU_TEXTURE. Clients must assume they do not
+     * have an alpha component.
+     */
+
+    /**
+     * Y8 is a YUV planar format comprised of a WxH Y plane, with each pixel
+     * being represented by 8 bits. It is equivalent to just the Y plane from
+     * YV12.
+     *
+     * This format assumes
+     * - an even width
+     * - an even height
+     * - a horizontal stride multiple of 16 pixels
+     * - a vertical stride equal to the height
+     *
+     *   size = stride * height
+     *
+     * This format must be accepted by the allocator when used with the
+     * following usage flags:
+     *
+     *    - BufferUsage::CAMERA_*
+     *    - BufferUsage::CPU_*
+     *
+     * The component values are unsigned normalized to the range [0, 1], whose
+     * interpretation is defined by the dataspace.
+     */
+    Y8                                 = 0x20203859,
+
+    /**
+     * Y16 is a YUV planar format comprised of a WxH Y plane, with each pixel
+     * being represented by 16 bits. It is just like Y8, but has double the
+     * bits per pixel (little endian).
+     *
+     * This format assumes
+     * - an even width
+     * - an even height
+     * - a horizontal stride multiple of 16 pixels
+     * - a vertical stride equal to the height
+     * - strides are specified in pixels, not in bytes
+     *
+     *   size = stride * height * 2
+     *
+     * This format must be accepted by the allocator when used with the
+     * following usage flags:
+     *
+     *    - BufferUsage::CAMERA_*
+     *    - BufferUsage::CPU_*
+     *
+     * The component values are unsigned normalized to the range [0, 1], whose
+     * interpretation is defined by the dataspace. When the dataspace is
+     * Dataspace::DEPTH, each pixel is a distance value measured by a depth
+     * camera, plus an associated confidence value.
+     */
+    Y16                                = 0x20363159,
+
+    /**
+     * YV12 is a 4:2:0 YCrCb planar format comprised of a WxH Y plane followed
+     * by (W/2) x (H/2) Cr and Cb planes.
+     *
+     * This format assumes
+     * - an even width
+     * - an even height
+     * - a horizontal stride multiple of 16 pixels
+     * - a vertical stride equal to the height
+     *
+     *   y_size = stride * height
+     *   c_stride = ALIGN(stride/2, 16)
+     *   c_size = c_stride * height/2
+     *   size = y_size + c_size * 2
+     *   cr_offset = y_size
+     *   cb_offset = y_size + c_size
+     *
+     * This range is reserved for vendor extensions. Formats in this range
+     * must support BufferUsage::GPU_TEXTURE. Clients must assume they do not
+     * have an alpha component.
+     *
+     * This format must be accepted by the allocator when used with the
+     * following usage flags:
+     *
+     *    - BufferUsage::CAMERA_*
+     *    - BufferUsage::CPU_*
+     *    - BufferUsage::GPU_TEXTURE
+     *
+     * The component values are unsigned normalized to the range [0, 1], whose
+     * interpretation is defined by the dataspace.
+     */
+    YV12                               = 0x32315659, // YCrCb 4:2:0 Planar
+
+    /**
+     * 16-bit format that has a single 16-bit depth component.
+     *
+     * The component values are unsigned normalized to the range [0, 1], whose
+     * interpretation is defined by the dataspace.
+     */
+    DEPTH_16                           = 0x30,
+
+    /**
+     * 32-bit format that has a single 24-bit depth component and, optionally,
+     * 8 bits that are unused.
+     *
+     * The component values are unsigned normalized to the range [0, 1], whose
+     * interpretation is defined by the dataspace.
+     */
+    DEPTH_24                           = 0x31,
+
+    /**
+     * 32-bit format that has a 24-bit depth component and an 8-bit stencil
+     * component packed into 32-bits.
+     *
+     * The depth component values are unsigned normalized to the range [0, 1],
+     * whose interpretation is defined by the dataspace. The stencil values are
+     * unsigned integers, whose interpretation is defined by the dataspace.
+     */
+    DEPTH_24_STENCIL_8                 = 0x32,
+
+    /**
+     * 32-bit format that has a single 32-bit depth component.
+     *
+     * The component values are signed floats, whose interpretation is defined
+     * by the dataspace.
+     */
+    DEPTH_32F                          = 0x33,
+
+    /**
+     * Two-component format that has a 32-bit depth component, an 8-bit stencil
+     * component, and optionally 24-bits unused.
+     *
+     * The depth component values are signed floats, whose interpretation is
+     * defined by the dataspace. The stencil bits are unsigned integers, whose
+     * interpretation is defined by the dataspace.
+     */
+    DEPTH_32F_STENCIL_8                = 0x34,
+
+    /**
+     * 8-bit format that has a single 8-bit stencil component.
+     *
+     * The component values are unsigned integers, whose interpretation is
+     * defined by the dataspace.
+     */
+    STENCIL_8                          = 0x35,
+
+    /**
+     * P010 is a 4:2:0 YCbCr semiplanar format comprised of a WxH Y plane
+     * followed immediately by a Wx(H/2) CbCr plane. Each sample is
+     * represented by a 16-bit little-endian value, with the lower 6 bits set
+     * to zero.
+     *
+     * This format assumes
+     * - an even height
+     * - a vertical stride equal to the height
+     *
+     *   stride_in_bytes = stride * 2
+     *   y_size = stride_in_bytes * height
+     *   cbcr_size = stride_in_bytes * (height / 2)
+     *   cb_offset = y_size
+     *   cr_offset = cb_offset + 2
+     *
+     * This format must be accepted by the allocator when used with the
+     * following usage flags:
+     *
+     *    - BufferUsage::VIDEO_*
+     *    - BufferUsage::CPU_*
+     *    - BufferUsage::GPU_TEXTURE
+     *
+     * The component values are unsigned normalized to the range [0, 1], whose
+     * interpretation is defined by the dataspace.
+     *
+     * This format is appropriate for 10bit video content.
+     *
+     * Buffers with this format must be locked with IMapper::lockYCbCr
+     * or with IMapper::lock.
+     */
+    YCBCR_P010                         = 0x36,
+
+    /**
+     * 24-bit format that has 8-bit H, S, and V components, in that order,
+     * from the lowest memory address to the highest memory address.
+     *
+     * The component values are unsigned normalized to the range [0, 1], whose
+     * interpretation is defined by the dataspace.
+    */
+    HSV_888                            = 0x37,
+}
diff --git a/graphics/mapper/4.0/utils/vts/MapperVts.cpp b/graphics/mapper/4.0/utils/vts/MapperVts.cpp
index 8a5f54e..cb90fa0 100644
--- a/graphics/mapper/4.0/utils/vts/MapperVts.cpp
+++ b/graphics/mapper/4.0/utils/vts/MapperVts.cpp
@@ -71,13 +71,6 @@
     return mAllocator;
 }
 
-std::string Gralloc::dumpDebugInfo() {
-    std::string debugInfo;
-    mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
-
-    return debugInfo;
-}
-
 const native_handle_t* Gralloc::cloneBuffer(const hidl_handle& rawHandle) {
     const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());
     EXPECT_NE(nullptr, bufferHandle);
diff --git a/graphics/mapper/4.0/utils/vts/include/mapper-vts/4.0/MapperVts.h b/graphics/mapper/4.0/utils/vts/include/mapper-vts/4.0/MapperVts.h
index 1c635c4..cd40aa4 100644
--- a/graphics/mapper/4.0/utils/vts/include/mapper-vts/4.0/MapperVts.h
+++ b/graphics/mapper/4.0/utils/vts/include/mapper-vts/4.0/MapperVts.h
@@ -45,8 +45,6 @@
 
     sp<IAllocator> getAllocator() const;
 
-    std::string dumpDebugInfo();
-
     // When import is false, this simply calls IAllocator::allocate. When import
     // is true, the returned buffers are also imported into the mapper.
     //
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index 7dc733c..4a0aabf 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -306,13 +306,6 @@
 };
 
 /**
- * Test IAllocator::dumpDebugInfo by calling it.
- */
-TEST_P(GraphicsMapperHidlTest, AllocatorDumpDebugInfo) {
-    mGralloc->dumpDebugInfo();
-}
-
-/**
  * Test IAllocator::allocate with valid buffer descriptors.
  */
 TEST_P(GraphicsMapperHidlTest, AllocatorAllocate) {
diff --git a/soundtrigger/2.3/Android.bp b/soundtrigger/2.3/Android.bp
new file mode 100644
index 0000000..3253a86
--- /dev/null
+++ b/soundtrigger/2.3/Android.bp
@@ -0,0 +1,22 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.soundtrigger@2.3",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "ISoundTriggerHw.hal",
+    ],
+    interfaces: [
+        "android.hardware.audio.common@2.0",
+        "android.hardware.soundtrigger@2.0",
+        "android.hardware.soundtrigger@2.1",
+        "android.hardware.soundtrigger@2.2",
+        "android.hidl.base@1.0",
+        "android.hidl.safe_union@1.0",
+    ],
+    gen_java: true,
+}
diff --git a/soundtrigger/2.3/ISoundTriggerHw.hal b/soundtrigger/2.3/ISoundTriggerHw.hal
new file mode 100644
index 0000000..207b9b7
--- /dev/null
+++ b/soundtrigger/2.3/ISoundTriggerHw.hal
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2019 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.
+ */
+
+package android.hardware.soundtrigger@2.3;
+
+import @2.0::SoundModelHandle;
+import @2.2::ISoundTriggerHw;
+
+/**
+ * SoundTrigger HAL interface. Used for hardware recognition of hotwords
+ * and other sounds.
+ */
+interface ISoundTriggerHw extends @2.2::ISoundTriggerHw {
+
+    /**
+     * Set a model specific parameter with the given value. This parameter
+     * will keep its value for the duration the model is loaded regardless of starting and stopping
+     * recognition. Once the model is unloaded, the value will be lost.
+     * It is expected to check if the handle supports the parameter via the queryParameter
+     * API prior to calling this method.
+     *
+     * @param modelHandle The sound model handle indicating which model to modify parameters
+     * @param modelParam Parameter to set which will be validated against the
+     *                   ModelParameter type. Not putting ModelParameter type
+     *                   directly in the definition and validating internally
+     *                   allows for forward compatibility.
+     * @param value The value to set for the given model parameter
+     * @return status Operation completion status: 0 in case of success,
+     *                -ENODEV if the native service cannot be reached
+     *                -EINVAL invalid input parameter
+     */
+    setParameter(SoundModelHandle modelHandle, ModelParameter modelParam, int32_t value)
+            generates (int32_t status);
+
+    /**
+     * Get a model specific parameter. This parameter will keep its value
+     * for the duration the model is loaded regardless of starting and stopping recognition.
+     * Once the model is unloaded, the value will be lost. If the value is not set, a default
+     * value is returned. See ModelParameter for parameter default values.
+     * It is expected to check if the handle supports the parameter via the queryParameter
+     * API prior to calling this method.
+     *
+     * @param modelHandle The sound model associated with given modelParam
+     * @param modelParam Parameter to set which will be validated against the
+     *                   ModelParameter type. Not putting ModelParameter type
+     *                   directly in the definition and validating internally
+     *                   allows for forward compatibility.
+     * @return status Operation completion status: 0 in case of success,
+     *                -ENODEV if the native service cannot be reached
+     *                -EINVAL invalid input parameter
+     * @return value Value set to the requested parameter. Value is only set when status
+     *                indicates success.
+     */
+    getParameter(SoundModelHandle modelHandle, ModelParameter modelParam)
+            generates (int32_t status, int32_t value);
+
+    /**
+     * Get supported parameter attributes with respect to the provided model
+     * handle. Along with determining the valid range, this API is also used
+     * to determine if a given parameter ID is supported at all by the
+     * modelHandle for use with getParameter and setParameter APIs.
+     *
+     * @param modelHandle The sound model handle indicating which model to query
+     * @param modelParam Parameter to set which will be validated against the
+     *                   ModelParameter type
+     * @return status Operation completion status: 0 in case of success
+     *                -ENODEV if the native service cannot be reached
+     *                -EINVAL invalid input parameter
+     * @return retval ModelParameter structure indicating supported attributes
+     *                of the parameter for the given model handle
+     */
+    queryParameter(SoundModelHandle modelHandle, ModelParameter modelParam)
+            generates (int32_t status, OptionalModelParameterRange retval);
+};
diff --git a/soundtrigger/2.3/default/Android.bp b/soundtrigger/2.3/default/Android.bp
new file mode 100644
index 0000000..be2c8b0
--- /dev/null
+++ b/soundtrigger/2.3/default/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2019 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.
+
+cc_library_shared {
+    name: "android.hardware.soundtrigger@2.3-impl",
+    relative_install_path: "hw",
+    vendor: true,
+    srcs: [
+        "SoundTriggerHw.cpp",
+    ],
+    shared_libs: [
+        "libhidlbase",
+        "liblog",
+        "libhidlmemory",
+        "libutils",
+        "libhardware",
+        "android.hardware.soundtrigger@2.0",
+        "android.hardware.soundtrigger@2.0-core",
+        "android.hardware.soundtrigger@2.1",
+        "android.hardware.soundtrigger@2.2",
+        "android.hardware.soundtrigger@2.3",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+    ],
+}
diff --git a/soundtrigger/2.3/default/SoundTriggerHw.cpp b/soundtrigger/2.3/default/SoundTriggerHw.cpp
new file mode 100644
index 0000000..4a39ab5
--- /dev/null
+++ b/soundtrigger/2.3/default/SoundTriggerHw.cpp
@@ -0,0 +1,804 @@
+/*
+ * Copyright (C) 2019 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_TAG "SoundTriggerHw"
+
+#include "SoundTriggerHw.h"
+
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/log.h>
+#include <hidlmemory/mapping.h>
+#include <utility>
+
+using android::hardware::hidl_memory;
+using android::hidl::allocator::V1_0::IAllocator;
+using android::hidl::memory::V1_0::IMemory;
+
+namespace android {
+namespace hardware {
+namespace soundtrigger {
+namespace V2_3 {
+namespace implementation {
+
+/**
+ * According to the HIDL C++ Users Guide: client and server implementations
+ * should never directly refer to anything other than the interface header
+ * generated from the HIDL definition file (ie. ISoundTriggerHw.hal), so
+ * this V2_3 implementation copies the previous implementations and
+ * then adds the new implementation.
+ */
+
+// Begin V2_0 implementation, copied from
+// hardware/interfaces/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp
+
+// static
+void soundModelCallback_(struct sound_trigger_model_event* halEvent, void* cookie) {
+    if (halEvent == NULL) {
+        ALOGW("soundModelCallback called with NULL event");
+        return;
+    }
+    sp<SoundTriggerHw::SoundModelClient> client =
+            wp<SoundTriggerHw::SoundModelClient>(
+                    static_cast<SoundTriggerHw::SoundModelClient*>(cookie))
+                    .promote();
+    if (client == 0) {
+        ALOGW("soundModelCallback called on stale client");
+        return;
+    }
+    if (halEvent->model != client->getHalHandle()) {
+        ALOGW("soundModelCallback call with wrong handle %d on client with handle %d",
+              (int)halEvent->model, (int)client->getHalHandle());
+        return;
+    }
+
+    client->soundModelCallback(halEvent);
+}
+
+// static
+void recognitionCallback_(struct sound_trigger_recognition_event* halEvent, void* cookie) {
+    if (halEvent == NULL) {
+        ALOGW("recognitionCallback call NULL event");
+        return;
+    }
+    sp<SoundTriggerHw::SoundModelClient> client =
+            wp<SoundTriggerHw::SoundModelClient>(
+                    static_cast<SoundTriggerHw::SoundModelClient*>(cookie))
+                    .promote();
+    if (client == 0) {
+        ALOGW("recognitionCallback called on stale client");
+        return;
+    }
+
+    client->recognitionCallback(halEvent);
+}
+
+Return<void> SoundTriggerHw::getProperties(ISoundTriggerHw::getProperties_cb _hidl_cb) {
+    ALOGV("getProperties() mHwDevice %p", mHwDevice);
+    int ret;
+    struct sound_trigger_properties halProperties;
+    ISoundTriggerHw::Properties properties;
+
+    if (mHwDevice == NULL) {
+        ret = -ENODEV;
+        goto exit;
+    }
+
+    ret = mHwDevice->get_properties(mHwDevice, &halProperties);
+
+    convertPropertiesFromHal(&properties, &halProperties);
+
+    ALOGV("getProperties implementor %s recognitionModes %08x", properties.implementor.c_str(),
+          properties.recognitionModes);
+
+exit:
+    _hidl_cb(ret, properties);
+    return Void();
+}
+
+int SoundTriggerHw::doLoadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel,
+                                     sp<SoundTriggerHw::SoundModelClient> client) {
+    int32_t ret = 0;
+    struct sound_trigger_sound_model* halSoundModel;
+
+    ALOGV("doLoadSoundModel() data size %zu", soundModel.data.size());
+
+    if (mHwDevice == NULL) {
+        ret = -ENODEV;
+        goto exit;
+    }
+
+    halSoundModel = convertSoundModelToHal(&soundModel);
+    if (halSoundModel == NULL) {
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    sound_model_handle_t halHandle;
+    ret = mHwDevice->load_sound_model(mHwDevice, halSoundModel, soundModelCallback_, client.get(),
+                                      &halHandle);
+
+    free(halSoundModel);
+
+    if (ret != 0) {
+        goto exit;
+    }
+
+    client->setHalHandle(halHandle);
+    {
+        AutoMutex lock(mLock);
+        mClients.add(client->getId(), client);
+    }
+
+exit:
+    return ret;
+}
+
+Return<void> SoundTriggerHw::loadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel,
+                                            const sp<V2_0::ISoundTriggerHwCallback>& callback,
+                                            V2_0::ISoundTriggerHwCallback::CallbackCookie cookie,
+                                            ISoundTriggerHw::loadSoundModel_cb _hidl_cb) {
+    sp<SoundTriggerHw::SoundModelClient> client =
+            new SoundModelClient_2_0(nextUniqueModelId(), cookie, callback);
+    _hidl_cb(doLoadSoundModel(soundModel, client), client->getId());
+    return Void();
+}
+
+Return<void> SoundTriggerHw::loadPhraseSoundModel(
+        const V2_0::ISoundTriggerHw::PhraseSoundModel& soundModel,
+        const sp<V2_0::ISoundTriggerHwCallback>& callback,
+        V2_0::ISoundTriggerHwCallback::CallbackCookie cookie,
+        ISoundTriggerHw::loadPhraseSoundModel_cb _hidl_cb) {
+    sp<SoundTriggerHw::SoundModelClient> client =
+            new SoundModelClient_2_0(nextUniqueModelId(), cookie, callback);
+    _hidl_cb(doLoadSoundModel((const V2_0::ISoundTriggerHw::SoundModel&)soundModel, client),
+             client->getId());
+    return Void();
+}
+
+Return<int32_t> SoundTriggerHw::unloadSoundModel(int32_t modelHandle) {
+    int32_t ret;
+    sp<SoundTriggerHw::SoundModelClient> client;
+
+    if (mHwDevice == NULL) {
+        ret = -ENODEV;
+        goto exit;
+    }
+
+    {
+        AutoMutex lock(mLock);
+        client = mClients.valueFor(modelHandle);
+        if (client == 0) {
+            ret = -ENOSYS;
+            goto exit;
+        }
+    }
+
+    ret = mHwDevice->unload_sound_model(mHwDevice, client->getHalHandle());
+
+    mClients.removeItem(modelHandle);
+
+exit:
+    return ret;
+}
+
+Return<int32_t> SoundTriggerHw::startRecognition(
+        int32_t modelHandle, const V2_0::ISoundTriggerHw::RecognitionConfig& config,
+        const sp<V2_0::ISoundTriggerHwCallback>& /* callback */, int32_t /* cookie */) {
+    int32_t ret;
+    sp<SoundTriggerHw::SoundModelClient> client;
+    struct sound_trigger_recognition_config* halConfig;
+
+    if (mHwDevice == NULL) {
+        ret = -ENODEV;
+        goto exit;
+    }
+
+    {
+        AutoMutex lock(mLock);
+        client = mClients.valueFor(modelHandle);
+        if (client == 0) {
+            ret = -ENOSYS;
+            goto exit;
+        }
+    }
+
+    halConfig =
+            convertRecognitionConfigToHal((const V2_0::ISoundTriggerHw::RecognitionConfig*)&config);
+
+    if (halConfig == NULL) {
+        ret = -EINVAL;
+        goto exit;
+    }
+    ret = mHwDevice->start_recognition(mHwDevice, client->getHalHandle(), halConfig,
+                                       recognitionCallback_, client.get());
+
+    free(halConfig);
+
+exit:
+    return ret;
+}
+
+Return<int32_t> SoundTriggerHw::stopRecognition(int32_t modelHandle) {
+    int32_t ret;
+    sp<SoundTriggerHw::SoundModelClient> client;
+    if (mHwDevice == NULL) {
+        ret = -ENODEV;
+        goto exit;
+    }
+
+    {
+        AutoMutex lock(mLock);
+        client = mClients.valueFor(modelHandle);
+        if (client == 0) {
+            ret = -ENOSYS;
+            goto exit;
+        }
+    }
+
+    ret = mHwDevice->stop_recognition(mHwDevice, client->getHalHandle());
+
+exit:
+    return ret;
+}
+
+Return<int32_t> SoundTriggerHw::stopAllRecognitions() {
+    int32_t ret;
+    if (mHwDevice == NULL) {
+        ret = -ENODEV;
+        goto exit;
+    }
+
+    ret = mHwDevice->stop_all_recognitions(mHwDevice);
+
+exit:
+    return ret;
+}
+
+SoundTriggerHw::SoundTriggerHw() : mModuleName("primary"), mHwDevice(NULL), mNextModelId(1) {}
+
+void SoundTriggerHw::onFirstRef() {
+    const hw_module_t* mod;
+    int rc;
+
+    rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, &mod);
+    if (rc != 0) {
+        ALOGE("couldn't load sound trigger module %s.%s (%s)", SOUND_TRIGGER_HARDWARE_MODULE_ID,
+              mModuleName, strerror(-rc));
+        return;
+    }
+    rc = sound_trigger_hw_device_open(mod, &mHwDevice);
+    if (rc != 0) {
+        ALOGE("couldn't open sound trigger hw device in %s.%s (%s)",
+              SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, strerror(-rc));
+        mHwDevice = NULL;
+        return;
+    }
+    if (mHwDevice->common.version != SOUND_TRIGGER_DEVICE_API_VERSION_1_3) {
+        ALOGE("wrong sound trigger hw device version %04x", mHwDevice->common.version);
+        sound_trigger_hw_device_close(mHwDevice);
+        mHwDevice = NULL;
+        return;
+    }
+
+    ALOGI("onFirstRef() mModuleName %s mHwDevice %p", mModuleName, mHwDevice);
+}
+
+SoundTriggerHw::~SoundTriggerHw() {
+    if (mHwDevice != NULL) {
+        sound_trigger_hw_device_close(mHwDevice);
+    }
+}
+
+uint32_t SoundTriggerHw::nextUniqueModelId() {
+    uint32_t modelId = 0;
+    {
+        AutoMutex lock(mLock);
+        do {
+            modelId = atomic_fetch_add_explicit(&mNextModelId, (uint_fast32_t)1,
+                                                memory_order_acq_rel);
+        } while (mClients.valueFor(modelId) != 0 && modelId != 0);
+    }
+    LOG_ALWAYS_FATAL_IF(modelId == 0, "wrap around in sound model IDs, num loaded models %zu",
+                        mClients.size());
+    return modelId;
+}
+
+void SoundTriggerHw::convertUuidFromHal(Uuid* uuid, const sound_trigger_uuid_t* halUuid) {
+    uuid->timeLow = halUuid->timeLow;
+    uuid->timeMid = halUuid->timeMid;
+    uuid->versionAndTimeHigh = halUuid->timeHiAndVersion;
+    uuid->variantAndClockSeqHigh = halUuid->clockSeq;
+    memcpy(&uuid->node[0], &halUuid->node[0], 6);
+}
+
+void SoundTriggerHw::convertUuidToHal(sound_trigger_uuid_t* halUuid, const Uuid* uuid) {
+    halUuid->timeLow = uuid->timeLow;
+    halUuid->timeMid = uuid->timeMid;
+    halUuid->timeHiAndVersion = uuid->versionAndTimeHigh;
+    halUuid->clockSeq = uuid->variantAndClockSeqHigh;
+    memcpy(&halUuid->node[0], &uuid->node[0], 6);
+}
+
+void SoundTriggerHw::convertPropertiesFromHal(
+        ISoundTriggerHw::Properties* properties,
+        const struct sound_trigger_properties* halProperties) {
+    properties->implementor = halProperties->implementor;
+    properties->description = halProperties->description;
+    properties->version = halProperties->version;
+    convertUuidFromHal(&properties->uuid, &halProperties->uuid);
+    properties->maxSoundModels = halProperties->max_sound_models;
+    properties->maxKeyPhrases = halProperties->max_key_phrases;
+    properties->maxUsers = halProperties->max_users;
+    properties->recognitionModes = halProperties->recognition_modes;
+    properties->captureTransition = halProperties->capture_transition;
+    properties->maxBufferMs = halProperties->max_buffer_ms;
+    properties->concurrentCapture = halProperties->concurrent_capture;
+    properties->triggerInEvent = halProperties->trigger_in_event;
+    properties->powerConsumptionMw = halProperties->power_consumption_mw;
+}
+
+void SoundTriggerHw::convertTriggerPhraseToHal(struct sound_trigger_phrase* halTriggerPhrase,
+                                               const ISoundTriggerHw::Phrase* triggerPhrase) {
+    halTriggerPhrase->id = triggerPhrase->id;
+    halTriggerPhrase->recognition_mode = triggerPhrase->recognitionModes;
+    unsigned int i;
+
+    halTriggerPhrase->num_users =
+            std::min((int)triggerPhrase->users.size(), SOUND_TRIGGER_MAX_USERS);
+    for (i = 0; i < halTriggerPhrase->num_users; i++) {
+        halTriggerPhrase->users[i] = triggerPhrase->users[i];
+    }
+
+    strlcpy(halTriggerPhrase->locale, triggerPhrase->locale.c_str(), SOUND_TRIGGER_MAX_LOCALE_LEN);
+    strlcpy(halTriggerPhrase->text, triggerPhrase->text.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
+}
+
+struct sound_trigger_sound_model* SoundTriggerHw::convertSoundModelToHal(
+        const V2_0::ISoundTriggerHw::SoundModel* soundModel) {
+    struct sound_trigger_sound_model* halModel = NULL;
+    if (soundModel->type == V2_0::SoundModelType::KEYPHRASE) {
+        size_t allocSize =
+                sizeof(struct sound_trigger_phrase_sound_model) + soundModel->data.size();
+        struct sound_trigger_phrase_sound_model* halKeyPhraseModel =
+                static_cast<struct sound_trigger_phrase_sound_model*>(malloc(allocSize));
+        LOG_ALWAYS_FATAL_IF(halKeyPhraseModel == NULL,
+                            "malloc failed for size %zu in convertSoundModelToHal PHRASE",
+                            allocSize);
+
+        const V2_0::ISoundTriggerHw::PhraseSoundModel* keyPhraseModel =
+                reinterpret_cast<const V2_0::ISoundTriggerHw::PhraseSoundModel*>(soundModel);
+
+        size_t i;
+        for (i = 0; i < keyPhraseModel->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
+            convertTriggerPhraseToHal(&halKeyPhraseModel->phrases[i], &keyPhraseModel->phrases[i]);
+        }
+        halKeyPhraseModel->num_phrases = (unsigned int)i;
+        halModel = reinterpret_cast<struct sound_trigger_sound_model*>(halKeyPhraseModel);
+        halModel->data_offset = sizeof(struct sound_trigger_phrase_sound_model);
+    } else {
+        size_t allocSize = sizeof(struct sound_trigger_sound_model) + soundModel->data.size();
+        halModel = static_cast<struct sound_trigger_sound_model*>(malloc(allocSize));
+        LOG_ALWAYS_FATAL_IF(halModel == NULL,
+                            "malloc failed for size %zu in convertSoundModelToHal GENERIC",
+                            allocSize);
+
+        halModel->data_offset = sizeof(struct sound_trigger_sound_model);
+    }
+    halModel->type = (sound_trigger_sound_model_type_t)soundModel->type;
+    convertUuidToHal(&halModel->uuid, &soundModel->uuid);
+    convertUuidToHal(&halModel->vendor_uuid, &soundModel->vendorUuid);
+    halModel->data_size = soundModel->data.size();
+    uint8_t* dst = reinterpret_cast<uint8_t*>(halModel) + halModel->data_offset;
+    const uint8_t* src = reinterpret_cast<const uint8_t*>(&soundModel->data[0]);
+    memcpy(dst, src, soundModel->data.size());
+
+    return halModel;
+}
+
+void SoundTriggerHw::convertPhraseRecognitionExtraToHal(
+        struct sound_trigger_phrase_recognition_extra* halExtra,
+        const V2_0::PhraseRecognitionExtra* extra) {
+    halExtra->id = extra->id;
+    halExtra->recognition_modes = extra->recognitionModes;
+    halExtra->confidence_level = extra->confidenceLevel;
+
+    unsigned int i;
+    for (i = 0; i < extra->levels.size() && i < SOUND_TRIGGER_MAX_USERS; i++) {
+        halExtra->levels[i].user_id = extra->levels[i].userId;
+        halExtra->levels[i].level = extra->levels[i].levelPercent;
+    }
+    halExtra->num_levels = i;
+}
+
+struct sound_trigger_recognition_config* SoundTriggerHw::convertRecognitionConfigToHal(
+        const V2_0::ISoundTriggerHw::RecognitionConfig* config) {
+    size_t allocSize = sizeof(struct sound_trigger_recognition_config) + config->data.size();
+    struct sound_trigger_recognition_config* halConfig =
+            static_cast<struct sound_trigger_recognition_config*>(malloc(allocSize));
+
+    LOG_ALWAYS_FATAL_IF(halConfig == NULL,
+                        "malloc failed for size %zu in convertRecognitionConfigToHal", allocSize);
+
+    halConfig->capture_handle = (audio_io_handle_t)config->captureHandle;
+    halConfig->capture_device = (audio_devices_t)config->captureDevice;
+    halConfig->capture_requested = config->captureRequested;
+
+    unsigned int i;
+    for (i = 0; i < config->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
+        convertPhraseRecognitionExtraToHal(&halConfig->phrases[i], &config->phrases[i]);
+    }
+    halConfig->num_phrases = i;
+
+    halConfig->data_offset = sizeof(struct sound_trigger_recognition_config);
+    halConfig->data_size = config->data.size();
+    uint8_t* dst = reinterpret_cast<uint8_t*>(halConfig) + halConfig->data_offset;
+    const uint8_t* src = reinterpret_cast<const uint8_t*>(&config->data[0]);
+    memcpy(dst, src, config->data.size());
+    return halConfig;
+}
+
+// static
+void SoundTriggerHw::convertSoundModelEventFromHal(
+        V2_0::ISoundTriggerHwCallback::ModelEvent* event,
+        const struct sound_trigger_model_event* halEvent) {
+    event->status = (V2_0::ISoundTriggerHwCallback::SoundModelStatus)halEvent->status;
+    // event->model to be remapped by called
+    event->data.setToExternal(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) +
+                                      halEvent->data_offset,
+                              halEvent->data_size);
+}
+
+// static
+void SoundTriggerHw::convertPhaseRecognitionEventFromHal(
+        V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent* event,
+        const struct sound_trigger_phrase_recognition_event* halEvent) {
+    event->phraseExtras.resize(halEvent->num_phrases);
+    for (unsigned int i = 0; i < halEvent->num_phrases; i++) {
+        convertPhraseRecognitionExtraFromHal(&event->phraseExtras[i], &halEvent->phrase_extras[i]);
+    }
+    convertRecognitionEventFromHal(&event->common, &halEvent->common);
+}
+
+// static
+void SoundTriggerHw::convertRecognitionEventFromHal(
+        V2_0::ISoundTriggerHwCallback::RecognitionEvent* event,
+        const struct sound_trigger_recognition_event* halEvent) {
+    event->status = static_cast<V2_0::ISoundTriggerHwCallback::RecognitionStatus>(halEvent->status);
+    event->type = static_cast<V2_0::SoundModelType>(halEvent->type);
+    // event->model to be remapped by called
+    event->captureAvailable = halEvent->capture_available;
+    event->captureSession = halEvent->capture_session;
+    event->captureDelayMs = halEvent->capture_delay_ms;
+    event->capturePreambleMs = halEvent->capture_preamble_ms;
+    event->triggerInData = halEvent->trigger_in_data;
+    event->audioConfig.sampleRateHz = halEvent->audio_config.sample_rate;
+    event->audioConfig.channelMask =
+            (audio::common::V2_0::AudioChannelMask)halEvent->audio_config.channel_mask;
+    event->audioConfig.format = (audio::common::V2_0::AudioFormat)halEvent->audio_config.format;
+    event->data.setToExternal(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) +
+                                      halEvent->data_offset,
+                              halEvent->data_size);
+}
+
+// static
+void SoundTriggerHw::convertPhraseRecognitionExtraFromHal(
+        V2_0::PhraseRecognitionExtra* extra,
+        const struct sound_trigger_phrase_recognition_extra* halExtra) {
+    extra->id = halExtra->id;
+    extra->recognitionModes = halExtra->recognition_modes;
+    extra->confidenceLevel = halExtra->confidence_level;
+
+    extra->levels.resize(halExtra->num_levels);
+    for (unsigned int i = 0; i < halExtra->num_levels; i++) {
+        extra->levels[i].userId = halExtra->levels[i].user_id;
+        extra->levels[i].levelPercent = halExtra->levels[i].level;
+    }
+}
+
+void SoundTriggerHw::SoundModelClient_2_0::recognitionCallback(
+        struct sound_trigger_recognition_event* halEvent) {
+    if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
+        V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent event;
+        convertPhaseRecognitionEventFromHal(
+                &event, reinterpret_cast<sound_trigger_phrase_recognition_event*>(halEvent));
+        event.common.model = mId;
+        mCallback->phraseRecognitionCallback(event, mCookie);
+    } else {
+        V2_0::ISoundTriggerHwCallback::RecognitionEvent event;
+        convertRecognitionEventFromHal(&event, halEvent);
+        event.model = mId;
+        mCallback->recognitionCallback(event, mCookie);
+    }
+}
+
+void SoundTriggerHw::SoundModelClient_2_0::soundModelCallback(
+        struct sound_trigger_model_event* halEvent) {
+    V2_0::ISoundTriggerHwCallback::ModelEvent event;
+    convertSoundModelEventFromHal(&event, halEvent);
+    event.model = mId;
+    mCallback->soundModelCallback(event, mCookie);
+}
+
+// Begin V2_1 implementation, copied from
+// hardware/interfaces/soundtrigger/2.1/default/SoundTriggerHw.cpp
+
+namespace {
+
+// Backs up by the vector with the contents of shared memory.
+// It is assumed that the passed hidl_vector is empty, so it's
+// not cleared if the memory is a null object.
+// The caller needs to keep the returned sp<IMemory> as long as
+// the data is needed.
+std::pair<bool, sp<IMemory>> memoryAsVector(const hidl_memory& m, hidl_vec<uint8_t>* vec) {
+    sp<IMemory> memory;
+    if (m.size() == 0) {
+        return std::make_pair(true, memory);
+    }
+    memory = mapMemory(m);
+    if (memory != nullptr) {
+        memory->read();
+        vec->setToExternal(static_cast<uint8_t*>(static_cast<void*>(memory->getPointer())),
+                           memory->getSize());
+        return std::make_pair(true, memory);
+    }
+    ALOGE("%s: Could not map HIDL memory to IMemory", __func__);
+    return std::make_pair(false, memory);
+}
+
+// Moves the data from the vector into allocated shared memory,
+// emptying the vector.
+// It is assumed that the passed hidl_memory is a null object, so it's
+// not reset if the vector is empty.
+// The caller needs to keep the returned sp<IMemory> as long as
+// the data is needed.
+std::pair<bool, sp<IMemory>> moveVectorToMemory(hidl_vec<uint8_t>* v, hidl_memory* mem) {
+    sp<IMemory> memory;
+    if (v->size() == 0) {
+        return std::make_pair(true, memory);
+    }
+    sp<IAllocator> ashmem = IAllocator::getService("ashmem");
+    if (ashmem == 0) {
+        ALOGE("Failed to retrieve ashmem allocator service");
+        return std::make_pair(false, memory);
+    }
+    bool success = false;
+    Return<void> r = ashmem->allocate(v->size(), [&](bool s, const hidl_memory& m) {
+        success = s;
+        if (success) *mem = m;
+    });
+    if (r.isOk() && success) {
+        memory = hardware::mapMemory(*mem);
+        if (memory != 0) {
+            memory->update();
+            memcpy(memory->getPointer(), v->data(), v->size());
+            memory->commit();
+            v->resize(0);
+            return std::make_pair(true, memory);
+        } else {
+            ALOGE("Failed to map allocated ashmem");
+        }
+    } else {
+        ALOGE("Failed to allocate %llu bytes from ashmem", (unsigned long long)v->size());
+    }
+    return std::make_pair(false, memory);
+}
+
+}  // namespace
+
+Return<void> SoundTriggerHw::loadSoundModel_2_1(
+        const V2_1::ISoundTriggerHw::SoundModel& soundModel,
+        const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie,
+        V2_1::ISoundTriggerHw::loadSoundModel_2_1_cb _hidl_cb) {
+    // It is assumed that legacy data vector is empty, thus making copy is cheap.
+    V2_0::ISoundTriggerHw::SoundModel soundModel_2_0(soundModel.header);
+    auto result = memoryAsVector(soundModel.data, &soundModel_2_0.data);
+    if (result.first) {
+        sp<SoundModelClient> client =
+                new SoundModelClient_2_1(nextUniqueModelId(), cookie, callback);
+        _hidl_cb(doLoadSoundModel(soundModel_2_0, client), client->getId());
+        return Void();
+    }
+    _hidl_cb(-ENOMEM, 0);
+    return Void();
+}
+
+Return<void> SoundTriggerHw::loadPhraseSoundModel_2_1(
+        const V2_1::ISoundTriggerHw::PhraseSoundModel& soundModel,
+        const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie,
+        V2_1::ISoundTriggerHw::loadPhraseSoundModel_2_1_cb _hidl_cb) {
+    V2_0::ISoundTriggerHw::PhraseSoundModel soundModel_2_0;
+    // It is assumed that legacy data vector is empty, thus making copy is cheap.
+    soundModel_2_0.common = soundModel.common.header;
+    // Avoid copying phrases data.
+    soundModel_2_0.phrases.setToExternal(
+            const_cast<V2_0::ISoundTriggerHw::Phrase*>(soundModel.phrases.data()),
+            soundModel.phrases.size());
+    auto result = memoryAsVector(soundModel.common.data, &soundModel_2_0.common.data);
+    if (result.first) {
+        sp<SoundModelClient> client =
+                new SoundModelClient_2_1(nextUniqueModelId(), cookie, callback);
+        _hidl_cb(doLoadSoundModel((const V2_0::ISoundTriggerHw::SoundModel&)soundModel_2_0, client),
+                 client->getId());
+        return Void();
+    }
+    _hidl_cb(-ENOMEM, 0);
+    return Void();
+}
+
+Return<int32_t> SoundTriggerHw::startRecognition_2_1(
+        int32_t modelHandle, const V2_1::ISoundTriggerHw::RecognitionConfig& config,
+        const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie) {
+    // It is assumed that legacy data vector is empty, thus making copy is cheap.
+    V2_0::ISoundTriggerHw::RecognitionConfig config_2_0(config.header);
+    auto result = memoryAsVector(config.data, &config_2_0.data);
+    return result.first ? startRecognition(modelHandle, config_2_0, callback, cookie)
+                        : Return<int32_t>(-ENOMEM);
+}
+
+void SoundTriggerHw::SoundModelClient_2_1::recognitionCallback(
+        struct sound_trigger_recognition_event* halEvent) {
+    if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
+        V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent event_2_0;
+        convertPhaseRecognitionEventFromHal(
+                &event_2_0, reinterpret_cast<sound_trigger_phrase_recognition_event*>(halEvent));
+        event_2_0.common.model = mId;
+        V2_1::ISoundTriggerHwCallback::PhraseRecognitionEvent event;
+        event.phraseExtras.setToExternal(event_2_0.phraseExtras.data(),
+                                         event_2_0.phraseExtras.size());
+        auto result = moveVectorToMemory(&event_2_0.common.data, &event.common.data);
+        if (result.first) {
+            // The data vector is now empty, thus copying is cheap.
+            event.common.header = event_2_0.common;
+            mCallback->phraseRecognitionCallback_2_1(event, mCookie);
+        }
+    } else {
+        V2_1::ISoundTriggerHwCallback::RecognitionEvent event;
+        convertRecognitionEventFromHal(&event.header, halEvent);
+        event.header.model = mId;
+        auto result = moveVectorToMemory(&event.header.data, &event.data);
+        if (result.first) {
+            mCallback->recognitionCallback_2_1(event, mCookie);
+        }
+    }
+}
+
+void SoundTriggerHw::SoundModelClient_2_1::soundModelCallback(
+        struct sound_trigger_model_event* halEvent) {
+    V2_1::ISoundTriggerHwCallback::ModelEvent event;
+    convertSoundModelEventFromHal(&event.header, halEvent);
+    event.header.model = mId;
+    auto result = moveVectorToMemory(&event.header.data, &event.data);
+    if (result.first) {
+        mCallback->soundModelCallback_2_1(event, mCookie);
+    }
+}
+
+// Begin V2_2 implementation, copied from
+// hardware/interfaces/soundtrigger/2.2/default/SoundTriggerHw.cpp
+
+Return<int32_t> SoundTriggerHw::getModelState(int32_t modelHandle) {
+    sp<SoundModelClient> client;
+    if (mHwDevice == NULL) {
+        return -ENODEV;
+    }
+
+    {
+        AutoMutex lock(mLock);
+        client = mClients.valueFor(modelHandle);
+        if (client == 0) {
+            return -ENOSYS;
+        }
+    }
+
+    return mHwDevice->get_model_state(mHwDevice, client->getHalHandle());
+}
+
+// Begin V2_3 implementation
+
+Return<int32_t> SoundTriggerHw::setParameter(V2_0::SoundModelHandle modelHandle,
+                                             ModelParameter modelParam, int32_t value) {
+    sp<SoundModelClient> client;
+    if (mHwDevice == NULL) {
+        return -ENODEV;
+    }
+
+    {
+        AutoMutex lock(mLock);
+        client = mClients.valueFor(modelHandle);
+        if (client == 0) {
+            return -EINVAL;
+        }
+    }
+
+    return mHwDevice->set_parameter(mHwDevice, client->getHalHandle(),
+                                    convertModelParameterToHal(modelParam), value);
+}
+
+Return<void> SoundTriggerHw::getParameter(V2_0::SoundModelHandle modelHandle,
+                                          ModelParameter modelParam, getParameter_cb _hidl_cb) {
+    sp<SoundModelClient> client;
+    if (mHwDevice == NULL) {
+        _hidl_cb(-ENODEV, 0);
+        return Void();
+    }
+
+    {
+        AutoMutex lock(mLock);
+        client = mClients.valueFor(modelHandle);
+        if (client == 0) {
+            _hidl_cb(-EINVAL, 0);
+            return Void();
+        }
+    }
+
+    int32_t value;
+    int32_t status = mHwDevice->get_parameter(mHwDevice, client->getHalHandle(),
+                                              convertModelParameterToHal(modelParam), &value);
+    _hidl_cb(status, value);
+    return Void();
+}
+
+Return<void> SoundTriggerHw::queryParameter(V2_0::SoundModelHandle modelHandle,
+                                            ModelParameter modelParam, queryParameter_cb _hidl_cb) {
+    OptionalModelParameterRange optionalParamRange;
+    sp<SoundModelClient> client;
+    if (mHwDevice == NULL) {
+        _hidl_cb(-ENODEV, optionalParamRange);
+        return Void();
+    }
+
+    {
+        AutoMutex lock(mLock);
+        client = mClients.valueFor(modelHandle);
+        if (client == 0) {
+            _hidl_cb(-EINVAL, optionalParamRange);
+            return Void();
+        }
+    }
+
+    sound_trigger_model_parameter_range_t paramRange;
+    int32_t status = mHwDevice->query_parameter(
+            mHwDevice, client->getHalHandle(), convertModelParameterToHal(modelParam), &paramRange);
+
+    if (status == 0) {
+        optionalParamRange.range({.start = paramRange.start, .end = paramRange.end});
+    }
+    _hidl_cb(status, optionalParamRange);
+    return Void();
+}
+
+// static
+sound_trigger_model_parameter_t SoundTriggerHw::convertModelParameterToHal(ModelParameter param) {
+    switch (param) {
+        case ModelParameter::THRESHOLD_FACTOR:
+            return MODEL_PARAMETER_THRESHOLD_FACTOR;
+        case ModelParameter::INVALID:
+        default:
+            return MODEL_PARAMETER_INVALID;
+    }
+}
+
+// Methods from ::android::hidl::base::V1_0::IBase follow.
+
+ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* /* name */) {
+    return new SoundTriggerHw();
+}
+
+}  // namespace implementation
+}  // namespace V2_3
+}  // namespace soundtrigger
+}  // namespace hardware
+}  // namespace android
diff --git a/soundtrigger/2.3/default/SoundTriggerHw.h b/soundtrigger/2.3/default/SoundTriggerHw.h
new file mode 100644
index 0000000..c82c9ea
--- /dev/null
+++ b/soundtrigger/2.3/default/SoundTriggerHw.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2019 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_SOUNDTRIGGER_V2_3_SOUNDTRIGGERHW_H
+#define ANDROID_HARDWARE_SOUNDTRIGGER_V2_3_SOUNDTRIGGERHW_H
+
+#include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
+#include <android/hardware/soundtrigger/2.0/ISoundTriggerHwCallback.h>
+#include <android/hardware/soundtrigger/2.3/ISoundTriggerHw.h>
+#include <android/hardware/soundtrigger/2.3/types.h>
+#include <hardware/sound_trigger.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <stdatomic.h>
+#include <system/sound_trigger.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+
+namespace android {
+namespace hardware {
+namespace soundtrigger {
+namespace V2_3 {
+namespace implementation {
+
+using ::android::sp;
+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::hardware::audio::common::V2_0::Uuid;
+
+/**
+ * According to the HIDL C++ Users Guide: client and server implementations
+ * should never directly refer to anything other than the interface header
+ * generated from the HIDL definition file (ie. ISoundTriggerHw.hal), so
+ * this V2_3 implementation copies the previous implementations and
+ * then adds the new implementation.
+ */
+struct SoundTriggerHw : public ISoundTriggerHw {
+    // Methods from V2_0::ISoundTriggerHw follow.
+    Return<void> getProperties(getProperties_cb _hidl_cb) override;
+    Return<void> loadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel,
+                                const sp<V2_0::ISoundTriggerHwCallback>& callback, int32_t cookie,
+                                loadSoundModel_cb _hidl_cb) override;
+    Return<void> loadPhraseSoundModel(const V2_0::ISoundTriggerHw::PhraseSoundModel& soundModel,
+                                      const sp<V2_0::ISoundTriggerHwCallback>& callback,
+                                      int32_t cookie, loadPhraseSoundModel_cb _hidl_cb) override;
+    Return<int32_t> unloadSoundModel(int32_t modelHandle) override;
+    Return<int32_t> startRecognition(int32_t modelHandle,
+                                     const V2_0::ISoundTriggerHw::RecognitionConfig& config,
+                                     const sp<V2_0::ISoundTriggerHwCallback>& callback,
+                                     int32_t cookie) override;
+    Return<int32_t> stopRecognition(int32_t modelHandle) override;
+    Return<int32_t> stopAllRecognitions() override;
+
+    // Methods from V2_1::ISoundTriggerHw follow.
+    Return<void> loadSoundModel_2_1(const V2_1::ISoundTriggerHw::SoundModel& soundModel,
+                                    const sp<V2_1::ISoundTriggerHwCallback>& callback,
+                                    int32_t cookie, loadSoundModel_2_1_cb _hidl_cb) override;
+    Return<void> loadPhraseSoundModel_2_1(const V2_1::ISoundTriggerHw::PhraseSoundModel& soundModel,
+                                          const sp<V2_1::ISoundTriggerHwCallback>& callback,
+                                          int32_t cookie,
+                                          loadPhraseSoundModel_2_1_cb _hidl_cb) override;
+    Return<int32_t> startRecognition_2_1(int32_t modelHandle,
+                                         const V2_1::ISoundTriggerHw::RecognitionConfig& config,
+                                         const sp<V2_1::ISoundTriggerHwCallback>& callback,
+                                         int32_t cookie) override;
+
+    // Methods from V2_2::ISoundTriggerHw follow.
+    Return<int32_t> getModelState(int32_t modelHandle) override;
+
+    // Methods from V2_3::ISoundTriggerHw follow.
+    Return<int32_t> setParameter(V2_0::SoundModelHandle modelHandle, ModelParameter modelParam,
+                                 int32_t value) override;
+    Return<void> getParameter(V2_0::SoundModelHandle modelHandle, ModelParameter modelParam,
+                              ISoundTriggerHw::getParameter_cb _hidl_cb) override;
+    Return<void> queryParameter(V2_0::SoundModelHandle modelHandle, ModelParameter modelParam,
+                                ISoundTriggerHw::queryParameter_cb _hidl_cb) override;
+
+    SoundTriggerHw();
+
+    // Copied from hardware/interfaces/soundtrigger/2.0/default/SoundTriggerHalImpl.h
+
+    /**
+     * Client object holding active handles and callback sctructures. Used for referencing
+     * which models map to which client of the HAL. SoundModelClients are stored in the
+     * mClients object while the model is active.
+     */
+    class SoundModelClient : public RefBase {
+      public:
+        SoundModelClient(uint32_t id, V2_0::ISoundTriggerHwCallback::CallbackCookie cookie)
+            : mId(id), mCookie(cookie) {}
+        virtual ~SoundModelClient() {}
+
+        uint32_t getId() const { return mId; }
+        sound_model_handle_t getHalHandle() const { return mHalHandle; }
+        void setHalHandle(sound_model_handle_t handle) { mHalHandle = handle; }
+
+        virtual void recognitionCallback(struct sound_trigger_recognition_event* halEvent) = 0;
+        virtual void soundModelCallback(struct sound_trigger_model_event* halEvent) = 0;
+
+      protected:
+        const uint32_t mId;
+        sound_model_handle_t mHalHandle;
+        V2_0::ISoundTriggerHwCallback::CallbackCookie mCookie;
+    };
+
+  private:
+    static void convertPhaseRecognitionEventFromHal(
+            V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent* event,
+            const struct sound_trigger_phrase_recognition_event* halEvent);
+    static void convertRecognitionEventFromHal(
+            V2_0::ISoundTriggerHwCallback::RecognitionEvent* event,
+            const struct sound_trigger_recognition_event* halEvent);
+    static void convertSoundModelEventFromHal(V2_0::ISoundTriggerHwCallback::ModelEvent* event,
+                                              const struct sound_trigger_model_event* halEvent);
+
+    virtual ~SoundTriggerHw();
+
+    uint32_t nextUniqueModelId();
+    int doLoadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel,
+                         sp<SoundModelClient> client);
+
+    // RefBase
+    void onFirstRef() override;
+
+    class SoundModelClient_2_0 : public SoundModelClient {
+      public:
+        SoundModelClient_2_0(uint32_t id, V2_0::ISoundTriggerHwCallback::CallbackCookie cookie,
+                             sp<V2_0::ISoundTriggerHwCallback> callback)
+            : SoundModelClient(id, cookie), mCallback(callback) {}
+
+        void recognitionCallback(struct sound_trigger_recognition_event* halEvent) override;
+        void soundModelCallback(struct sound_trigger_model_event* halEvent) override;
+
+      private:
+        sp<V2_0::ISoundTriggerHwCallback> mCallback;
+    };
+
+    void convertUuidFromHal(Uuid* uuid, const sound_trigger_uuid_t* halUuid);
+    void convertUuidToHal(sound_trigger_uuid_t* halUuid, const Uuid* uuid);
+    void convertPropertiesFromHal(V2_0::ISoundTriggerHw::Properties* properties,
+                                  const struct sound_trigger_properties* halProperties);
+    static sound_trigger_model_parameter_t convertModelParameterToHal(ModelParameter param);
+    void convertTriggerPhraseToHal(struct sound_trigger_phrase* halTriggerPhrase,
+                                   const V2_0::ISoundTriggerHw::Phrase* triggerPhrase);
+    // returned HAL sound model must be freed by caller
+    struct sound_trigger_sound_model* convertSoundModelToHal(
+            const V2_0::ISoundTriggerHw::SoundModel* soundModel);
+    void convertPhraseRecognitionExtraToHal(struct sound_trigger_phrase_recognition_extra* halExtra,
+                                            const V2_0::PhraseRecognitionExtra* extra);
+    // returned recognition config must be freed by caller
+    struct sound_trigger_recognition_config* convertRecognitionConfigToHal(
+            const V2_0::ISoundTriggerHw::RecognitionConfig* config);
+
+    static void convertPhraseRecognitionExtraFromHal(
+            V2_0::PhraseRecognitionExtra* extra,
+            const struct sound_trigger_phrase_recognition_extra* halExtra);
+
+    static void soundModelCallback(struct sound_trigger_model_event* halEvent, void* cookie);
+    static void recognitionCallback(struct sound_trigger_recognition_event* halEvent, void* cookie);
+
+    const char* mModuleName;
+    struct sound_trigger_hw_device* mHwDevice;
+    volatile atomic_uint_fast32_t mNextModelId;
+    DefaultKeyedVector<int32_t, sp<SoundModelClient>> mClients;
+    Mutex mLock;
+
+    // Copied from hardware/interfaces/soundtrigger/2.1/default/SoundTriggerHw.h
+    class SoundModelClient_2_1 : public SoundModelClient {
+      public:
+        SoundModelClient_2_1(uint32_t id, V2_1::ISoundTriggerHwCallback::CallbackCookie cookie,
+                             sp<V2_1::ISoundTriggerHwCallback> callback)
+            : SoundModelClient(id, cookie), mCallback(callback) {}
+
+        void recognitionCallback(struct sound_trigger_recognition_event* halEvent) override;
+        void soundModelCallback(struct sound_trigger_model_event* halEvent) override;
+
+      private:
+        sp<V2_1::ISoundTriggerHwCallback> mCallback;
+    };
+};
+
+extern "C" ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* name);
+
+}  // namespace implementation
+}  // namespace V2_3
+}  // namespace soundtrigger
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_SOUNDTRIGGER_V2_2_SOUNDTRIGGERHW_H
diff --git a/soundtrigger/2.3/types.hal b/soundtrigger/2.3/types.hal
new file mode 100644
index 0000000..c3a522b
--- /dev/null
+++ b/soundtrigger/2.3/types.hal
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2019 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.
+ */
+
+package android.hardware.soundtrigger@2.3;
+
+import android.hidl.safe_union@1.0::Monostate;
+
+/**
+ * Model specific parameters to be used with parameter set and get APIs
+ */
+enum ModelParameter : int32_t {
+    /**
+     * Placeholder for invalid model parameter used for returning error or
+     * passing an invalid value.
+     */
+    INVALID = -1,
+
+    /**
+     * Controls the sensitivity threshold adjustment factor for a given model.
+     * Negative value corresponds to less sensitive model (high threshold) and
+     * a positive value corresponds to a more sensitive model (low threshold).
+     * Default value is 0.
+     */
+    THRESHOLD_FACTOR = 0
+};
+
+/**
+ * Safe union wrapping ModelParameterRange.
+ * Monostate is used to indicate there is no valid range
+ */
+safe_union OptionalModelParameterRange {
+    Monostate noinit;
+    ModelParameterRange range;
+};
+
+/**
+ * Model specific range support for a given parameter
+ */
+struct ModelParameterRange {
+    /**
+     * start of supported value range inclusive
+     */
+    int32_t start;
+    /**
+     * end of supported value range inclusive
+     */
+    int32_t end;
+};
diff --git a/soundtrigger/2.3/vts/functional/Android.bp b/soundtrigger/2.3/vts/functional/Android.bp
new file mode 100644
index 0000000..e3855fc
--- /dev/null
+++ b/soundtrigger/2.3/vts/functional/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2019 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.
+//
+
+cc_test {
+    name: "VtsHalSoundtriggerV2_3TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalSoundtriggerV2_3TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.soundtrigger@2.0",
+        "android.hardware.soundtrigger@2.1",
+        "android.hardware.soundtrigger@2.2",
+        "android.hardware.soundtrigger@2.3",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts-core",
+    ],
+}
diff --git a/soundtrigger/2.3/vts/functional/VtsHalSoundtriggerV2_3TargetTest.cpp b/soundtrigger/2.3/vts/functional/VtsHalSoundtriggerV2_3TargetTest.cpp
new file mode 100644
index 0000000..202eb6c
--- /dev/null
+++ b/soundtrigger/2.3/vts/functional/VtsHalSoundtriggerV2_3TargetTest.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2019 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_TAG "SoundTriggerHidlHalTest"
+
+#include <android-base/logging.h>
+#include <android/hardware/audio/common/2.0/types.h>
+#include <android/hardware/soundtrigger/2.3/ISoundTriggerHw.h>
+#include <android/hardware/soundtrigger/2.3/types.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+using ::android::sp;
+using ::android::hardware::Return;
+using ::android::hardware::soundtrigger::V2_3::ISoundTriggerHw;
+
+/**
+ * Test class holding the instance of the SoundTriggerHW service to test.
+ * The passed parameter is the registered name of the implementing service
+ * supplied by INSTANTIATE_TEST_SUITE_P() call.
+ */
+class SoundTriggerHidlTest : public testing::TestWithParam<std::string> {
+  public:
+    void SetUp() override {
+        soundtrigger = ISoundTriggerHw::getService(GetParam());
+
+        ASSERT_NE(soundtrigger, nullptr);
+        LOG(INFO) << "Test is remote " << soundtrigger->isRemote();
+    }
+
+    sp<ISoundTriggerHw> soundtrigger;
+};
+
+/**
+ * Empty test is in place to ensure service is initalized.
+ * Due to the nature of SoundTrigger HAL providing an interface for
+ * proprietary or vendor specific implementations, limited testing on
+ * individual APIs is possible.
+ */
+TEST_P(SoundTriggerHidlTest, ServiceIsInstantiated) {}
+
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, SoundTriggerHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(ISoundTriggerHw::descriptor)),
+        android::hardware::PrintInstanceNameToString);
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index f47b10d..0e2b3e1 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -34,18 +34,10 @@
 using android::hardware::vibrator::EffectStrength;
 using android::hardware::vibrator::IVibrator;
 
-// TODO(b/143992652): autogenerate
-const std::vector<Effect> kEffects = {
-        Effect::CLICK,       Effect::DOUBLE_CLICK, Effect::TICK,        Effect::THUD,
-        Effect::POP,         Effect::HEAVY_CLICK,  Effect::RINGTONE_1,  Effect::RINGTONE_2,
-        Effect::RINGTONE_3,  Effect::RINGTONE_4,   Effect::RINGTONE_5,  Effect::RINGTONE_6,
-        Effect::RINGTONE_7,  Effect::RINGTONE_8,   Effect::RINGTONE_9,  Effect::RINGTONE_10,
-        Effect::RINGTONE_11, Effect::RINGTONE_12,  Effect::RINGTONE_13, Effect::RINGTONE_14,
-        Effect::RINGTONE_15, Effect::TEXTURE_TICK};
-
-// TODO(b/143992652): autogenerate
-const std::vector<EffectStrength> kEffectStrengths = {EffectStrength::LIGHT, EffectStrength::MEDIUM,
-                                                      EffectStrength::STRONG};
+const std::vector<Effect> kEffects{android::enum_range<Effect>().begin(),
+                                   android::enum_range<Effect>().end()};
+const std::vector<EffectStrength> kEffectStrengths{android::enum_range<EffectStrength>().begin(),
+                                                   android::enum_range<EffectStrength>().end()};
 
 const std::vector<Effect> kInvalidEffects = {
         static_cast<Effect>(static_cast<int32_t>(kEffects.front()) - 1),
diff --git a/wifi/1.4/Android.bp b/wifi/1.4/Android.bp
index b443230..3b94619 100644
--- a/wifi/1.4/Android.bp
+++ b/wifi/1.4/Android.bp
@@ -15,7 +15,6 @@
         "IWifiNanIface.hal",
         "IWifiRttController.hal",
         "IWifiRttControllerEventCallback.hal",
-        "IWifiStaIface.hal",
     ],
     interfaces: [
         "android.hardware.wifi@1.0",
diff --git a/wifi/1.4/IWifiStaIface.hal b/wifi/1.4/IWifiStaIface.hal
deleted file mode 100644
index 8bb0de8..0000000
--- a/wifi/1.4/IWifiStaIface.hal
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2019 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.
- */
-
-package android.hardware.wifi@1.4;
-
-import @1.0::WifiStatus;
-import @1.0::MacAddress;
-import @1.0::IWifiStaIface;
-import @1.3::IWifiStaIface;
-
-/**
- * Interface used to represent a single STA iface.
- *
- * IWifiChip.createStaIface() may return a @1.4::IWifiStaIface when supported.
- */
-interface IWifiStaIface extends @1.3::IWifiStaIface {
-    enum StaIfaceCapabilityMask : @1.0::IWifiStaIface.StaIfaceCapabilityMask {
-        STA_6G = 1 << 15,
-    };
-
-    /**
-     * Get the capabilities supported by this STA iface.
-     *
-     * @return status WifiStatus of the operation.
-     *         Possible status codes:
-     *         |WifiStatusCode.SUCCESS|,
-     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
-     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
-     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
-     *         |WifiStatusCode.ERROR_UNKNOWN|
-     * @return capabilities Bitset of |StaIfaceCapabilityMask| values.
-     */
-    getCapabilities_1_4()
-        generates (WifiStatus status, bitfield<StaIfaceCapabilityMask> capabilities);
-};
diff --git a/wifi/1.4/default/hidl_struct_util.cpp b/wifi/1.4/default/hidl_struct_util.cpp
index a7c5686..4996e35 100644
--- a/wifi/1.4/default/hidl_struct_util.cpp
+++ b/wifi/1.4/default/hidl_struct_util.cpp
@@ -120,8 +120,6 @@
             return HidlStaIfaceCaps::ND_OFFLOAD;
         case WIFI_FEATURE_MKEEP_ALIVE:
             return HidlStaIfaceCaps::KEEP_ALIVE;
-        case WIFI_FEATURE_INFRA_6G:
-            return HidlStaIfaceCaps::STA_6G;
     };
     CHECK(false) << "Unknown legacy feature: " << feature;
     return {};
@@ -394,8 +392,7 @@
           WIFI_FEATURE_IE_WHITELIST, WIFI_FEATURE_SCAN_RAND,
           WIFI_FEATURE_INFRA_5G, WIFI_FEATURE_HOTSPOT, WIFI_FEATURE_PNO,
           WIFI_FEATURE_TDLS, WIFI_FEATURE_TDLS_OFFCHANNEL,
-          WIFI_FEATURE_CONFIG_NDO, WIFI_FEATURE_MKEEP_ALIVE,
-          WIFI_FEATURE_INFRA_6G}) {
+          WIFI_FEATURE_CONFIG_NDO, WIFI_FEATURE_MKEEP_ALIVE}) {
         if (feature & legacy_feature_set) {
             *hidl_caps |= convertLegacyFeatureToHidlStaIfaceCapability(feature);
         }
@@ -1135,9 +1132,9 @@
     legacy_request->disc_mac_addr_rand_interval_sec =
         hidl_request.configParams.macAddressRandomizationIntervalSec;
     legacy_request->config_2dot4g_rssi_close = 1;
-    if (hidl_request.configParams.bandSpecificConfig.size() != 2) {
+    if (hidl_request.configParams.bandSpecificConfig.size() != 3) {
         LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: "
-                      "bandSpecificConfig.size() != 2";
+                      "bandSpecificConfig.size() != 3";
         return false;
     }
     legacy_request->rssi_close_2dot4g_val =
diff --git a/wifi/1.4/default/hidl_struct_util.h b/wifi/1.4/default/hidl_struct_util.h
index 160870a..d040c1f 100644
--- a/wifi/1.4/default/hidl_struct_util.h
+++ b/wifi/1.4/default/hidl_struct_util.h
@@ -25,7 +25,6 @@
 #include <android/hardware/wifi/1.3/IWifiChip.h>
 #include <android/hardware/wifi/1.3/types.h>
 #include <android/hardware/wifi/1.4/IWifiChipEventCallback.h>
-#include <android/hardware/wifi/1.4/IWifiStaIface.h>
 #include <android/hardware/wifi/1.4/types.h>
 
 #include "wifi_legacy_hal.h"
diff --git a/wifi/1.4/default/wifi_chip.cpp b/wifi/1.4/default/wifi_chip.cpp
index 2b015d3..a70457b 100644
--- a/wifi/1.4/default/wifi_chip.cpp
+++ b/wifi/1.4/default/wifi_chip.cpp
@@ -938,7 +938,8 @@
     return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 
-std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::createStaIfaceInternal() {
+std::pair<WifiStatus, sp<V1_3::IWifiStaIface>>
+WifiChip::createStaIfaceInternal() {
     if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::STA)) {
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
@@ -962,7 +963,7 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(sta_ifaces_)};
 }
 
-std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::getStaIfaceInternal(
+std::pair<WifiStatus, sp<V1_3::IWifiStaIface>> WifiChip::getStaIfaceInternal(
     const std::string& ifname) {
     const auto iface = findUsingName(sta_ifaces_, ifname);
     if (!iface.get()) {
diff --git a/wifi/1.4/default/wifi_chip.h b/wifi/1.4/default/wifi_chip.h
index c76eabf..3323ade 100644
--- a/wifi/1.4/default/wifi_chip.h
+++ b/wifi/1.4/default/wifi_chip.h
@@ -197,9 +197,9 @@
     std::pair<WifiStatus, sp<IWifiP2pIface>> getP2pIfaceInternal(
         const std::string& ifname);
     WifiStatus removeP2pIfaceInternal(const std::string& ifname);
-    std::pair<WifiStatus, sp<IWifiStaIface>> createStaIfaceInternal();
+    std::pair<WifiStatus, sp<V1_3::IWifiStaIface>> createStaIfaceInternal();
     std::pair<WifiStatus, std::vector<hidl_string>> getStaIfaceNamesInternal();
-    std::pair<WifiStatus, sp<IWifiStaIface>> getStaIfaceInternal(
+    std::pair<WifiStatus, sp<V1_3::IWifiStaIface>> getStaIfaceInternal(
         const std::string& ifname);
     WifiStatus removeStaIfaceInternal(const std::string& ifname);
     std::pair<WifiStatus, sp<V1_0::IWifiRttController>>
diff --git a/wifi/1.4/default/wifi_sta_iface.cpp b/wifi/1.4/default/wifi_sta_iface.cpp
index 68c989d..e2ea6e4 100644
--- a/wifi/1.4/default/wifi_sta_iface.cpp
+++ b/wifi/1.4/default/wifi_sta_iface.cpp
@@ -266,13 +266,6 @@
                            hidl_status_cb);
 }
 
-Return<void> WifiStaIface::getCapabilities_1_4(
-    getCapabilities_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::getCapabilitiesInternal_1_4,
-                           hidl_status_cb);
-}
-
 std::pair<WifiStatus, std::string> WifiStaIface::getNameInternal() {
     return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
 }
@@ -290,7 +283,26 @@
 }
 
 std::pair<WifiStatus, uint32_t> WifiStaIface::getCapabilitiesInternal() {
-    return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), 0};
+    legacy_hal::wifi_error legacy_status;
+    uint64_t legacy_feature_set;
+    std::tie(legacy_status, legacy_feature_set) =
+        legacy_hal_.lock()->getSupportedFeatureSet(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), 0};
+    }
+    uint32_t legacy_logger_feature_set;
+    std::tie(legacy_status, legacy_logger_feature_set) =
+        legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        // some devices don't support querying logger feature set
+        legacy_logger_feature_set = 0;
+    }
+    uint32_t hidl_caps;
+    if (!hidl_struct_util::convertLegacyFeaturesToHidlStaCapabilities(
+            legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
 }
 
 std::pair<WifiStatus, StaApfPacketFilterCapabilities>
@@ -628,29 +640,6 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), mac};
 }
 
-std::pair<WifiStatus, uint32_t> WifiStaIface::getCapabilitiesInternal_1_4() {
-    legacy_hal::wifi_error legacy_status;
-    uint64_t legacy_feature_set;
-    std::tie(legacy_status, legacy_feature_set) =
-        legacy_hal_.lock()->getSupportedFeatureSet(ifname_);
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        return {createWifiStatusFromLegacyError(legacy_status), 0};
-    }
-    uint32_t legacy_logger_feature_set;
-    std::tie(legacy_status, legacy_logger_feature_set) =
-        legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname_);
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        // some devices don't support querying logger feature set
-        legacy_logger_feature_set = 0;
-    }
-    uint32_t hidl_caps;
-    if (!hidl_struct_util::convertLegacyFeaturesToHidlStaCapabilities(
-            legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) {
-        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0};
-    }
-    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
-}
-
 }  // namespace implementation
 }  // namespace V1_4
 }  // namespace wifi
diff --git a/wifi/1.4/default/wifi_sta_iface.h b/wifi/1.4/default/wifi_sta_iface.h
index e85e39d..dee04f2 100644
--- a/wifi/1.4/default/wifi_sta_iface.h
+++ b/wifi/1.4/default/wifi_sta_iface.h
@@ -19,7 +19,7 @@
 
 #include <android-base/macros.h>
 #include <android/hardware/wifi/1.0/IWifiStaIfaceEventCallback.h>
-#include <android/hardware/wifi/1.4/IWifiStaIface.h>
+#include <android/hardware/wifi/1.3/IWifiStaIface.h>
 
 #include "hidl_callback_util.h"
 #include "wifi_iface_util.h"
@@ -35,7 +35,7 @@
 /**
  * HIDL interface object used to control a STA Iface instance.
  */
-class WifiStaIface : public V1_4::IWifiStaIface {
+class WifiStaIface : public V1_3::IWifiStaIface {
    public:
     WifiStaIface(const std::string& ifname,
                  const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
@@ -112,8 +112,6 @@
                                setMacAddress_cb hidl_status_cb) override;
     Return<void> getFactoryMacAddress(
         getFactoryMacAddress_cb hidl_status_cb) override;
-    Return<void> getCapabilities_1_4(
-        getCapabilities_1_4_cb hidl_status_cb) override;
 
    private:
     // Corresponding worker functions for the HIDL methods.
@@ -162,7 +160,6 @@
     WifiStatus setMacAddressInternal(const std::array<uint8_t, 6>& mac);
     std::pair<WifiStatus, std::array<uint8_t, 6>>
     getFactoryMacAddressInternal();
-    std::pair<WifiStatus, uint32_t> getCapabilitiesInternal_1_4();
 
     std::string ifname_;
     std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
diff --git a/wifi/1.4/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_sta_iface_hidl_test.cpp
deleted file mode 100644
index ec4b2c9..0000000
--- a/wifi/1.4/vts/functional/wifi_sta_iface_hidl_test.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Staache 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 <android-base/logging.h>
-
-#include <android/hardware/wifi/1.4/IWifiStaIface.h>
-
-#include <VtsHalHidlTargetTestBase.h>
-
-#include "wifi_hidl_call_util.h"
-#include "wifi_hidl_test_utils.h"
-
-using ::android::sp;
-using ::android::hardware::hidl_array;
-using ::android::hardware::wifi::V1_0::WifiStatus;
-using ::android::hardware::wifi::V1_0::WifiStatusCode;
-using ::android::hardware::wifi::V1_4::IWifiStaIface;
-
-/**
- * Fixture to use for all STA Iface HIDL interface tests.
- */
-class WifiStaIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-   public:
-    virtual void SetUp() override {
-        wifi_sta_iface_ = IWifiStaIface::castFrom(getWifiStaIface());
-        ASSERT_NE(nullptr, wifi_sta_iface_.get());
-    }
-
-    virtual void TearDown() override { stopWifi(); }
-
-   protected:
-    sp<IWifiStaIface> wifi_sta_iface_;
-};
-
-/*
- * GetCapabilities_1_4
- */
-TEST_F(WifiStaIfaceHidlTest, GetCapabilities_1_4) {
-    configureChipForIfaceType(IfaceType::STA, true);
-
-    const auto& status_and_caps =
-        HIDL_INVOKE(wifi_sta_iface_, getCapabilities_1_4);
-    if (status_and_caps.first.code != WifiStatusCode::SUCCESS) {
-        EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED,
-                  status_and_caps.first.code);
-        return;
-    }
-    EXPECT_NE(0u, status_and_caps.second);
-}