Merge "NN HAL: Upgrade IPreparedModel::executeSynchronously to 1.3."
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 0140275..6740bb5 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -2,6 +2,7 @@
 ignore_merged_commits = true
 
 [Builtin Hooks]
+bpfmt = true
 clang_format = true
 
 [Hook Scripts]
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 98e125b..0e18f48 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,6 +1,12 @@
 {
   "presubmit": [
     {
+      "name": "vts_treble_vintf_framework_test"
+    },
+    {
+      "name": "vts_treble_vintf_vendor_test"
+    },
+    {
       "name": "hidl_implementation_test"
     }
   ]
diff --git a/audio/5.0/config/api/current.txt b/audio/5.0/config/api/current.txt
index c665781..a1d8e1e 100644
--- a/audio/5.0/config/api/current.txt
+++ b/audio/5.0/config/api/current.txt
@@ -237,6 +237,7 @@
     method public audio.policy.configuration.V5_0.GainMode getMode();
     method public String getName();
     method public int getStepValueMB();
+    method public boolean getUseForVolume();
     method public void setChannel_mask(String);
     method public void setDefaultValueMB(int);
     method public void setMaxRampMs(int);
@@ -246,6 +247,7 @@
     method public void setMode(audio.policy.configuration.V5_0.GainMode);
     method public void setName(String);
     method public void setStepValueMB(int);
+    method public void setUseForVolume(boolean);
   }
 
   public class GlobalConfiguration {
diff --git a/audio/5.0/config/audio_policy_configuration.xsd b/audio/5.0/config/audio_policy_configuration.xsd
index 2e1a722..284d2e2 100644
--- a/audio/5.0/config/audio_policy_configuration.xsd
+++ b/audio/5.0/config/audio_policy_configuration.xsd
@@ -446,6 +446,7 @@
                     <xs:attribute name="stepValueMB" type="xs:int" use="optional"/>
                     <xs:attribute name="minRampMs" type="xs:int" use="optional"/>
                     <xs:attribute name="maxRampMs" type="xs:int" use="optional"/>
+                    <xs:attribute name="useForVolume" type="xs:boolean" use="optional"/>
                 </xs:complexType>
             </xs:element>
         </xs:sequence>
diff --git a/audio/6.0/IDevice.hal b/audio/6.0/IDevice.hal
index e885fe2..122c550 100644
--- a/audio/6.0/IDevice.hal
+++ b/audio/6.0/IDevice.hal
@@ -280,4 +280,19 @@
      */
     setConnectedState(DeviceAddress address, bool connected)
             generates (Result retval);
+
+    /**
+     * Called by the framework to deinitialize the device and free up
+     * all currently allocated resources. It is recommended to close
+     * the device on the client side as soon as it is becomes unused.
+     *
+     * Note that all streams must be closed by the client before
+     * attempting to close the device they belong to.
+     *
+     * @return retval OK in case the success.
+     *                INVALID_STATE if the device was already closed
+     *                or there are streams currently opened.
+     */
+    @exit
+    close() generates (Result retval);
 };
diff --git a/audio/6.0/IStream.hal b/audio/6.0/IStream.hal
index 451e116..d7d3c84 100644
--- a/audio/6.0/IStream.hal
+++ b/audio/6.0/IStream.hal
@@ -277,7 +277,7 @@
      * @return retval OK in case the success.
      *                NOT_SUPPORTED on non mmap mode streams
      *                NOT_INITIALIZED in case of memory allocation error
-     *                INVALID_ARGUMENTS if the requested buffer size is too large
+     *                INVALID_ARGUMENTS if the requested buffer size is invalid
      *                INVALID_STATE if called out of sequence
      * @return info    a MmapBufferInfo struct containing information on the MMMAP buffer created.
      */
@@ -300,13 +300,17 @@
 
     /**
      * Called by the framework to deinitialize the stream and free up
-     * all the currently allocated resources. It is recommended to close
+     * all currently allocated resources. It is recommended to close
      * the stream on the client side as soon as it is becomes unused.
      *
+     * The client must ensure that this function is not called while
+     * audio data is being transferred through the stream's message queues.
+     *
      * @return retval OK in case the success.
      *                NOT_SUPPORTED if called on IStream instead of input or
      *                              output stream interface.
      *                INVALID_STATE if the stream was already closed.
      */
+    @exit
     close() generates (Result retval);
 };
diff --git a/audio/6.0/config/api/current.txt b/audio/6.0/config/api/current.txt
index e67831c..ddd4d1c 100644
--- a/audio/6.0/config/api/current.txt
+++ b/audio/6.0/config/api/current.txt
@@ -237,6 +237,7 @@
     method public audio.policy.configuration.V6_0.GainMode getMode();
     method public String getName();
     method public int getStepValueMB();
+    method public boolean getUseForVolume();
     method public void setChannel_mask(String);
     method public void setDefaultValueMB(int);
     method public void setMaxRampMs(int);
@@ -246,6 +247,7 @@
     method public void setMode(audio.policy.configuration.V6_0.GainMode);
     method public void setName(String);
     method public void setStepValueMB(int);
+    method public void setUseForVolume(boolean);
   }
 
   public class GlobalConfiguration {
diff --git a/audio/6.0/config/audio_policy_configuration.xsd b/audio/6.0/config/audio_policy_configuration.xsd
index 29f6f38..3fab7dc 100644
--- a/audio/6.0/config/audio_policy_configuration.xsd
+++ b/audio/6.0/config/audio_policy_configuration.xsd
@@ -447,6 +447,7 @@
                     <xs:attribute name="stepValueMB" type="xs:int" use="optional"/>
                     <xs:attribute name="minRampMs" type="xs:int" use="optional"/>
                     <xs:attribute name="maxRampMs" type="xs:int" use="optional"/>
+                    <xs:attribute name="useForVolume" type="xs:boolean" use="optional"/>
                 </xs:complexType>
             </xs:element>
         </xs:sequence>
diff --git a/audio/common/6.0/Android.bp b/audio/common/6.0/Android.bp
index 1a4e054..94f1cf8 100644
--- a/audio/common/6.0/Android.bp
+++ b/audio/common/6.0/Android.bp
@@ -12,6 +12,6 @@
     interfaces: [
         "android.hidl.safe_union@1.0",
     ],
-    gen_java: false,
+    gen_java: true,
     gen_java_constants: true,
 }
diff --git a/audio/common/6.0/types.hal b/audio/common/6.0/types.hal
index 0c97c36..fa2f3a9 100644
--- a/audio/common/6.0/types.hal
+++ b/audio/common/6.0/types.hal
@@ -156,6 +156,11 @@
 @export(name="audio_session_t", value_prefix="AUDIO_SESSION_")
 enum AudioSessionConsts : int32_t {
     /**
+     * Session for effects attached to a particular sink or source audio device
+     * (e.g an effect only applied to a speaker)
+     */
+    DEVICE = -2,
+    /**
      * Session for effects attached to a particular output stream
      * (value must be less than 0)
      */
diff --git a/audio/common/all-versions/test/utility/include/utility/PrettyPrintAudioTypes.h b/audio/common/all-versions/test/utility/include/utility/PrettyPrintAudioTypes.h
deleted file mode 100644
index 3833fd0..0000000
--- a/audio/common/all-versions/test/utility/include/utility/PrettyPrintAudioTypes.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2018 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_AUDIO_COMMON_TEST_UTILITY_PRETTY_PRINT_AUDIO_TYPES_H
-#define ANDROID_HARDWARE_AUDIO_COMMON_TEST_UTILITY_PRETTY_PRINT_AUDIO_TYPES_H
-
-#include <iosfwd>
-#include <utility>
-
-/** @file Use HIDL generated toString methods to pretty print gtest errors
- *        Unfortunately Gtest does not offer a template to specialize, only
- *        overloading PrintTo.
- *  @note that this overload can NOT be template because
- *        the fallback is already template, resulting in ambiguity.
- *  @note that the overload MUST be in the exact namespace
- *        the type is declared in, as per the ADL rules.
- */
-
-namespace android {
-namespace hardware {
-namespace audio {
-
-#define DEFINE_GTEST_PRINT_TO(T) \
-    inline void PrintTo(const T& val, ::std::ostream* os) { *os << toString(val); }
-
-namespace CPP_VERSION {
-DEFINE_GTEST_PRINT_TO(IPrimaryDevice::TtyMode)
-DEFINE_GTEST_PRINT_TO(Result)
-}  // namespace CPP_VERSION
-
-namespace common {
-namespace CPP_VERSION {
-DEFINE_GTEST_PRINT_TO(AudioConfig)
-DEFINE_GTEST_PRINT_TO(AudioMode)
-DEFINE_GTEST_PRINT_TO(AudioDevice)
-DEFINE_GTEST_PRINT_TO(AudioFormat)
-DEFINE_GTEST_PRINT_TO(AudioChannelMask)
-}  // namespace CPP_VERSION
-}  // namespace common
-
-#undef DEFINE_GTEST_PRINT_TO
-
-}  // namespace audio
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_AUDIO_COMMON_TEST_UTILITY_PRETTY_PRINT_AUDIO_TYPES_H
diff --git a/audio/core/all-versions/default/Conversions.cpp b/audio/core/all-versions/default/Conversions.cpp
index 11872c0..eddff55 100644
--- a/audio/core/all-versions/default/Conversions.cpp
+++ b/audio/core/all-versions/default/Conversions.cpp
@@ -19,6 +19,7 @@
 #include <stdio.h>
 
 #include <log/log.h>
+#include <media/AudioContainers.h>
 
 namespace android {
 namespace hardware {
@@ -31,26 +32,22 @@
     char halAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
     memset(halAddress, 0, sizeof(halAddress));
     uint32_t halDevice = static_cast<uint32_t>(address.device);
-    const bool isInput = (halDevice & AUDIO_DEVICE_BIT_IN) != 0;
-    if (isInput) halDevice &= ~AUDIO_DEVICE_BIT_IN;
-    if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != 0) ||
-        (isInput && (halDevice & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0)) {
+    if (getAudioDeviceOutAllA2dpSet().count(halDevice) > 0 ||
+        halDevice == AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
         snprintf(halAddress, sizeof(halAddress), "%02X:%02X:%02X:%02X:%02X:%02X",
                  address.address.mac[0], address.address.mac[1], address.address.mac[2],
                  address.address.mac[3], address.address.mac[4], address.address.mac[5]);
-    } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_IP) != 0) ||
-               (isInput && (halDevice & AUDIO_DEVICE_IN_IP) != 0)) {
+    } else if (halDevice == AUDIO_DEVICE_OUT_IP || halDevice == AUDIO_DEVICE_IN_IP) {
         snprintf(halAddress, sizeof(halAddress), "%d.%d.%d.%d", address.address.ipv4[0],
                  address.address.ipv4[1], address.address.ipv4[2], address.address.ipv4[3]);
-    } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_ALL_USB) != 0) ||
-               (isInput && (halDevice & AUDIO_DEVICE_IN_ALL_USB) != 0)) {
+    } else if (getAudioDeviceOutAllUsbSet().count(halDevice) > 0 ||
+               getAudioDeviceInAllUsbSet().count(halDevice) > 0) {
         snprintf(halAddress, sizeof(halAddress), "card=%d;device=%d", address.address.alsa.card,
                  address.address.alsa.device);
-    } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_BUS) != 0) ||
-               (isInput && (halDevice & AUDIO_DEVICE_IN_BUS) != 0)) {
+    } else if (halDevice == AUDIO_DEVICE_OUT_BUS || halDevice == AUDIO_DEVICE_IN_BUS) {
         snprintf(halAddress, sizeof(halAddress), "%s", address.busAddress.c_str());
-    } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0 ||
-               (isInput && (halDevice & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0)) {
+    } else if (halDevice == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ||
+               halDevice == AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
         snprintf(halAddress, sizeof(halAddress), "%s", address.rSubmixAddress.c_str());
     }
     return halAddress;
@@ -67,32 +64,28 @@
         return OK;
     }
 
-    const bool isInput = (device & AUDIO_DEVICE_BIT_IN) != 0;
-    if (isInput) device &= ~AUDIO_DEVICE_BIT_IN;
-    if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_A2DP) != 0) ||
-        (isInput && (device & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0)) {
+    if (getAudioDeviceOutAllA2dpSet().count(device) > 0 ||
+        device == AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
         int status =
             sscanf(halAddress, "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX", &address->address.mac[0],
                    &address->address.mac[1], &address->address.mac[2], &address->address.mac[3],
                    &address->address.mac[4], &address->address.mac[5]);
         return status == 6 ? OK : BAD_VALUE;
-    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_IP) != 0) ||
-               (isInput && (device & AUDIO_DEVICE_IN_IP) != 0)) {
+    } else if (device == AUDIO_DEVICE_OUT_IP || device == AUDIO_DEVICE_IN_IP) {
         int status =
             sscanf(halAddress, "%hhu.%hhu.%hhu.%hhu", &address->address.ipv4[0],
                    &address->address.ipv4[1], &address->address.ipv4[2], &address->address.ipv4[3]);
         return status == 4 ? OK : BAD_VALUE;
-    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_USB)) != 0 ||
-               (isInput && (device & AUDIO_DEVICE_IN_ALL_USB)) != 0) {
+    } else if (getAudioDeviceOutAllUsbSet().count(device) > 0 ||
+               getAudioDeviceInAllUsbSet().count(device) > 0) {
         int status = sscanf(halAddress, "card=%d;device=%d", &address->address.alsa.card,
                             &address->address.alsa.device);
         return status == 2 ? OK : BAD_VALUE;
-    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_BUS) != 0) ||
-               (isInput && (device & AUDIO_DEVICE_IN_BUS) != 0)) {
+    } else if (device == AUDIO_DEVICE_OUT_BUS || device == AUDIO_DEVICE_IN_BUS) {
         address->busAddress = halAddress;
         return OK;
-    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0 ||
-               (isInput && (device & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0)) {
+    } else if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ||
+               device == AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
         address->rSubmixAddress = halAddress;
         return OK;
     }
diff --git a/audio/core/all-versions/default/Device.cpp b/audio/core/all-versions/default/Device.cpp
index 1a9df21..21dab00 100644
--- a/audio/core/all-versions/default/Device.cpp
+++ b/audio/core/all-versions/default/Device.cpp
@@ -39,11 +39,10 @@
 
 using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
 
-Device::Device(audio_hw_device_t* device) : mDevice(device) {}
+Device::Device(audio_hw_device_t* device) : mIsClosed(false), mDevice(device) {}
 
 Device::~Device() {
-    int status = audio_hw_device_close(mDevice);
-    ALOGW_IF(status, "Error closing audio hw device %p: %s", mDevice, strerror(-status));
+    (void)doClose();
     mDevice = nullptr;
 }
 
@@ -54,10 +53,14 @@
 
 void Device::closeInputStream(audio_stream_in_t* stream) {
     mDevice->close_input_stream(mDevice, stream);
+    LOG_ALWAYS_FATAL_IF(mOpenedStreamsCount == 0, "mOpenedStreamsCount is already 0");
+    --mOpenedStreamsCount;
 }
 
 void Device::closeOutputStream(audio_stream_out_t* stream) {
     mDevice->close_output_stream(mDevice, stream);
+    LOG_ALWAYS_FATAL_IF(mOpenedStreamsCount == 0, "mOpenedStreamsCount is already 0");
+    --mOpenedStreamsCount;
 }
 
 char* Device::halGetParameters(const char* keys) {
@@ -159,6 +162,7 @@
     sp<IStreamOut> streamOut;
     if (status == OK) {
         streamOut = new StreamOut(this, halStream);
+        ++mOpenedStreamsCount;
     }
     HidlUtils::audioConfigFromHal(halConfig, suggestedConfig);
     return {analyzeStatus("open_output_stream", status, {EINVAL} /*ignore*/), streamOut};
@@ -185,6 +189,7 @@
     sp<IStreamIn> streamIn;
     if (status == OK) {
         streamIn = new StreamIn(this, halStream);
+        ++mOpenedStreamsCount;
     }
     HidlUtils::audioConfigFromHal(halConfig, suggestedConfig);
     return {analyzeStatus("open_input_stream", status, {EINVAL} /*ignore*/), streamIn};
@@ -383,6 +388,18 @@
 }
 #endif
 
+Result Device::doClose() {
+    if (mIsClosed || mOpenedStreamsCount != 0) return Result::INVALID_STATE;
+    mIsClosed = true;
+    return analyzeStatus("close", audio_hw_device_close(mDevice));
+}
+
+#if MAJOR_VERSION >= 6
+Return<Result> Device::close() {
+    return doClose();
+}
+#endif
+
 }  // namespace implementation
 }  // namespace CPP_VERSION
 }  // namespace audio
diff --git a/audio/core/all-versions/default/PrimaryDevice.cpp b/audio/core/all-versions/default/PrimaryDevice.cpp
index 99590b0..3cf0932 100644
--- a/audio/core/all-versions/default/PrimaryDevice.cpp
+++ b/audio/core/all-versions/default/PrimaryDevice.cpp
@@ -31,7 +31,11 @@
 
 PrimaryDevice::PrimaryDevice(audio_hw_device_t* device) : mDevice(new Device(device)) {}
 
-PrimaryDevice::~PrimaryDevice() {}
+PrimaryDevice::~PrimaryDevice() {
+    // Do not call mDevice->close here. If there are any unclosed streams,
+    // they only hold IDevice instance, not IPrimaryDevice, thus IPrimaryDevice
+    // "part" of a device can be destroyed before the streams.
+}
 
 // Methods from ::android::hardware::audio::CPP_VERSION::IDevice follow.
 Return<Result> PrimaryDevice::initCheck() {
@@ -160,6 +164,11 @@
     return mDevice->setConnectedState(address, connected);
 }
 #endif
+#if MAJOR_VERSION >= 6
+Return<Result> PrimaryDevice::close() {
+    return mDevice->close();
+}
+#endif
 
 // Methods from ::android::hardware::audio::CPP_VERSION::IPrimaryDevice follow.
 Return<Result> PrimaryDevice::setVoiceVolume(float volume) {
diff --git a/audio/core/all-versions/default/StreamIn.cpp b/audio/core/all-versions/default/StreamIn.cpp
index d316f83..f1152ca 100644
--- a/audio/core/all-versions/default/StreamIn.cpp
+++ b/audio/core/all-versions/default/StreamIn.cpp
@@ -139,8 +139,7 @@
 }  // namespace
 
 StreamIn::StreamIn(const sp<Device>& device, audio_stream_in_t* stream)
-    : mIsClosed(false),
-      mDevice(device),
+    : mDevice(device),
       mStream(stream),
       mStreamCommon(new Stream(&stream->common)),
       mStreamMmap(new StreamMmap<audio_stream_in_t>(stream)),
@@ -159,7 +158,9 @@
         status_t status = EventFlag::deleteEventFlag(&mEfGroup);
         ALOGE_IF(status, "read MQ event flag deletion error: %s", strerror(-status));
     }
+#if MAJOR_VERSION <= 5
     mDevice->closeInputStream(mStream);
+#endif
     mStream = nullptr;
 }
 
@@ -303,14 +304,16 @@
 }
 
 Return<Result> StreamIn::close() {
-    if (mIsClosed) return Result::INVALID_STATE;
-    mIsClosed = true;
-    if (mReadThread.get()) {
-        mStopReadThread.store(true, std::memory_order_release);
+    if (mStopReadThread.load(std::memory_order_relaxed)) {  // only this thread writes
+        return Result::INVALID_STATE;
     }
+    mStopReadThread.store(true, std::memory_order_release);
     if (mEfGroup) {
         mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
     }
+#if MAJOR_VERSION >= 6
+    mDevice->closeInputStream(mStream);
+#endif
     return Result::OK;
 }
 
diff --git a/audio/core/all-versions/default/StreamOut.cpp b/audio/core/all-versions/default/StreamOut.cpp
index 82cc408..396d354 100644
--- a/audio/core/all-versions/default/StreamOut.cpp
+++ b/audio/core/all-versions/default/StreamOut.cpp
@@ -138,8 +138,7 @@
 }  // namespace
 
 StreamOut::StreamOut(const sp<Device>& device, audio_stream_out_t* stream)
-    : mIsClosed(false),
-      mDevice(device),
+    : mDevice(device),
       mStream(stream),
       mStreamCommon(new Stream(&stream->common)),
       mStreamMmap(new StreamMmap<audio_stream_out_t>(stream)),
@@ -148,7 +147,7 @@
 
 StreamOut::~StreamOut() {
     ATRACE_CALL();
-    close();
+    (void)close();
     if (mWriteThread.get()) {
         ATRACE_NAME("mWriteThread->join");
         status_t status = mWriteThread->join();
@@ -159,10 +158,12 @@
         ALOGE_IF(status, "write MQ event flag deletion error: %s", strerror(-status));
     }
     mCallback.clear();
+#if MAJOR_VERSION <= 5
     mDevice->closeOutputStream(mStream);
     // Closing the output stream in the HAL waits for the callback to finish,
     // and joins the callback thread. Thus is it guaranteed that the callback
     // thread will not be accessing our object anymore.
+#endif
     mStream = nullptr;
 }
 
@@ -291,14 +292,16 @@
 #endif
 
 Return<Result> StreamOut::close() {
-    if (mIsClosed) return Result::INVALID_STATE;
-    mIsClosed = true;
-    if (mWriteThread.get()) {
-        mStopWriteThread.store(true, std::memory_order_release);
+    if (mStopWriteThread.load(std::memory_order_relaxed)) {  // only this thread writes
+        return Result::INVALID_STATE;
     }
+    mStopWriteThread.store(true, std::memory_order_release);
     if (mEfGroup) {
         mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
     }
+#if MAJOR_VERSION >= 6
+    mDevice->closeOutputStream(mStream);
+#endif
     return Result::OK;
 }
 
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 e64f00f..11ab607 100644
--- a/audio/core/all-versions/default/include/core/default/Device.h
+++ b/audio/core/all-versions/default/include/core/default/Device.h
@@ -114,6 +114,9 @@
     Return<void> getMicrophones(getMicrophones_cb _hidl_cb) override;
     Return<Result> setConnectedState(const DeviceAddress& address, bool connected) override;
 #endif
+#if MAJOR_VERSION >= 6
+    Return<Result> close() override;
+#endif
 
     Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
 
@@ -124,11 +127,15 @@
     void closeOutputStream(audio_stream_out_t* stream);
     audio_hw_device_t* device() const { return mDevice; }
 
-   private:
+  private:
+    bool mIsClosed;
     audio_hw_device_t* mDevice;
+    int mOpenedStreamsCount = 0;
 
     virtual ~Device();
 
+    Result doClose();
+
     // Methods from ParametersUtil.
     char* halGetParameters(const char* keys) override;
     int halSetParameters(const char* keysAndValues) 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 9d69cb0..f5f3848 100644
--- a/audio/core/all-versions/default/include/core/default/PrimaryDevice.h
+++ b/audio/core/all-versions/default/include/core/default/PrimaryDevice.h
@@ -96,6 +96,9 @@
     Return<void> getMicrophones(getMicrophones_cb _hidl_cb) override;
     Return<Result> setConnectedState(const DeviceAddress& address, bool connected) override;
 #endif
+#if MAJOR_VERSION >= 6
+    Return<Result> close() override;
+#endif
 
     Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
 
diff --git a/audio/core/all-versions/default/include/core/default/StreamIn.h b/audio/core/all-versions/default/include/core/default/StreamIn.h
index 6209b8f..24f9944 100644
--- a/audio/core/all-versions/default/include/core/default/StreamIn.h
+++ b/audio/core/all-versions/default/include/core/default/StreamIn.h
@@ -120,7 +120,6 @@
                                          uint64_t* time);
 
    private:
-    bool mIsClosed;
     const sp<Device> mDevice;
     audio_stream_in_t* mStream;
     const sp<Stream> mStreamCommon;
diff --git a/audio/core/all-versions/default/include/core/default/StreamOut.h b/audio/core/all-versions/default/include/core/default/StreamOut.h
index b098005..6334785 100644
--- a/audio/core/all-versions/default/include/core/default/StreamOut.h
+++ b/audio/core/all-versions/default/include/core/default/StreamOut.h
@@ -126,7 +126,6 @@
                                               TimeSpec* timeStamp);
 
    private:
-    bool mIsClosed;
     const sp<Device> mDevice;
     audio_stream_out_t* mStream;
     const sp<Stream> mStreamCommon;
diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
index e267a5e..709b7cd 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
@@ -22,18 +22,16 @@
         GTEST_SKIP() << "No primary device on this factory";  // returns
     }
 
-    struct WaitExecutor {
-        ~WaitExecutor() { DeviceManager::waitForInstanceDestruction(); }
-    } waitExecutor;  // Make sure we wait for the device destruction on exiting from the test.
-    Result result;
-    sp<IDevice> baseDevice;
-    ASSERT_OK(getDevicesFactory()->openDevice("primary", returnIn(result, baseDevice)));
-    ASSERT_OK(result);
-    ASSERT_TRUE(baseDevice != nullptr);
-
-    Return<sp<IPrimaryDevice>> primaryDevice = IPrimaryDevice::castFrom(baseDevice);
-    ASSERT_TRUE(primaryDevice.isOk());
-    ASSERT_TRUE(sp<IPrimaryDevice>(primaryDevice) != nullptr);
+    {  // Scope for device SPs
+        sp<IDevice> baseDevice =
+                DeviceManager::getInstance().get(getFactoryName(), DeviceManager::kPrimaryDevice);
+        ASSERT_TRUE(baseDevice != nullptr);
+        Return<sp<IPrimaryDevice>> primaryDevice = IPrimaryDevice::castFrom(baseDevice);
+        EXPECT_TRUE(primaryDevice.isOk());
+        EXPECT_TRUE(sp<IPrimaryDevice>(primaryDevice) != nullptr);
+    }
+    EXPECT_TRUE(
+            DeviceManager::getInstance().reset(getFactoryName(), DeviceManager::kPrimaryDevice));
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -54,7 +52,6 @@
         doc::test(
             "Make sure getMicrophones always succeeds"
             "and getActiveMicrophones always succeeds when recording from these microphones.");
-        AudioIoHandle ioHandle = (AudioIoHandle)AudioHandleConsts::AUDIO_IO_HANDLE_NONE;
         AudioConfig config{};
         config.channelMask = mkEnumBitfield(AudioChannelMask::IN_MONO);
         config.sampleRateHz = 8000;
@@ -67,18 +64,14 @@
                 continue;
             }
             sp<IStreamIn> stream;
+            StreamHelper<IStreamIn> helper(stream);
             AudioConfig suggestedConfig{};
-            ASSERT_OK(getDevice()->openInputStream(ioHandle, microphone.deviceAddress, config,
-                                                   flags, initMetadata,
-                                                   returnIn(res, stream, suggestedConfig)));
-            if (res != Result::OK) {
-                ASSERT_TRUE(stream == nullptr);
-                AudioConfig suggestedConfigRetry{};
-                ASSERT_OK(getDevice()->openInputStream(
-                        ioHandle, microphone.deviceAddress, suggestedConfig, flags, initMetadata,
-                        returnIn(res, stream, suggestedConfigRetry)));
-            }
-            ASSERT_OK(res);
+            ASSERT_NO_FATAL_FAILURE(helper.open(
+                    [&](AudioIoHandle handle, AudioConfig config, auto cb) {
+                        return getDevice()->openInputStream(handle, microphone.deviceAddress,
+                                                            config, flags, initMetadata, cb);
+                    },
+                    config, &res, &suggestedConfig));
             hidl_vec<MicrophoneInfo> activeMicrophones;
             Result readRes;
             typedef MessageQueue<IStreamIn::ReadParameters, kSynchronizedReadWrite> CommandMQ;
@@ -112,11 +105,8 @@
                 ASSERT_OK(res);
                 ASSERT_NE(0U, activeMicrophones.size());
             }
-            stream->close();
-            // Workaround for b/139329877. Ensures the stream gets closed on the audio hal side.
-            stream.clear();
-            IPCThreadState::self()->flushCommands();
-            usleep(1000);
+            helper.close(true /*clear*/, &res);
+            ASSERT_OK(res);
             if (efGroup) {
                 EventFlag::deleteEventFlag(&efGroup);
             }
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 30f8a7a..2afbbb8 100644
--- a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
@@ -83,7 +83,6 @@
                     for (auto& config : configs) {
                         // Some combinations of flags declared in the config file require special
                         // treatment.
-                        bool special = false;
                         if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
                             config.offloadInfo.sampleRateHz = config.sampleRateHz;
                             config.offloadInfo.channelMask = config.channelMask;
@@ -94,21 +93,13 @@
                             config.offloadInfo.bitWidth = 16;
                             config.offloadInfo.bufferSize = 256;  // arbitrary value
                             config.offloadInfo.usage = AudioUsage::MEDIA;
-                            result.emplace_back(
-                                    device, config,
-                                    AudioOutputFlag(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD));
-                            special = true;
-                        }
-                        if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
-                            !(flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
                             result.emplace_back(device, config,
-                                                AudioOutputFlag(AUDIO_OUTPUT_FLAG_DIRECT));
-                            special = true;
-                        }
-                        if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {  // ignore the flag
-                            flags &= ~AUDIO_OUTPUT_FLAG_PRIMARY;
-                        }
-                        if (!special) {
+                                                AudioOutputFlag(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD |
+                                                                AUDIO_OUTPUT_FLAG_DIRECT));
+                        } else {
+                            if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {  // ignore the flag
+                                flags &= ~AUDIO_OUTPUT_FLAG_PRIMARY;
+                            }
                             result.emplace_back(device, config, AudioOutputFlag(flags));
                         }
                     }
@@ -144,3 +135,49 @@
     }();
     return parameters;
 }
+
+TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedOutputStreams) {
+    doc::test("Verify that a device can't be closed if there are streams opened");
+    DeviceAddress address{.device = AudioDevice::OUT_DEFAULT};
+    AudioConfig config{};
+    auto flags = hidl_bitfield<AudioOutputFlag>(AudioOutputFlag::NONE);
+    SourceMetadata initMetadata = {{{AudioUsage::MEDIA, AudioContentType::MUSIC, 1 /* gain */}}};
+    sp<IStreamOut> stream;
+    StreamHelper<IStreamOut> helper(stream);
+    AudioConfig suggestedConfig{};
+    ASSERT_NO_FATAL_FAILURE(helper.open(
+            [&](AudioIoHandle handle, AudioConfig config, auto cb) {
+                return getDevice()->openOutputStream(handle, address, config, flags, initMetadata,
+                                                     cb);
+            },
+            config, &res, &suggestedConfig));
+    ASSERT_RESULT(Result::INVALID_STATE, getDevice()->close());
+    ASSERT_NO_FATAL_FAILURE(helper.close(true /*clear*/, &res));
+    ASSERT_OK(getDevice()->close());
+    ASSERT_TRUE(resetDevice());
+}
+
+TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedInputStreams) {
+    doc::test("Verify that a device can't be closed if there are streams opened");
+    auto module = getCachedPolicyConfig().getModuleFromName(getDeviceName());
+    if (module->getInputProfiles().empty()) {
+        GTEST_SKIP() << "Device doesn't have input profiles";
+    }
+    DeviceAddress address{.device = AudioDevice::IN_DEFAULT};
+    AudioConfig config{};
+    auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE);
+    SinkMetadata initMetadata = {{{.source = AudioSource::MIC, .gain = 1}}};
+    sp<IStreamIn> stream;
+    StreamHelper<IStreamIn> helper(stream);
+    AudioConfig suggestedConfig{};
+    ASSERT_NO_FATAL_FAILURE(helper.open(
+            [&](AudioIoHandle handle, AudioConfig config, auto cb) {
+                return getDevice()->openInputStream(handle, address, config, flags, initMetadata,
+                                                    cb);
+            },
+            config, &res, &suggestedConfig));
+    ASSERT_RESULT(Result::INVALID_STATE, getDevice()->close());
+    ASSERT_NO_FATAL_FAILURE(helper.close(true /*clear*/, &res));
+    ASSERT_OK(getDevice()->close());
+    ASSERT_TRUE(resetDevice());
+}
diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index 468f9b2..d0d39e8 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -58,7 +58,6 @@
 
 #include "utility/AssertOk.h"
 #include "utility/Documentation.h"
-#include "utility/PrettyPrintAudioTypes.h"
 #include "utility/ReturnIn.h"
 #include "utility/ValidateXml.h"
 
@@ -719,12 +718,6 @@
                 ::testing::Values(AudioInputFlag::NONE)),
         &DeviceConfigParameterToString);
 INSTANTIATE_TEST_CASE_P(
-        SupportedInputBufferSize, RequiredInputBufferSizeTest,
-        ::testing::Combine(::testing::ValuesIn(getDeviceParameters()),
-                           ::testing::ValuesIn(ConfigHelper::getSupportedCaptureAudioConfig()),
-                           ::testing::Values(AudioInputFlag::NONE)),
-        &DeviceConfigParameterToString);
-INSTANTIATE_TEST_CASE_P(
         RecommendedCaptureAudioConfigSupport, OptionalInputBufferSizeTest,
         ::testing::Combine(
                 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
@@ -816,60 +809,84 @@
 ////////////////////////// open{Output,Input}Stream //////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
+// This class is also used by some device tests.
 template <class Stream>
-class OpenStreamTest : public AudioHidlTestWithDeviceConfigParameter {
-  protected:
+class StreamHelper {
+  public:
+    // StreamHelper doesn't own the stream, this is for simpler stream lifetime management.
+    explicit StreamHelper(sp<Stream>& stream) : mStream(stream) {}
     template <class Open>
-    void testOpen(Open openStream, const AudioConfig& config) {
+    void open(Open openStream, const AudioConfig& config, Result* res,
+              AudioConfig* suggestedConfigPtr) {
         // FIXME: Open a stream without an IOHandle
         //        This is not required to be accepted by hal implementations
         AudioIoHandle ioHandle = (AudioIoHandle)AudioHandleConsts::AUDIO_IO_HANDLE_NONE;
         AudioConfig suggestedConfig{};
-        ASSERT_OK(openStream(ioHandle, config, returnIn(res, stream, suggestedConfig)));
-
-        // TODO: only allow failure for RecommendedPlaybackAudioConfig
-        switch (res) {
+        bool retryWithSuggestedConfig = true;
+        if (suggestedConfigPtr == nullptr) {
+            suggestedConfigPtr = &suggestedConfig;
+            retryWithSuggestedConfig = false;
+        }
+        ASSERT_OK(openStream(ioHandle, config, returnIn(*res, mStream, *suggestedConfigPtr)));
+        switch (*res) {
             case Result::OK:
-                ASSERT_TRUE(stream != nullptr);
-                audioConfig = config;
+                ASSERT_TRUE(mStream != nullptr);
+                *suggestedConfigPtr = config;
                 break;
             case Result::INVALID_ARGUMENTS:
-                ASSERT_TRUE(stream == nullptr);
-                AudioConfig suggestedConfigRetry;
-                // Could not open stream with config, try again with the
-                // suggested one
-                ASSERT_OK(openStream(ioHandle, suggestedConfig,
-                                     returnIn(res, stream, suggestedConfigRetry)));
-                // This time it must succeed
-                ASSERT_OK(res);
-                ASSERT_TRUE(stream != nullptr);
-                audioConfig = suggestedConfig;
+                ASSERT_TRUE(mStream == nullptr);
+                if (retryWithSuggestedConfig) {
+                    AudioConfig suggestedConfigRetry;
+                    ASSERT_OK(openStream(ioHandle, *suggestedConfigPtr,
+                                         returnIn(*res, mStream, suggestedConfigRetry)));
+                    ASSERT_OK(*res);
+                    ASSERT_TRUE(mStream != nullptr);
+                }
                 break;
             default:
-                FAIL() << "Invalid return status: " << ::testing::PrintToString(res);
+                FAIL() << "Invalid return status: " << ::testing::PrintToString(*res);
         }
+    }
+    void close(bool clear, Result* res) {
+        auto ret = mStream->close();
+        EXPECT_TRUE(ret.isOk());
+        *res = ret;
+        if (clear) {
+            mStream.clear();
+#if MAJOR_VERSION <= 5
+            // FIXME: there is no way to know when the remote IStream is being destroyed
+            //        Binder does not support testing if an object is alive, thus
+            //        wait for 100ms to let the binder destruction propagates and
+            //        the remote device has the time to be destroyed.
+            //        flushCommand makes sure all local command are sent, thus should reduce
+            //        the latency between local and remote destruction.
+            IPCThreadState::self()->flushCommands();
+            usleep(100 * 1000);
+#endif
+        }
+    }
+
+  private:
+    sp<Stream>& mStream;
+};
+
+template <class Stream>
+class OpenStreamTest : public AudioHidlTestWithDeviceConfigParameter {
+  protected:
+    OpenStreamTest() : AudioHidlTestWithDeviceConfigParameter(), helper(stream) {}
+    template <class Open>
+    void testOpen(Open openStream, const AudioConfig& config) {
+        // TODO: only allow failure for RecommendedPlaybackAudioConfig
+        ASSERT_NO_FATAL_FAILURE(helper.open(openStream, config, &res, &audioConfig));
         open = true;
     }
 
-    Return<Result> closeStream() {
+    Result closeStream(bool clear = true) {
         open = false;
-        auto res = stream->close();
-        stream.clear();
-        waitForStreamDestruction();
+        helper.close(clear, &res);
         return res;
     }
 
-    static void waitForStreamDestruction() {
-        // FIXME: there is no way to know when the remote IStream is being destroyed
-        //        Binder does not support testing if an object is alive, thus
-        //        wait for 100ms to let the binder destruction propagates and
-        //        the remote device has the time to be destroyed.
-        //        flushCommand makes sure all local command are sent, thus should reduce
-        //        the latency between local and remote destruction.
-        IPCThreadState::self()->flushCommands();
-        usleep(100 * 1000);
-    }
-
   private:
     void TearDown() override {
         if (open) {
@@ -882,6 +899,7 @@
     AudioConfig audioConfig;
     DeviceAddress address = {};
     sp<Stream> stream;
+    StreamHelper<Stream> helper;
     bool open = false;
 };
 
@@ -930,12 +948,6 @@
                 ::testing::Values(AudioOutputFlag::NONE)),
         &DeviceConfigParameterToString);
 INSTANTIATE_TEST_CASE_P(
-        SupportedOutputStreamConfig, OutputStreamTest,
-        ::testing::Combine(::testing::ValuesIn(getDeviceParameters()),
-                           ::testing::ValuesIn(ConfigHelper::getSupportedPlaybackAudioConfig()),
-                           ::testing::Values(AudioOutputFlag::NONE)),
-        &DeviceConfigParameterToString);
-INSTANTIATE_TEST_CASE_P(
         RecommendedOutputStreamConfigSupport, OutputStreamTest,
         ::testing::Combine(
                 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
@@ -945,7 +957,7 @@
 #elif MAJOR_VERSION >= 6
 // For V6 and above test according to the audio policy manager configuration.
 // This is more correct as CDD is written from the apps perspective.
-// Audio system provides necessary format conversions for the missing configurations.
+// Audio system provides necessary format conversions for missing configurations.
 INSTANTIATE_TEST_CASE_P(DeclaredOutputStreamConfigSupport, OutputStreamTest,
                         ::testing::ValuesIn(getOutputDeviceConfigParameters()),
                         &DeviceConfigParameterToString);
@@ -991,12 +1003,6 @@
                 ::testing::Values(AudioInputFlag::NONE)),
         &DeviceConfigParameterToString);
 INSTANTIATE_TEST_CASE_P(
-        SupportedInputStreamConfig, InputStreamTest,
-        ::testing::Combine(::testing::ValuesIn(getDeviceParameters()),
-                           ::testing::ValuesIn(ConfigHelper::getSupportedCaptureAudioConfig()),
-                           ::testing::Values(AudioInputFlag::NONE)),
-        &DeviceConfigParameterToString);
-INSTANTIATE_TEST_CASE_P(
         RecommendedInputStreamConfigSupport, InputStreamTest,
         ::testing::Combine(
                 ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
@@ -1006,7 +1012,7 @@
 #elif MAJOR_VERSION >= 6
 // For V6 and above test according to the audio policy manager configuration.
 // This is more correct as CDD is written from the apps perspective.
-// Audio system provides necessary format conversions for the missing configurations.
+// Audio system provides necessary format conversions for missing configurations.
 INSTANTIATE_TEST_CASE_P(DeclaredInputStreamConfigSupport, InputStreamTest,
                         ::testing::ValuesIn(getInputDeviceConfigParameters()),
                         &DeviceConfigParameterToString);
@@ -1195,26 +1201,21 @@
 TEST_IO_STREAM(close, "Make sure a stream can be closed", ASSERT_OK(closeStream()))
 // clang-format off
 TEST_IO_STREAM(closeTwice, "Make sure a stream can not be closed twice",
-        auto streamCopy = stream;
-        ASSERT_OK(closeStream());
-        ASSERT_RESULT(Result::INVALID_STATE, streamCopy->close());
-        streamCopy.clear();
-        waitForStreamDestruction())
+        ASSERT_OK(closeStream(false /*clear*/));
+        ASSERT_EQ(Result::INVALID_STATE, closeStream()))
 // clang-format on
 
-static void testCreateTooBigMmapBuffer(IStream* stream) {
-    MmapBufferInfo info;
-    Result res;
-    // Assume that int max is a value too big to be allocated
-    // This is true currently with a 32bit media server, but might not when it
-    // will run in 64 bit
-    auto minSizeFrames = std::numeric_limits<int32_t>::max();
-    ASSERT_OK(stream->createMmapBuffer(minSizeFrames, returnIn(res, info)));
-    ASSERT_RESULT(invalidArgsOrNotSupported, res);
+static void testMmapBufferOfInvalidSize(IStream* stream) {
+    for (int32_t value : {-1, 0, std::numeric_limits<int32_t>::max()}) {
+        MmapBufferInfo info;
+        Result res;
+        EXPECT_OK(stream->createMmapBuffer(value, returnIn(res, info)));
+        EXPECT_RESULT(invalidArgsOrNotSupported, res) << "value=" << value;
+    }
 }
 
-TEST_IO_STREAM(CreateTooBigMmapBuffer, "Create mmap buffer too big should fail",
-               testCreateTooBigMmapBuffer(stream.get()))
+TEST_IO_STREAM(CreateTooBigMmapBuffer, "Create mmap buffer of invalid size must fail",
+               testMmapBufferOfInvalidSize(stream.get()))
 
 static void testGetMmapPositionOfNonMmapedStream(IStream* stream) {
     Result res;
diff --git a/audio/core/all-versions/vts/functional/ConfigHelper.h b/audio/core/all-versions/vts/functional/ConfigHelper.h
index 48aae8c..a2f4116 100644
--- a/audio/core/all-versions/vts/functional/ConfigHelper.h
+++ b/audio/core/all-versions/vts/functional/ConfigHelper.h
@@ -57,12 +57,6 @@
                                   {24000, 48000}, {AudioFormat::PCM_16_BIT});
     }
 
-    static const vector<AudioConfig> getSupportedPlaybackAudioConfig() {
-        // TODO: retrieve audio config supported by the platform
-        // as declared in the policy configuration
-        return {};
-    }
-
     static const vector<AudioConfig> getRequiredSupportCaptureAudioConfig() {
         if (!primaryHasMic()) return {};
         return combineAudioConfig({AudioChannelMask::IN_MONO}, {8000, 11025, 16000, 44100},
@@ -73,11 +67,6 @@
         return combineAudioConfig({AudioChannelMask::IN_STEREO}, {22050, 48000},
                                   {AudioFormat::PCM_16_BIT});
     }
-    static const vector<AudioConfig> getSupportedCaptureAudioConfig() {
-        // TODO: retrieve audio config supported by the platform
-        // as declared in the policy configuration
-        return {};
-    }
 
     static vector<AudioConfig> combineAudioConfig(vector<audio_channel_mask_t> channelMasks,
                                                   vector<uint32_t> sampleRates,
diff --git a/audio/core/all-versions/vts/functional/DeviceManager.h b/audio/core/all-versions/vts/functional/DeviceManager.h
index b6e2db0..d849f85 100644
--- a/audio/core/all-versions/vts/functional/DeviceManager.h
+++ b/audio/core/all-versions/vts/functional/DeviceManager.h
@@ -22,25 +22,33 @@
 template <class Derived, class Key, class Interface>
 class InterfaceManager {
   public:
+    sp<Interface> getExisting(const Key& name) {
+        auto existing = instances.find(name);
+        return existing != instances.end() ? existing->second : sp<Interface>();
+    }
+
     sp<Interface> get(const Key& name) {
         auto existing = instances.find(name);
         if (existing != instances.end()) return existing->second;
         auto [inserted, _] = instances.emplace(name, Derived::createInterfaceInstance(name));
         if (inserted->second) {
-            environment->registerTearDown([name]() { (void)Derived::getInstance().reset(name); });
+            environment->registerTearDown(
+                    [name]() { (void)Derived::getInstance().reset(name, false); });
         }
         return inserted->second;
     }
 
     // The test must check that reset was successful. Reset failure means that the test code
     // is holding a strong reference to the device.
-    bool reset(const Key& name) __attribute__((warn_unused_result)) {
+    bool reset(const Key& name, bool waitForDestruction) __attribute__((warn_unused_result)) {
         auto iter = instances.find(name);
         if (iter == instances.end()) return true;
         ::android::wp<Interface> weak = iter->second;
         instances.erase(iter);
         if (weak.promote() != nullptr) return false;
-        waitForInstanceDestruction();
+        if (waitForDestruction) {
+            waitForInstanceDestruction();
+        }
         return true;
     }
 
@@ -100,7 +108,15 @@
     }
     bool reset(const std::string& factoryName, const std::string& name)
             __attribute__((warn_unused_result)) {
-        return InterfaceManager::reset(std::make_tuple(factoryName, name));
+#if MAJOR_VERSION <= 5
+        return InterfaceManager::reset(std::make_tuple(factoryName, name), true);
+#elif MAJOR_VERSION >= 6
+        {
+            sp<IDevice> device = getExisting(std::make_tuple(factoryName, name));
+            if (device != nullptr) device->close();
+        }
+        return InterfaceManager::reset(std::make_tuple(factoryName, name), false);
+#endif
     }
     bool resetPrimary(const std::string& factoryName) __attribute__((warn_unused_result)) {
         return reset(factoryName, kPrimaryDevice);
diff --git a/audio/effect/6.0/IEffect.hal b/audio/effect/6.0/IEffect.hal
index b35afee..f4c50a2 100644
--- a/audio/effect/6.0/IEffect.hal
+++ b/audio/effect/6.0/IEffect.hal
@@ -407,9 +407,12 @@
 
     /**
      * Called by the framework to deinitialize the effect and free up
-     * all the currently allocated resources. It is recommended to close
+     * all currently allocated resources. It is recommended to close
      * the effect on the client side as soon as it is becomes unused.
      *
+     * The client must ensure that this function is not called while
+     * audio data is being transferred through the effect's message queues.
+     *
      * @return retval OK in case the success.
      *                INVALID_STATE if the effect was already closed.
      */
diff --git a/audio/effect/all-versions/default/Effect.cpp b/audio/effect/all-versions/default/Effect.cpp
index 3c0d878..406a571 100644
--- a/audio/effect/all-versions/default/Effect.cpp
+++ b/audio/effect/all-versions/default/Effect.cpp
@@ -138,11 +138,11 @@
 const char* Effect::sContextCallFunction = sContextCallToCommand;
 
 Effect::Effect(effect_handle_t handle)
-    : mIsClosed(false), mHandle(handle), mEfGroup(nullptr), mStopProcessThread(false) {}
+    : mHandle(handle), mEfGroup(nullptr), mStopProcessThread(false) {}
 
 Effect::~Effect() {
     ATRACE_CALL();
-    close();
+    (void)close();
     if (mProcessThread.get()) {
         ATRACE_NAME("mProcessThread->join");
         status_t status = mProcessThread->join();
@@ -154,8 +154,10 @@
     }
     mInBuffer.clear();
     mOutBuffer.clear();
+#if MAJOR_VERSION <= 5
     int status = EffectRelease(mHandle);
     ALOGW_IF(status, "Error releasing effect %p: %s", mHandle, strerror(-status));
+#endif
     EffectMap::getInstance().remove(mHandle);
     mHandle = 0;
 }
@@ -305,12 +307,11 @@
 Result Effect::getCurrentConfigImpl(uint32_t featureId, uint32_t configSize,
                                     GetCurrentConfigSuccessCallback onSuccess) {
     uint32_t halCmd = featureId;
-    uint32_t halResult[alignedSizeIn<uint32_t>(sizeof(uint32_t) + configSize)];
-    memset(halResult, 0, sizeof(halResult));
+    std::vector<uint32_t> halResult(alignedSizeIn<uint32_t>(sizeof(uint32_t) + configSize), 0);
     uint32_t halResultSize = 0;
-    return sendCommandReturningStatusAndData(EFFECT_CMD_GET_FEATURE_CONFIG, "GET_FEATURE_CONFIG",
-                                             sizeof(uint32_t), &halCmd, &halResultSize, halResult,
-                                             sizeof(uint32_t), [&] { onSuccess(&halResult[1]); });
+    return sendCommandReturningStatusAndData(
+            EFFECT_CMD_GET_FEATURE_CONFIG, "GET_FEATURE_CONFIG", sizeof(uint32_t), &halCmd,
+            &halResultSize, &halResult[0], sizeof(uint32_t), [&] { onSuccess(&halResult[1]); });
 }
 
 Result Effect::getParameterImpl(uint32_t paramSize, const void* paramData,
@@ -337,8 +338,7 @@
                                        GetSupportedConfigsSuccessCallback onSuccess) {
     uint32_t halCmd[2] = {featureId, maxConfigs};
     uint32_t halResultSize = 2 * sizeof(uint32_t) + maxConfigs * sizeof(configSize);
-    uint8_t halResult[halResultSize];
-    memset(&halResult[0], 0, halResultSize);
+    std::vector<uint8_t> halResult(static_cast<size_t>(halResultSize), 0);
     return sendCommandReturningStatusAndData(
         EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS, "GET_FEATURE_SUPPORTED_CONFIGS", sizeof(halCmd),
         halCmd, &halResultSize, &halResult[0], 2 * sizeof(uint32_t), [&] {
@@ -517,9 +517,9 @@
     uint32_t halDataSize;
     std::unique_ptr<uint8_t[]> halData = hidlVecToHal(volumes, &halDataSize);
     uint32_t halResultSize = halDataSize;
-    uint32_t halResult[volumes.size()];
+    std::vector<uint32_t> halResult(volumes.size(), 0);
     Result retval = sendCommandReturningData(EFFECT_CMD_SET_VOLUME, "SET_VOLUME", halDataSize,
-                                             &halData[0], &halResultSize, halResult);
+                                             &halData[0], &halResultSize, &halResult[0]);
     hidl_vec<uint32_t> result;
     if (retval == Result::OK) {
         result.setToExternal(&halResult[0], halResultSize);
@@ -579,8 +579,6 @@
 }
 
 Return<void> Effect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
-    uint32_t halResult[alignedSizeIn<uint32_t>(sizeof(uint32_t) + sizeof(channel_config_t))];
-    memset(halResult, 0, sizeof(halResult));
     EffectAuxChannelsConfig result;
     Result retval = getCurrentConfigImpl(
         EFFECT_FEATURE_AUX_CHANNELS, sizeof(channel_config_t), [&](void* configData) {
@@ -592,11 +590,12 @@
 }
 
 Return<Result> Effect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config) {
-    uint32_t halCmd[alignedSizeIn<uint32_t>(sizeof(uint32_t) + sizeof(channel_config_t))];
+    std::vector<uint32_t> halCmd(
+            alignedSizeIn<uint32_t>(sizeof(uint32_t) + sizeof(channel_config_t)), 0);
     halCmd[0] = EFFECT_FEATURE_AUX_CHANNELS;
     effectAuxChannelsConfigToHal(config, reinterpret_cast<channel_config_t*>(&halCmd[1]));
     return sendCommandReturningStatus(EFFECT_CMD_SET_FEATURE_CONFIG,
-                                      "SET_FEATURE_CONFIG AUX_CHANNELS", sizeof(halCmd), halCmd);
+                                      "SET_FEATURE_CONFIG AUX_CHANNELS", halCmd.size(), &halCmd[0]);
 }
 
 Return<Result> Effect::setAudioSource(AudioSource source) {
@@ -690,24 +689,31 @@
 
 Return<Result> Effect::setCurrentConfigForFeature(uint32_t featureId,
                                                   const hidl_vec<uint8_t>& configData) {
-    uint32_t halCmd[alignedSizeIn<uint32_t>(sizeof(uint32_t) + configData.size())];
-    memset(halCmd, 0, sizeof(halCmd));
+    std::vector<uint32_t> halCmd(alignedSizeIn<uint32_t>(sizeof(uint32_t) + configData.size()), 0);
     halCmd[0] = featureId;
     memcpy(&halCmd[1], &configData[0], configData.size());
     return sendCommandReturningStatus(EFFECT_CMD_SET_FEATURE_CONFIG, "SET_FEATURE_CONFIG",
-                                      sizeof(halCmd), halCmd);
+                                      halCmd.size(), &halCmd[0]);
 }
 
 Return<Result> Effect::close() {
-    if (mIsClosed) return Result::INVALID_STATE;
-    mIsClosed = true;
-    if (mProcessThread.get()) {
-        mStopProcessThread.store(true, std::memory_order_release);
+    if (mStopProcessThread.load(std::memory_order_relaxed)) {  // only this thread modifies
+        return Result::INVALID_STATE;
     }
+    mStopProcessThread.store(true, std::memory_order_release);
     if (mEfGroup) {
         mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_QUIT));
     }
+#if MAJOR_VERSION <= 5
     return Result::OK;
+#elif MAJOR_VERSION >= 6
+    // No need to join the processing thread, it is part of the API contract that the client
+    // must finish processing before closing the effect.
+    Result retval =
+            analyzeStatus("EffectRelease", "", sContextCallFunction, EffectRelease(mHandle));
+    EffectMap::getInstance().remove(mHandle);
+    return retval;
+#endif
 }
 
 Return<void> Effect::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
diff --git a/audio/effect/all-versions/default/Effect.h b/audio/effect/all-versions/default/Effect.h
index 3d99a0e..181e542 100644
--- a/audio/effect/all-versions/default/Effect.h
+++ b/audio/effect/all-versions/default/Effect.h
@@ -170,7 +170,6 @@
     static const char* sContextCallToCommand;
     static const char* sContextCallFunction;
 
-    bool mIsClosed;
     effect_handle_t mHandle;
     sp<AudioBufferWrapper> mInBuffer;
     sp<AudioBufferWrapper> mOutBuffer;
diff --git a/automotive/audiocontrol/1.0/default/Android.bp b/automotive/audiocontrol/1.0/default/Android.bp
index 314830b..3d04c89 100644
--- a/automotive/audiocontrol/1.0/default/Android.bp
+++ b/automotive/audiocontrol/1.0/default/Android.bp
@@ -29,7 +29,7 @@
         "liblog",
         "libutils",
     ],
-
+    vintf_fragments: ["audiocontrol_manifest.xml"],
     cflags: [
         "-DLOG_TAG=\"AudCntrlDrv\"",
         "-O0",
diff --git a/automotive/audiocontrol/1.0/default/audiocontrol_manifest.xml b/automotive/audiocontrol/1.0/default/audiocontrol_manifest.xml
new file mode 100644
index 0000000..0981eb7
--- /dev/null
+++ b/automotive/audiocontrol/1.0/default/audiocontrol_manifest.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.automotive.audiocontrol</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IAudioControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
\ No newline at end of file
diff --git a/automotive/can/1.0/default/service.cpp b/automotive/can/1.0/default/service.cpp
index 7ef44fc..ebc2f8c 100644
--- a/automotive/can/1.0/default/service.cpp
+++ b/automotive/can/1.0/default/service.cpp
@@ -32,8 +32,8 @@
     configureRpcThreadpool(16, true);
     LOG(DEBUG) << "CAN controller service starting...";
 
-    CanController canController;
-    if (canController.registerAsService("socketcan") != OK) {
+    sp<CanController> canController(new CanController);
+    if (canController->registerAsService("socketcan") != OK) {
         LOG(FATAL) << "Failed to register CAN controller";
         return;
     }
diff --git a/automotive/occupant_awareness/aidl/Android.bp b/automotive/occupant_awareness/aidl/Android.bp
new file mode 100644
index 0000000..6e9e8aa
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/Android.bp
@@ -0,0 +1,13 @@
+aidl_interface {
+    name: "android.hardware.automotive.occupant_awareness",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/automotive/occupant_awareness/*.aidl",
+    ],
+    stability: "vintf",
+    backend: {
+        java: {
+            enabled: false,
+        },
+    }
+}
diff --git a/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/ConfidenceLevel.aidl b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/ConfidenceLevel.aidl
new file mode 100644
index 0000000..8597ddb
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/ConfidenceLevel.aidl
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+package android.hardware.automotive.occupant_awareness;
+
+@VintfStability
+@Backing(type="byte")
+enum ConfidenceLevel {
+    /**
+     * No prediction could be made.
+     */
+    NONE,
+    /**
+     * Best-guess, low-confidence prediction. Predictions exceeding this threshold are adequate
+     * for non-critical applications.
+     */
+    LOW,
+    /**
+     * High-confidence prediction. Predictions exceeding this threshold are adequate for
+     * applications that require reliable predictions.
+     */
+    HIGH,
+    /**
+     * Highest confidence rate achievable.
+     */
+    MAX,
+}
diff --git a/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/DriverMonitoringDetection.aidl b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/DriverMonitoringDetection.aidl
new file mode 100644
index 0000000..f5cc9d5
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/DriverMonitoringDetection.aidl
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package android.hardware.automotive.occupant_awareness;
+
+import android.hardware.automotive.occupant_awareness.ConfidenceLevel;
+
+@VintfStability
+parcelable DriverMonitoringDetection {
+    /*
+     * Confidence of the computed attention data.
+     */
+    ConfidenceLevel confidenceScore;
+    /*
+     * Is the driver currently looking on-road?
+     */
+    boolean isLookingOnRoad;
+    /*
+     * Duration the driver has been looking on or off road, in milliseconds.
+     */
+    long gazeDurationMillis;
+}
+
diff --git a/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/GazeDetection.aidl b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/GazeDetection.aidl
new file mode 100644
index 0000000..fc36e13
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/GazeDetection.aidl
@@ -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.
+ */
+
+package android.hardware.automotive.occupant_awareness;
+
+import android.hardware.automotive.occupant_awareness.VehicleRegion;
+import android.hardware.automotive.occupant_awareness.ConfidenceLevel;
+
+@VintfStability
+parcelable GazeDetection {
+    /*
+     * Confidence level for the gaze detection.
+     */
+    ConfidenceLevel gazeConfidence;
+    /*
+     * Head position, in millimeters. The vehicle coordinate system is specified in the cabin space
+     * configuration. headPosition is double[3] array.
+     */
+    double[] headPosition;
+    /*
+     * Unit vector for the head pose direction. The vehicle coordinate system is specified in the
+     * cabin space configuration. headAngleUnitVector is double[3] array.
+     */
+    double[] headAngleUnitVector;
+    /*
+     * Unit vector for the gaze direction. The vehicle coordinate system is specified in the cabin
+     * space configuration. gazeAngleUnitVector is double[3] array.
+     */
+    double[] gazeAngleUnitVector;
+    /*
+     * Current gaze target.
+     */
+    VehicleRegion gazeTarget;
+    /*
+     * Custom gaze target string. This only need to be populated when gazeTarget is CUSTOM_TARGET.
+     * Vendors should use "com.vendor_name.target_name" format to avoid name collision with other
+     * vendors.
+     */
+    String customGazeTarget;
+    /*
+     * Duration that the subject has been looking at the current gaze target in milliseconds.
+     */
+    long timeOnTargetMillis;
+}
diff --git a/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/IOccupantAwareness.aidl b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/IOccupantAwareness.aidl
new file mode 100644
index 0000000..1df0bda
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/IOccupantAwareness.aidl
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+package android.hardware.automotive.occupant_awareness;
+
+import android.hardware.automotive.occupant_awareness.OccupantAwarenessStatus;
+import android.hardware.automotive.occupant_awareness.Role;
+import android.hardware.automotive.occupant_awareness.IOccupantAwarenessClientCallback;
+import android.hardware.automotive.occupant_awareness.OccupantDetections;
+
+@VintfStability
+interface IOccupantAwareness {
+    /*
+     * System not able to generate any occupancy awareness.
+     */
+    const int CAP_NONE = 0;
+    /*
+     * System is able to detect the presence of humans.
+     */
+    const int CAP_PRESENCE_DETECTION = 1 << 0;
+    /*
+     * System is able to detect the gaze of humans.
+     */
+    const int CAP_GAZE_DETECTION = 1 << 1;
+    /*
+     * System is able to compute the attention details of humans.
+     */
+    const int CAP_DRIVER_MONITORING_DETECTION = 1 << 2;
+
+    /**
+     * Starts the occupant awareness detection system. This is a non-blocking function call.
+     * Once system is ready, state will be modified. State update can be inrquired using callback
+     * or getState() function.
+     * @return status is the current system state.
+     */
+    OccupantAwarenessStatus startDetection();
+
+    /**
+     * Stops the occupant awareness detection system. This is a non-blocking function call.
+     * Once system is reset, state will be modified. State update can be inrquired using callback
+     * or getState() function.
+     * @return status is the current system state.
+     */
+    OccupantAwarenessStatus stopDetection();
+
+    /**
+     * Returns list of Awareness Capability supported for the given type of occupants.
+     *
+     * @param out Bitwise OR of supported capabilities (CAP_* mask).
+     */
+    int getCapabilityForRole(in Role occupantRole);
+
+    /**
+     * Inquires the current state of the occupant awareness system.
+     * @param occupantRole specifies the role of occupants of interest.
+     * @param detectionCapability specifies a single detection capability (CAP_* ) of interest.
+     *
+     * @return status is the current system state.
+     */
+    OccupantAwarenessStatus getState(in Role occupantRole, in int detectionCapability);
+
+    /**
+     * Registers a callback for data streaming. Only single callback is supported. setCallback()
+     *        should replace existing callback with new callback.
+     * @return: returns ok if successful.
+     */
+    void setCallback(in IOccupantAwarenessClientCallback callback);
+
+    /**
+     * Returns the most recent set of detections.
+     * @param OccupantDetections output detections.
+     * @return returns ok if successful.
+     */
+    void getLatestDetection(out OccupantDetections detections);
+}
diff --git a/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/IOccupantAwarenessClientCallback.aidl b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/IOccupantAwarenessClientCallback.aidl
new file mode 100644
index 0000000..69f7b0b
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/IOccupantAwarenessClientCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+package android.hardware.automotive.occupant_awareness;
+
+import android.hardware.automotive.occupant_awareness.OccupantAwarenessStatus;
+import android.hardware.automotive.occupant_awareness.OccupantDetections;
+
+@VintfStability
+interface IOccupantAwarenessClientCallback {
+    /**
+     * A callback invoked when the system status changes.
+     *
+     * @param detectionFlags The detection subsystem(s) whose status has changed.
+     * @param status The new system status.
+     */
+    oneway void onSystemStatusChanged(in int detectionFlags, in OccupantAwarenessStatus status);
+
+    /**
+     * A callback invoked when a new set of detections are available.
+     *
+     * @param detections Occupant detections.
+     */
+    oneway void onDetectionEvent(in OccupantDetections detections);
+}
diff --git a/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/OccupantAwarenessStatus.aidl b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/OccupantAwarenessStatus.aidl
new file mode 100644
index 0000000..6a3453d
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/OccupantAwarenessStatus.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+package android.hardware.automotive.occupant_awareness;
+
+@VintfStability
+@Backing(type="byte")
+enum OccupantAwarenessStatus {
+    /*
+     * System is online and ready to serve requests.
+     */
+    READY = 0,
+    /**
+     * Detection is not supported in this vehicle due to a permanent lack of capabilities. Clients
+     * need not retry.
+     */
+    NOT_SUPPORTED = 1,
+    /*
+     * The system has not yet been initialized. No requests can be served until the
+     * initialization process completes. This state does not indicate any error and
+     * clients should retry later.
+     */
+    NOT_INITIALIZED = 2,
+    /*
+     * A permanent failure has occurred. No detections will be provided.
+     */
+    FAILURE = 3,
+}
diff --git a/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/OccupantDetection.aidl b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/OccupantDetection.aidl
new file mode 100644
index 0000000..47ca35a
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/OccupantDetection.aidl
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+package android.hardware.automotive.occupant_awareness;
+
+import android.hardware.automotive.occupant_awareness.Role;
+import android.hardware.automotive.occupant_awareness.PresenceDetection;
+import android.hardware.automotive.occupant_awareness.GazeDetection;
+import android.hardware.automotive.occupant_awareness.DriverMonitoringDetection;
+
+/*
+ * A complete detection for a single occupant in the vehicle. Includes data about the subject's
+ * presence in the vehicle, gaze and attention.
+ */
+ @VintfStability
+parcelable OccupantDetection {
+    /*
+     * Role of the occupant (e.g., driver, passenger).
+     */
+    Role role;
+    /*
+     * Occupant presence state for a single occupant.
+     * If the vector is empty, no data could be generated.
+     */
+    PresenceDetection[] presenceData;
+    /*
+     * Gaze data for a single occupant.
+     * If the vector is empty, no data could be generated.
+     */
+    GazeDetection[] gazeData;
+    /*
+     * Attention data for a single occupant.
+     * If the vector is empty, no data could be generated.
+     */
+    DriverMonitoringDetection[] attentionData;
+}
+
diff --git a/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/OccupantDetections.aidl b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/OccupantDetections.aidl
new file mode 100644
index 0000000..e8f6621
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/OccupantDetections.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+package android.hardware.automotive.occupant_awareness;
+
+import android.hardware.automotive.occupant_awareness.OccupantDetection;
+
+@VintfStability
+parcelable OccupantDetections {
+    /**
+     * Timestamp that the underlying source image was captured, in milliseconds since Jan 1, 1970
+     * (Unix time).
+     */
+    long timeStampMillis;
+    /**
+     * A vector of detections for all occupants in the vehicle. One OccupantDetection will be
+     * generated per detected face.
+     */
+    OccupantDetection[] detections;
+}
+
diff --git a/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/PresenceDetection.aidl b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/PresenceDetection.aidl
new file mode 100644
index 0000000..a018106
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/PresenceDetection.aidl
@@ -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.
+ */
+
+package android.hardware.automotive.occupant_awareness;
+
+@VintfStability
+parcelable PresenceDetection {
+    /*
+     * Boolean representing whether an occupant was detected.
+     */
+    boolean isOccupantDetected;
+    /**
+     * Duration that a particular occupant has been continuously
+     * detected, in milliseconds. Will be zero duration if the occupant is not
+     * currently detected.
+     */
+    long detectionDurationMillis;
+}
diff --git a/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/Role.aidl b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/Role.aidl
new file mode 100644
index 0000000..42e86ad
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/Role.aidl
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+package android.hardware.automotive.occupant_awareness;
+
+@VintfStability
+@Backing(type="int")
+enum Role {
+    /*
+     * All valid role(s) must have at least 1 bit set.
+     */
+    INVALID = 0,
+    /*
+     * System could not determine role for this occupant.
+     */
+    UNKNOWN = 1 << 0,
+    /*
+     * Occupants that the system detects as front seat passengers.
+     */
+    FRONT_PASSENGER = 1 << 1,
+    /*
+     * Occupants that the system detects as driver(s).
+     */
+    DRIVER = 1 << 2,
+    /*
+     * Occupants on left seat of row 2.
+     */
+    ROW_2_PASSENGER_LEFT = 1 << 3,
+    /*
+     * Occupants on center seat of row 2.
+     */
+    ROW_2_PASSENGER_CENTER = 1 << 4,
+    /*
+     * Occupants on right seat of row 2.
+     */
+    ROW_2_PASSENGER_RIGHT = 1 << 5,
+    /*
+     * Occupants on left seat of row 3.
+     */
+    ROW_3_PASSENGER_LEFT = 1 << 6,
+    /*
+     * Occupants on center seat of row 3.
+     */
+    ROW_3_PASSENGER_CENTER = 1 << 7,
+    /*
+     * Occupants on right seat of row 3.
+     */
+    ROW_3_PASSENGER_RIGHT = 1 << 8,
+
+    /*
+     * Occupants that the system detects as front seat occupant.
+     * FRONT_OCCUPANTS = DRIVER | FRONT_PASSENGER
+     */
+    FRONT_OCCUPANTS = 1 << 1 | 1 << 2,
+    /*
+     * Occupants of row 2.
+     * ROW_2_OCCUPANTS = ROW_2_PASSENGER_LEFT | ROW_2_PASSENGER_CENTER | ROW_2_PASSENGER_RIGHT
+     */
+    ROW_2_OCCUPANTS = 1 << 3 | 1 << 4 | 1 << 5,
+    /*
+     * Occupants of row 3.
+     * ROW_3_OCCUPANTS = ROW_3_PASSENGER_LEFT | ROW_3_PASSENGER_CENTER | ROW_3_PASSENGER_RIGHT
+     */
+    ROW_3_OCCUPANTS = 1 << 6 | 1 << 7 | 1 << 8,
+    /*
+     * All the occupants in the vehicle.
+     * ALL_OCCUPANTS = UNKNOWN | FRONT_OCCUPANTS | ROW_2_OCCUPANTS | ROW_3_OCCUPANTS
+     */
+    ALL_OCCUPANTS = 0x1FF,
+}
diff --git a/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/VehicleRegion.aidl b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/VehicleRegion.aidl
new file mode 100644
index 0000000..9ee9d52
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/android/hardware/automotive/occupant_awareness/VehicleRegion.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+package android.hardware.automotive.occupant_awareness;
+
+@VintfStability
+@Backing(type="int")
+enum VehicleRegion {
+    /*
+     * List of targets in the car.
+     */
+    UNKNOWN = 0,
+    INSTRUMENT_CLUSTER = 1,
+    REAR_VIEW_MIRROR = 2,
+    LEFT_SIDE_MIRROR = 3,
+    RIGHT_SIDE_MIRROR = 4,
+    FORWARD_ROADWAY = 5,
+    LEFT_ROADWAY = 6,
+    RIGHT_ROADWAY = 7,
+    HEAD_UNIT_DISPLAY = 8,
+    /*
+     * Vendors can use this value along with customGazeTarget string to uniquely identify their
+     * custom region.
+     */
+    CUSTOM_TARGET = 200,
+}
diff --git a/automotive/occupant_awareness/aidl/default/Android.bp b/automotive/occupant_awareness/aidl/default/Android.bp
new file mode 100644
index 0000000..1b2fba2
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/default/Android.bp
@@ -0,0 +1,32 @@
+/*
+ * 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_binary {
+    name: "android.hardware.automotive.occupant_awareness@1.0-service",
+    init_rc: ["android.hardware.automotive.occupant_awareness@1.0-service.rc"],
+    relative_install_path: "hw",
+    vendor: true,
+    srcs: [
+        "service.cpp",
+        "OccupantAwareness.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "libutils",
+        "android.hardware.automotive.occupant_awareness-ndk_platform",
+    ],
+}
diff --git a/automotive/occupant_awareness/aidl/default/OccupantAwareness.cpp b/automotive/occupant_awareness/aidl/default/OccupantAwareness.cpp
new file mode 100644
index 0000000..a156075
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/default/OccupantAwareness.cpp
@@ -0,0 +1,122 @@
+/*
+ * 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 "OccupantAwareness.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace occupant_awareness {
+namespace V1_0 {
+namespace implementation {
+
+using ndk::ScopedAStatus;
+
+static const int32_t kAllCapabilities = OccupantAwareness::CAP_PRESENCE_DETECTION |
+                                        OccupantAwareness::CAP_GAZE_DETECTION |
+                                        OccupantAwareness::CAP_DRIVER_MONITORING_DETECTION;
+
+ScopedAStatus OccupantAwareness::startDetection(OccupantAwarenessStatus* status) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (mStatus != OccupantAwarenessStatus::NOT_SUPPORTED) {
+        mStatus = OccupantAwarenessStatus::NOT_SUPPORTED;
+        if (mCallback) {
+            mCallback->onSystemStatusChanged(kAllCapabilities,
+                                             OccupantAwarenessStatus::NOT_SUPPORTED);
+        }
+    }
+    *status = mStatus;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus OccupantAwareness::stopDetection(OccupantAwarenessStatus* status) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (mStatus != OccupantAwarenessStatus::NOT_INITIALIZED) {
+        mStatus = OccupantAwarenessStatus::NOT_INITIALIZED;
+        if (mCallback) {
+            mCallback->onSystemStatusChanged(kAllCapabilities,
+                                             OccupantAwarenessStatus::NOT_INITIALIZED);
+        }
+    }
+    *status = mStatus;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus OccupantAwareness::getCapabilityForRole(Role occupantRole, int32_t* capabilities) {
+    if (!isValidRole(occupantRole)) {
+        return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
+    }
+
+    // No awareness capability for default HAL.
+    *capabilities = 0;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus OccupantAwareness::getState(Role occupantRole, int detectionCapability,
+                                          OccupantAwarenessStatus* status) {
+    if (!isValidRole(occupantRole)) {
+        return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
+    }
+
+    if (!isValidDetectionCapabilities(detectionCapability) ||
+        !isSingularCapability(detectionCapability)) {
+        return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
+    }
+
+    std::lock_guard<std::mutex> lock(mMutex);
+    *status = mStatus;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus OccupantAwareness::setCallback(
+        const std::shared_ptr<IOccupantAwarenessClientCallback>& callback) {
+    if (callback == nullptr) {
+        return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
+    }
+
+    std::lock_guard<std::mutex> lock(mMutex);
+    mCallback = callback;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus OccupantAwareness::getLatestDetection(OccupantDetections* detections) {
+    // No detection generated for default hal.
+    (void)detections;
+    return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
+}
+
+bool OccupantAwareness::isValidRole(Role occupantRole) {
+    int intVal = static_cast<int>(occupantRole);
+    int allOccupants = static_cast<int>(Role::ALL_OCCUPANTS);
+    return (occupantRole != Role::INVALID) && ((intVal & (~allOccupants)) == 0);
+}
+
+bool OccupantAwareness::isValidDetectionCapabilities(int detectionCapabilities) {
+    return (detectionCapabilities != CAP_NONE) &&
+           ((detectionCapabilities & (~kAllCapabilities)) == 0);
+}
+
+bool OccupantAwareness::isSingularCapability(int detectionCapability) {
+    // Check whether the value is 0, or the value has only one bit set.
+    return (detectionCapability & (detectionCapability - 1)) == 0;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace occupant_awareness
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/occupant_awareness/aidl/default/OccupantAwareness.h b/automotive/occupant_awareness/aidl/default/OccupantAwareness.h
new file mode 100644
index 0000000..ac51aa4
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/default/OccupantAwareness.h
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#pragma once
+#include <aidl/android/hardware/automotive/occupant_awareness/BnOccupantAwareness.h>
+#include <aidl/android/hardware/automotive/occupant_awareness/BnOccupantAwarenessClientCallback.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace occupant_awareness {
+namespace V1_0 {
+namespace implementation {
+
+using ::aidl::android::hardware::automotive::occupant_awareness::BnOccupantAwareness;
+using ::aidl::android::hardware::automotive::occupant_awareness::IOccupantAwarenessClientCallback;
+using ::aidl::android::hardware::automotive::occupant_awareness::OccupantAwarenessStatus;
+using ::aidl::android::hardware::automotive::occupant_awareness::OccupantDetections;
+using ::aidl::android::hardware::automotive::occupant_awareness::Role;
+
+/**
+ * The default HAL mimics a system which has no Occupant awareness capability. The hal does not
+ * do any useful work, and returns appropriate failure code / status.
+ **/
+class OccupantAwareness : public BnOccupantAwareness {
+  public:
+    // Methods from ::android::hardware::automotive::occupant_awareness::IOccupantAwareness
+    // follow.
+    ndk::ScopedAStatus startDetection(OccupantAwarenessStatus* status) override;
+    ndk::ScopedAStatus stopDetection(OccupantAwarenessStatus* status) override;
+    ndk::ScopedAStatus getCapabilityForRole(Role occupantRole, int32_t* capabilities) override;
+    ndk::ScopedAStatus getState(Role occupantRole, int detectionCapability,
+                                OccupantAwarenessStatus* status) override;
+    ndk::ScopedAStatus setCallback(
+            const std::shared_ptr<IOccupantAwarenessClientCallback>& callback) override;
+    ndk::ScopedAStatus getLatestDetection(OccupantDetections* detections) override;
+
+  private:
+    bool isValidRole(Role occupantRole);
+    bool isValidDetectionCapabilities(int detectionCapabilities);
+    bool isSingularCapability(int detectionCapability);
+
+    std::mutex mMutex;
+    std::shared_ptr<IOccupantAwarenessClientCallback> mCallback = nullptr;
+    OccupantAwarenessStatus mStatus = OccupantAwarenessStatus::NOT_INITIALIZED;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace occupant_awareness
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/occupant_awareness/aidl/default/android.hardware.automotive.occupant_awareness@1.0-service.rc b/automotive/occupant_awareness/aidl/default/android.hardware.automotive.occupant_awareness@1.0-service.rc
new file mode 100644
index 0000000..35d5bca
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/default/android.hardware.automotive.occupant_awareness@1.0-service.rc
@@ -0,0 +1,4 @@
+service hal_occupant_awareness_default /vendor/bin/hw/android.hardware.automotive.occupant_awareness@1.0-service
+    class hal
+    user system
+    group system
diff --git a/automotive/occupant_awareness/aidl/default/service.cpp b/automotive/occupant_awareness/aidl/default/service.cpp
new file mode 100644
index 0000000..44960fb
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/default/service.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.automotive.occupant_awareness@1.0-service"
+
+#include <unistd.h>
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include "OccupantAwareness.h"
+
+using ::aidl::android::hardware::automotive::occupant_awareness::IOccupantAwareness;
+using ::android::hardware::automotive::occupant_awareness::V1_0::implementation::OccupantAwareness;
+using ::ndk::ScopedAStatus;
+using ::ndk::SharedRefBase;
+
+const static char kOccupantAwarenessServiceName[] = "default";
+
+int main() {
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+    LOG(INFO) << "Occupant Awareness service is starting";
+    std::shared_ptr<OccupantAwareness> occupantAwareness = SharedRefBase::make<OccupantAwareness>();
+
+    const std::string instance =
+            std::string() + IOccupantAwareness::descriptor + "/" + kOccupantAwarenessServiceName;
+
+    binder_status_t status =
+            AServiceManager_addService(occupantAwareness->asBinder().get(), instance.c_str());
+    if (status == STATUS_OK) {
+        LOG(INFO) << "Service " << kOccupantAwarenessServiceName << " is ready";
+        ABinderProcess_joinThreadPool();
+    } else {
+        LOG(ERROR) << "Could not register service " << kOccupantAwarenessServiceName
+                   << ", status: " << status;
+    }
+
+    // In normal operation, we don't expect the thread pool to exit.
+    LOG(ERROR) << "Occupant Awareness service is shutting down";
+    return 1;
+}
diff --git a/automotive/occupant_awareness/aidl/mock/Android.bp b/automotive/occupant_awareness/aidl/mock/Android.bp
new file mode 100644
index 0000000..4b30866
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/mock/Android.bp
@@ -0,0 +1,32 @@
+/*
+ * 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_binary {
+    name: "android.hardware.automotive.occupant_awareness@1.0-service_mock",
+    relative_install_path: "hw",
+    vendor: true,
+    srcs: [
+        "service.cpp",
+        "OccupantAwareness.cpp",
+        "DetectionGenerator.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "libutils",
+        "android.hardware.automotive.occupant_awareness-ndk_platform",
+    ],
+}
diff --git a/automotive/occupant_awareness/aidl/mock/DetectionGenerator.cpp b/automotive/occupant_awareness/aidl/mock/DetectionGenerator.cpp
new file mode 100644
index 0000000..79d4dbc
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/mock/DetectionGenerator.cpp
@@ -0,0 +1,71 @@
+/*
+ * 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 <utils/SystemClock.h>
+
+#include "DetectionGenerator.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace occupant_awareness {
+namespace V1_0 {
+namespace implementation {
+
+using ::aidl::android::hardware::automotive::occupant_awareness::ConfidenceLevel;
+using ::aidl::android::hardware::automotive::occupant_awareness::DriverMonitoringDetection;
+using ::aidl::android::hardware::automotive::occupant_awareness::OccupantDetection;
+using ::aidl::android::hardware::automotive::occupant_awareness::PresenceDetection;
+
+static int64_t kNanoSecondsPerMilliSecond = 1000 * 1000;
+
+OccupantDetections DetectionGenerator::GetNextDetections() {
+    OccupantDetections detections;
+    detections.timeStampMillis = android::elapsedRealtimeNano() / kNanoSecondsPerMilliSecond;
+    int remainingRoles = getSupportedRoles();
+    while (remainingRoles) {
+        int currentRole = remainingRoles & (~(remainingRoles - 1));
+        remainingRoles = remainingRoles & (remainingRoles - 1);
+
+        OccupantDetection occupantDetection;
+        occupantDetection.role = static_cast<Role>(currentRole);
+
+        // Add presence detection object for this occupant.
+        PresenceDetection presenceDetection;
+        presenceDetection.isOccupantDetected = true;
+        presenceDetection.detectionDurationMillis = detections.timeStampMillis;
+        occupantDetection.presenceData.emplace_back(presenceDetection);
+
+        if (occupantDetection.role == Role::DRIVER) {
+            // Add driver monitoring detection object for this occupant.
+            DriverMonitoringDetection driverMonitoringDetection;
+            driverMonitoringDetection.confidenceScore = ConfidenceLevel::HIGH;
+            driverMonitoringDetection.isLookingOnRoad = 0;
+            driverMonitoringDetection.gazeDurationMillis = detections.timeStampMillis;
+            occupantDetection.attentionData.emplace_back(driverMonitoringDetection);
+        }
+
+        detections.detections.emplace_back(occupantDetection);
+    }
+    return detections;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace occupant_awareness
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/occupant_awareness/aidl/mock/DetectionGenerator.h b/automotive/occupant_awareness/aidl/mock/DetectionGenerator.h
new file mode 100644
index 0000000..0884685
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/mock/DetectionGenerator.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/automotive/occupant_awareness/BnOccupantAwareness.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace occupant_awareness {
+namespace V1_0 {
+namespace implementation {
+
+using ::aidl::android::hardware::automotive::occupant_awareness::BnOccupantAwareness;
+using ::aidl::android::hardware::automotive::occupant_awareness::OccupantDetections;
+using ::aidl::android::hardware::automotive::occupant_awareness::Role;
+
+class DetectionGenerator {
+  public:
+    static int getSupportedRoles() {
+        return static_cast<int>(Role::DRIVER) | static_cast<int>(Role::FRONT_PASSENGER);
+    }
+    static int getSupportedCapabilities() {
+        return static_cast<int>(BnOccupantAwareness::CAP_PRESENCE_DETECTION) |
+               static_cast<int>(BnOccupantAwareness::CAP_DRIVER_MONITORING_DETECTION);
+    }
+
+    OccupantDetections GetNextDetections();
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace occupant_awareness
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/occupant_awareness/aidl/mock/OccupantAwareness.cpp b/automotive/occupant_awareness/aidl/mock/OccupantAwareness.cpp
new file mode 100644
index 0000000..910760a
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/mock/OccupantAwareness.cpp
@@ -0,0 +1,176 @@
+/*
+ * 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 <utils/SystemClock.h>
+
+#include "OccupantAwareness.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace occupant_awareness {
+namespace V1_0 {
+namespace implementation {
+
+using ndk::ScopedAStatus;
+
+static const int32_t kAllCapabilities = OccupantAwareness::CAP_PRESENCE_DETECTION |
+                                        OccupantAwareness::CAP_GAZE_DETECTION |
+                                        OccupantAwareness::CAP_DRIVER_MONITORING_DETECTION;
+
+constexpr int64_t kNanoSecondsPerMilliSecond = 1000 * 1000;
+
+ScopedAStatus OccupantAwareness::startDetection(OccupantAwarenessStatus* status) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (mStatus != OccupantAwarenessStatus::NOT_INITIALIZED) {
+        return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
+    }
+
+    mStatus = OccupantAwarenessStatus::READY;
+    mWorkerThread = std::thread(startWorkerThread, this);
+    if (mCallback) {
+        mCallback->onSystemStatusChanged(kAllCapabilities, mStatus);
+    }
+
+    *status = mStatus;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus OccupantAwareness::stopDetection(OccupantAwarenessStatus* status) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (mStatus != OccupantAwarenessStatus::READY) {
+        return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
+    }
+
+    mStatus = OccupantAwarenessStatus::NOT_INITIALIZED;
+    mWorkerThread.join();
+    if (mCallback) {
+        mCallback->onSystemStatusChanged(kAllCapabilities, mStatus);
+    }
+
+    *status = mStatus;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus OccupantAwareness::getCapabilityForRole(Role occupantRole, int32_t* capabilities) {
+    if (!isValidRole(occupantRole)) {
+        return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
+    }
+
+    int intVal = static_cast<int>(occupantRole);
+    if ((intVal & DetectionGenerator::getSupportedRoles()) == intVal) {
+        int capabilities_ = DetectionGenerator::getSupportedCapabilities();
+        if (occupantRole != Role::DRIVER) {
+            capabilities_ &= ~CAP_DRIVER_MONITORING_DETECTION;
+        }
+        *capabilities = capabilities_;
+    } else {
+        *capabilities = 0;
+    }
+
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus OccupantAwareness::getState(Role occupantRole, int detectionCapability,
+                                          OccupantAwarenessStatus* status) {
+    if (!isValidRole(occupantRole)) {
+        return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
+    }
+
+    if (!isValidDetectionCapabilities(detectionCapability) ||
+        !isSingularCapability(detectionCapability)) {
+        return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
+    }
+
+    int roleVal = static_cast<int>(occupantRole);
+
+    if (((roleVal & DetectionGenerator::getSupportedRoles()) != roleVal) ||
+        ((detectionCapability & DetectionGenerator::getSupportedCapabilities()) !=
+         detectionCapability)) {
+        *status = OccupantAwarenessStatus::NOT_SUPPORTED;
+        return ScopedAStatus::ok();
+    }
+
+    std::lock_guard<std::mutex> lock(mMutex);
+    *status = mStatus;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus OccupantAwareness::setCallback(
+        const std::shared_ptr<IOccupantAwarenessClientCallback>& callback) {
+    if (callback == nullptr) {
+        return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
+    }
+
+    std::lock_guard<std::mutex> lock(mMutex);
+    mCallback = callback;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus OccupantAwareness::getLatestDetection(OccupantDetections* detections) {
+    std::lock_guard<std::mutex> lock(mMutex);
+
+    if (mStatus != OccupantAwarenessStatus::READY) {
+        return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
+    }
+
+    *detections = mLatestDetections;
+    return ScopedAStatus::ok();
+}
+
+bool OccupantAwareness::isValidRole(Role occupantRole) {
+    int intVal = static_cast<int>(occupantRole);
+    int allOccupants = static_cast<int>(Role::ALL_OCCUPANTS);
+    return (occupantRole != Role::INVALID) && ((intVal & (~allOccupants)) == 0);
+}
+
+bool OccupantAwareness::isValidDetectionCapabilities(int detectionCapabilities) {
+    return (detectionCapabilities != OccupantAwareness::CAP_NONE) &&
+           ((detectionCapabilities & (~kAllCapabilities)) == 0);
+}
+
+bool OccupantAwareness::isSingularCapability(int detectionCapability) {
+    // Check whether the value is 0, or the value has only one bit set.
+    return (detectionCapability & (detectionCapability - 1)) == 0;
+}
+
+void OccupantAwareness::startWorkerThread(OccupantAwareness* occupantAwareness) {
+    occupantAwareness->workerThreadFunction();
+}
+
+void OccupantAwareness::workerThreadFunction() {
+    bool isFirstDetection = true;
+    int64_t prevDetectionTimeMs;
+    while (mStatus == OccupantAwarenessStatus::READY) {
+        int64_t currentTimeMs = android::elapsedRealtimeNano() / kNanoSecondsPerMilliSecond;
+        if ((isFirstDetection) || (currentTimeMs - prevDetectionTimeMs > mDetectionDurationMs)) {
+            std::lock_guard<std::mutex> lock(mMutex);
+            mLatestDetections = mGenerator.GetNextDetections();
+            if (mCallback != nullptr) {
+                mCallback->onDetectionEvent(mLatestDetections);
+            }
+            isFirstDetection = false;
+            prevDetectionTimeMs = currentTimeMs;
+        }
+    }
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace occupant_awareness
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/occupant_awareness/aidl/mock/OccupantAwareness.h b/automotive/occupant_awareness/aidl/mock/OccupantAwareness.h
new file mode 100644
index 0000000..c5f6dd6
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/mock/OccupantAwareness.h
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <thread>
+
+#include <aidl/android/hardware/automotive/occupant_awareness/BnOccupantAwareness.h>
+#include <aidl/android/hardware/automotive/occupant_awareness/BnOccupantAwarenessClientCallback.h>
+#include <utils/StrongPointer.h>
+
+#include "DetectionGenerator.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace occupant_awareness {
+namespace V1_0 {
+namespace implementation {
+
+using ::aidl::android::hardware::automotive::occupant_awareness::BnOccupantAwareness;
+using ::aidl::android::hardware::automotive::occupant_awareness::IOccupantAwarenessClientCallback;
+using ::aidl::android::hardware::automotive::occupant_awareness::OccupantAwarenessStatus;
+using ::aidl::android::hardware::automotive::occupant_awareness::OccupantDetections;
+using ::aidl::android::hardware::automotive::occupant_awareness::Role;
+
+/**
+ * The mock HAL can detect presence of Driver and front passenger, and driver awareness detection
+ * for driver.
+ **/
+class OccupantAwareness : public BnOccupantAwareness {
+  public:
+    // Methods from ::android::hardware::automotive::occupant_awareness::IOccupantAwareness
+    // follow.
+    ndk::ScopedAStatus startDetection(OccupantAwarenessStatus* status) override;
+    ndk::ScopedAStatus stopDetection(OccupantAwarenessStatus* status) override;
+    ndk::ScopedAStatus getCapabilityForRole(Role occupantRole, int32_t* capabilities) override;
+    ndk::ScopedAStatus getState(Role occupantRole, int detectionCapability,
+                                OccupantAwarenessStatus* status) override;
+    ndk::ScopedAStatus setCallback(
+            const std::shared_ptr<IOccupantAwarenessClientCallback>& callback) override;
+    ndk::ScopedAStatus getLatestDetection(OccupantDetections* detections) override;
+
+  private:
+    bool isValidRole(Role occupantRole);
+    bool isValidDetectionCapabilities(int detectionCapabilities);
+    bool isSingularCapability(int detectionCapability);
+
+    void workerThreadFunction();
+    static void startWorkerThread(OccupantAwareness* occupantAwareness);
+
+    std::mutex mMutex;
+    std::shared_ptr<IOccupantAwarenessClientCallback> mCallback = nullptr;
+    OccupantAwarenessStatus mStatus = OccupantAwarenessStatus::NOT_INITIALIZED;
+
+    OccupantDetections mLatestDetections;
+    std::thread mWorkerThread;
+
+    DetectionGenerator mGenerator;
+
+    // Generate a new detection every 1ms.
+    const int64_t mDetectionDurationMs = 1;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace occupant_awareness
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/occupant_awareness/aidl/mock/service.cpp b/automotive/occupant_awareness/aidl/mock/service.cpp
new file mode 100644
index 0000000..d8860df
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/mock/service.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.automotive.occupant_awareness@1.0-service_mock"
+
+#include <unistd.h>
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include "OccupantAwareness.h"
+
+using ::aidl::android::hardware::automotive::occupant_awareness::IOccupantAwareness;
+using ::android::hardware::automotive::occupant_awareness::V1_0::implementation::OccupantAwareness;
+using ::ndk::ScopedAStatus;
+using ::ndk::SharedRefBase;
+
+const static char kOccupantAwarenessServiceName[] = "default";
+
+int main() {
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+    LOG(INFO) << "Occupant Awareness service is starting";
+    std::shared_ptr<OccupantAwareness> occupantAwareness = SharedRefBase::make<OccupantAwareness>();
+
+    const std::string instance =
+            std::string() + IOccupantAwareness::descriptor + "/" + kOccupantAwarenessServiceName;
+
+    binder_status_t status =
+            AServiceManager_addService(occupantAwareness->asBinder().get(), instance.c_str());
+    if (status == STATUS_OK) {
+        LOG(INFO) << "Service " << kOccupantAwarenessServiceName << " is ready";
+        ABinderProcess_joinThreadPool();
+    } else {
+        LOG(ERROR) << "Could not register service " << kOccupantAwarenessServiceName
+                   << ", status: " << status;
+    }
+
+    // In normal operation, we don't expect the thread pool to exit.
+    LOG(ERROR) << "Occupant Awareness service is shutting down";
+    return 1;
+}
diff --git a/automotive/occupant_awareness/aidl/vts/functional/Android.bp b/automotive/occupant_awareness/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..1256b69
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/vts/functional/Android.bp
@@ -0,0 +1,17 @@
+cc_test {
+    name: "VtsHalOccupantAwarenessV1_0TargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: ["VtsHalOccupantAwarenessV1_0TargetTest.cpp"],
+    shared_libs: [
+        "libbinder",
+    ],
+    static_libs: [
+        "android.hardware.automotive.occupant_awareness-cpp",
+    ],
+    test_suites: [
+        "vts-core",
+    ],
+}
diff --git a/automotive/occupant_awareness/aidl/vts/functional/VtsHalOccupantAwarenessV1_0TargetTest.cpp b/automotive/occupant_awareness/aidl/vts/functional/VtsHalOccupantAwarenessV1_0TargetTest.cpp
new file mode 100644
index 0000000..c431f9d
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/vts/functional/VtsHalOccupantAwarenessV1_0TargetTest.cpp
@@ -0,0 +1,203 @@
+/*
+ * 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 "**** HAL log ****"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <android-base/logging.h>
+#include <android/hardware/automotive/occupant_awareness/BnOccupantAwarenessClientCallback.h>
+#include <android/hardware/automotive/occupant_awareness/IOccupantAwareness.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <gtest/gtest.h>
+
+#include <chrono>
+#include <future>
+#include <vector>
+
+using namespace android::hardware::automotive::occupant_awareness;
+using android::hardware::automotive::occupant_awareness::IOccupantAwareness;
+
+using android::ProcessState;
+using android::sp;
+using android::String16;
+using android::binder::Status;
+
+constexpr auto kTimeout = std::chrono::seconds(3);
+
+#define EXPECT_OK(ret) ASSERT_TRUE((ret).isOk())
+
+class OccupantAwarenessCallback : public BnOccupantAwarenessClientCallback {
+  public:
+    OccupantAwarenessCallback(const std::function<void(int, OccupantAwarenessStatus)>& callback)
+        : mCallback(callback) {}
+    Status onSystemStatusChanged(int detectionFlags, OccupantAwarenessStatus status) override {
+        mCallback(detectionFlags, status);
+        return Status::ok();
+    }
+
+    Status onDetectionEvent(const OccupantDetections& detections) override {
+        (void)detections;
+        return Status::ok();
+    }
+
+  private:
+    std::function<void(int, OccupantAwarenessStatus)> mCallback;
+};
+
+class OccupantAwarenessAidl : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        mOccupantAwarenessService =
+                android::waitForDeclaredService<IOccupantAwareness>(String16(GetParam().c_str()));
+        ASSERT_NE(mOccupantAwarenessService, nullptr);
+    }
+
+    sp<IOccupantAwareness> mOccupantAwarenessService;
+};
+
+// Test that startDetection() returns within the timeout.
+TEST_P(OccupantAwarenessAidl, StartDetectionTest) {
+    auto start = std::chrono::system_clock::now();
+    OccupantAwarenessStatus occupantAwarenessStatus;
+    Status status = mOccupantAwarenessService->startDetection(&occupantAwarenessStatus);
+    auto elapsed = std::chrono::system_clock::now() - start;
+    EXPECT_OK(status);
+    ASSERT_LE(elapsed, kTimeout);
+
+    EXPECT_OK(mOccupantAwarenessService->stopDetection(&occupantAwarenessStatus));
+}
+
+// Test that getCapabilityForRole() returns supported capabilities for the role. The test only
+// verifies that the IPC call returns successfully and does not verify the supported capabilities.
+TEST_P(OccupantAwarenessAidl, GetCapabilityTest) {
+    std::vector<Role> rolesToTest = {Role::FRONT_PASSENGER,        Role::DRIVER,
+                                     Role::ROW_2_PASSENGER_LEFT,   Role::ROW_2_PASSENGER_CENTER,
+                                     Role::ROW_2_PASSENGER_RIGHT,  Role::ROW_3_PASSENGER_LEFT,
+                                     Role::ROW_3_PASSENGER_CENTER, Role::ROW_3_PASSENGER_RIGHT,
+                                     Role::FRONT_OCCUPANTS,        Role::ROW_2_OCCUPANTS,
+                                     Role::ROW_3_OCCUPANTS,        Role::ALL_OCCUPANTS};
+
+    for (auto role : rolesToTest) {
+        int32_t capabilities;
+        EXPECT_OK(mOccupantAwarenessService->getCapabilityForRole(role, &capabilities));
+    }
+}
+
+// Test that getCapabilityForRole() returns failure when arguments are invalid.
+TEST_P(OccupantAwarenessAidl, GetCapabilityFailureTest) {
+    int32_t capabilities;
+    EXPECT_FALSE(
+            mOccupantAwarenessService->getCapabilityForRole(Role::INVALID, &capabilities).isOk());
+
+    Role invalidRole = static_cast<Role>(static_cast<int>(Role::ALL_OCCUPANTS) + 1);
+    EXPECT_FALSE(
+            mOccupantAwarenessService->getCapabilityForRole(invalidRole, &capabilities).isOk());
+}
+
+// Test that getState() returns within the timeout. The test do not attempt to verify the state, but
+// only checks that the IPC call returns successfully.
+TEST_P(OccupantAwarenessAidl, GetStateTest) {
+    std::vector<Role> rolesToTest = {Role::FRONT_PASSENGER,        Role::DRIVER,
+                                     Role::ROW_2_PASSENGER_LEFT,   Role::ROW_2_PASSENGER_CENTER,
+                                     Role::ROW_2_PASSENGER_RIGHT,  Role::ROW_3_PASSENGER_LEFT,
+                                     Role::ROW_3_PASSENGER_CENTER, Role::ROW_3_PASSENGER_RIGHT,
+                                     Role::FRONT_OCCUPANTS,        Role::ROW_2_OCCUPANTS,
+                                     Role::ROW_3_OCCUPANTS,        Role::ALL_OCCUPANTS};
+
+    std::vector<int> detectionCapabilities = {IOccupantAwareness::CAP_PRESENCE_DETECTION,
+                                              IOccupantAwareness::CAP_GAZE_DETECTION,
+                                              IOccupantAwareness::CAP_DRIVER_MONITORING_DETECTION};
+
+    for (auto role : rolesToTest) {
+        for (auto detectionCapability : detectionCapabilities) {
+            OccupantAwarenessStatus oasStatus;
+            EXPECT_OK(mOccupantAwarenessService->getState(role, detectionCapability, &oasStatus));
+        }
+    }
+}
+
+// Test that getState() returns failure with invalid args.
+TEST_P(OccupantAwarenessAidl, GetStateFailureTest) {
+    // Verify that getState() returns error when role is invalid (0).
+    OccupantAwarenessStatus oasStatus;
+    EXPECT_FALSE(mOccupantAwarenessService
+                         ->getState(Role::INVALID, IOccupantAwareness::CAP_PRESENCE_DETECTION,
+                                    &oasStatus)
+                         .isOk());
+
+    // Verify that getState() returns error when role is invalid (invalid flag).
+    int invalidRole = static_cast<int>(Role::ALL_OCCUPANTS) + 1;
+    EXPECT_FALSE(mOccupantAwarenessService
+                         ->getState(static_cast<Role>(invalidRole),
+                                    IOccupantAwareness::CAP_PRESENCE_DETECTION, &oasStatus)
+                         .isOk());
+
+    // Verify that getState() returns error when capability is invalid (none).
+    EXPECT_FALSE(mOccupantAwarenessService
+                         ->getState(Role::FRONT_PASSENGER, IOccupantAwareness::CAP_NONE, &oasStatus)
+                         .isOk());
+
+    // Verify that getState() returns error when capability is invalid (invalid flag).
+    int invalidDetectionFlags = 0x10;
+    EXPECT_FALSE(mOccupantAwarenessService
+                         ->getState(Role::FRONT_PASSENGER, invalidDetectionFlags, &oasStatus)
+                         .isOk());
+}
+
+// Test that setCallback() returns within the timeout.
+TEST_P(OccupantAwarenessAidl, SetCallbackTest) {
+    sp<OccupantAwarenessCallback> callback =
+            new OccupantAwarenessCallback([](int detectionFlags, OccupantAwarenessStatus status) {
+                (void)detectionFlags;
+                (void)status;
+            });
+    auto start = std::chrono::system_clock::now();
+    Status status = mOccupantAwarenessService->setCallback(callback);
+    auto elapsed = std::chrono::system_clock::now() - start;
+    EXPECT_OK(status);
+    ASSERT_LE(elapsed, kTimeout);
+}
+
+// Test that setCallback() returns failure with invalid args.
+TEST_P(OccupantAwarenessAidl, SetCallbackFailureTest) {
+    sp<OccupantAwarenessCallback> callback = nullptr;
+    Status status = mOccupantAwarenessService->setCallback(callback);
+    EXPECT_FALSE(status.isOk());
+}
+
+// Test that getLatestDetection() returns within the timeout.
+TEST_P(OccupantAwarenessAidl, GetLatestDetectionTest) {
+    auto start = std::chrono::system_clock::now();
+    OccupantDetections detections;
+    // Do not check status here, since error status is returned when no detection is present.
+    (void)mOccupantAwarenessService->getLatestDetection(&detections);
+    auto elapsed = std::chrono::system_clock::now() - start;
+    ASSERT_LE(elapsed, kTimeout);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        InstantiationName, OccupantAwarenessAidl,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IOccupantAwareness::descriptor)),
+        android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ProcessState::self()->setThreadPoolMaxThreadCount(1);
+    ProcessState::self()->startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index ed09859..f9c25d1 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -58,6 +58,7 @@
     defaults: ["vhal_v2_0_defaults"],
     srcs: [
         "impl/vhal_v2_0/CommConn.cpp",
+        "impl/vhal_v2_0/EmulatedVehicleConnector.cpp",
         "impl/vhal_v2_0/EmulatedVehicleHal.cpp",
         "impl/vhal_v2_0/VehicleEmulator.cpp",
         "impl/vhal_v2_0/PipeComm.cpp",
diff --git a/automotive/vehicle/2.0/default/VehicleService.cpp b/automotive/vehicle/2.0/default/VehicleService.cpp
index d1fd555..127eb98 100644
--- a/automotive/vehicle/2.0/default/VehicleService.cpp
+++ b/automotive/vehicle/2.0/default/VehicleService.cpp
@@ -20,8 +20,9 @@
 
 #include <iostream>
 
-#include <vhal_v2_0/VehicleHalManager.h>
+#include <vhal_v2_0/EmulatedVehicleConnector.h>
 #include <vhal_v2_0/EmulatedVehicleHal.h>
+#include <vhal_v2_0/VehicleHalManager.h>
 
 using namespace android;
 using namespace android::hardware;
@@ -29,9 +30,11 @@
 
 int main(int /* argc */, char* /* argv */ []) {
     auto store = std::make_unique<VehiclePropertyStore>();
-    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get());
+    auto connector = impl::makeEmulatedPassthroughConnector();
+    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get());
     auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get());
     auto service = std::make_unique<VehicleHalManager>(hal.get());
+    connector->setValuePool(hal->getValuePool());
 
     configureRpcThreadpool(4, true /* callerWillJoin */);
 
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
new file mode 100644
index 0000000..56ecd67
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
@@ -0,0 +1,141 @@
+/*
+ * 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_automotive_vehicle_V2_0_VehicleConnector_H_
+#define android_hardware_automotive_vehicle_V2_0_VehicleConnector_H_
+
+#include <vector>
+
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+/**
+ *  This file defines the interface of client/server pair for HAL-vehicle
+ *  communication. Vehicle HAL may use this interface to talk to the vehicle
+ *  regardless of the underlying communication channels.
+ */
+
+/**
+ *  Vehicle HAL talks to the vehicle through a client, instead of accessing
+ *  the car bus directly, to give us more flexibility on the implementation.
+ *  Android OS do not need direct access to the vehicle, and the communication
+ *  channel is also customizable.
+ *
+ *  Client lives on the Android (HAL) side to talk to the vehicle
+ */
+class IVehicleClient {
+  public:
+    IVehicleClient() = default;
+
+    IVehicleClient(const IVehicleClient&) = delete;
+
+    IVehicleClient& operator=(const IVehicleClient&) = delete;
+
+    IVehicleClient(IVehicleClient&&) = default;
+
+    virtual ~IVehicleClient() = default;
+
+    // Get configuration of all properties from server
+    virtual std::vector<VehiclePropConfig> getAllPropertyConfig() const = 0;
+
+    // Send the set property request to server
+    virtual StatusCode setProperty(const VehiclePropValue& value) = 0;
+
+    // Receive a new property value from server
+    virtual void onPropertyValue(const VehiclePropValue& value) = 0;
+};
+
+/**
+ *  Server lives on the vehicle side to talk to Android HAL
+ */
+class IVehicleServer {
+  public:
+    IVehicleServer() = default;
+
+    IVehicleServer(const IVehicleServer&) = delete;
+
+    IVehicleServer& operator=(const IVehicleServer&) = delete;
+
+    IVehicleServer(IVehicleServer&&) = default;
+
+    virtual ~IVehicleServer() = default;
+
+    // Receive the get property configuration request from HAL.
+    // Return a list of all property config
+    virtual std::vector<VehiclePropConfig> onGetAllPropertyConfig() const = 0;
+
+    // Receive the set property request from HAL.
+    // Process the setting and return the status code
+    virtual StatusCode onSetProperty(const VehiclePropValue& value) = 0;
+
+    // Receive a new property value from car (via direct connection to the car bus or the emulator)
+    // and forward the value to HAL
+    virtual void onPropertyValueFromCar(const VehiclePropValue& value) = 0;
+};
+
+/**
+ *  If Android has direct access to the vehicle, then the client and
+ *  the server may act in passthrough mode to avoid extra IPC
+ *
+ *  Template is used here for spliting the logic of operating Android objects (VehicleClientType),
+ *  talking to cars (VehicleServerType) and the commucation between client and server (passthrough
+ *  mode in this case), so that we can easily combine different parts together without duplicating
+ *  codes (for example, in Google VHAL, the server talks to the fake car in the same way no matter
+ *  if it is on top of passthrough connector or VSOCK or any other communication channels between
+ *  client and server)
+ *
+ *  The alternative may be factoring the common logic of every operations for both client and
+ *  server. Which is not always the case. Making sure different non-template connectors calling
+ *  the same method is hard, especially when the engineer maintaining the code may not be aware
+ *  of it when making changes. Template is a clean and easy way to solve this problem in this
+ *  case.
+ */
+template <typename VehicleClientType, typename VehicleServerType>
+class IPassThroughConnector : public VehicleClientType, public VehicleServerType {
+    static_assert(std::is_base_of_v<IVehicleClient, VehicleClientType>);
+    static_assert(std::is_base_of_v<IVehicleServer, VehicleServerType>);
+
+  public:
+    std::vector<VehiclePropConfig> getAllPropertyConfig() const override {
+        return this->onGetAllPropertyConfig();
+    }
+
+    StatusCode setProperty(const VehiclePropValue& value) override {
+        return this->onSetProperty(value);
+    }
+
+    void onPropertyValueFromCar(const VehiclePropValue& value) override {
+        return this->onPropertyValue(value);
+    }
+
+    // To be implemented:
+    // virtual std::vector<VehiclePropConfig> onGetAllPropertyConfig() = 0;
+    // virtual void onPropertyValue(const VehiclePropValue& value) = 0;
+    // virtual StatusCode onSetProperty(const VehiclePropValue& value) = 0;
+};
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_V2_0_VehicleConnector_H_
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h
index 8ee3c54..f8b10ca 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h
@@ -61,7 +61,7 @@
 
 struct VmsLayerAndPublisher {
     VmsLayerAndPublisher(VmsLayer layer, int publisher_id)
-        : layer(layer), publisher_id(publisher_id) {}
+        : layer(std::move(layer)), publisher_id(publisher_id) {}
     VmsLayer layer;
     int publisher_id;
 };
@@ -69,6 +69,8 @@
 // A VmsAssociatedLayer is used by subscribers to specify which publisher IDs
 // are acceptable for a given layer.
 struct VmsAssociatedLayer {
+    VmsAssociatedLayer(VmsLayer layer, std::vector<int> publisher_ids)
+        : layer(std::move(layer)), publisher_ids(std::move(publisher_ids)) {}
     VmsLayer layer;
     std::vector<int> publisher_ids;
 };
@@ -77,7 +79,7 @@
 // its dependencies. Dependencies can be empty.
 struct VmsLayerOffering {
     VmsLayerOffering(VmsLayer layer, std::vector<VmsLayer> dependencies)
-        : layer(layer), dependencies(dependencies) {}
+        : layer(std::move(layer)), dependencies(std::move(dependencies)) {}
     VmsLayerOffering(VmsLayer layer) : layer(layer), dependencies() {}
     VmsLayer layer;
     std::vector<VmsLayer> dependencies;
@@ -87,7 +89,7 @@
 // with the specified publisher ID.
 struct VmsOffers {
     VmsOffers(int publisher_id, std::vector<VmsLayerOffering> offerings)
-        : publisher_id(publisher_id), offerings(offerings) {}
+        : publisher_id(publisher_id), offerings(std::move(offerings)) {}
     int publisher_id;
     std::vector<VmsLayerOffering> offerings;
 };
@@ -231,6 +233,24 @@
                                           const int current_service_id, const int current_client_id,
                                           int* new_service_id);
 
+// Returns true if the new sequence number of the availability state message is greater than
+// the last seen availability sequence number.
+bool isAvailabilitySequenceNumberNewer(const VehiclePropValue& availability_state,
+                                       const int last_seen_availability_sequence_number);
+
+// Returns sequence number of the availability state message.
+int32_t getSequenceNumberForAvailabilityState(const VehiclePropValue& availability_state);
+
+// Takes a availability state message and returns the associated layers that are
+// available to publish data.
+//
+// A subscriber can use this function when receiving an availability response or availability
+// change message to determine which associated layers are ready to publish data.
+// The caller of this function can optionally decide to not consume these layers
+// if the availability change has the sequence number less than the last seen
+// sequence number.
+std::vector<VmsAssociatedLayer> getAvailableLayers(const VehiclePropValue& availability_state);
+
 }  // namespace vms
 }  // namespace V2_0
 }  // namespace vehicle
diff --git a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
index 9eba905..a65cded 100644
--- a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
@@ -219,12 +219,9 @@
     if (isValidVmsMessage(subscriptions_state) &&
         (parseMessageType(subscriptions_state) == VmsMessageType::SUBSCRIPTIONS_CHANGE ||
          parseMessageType(subscriptions_state) == VmsMessageType::SUBSCRIPTIONS_RESPONSE) &&
-        subscriptions_state.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex) {
-        const int32_t num_of_layers = subscriptions_state.value.int32Values[toInt(
-                VmsSubscriptionsStateIntegerValuesIndex::NUMBER_OF_LAYERS)];
-        const int32_t num_of_associated_layers = subscriptions_state.value.int32Values[toInt(
-                VmsSubscriptionsStateIntegerValuesIndex ::NUMBER_OF_ASSOCIATED_LAYERS)];
-
+        subscriptions_state.value.int32Values.size() >
+                toInt(VmsSubscriptionsStateIntegerValuesIndex::NUMBER_OF_LAYERS)) {
+        int subscriptions_state_int_size = subscriptions_state.value.int32Values.size();
         std::unordered_set<VmsLayer, VmsLayer::VmsLayerHashFunction> offered_layers;
         for (const auto& offer : offers.offerings) {
             offered_layers.insert(offer.layer);
@@ -232,33 +229,52 @@
         std::vector<VmsLayer> subscribed_layers;
 
         int current_index = toInt(VmsSubscriptionsStateIntegerValuesIndex::SUBSCRIPTIONS_START);
+
         // Add all subscribed layers which are offered by the current publisher.
+        const int32_t num_of_layers = subscriptions_state.value.int32Values[toInt(
+                VmsSubscriptionsStateIntegerValuesIndex::NUMBER_OF_LAYERS)];
         for (int i = 0; i < num_of_layers; i++) {
+            if (subscriptions_state_int_size < current_index + kLayerSize) {
+                return {};
+            }
             VmsLayer layer = VmsLayer(subscriptions_state.value.int32Values[current_index],
                                       subscriptions_state.value.int32Values[current_index + 1],
                                       subscriptions_state.value.int32Values[current_index + 2]);
             if (offered_layers.find(layer) != offered_layers.end()) {
-                subscribed_layers.push_back(layer);
+                subscribed_layers.push_back(std::move(layer));
             }
             current_index += kLayerSize;
         }
+
         // Add all subscribed associated layers which are offered by the current publisher.
         // For this, we need to check if the associated layer has a publisher ID which is
         // same as that of the current publisher.
-        for (int i = 0; i < num_of_associated_layers; i++) {
-            VmsLayer layer = VmsLayer(subscriptions_state.value.int32Values[current_index],
-                                      subscriptions_state.value.int32Values[current_index + 1],
-                                      subscriptions_state.value.int32Values[current_index + 2]);
-            current_index += kLayerSize;
-            if (offered_layers.find(layer) != offered_layers.end()) {
-                int32_t num_of_publisher_ids = subscriptions_state.value.int32Values[current_index];
-                current_index++;
-                for (int j = 0; j < num_of_publisher_ids; j++) {
-                    if (subscriptions_state.value.int32Values[current_index] ==
-                        offers.publisher_id) {
-                        subscribed_layers.push_back(layer);
-                    }
+        if (subscriptions_state_int_size >
+            toInt(VmsSubscriptionsStateIntegerValuesIndex::NUMBER_OF_ASSOCIATED_LAYERS)) {
+            const int32_t num_of_associated_layers = subscriptions_state.value.int32Values[toInt(
+                    VmsSubscriptionsStateIntegerValuesIndex::NUMBER_OF_ASSOCIATED_LAYERS)];
+
+            for (int i = 0; i < num_of_associated_layers; i++) {
+                if (subscriptions_state_int_size < current_index + kLayerSize) {
+                    return {};
+                }
+                VmsLayer layer = VmsLayer(subscriptions_state.value.int32Values[current_index],
+                                          subscriptions_state.value.int32Values[current_index + 1],
+                                          subscriptions_state.value.int32Values[current_index + 2]);
+                current_index += kLayerSize;
+                if (offered_layers.find(layer) != offered_layers.end() &&
+                    subscriptions_state_int_size > current_index) {
+                    int32_t num_of_publisher_ids =
+                            subscriptions_state.value.int32Values[current_index];
                     current_index++;
+                    for (int j = 0; j < num_of_publisher_ids; j++) {
+                        if (subscriptions_state_int_size > current_index &&
+                            subscriptions_state.value.int32Values[current_index] ==
+                                    offers.publisher_id) {
+                            subscribed_layers.push_back(std::move(layer));
+                        }
+                        current_index++;
+                    }
                 }
             }
         }
@@ -300,6 +316,64 @@
     return VmsSessionStatus::kInvalidMessage;
 }
 
+bool isAvailabilitySequenceNumberNewer(const VehiclePropValue& availability_state,
+                                       const int last_seen_availability_sequence_number) {
+    return (isValidVmsMessage(availability_state) &&
+            (parseMessageType(availability_state) == VmsMessageType::AVAILABILITY_CHANGE ||
+             parseMessageType(availability_state) == VmsMessageType::AVAILABILITY_RESPONSE) &&
+            availability_state.value.int32Values.size() > kAvailabilitySequenceNumberIndex &&
+            availability_state.value.int32Values[kAvailabilitySequenceNumberIndex] >
+                    last_seen_availability_sequence_number);
+}
+
+int32_t getSequenceNumberForAvailabilityState(const VehiclePropValue& availability_state) {
+    if (isValidVmsMessage(availability_state) &&
+        (parseMessageType(availability_state) == VmsMessageType::AVAILABILITY_CHANGE ||
+         parseMessageType(availability_state) == VmsMessageType::AVAILABILITY_RESPONSE) &&
+        availability_state.value.int32Values.size() > kAvailabilitySequenceNumberIndex) {
+        return availability_state.value.int32Values[kAvailabilitySequenceNumberIndex];
+    }
+    return -1;
+}
+
+std::vector<VmsAssociatedLayer> getAvailableLayers(const VehiclePropValue& availability_state) {
+    if (isValidVmsMessage(availability_state) &&
+        (parseMessageType(availability_state) == VmsMessageType::AVAILABILITY_CHANGE ||
+         parseMessageType(availability_state) == VmsMessageType::AVAILABILITY_RESPONSE) &&
+        availability_state.value.int32Values.size() >
+                toInt(VmsAvailabilityStateIntegerValuesIndex::NUMBER_OF_ASSOCIATED_LAYERS)) {
+        int availability_state_int_size = availability_state.value.int32Values.size();
+        const int32_t num_of_associated_layers = availability_state.value.int32Values[toInt(
+                VmsAvailabilityStateIntegerValuesIndex::NUMBER_OF_ASSOCIATED_LAYERS)];
+        int current_index = toInt(VmsAvailabilityStateIntegerValuesIndex::LAYERS_START);
+        std::vector<VmsAssociatedLayer> available_layers;
+        for (int i = 0; i < num_of_associated_layers; i++) {
+            if (availability_state_int_size < current_index + kLayerSize) {
+                return {};
+            }
+            VmsLayer layer = VmsLayer(availability_state.value.int32Values[current_index],
+                                      availability_state.value.int32Values[current_index + 1],
+                                      availability_state.value.int32Values[current_index + 2]);
+            current_index += kLayerSize;
+            std::vector<int> publisher_ids;
+            if (availability_state_int_size > current_index) {
+                int32_t num_of_publisher_ids = availability_state.value.int32Values[current_index];
+                current_index++;
+                for (int j = 0; j < num_of_publisher_ids; j++) {
+                    if (availability_state_int_size > current_index) {
+                        publisher_ids.push_back(
+                                availability_state.value.int32Values[current_index]);
+                        current_index++;
+                    }
+                }
+            }
+            available_layers.emplace_back(layer, std::move(publisher_ids));
+        }
+        return available_layers;
+    }
+    return {};
+}
+
 }  // namespace vms
 }  // namespace V2_0
 }  // namespace vehicle
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index f41b33c..2dbcbba 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -948,6 +948,24 @@
                     .access = VehiclePropertyAccess::READ_WRITE,
                     .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
          .initialValue = {.stringValue = "Vendor String Property"}},
+
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::SUPPORT_CUSTOMIZE_VENDOR_PERMISSION),
+                         .access = VehiclePropertyAccess::READ_WRITE,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                         .configArray =
+                                 {kMixedTypePropertyForTest,
+                                  (int)VehicleVendorPermission::PERMISSION_GET_VENDOR_CATEGORY_INFO,
+                                  (int)VehicleVendorPermission::PERMISSION_SET_VENDOR_CATEGORY_INFO,
+                                  VENDOR_EXTENSION_INT_PROPERTY,
+                                  (int)VehicleVendorPermission::PERMISSION_GET_VENDOR_CATEGORY_SEAT,
+                                  (int)VehicleVendorPermission::PERMISSION_NOT_ACCESSIBLE,
+                                  VENDOR_EXTENSION_FLOAT_PROPERTY,
+                                  (int)VehicleVendorPermission::PERMISSION_DEFAULT,
+                                  (int)VehicleVendorPermission::PERMISSION_DEFAULT},
+                 },
+         .initialValue = {.int32Values = {1}}},
 };
 
 }  // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
new file mode 100644
index 0000000..168999d
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
@@ -0,0 +1,254 @@
+/*
+ * 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 <android-base/logging.h>
+#include <utils/SystemClock.h>
+
+#include "DefaultConfig.h"
+#include "EmulatedVehicleConnector.h"
+#include "JsonFakeValueGenerator.h"
+#include "LinearFakeValueGenerator.h"
+#include "Obd2SensorStore.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+void EmulatedVehicleClient::onPropertyValue(const VehiclePropValue& value) {
+    if (!mPropCallback) {
+        LOG(ERROR) << __func__ << ": PropertyCallBackType is not registered!";
+        return;
+    }
+    return mPropCallback(value);
+}
+
+void EmulatedVehicleClient::registerPropertyValueCallback(PropertyCallBackType&& callback) {
+    if (mPropCallback) {
+        LOG(ERROR) << __func__ << ": Cannot register multiple callbacks!";
+        return;
+    }
+    mPropCallback = std::move(callback);
+}
+
+GeneratorHub* EmulatedVehicleServer::getGenerator() {
+    return &mGeneratorHub;
+}
+
+VehiclePropValuePool* EmulatedVehicleServer::getValuePool() const {
+    if (!mValuePool) {
+        LOG(WARNING) << __func__ << ": Value pool not set!";
+    }
+    return mValuePool;
+}
+
+void EmulatedVehicleServer::setValuePool(VehiclePropValuePool* valuePool) {
+    if (!valuePool) {
+        LOG(WARNING) <<  __func__ << ": Setting value pool to nullptr!";
+    }
+    mValuePool = valuePool;
+}
+
+void EmulatedVehicleServer::onFakeValueGenerated(const VehiclePropValue& value) {
+    LOG(DEBUG) << __func__ << ": " << toString(value);
+    auto updatedPropValue = getValuePool()->obtain(value);
+    if (updatedPropValue) {
+        updatedPropValue->timestamp = value.timestamp;
+        updatedPropValue->status = VehiclePropertyStatus::AVAILABLE;
+        onPropertyValueFromCar(*updatedPropValue);
+    }
+}
+
+std::vector<VehiclePropConfig> EmulatedVehicleServer::onGetAllPropertyConfig() const {
+    std::vector<VehiclePropConfig> vehiclePropConfigs;
+    constexpr size_t numOfVehiclePropConfigs =
+            sizeof(kVehicleProperties) / sizeof(kVehicleProperties[0]);
+    vehiclePropConfigs.reserve(numOfVehiclePropConfigs);
+    for (auto& it : kVehicleProperties) {
+        vehiclePropConfigs.emplace_back(it.config);
+    }
+    return vehiclePropConfigs;
+}
+
+StatusCode EmulatedVehicleServer::handleGenerateFakeDataRequest(const VehiclePropValue& request) {
+    LOG(INFO) << __func__;
+    const auto& v = request.value;
+    if (!v.int32Values.size()) {
+        LOG(ERROR) << __func__ << ": expected at least \"command\" field in int32Values";
+        return StatusCode::INVALID_ARG;
+    }
+
+    FakeDataCommand command = static_cast<FakeDataCommand>(v.int32Values[0]);
+
+    switch (command) {
+        case FakeDataCommand::StartLinear: {
+            LOG(INFO) << __func__ << ", FakeDataCommand::StartLinear";
+            if (v.int32Values.size() < 2) {
+                LOG(ERROR) << __func__ << ": expected property ID in int32Values";
+                return StatusCode::INVALID_ARG;
+            }
+            if (!v.int64Values.size()) {
+                LOG(ERROR) << __func__ << ": interval is not provided in int64Values";
+                return StatusCode::INVALID_ARG;
+            }
+            if (v.floatValues.size() < 3) {
+                LOG(ERROR) << __func__ << ": expected at least 3 elements in floatValues, got: "
+                      << v.floatValues.size();
+                return StatusCode::INVALID_ARG;
+            }
+            int32_t cookie = v.int32Values[1];
+            getGenerator()->registerGenerator(cookie,
+                                              std::make_unique<LinearFakeValueGenerator>(request));
+            break;
+        }
+        case FakeDataCommand::StartJson: {
+            LOG(INFO) << __func__ << ", FakeDataCommand::StartJson";
+            if (v.stringValue.empty()) {
+                LOG(ERROR) << __func__ << ": path to JSON file is missing";
+                return StatusCode::INVALID_ARG;
+            }
+            int32_t cookie = std::hash<std::string>()(v.stringValue);
+            getGenerator()->registerGenerator(cookie,
+                                              std::make_unique<JsonFakeValueGenerator>(request));
+            break;
+        }
+        case FakeDataCommand::StopLinear: {
+            LOG(INFO) << __func__ << ", FakeDataCommand::StopLinear";
+            if (v.int32Values.size() < 2) {
+                LOG(ERROR) << __func__ << ": expected property ID in int32Values";
+                return StatusCode::INVALID_ARG;
+            }
+            int32_t cookie = v.int32Values[1];
+            getGenerator()->unregisterGenerator(cookie);
+            break;
+        }
+        case FakeDataCommand::StopJson: {
+            LOG(INFO) << __func__ << ", FakeDataCommand::StopJson";
+            if (v.stringValue.empty()) {
+                LOG(ERROR) << __func__ << ": path to JSON file is missing";
+                return StatusCode::INVALID_ARG;
+            }
+            int32_t cookie = std::hash<std::string>()(v.stringValue);
+            getGenerator()->unregisterGenerator(cookie);
+            break;
+        }
+        case FakeDataCommand::KeyPress: {
+            LOG(INFO) << __func__ << ", FakeDataCommand::KeyPress";
+            int32_t keyCode = request.value.int32Values[2];
+            int32_t display = request.value.int32Values[3];
+            // Send back to HAL
+            onPropertyValueFromCar(
+                    *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display));
+            onPropertyValueFromCar(
+                    *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display));
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << ": unexpected command: " << toInt(command);
+            return StatusCode::INVALID_ARG;
+        }
+    }
+    return StatusCode::OK;
+}
+
+VehicleHal::VehiclePropValuePtr EmulatedVehicleServer::createApPowerStateReq(
+    VehicleApPowerStateReq state, int32_t param) {
+    auto req = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 2);
+    req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ);
+    req->areaId = 0;
+    req->timestamp = elapsedRealtimeNano();
+    req->status = VehiclePropertyStatus::AVAILABLE;
+    req->value.int32Values[0] = toInt(state);
+    req->value.int32Values[1] = param;
+    return req;
+}
+
+VehicleHal::VehiclePropValuePtr EmulatedVehicleServer::createHwInputKeyProp(
+        VehicleHwKeyInputAction action, int32_t keyCode, int32_t targetDisplay) {
+    auto keyEvent = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 3);
+    keyEvent->prop = toInt(VehicleProperty::HW_KEY_INPUT);
+    keyEvent->areaId = 0;
+    keyEvent->timestamp = elapsedRealtimeNano();
+    keyEvent->status = VehiclePropertyStatus::AVAILABLE;
+    keyEvent->value.int32Values[0] = toInt(action);
+    keyEvent->value.int32Values[1] = keyCode;
+    keyEvent->value.int32Values[2] = targetDisplay;
+    return keyEvent;
+}
+
+StatusCode EmulatedVehicleServer::onSetProperty(const VehiclePropValue& value) {
+    // Some properties need to be treated non-trivially
+    switch (value.prop) {
+        case AP_POWER_STATE_REPORT:
+            switch (value.value.int32Values[0]) {
+                case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT):
+                case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
+                case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
+                    // CPMS is in WAIT_FOR_VHAL state, simply move to ON
+                    // Send back to HAL
+                    onPropertyValueFromCar(
+                            *createApPowerStateReq(VehicleApPowerStateReq::ON, 0));
+                    break;
+                case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
+                case toInt(VehicleApPowerStateReport::SHUTDOWN_START):
+                    // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command
+                    // Send back to HAL
+                    onPropertyValueFromCar(
+                            *createApPowerStateReq(VehicleApPowerStateReq::FINISHED, 0));
+                    break;
+                case toInt(VehicleApPowerStateReport::ON):
+                case toInt(VehicleApPowerStateReport::SHUTDOWN_POSTPONE):
+                case toInt(VehicleApPowerStateReport::SHUTDOWN_PREPARE):
+                    // Do nothing
+                    break;
+                default:
+                    // Unknown state
+                    break;
+            }
+            break;
+        default:
+            break;
+    }
+
+    // In the real vhal, the value will be sent to Car ECU.
+    // We just pretend it is done here.
+    return StatusCode::OK;
+}
+
+StatusCode EmulatedVehicleServer::onSetPropertyFromVehicle(const VehiclePropValue& value) {
+    if (value.prop == kGenerateFakeDataControllingProperty) {
+        auto status = handleGenerateFakeDataRequest(value);
+        return status;
+    } else {
+        // Send back to HAL
+        onPropertyValueFromCar(value);
+        return StatusCode::OK;
+    }
+}
+
+EmulatedPassthroughConnectorPtr makeEmulatedPassthroughConnector() {
+    return std::make_unique<EmulatedPassthroughConnector>();
+}
+
+}  // namespace impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
new file mode 100644
index 0000000..d424cd8
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
@@ -0,0 +1,110 @@
+/*
+ * 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_automotive_vehicle_V2_0_impl_EmulatedVehicleConnector_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleConnector_H_
+
+#include <vhal_v2_0/VehicleConnector.h>
+#include <vhal_v2_0/VehicleHal.h>
+
+#include "GeneratorHub.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+// Extension of the client/server interfaces for emulated vehicle
+
+class EmulatedVehicleClient : public IVehicleClient {
+  public:
+    // Type of callback function for handling the new property values
+    using PropertyCallBackType = std::function<void(const VehiclePropValue&)>;
+
+    // Method from IVehicleClient
+    void onPropertyValue(const VehiclePropValue& value) override;
+
+    // Request to change the value on the VEHICLE side (for testing)
+    virtual StatusCode setPropertyFromVehicle(const VehiclePropValue& value) = 0;
+
+    void registerPropertyValueCallback(PropertyCallBackType&& callback);
+
+  private:
+    PropertyCallBackType mPropCallback;
+};
+
+class EmulatedVehicleServer : public IVehicleServer {
+  public:
+    // Methods from IVehicleServer
+
+    std::vector<VehiclePropConfig> onGetAllPropertyConfig() const override;
+
+    StatusCode onSetProperty(const VehiclePropValue& value) override;
+
+    // Process the request to change the value on the VEHICLE side (for testing)
+    StatusCode onSetPropertyFromVehicle(const VehiclePropValue& value);
+
+    // Set the Property Value Pool used in this server
+    void setValuePool(VehiclePropValuePool* valuePool);
+
+  private:
+    GeneratorHub* getGenerator();
+
+    VehiclePropValuePool* getValuePool() const;
+
+    void onFakeValueGenerated(const VehiclePropValue& value);
+
+    StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
+
+    VehicleHal::VehiclePropValuePtr createApPowerStateReq(VehicleApPowerStateReq req, int32_t param);
+
+    VehicleHal::VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action,
+                                                         int32_t keyCode, int32_t targetDisplay);
+
+    // private data members
+
+    GeneratorHub mGeneratorHub{
+            std::bind(&EmulatedVehicleServer::onFakeValueGenerated, this, std::placeholders::_1)};
+
+    VehiclePropValuePool* mValuePool{nullptr};
+};
+
+class EmulatedPassthroughConnector
+    : public IPassThroughConnector<EmulatedVehicleClient, EmulatedVehicleServer> {
+  public:
+    StatusCode setPropertyFromVehicle(const VehiclePropValue& value) override {
+        return this->onSetPropertyFromVehicle(value);
+    }
+};
+
+// Helper functions
+
+using EmulatedPassthroughConnectorPtr = std::unique_ptr<EmulatedPassthroughConnector>;
+
+EmulatedPassthroughConnectorPtr makeEmulatedPassthroughConnector();
+
+}  // namespace impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleConnector_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
index dc051d8..6508efe 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -87,17 +87,19 @@
     return sensorStore;
 }
 
-EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore)
+EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore,
+                                       EmulatedVehicleClient* client)
     : mPropStore(propStore),
       mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)),
       mRecurrentTimer(
           std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this, std::placeholders::_1)),
-      mGeneratorHub(
-          std::bind(&EmulatedVehicleHal::onFakeValueGenerated, this, std::placeholders::_1)) {
+      mVehicleClient(client) {
     initStaticConfig();
     for (size_t i = 0; i < arraysize(kVehicleProperties); i++) {
         mPropStore->registerProperty(kVehicleProperties[i].config);
     }
+    mVehicleClient->registerPropertyValueCallback(
+        std::bind(&EmulatedVehicleHal::onPropertyValue, this, std::placeholders::_1));
 }
 
 VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
@@ -162,7 +164,8 @@
     }
 
     if (propValue.prop == kGenerateFakeDataControllingProperty) {
-        StatusCode status = handleGenerateFakeDataRequest(propValue);
+        // send the generator controlling request to the server
+        auto status = mVehicleClient->setPropertyFromVehicle(propValue);
         if (status != StatusCode::OK) {
             return status;
         }
@@ -186,29 +189,6 @@
                 // Placeholder for future implementation of VMS property in the default hal. For
                 // now, just returns OK; otherwise, hal clients crash with property not supported.
                 return StatusCode::OK;
-            case AP_POWER_STATE_REPORT:
-                switch (propValue.value.int32Values[0]) {
-                    case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT):
-                    case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
-                    case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
-                        // CPMS is in WAIT_FOR_VHAL state, simply move to ON
-                        doHalEvent(createApPowerStateReq(VehicleApPowerStateReq::ON, 0));
-                        break;
-                    case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
-                    case toInt(VehicleApPowerStateReport::SHUTDOWN_START):
-                        // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command
-                        doHalEvent(createApPowerStateReq(VehicleApPowerStateReq::FINISHED, 0));
-                        break;
-                    case toInt(VehicleApPowerStateReport::ON):
-                    case toInt(VehicleApPowerStateReport::SHUTDOWN_POSTPONE):
-                    case toInt(VehicleApPowerStateReport::SHUTDOWN_PREPARE):
-                        // Do nothing
-                        break;
-                    default:
-                        // Unknown state
-                        break;
-                }
-                break;
         }
     }
 
@@ -231,10 +211,16 @@
     /**
      * After checking all conditions, such as the property is available, a real vhal will
      * sent the events to Car ECU to take actions.
-     * Google HAL will just add a timestamp for the value and triggle the callback to android.
      */
     VehiclePropValuePtr updatedPropValue = getValuePool()->obtain(propValue);
     updatedPropValue->timestamp = elapsedRealtimeNano();
+
+    // Send the value to the vehicle server, the server will talk to the (real or emulated) car
+    auto setValueStatus = mVehicleClient->setProperty(*updatedPropValue);
+    if (setValueStatus != StatusCode::OK) {
+        return setValueStatus;
+    }
+
     if (!mPropStore->writeValue(*updatedPropValue, shouldUpdateStatus)) {
         return StatusCode::INTERNAL_ERROR;
     }
@@ -361,144 +347,19 @@
 }
 
 bool EmulatedVehicleHal::setPropertyFromVehicle(const VehiclePropValue& propValue) {
-    static constexpr bool shouldUpdateStatus = true;
-
-    if (propValue.prop == kGenerateFakeDataControllingProperty) {
-        StatusCode status = handleGenerateFakeDataRequest(propValue);
-        if (status != StatusCode::OK) {
-            return false;
-        }
-    }
-
-    if (mPropStore->writeValue(propValue, shouldUpdateStatus)) {
-        doHalEvent(getValuePool()->obtain(propValue));
-        return true;
-    } else {
-        return false;
-    }
+    return mVehicleClient->setPropertyFromVehicle(propValue) == StatusCode::OK;
 }
 
 std::vector<VehiclePropValue> EmulatedVehicleHal::getAllProperties() const  {
     return mPropStore->readAllValues();
 }
 
-StatusCode EmulatedVehicleHal::handleGenerateFakeDataRequest(const VehiclePropValue& request) {
-    ALOGI("%s", __func__);
-    const auto& v = request.value;
-    if (!v.int32Values.size()) {
-        ALOGE("%s: expected at least \"command\" field in int32Values", __func__);
-        return StatusCode::INVALID_ARG;
-    }
-
-    FakeDataCommand command = static_cast<FakeDataCommand>(v.int32Values[0]);
-
-    switch (command) {
-        case FakeDataCommand::StartLinear: {
-            ALOGI("%s, FakeDataCommand::StartLinear", __func__);
-            if (v.int32Values.size() < 2) {
-                ALOGE("%s: expected property ID in int32Values", __func__);
-                return StatusCode::INVALID_ARG;
-            }
-            if (!v.int64Values.size()) {
-                ALOGE("%s: interval is not provided in int64Values", __func__);
-                return StatusCode::INVALID_ARG;
-            }
-            if (v.floatValues.size() < 3) {
-                ALOGE("%s: expected at least 3 elements in floatValues, got: %zu", __func__,
-                      v.floatValues.size());
-                return StatusCode::INVALID_ARG;
-            }
-            int32_t cookie = v.int32Values[1];
-            mGeneratorHub.registerGenerator(cookie,
-                                            std::make_unique<LinearFakeValueGenerator>(request));
-            break;
-        }
-        case FakeDataCommand::StartJson: {
-            ALOGI("%s, FakeDataCommand::StartJson", __func__);
-            if (v.stringValue.empty()) {
-                ALOGE("%s: path to JSON file is missing", __func__);
-                return StatusCode::INVALID_ARG;
-            }
-            int32_t cookie = std::hash<std::string>()(v.stringValue);
-            mGeneratorHub.registerGenerator(cookie,
-                                            std::make_unique<JsonFakeValueGenerator>(request));
-            break;
-        }
-        case FakeDataCommand::StopLinear: {
-            ALOGI("%s, FakeDataCommand::StopLinear", __func__);
-            if (v.int32Values.size() < 2) {
-                ALOGE("%s: expected property ID in int32Values", __func__);
-                return StatusCode::INVALID_ARG;
-            }
-            int32_t cookie = v.int32Values[1];
-            mGeneratorHub.unregisterGenerator(cookie);
-            break;
-        }
-        case FakeDataCommand::StopJson: {
-            ALOGI("%s, FakeDataCommand::StopJson", __func__);
-            if (v.stringValue.empty()) {
-                ALOGE("%s: path to JSON file is missing", __func__);
-                return StatusCode::INVALID_ARG;
-            }
-            int32_t cookie = std::hash<std::string>()(v.stringValue);
-            mGeneratorHub.unregisterGenerator(cookie);
-            break;
-        }
-        case FakeDataCommand::KeyPress: {
-            ALOGI("%s, FakeDataCommand::KeyPress", __func__);
-            int32_t keyCode = request.value.int32Values[2];
-            int32_t display = request.value.int32Values[3];
-            doHalEvent(
-                createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display));
-            doHalEvent(createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display));
-            break;
-        }
-        default: {
-            ALOGE("%s: unexpected command: %d", __func__, command);
-            return StatusCode::INVALID_ARG;
-        }
-    }
-    return StatusCode::OK;
-}
-
-VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::createApPowerStateReq(
-    VehicleApPowerStateReq state, int32_t param) {
-    auto req = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 2);
-    req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ);
-    req->areaId = 0;
-    req->timestamp = elapsedRealtimeNano();
-    req->status = VehiclePropertyStatus::AVAILABLE;
-    req->value.int32Values[0] = toInt(state);
-    req->value.int32Values[1] = param;
-    return req;
-}
-
-VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::createHwInputKeyProp(
-    VehicleHwKeyInputAction action, int32_t keyCode, int32_t targetDisplay) {
-    auto keyEvent = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 3);
-    keyEvent->prop = toInt(VehicleProperty::HW_KEY_INPUT);
-    keyEvent->areaId = 0;
-    keyEvent->timestamp = elapsedRealtimeNano();
-    keyEvent->status = VehiclePropertyStatus::AVAILABLE;
-    keyEvent->value.int32Values[0] = toInt(action);
-    keyEvent->value.int32Values[1] = keyCode;
-    keyEvent->value.int32Values[2] = targetDisplay;
-    return keyEvent;
-}
-
-void EmulatedVehicleHal::onFakeValueGenerated(const VehiclePropValue& value) {
-    ALOGD("%s: %s", __func__, toString(value).c_str());
-    static constexpr bool shouldUpdateStatus = false;
-
+void EmulatedVehicleHal::onPropertyValue(const VehiclePropValue& value) {
+    static constexpr bool shouldUpdateStatus = true;
     VehiclePropValuePtr updatedPropValue = getValuePool()->obtain(value);
-    if (updatedPropValue) {
-        updatedPropValue->timestamp = value.timestamp;
-        updatedPropValue->status = VehiclePropertyStatus::AVAILABLE;
-        mPropStore->writeValue(*updatedPropValue, shouldUpdateStatus);
-        auto changeMode = mPropStore->getConfigOrDie(value.prop)->changeMode;
-        if (VehiclePropertyChangeMode::ON_CHANGE == changeMode) {
-            doHalEvent(std::move(updatedPropValue));
-        }
+
+    if (mPropStore->writeValue(*updatedPropValue, shouldUpdateStatus)) {
+        doHalEvent(std::move(updatedPropValue));
     }
 }
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index 78895e3..98315ec 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -30,6 +30,7 @@
 #include "vhal_v2_0/VehiclePropertyStore.h"
 
 #include "DefaultConfig.h"
+#include "EmulatedVehicleConnector.h"
 #include "GeneratorHub.h"
 #include "VehicleEmulator.h"
 
@@ -44,7 +45,8 @@
 /** Implementation of VehicleHal that connected to emulator instead of real vehicle network. */
 class EmulatedVehicleHal : public EmulatedVehicleHalIface {
 public:
-    EmulatedVehicleHal(VehiclePropertyStore* propStore);
+    EmulatedVehicleHal(VehiclePropertyStore* propStore,
+                       EmulatedVehicleClient* client);
     ~EmulatedVehicleHal() = default;
 
     //  Methods from VehicleHal
@@ -66,10 +68,7 @@
     }
 
     StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
-    void onFakeValueGenerated(const VehiclePropValue& value);
-    VehiclePropValuePtr createApPowerStateReq(VehicleApPowerStateReq req, int32_t param);
-    VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode,
-                                             int32_t targetDisplay);
+    void onPropertyValue(const VehiclePropValue& value);
 
     void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
     bool isContinuousProperty(int32_t propId) const;
@@ -85,7 +84,7 @@
     VehiclePropertyStore* mPropStore;
     std::unordered_set<int32_t> mHvacPowerProps;
     RecurrentTimer mRecurrentTimer;
-    GeneratorHub mGeneratorHub;
+    EmulatedVehicleClient* mVehicleClient;
 };
 
 }  // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
index 6754843..2eedecd 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
@@ -29,3 +29,64 @@
     ],
     srcs: ["VehicleHalProto.proto"]
 }
+
+cc_library_static {
+    name: "android.hardware.automotive.vehicle@2.0-grpc",
+    vendor: true,
+    include_dirs: [
+        "external/protobuf/src",
+    ],
+    generated_headers: [
+        "DefaultVehicleHalProtoStub_h",
+    ],
+    export_generated_headers: [
+        "DefaultVehicleHalProtoStub_h",
+    ],
+    generated_sources: [
+        "DefaultVehicleHalProtoStub_cc",
+    ],
+    shared_libs: [
+        "libgrpc++_unsecure",
+    ],
+    cflags: [
+        "-Wno-unused-parameter"
+    ],
+}
+
+genrule {
+    name: "DefaultVehicleHalProtoStub_h",
+    tools: [
+        "aprotoc",
+        "protoc-gen-grpc-cpp-plugin",
+    ],
+    cmd: "$(location aprotoc) -I$$(dirname $(in)) -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
+    srcs: [
+        "VehicleHalProto.proto",
+        "VehicleServer.proto",
+    ],
+    out: [
+        "VehicleHalProto.pb.h",
+        "VehicleHalProto.grpc.pb.h",
+        "VehicleServer.pb.h",
+        "VehicleServer.grpc.pb.h",
+    ],
+}
+
+genrule {
+    name: "DefaultVehicleHalProtoStub_cc",
+    tools: [
+        "aprotoc",
+        "protoc-gen-grpc-cpp-plugin",
+    ],
+    cmd: "$(location aprotoc) -I$$(dirname $(in)) -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
+    srcs: [
+        "VehicleHalProto.proto",
+        "VehicleServer.proto",
+    ],
+    out: [
+        "VehicleHalProto.pb.cc",
+        "VehicleHalProto.grpc.pb.cc",
+        "VehicleServer.pb.cc",
+        "VehicleServer.grpc.pb.cc",
+    ],
+}
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto
index 2ef64fb..04df5a8 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto
@@ -15,7 +15,6 @@
  */
 
 syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
 
 package emulator;
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleServer.proto b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleServer.proto
new file mode 100644
index 0000000..7ce3c32
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleServer.proto
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+package emulator;
+
+import "google/protobuf/empty.proto";
+import "VehicleHalProto.proto";
+
+// correspond to StatusCode defined in types.hal
+enum VehicleHalStatusCode {
+    OK                                  = 0;
+    TRY_AGAIN                           = 1;
+    INVALID_ARG                         = 2;
+    NOT_AVAILABLE                       = 3;
+    ACCESS_DENIED                       = 4;
+    INTERNAL_ERROR                      = 5;
+}
+
+message VehicleHalCallStatus {
+    required VehicleHalStatusCode status_code      = 1;
+}
+
+service VehicleServer {
+    rpc GetAllPropertyConfig(google.protobuf.Empty) returns (stream VehiclePropConfig) {}
+
+    // Change the property value of the vehicle
+    rpc SetProperty(VehiclePropValue) returns (VehicleHalCallStatus) {}
+
+    // Start a vehicle property value stream
+    rpc StartPropertyValuesStream(google.protobuf.Empty) returns (stream VehiclePropValue) {}
+}
+
diff --git a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
index 8b547f1..a48d19c 100644
--- a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
@@ -279,7 +279,7 @@
     VmsOffers offers = {123,
                         {VmsLayerOffering(VmsLayer(1, 0, 1), {VmsLayer(4, 1, 1)}),
                          VmsLayerOffering(VmsLayer(2, 0, 1))}};
-    auto message = createBaseVmsMessage(2);
+    auto message = createBaseVmsMessage(16);
     message->value.int32Values = hidl_vec<int32_t>{toInt(type),
                                                    1234,  // sequence number
                                                    2,     // number of layers
@@ -308,9 +308,28 @@
     testSubscribedLayers(VmsMessageType::SUBSCRIPTIONS_RESPONSE);
 }
 
+void testGetSubscribedLayersMalformedData(VmsMessageType type) {
+    VmsOffers offers = {123,
+                        {VmsLayerOffering(VmsLayer(1, 0, 1), {VmsLayer(4, 1, 1)}),
+                         VmsLayerOffering(VmsLayer(2, 0, 1))}};
+    auto message = createBaseVmsMessage(2);
+    message->value.int32Values = hidl_vec<int32_t>{toInt(type), 1234};  // sequence number
+    EXPECT_TRUE(isValidVmsMessage(*message));
+    auto result = getSubscribedLayers(*message, offers);
+    EXPECT_EQ(static_cast<int>(result.size()), 0);
+}
+
+TEST(VmsUtilsTest, subscribedLayersForMalformedChange) {
+    testGetSubscribedLayersMalformedData(VmsMessageType::SUBSCRIPTIONS_CHANGE);
+}
+
+TEST(VmsUtilsTest, subscribedLayersForMalformedResponse) {
+    testGetSubscribedLayersMalformedData(VmsMessageType::SUBSCRIPTIONS_RESPONSE);
+}
+
 void testSubscribedLayersWithDifferentSubtype(VmsMessageType type) {
     VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}};
-    auto message = createBaseVmsMessage(2);
+    auto message = createBaseVmsMessage(7);
     message->value.int32Values = hidl_vec<int32_t>{toInt(type),
                                                    1234,  // sequence number
                                                    1,     // number of layers
@@ -332,7 +351,7 @@
 
 void subscribedLayersWithDifferentVersion(VmsMessageType type) {
     VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}};
-    auto message = createBaseVmsMessage(2);
+    auto message = createBaseVmsMessage(7);
     message->value.int32Values = hidl_vec<int32_t>{toInt(type),
                                                    1234,             // sequence number
                                                    1,                // number of layers
@@ -353,7 +372,7 @@
 
 void subscribedLayersWithDifferentPublisherId(VmsMessageType type) {
     VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}};
-    auto message = createBaseVmsMessage(2);
+    auto message = createBaseVmsMessage(9);
     message->value.int32Values = hidl_vec<int32_t>{toInt(type),
                                                    1234,  // sequence number
                                                    0,     // number of layers
@@ -475,6 +494,113 @@
     EXPECT_EQ(new_service_id, 123);
 }
 
+TEST(VmsUtilsTest, newAvailabilitySequenceNumberForExistingSmallerNumberForChange) {
+    auto message = createBaseVmsMessage(2);
+    message->value.int32Values =
+            hidl_vec<int32_t>{toInt(VmsMessageType::AVAILABILITY_CHANGE), 1234};
+    EXPECT_TRUE(isAvailabilitySequenceNumberNewer(*message, 1233));
+}
+
+TEST(VmsUtilsTest, newAvailabilitySequenceNumberForExistingSmallerNumberForResponse) {
+    auto message = createBaseVmsMessage(2);
+    message->value.int32Values =
+            hidl_vec<int32_t>{toInt(VmsMessageType::AVAILABILITY_RESPONSE), 1234};
+    EXPECT_TRUE(isAvailabilitySequenceNumberNewer(*message, 1233));
+}
+
+TEST(VmsUtilsTest, newAvailabilitySequenceNumberForExistingGreaterNumberForChange) {
+    auto message = createBaseVmsMessage(2);
+    message->value.int32Values =
+            hidl_vec<int32_t>{toInt(VmsMessageType::AVAILABILITY_CHANGE), 1234};
+    EXPECT_FALSE(isAvailabilitySequenceNumberNewer(*message, 1235));
+}
+
+TEST(VmsUtilsTest, newAvailabilitySequenceNumberForExistingGreaterNumberForResponse) {
+    auto message = createBaseVmsMessage(2);
+    message->value.int32Values =
+            hidl_vec<int32_t>{toInt(VmsMessageType::AVAILABILITY_RESPONSE), 1234};
+    EXPECT_FALSE(isAvailabilitySequenceNumberNewer(*message, 1235));
+}
+
+TEST(VmsUtilsTest, newAvailabilitySequenceNumberForSameNumberForChange) {
+    auto message = createBaseVmsMessage(2);
+    message->value.int32Values =
+            hidl_vec<int32_t>{toInt(VmsMessageType::AVAILABILITY_CHANGE), 1234};
+    EXPECT_FALSE(isAvailabilitySequenceNumberNewer(*message, 1234));
+}
+
+TEST(VmsUtilsTest, newAvailabilitySequenceNumberForSameNumberForResponse) {
+    auto message = createBaseVmsMessage(2);
+    message->value.int32Values =
+            hidl_vec<int32_t>{toInt(VmsMessageType::AVAILABILITY_RESPONSE), 1234};
+    EXPECT_FALSE(isAvailabilitySequenceNumberNewer(*message, 1234));
+}
+
+TEST(VmsUtilsTest, validSequenceNumberForAvailabilityChange) {
+    auto message = createBaseVmsMessage(2);
+    message->value.int32Values =
+            hidl_vec<int32_t>{toInt(VmsMessageType::AVAILABILITY_CHANGE), 1234};
+    EXPECT_EQ(getSequenceNumberForAvailabilityState(*message), 1234);
+}
+
+TEST(VmsUtilsTest, validSequenceNumberForAvailabilityResponse) {
+    auto message = createBaseVmsMessage(2);
+    message->value.int32Values =
+            hidl_vec<int32_t>{toInt(VmsMessageType::AVAILABILITY_RESPONSE), 1234};
+    EXPECT_EQ(getSequenceNumberForAvailabilityState(*message), 1234);
+}
+
+TEST(VmsUtilsTest, invalidAvailabilityState) {
+    auto message = createBaseVmsMessage(1);
+    EXPECT_EQ(getSequenceNumberForAvailabilityState(*message), -1);
+}
+
+void testGetAvailableLayers(VmsMessageType type) {
+    auto message = createBaseVmsMessage(13);
+    message->value.int32Values = hidl_vec<int32_t>{toInt(type),
+                                                   1234,  // sequence number
+                                                   2,     // number of associated layers
+                                                   1,     // associated layer 1
+                                                   0,           1,
+                                                   2,    // number of publisher IDs
+                                                   111,  // publisher IDs
+                                                   123,
+                                                   2,                   // associated layer 2
+                                                   0,           1, 0};  // number of publisher IDs
+    EXPECT_TRUE(isValidVmsMessage(*message));
+    auto result = getAvailableLayers(*message);
+    EXPECT_EQ(static_cast<int>(result.size()), 2);
+    EXPECT_EQ(result.at(0).layer, VmsLayer(1, 0, 1));
+    EXPECT_EQ(result.at(0).publisher_ids.at(0), 111);
+    EXPECT_EQ(result.at(0).publisher_ids.at(1), 123);
+    EXPECT_EQ(result.at(1).layer, VmsLayer(2, 0, 1));
+    EXPECT_EQ(static_cast<int>(result.at(1).publisher_ids.size()), 0);
+}
+
+TEST(VmsUtilsTest, availableLayersForChange) {
+    testGetAvailableLayers(VmsMessageType::AVAILABILITY_CHANGE);
+}
+
+TEST(VmsUtilsTest, availableLayersForResponse) {
+    testGetAvailableLayers(VmsMessageType::AVAILABILITY_RESPONSE);
+}
+
+void testGetAvailableLayersMalformedData(VmsMessageType type) {
+    auto message = createBaseVmsMessage(2);
+    message->value.int32Values = hidl_vec<int32_t>{toInt(type), 1234};  // sequence number
+    EXPECT_TRUE(isValidVmsMessage(*message));
+    auto result = getAvailableLayers(*message);
+    EXPECT_EQ(static_cast<int>(result.size()), 0);
+}
+
+TEST(VmsUtilsTest, availableLayersForMalformedChange) {
+    testGetAvailableLayersMalformedData(VmsMessageType::AVAILABILITY_CHANGE);
+}
+
+TEST(VmsUtilsTest, availableLayersForMalformedResponse) {
+    testGetAvailableLayersMalformedData(VmsMessageType::AVAILABILITY_RESPONSE);
+}
+
 }  // namespace
 
 }  // namespace vms
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index bc0b4d3..24fcf76 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -2349,6 +2349,116 @@
         | VehiclePropertyType:INT32
         | VehicleArea:SEAT),
 
+    /**
+     * Support customize permissions for vendor properties
+     *
+     * Implement this property if vehicle hal support customize vendor permissions feature.
+     * VehiclePropConfig.configArray is used to indicate vendor properties and permissions
+     * which selected for this vendor property. The permission must be one of enum in
+     * VehicleVendorPermission.
+     * The configArray is set as follows:
+     *      configArray[n] = propId : property ID for the vendor property
+     *      configArray[n+1] = one of enums in VehicleVendorPermission. It indicates the permission
+     *      for reading value of the property.
+     *      configArray[n+2] = one of enums in VehicleVendorPermission. It indicates the permission
+     *      for writing value of the property.
+     *
+     * For example:
+     * configArray = {
+     *      vendor_prop_1, PERMISSION_VENDOR_SEAT_READ, PERMISSION_VENDOR_SEAT_WRITE,
+     *      vendor_prop_2, PERMISSION_VENDOR_INFO, PERMISSION_NOT_ACCESSIBLE,
+     * }
+     * If vendor properties are not in this array, they will have the default vendor permission.
+     * If vendor chose PERMISSION_NOT_ACCESSIBLE, android will not have access to the property. In
+     * the example, Android can not write value for vendor_prop_2.
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     */
+    SUPPORT_CUSTOMIZE_VENDOR_PERMISSION = (
+        0x0F05
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Allow disabling optional featurs from vhal.
+     *
+     * This property reports optional features that should be disabled.
+     * All allowed optional features for the system is declared in Car service overlay,
+     * config_allowed_optional_car_features.
+     * This property allows disabling features defined in the overlay. Without this property,
+     * all the features declared in the overlay will be enabled.
+     *
+     * Value read should include all features disabled with ',' separation.
+     * ex) "com.android.car.user.CarUserNoticeService,storage_monitoring"
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     */
+    DISABLED_OPTIONAL_FEATURES = (
+        0x0F06
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:STRING
+        | VehicleArea:GLOBAL),
+
+};
+
+/**
+ * Used by SUPPORT_CUSTOMIZE_VENDOR_PERMISSION to indicate the permission of vendor properties.
+ */
+enum VehicleVendorPermission : int32_t {
+    PERMISSION_DEFAULT = 0x00000000,
+
+    // permissions for the property related with window
+    PERMISSION_SET_VENDOR_CATEGORY_WINDOW= 0X00000001,
+    PERMISSION_GET_VENDOR_CATEGORY_WINDOW = 0x00000002,
+    // permissions for the property related with door
+    PERMISSION_SET_VENDOR_CATEGORY_DOOR  = 0x00000003,
+    PERMISSION_GET_VENDOR_CATEGORY_DOOR   = 0x00000004,
+    // permissions for the property related with seat
+    PERMISSION_SET_VENDOR_CATEGORY_SEAT  = 0x00000005,
+    PERMISSION_GET_VENDOR_CATEGORY_SEAT   = 0x00000006,
+    // permissions for the property related with mirror
+    PERMISSION_SET_VENDOR_CATEGORY_MIRROR= 0x00000007,
+    PERMISSION_GET_VENDOR_CATEGORY_MIRROR = 0x00000008,
+
+    // permissions for the property related with car's information
+    PERMISSION_SET_VENDOR_CATEGORY_INFO  = 0x00000009,
+    PERMISSION_GET_VENDOR_CATEGORY_INFO   = 0x0000000A,
+    // permissions for the property related with car's engine
+    PERMISSION_SET_VENDOR_CATEGORY_ENGINE= 0x0000000B,
+    PERMISSION_GET_VENDOR_CATEGORY_ENGINE = 0x0000000C,
+    // permissions for the property related with car's HVAC
+    PERMISSION_SET_VENDOR_CATEGORY_HVAC  = 0x0000000D,
+    PERMISSION_GET_VENDOR_CATEGORY_HVAC   = 0x0000000E,
+    // permissions for the property related with car's light
+    PERMISSION_SET_VENDOR_CATEGORY_LIGHT = 0x0000000F,
+    PERMISSION_GET_VENDOR_CATEGORY_LIGHT  = 0x00000010,
+
+    // permissions reserved for other vendor permission
+    PERMISSION_SET_VENDOR_CATEGORY_1  = 0x00010000,
+    PERMISSION_GET_VENDOR_CATEGORY_1   = 0x00011000,
+    PERMISSION_SET_VENDOR_CATEGORY_2  = 0x00020000,
+    PERMISSION_GET_VENDOR_CATEGORY_2   = 0x00021000,
+    PERMISSION_SET_VENDOR_CATEGORY_3  = 0x00030000,
+    PERMISSION_GET_VENDOR_CATEGORY_3   = 0x00031000,
+    PERMISSION_SET_VENDOR_CATEGORY_4  = 0x00040000,
+    PERMISSION_GET_VENDOR_CATEGORY_4   = 0x00041000,
+    PERMISSION_SET_VENDOR_CATEGORY_5  = 0x00050000,
+    PERMISSION_GET_VENDOR_CATEGORY_5   = 0x00051000,
+    PERMISSION_SET_VENDOR_CATEGORY_6  = 0x00060000,
+    PERMISSION_GET_VENDOR_CATEGORY_6   = 0x00061000,
+    PERMISSION_SET_VENDOR_CATEGORY_7  = 0x00070000,
+    PERMISSION_GET_VENDOR_CATEGORY_7   = 0x00071000,
+    PERMISSION_SET_VENDOR_CATEGORY_8  = 0x00080000,
+    PERMISSION_GET_VENDOR_CATEGORY_8   = 0x00081000,
+    PERMISSION_SET_VENDOR_CATEGORY_9  = 0x00090000,
+    PERMISSION_GET_VENDOR_CATEGORY_9   = 0x00091000,
+    PERMISSION_SET_VENDOR_CATEGORY_10 = 0x000A0000,
+    PERMISSION_GET_VENDOR_CATEGORY_10  = 0x000A1000,
+
+    // Indicate not available for android to access.
+    PERMISSION_NOT_ACCESSIBLE = 0xF0000000
 };
 
 /**
diff --git a/biometrics/face/1.0/vts/functional/Android.bp b/biometrics/face/1.0/vts/functional/Android.bp
index fa68c4e..f2598a7 100644
--- a/biometrics/face/1.0/vts/functional/Android.bp
+++ b/biometrics/face/1.0/vts/functional/Android.bp
@@ -19,6 +19,6 @@
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalBiometricsFaceV1_0TargetTest.cpp"],
     static_libs: ["android.hardware.biometrics.face@1.0"],
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "vts-core"],
 }
 
diff --git a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
index a4e95ed..7ac44a4 100644
--- a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
+++ b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
@@ -20,9 +20,10 @@
 #include <android/hardware/biometrics/face/1.0/IBiometricsFaceClientCallback.h>
 
 #include <VtsHalHidlTargetCallbackBase.h>
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
 #include <android-base/logging.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include <chrono>
 #include <cstdint>
@@ -124,27 +125,11 @@
     }
 };
 
-// Test environment for the BiometricsFace HAL.
-class FaceHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-  public:
-    // Get the test environment singleton.
-    static FaceHidlEnvironment* Instance() {
-        static FaceHidlEnvironment* instance = new FaceHidlEnvironment;
-        return instance;
-    }
-
-    void registerTestServices() override { registerTestService<IBiometricsFace>(); }
-
-  private:
-    FaceHidlEnvironment() = default;
-};
-
 // Test class for the BiometricsFace HAL.
-class FaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class FaceHidlTest : public ::testing::TestWithParam<std::string> {
   public:
     void SetUp() override {
-        mService = ::testing::VtsHalHidlTargetTestBase::getService<IBiometricsFace>(
-                FaceHidlEnvironment::Instance()->getServiceName<IBiometricsFace>());
+        mService = IBiometricsFace::getService(GetParam());
         ASSERT_NE(mService, nullptr);
         mCallback = new FaceCallback();
         mCallback->SetWaitTimeoutDefault(kTimeout);
@@ -167,7 +152,7 @@
 
 // generateChallenge should always return a unique, cryptographically secure,
 // non-zero number.
-TEST_F(FaceHidlTest, GenerateChallengeTest) {
+TEST_P(FaceHidlTest, GenerateChallengeTest) {
     std::map<uint64_t, int> m;
     for (int i = 0; i < kGenerateChallengeIterations; ++i) {
         Return<void> ret =
@@ -182,7 +167,7 @@
 }
 
 // enroll with an invalid (all zeroes) HAT should fail.
-TEST_F(FaceHidlTest, EnrollZeroHatTest) {
+TEST_P(FaceHidlTest, EnrollZeroHatTest) {
     // Filling HAT with zeros
     hidl_vec<uint8_t> token(69);
     for (size_t i = 0; i < 69; i++) {
@@ -200,7 +185,7 @@
 }
 
 // enroll with an invalid HAT should fail.
-TEST_F(FaceHidlTest, EnrollGarbageHatTest) {
+TEST_P(FaceHidlTest, EnrollGarbageHatTest) {
     // Filling HAT with pseudorandom invalid data.
     // Using default seed to make the test reproducible.
     std::mt19937 gen(std::mt19937::default_seed);
@@ -221,7 +206,7 @@
 }
 
 // setFeature with an invalid (all zeros) HAT should fail.
-TEST_F(FaceHidlTest, SetFeatureZeroHatTest) {
+TEST_P(FaceHidlTest, SetFeatureZeroHatTest) {
     hidl_vec<uint8_t> token(69);
     for (size_t i = 0; i < 69; i++) {
         token[i] = 0;
@@ -232,7 +217,7 @@
 }
 
 // setFeature with an invalid HAT should fail.
-TEST_F(FaceHidlTest, SetFeatureGarbageHatTest) {
+TEST_P(FaceHidlTest, SetFeatureGarbageHatTest) {
     // Filling HAT with pseudorandom invalid data.
     // Using default seed to make the test reproducible.
     std::mt19937 gen(std::mt19937::default_seed);
@@ -254,16 +239,16 @@
     ASSERT_TRUE(res.isOk());
 }
 
-TEST_F(FaceHidlTest, GetFeatureRequireAttentionTest) {
+TEST_P(FaceHidlTest, GetFeatureRequireAttentionTest) {
     assertGetFeatureFails(mService, 0 /* faceId */, Feature::REQUIRE_ATTENTION);
 }
 
-TEST_F(FaceHidlTest, GetFeatureRequireDiversityTest) {
+TEST_P(FaceHidlTest, GetFeatureRequireDiversityTest) {
     assertGetFeatureFails(mService, 0 /* faceId */, Feature::REQUIRE_DIVERSITY);
 }
 
 // revokeChallenge should always return within the timeout
-TEST_F(FaceHidlTest, RevokeChallengeTest) {
+TEST_P(FaceHidlTest, RevokeChallengeTest) {
     auto start = std::chrono::system_clock::now();
     Return<Status> ret = mService->revokeChallenge();
     auto elapsed = std::chrono::system_clock::now() - start;
@@ -272,14 +257,14 @@
 }
 
 // The call to getAuthenticatorId should succeed.
-TEST_F(FaceHidlTest, GetAuthenticatorIdTest) {
+TEST_P(FaceHidlTest, GetAuthenticatorIdTest) {
     Return<void> ret = mService->getAuthenticatorId(
             [](const OptionalUint64& res) { ASSERT_EQ(Status::OK, res.status); });
     ASSERT_TRUE(ret.isOk());
 }
 
 // The call to enumerate should succeed.
-TEST_F(FaceHidlTest, EnumerateTest) {
+TEST_P(FaceHidlTest, EnumerateTest) {
     Return<Status> ret = mService->enumerate();
     ASSERT_EQ(Status::OK, static_cast<Status>(ret));
     auto res = mCallback->WaitForCallback(kCallbackNameOnEnumerate);
@@ -288,21 +273,21 @@
 }
 
 // The call to remove should succeed for any faceId
-TEST_F(FaceHidlTest, RemoveFaceTest) {
+TEST_P(FaceHidlTest, RemoveFaceTest) {
     // Remove a face
     Return<Status> ret = mService->remove(kFaceId);
     ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 }
 
 // Remove should accept 0 to delete all faces
-TEST_F(FaceHidlTest, RemoveAllFacesTest) {
+TEST_P(FaceHidlTest, RemoveAllFacesTest) {
     // Remove all faces
     Return<Status> ret = mService->remove(0);
     ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 }
 
 // Active user should successfully set to a writable location.
-TEST_F(FaceHidlTest, SetActiveUserTest) {
+TEST_P(FaceHidlTest, SetActiveUserTest) {
     // Create an active user
     Return<Status> ret = mService->setActiveUser(2, kFacedataDir);
     ASSERT_EQ(Status::OK, static_cast<Status>(ret));
@@ -313,7 +298,7 @@
 }
 
 // Active user should fail to set to an unwritable location.
-TEST_F(FaceHidlTest, SetActiveUserUnwritableTest) {
+TEST_P(FaceHidlTest, SetActiveUserUnwritableTest) {
     // Create an active user to an unwritable location (device root dir)
     Return<Status> ret = mService->setActiveUser(3, "/");
     ASSERT_NE(Status::OK, static_cast<Status>(ret));
@@ -324,7 +309,7 @@
 }
 
 // Active user should fail to set to a null location.
-TEST_F(FaceHidlTest, SetActiveUserNullTest) {
+TEST_P(FaceHidlTest, SetActiveUserNullTest) {
     // Create an active user to a null location.
     Return<Status> ret = mService->setActiveUser(4, nullptr);
     ASSERT_NE(Status::OK, static_cast<Status>(ret));
@@ -336,7 +321,7 @@
 
 // Cancel should always return CANCELED from any starting state including
 // the IDLE state.
-TEST_F(FaceHidlTest, CancelTest) {
+TEST_P(FaceHidlTest, CancelTest) {
     Return<Status> ret = mService->cancel();
     // check that we were able to make an IPC request successfully
     ASSERT_EQ(Status::OK, static_cast<Status>(ret));
@@ -347,7 +332,7 @@
     EXPECT_EQ(FaceError::CANCELED, res.args->error);
 }
 
-TEST_F(FaceHidlTest, OnLockoutChangedTest) {
+TEST_P(FaceHidlTest, OnLockoutChangedTest) {
     // Update active user and ensure onLockoutChanged was called.
     Return<Status> ret = mService->setActiveUser(kUserId + 1, kFacedataDir);
     ASSERT_EQ(Status::OK, static_cast<Status>(ret));
@@ -359,11 +344,7 @@
 
 }  // anonymous namespace
 
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(FaceHidlEnvironment::Instance());
-    ::testing::InitGoogleTest(&argc, argv);
-    FaceHidlEnvironment::Instance()->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    LOG(INFO) << "Test result = " << status;
-    return status;
-}
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, FaceHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IBiometricsFace::descriptor)),
+        android::hardware::PrintInstanceNameToString);
diff --git a/bluetooth/1.0/default/bluetooth_hci.cc b/bluetooth/1.0/default/bluetooth_hci.cc
index e14e3d7..a2211f4 100644
--- a/bluetooth/1.0/default/bluetooth_hci.cc
+++ b/bluetooth/1.0/default/bluetooth_hci.cc
@@ -89,6 +89,9 @@
         if (!hidl_status.isOk()) {
           ALOGE("VendorInterface -> Unable to call scoDataReceived()");
         }
+      },
+      [cb](const hidl_vec<uint8_t>&) {
+        ALOGE("VendorInterface -> No callback for ISO packets in HAL V1_0");
       });
   if (!rc) {
     auto hidl_status = cb->initializationComplete(Status::INITIALIZATION_ERROR);
diff --git a/bluetooth/1.0/default/h4_protocol.cc b/bluetooth/1.0/default/h4_protocol.cc
index 98e3273..8c24f76 100644
--- a/bluetooth/1.0/default/h4_protocol.cc
+++ b/bluetooth/1.0/default/h4_protocol.cc
@@ -58,6 +58,9 @@
     case HCI_PACKET_TYPE_SCO_DATA:
       sco_cb_(hci_packetizer_.GetPacket());
       break;
+    case HCI_PACKET_TYPE_ISO_DATA:
+      iso_cb_(hci_packetizer_.GetPacket());
+      break;
     default:
       LOG_ALWAYS_FATAL("%s: Unimplemented packet type %d", __func__,
                        static_cast<int>(hci_packet_type_));
diff --git a/bluetooth/1.0/default/h4_protocol.h b/bluetooth/1.0/default/h4_protocol.h
index 0d0a1ca..0c82fd6 100644
--- a/bluetooth/1.0/default/h4_protocol.h
+++ b/bluetooth/1.0/default/h4_protocol.h
@@ -31,11 +31,12 @@
 class H4Protocol : public HciProtocol {
  public:
   H4Protocol(int fd, PacketReadCallback event_cb, PacketReadCallback acl_cb,
-             PacketReadCallback sco_cb)
+             PacketReadCallback sco_cb, PacketReadCallback iso_cb)
       : uart_fd_(fd),
         event_cb_(event_cb),
         acl_cb_(acl_cb),
         sco_cb_(sco_cb),
+        iso_cb_(iso_cb),
         hci_packetizer_([this]() { OnPacketReady(); }) {}
 
   size_t Send(uint8_t type, const uint8_t* data, size_t length);
@@ -50,6 +51,7 @@
   PacketReadCallback event_cb_;
   PacketReadCallback acl_cb_;
   PacketReadCallback sco_cb_;
+  PacketReadCallback iso_cb_;
 
   HciPacketType hci_packet_type_{HCI_PACKET_TYPE_UNKNOWN};
   hci::HciPacketizer hci_packetizer_;
diff --git a/bluetooth/1.0/default/hci_internals.h b/bluetooth/1.0/default/hci_internals.h
index 1e1f300..24e944f 100644
--- a/bluetooth/1.0/default/hci_internals.h
+++ b/bluetooth/1.0/default/hci_internals.h
@@ -24,7 +24,8 @@
   HCI_PACKET_TYPE_COMMAND = 1,
   HCI_PACKET_TYPE_ACL_DATA = 2,
   HCI_PACKET_TYPE_SCO_DATA = 3,
-  HCI_PACKET_TYPE_EVENT = 4
+  HCI_PACKET_TYPE_EVENT = 4,
+  HCI_PACKET_TYPE_ISO_DATA = 5,
 };
 
 // 2 bytes for opcode, 1 byte for parameter length (Volume 2, Part E, 5.4.1)
diff --git a/bluetooth/1.0/default/test/h4_protocol_unittest.cc b/bluetooth/1.0/default/test/h4_protocol_unittest.cc
index ba56c0d..283243d 100644
--- a/bluetooth/1.0/default/test/h4_protocol_unittest.cc
+++ b/bluetooth/1.0/default/test/h4_protocol_unittest.cc
@@ -42,11 +42,15 @@
 static char sample_data1[100] = "A point is that which has no part.";
 static char sample_data2[100] = "A line is breadthless length.";
 static char sample_data3[100] = "The ends of a line are points.";
+static char sample_data4[100] =
+    "A plane surface is a surface which lies evenly with the straight ...";
 static char acl_data[100] =
     "A straight line is a line which lies evenly with the points on itself.";
 static char sco_data[100] =
     "A surface is that which has length and breadth only.";
 static char event_data[100] = "The edges of a surface are lines.";
+static char iso_data[100] =
+    "A plane angle is the inclination to one another of two lines in a ...";
 
 MATCHER_P3(HidlVecMatches, preamble, preamble_length, payload, "") {
   size_t length = strlen(payload) + preamble_length;
@@ -75,9 +79,9 @@
 
     int sockfd[2];
     socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd);
-    H4Protocol* h4_hci =
-        new H4Protocol(sockfd[0], event_cb_.AsStdFunction(),
-                       acl_cb_.AsStdFunction(), sco_cb_.AsStdFunction());
+    H4Protocol* h4_hci = new H4Protocol(
+        sockfd[0], event_cb_.AsStdFunction(), acl_cb_.AsStdFunction(),
+        sco_cb_.AsStdFunction(), iso_cb_.AsStdFunction());
     fd_watcher_.WatchFdForNonBlockingReads(
         sockfd[0], [h4_hci](int fd) { h4_hci->OnDataReady(fd); });
     protocol_ = h4_hci;
@@ -184,9 +188,35 @@
     }
   }
 
+  void WriteAndExpectInboundIsoData(char* payload) {
+    // h4 type[1] + handle[2] + size[1]
+    char preamble[4] = {HCI_PACKET_TYPE_ISO_DATA, 20, 17, 0};
+    preamble[3] = strlen(payload) & 0xFF;
+
+    ALOGD("%s writing", __func__);
+    TEMP_FAILURE_RETRY(write(fake_uart_, preamble, sizeof(preamble)));
+    TEMP_FAILURE_RETRY(write(fake_uart_, payload, strlen(payload)));
+
+    ALOGD("%s waiting", __func__);
+    std::mutex mutex;
+    std::condition_variable done;
+    EXPECT_CALL(iso_cb_, Call(HidlVecMatches(preamble + 1, sizeof(preamble) - 1,
+                                             payload)))
+        .WillOnce(Notify(&mutex, &done));
+
+    // Fail if it takes longer than 100 ms.
+    auto timeout_time =
+        std::chrono::steady_clock::now() + std::chrono::milliseconds(100);
+    {
+      std::unique_lock<std::mutex> lock(mutex);
+      done.wait_until(lock, timeout_time);
+    }
+  }
+
   testing::MockFunction<void(const hidl_vec<uint8_t>&)> event_cb_;
   testing::MockFunction<void(const hidl_vec<uint8_t>&)> acl_cb_;
   testing::MockFunction<void(const hidl_vec<uint8_t>&)> sco_cb_;
+  testing::MockFunction<void(const hidl_vec<uint8_t>&)> iso_cb_;
   async::AsyncFdWatcher fd_watcher_;
   H4Protocol* protocol_;
   int fake_uart_;
@@ -197,6 +227,7 @@
   SendAndReadUartOutbound(HCI_PACKET_TYPE_COMMAND, sample_data1);
   SendAndReadUartOutbound(HCI_PACKET_TYPE_ACL_DATA, sample_data2);
   SendAndReadUartOutbound(HCI_PACKET_TYPE_SCO_DATA, sample_data3);
+  SendAndReadUartOutbound(HCI_PACKET_TYPE_ISO_DATA, sample_data4);
 }
 
 // Ensure we properly parse data coming from the UART
@@ -204,6 +235,7 @@
   WriteAndExpectInboundAclData(acl_data);
   WriteAndExpectInboundScoData(sco_data);
   WriteAndExpectInboundEvent(event_data);
+  WriteAndExpectInboundIsoData(iso_data);
 }
 
 }  // namespace implementation
diff --git a/bluetooth/1.0/default/vendor_interface.cc b/bluetooth/1.0/default/vendor_interface.cc
index d56e344..d809313 100644
--- a/bluetooth/1.0/default/vendor_interface.cc
+++ b/bluetooth/1.0/default/vendor_interface.cc
@@ -162,14 +162,14 @@
 bool VendorInterface::Initialize(
     InitializeCompleteCallback initialize_complete_cb,
     PacketReadCallback event_cb, PacketReadCallback acl_cb,
-    PacketReadCallback sco_cb) {
+    PacketReadCallback sco_cb, PacketReadCallback iso_cb) {
   if (g_vendor_interface) {
     ALOGE("%s: No previous Shutdown()?", __func__);
     return false;
   }
   g_vendor_interface = new VendorInterface();
   return g_vendor_interface->Open(initialize_complete_cb, event_cb, acl_cb,
-                                  sco_cb);
+                                  sco_cb, iso_cb);
 }
 
 void VendorInterface::Shutdown() {
@@ -185,7 +185,8 @@
 bool VendorInterface::Open(InitializeCompleteCallback initialize_complete_cb,
                            PacketReadCallback event_cb,
                            PacketReadCallback acl_cb,
-                           PacketReadCallback sco_cb) {
+                           PacketReadCallback sco_cb,
+                           PacketReadCallback iso_cb) {
   initialize_complete_cb_ = initialize_complete_cb;
 
   // Initialize vendor interface
@@ -248,7 +249,7 @@
 
   if (fd_count == 1) {
     hci::H4Protocol* h4_hci =
-        new hci::H4Protocol(fd_list[0], intercept_events, acl_cb, sco_cb);
+        new hci::H4Protocol(fd_list[0], intercept_events, acl_cb, sco_cb, iso_cb);
     fd_watcher_.WatchFdForNonBlockingReads(
         fd_list[0], [h4_hci](int fd) { h4_hci->OnDataReady(fd); });
     hci_ = h4_hci;
diff --git a/bluetooth/1.0/default/vendor_interface.h b/bluetooth/1.0/default/vendor_interface.h
index 1d69040..040f31a 100644
--- a/bluetooth/1.0/default/vendor_interface.h
+++ b/bluetooth/1.0/default/vendor_interface.h
@@ -38,7 +38,7 @@
  public:
   static bool Initialize(InitializeCompleteCallback initialize_complete_cb,
                          PacketReadCallback event_cb, PacketReadCallback acl_cb,
-                         PacketReadCallback sco_cb);
+                         PacketReadCallback sco_cb, PacketReadCallback iso_cb);
   static void Shutdown();
   static VendorInterface* get();
 
@@ -51,7 +51,7 @@
 
   bool Open(InitializeCompleteCallback initialize_complete_cb,
             PacketReadCallback event_cb, PacketReadCallback acl_cb,
-            PacketReadCallback sco_cb);
+            PacketReadCallback sco_cb, PacketReadCallback iso_cb);
   void Close();
 
   void OnTimeout();
diff --git a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
index beb9a3e..ef02eff 100644
--- a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
+++ b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
@@ -24,8 +24,9 @@
 #include <utils/Log.h>
 
 #include <VtsHalHidlTargetCallbackBase.h>
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include <chrono>
 #include <queue>
@@ -137,30 +138,12 @@
   std::chrono::steady_clock::time_point start_time_;
 };
 
-// Test environment for Bluetooth HIDL HAL.
-class BluetoothHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
-  // get the test environment singleton
-  static BluetoothHidlEnvironment* Instance() {
-    static BluetoothHidlEnvironment* instance = new BluetoothHidlEnvironment;
-    return instance;
-  }
-
-  virtual void registerTestServices() override {
-    registerTestService<IBluetoothHci>();
-  }
-
- private:
-  BluetoothHidlEnvironment() {}
-};
-
 // The main test class for Bluetooth HIDL HAL.
-class BluetoothHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class BluetoothHidlTest : public ::testing::TestWithParam<std::string> {
  public:
   virtual void SetUp() override {
     // currently test passthrough mode only
-    bluetooth =
-        ::testing::VtsHalHidlTargetTestBase::getService<IBluetoothHci>();
+    bluetooth = IBluetoothHci::getService(GetParam());
     ASSERT_NE(bluetooth, nullptr);
     ALOGI("%s: getService() for bluetooth is %s", __func__,
           bluetooth->isRemote() ? "remote" : "local");
@@ -617,10 +600,10 @@
 }
 
 // Empty test: Initialize()/Close() are called in SetUp()/TearDown().
-TEST_F(BluetoothHidlTest, InitializeAndClose) {}
+TEST_P(BluetoothHidlTest, InitializeAndClose) {}
 
 // Send an HCI Reset with sendHciCommand and wait for a command complete event.
-TEST_F(BluetoothHidlTest, HciReset) {
+TEST_P(BluetoothHidlTest, HciReset) {
   hidl_vec<uint8_t> cmd = COMMAND_HCI_RESET;
   bluetooth->sendHciCommand(cmd);
 
@@ -628,7 +611,7 @@
 }
 
 // Read and check the HCI version of the controller.
-TEST_F(BluetoothHidlTest, HciVersionTest) {
+TEST_P(BluetoothHidlTest, HciVersionTest) {
   hidl_vec<uint8_t> cmd = COMMAND_HCI_READ_LOCAL_VERSION_INFORMATION;
   bluetooth->sendHciCommand(cmd);
 
@@ -649,7 +632,7 @@
 }
 
 // Send an unknown HCI command and wait for the error message.
-TEST_F(BluetoothHidlTest, HciUnknownCommand) {
+TEST_P(BluetoothHidlTest, HciUnknownCommand) {
   hidl_vec<uint8_t> cmd = COMMAND_HCI_SHOULD_BE_UNKNOWN;
   bluetooth->sendHciCommand(cmd);
 
@@ -676,14 +659,14 @@
 }
 
 // Enter loopback mode, but don't send any packets.
-TEST_F(BluetoothHidlTest, WriteLoopbackMode) {
+TEST_P(BluetoothHidlTest, WriteLoopbackMode) {
   std::vector<uint16_t> sco_connection_handles;
   std::vector<uint16_t> acl_connection_handles;
   enterLoopbackMode(sco_connection_handles, acl_connection_handles);
 }
 
 // Enter loopback mode and send single packets.
-TEST_F(BluetoothHidlTest, LoopbackModeSinglePackets) {
+TEST_P(BluetoothHidlTest, LoopbackModeSinglePackets) {
   setBufferSizes();
 
   std::vector<uint16_t> sco_connection_handles;
@@ -720,7 +703,7 @@
 }
 
 // Enter loopback mode and send packets for bandwidth measurements.
-TEST_F(BluetoothHidlTest, LoopbackModeBandwidth) {
+TEST_P(BluetoothHidlTest, LoopbackModeBandwidth) {
   setBufferSizes();
 
   std::vector<uint16_t> sco_connection_handles;
@@ -758,11 +741,8 @@
   }
 }
 
-int main(int argc, char** argv) {
-  ::testing::AddGlobalTestEnvironment(BluetoothHidlEnvironment::Instance());
-  ::testing::InitGoogleTest(&argc, argv);
-  BluetoothHidlEnvironment::Instance()->init(&argc, argv);
-  int status = RUN_ALL_TESTS();
-  ALOGI("Test result = %d", status);
-  return status;
-}
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, BluetoothHidlTest,
+    testing::ValuesIn(
+        android::hardware::getAllHalInstanceNames(IBluetoothHci::descriptor)),
+    android::hardware::PrintInstanceNameToString);
diff --git a/bluetooth/1.1/Android.bp b/bluetooth/1.1/Android.bp
new file mode 100644
index 0000000..4204aed
--- /dev/null
+++ b/bluetooth/1.1/Android.bp
@@ -0,0 +1,18 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.bluetooth@1.1",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "IBluetoothHci.hal",
+        "IBluetoothHciCallbacks.hal",
+    ],
+    interfaces: [
+        "android.hardware.bluetooth@1.0",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
diff --git a/bluetooth/1.1/IBluetoothHci.hal b/bluetooth/1.1/IBluetoothHci.hal
new file mode 100644
index 0000000..0f69c6e
--- /dev/null
+++ b/bluetooth/1.1/IBluetoothHci.hal
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+package android.hardware.bluetooth@1.1;
+
+import @1.0::HciPacket;
+import @1.0::IBluetoothHci;
+import IBluetoothHciCallbacks;
+
+/**
+ * The Host Controller Interface (HCI) is the layer defined by the Bluetooth
+ * specification between the software that runs on the host and the Bluetooth
+ * controller chip. This boundary is the natural choice for a Hardware
+ * Abstraction Layer (HAL). Dealing only in HCI packets and events simplifies
+ * the stack and abstracts away power management, initialization, and other
+ * implementation-specific details related to the hardware.
+ */
+interface IBluetoothHci extends @1.0::IBluetoothHci {
+    /**
+     * Same as @1.0, but uses 1.1 Callbacks version
+     */
+    initialize_1_1(@1.1::IBluetoothHciCallbacks callback);
+
+    /**
+     * Send an ISO data packet (as specified in the Bluetooth Specification
+     * V6.0) to the Bluetooth controller.
+     * Packets must be processed in order.
+     * @param data HCI data packet to be sent
+     */
+    sendIsoData(HciPacket data);
+};
diff --git a/bluetooth/1.1/IBluetoothHciCallbacks.hal b/bluetooth/1.1/IBluetoothHciCallbacks.hal
new file mode 100644
index 0000000..62cbe45
--- /dev/null
+++ b/bluetooth/1.1/IBluetoothHciCallbacks.hal
@@ -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.
+ */
+
+package android.hardware.bluetooth@1.1;
+
+import @1.0::HciPacket;
+import @1.0::IBluetoothHciCallbacks;
+
+/**
+ * The interface from the Bluetooth Controller to the stack.
+ */
+interface IBluetoothHciCallbacks extends @1.0::IBluetoothHciCallbacks {
+    /**
+     * Send a ISO data packet form the controller to the host.
+     * @param data the ISO HCI packet to be passed to the host stack
+     */
+    isoDataReceived(HciPacket data);
+};
diff --git a/bluetooth/1.1/default/Android.bp b/bluetooth/1.1/default/Android.bp
new file mode 100644
index 0000000..4f7fecb
--- /dev/null
+++ b/bluetooth/1.1/default/Android.bp
@@ -0,0 +1,42 @@
+//
+// 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_binary {
+    name: "android.hardware.bluetooth@1.1-service",
+    defaults: ["hidl_defaults"],
+    relative_install_path: "hw",
+    vendor: true,
+    init_rc: ["android.hardware.bluetooth@1.1-service.rc"],
+    srcs: [
+        "service.cpp",
+        "bluetooth_hci.cc",
+    ],
+
+    shared_libs: [
+        "liblog",
+        "libcutils",
+        "libdl",
+        "libbase",
+        "libutils",
+        "libhardware",
+        "libhidlbase",
+        "android.hardware.bluetooth@1.0-impl",
+        "android.hardware.bluetooth@1.1",
+    ],
+
+    static_libs: [
+        "android.hardware.bluetooth-hci",
+    ],
+}
diff --git a/bluetooth/1.1/default/OWNERS b/bluetooth/1.1/default/OWNERS
new file mode 100644
index 0000000..0c01df6
--- /dev/null
+++ b/bluetooth/1.1/default/OWNERS
@@ -0,0 +1,3 @@
+zachoverflow@google.com
+mylesgw@google.com
+jpawlowski@google.com
diff --git a/bluetooth/1.1/default/android.hardware.bluetooth@1.1-service.rc b/bluetooth/1.1/default/android.hardware.bluetooth@1.1-service.rc
new file mode 100644
index 0000000..49f0be3
--- /dev/null
+++ b/bluetooth/1.1/default/android.hardware.bluetooth@1.1-service.rc
@@ -0,0 +1,9 @@
+service vendor.bluetooth-1-1 /vendor/bin/hw/android.hardware.bluetooth@1.1-service
+    interface android.hardware.bluetooth@1.1::IBluetoothHci default
+    interface android.hardware.bluetooth@1.0::IBluetoothHci default
+    class hal
+    capabilities BLOCK_SUSPEND NET_ADMIN SYS_NICE
+    user bluetooth
+    group bluetooth
+    writepid /dev/stune/foreground/tasks
+
diff --git a/bluetooth/1.1/default/bluetooth_hci.cc b/bluetooth/1.1/default/bluetooth_hci.cc
new file mode 100644
index 0000000..7ccce80
--- /dev/null
+++ b/bluetooth/1.1/default/bluetooth_hci.cc
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.bluetooth@1.1-impl"
+#include "bluetooth_hci.h"
+
+#include <log/log.h>
+
+#include "vendor_interface.h"
+
+using android::hardware::bluetooth::V1_0::implementation::VendorInterface;
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace V1_1 {
+namespace implementation {
+
+static const uint8_t HCI_DATA_TYPE_COMMAND = 1;
+static const uint8_t HCI_DATA_TYPE_ACL = 2;
+static const uint8_t HCI_DATA_TYPE_SCO = 3;
+static const uint8_t HCI_DATA_TYPE_ISO = 5;
+
+class BluetoothDeathRecipient : public hidl_death_recipient {
+ public:
+  BluetoothDeathRecipient(const sp<IBluetoothHci> hci) : mHci(hci) {}
+
+  virtual void serviceDied(
+      uint64_t /*cookie*/,
+      const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
+    ALOGE("BluetoothDeathRecipient::serviceDied - Bluetooth service died");
+    has_died_ = true;
+    mHci->close();
+  }
+  sp<IBluetoothHci> mHci;
+  bool getHasDied() const { return has_died_; }
+  void setHasDied(bool has_died) { has_died_ = has_died; }
+
+ private:
+  bool has_died_;
+};
+
+BluetoothHci::BluetoothHci()
+    : death_recipient_(new BluetoothDeathRecipient(this)) {}
+
+Return<void> BluetoothHci::initialize_1_1(
+    const ::android::sp<V1_1::IBluetoothHciCallbacks>& cb) {
+  ALOGI("BluetoothHci::initialize_1_1()");
+  if (cb == nullptr) {
+    ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
+    return Void();
+  }
+
+  death_recipient_->setHasDied(false);
+  cb->linkToDeath(death_recipient_, 0);
+
+  bool rc = VendorInterface::Initialize(
+      [cb](bool status) {
+        auto hidl_status = cb->initializationComplete(
+            status ? V1_0::Status::SUCCESS
+                   : V1_0::Status::INITIALIZATION_ERROR);
+        if (!hidl_status.isOk()) {
+          ALOGE("VendorInterface -> Unable to call initializationComplete()");
+        }
+      },
+      [cb](const hidl_vec<uint8_t>& packet) {
+        auto hidl_status = cb->hciEventReceived(packet);
+        if (!hidl_status.isOk()) {
+          ALOGE("VendorInterface -> Unable to call hciEventReceived()");
+        }
+      },
+      [cb](const hidl_vec<uint8_t>& packet) {
+        auto hidl_status = cb->aclDataReceived(packet);
+        if (!hidl_status.isOk()) {
+          ALOGE("VendorInterface -> Unable to call aclDataReceived()");
+        }
+      },
+      [cb](const hidl_vec<uint8_t>& packet) {
+        auto hidl_status = cb->scoDataReceived(packet);
+        if (!hidl_status.isOk()) {
+          ALOGE("VendorInterface -> Unable to call scoDataReceived()");
+        }
+      },
+      [cb](const hidl_vec<uint8_t>& packet) {
+        auto hidl_status = cb->isoDataReceived(packet);
+        if (!hidl_status.isOk()) {
+          ALOGE("VendorInterface -> Unable to call isoDataReceived()");
+        }
+      });
+  if (!rc) {
+    auto hidl_status =
+        cb->initializationComplete(V1_0::Status::INITIALIZATION_ERROR);
+    if (!hidl_status.isOk()) {
+      ALOGE("VendorInterface -> Unable to call initializationComplete(ERR)");
+    }
+  }
+
+  unlink_cb_ = [cb](sp<BluetoothDeathRecipient>& death_recipient) {
+    if (death_recipient->getHasDied())
+      ALOGI("Skipping unlink call, service died.");
+    else
+      cb->unlinkToDeath(death_recipient);
+  };
+
+  return Void();
+}
+
+class OldCbWrapper : public V1_1::IBluetoothHciCallbacks {
+ public:
+  const ::android::sp<V1_0::IBluetoothHciCallbacks> old_cb_;
+  OldCbWrapper(const ::android::sp<V1_0::IBluetoothHciCallbacks>& old_cb)
+      : old_cb_(old_cb) {}
+
+  virtual ~OldCbWrapper() = default;
+
+  Return<void> initializationComplete(V1_0::Status status) override {
+    return old_cb_->initializationComplete(status);
+  };
+
+  Return<void> hciEventReceived(
+      const ::android::hardware::hidl_vec<uint8_t>& event) override {
+    return old_cb_->hciEventReceived(event);
+  };
+
+  Return<void> aclDataReceived(
+      const ::android::hardware::hidl_vec<uint8_t>& data) override {
+    return old_cb_->aclDataReceived(data);
+  };
+
+  Return<void> scoDataReceived(
+      const ::android::hardware::hidl_vec<uint8_t>& data) override {
+    return old_cb_->scoDataReceived(data);
+  };
+
+  Return<void> isoDataReceived(
+      const ::android::hardware::hidl_vec<uint8_t>&) override {
+    ALOGE("Please use HAL V1_1 for ISO.");
+    return Void();
+  };
+};
+
+Return<void> BluetoothHci::initialize(
+    const ::android::sp<V1_0::IBluetoothHciCallbacks>& cb) {
+  ALOGE("Using initialize from HAL V1_0 instead of initialize_1_1.");
+  return initialize_1_1(new OldCbWrapper(cb));
+}
+
+Return<void> BluetoothHci::close() {
+  ALOGI("BluetoothHci::close()");
+  unlink_cb_(death_recipient_);
+  VendorInterface::Shutdown();
+  return Void();
+}
+
+Return<void> BluetoothHci::sendHciCommand(const hidl_vec<uint8_t>& command) {
+  sendDataToController(HCI_DATA_TYPE_COMMAND, command);
+  return Void();
+}
+
+Return<void> BluetoothHci::sendAclData(const hidl_vec<uint8_t>& data) {
+  sendDataToController(HCI_DATA_TYPE_ACL, data);
+  return Void();
+}
+
+Return<void> BluetoothHci::sendScoData(const hidl_vec<uint8_t>& data) {
+  sendDataToController(HCI_DATA_TYPE_SCO, data);
+  return Void();
+}
+
+Return<void> BluetoothHci::sendIsoData(const hidl_vec<uint8_t>& data) {
+  sendDataToController(HCI_DATA_TYPE_ISO, data);
+  return Void();
+}
+
+void BluetoothHci::sendDataToController(const uint8_t type,
+                                        const hidl_vec<uint8_t>& data) {
+  VendorInterface::get()->Send(type, data.data(), data.size());
+}
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/1.1/default/bluetooth_hci.h b/bluetooth/1.1/default/bluetooth_hci.h
new file mode 100644
index 0000000..5f59cb0
--- /dev/null
+++ b/bluetooth/1.1/default/bluetooth_hci.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+#ifndef HIDL_GENERATED_android_hardware_bluetooth_V1_1_BluetoothHci_H_
+#define HIDL_GENERATED_android_hardware_bluetooth_V1_1_BluetoothHci_H_
+
+#include <android/hardware/bluetooth/1.1/IBluetoothHci.h>
+#include <android/hardware/bluetooth/1.1/IBluetoothHciCallbacks.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include <functional>
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+
+class BluetoothDeathRecipient;
+
+class BluetoothHci : public V1_1::IBluetoothHci {
+ public:
+  BluetoothHci();
+  Return<void> initialize(
+      const ::android::sp<V1_0::IBluetoothHciCallbacks>& cb) override;
+  Return<void> initialize_1_1(
+      const ::android::sp<V1_1::IBluetoothHciCallbacks>& cb) override;
+  Return<void> sendHciCommand(const hidl_vec<uint8_t>& packet) override;
+  Return<void> sendAclData(const hidl_vec<uint8_t>& data) override;
+  Return<void> sendScoData(const hidl_vec<uint8_t>& data) override;
+  Return<void> sendIsoData(const hidl_vec<uint8_t>& data) override;
+  Return<void> close() override;
+
+ private:
+  void sendDataToController(const uint8_t type, const hidl_vec<uint8_t>& data);
+  ::android::sp<BluetoothDeathRecipient> death_recipient_;
+  std::function<void(sp<BluetoothDeathRecipient>&)> unlink_cb_;
+};
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HIDL_GENERATED_android_hardware_bluetooth_V1_1_BluetoothHci_H_
diff --git a/bluetooth/1.1/default/service.cpp b/bluetooth/1.1/default/service.cpp
new file mode 100644
index 0000000..affa855
--- /dev/null
+++ b/bluetooth/1.1/default/service.cpp
@@ -0,0 +1,43 @@
+//
+// 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.
+//
+
+#define LOG_TAG "android.hardware.bluetooth@1.1-service"
+
+#include <android/hardware/bluetooth/1.1/IBluetoothHci.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "bluetooth_hci.h"
+
+// Generated HIDL files
+using android::hardware::bluetooth::V1_1::IBluetoothHci;
+using android::hardware::bluetooth::V1_1::implementation::BluetoothHci;
+
+using android::sp;
+using android::status_t;
+
+int main() {
+  ::android::hardware::configureRpcThreadpool(1 /*threads*/, true /*willJoin*/);
+
+  sp bluetoothHci = new BluetoothHci();
+  const status_t status = bluetoothHci->registerAsService();
+  if (status != ::android::OK) {
+    ALOGE("Cannot register Bluetooth HAL service");
+    return 1;  // or handle error
+  }
+
+  ::android::hardware::joinRpcThreadpool();
+  return 1;  // joinRpcThreadpool should never return
+}
diff --git a/bluetooth/1.1/vts/OWNERS b/bluetooth/1.1/vts/OWNERS
new file mode 100644
index 0000000..ff6fd93
--- /dev/null
+++ b/bluetooth/1.1/vts/OWNERS
@@ -0,0 +1,6 @@
+zachoverflow@google.com
+siyuanh@google.com
+mylesgw@google.com
+jpawlowski@google.com
+hsz@google.com
+
diff --git a/vibrator/1.4/vts/functional/Android.bp b/bluetooth/1.1/vts/functional/Android.bp
similarity index 65%
copy from vibrator/1.4/vts/functional/Android.bp
copy to bluetooth/1.1/vts/functional/Android.bp
index 202a824..8d6d749 100644
--- a/vibrator/1.4/vts/functional/Android.bp
+++ b/bluetooth/1.1/vts/functional/Android.bp
@@ -15,19 +15,13 @@
 //
 
 cc_test {
-    name: "VtsHalVibratorV1_4TargetTest",
+    name: "VtsHalBluetoothV1_1TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
-    srcs: ["VtsHalVibratorV1_4TargetTest.cpp"],
+    srcs: ["VtsHalBluetoothV1_1TargetTest.cpp"],
     static_libs: [
-        "android.hardware.vibrator@1.0",
-        "android.hardware.vibrator@1.1",
-        "android.hardware.vibrator@1.2",
-        "android.hardware.vibrator@1.3",
-        "android.hardware.vibrator@1.4",
+        "android.hardware.bluetooth@1.1",
+        "android.hardware.bluetooth@1.0",
+        "libbluetooth-types",
     ],
-    test_suites: [
-        "general-tests",
-        "vts-core",
-    ],
+    test_suites: ["general-tests", "vts-core"],
 }
-
diff --git a/bluetooth/1.1/vts/functional/VtsHalBluetoothV1_1TargetTest.cpp b/bluetooth/1.1/vts/functional/VtsHalBluetoothV1_1TargetTest.cpp
new file mode 100644
index 0000000..659b2c8
--- /dev/null
+++ b/bluetooth/1.1/vts/functional/VtsHalBluetoothV1_1TargetTest.cpp
@@ -0,0 +1,760 @@
+/*
+ * 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 "bluetooth_hidl_hal_test"
+#include <android-base/logging.h>
+
+#include <android/hardware/bluetooth/1.0/types.h>
+#include <android/hardware/bluetooth/1.1/IBluetoothHci.h>
+#include <android/hardware/bluetooth/1.1/IBluetoothHciCallbacks.h>
+#include <hardware/bluetooth.h>
+#include <utils/Log.h>
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include <chrono>
+#include <queue>
+#include <thread>
+
+using ::android::sp;
+using ::android::hardware::hidl_death_recipient;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::bluetooth::V1_0::Status;
+using ::android::hardware::bluetooth::V1_1::IBluetoothHci;
+using ::android::hardware::bluetooth::V1_1::IBluetoothHciCallbacks;
+
+#define HCI_MINIMUM_HCI_VERSION 5  // Bluetooth Core Specification 3.0 + HS
+#define HCI_MINIMUM_LMP_VERSION 5  // Bluetooth Core Specification 3.0 + HS
+#define NUM_HCI_COMMANDS_BANDWIDTH 1000
+#define NUM_SCO_PACKETS_BANDWIDTH 1000
+#define NUM_ACL_PACKETS_BANDWIDTH 1000
+#define WAIT_FOR_INIT_TIMEOUT std::chrono::milliseconds(2000)
+#define WAIT_FOR_HCI_EVENT_TIMEOUT std::chrono::milliseconds(2000)
+#define WAIT_FOR_SCO_DATA_TIMEOUT std::chrono::milliseconds(1000)
+#define WAIT_FOR_ACL_DATA_TIMEOUT std::chrono::milliseconds(1000)
+#define INTERFACE_CLOSE_DELAY_MS std::chrono::milliseconds(200)
+
+#define COMMAND_HCI_SHOULD_BE_UNKNOWN \
+  { 0xff, 0x3B, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }
+#define COMMAND_HCI_READ_LOCAL_VERSION_INFORMATION \
+  { 0x01, 0x10, 0x00 }
+#define COMMAND_HCI_READ_BUFFER_SIZE \
+  { 0x05, 0x10, 0x00 }
+#define COMMAND_HCI_WRITE_LOOPBACK_MODE_LOCAL \
+  { 0x02, 0x18, 0x01, 0x01 }
+#define COMMAND_HCI_RESET \
+  { 0x03, 0x0c, 0x00 }
+#define COMMAND_HCI_WRITE_LOCAL_NAME \
+  { 0x13, 0x0c, 0xf8 }
+#define HCI_STATUS_SUCCESS 0x00
+#define HCI_STATUS_UNKNOWN_HCI_COMMAND 0x01
+
+#define EVENT_CONNECTION_COMPLETE 0x03
+#define EVENT_COMMAND_COMPLETE 0x0e
+#define EVENT_COMMAND_STATUS 0x0f
+#define EVENT_NUMBER_OF_COMPLETED_PACKETS 0x13
+#define EVENT_LOOPBACK_COMMAND 0x19
+
+#define EVENT_CODE_BYTE 0
+#define EVENT_LENGTH_BYTE 1
+#define EVENT_FIRST_PAYLOAD_BYTE 2
+#define EVENT_COMMAND_STATUS_STATUS_BYTE 2
+#define EVENT_COMMAND_STATUS_ALLOWED_PACKETS_BYTE 3
+#define EVENT_COMMAND_STATUS_OPCODE_LSBYTE 4  // Bytes 4 and 5
+#define EVENT_COMMAND_COMPLETE_ALLOWED_PACKETS_BYTE 2
+#define EVENT_COMMAND_COMPLETE_OPCODE_LSBYTE 3  // Bytes 3 and 4
+#define EVENT_COMMAND_COMPLETE_STATUS_BYTE 5
+#define EVENT_COMMAND_COMPLETE_FIRST_PARAM_BYTE 6
+#define EVENT_LOCAL_HCI_VERSION_BYTE EVENT_COMMAND_COMPLETE_FIRST_PARAM_BYTE
+#define EVENT_LOCAL_LMP_VERSION_BYTE EVENT_LOCAL_HCI_VERSION_BYTE + 3
+
+#define EVENT_CONNECTION_COMPLETE_PARAM_LENGTH 11
+#define EVENT_CONNECTION_COMPLETE_TYPE 11
+#define EVENT_CONNECTION_COMPLETE_TYPE_SCO 0
+#define EVENT_CONNECTION_COMPLETE_TYPE_ACL 1
+#define EVENT_CONNECTION_COMPLETE_HANDLE_LSBYTE 3
+#define EVENT_COMMAND_STATUS_LENGTH 4
+
+#define EVENT_NUMBER_OF_COMPLETED_PACKETS_NUM_HANDLES 2
+
+#define ACL_BROADCAST_FLAG_OFFSET 6
+#define ACL_BROADCAST_FLAG_POINT_TO_POINT 0x0
+#define ACL_BROADCAST_POINT_TO_POINT \
+  (ACL_BROADCAST_FLAG_POINT_TO_POINT << ACL_BROADCAST_FLAG_OFFSET)
+
+#define ACL_PACKET_BOUNDARY_FLAG_OFFSET 4
+#define ACL_PACKET_BOUNDARY_FLAG_FIRST_AUTO_FLUSHABLE 0x2
+#define ACL_PACKET_BOUNDARY_FIRST_AUTO_FLUSHABLE \
+  (ACL_PACKET_BOUNDARY_FLAG_FIRST_AUTO_FLUSHABLE \
+   << ACL_PACKET_BOUNDARY_FLAG_OFFSET)
+
+// To be removed in VTS release builds
+#define ACL_HANDLE_QCA_DEBUG_MESSAGE 0xedc
+
+constexpr char kCallbackNameAclEventReceived[] = "aclDataReceived";
+constexpr char kCallbackNameHciEventReceived[] = "hciEventReceived";
+constexpr char kCallbackNameInitializationComplete[] = "initializationComplete";
+constexpr char kCallbackNameScoEventReceived[] = "scoDataReceived";
+constexpr char kCallbackNameIsoEventReceived[] = "isoDataReceived";
+
+class ThroughputLogger {
+ public:
+  ThroughputLogger(std::string task)
+      : task_(task), start_time_(std::chrono::steady_clock::now()) {}
+
+  ~ThroughputLogger() {
+    if (total_bytes_ == 0) return;
+    std::chrono::duration<double> duration =
+        std::chrono::steady_clock::now() - start_time_;
+    double s = duration.count();
+    if (s == 0) return;
+    double rate_kb = (static_cast<double>(total_bytes_) / s) / 1024;
+    ALOGD("%s %.1f KB/s (%zu bytes in %.3fs)", task_.c_str(), rate_kb,
+          total_bytes_, s);
+  }
+
+  void setTotalBytes(size_t total_bytes) { total_bytes_ = total_bytes; }
+
+ private:
+  size_t total_bytes_;
+  std::string task_;
+  std::chrono::steady_clock::time_point start_time_;
+};
+
+// The main test class for Bluetooth HIDL HAL.
+class BluetoothHidlTest : public ::testing::TestWithParam<std::string> {
+ public:
+  virtual void SetUp() override {
+    // currently test passthrough mode only
+    bluetooth = IBluetoothHci::getService(GetParam());
+    ASSERT_NE(bluetooth, nullptr);
+    ALOGI("%s: getService() for bluetooth is %s", __func__,
+          bluetooth->isRemote() ? "remote" : "local");
+
+    bluetooth_hci_death_recipient = new BluetoothHciDeathRecipient();
+    ASSERT_NE(bluetooth_hci_death_recipient, nullptr);
+    ASSERT_TRUE(
+        bluetooth->linkToDeath(bluetooth_hci_death_recipient, 0).isOk());
+
+    bluetooth_cb = new BluetoothHciCallbacks(*this);
+    ASSERT_NE(bluetooth_cb, nullptr);
+
+    max_acl_data_packet_length = 0;
+    max_sco_data_packet_length = 0;
+    max_acl_data_packets = 0;
+    max_sco_data_packets = 0;
+
+    initialized = false;
+    event_cb_count = 0;
+    acl_cb_count = 0;
+    sco_cb_count = 0;
+
+    ASSERT_FALSE(initialized);
+    // Should not be checked in production code
+    ASSERT_TRUE(bluetooth->initialize(bluetooth_cb).isOk());
+
+    bluetooth_cb->SetWaitTimeout(kCallbackNameInitializationComplete,
+                                 WAIT_FOR_INIT_TIMEOUT);
+    bluetooth_cb->SetWaitTimeout(kCallbackNameHciEventReceived,
+                                 WAIT_FOR_HCI_EVENT_TIMEOUT);
+    bluetooth_cb->SetWaitTimeout(kCallbackNameAclEventReceived,
+                                 WAIT_FOR_ACL_DATA_TIMEOUT);
+    bluetooth_cb->SetWaitTimeout(kCallbackNameScoEventReceived,
+                                 WAIT_FOR_SCO_DATA_TIMEOUT);
+
+    EXPECT_TRUE(
+        bluetooth_cb->WaitForCallback(kCallbackNameInitializationComplete)
+            .no_timeout);
+
+    ASSERT_TRUE(initialized);
+  }
+
+  virtual void TearDown() override {
+    ALOGI("TearDown");
+    // Should not be checked in production code
+    ASSERT_TRUE(bluetooth->close().isOk());
+    std::this_thread::sleep_for(INTERFACE_CLOSE_DELAY_MS);
+    handle_no_ops();
+    EXPECT_EQ(static_cast<size_t>(0), event_queue.size());
+    EXPECT_EQ(static_cast<size_t>(0), sco_queue.size());
+    EXPECT_EQ(static_cast<size_t>(0), acl_queue.size());
+    EXPECT_EQ(static_cast<size_t>(0), iso_queue.size());
+  }
+
+  void setBufferSizes();
+
+  // Functions called from within tests in loopback mode
+  void sendAndCheckHCI(int num_packets);
+  void sendAndCheckSCO(int num_packets, size_t size, uint16_t handle);
+  void sendAndCheckACL(int num_packets, size_t size, uint16_t handle);
+
+  // Helper functions to try to get a handle on verbosity
+  void enterLoopbackMode(std::vector<uint16_t>* sco_handles,
+                         std::vector<uint16_t>* acl_handles);
+  void handle_no_ops();
+  void wait_for_event(bool timeout_is_error);
+  void wait_for_command_complete_event(hidl_vec<uint8_t> cmd);
+  int wait_for_completed_packets_event(uint16_t handle);
+
+  class BluetoothHciDeathRecipient : public hidl_death_recipient {
+   public:
+    void serviceDied(
+        uint64_t /*cookie*/,
+        const android::wp<::android::hidl::base::V1_0::IBase>& /*who*/)
+        override {
+      FAIL();
+    }
+  };
+
+  // A simple test implementation of BluetoothHciCallbacks.
+  class BluetoothHciCallbacks
+      : public ::testing::VtsHalHidlTargetCallbackBase<BluetoothHidlTest>,
+        public IBluetoothHciCallbacks {
+    BluetoothHidlTest& parent_;
+
+   public:
+    BluetoothHciCallbacks(BluetoothHidlTest& parent) : parent_(parent){};
+
+    virtual ~BluetoothHciCallbacks() = default;
+
+    Return<void> initializationComplete(Status status) override {
+      parent_.initialized = (status == Status::SUCCESS);
+      NotifyFromCallback(kCallbackNameInitializationComplete);
+      ALOGV("%s (status = %d)", __func__, static_cast<int>(status));
+      return Void();
+    };
+
+    Return<void> hciEventReceived(
+        const ::android::hardware::hidl_vec<uint8_t>& event) override {
+      parent_.event_cb_count++;
+      parent_.event_queue.push(event);
+      NotifyFromCallback(kCallbackNameHciEventReceived);
+      ALOGV("Event received (length = %d)", static_cast<int>(event.size()));
+      return Void();
+    };
+
+    Return<void> aclDataReceived(
+        const ::android::hardware::hidl_vec<uint8_t>& data) override {
+      parent_.acl_cb_count++;
+      parent_.acl_queue.push(data);
+      NotifyFromCallback(kCallbackNameAclEventReceived);
+      return Void();
+    };
+
+    Return<void> scoDataReceived(
+        const ::android::hardware::hidl_vec<uint8_t>& data) override {
+      parent_.sco_cb_count++;
+      parent_.sco_queue.push(data);
+      NotifyFromCallback(kCallbackNameScoEventReceived);
+      return Void();
+    };
+
+    Return<void> isoDataReceived(
+        const ::android::hardware::hidl_vec<uint8_t>& data) override {
+      parent_.iso_cb_count++;
+      parent_.iso_queue.push(data);
+      NotifyFromCallback(kCallbackNameIsoEventReceived);
+      return Void();
+    };
+  };
+
+  sp<IBluetoothHci> bluetooth;
+  sp<BluetoothHciCallbacks> bluetooth_cb;
+  sp<BluetoothHciDeathRecipient> bluetooth_hci_death_recipient;
+  std::queue<hidl_vec<uint8_t>> event_queue;
+  std::queue<hidl_vec<uint8_t>> acl_queue;
+  std::queue<hidl_vec<uint8_t>> sco_queue;
+  std::queue<hidl_vec<uint8_t>> iso_queue;
+
+  bool initialized;
+
+  int event_cb_count;
+  int sco_cb_count;
+  int acl_cb_count;
+  int iso_cb_count;
+
+  int max_acl_data_packet_length;
+  int max_sco_data_packet_length;
+  int max_acl_data_packets;
+  int max_sco_data_packets;
+};
+
+// Discard NO-OPs from the event queue.
+void BluetoothHidlTest::handle_no_ops() {
+  while (event_queue.size() > 0) {
+    hidl_vec<uint8_t> event = event_queue.front();
+    EXPECT_GE(event.size(),
+              static_cast<size_t>(EVENT_COMMAND_COMPLETE_STATUS_BYTE));
+    bool event_is_no_op =
+        (event[EVENT_CODE_BYTE] == EVENT_COMMAND_COMPLETE) &&
+        (event[EVENT_COMMAND_COMPLETE_OPCODE_LSBYTE] == 0x00) &&
+        (event[EVENT_COMMAND_COMPLETE_OPCODE_LSBYTE + 1] == 0x00);
+    event_is_no_op |= (event[EVENT_CODE_BYTE] == EVENT_COMMAND_STATUS) &&
+                      (event[EVENT_COMMAND_STATUS_OPCODE_LSBYTE] == 0x00) &&
+                      (event[EVENT_COMMAND_STATUS_OPCODE_LSBYTE + 1] == 0x00);
+    if (event_is_no_op) {
+      event_queue.pop();
+    } else {
+      break;
+    }
+  }
+  // To be removed in VTS release builds
+  while (acl_queue.size() > 0) {
+    hidl_vec<uint8_t> acl_packet = acl_queue.front();
+    uint16_t connection_handle = acl_packet[1] & 0xF;
+    connection_handle <<= 8;
+    connection_handle |= acl_packet[0];
+    bool packet_is_no_op = connection_handle == ACL_HANDLE_QCA_DEBUG_MESSAGE;
+    if (packet_is_no_op) {
+      acl_queue.pop();
+    } else {
+      break;
+    }
+  }
+}
+
+// Receive an event, discarding NO-OPs.
+void BluetoothHidlTest::wait_for_event(bool timeout_is_error = true) {
+  hidl_vec<uint8_t> event;
+  do {
+    bool no_timeout =
+        bluetooth_cb->WaitForCallback(kCallbackNameHciEventReceived).no_timeout;
+    EXPECT_TRUE(no_timeout || !timeout_is_error);
+    if (no_timeout && timeout_is_error) {
+      EXPECT_LT(static_cast<size_t>(0), event_queue.size());
+    }
+    if (event_queue.size() == 0) {
+      // WaitForCallback timed out.
+      return;
+    }
+    handle_no_ops();
+  } while (event_queue.size() == 0);
+}
+
+// Wait until a COMMAND_COMPLETE is received.
+void BluetoothHidlTest::wait_for_command_complete_event(hidl_vec<uint8_t> cmd) {
+  wait_for_event();
+  hidl_vec<uint8_t> event = event_queue.front();
+  event_queue.pop();
+
+  EXPECT_GT(event.size(),
+            static_cast<size_t>(EVENT_COMMAND_COMPLETE_STATUS_BYTE));
+  EXPECT_EQ(EVENT_COMMAND_COMPLETE, event[EVENT_CODE_BYTE]);
+  EXPECT_EQ(cmd[0], event[EVENT_COMMAND_COMPLETE_OPCODE_LSBYTE]);
+  EXPECT_EQ(cmd[1], event[EVENT_COMMAND_COMPLETE_OPCODE_LSBYTE + 1]);
+  EXPECT_EQ(HCI_STATUS_SUCCESS, event[EVENT_COMMAND_COMPLETE_STATUS_BYTE]);
+}
+
+// Send the command to read the controller's buffer sizes.
+void BluetoothHidlTest::setBufferSizes() {
+  hidl_vec<uint8_t> cmd = COMMAND_HCI_READ_BUFFER_SIZE;
+  bluetooth->sendHciCommand(cmd);
+
+  wait_for_event();
+  if (event_queue.size() == 0) return;
+
+  hidl_vec<uint8_t> event = event_queue.front();
+  event_queue.pop();
+
+  EXPECT_EQ(EVENT_COMMAND_COMPLETE, event[EVENT_CODE_BYTE]);
+  EXPECT_EQ(cmd[0], event[EVENT_COMMAND_COMPLETE_OPCODE_LSBYTE]);
+  EXPECT_EQ(cmd[1], event[EVENT_COMMAND_COMPLETE_OPCODE_LSBYTE + 1]);
+  EXPECT_EQ(HCI_STATUS_SUCCESS, event[EVENT_COMMAND_COMPLETE_STATUS_BYTE]);
+
+  max_acl_data_packet_length =
+      event[EVENT_COMMAND_COMPLETE_STATUS_BYTE + 1] +
+      (event[EVENT_COMMAND_COMPLETE_STATUS_BYTE + 2] << 8);
+  max_sco_data_packet_length = event[EVENT_COMMAND_COMPLETE_STATUS_BYTE + 3];
+  max_acl_data_packets = event[EVENT_COMMAND_COMPLETE_STATUS_BYTE + 4] +
+                         (event[EVENT_COMMAND_COMPLETE_STATUS_BYTE + 5] << 8);
+  max_sco_data_packets = event[EVENT_COMMAND_COMPLETE_STATUS_BYTE + 6] +
+                         (event[EVENT_COMMAND_COMPLETE_STATUS_BYTE + 7] << 8);
+
+  ALOGD("%s: ACL max %d num %d SCO max %d num %d", __func__,
+        static_cast<int>(max_acl_data_packet_length),
+        static_cast<int>(max_acl_data_packets),
+        static_cast<int>(max_sco_data_packet_length),
+        static_cast<int>(max_sco_data_packets));
+}
+
+// Send an HCI command (in Loopback mode) and check the response.
+void BluetoothHidlTest::sendAndCheckHCI(int num_packets) {
+  ThroughputLogger logger = {__func__};
+  int command_size = 0;
+  for (int n = 0; n < num_packets; n++) {
+    // Send an HCI packet
+    std::vector<uint8_t> write_name = COMMAND_HCI_WRITE_LOCAL_NAME;
+    // With a name
+    char new_name[] = "John Jacob Jingleheimer Schmidt ___________________0";
+    size_t new_name_length = strlen(new_name);
+    for (size_t i = 0; i < new_name_length; i++)
+      write_name.push_back(static_cast<uint8_t>(new_name[i]));
+    // And the packet number
+    size_t i = new_name_length - 1;
+    for (int digits = n; digits > 0; digits = digits / 10, i--)
+      write_name[i] = static_cast<uint8_t>('0' + digits % 10);
+    // And padding
+    for (size_t i = 0; i < 248 - new_name_length; i++)
+      write_name.push_back(static_cast<uint8_t>(0));
+
+    hidl_vec<uint8_t> cmd = write_name;
+    bluetooth->sendHciCommand(cmd);
+
+    // Check the loopback of the HCI packet
+    wait_for_event();
+    if (event_queue.size() == 0) return;
+
+    hidl_vec<uint8_t> event = event_queue.front();
+    event_queue.pop();
+    size_t compare_length =
+        (cmd.size() > static_cast<size_t>(0xff) ? static_cast<size_t>(0xff)
+                                                : cmd.size());
+    EXPECT_GT(event.size(), compare_length + EVENT_FIRST_PAYLOAD_BYTE - 1);
+
+    EXPECT_EQ(EVENT_LOOPBACK_COMMAND, event[EVENT_CODE_BYTE]);
+    EXPECT_EQ(compare_length, event[EVENT_LENGTH_BYTE]);
+
+    // Don't compare past the end of the event.
+    if (compare_length + EVENT_FIRST_PAYLOAD_BYTE > event.size()) {
+      compare_length = event.size() - EVENT_FIRST_PAYLOAD_BYTE;
+      ALOGE("Only comparing %d bytes", static_cast<int>(compare_length));
+    }
+
+    if (n == num_packets - 1) {
+      command_size = cmd.size();
+    }
+
+    for (size_t i = 0; i < compare_length; i++)
+      EXPECT_EQ(cmd[i], event[EVENT_FIRST_PAYLOAD_BYTE + i]);
+  }
+  logger.setTotalBytes(command_size * num_packets * 2);
+}
+
+// Send a SCO data packet (in Loopback mode) and check the response.
+void BluetoothHidlTest::sendAndCheckSCO(int num_packets, size_t size,
+                                        uint16_t handle) {
+  ThroughputLogger logger = {__func__};
+  for (int n = 0; n < num_packets; n++) {
+    // Send a SCO packet
+    hidl_vec<uint8_t> sco_packet;
+    std::vector<uint8_t> sco_vector;
+    sco_vector.push_back(static_cast<uint8_t>(handle & 0xff));
+    sco_vector.push_back(static_cast<uint8_t>((handle & 0x0f00) >> 8));
+    sco_vector.push_back(static_cast<uint8_t>(size & 0xff));
+    sco_vector.push_back(static_cast<uint8_t>((size & 0xff00) >> 8));
+    for (size_t i = 0; i < size; i++) {
+      sco_vector.push_back(static_cast<uint8_t>(i + n));
+    }
+    sco_packet = sco_vector;
+    bluetooth->sendScoData(sco_vector);
+
+    // Check the loopback of the SCO packet
+    EXPECT_TRUE(bluetooth_cb->WaitForCallback(kCallbackNameScoEventReceived)
+                    .no_timeout);
+    hidl_vec<uint8_t> sco_loopback = sco_queue.front();
+    sco_queue.pop();
+
+    EXPECT_EQ(sco_packet.size(), sco_loopback.size());
+    size_t successful_bytes = 0;
+
+    for (size_t i = 0; i < sco_packet.size(); i++) {
+      if (sco_packet[i] == sco_loopback[i]) {
+        successful_bytes = i;
+      } else {
+        ALOGE("Miscompare at %d (expected %x, got %x)", static_cast<int>(i),
+              sco_packet[i], sco_loopback[i]);
+        ALOGE("At %d (expected %x, got %x)", static_cast<int>(i + 1),
+              sco_packet[i + 1], sco_loopback[i + 1]);
+        break;
+      }
+    }
+    EXPECT_EQ(sco_packet.size(), successful_bytes + 1);
+  }
+  logger.setTotalBytes(num_packets * size * 2);
+}
+
+// Send an ACL data packet (in Loopback mode) and check the response.
+void BluetoothHidlTest::sendAndCheckACL(int num_packets, size_t size,
+                                        uint16_t handle) {
+  ThroughputLogger logger = {__func__};
+  for (int n = 0; n < num_packets; n++) {
+    // Send an ACL packet
+    hidl_vec<uint8_t> acl_packet;
+    std::vector<uint8_t> acl_vector;
+    acl_vector.push_back(static_cast<uint8_t>(handle & 0xff));
+    acl_vector.push_back(static_cast<uint8_t>((handle & 0x0f00) >> 8) |
+                         ACL_BROADCAST_POINT_TO_POINT |
+                         ACL_PACKET_BOUNDARY_FIRST_AUTO_FLUSHABLE);
+    acl_vector.push_back(static_cast<uint8_t>(size & 0xff));
+    acl_vector.push_back(static_cast<uint8_t>((size & 0xff00) >> 8));
+    for (size_t i = 0; i < size; i++) {
+      acl_vector.push_back(static_cast<uint8_t>(i + n));
+    }
+    acl_packet = acl_vector;
+    bluetooth->sendAclData(acl_vector);
+
+    // Check the loopback of the ACL packet
+    EXPECT_TRUE(bluetooth_cb->WaitForCallback(kCallbackNameAclEventReceived)
+                    .no_timeout);
+    hidl_vec<uint8_t> acl_loopback = acl_queue.front();
+    acl_queue.pop();
+
+    EXPECT_EQ(acl_packet.size(), acl_loopback.size());
+    size_t successful_bytes = 0;
+
+    for (size_t i = 0; i < acl_packet.size(); i++) {
+      if (acl_packet[i] == acl_loopback[i]) {
+        successful_bytes = i;
+      } else {
+        ALOGE("Miscompare at %d (expected %x, got %x)", static_cast<int>(i),
+              acl_packet[i], acl_loopback[i]);
+        ALOGE("At %d (expected %x, got %x)", static_cast<int>(i + 1),
+              acl_packet[i + 1], acl_loopback[i + 1]);
+        break;
+      }
+    }
+    EXPECT_EQ(acl_packet.size(), successful_bytes + 1);
+  }
+  logger.setTotalBytes(num_packets * size * 2);
+}
+
+// Return the number of completed packets reported by the controller.
+int BluetoothHidlTest::wait_for_completed_packets_event(uint16_t handle) {
+  int packets_processed = 0;
+  wait_for_event(false);
+  if (event_queue.size() == 0) {
+    ALOGW("%s: WaitForCallback timed out.", __func__);
+    return packets_processed;
+  }
+  while (event_queue.size() > 0) {
+    hidl_vec<uint8_t> event = event_queue.front();
+    event_queue.pop();
+
+    EXPECT_EQ(EVENT_NUMBER_OF_COMPLETED_PACKETS, event[EVENT_CODE_BYTE]);
+    EXPECT_EQ(1, event[EVENT_NUMBER_OF_COMPLETED_PACKETS_NUM_HANDLES]);
+
+    uint16_t event_handle = event[3] + (event[4] << 8);
+    EXPECT_EQ(handle, event_handle);
+
+    packets_processed += event[5] + (event[6] << 8);
+  }
+  return packets_processed;
+}
+
+// Send local loopback command and initialize SCO and ACL handles.
+void BluetoothHidlTest::enterLoopbackMode(std::vector<uint16_t>* sco_handles,
+                                          std::vector<uint16_t>* acl_handles) {
+  hidl_vec<uint8_t> cmd = COMMAND_HCI_WRITE_LOOPBACK_MODE_LOCAL;
+  bluetooth->sendHciCommand(cmd);
+
+  // Receive connection complete events with data channels
+  int connection_event_count = 0;
+  bool command_complete_received = false;
+  while (true) {
+    wait_for_event(false);
+    if (event_queue.size() == 0) {
+      // Fail if there was no event received or no connections completed.
+      EXPECT_TRUE(command_complete_received);
+      EXPECT_LT(0, connection_event_count);
+      return;
+    }
+    hidl_vec<uint8_t> event = event_queue.front();
+    event_queue.pop();
+    EXPECT_GT(event.size(),
+              static_cast<size_t>(EVENT_COMMAND_COMPLETE_STATUS_BYTE));
+    if (event[EVENT_CODE_BYTE] == EVENT_CONNECTION_COMPLETE) {
+      EXPECT_GT(event.size(),
+                static_cast<size_t>(EVENT_CONNECTION_COMPLETE_TYPE));
+      EXPECT_EQ(event[EVENT_LENGTH_BYTE],
+                EVENT_CONNECTION_COMPLETE_PARAM_LENGTH);
+      uint8_t connection_type = event[EVENT_CONNECTION_COMPLETE_TYPE];
+
+      EXPECT_TRUE(connection_type == EVENT_CONNECTION_COMPLETE_TYPE_SCO ||
+                  connection_type == EVENT_CONNECTION_COMPLETE_TYPE_ACL);
+
+      // Save handles
+      uint16_t handle = event[EVENT_CONNECTION_COMPLETE_HANDLE_LSBYTE] |
+                        event[EVENT_CONNECTION_COMPLETE_HANDLE_LSBYTE + 1] << 8;
+      if (connection_type == EVENT_CONNECTION_COMPLETE_TYPE_SCO)
+        sco_handles->push_back(handle);
+      else
+        acl_handles->push_back(handle);
+
+      ALOGD("Connect complete type = %d handle = %d",
+            event[EVENT_CONNECTION_COMPLETE_TYPE], handle);
+      connection_event_count++;
+    } else {
+      EXPECT_EQ(EVENT_COMMAND_COMPLETE, event[EVENT_CODE_BYTE]);
+      EXPECT_EQ(cmd[0], event[EVENT_COMMAND_COMPLETE_OPCODE_LSBYTE]);
+      EXPECT_EQ(cmd[1], event[EVENT_COMMAND_COMPLETE_OPCODE_LSBYTE + 1]);
+      EXPECT_EQ(HCI_STATUS_SUCCESS, event[EVENT_COMMAND_COMPLETE_STATUS_BYTE]);
+      command_complete_received = true;
+    }
+  }
+}
+
+// Empty test: Initialize()/Close() are called in SetUp()/TearDown().
+TEST_P(BluetoothHidlTest, InitializeAndClose) {}
+
+// Send an HCI Reset with sendHciCommand and wait for a command complete event.
+TEST_P(BluetoothHidlTest, HciReset) {
+  hidl_vec<uint8_t> cmd = COMMAND_HCI_RESET;
+  bluetooth->sendHciCommand(cmd);
+
+  wait_for_command_complete_event(cmd);
+}
+
+// Read and check the HCI version of the controller.
+TEST_P(BluetoothHidlTest, HciVersionTest) {
+  hidl_vec<uint8_t> cmd = COMMAND_HCI_READ_LOCAL_VERSION_INFORMATION;
+  bluetooth->sendHciCommand(cmd);
+
+  wait_for_event();
+  if (event_queue.size() == 0) return;
+
+  hidl_vec<uint8_t> event = event_queue.front();
+  event_queue.pop();
+  EXPECT_GT(event.size(), static_cast<size_t>(EVENT_LOCAL_LMP_VERSION_BYTE));
+
+  EXPECT_EQ(EVENT_COMMAND_COMPLETE, event[EVENT_CODE_BYTE]);
+  EXPECT_EQ(cmd[0], event[EVENT_COMMAND_COMPLETE_OPCODE_LSBYTE]);
+  EXPECT_EQ(cmd[1], event[EVENT_COMMAND_COMPLETE_OPCODE_LSBYTE + 1]);
+  EXPECT_EQ(HCI_STATUS_SUCCESS, event[EVENT_COMMAND_COMPLETE_STATUS_BYTE]);
+
+  EXPECT_LE(HCI_MINIMUM_HCI_VERSION, event[EVENT_LOCAL_HCI_VERSION_BYTE]);
+  EXPECT_LE(HCI_MINIMUM_LMP_VERSION, event[EVENT_LOCAL_LMP_VERSION_BYTE]);
+}
+
+// Send an unknown HCI command and wait for the error message.
+TEST_P(BluetoothHidlTest, HciUnknownCommand) {
+  hidl_vec<uint8_t> cmd = COMMAND_HCI_SHOULD_BE_UNKNOWN;
+  bluetooth->sendHciCommand(cmd);
+
+  wait_for_event();
+  if (event_queue.size() == 0) return;
+
+  hidl_vec<uint8_t> event = event_queue.front();
+  event_queue.pop();
+
+  EXPECT_GT(event.size(),
+            static_cast<size_t>(EVENT_COMMAND_COMPLETE_STATUS_BYTE));
+  if (event[EVENT_CODE_BYTE] == EVENT_COMMAND_COMPLETE) {
+    EXPECT_EQ(cmd[0], event[EVENT_COMMAND_COMPLETE_OPCODE_LSBYTE]);
+    EXPECT_EQ(cmd[1], event[EVENT_COMMAND_COMPLETE_OPCODE_LSBYTE + 1]);
+    EXPECT_EQ(HCI_STATUS_UNKNOWN_HCI_COMMAND,
+              event[EVENT_COMMAND_COMPLETE_STATUS_BYTE]);
+  } else {
+    EXPECT_EQ(EVENT_COMMAND_STATUS, event[EVENT_CODE_BYTE]);
+    EXPECT_EQ(cmd[0], event[EVENT_COMMAND_STATUS_OPCODE_LSBYTE]);
+    EXPECT_EQ(cmd[1], event[EVENT_COMMAND_STATUS_OPCODE_LSBYTE + 1]);
+    EXPECT_EQ(HCI_STATUS_UNKNOWN_HCI_COMMAND,
+              event[EVENT_COMMAND_STATUS_STATUS_BYTE]);
+  }
+}
+
+// Enter loopback mode, but don't send any packets.
+TEST_P(BluetoothHidlTest, WriteLoopbackMode) {
+  std::vector<uint16_t> sco_connection_handles;
+  std::vector<uint16_t> acl_connection_handles;
+  enterLoopbackMode(&sco_connection_handles, &acl_connection_handles);
+}
+
+// Enter loopback mode and send single packets.
+TEST_P(BluetoothHidlTest, LoopbackModeSinglePackets) {
+  setBufferSizes();
+
+  std::vector<uint16_t> sco_connection_handles;
+  std::vector<uint16_t> acl_connection_handles;
+  enterLoopbackMode(&sco_connection_handles, &acl_connection_handles);
+
+  sendAndCheckHCI(1);
+
+  // This should work, but breaks on some current platforms.  Figure out how to
+  // grandfather older devices but test new ones.
+  if (0 && sco_connection_handles.size() > 0) {
+    EXPECT_LT(0, max_sco_data_packet_length);
+    sendAndCheckSCO(1, max_sco_data_packet_length, sco_connection_handles[0]);
+    int sco_packets_sent = 1;
+    int completed_packets =
+        wait_for_completed_packets_event(sco_connection_handles[0]);
+    if (sco_packets_sent != completed_packets) {
+      ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__,
+            sco_packets_sent, completed_packets);
+    }
+  }
+
+  if (acl_connection_handles.size() > 0) {
+    EXPECT_LT(0, max_acl_data_packet_length);
+    sendAndCheckACL(1, max_acl_data_packet_length, acl_connection_handles[0]);
+    int acl_packets_sent = 1;
+    int completed_packets =
+        wait_for_completed_packets_event(acl_connection_handles[0]);
+    if (acl_packets_sent != completed_packets) {
+      ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__,
+            acl_packets_sent, completed_packets);
+    }
+  }
+}
+
+// Enter loopback mode and send packets for bandwidth measurements.
+TEST_P(BluetoothHidlTest, LoopbackModeBandwidth) {
+  setBufferSizes();
+
+  std::vector<uint16_t> sco_connection_handles;
+  std::vector<uint16_t> acl_connection_handles;
+  enterLoopbackMode(&sco_connection_handles, &acl_connection_handles);
+
+  sendAndCheckHCI(NUM_HCI_COMMANDS_BANDWIDTH);
+
+  // This should work, but breaks on some current platforms.  Figure out how to
+  // grandfather older devices but test new ones.
+  if (0 && sco_connection_handles.size() > 0) {
+    EXPECT_LT(0, max_sco_data_packet_length);
+    sendAndCheckSCO(NUM_SCO_PACKETS_BANDWIDTH, max_sco_data_packet_length,
+                    sco_connection_handles[0]);
+    int sco_packets_sent = NUM_SCO_PACKETS_BANDWIDTH;
+    int completed_packets =
+        wait_for_completed_packets_event(sco_connection_handles[0]);
+    if (sco_packets_sent != completed_packets) {
+      ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__,
+            sco_packets_sent, completed_packets);
+    }
+  }
+
+  if (acl_connection_handles.size() > 0) {
+    EXPECT_LT(0, max_acl_data_packet_length);
+    sendAndCheckACL(NUM_ACL_PACKETS_BANDWIDTH, max_acl_data_packet_length,
+                    acl_connection_handles[0]);
+    int acl_packets_sent = NUM_ACL_PACKETS_BANDWIDTH;
+    int completed_packets =
+        wait_for_completed_packets_event(acl_connection_handles[0]);
+    if (acl_packets_sent != completed_packets) {
+      ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__,
+            acl_packets_sent, completed_packets);
+    }
+  }
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, BluetoothHidlTest,
+    testing::ValuesIn(
+        android::hardware::getAllHalInstanceNames(IBluetoothHci::descriptor)),
+    android::hardware::PrintInstanceNameToString);
diff --git a/bluetooth/audio/2.0/vts/functional/Android.bp b/bluetooth/audio/2.0/vts/functional/Android.bp
index b672fe4..b778b97 100644
--- a/bluetooth/audio/2.0/vts/functional/Android.bp
+++ b/bluetooth/audio/2.0/vts/functional/Android.bp
@@ -9,4 +9,5 @@
     shared_libs: [
         "libfmq",
     ],
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/bluetooth/audio/2.0/vts/functional/VtsHalBluetoothAudioV2_0TargetTest.cpp b/bluetooth/audio/2.0/vts/functional/VtsHalBluetoothAudioV2_0TargetTest.cpp
index 9572d3f..b3cb6f7 100644
--- a/bluetooth/audio/2.0/vts/functional/VtsHalBluetoothAudioV2_0TargetTest.cpp
+++ b/bluetooth/audio/2.0/vts/functional/VtsHalBluetoothAudioV2_0TargetTest.cpp
@@ -21,12 +21,13 @@
 #include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioProvider.h>
 #include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioProvidersFactory.h>
 #include <fmq/MessageQueue.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
 #include <hidl/MQDescriptor.h>
+#include <hidl/ServiceManagement.h>
 #include <utils/Log.h>
 
 #include <VtsHalHidlTargetCallbackBase.h>
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
 
 using ::android::sp;
 using ::android::hardware::hidl_vec;
@@ -105,34 +106,13 @@
 }
 }  // namespace
 
-// Test environment for Bluetooth Audio HAL.
-class BluetoothAudioHidlEnvironment
-    : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
-  // get the test environment singleton
-  static BluetoothAudioHidlEnvironment* Instance() {
-    static BluetoothAudioHidlEnvironment* instance =
-        new BluetoothAudioHidlEnvironment;
-    return instance;
-  }
-
-  virtual void registerTestServices() override {
-    registerTestService<IBluetoothAudioProvidersFactory>();
-  }
-
- private:
-  BluetoothAudioHidlEnvironment() {}
-};
-
 // The base test class for Bluetooth Audio HAL.
 class BluetoothAudioProvidersFactoryHidlTest
-    : public ::testing::VtsHalHidlTargetTestBase {
+    : public ::testing::TestWithParam<std::string> {
  public:
   virtual void SetUp() override {
-    providers_factory_ = ::testing::VtsHalHidlTargetTestBase::getService<
-        IBluetoothAudioProvidersFactory>(
-        BluetoothAudioHidlEnvironment::Instance()
-            ->getServiceName<IBluetoothAudioProvidersFactory>());
+    providers_factory_ =
+        IBluetoothAudioProvidersFactory::getService(GetParam());
     ASSERT_NE(providers_factory_, nullptr);
   }
 
@@ -300,13 +280,13 @@
 /**
  * Test whether we can get the FactoryService from HIDL
  */
-TEST_F(BluetoothAudioProvidersFactoryHidlTest, GetProvidersFactoryService) {}
+TEST_P(BluetoothAudioProvidersFactoryHidlTest, GetProvidersFactoryService) {}
 
 /**
  * Test whether we can open a provider for each provider returned by
  * getProviderCapabilities() with non-empty capabalities
  */
-TEST_F(BluetoothAudioProvidersFactoryHidlTest,
+TEST_P(BluetoothAudioProvidersFactoryHidlTest,
        OpenProviderAndCheckCapabilitiesBySession) {
   for (auto session_type : session_types_) {
     GetProviderCapabilitiesHelper(session_type);
@@ -341,14 +321,14 @@
 /**
  * Test whether we can open a provider of type
  */
-TEST_F(BluetoothAudioProviderA2dpSoftwareHidlTest, OpenA2dpSoftwareProvider) {}
+TEST_P(BluetoothAudioProviderA2dpSoftwareHidlTest, OpenA2dpSoftwareProvider) {}
 
 /**
  * Test whether each provider of type
  * SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH can be started and stopped with
  * different PCM config
  */
-TEST_F(BluetoothAudioProviderA2dpSoftwareHidlTest,
+TEST_P(BluetoothAudioProviderA2dpSoftwareHidlTest,
        StartAndEndA2dpSoftwareSessionWithPossiblePcmConfig) {
   bool is_codec_config_valid;
   std::unique_ptr<DataMQ> tempDataMQ;
@@ -616,14 +596,14 @@
 /**
  * Test whether we can open a provider of type
  */
-TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest, OpenA2dpHardwareProvider) {}
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest, OpenA2dpHardwareProvider) {}
 
 /**
  * Test whether each provider of type
  * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
  * SBC hardware encoding config
  */
-TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest,
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
        StartAndEndA2dpSbcHardwareSession) {
   if (!IsOffloadSupported()) {
     return;
@@ -658,7 +638,7 @@
  * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
  * AAC hardware encoding config
  */
-TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest,
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
        StartAndEndA2dpAacHardwareSession) {
   if (!IsOffloadSupported()) {
     return;
@@ -693,7 +673,7 @@
  * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
  * LDAC hardware encoding config
  */
-TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest,
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
        StartAndEndA2dpLdacHardwareSession) {
   if (!IsOffloadSupported()) {
     return;
@@ -728,7 +708,7 @@
  * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
  * AptX hardware encoding config
  */
-TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest,
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
        StartAndEndA2dpAptxHardwareSession) {
   if (!IsOffloadSupported()) {
     return;
@@ -767,7 +747,7 @@
  * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
  * an invalid codec config
  */
-TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest,
+TEST_P(BluetoothAudioProviderA2dpHardwareHidlTest,
        StartAndEndA2dpHardwareSessionInvalidCodecConfig) {
   if (!IsOffloadSupported()) {
     return;
@@ -857,7 +837,7 @@
  * SessionType::HEARING_AID_HARDWARE_ENCODING_DATAPATH can be started and
  * stopped with SBC hardware encoding config
  */
-TEST_F(BluetoothAudioProviderHearingAidSoftwareHidlTest,
+TEST_P(BluetoothAudioProviderHearingAidSoftwareHidlTest,
        OpenHearingAidSoftwareProvider) {}
 
 /**
@@ -865,7 +845,7 @@
  * SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH can be started and
  * stopped with different PCM config
  */
-TEST_F(BluetoothAudioProviderHearingAidSoftwareHidlTest,
+TEST_P(BluetoothAudioProviderHearingAidSoftwareHidlTest,
        StartAndEndHearingAidSessionWithPossiblePcmConfig) {
   bool is_codec_config_valid;
   std::unique_ptr<DataMQ> tempDataMQ;
@@ -904,12 +884,25 @@
   }      // SampleRate
 }
 
-int main(int argc, char** argv) {
-  ::testing::AddGlobalTestEnvironment(
-      BluetoothAudioHidlEnvironment::Instance());
-  ::testing::InitGoogleTest(&argc, argv);
-  BluetoothAudioHidlEnvironment::Instance()->init(&argc, argv);
-  int status = RUN_ALL_TESTS();
-  LOG(INFO) << "Test result = " << status;
-  return status;
-}
+static const std::vector<std::string> kAudioInstances =
+    android::hardware::getAllHalInstanceNames(
+        IBluetoothAudioProvidersFactory::descriptor);
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProvidersFactoryHidlTest,
+                         testing::ValuesIn(kAudioInstances),
+                         android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderA2dpSoftwareHidlTest,
+                         testing::ValuesIn(kAudioInstances),
+                         android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderA2dpHardwareHidlTest,
+                         testing::ValuesIn(kAudioInstances),
+                         android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderHearingAidSoftwareHidlTest,
+                         testing::ValuesIn(kAudioInstances),
+                         android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/broadcastradio/1.1/default/service.cpp b/broadcastradio/1.1/default/service.cpp
index f8af0b7..29dc76f 100644
--- a/broadcastradio/1.1/default/service.cpp
+++ b/broadcastradio/1.1/default/service.cpp
@@ -20,6 +20,7 @@
 
 #include "BroadcastRadioFactory.h"
 
+using android::sp;
 using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
 using android::hardware::broadcastradio::V1_1::implementation::BroadcastRadioFactory;
@@ -27,8 +28,8 @@
 int main(int /* argc */, char** /* argv */) {
     configureRpcThreadpool(4, true);
 
-    BroadcastRadioFactory broadcastRadioFactory;
-    auto status = broadcastRadioFactory.registerAsService();
+    sp<BroadcastRadioFactory> broadcastRadioFactory(new BroadcastRadioFactory());
+    auto status = broadcastRadioFactory->registerAsService();
     CHECK_EQ(status, android::OK) << "Failed to register Broadcast Radio HAL implementation";
 
     joinRpcThreadpool();
diff --git a/broadcastradio/2.0/default/service.cpp b/broadcastradio/2.0/default/service.cpp
index 349aba2..bd746fd 100644
--- a/broadcastradio/2.0/default/service.cpp
+++ b/broadcastradio/2.0/default/service.cpp
@@ -19,6 +19,7 @@
 #include "BroadcastRadio.h"
 #include "VirtualRadio.h"
 
+using android::sp;
 using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
 using android::hardware::broadcastradio::V2_0::implementation::BroadcastRadio;
@@ -30,13 +31,13 @@
     android::base::SetMinimumLogSeverity(android::base::VERBOSE);
     configureRpcThreadpool(4, true);
 
-    BroadcastRadio broadcastRadio(gAmFmRadio);
-    auto amFmStatus = broadcastRadio.registerAsService("amfm");
+    sp<BroadcastRadio> broadcastRadio(new BroadcastRadio(gAmFmRadio));
+    auto amFmStatus = broadcastRadio->registerAsService("amfm");
     CHECK_EQ(amFmStatus, android::OK)
         << "Failed to register Broadcast Radio AM/FM HAL implementation";
 
-    BroadcastRadio dabRadio(gDabRadio);
-    auto dabStatus = dabRadio.registerAsService("dab");
+    sp<BroadcastRadio> dabRadio(new BroadcastRadio(gDabRadio));
+    auto dabStatus = dabRadio->registerAsService("dab");
     CHECK_EQ(dabStatus, android::OK) << "Failed to register Broadcast Radio DAB HAL implementation";
 
     joinRpcThreadpool();
diff --git a/camera/common/1.0/default/HandleImporter.cpp b/camera/common/1.0/default/HandleImporter.cpp
index 76f9778..ac32c95 100644
--- a/camera/common/1.0/default/HandleImporter.cpp
+++ b/camera/common/1.0/default/HandleImporter.cpp
@@ -252,8 +252,7 @@
         // No need to use bytesPerPixel and bytesPerStride because we are using
         // an 1-D buffer and accressRegion.
         mMapperV4->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
-                        [&](const auto& tmpError, const auto& tmpPtr, const auto& /*bytesPerPixel*/,
-                            const auto& /*bytesPerStride*/) {
+                        [&](const auto& tmpError, const auto& tmpPtr) {
                             if (tmpError == MapperErrorV4::NONE) {
                                 ret = tmpPtr;
                             } else {
@@ -301,7 +300,13 @@
     }
 
     if (mMapperV4 != nullptr) {
-        return lockYCbCrInternal<IMapperV4, MapperErrorV4>(mMapperV4, buf, cpuUsage, accessRegion);
+        // No device currently supports IMapper 4.0 so it is safe to just return an error code here.
+        //
+        // This will be supported by a combination of lock and BufferMetadata getters. We are going
+        // to refactor all the IAllocator/IMapper versioning code into a shared library. We will
+        // then add the IMapper 4.0 lockYCbCr support then.
+        ALOGE("%s: MapperV4 doesn't support lockYCbCr directly!", __FUNCTION__);
+        return {};
     }
 
     if (mMapperV3 != nullptr) {
diff --git a/camera/provider/2.4/vts/functional/Android.bp b/camera/provider/2.4/vts/functional/Android.bp
index 5fe7b19..080fa19 100644
--- a/camera/provider/2.4/vts/functional/Android.bp
+++ b/camera/provider/2.4/vts/functional/Android.bp
@@ -25,6 +25,7 @@
         "libcamera_metadata",
         "libcutils",
         "libfmq",
+        "libgralloctypes",
         "libgui",
         "libui",
     ],
@@ -41,13 +42,7 @@
 	"android.hardware.camera.metadata@3.4",
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.provider@2.5",
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.allocator@3.0",
-        "android.hardware.graphics.allocator@4.0",
         "android.hardware.graphics.common@1.0",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@3.0",
-        "android.hardware.graphics.mapper@4.0",
         "android.hidl.allocator@1.0",
         "libgrallocusage",
         "libhidlmemory",
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 49f9fe1..9416a54 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -26,21 +26,21 @@
 
 #include <inttypes.h>
 
-#include <android/hardware/camera/device/1.0/ICameraDevice.h>
-#include <android/hardware/camera/device/3.2/ICameraDevice.h>
-#include <android/hardware/camera/device/3.5/ICameraDevice.h>
-#include <android/hardware/camera/device/3.3/ICameraDeviceSession.h>
-#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
-#include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
-#include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h>
-#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
-#include <android/hardware/camera/provider/2.4/ICameraProvider.h>
-#include <android/hardware/camera/provider/2.5/ICameraProvider.h>
-#include <android/hardware/camera/metadata/3.4/types.h>
-#include <android/hidl/manager/1.0/IServiceManager.h>
-#include <binder/MemoryHeapBase.h>
 #include <CameraMetadata.h>
 #include <CameraParameters.h>
+#include <android/hardware/camera/device/1.0/ICameraDevice.h>
+#include <android/hardware/camera/device/3.2/ICameraDevice.h>
+#include <android/hardware/camera/device/3.3/ICameraDeviceSession.h>
+#include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h>
+#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
+#include <android/hardware/camera/device/3.5/ICameraDevice.h>
+#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
+#include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
+#include <android/hardware/camera/metadata/3.4/types.h>
+#include <android/hardware/camera/provider/2.4/ICameraProvider.h>
+#include <android/hardware/camera/provider/2.5/ICameraProvider.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <binder/MemoryHeapBase.h>
 #include <cutils/properties.h>
 #include <fmq/MessageQueue.h>
 #include <grallocusage/GrallocUsageConversion.h>
@@ -52,14 +52,9 @@
 #include <system/camera.h>
 #include <system/camera_metadata.h>
 #include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/GraphicBufferMapper.h>
 
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
-#include <android/hardware/graphics/allocator/4.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <android/hardware/graphics/mapper/2.0/types.h>
-#include <android/hardware/graphics/mapper/3.0/IMapper.h>
-#include <android/hardware/graphics/mapper/4.0/IMapper.h>
 #include <android/hidl/allocator/1.0/IAllocator.h>
 #include <android/hidl/memory/1.0/IMapper.h>
 #include <android/hidl/memory/1.0/IMemory.h>
@@ -1494,7 +1489,7 @@
         ADD_FAILURE();
     }
 
-    std::lock_guard<std::mutex> l(mLock);
+    std::unique_lock<std::mutex> l(mLock);
     for (const auto& buf : buffers) {
         bool found = false;
         for (size_t idx = 0; idx < mOutstandingBufferIds.size(); idx++) {
@@ -1514,6 +1509,10 @@
         ALOGE("%s: unknown buffer ID %" PRIu64, __FUNCTION__, buf.bufferId);
         ADD_FAILURE();
     }
+    if (!hasOutstandingBuffersLocked()) {
+        l.unlock();
+        mFlushedCondition.notify_one();
+    }
     return Void();
 }
 
@@ -6307,102 +6306,15 @@
         PixelFormat format, hidl_handle *buffer_handle /*out*/) {
     ASSERT_NE(buffer_handle, nullptr);
 
-    sp<android::hardware::graphics::allocator::V2_0::IAllocator> allocator =
-        android::hardware::graphics::allocator::V2_0::IAllocator::getService();
-    sp<android::hardware::graphics::allocator::V3_0::IAllocator> allocatorV3 =
-        android::hardware::graphics::allocator::V3_0::IAllocator::getService();
-    sp<android::hardware::graphics::allocator::V4_0::IAllocator> allocatorV4 =
-            android::hardware::graphics::allocator::V4_0::IAllocator::getService();
+    buffer_handle_t buffer;
+    uint32_t stride;
 
-    sp<android::hardware::graphics::mapper::V4_0::IMapper> mapperV4 =
-            android::hardware::graphics::mapper::V4_0::IMapper::getService();
-    sp<android::hardware::graphics::mapper::V3_0::IMapper> mapperV3 =
-        android::hardware::graphics::mapper::V3_0::IMapper::getService();
-    sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper =
-        android::hardware::graphics::mapper::V2_0::IMapper::getService();
-    if (mapperV4 != nullptr && allocatorV4 != nullptr) {
-        ::android::hardware::hidl_vec<uint8_t> descriptor;
-        android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo descriptorInfo{};
-        descriptorInfo.name = "VtsHalCameraProviderV2_4";
-        descriptorInfo.width = width;
-        descriptorInfo.height = height;
-        descriptorInfo.layerCount = 1;
-        descriptorInfo.format =
-                static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
-        descriptorInfo.usage = usage;
+    android::status_t err = android::GraphicBufferAllocator::get().allocate(
+            width, height, static_cast<int32_t>(format), 1u /*layerCount*/, usage, &buffer, &stride,
+            "VtsHalCameraProviderV2_4");
+    ASSERT_EQ(err, android::NO_ERROR);
 
-        auto ret = mapperV4->createDescriptor(
-                descriptorInfo, [&descriptor](android::hardware::graphics::mapper::V4_0::Error err,
-                                              ::android::hardware::hidl_vec<uint8_t> desc) {
-                    ASSERT_EQ(err, android::hardware::graphics::mapper::V4_0::Error::NONE);
-                    descriptor = desc;
-                });
-        ASSERT_TRUE(ret.isOk());
-
-        ret = allocatorV4->allocate(
-                descriptor, 1u,
-                [&](android::hardware::graphics::mapper::V4_0::Error err, uint32_t /*stride*/,
-                    const ::android::hardware::hidl_vec<::android::hardware::hidl_handle>&
-                            buffers) {
-                    ASSERT_EQ(android::hardware::graphics::mapper::V4_0::Error::NONE, err);
-                    ASSERT_EQ(buffers.size(), 1u);
-                    *buffer_handle = buffers[0];
-                });
-        ASSERT_TRUE(ret.isOk());
-    } else if (mapperV3 != nullptr && allocatorV3 != nullptr) {
-        ::android::hardware::hidl_vec<uint32_t> descriptor;
-        android::hardware::graphics::mapper::V3_0::IMapper::BufferDescriptorInfo descriptorInfo {};
-        descriptorInfo.width = width;
-        descriptorInfo.height = height;
-        descriptorInfo.layerCount = 1;
-        descriptorInfo.format =
-                static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
-        descriptorInfo.usage = usage;
-
-        auto ret = mapperV3->createDescriptor(
-            descriptorInfo, [&descriptor](android::hardware::graphics::mapper::V3_0::Error err,
-                                ::android::hardware::hidl_vec<uint32_t> desc) {
-                ASSERT_EQ(err, android::hardware::graphics::mapper::V3_0::Error::NONE);
-                descriptor = desc;
-            });
-        ASSERT_TRUE(ret.isOk());
-
-        ret = allocatorV3->allocate(descriptor, 1u,
-            [&](android::hardware::graphics::mapper::V3_0::Error err, uint32_t /*stride*/,
-                const ::android::hardware::hidl_vec<::android::hardware::hidl_handle>& buffers) {
-                ASSERT_EQ(android::hardware::graphics::mapper::V3_0::Error::NONE, err);
-                ASSERT_EQ(buffers.size(), 1u);
-                *buffer_handle = buffers[0];
-            });
-        ASSERT_TRUE(ret.isOk());
-    } else {
-        ::android::hardware::hidl_vec<uint32_t> descriptor;
-        ASSERT_NE(mapper.get(), nullptr);
-        ASSERT_NE(allocator.get(), nullptr);
-        android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo {};
-        descriptorInfo.width = width;
-        descriptorInfo.height = height;
-        descriptorInfo.layerCount = 1;
-        descriptorInfo.format = format;
-        descriptorInfo.usage = usage;
-
-        auto ret = mapper->createDescriptor(
-            descriptorInfo, [&descriptor](android::hardware::graphics::mapper::V2_0::Error err,
-                                ::android::hardware::hidl_vec<uint32_t> desc) {
-                ASSERT_EQ(err, android::hardware::graphics::mapper::V2_0::Error::NONE);
-                descriptor = desc;
-            });
-        ASSERT_TRUE(ret.isOk());
-
-        ret = allocator->allocate(descriptor, 1u,
-            [&](android::hardware::graphics::mapper::V2_0::Error err, uint32_t /*stride*/,
-                const ::android::hardware::hidl_vec<::android::hardware::hidl_handle>& buffers) {
-                ASSERT_EQ(android::hardware::graphics::mapper::V2_0::Error::NONE, err);
-                ASSERT_EQ(buffers.size(), 1u);
-                *buffer_handle = buffers[0];
-            });
-        ASSERT_TRUE(ret.isOk());
-    }
+    buffer_handle->setTo(const_cast<native_handle_t*>(buffer), true /*shouldOwn*/);
 }
 
 void CameraHidlTest::verifyRecommendedConfigs(const CameraMetadata& chars) {
diff --git a/cas/1.2/Android.bp b/cas/1.2/Android.bp
index af98b2e..fbb38b0 100644
--- a/cas/1.2/Android.bp
+++ b/cas/1.2/Android.bp
@@ -7,10 +7,10 @@
         enabled: true,
     },
     srcs: [
+        "types.hal",
         "ICas.hal",
         "ICasListener.hal",
         "IMediaCasService.hal",
-        "types.hal",
     ],
     interfaces: [
         "android.hardware.cas@1.0",
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index 799ab07..7883dd9 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -83,8 +83,8 @@
         "compatibility_matrix.current.xml",
     ],
     kernel_configs: [
-        "kernel_config_current_4.9",
         "kernel_config_current_4.14",
         "kernel_config_current_4.19",
+        "kernel_config_current_5.4",
     ]
 }
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index fb8d395..b0a82a5 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -49,6 +49,13 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.automotive.occupant_awareness</name>
+        <interface>
+            <name>IOccupantAwareness</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.automotive.vehicle</name>
         <version>2.0</version>
@@ -75,7 +82,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.bluetooth</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IBluetoothHci</name>
             <instance>default</instance>
@@ -155,7 +162,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.drm</name>
-        <version>1.0-2</version>
+        <version>1.0-3</version>
         <interface>
             <name>ICryptoFactory</name>
             <regex-instance>.*</regex-instance>
@@ -189,7 +196,7 @@
          - test DeviceManifestTest#GnssHalVersionCompatibility.
         -->
         <version>1.1</version>
-        <version>2.0</version>
+        <version>2.0-1</version>
         <interface>
             <name>IGnss</name>
             <instance>default</instance>
@@ -256,7 +263,7 @@
     <hal format="hidl" optional="false">
         <name>android.hardware.keymaster</name>
         <version>3.0</version>
-        <version>4.0</version>
+        <version>4.0-1</version>
         <interface>
             <name>IKeymasterDevice</name>
             <instance>default</instance>
@@ -264,7 +271,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.keymaster</name>
-        <version>4.0</version>
+        <version>4.0-1</version>
         <interface>
             <name>IKeymasterDevice</name>
             <instance>strongbox</instance>
@@ -280,7 +287,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.media.c2</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IComponentStore</name>
             <regex-instance>default[0-9]*</regex-instance>
@@ -349,7 +356,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.radio</name>
-        <version>1.4</version>
+        <version>1.5</version>
         <interface>
             <name>IRadio</name>
             <instance>slot1</instance>
@@ -367,10 +374,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.radio.config</name>
-        <!--
-        See compatibility_matrix.4.xml on versioning of radio config HAL.
-        -->
-        <version>1.1</version>
+        <version>1.3</version>
         <interface>
             <name>IRadioConfig</name>
             <instance>default</instance>
@@ -508,7 +512,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.wifi.hostapd</name>
-        <version>1.0-1</version>
+        <version>1.0-2</version>
         <interface>
             <name>IHostapd</name>
             <instance>default</instance>
diff --git a/configstore/1.1/default/seccomp_policy/configstore@1.1-arm64.policy b/configstore/1.1/default/seccomp_policy/configstore@1.1-arm64.policy
index 937fddd..a609620 100644
--- a/configstore/1.1/default/seccomp_policy/configstore@1.1-arm64.policy
+++ b/configstore/1.1/default/seccomp_policy/configstore@1.1-arm64.policy
@@ -45,6 +45,7 @@
 getdents64: 1
 clock_gettime: 1
 getpid: 1
+gettid: 1
 
 # used during process crash by crash_dump to dump process info
 rt_sigprocmask: 1
diff --git a/current.txt b/current.txt
index b46f37f..cdd98a9 100644
--- a/current.txt
+++ b/current.txt
@@ -576,35 +576,79 @@
 b69a7615c508acf5c5201efd1bfa3262167874fc3594e2db5a3ff93addd8ac75 android.hardware.keymaster@4.0::IKeymasterDevice
 eb2fa0c883c2185d514be0b84c179b283753ef0c1b77b45b4f359bd23bba8b75 android.hardware.neuralnetworks@1.0::IPreparedModel
 f1109cbb10297b7429a11fab42afa912710b303c9bf20bd5cdb8bd57b9c84186 android.hardware.neuralnetworks@1.0::types
-9d8ee57c490ffeaa28f702eaea8d198cb510e4bbfb99e6cb5f63e73341057c7c android.hardware.neuralnetworks@1.1::types
+5f6d3097ba84cb63c430787123f4de1b31c11f90b531b98eae9a8623a5ae962a android.hardware.neuralnetworks@1.1::types
 fb382e986c10b8fbb797a8546e8f9ea6d1107bfe6f3fb7e57f6bbbf1f807a906 android.hardware.neuralnetworks@1.2::IDevice
 40e71cd693de5b832325c5d8f081f2ff20a7ba2b89d401cee5b4b3eb0e241681 android.hardware.neuralnetworks@1.2::IPreparedModel
-71c0f7127335e5b74d1615d5e7f129831b43ffbae5318ad0924d7d8d8910a859 android.hardware.neuralnetworks@1.2::types
+2d5483fbf59d5fd2de94665a6df05da5c3d09de67561d0db5e9f09e59e9aea46 android.hardware.neuralnetworks@1.2::types
 a785a57447a81e9c130eef6904c3a5c256076c6a04588c40620ebd6fa2660d77 android.hardware.radio@1.2::types
 1a6e2bd289f22931c526b21916910f1d4c436b7acb9556e4243de4ce8e6cc2e4 android.hardware.soundtrigger@2.0::ISoundTriggerHwCallback
 fd65298e1e09e0e3c781ab18305920d757dbe55a3b459ce17814ec5cf6dfee99 android.hardware.wifi@1.0::IWifiP2pIface
 
 # HALs released in Android R
+e966a3437d6a98d9d9e14e9d672088771716031900c0deb55a0946c751a03a44 android.hardware.audio@6.0::types
+2736c59abaccacac407ebe80c5e48d446edf015051d05632fb679ba471779e6e android.hardware.audio@6.0::IDevice
+2402876cbc23c0de3690a665eca84fd3857d1808dba5cad25ce272f81ecef8c9 android.hardware.audio@6.0::IDevicesFactory
+bca5379d5065e2e08b6ad7308ffc8a71a972fc0698bec678ea32eea786d01cb5 android.hardware.audio@6.0::IPrimaryDevice
+7318b521ea12fdd4b6e3f381085c71784c810d1ec7a8d701ec2250f3f86712e4 android.hardware.audio@6.0::IStream
+2df5d5866b37776f25079c0e54b54350a2abe4e025a59c9e02a7d3abe8ca00e8 android.hardware.audio@6.0::IStreamIn
+78e4138cc8307c11fc777c3bd376e581ba4ba48196b05ca1d7cdfa515c87b48a android.hardware.audio@6.0::IStreamOut
+997fdaad7a9d17ee7e01feb7031a753e2365e72ad30b11d950e9183fabdf3844 android.hardware.audio@6.0::IStreamOutCallback
+0b291ebd7e94dd1cfaadd41a8b9a80bc9389bbb76f5ad5b3df94db5fe7faea9d android.hardware.audio.common@6.0::types
+817930d58412d662cb45e641c50cb62c727e4a3e3ffe7029a53cad9677b97d58 android.hardware.audio.effect@6.0::types
+525bec6b44f1103869c269a128d51b8dccd73af5340ba863c8886c68357c7faf android.hardware.audio.effect@6.0::IAcousticEchoCancelerEffect
+8d76bbe3719d051a8e9a1dcf9244f37f5b0a491feb249fa48391edf7cb4f3131 android.hardware.audio.effect@6.0::IAutomaticGainControlEffect
+461b1114cb35d89f87e5694e0792ba53c112a7fa9a14d9b95188cf9c4764be23 android.hardware.audio.effect@6.0::IBassBoostEffect
+8bc597d166e07e9eba633267fc2872c4c53d13d3f0025b778c98e13324a165de android.hardware.audio.effect@6.0::IDownmixEffect
+9ee022c81e79da6051fde0836c1c1c4d5414e0c9a6cccc0ce17a90346ceb1391 android.hardware.audio.effect@6.0::IEffect
+75c99a70577d543359910a0b378bcbf5a0d6076712e58e6864cd8803f76c8684 android.hardware.audio.effect@6.0::IEffectBufferProviderCallback
+5910bdd600fc6501a67233a9a3f4f21dda86af08c05497322712600131d1fa8f android.hardware.audio.effect@6.0::IEffectsFactory
+dd377f404a8e71f6191d295e10067db629b0f0c28e594af906f2bea5d87fe2cc android.hardware.audio.effect@6.0::IEnvironmentalReverbEffect
+455e085e136767302ec34d02b51a085c310e79bf500b76dda7c96a7f3637f11a android.hardware.audio.effect@6.0::IEqualizerEffect
+24b5e107a0cbd2b322f764a4d5f7fb8b5d8c337a060b9a4a26b9af050c57b5d0 android.hardware.audio.effect@6.0::ILoudnessEnhancerEffect
+4aae0a13f53a8ce20fad372de2d1d864a0bae194b0f1b1d2c090367af8615af2 android.hardware.audio.effect@6.0::INoiseSuppressionEffect
+5237c42d3913ef569f07bec802568084b615155d05a7951e75085da54856508c android.hardware.audio.effect@6.0::IPresetReverbEffect
+282193799d60bff27a84c65a36218c1e7d8f582f5828e2e059383d1b90aa56bd android.hardware.audio.effect@6.0::IVirtualizerEffect
+0868e00f7c5ee16723bda1a8f57099763d04100ae7126a1c2d3a9a87c844a7e8 android.hardware.audio.effect@6.0::IVisualizerEffect
+79e115c8f8970b8b914bafc66df5425e065fda4dcda97222966ef12451d2a1cc android.hardware.bluetooth@1.1::IBluetoothHci
+40ab2c6866c18d32baf6e49e3053949e79601f56963a791e93e68b9ee18f718d android.hardware.bluetooth@1.1::IBluetoothHciCallbacks
 07d0a252b2d8fa35887908a996ba395cf392968395fc30afab791f46e0c22a52 android.hardware.boot@1.1::IBootControl
 74049a402be913963edfdd80828a53736570e9d8124a1bf18166b6ed46a6b0ab android.hardware.boot@1.1::types
 c1aa508d00b66ed5feefea398fd5edf28fa651ac89773adad7dfda4e0a73a952 android.hardware.cas@1.2::ICas
 9811f867def49b420d8c707f7e38d3bdd64f835244e1d2a5e9762ab9835672dc android.hardware.cas@1.2::ICasListener
 f18695dd36ee205640b8326a17453858a7b4596653aaa6ef0016b0aef1bd4dac android.hardware.cas@1.2::IMediaCasService
 4d85e814f94949dae4dc6cb82bbd7d6bb24ffafda6ddb2eac928d2a4fc2e21ce android.hardware.cas@1.2::types
+66931c2506fbb5af61f20138cb05e0a09e7bf67d6964c231d27c648933bb33ec android.hardware.drm@1.3::ICryptoFactory
+994d08ab27d613022c258a9ec48cece7adf2a305e92df5d76ef923e2c6665f64 android.hardware.drm@1.3::IDrmFactory
+3dacec7801968e1e4479724dc0180442d9e915466bff051f80996266b1a51c2c android.hardware.gnss@2.1::IGnss
+ba62e1e8993bfb9f27fa04816fa0f2241ae2d01edfa3d0c04182e2e5de80045c android.hardware.gnss@2.1::IGnssCallback
+ccdf3c0fb2c02a6d4dc57afb276c3497ae8172b80b00ebc0bf8a0238dd38b01d android.hardware.gnss@2.1::IGnssConfiguration
+5a125c49ca83629e22afc8c39e865509343bfa2c38f0baea9a186bbac103492d android.hardware.gnss@2.1::IGnssMeasurement
+0bfb291708dd4a7c6ec6b9883e2b8592357edde8d7e962ef83918e4a2154ce69 android.hardware.gnss@2.1::IGnssMeasurementCallback
 ce8dbe76eb9ee94b46ef98f725be992e760a5751073d4f4912484026541371f3 android.hardware.health@2.1::IHealth
 26f04510a0b57aba5167c5c0a7c2f077c2acbb98b81902a072517829fd9fd67f android.hardware.health@2.1::IHealthInfoCallback
 db47f4ceceb1f06c656f39caa70c557b0f8471ef59fd58611bea667ffca20101 android.hardware.health@2.1::types
+c228aaa27f66c48e147159a4f4996c5273191fece1b08de31bd171c61334855e android.hardware.keymaster@4.1::IKeymasterDevice
+adb0efdf1462e9b2e742c0dcadd598666aac551f178be06e755bfcdf5797abd0 android.hardware.keymaster@4.1::IOperation
+7a04ea5595ed418ca3e91c28b8bd7353dd988be9be7b0c8c9e64fb4b77bd4523 android.hardware.keymaster@4.1::types
+df9c79c4fdde2821550c6d5c3d07f5ec0adfb1b702561ce543c906ddef698703 android.hardware.media.c2@1.1::IComponent
+a3eddd9bbdc87e8c22764070037dd1154f1cf006e6fba93364c4f85d4c134a19 android.hardware.media.c2@1.1::IComponentStore
 9e59fffceed0dd72a9799e04505db5f777bbbea1af0695ba4107ef6d967c6fda android.hardware.neuralnetworks@1.3::IDevice
 258825966435b3ed08832055bb736d81516013e405f161d9ccde9a90cfcdde83 android.hardware.neuralnetworks@1.3::IPreparedModel
 94e803236398bed1febb11cc21051bc42ec003700139b099d6c479e02a7ca3c3 android.hardware.neuralnetworks@1.3::IPreparedModelCallback
-c511b1427b1c3f76af90967bbddaaf250db983a8d3abb9ff189fb5a807cf3d4d android.hardware.neuralnetworks@1.3::types
+cf1d55e8c68300090747ab90b94c22e4c859b29c84ced68a317c595bb115eab2 android.hardware.neuralnetworks@1.3::types
 3e01d4446cd69fd1c48f8572efd97487bc179564b32bd795800b97bbe10be37b android.hardware.wifi@1.4::IWifi
+03d37dfebbc27b13adce1ed6389ac483bf7cf32488ca14037c5569bc3e903e4f android.hardware.wifi.hostapd@1.2::IHostapd
+2defa258951e25a132aaeb36e3febe6f41bf9c6dbb1b1ebdf0b41708ab4e107e android.hardware.wifi.hostapd@1.2::types
 a64467bae843569f0d465c5be7f0c7a5b987985b55a3ef4794dd5afc68538650 android.hardware.wifi.supplicant@1.3::ISupplicant
 44445b8a03d7b9e68b2fbd954672c18a8fce9e32851b0692f4f4ab3407f86ecb android.hardware.wifi.supplicant@1.3::ISupplicantStaIface
 619fc9839ec6e369cfa9b28e3e9412e6885720ff8f9b5750c1b6ffb905120391 android.hardware.wifi.supplicant@1.3::ISupplicantStaIfaceCallback
 c9273429fcf98d797d3bb07fdba6f1be95bf960f9255cde169fd1ca4db85f856 android.hardware.wifi.supplicant@1.3::ISupplicantStaNetwork
 9b0a3ab6f4f74b971ed094426d8a443e29b512ff03e1ab50c07156396cdb2483 android.hardware.wifi.supplicant@1.3::types
-d3636ff9d5fef59f59f678887209156b2608d29f676fb1e600fe33b7e57a8a61 android.hardware.radio@1.5::types
-c8e81d912827a5d49b2ddcdc4eb4556c5d231a899a1dca879309e04210daa4a0 android.hardware.radio@1.5::IRadio
-a62a93faf173b14a6175b683ebf61ffa568dc61f81e369d2dce7b1265e86cf2f android.hardware.radio@1.5::IRadioIndication
-260ce05806d753d728f844d405e832179ed7d9b65986ec18fef3d21cf7285587 android.hardware.radio@1.5::IRadioResponse
+eaf870a7439838c66127a74e1896c4a2346979c116eb1931785ebb4d353230ae android.hardware.radio@1.5::types
+584001c25a16e3a29d496cff28dee690833cd2bda5376febe01cecd476ce876f android.hardware.radio@1.5::IRadio
+3afac66f21a33bc9c4b80481c7d5540038348651d9a7d8af64ea13610af138da android.hardware.radio@1.5::IRadioIndication
+caf00e0d942b77b17d7061b38de11e5b19e1da90d4818434cb4916ba89e30686 android.hardware.radio@1.5::IRadioResponse
+55f0a15642869ec98a55ea0a5ac049d3e1a6245ff7750deb6bcb7182057eee83 android.hardware.radio.config@1.3::types
+b27ab0cd40b0b078cdcd024bfe1061c4c4c065f3519eeb9347fa359a3268a5ae android.hardware.radio.config@1.3::IRadioConfig
+742360c775313438b0f82256eac62fb5bbc76a6ae6f388573f3aa142fb2c1eea android.hardware.radio.config@1.3::IRadioConfigIndication
+7683fed9d253956071f18b152e6be657719536f98d9b534433d5e411bcde5061 android.hardware.radio.config@1.3::IRadioConfigResponse
diff --git a/drm/1.0/Android.bp b/drm/1.0/Android.bp
index a950c57..9049af2 100644
--- a/drm/1.0/Android.bp
+++ b/drm/1.0/Android.bp
@@ -17,5 +17,5 @@
     interfaces: [
         "android.hidl.base@1.0",
     ],
-    gen_java: false,
+    gen_java: true,
 }
diff --git a/drm/1.3/Android.bp b/drm/1.3/Android.bp
new file mode 100644
index 0000000..b0ffcb9
--- /dev/null
+++ b/drm/1.3/Android.bp
@@ -0,0 +1,20 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.drm@1.3",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "IDrmFactory.hal",
+        "ICryptoFactory.hal",
+    ],
+    interfaces: [
+        "android.hardware.drm@1.0",
+        "android.hardware.drm@1.1",
+        "android.hardware.drm@1.2",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: false,
+}
diff --git a/drm/1.3/ICryptoFactory.hal b/drm/1.3/ICryptoFactory.hal
new file mode 100644
index 0000000..d7864eb
--- /dev/null
+++ b/drm/1.3/ICryptoFactory.hal
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+package android.hardware.drm@1.3;
+
+import @1.2::ICryptoFactory;
+
+/**
+ * ICryptoFactory is the main entry point for interacting with a vendor's
+ * crypto HAL to create crypto plugins. Crypto plugins create crypto sessions
+ * which are used by a codec to decrypt protected video content.
+ *
+ * The 1.3 factory must always create 1.2 ICryptoPlugin interfaces, which are
+ * returned via the 1.0 createPlugin method.
+ *
+ * The ICryptoFactory hal is required because all top-level interfaces
+ * have to be updated in a minor uprev.
+ */
+interface ICryptoFactory extends @1.2::ICryptoFactory {
+};
diff --git a/drm/1.3/IDrmFactory.hal b/drm/1.3/IDrmFactory.hal
new file mode 100644
index 0000000..5208028
--- /dev/null
+++ b/drm/1.3/IDrmFactory.hal
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+package android.hardware.drm@1.3;
+
+import @1.2::IDrmFactory;
+
+/**
+ * IDrmFactory is the main entry point for interacting with a vendor's
+ * drm HAL to create drm plugin instances. A drm plugin instance
+ * creates drm sessions which are used to obtain keys for a crypto
+ * session so it can decrypt protected video content.
+ *
+ * The 1.3 factory must always create 1.2 IDrmPlugin interfaces, which are
+ * returned via the 1.0 createPlugin method.
+ */
+
+interface IDrmFactory extends @1.2::IDrmFactory {
+    /**
+     * Return vector of uuids identifying crypto schemes supported by this HAL.
+     *
+     * @return schemes Vector of uuids for which isCryptoSchemeSupported is true;
+     *                 each uuid can be used as input to createPlugin.
+     */
+    getSupportedCryptoSchemes() generates(vec<uint8_t[16]> schemes);
+};
diff --git a/gatekeeper/1.0/vts/functional/Android.bp b/gatekeeper/1.0/vts/functional/Android.bp
index f55e5d2..a115285 100644
--- a/gatekeeper/1.0/vts/functional/Android.bp
+++ b/gatekeeper/1.0/vts/functional/Android.bp
@@ -19,5 +19,5 @@
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalGatekeeperV1_0TargetTest.cpp"],
     static_libs: ["android.hardware.gatekeeper@1.0"],
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp b/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
index 715e9fc..afc737c 100644
--- a/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
+++ b/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
@@ -24,7 +24,10 @@
 #include <inttypes.h>
 #include <unistd.h>
 
+#include <gtest/gtest.h>
 #include <hardware/hw_auth_token.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include <android/log.h>
 #include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
@@ -32,9 +35,6 @@
 
 #include <log/log.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
-
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
 using ::android::hardware::gatekeeper::V1_0::IGatekeeper;
@@ -78,22 +78,8 @@
   return auth_token;
 }
 
-// Test environment for Gatekeeper HIDL HAL.
-class GatekeeperHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
-  // get the test environment singleton
-  static GatekeeperHidlEnvironment* Instance() {
-    static GatekeeperHidlEnvironment* instance = new GatekeeperHidlEnvironment;
-    return instance;
-  }
-
-  virtual void registerTestServices() override { registerTestService<IGatekeeper>(); }
- private:
-  GatekeeperHidlEnvironment() {}
-};
-
 // The main test class for Gatekeeper HIDL HAL.
-class GatekeeperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class GatekeeperHidlTest : public ::testing::TestWithParam<std::string> {
  protected:
   void setUid(uint32_t uid) { uid_ = uid; }
 
@@ -204,8 +190,7 @@
   GatekeeperHidlTest() : uid_(0) {}
   virtual void SetUp() override {
     GatekeeperResponse rsp;
-    gatekeeper_ = ::testing::VtsHalHidlTargetTestBase::getService<IGatekeeper>(
-        GatekeeperHidlEnvironment::Instance()->getServiceName<IGatekeeper>());
+    gatekeeper_ = IGatekeeper::getService(GetParam());
     ASSERT_NE(nullptr, gatekeeper_.get());
     doDeleteAllUsers(rsp);
   }
@@ -219,7 +204,7 @@
 /**
  * Ensure we can enroll new password
  */
-TEST_F(GatekeeperHidlTest, EnrollSuccess) {
+TEST_P(GatekeeperHidlTest, EnrollSuccess) {
   hidl_vec<uint8_t> password;
   GatekeeperResponse rsp;
   ALOGI("Testing Enroll (expected success)");
@@ -231,7 +216,7 @@
 /**
  * Ensure we can not enroll empty password
  */
-TEST_F(GatekeeperHidlTest, EnrollNoPassword) {
+TEST_P(GatekeeperHidlTest, EnrollNoPassword) {
   hidl_vec<uint8_t> password;
   GatekeeperResponse rsp;
   ALOGI("Testing Enroll (expected failure)");
@@ -242,7 +227,7 @@
 /**
  * Ensure we can successfully verify previously enrolled password
  */
-TEST_F(GatekeeperHidlTest, VerifySuccess) {
+TEST_P(GatekeeperHidlTest, VerifySuccess) {
   GatekeeperResponse enrollRsp;
   GatekeeperResponse verifyRsp;
   hidl_vec<uint8_t> password;
@@ -258,7 +243,7 @@
  * Ensure we can securely update password (keep the same
  * secure user_id) if we prove we know old password
  */
-TEST_F(GatekeeperHidlTest, TrustedReenroll) {
+TEST_P(GatekeeperHidlTest, TrustedReenroll) {
   GatekeeperResponse enrollRsp;
   GatekeeperRequest reenrollReq;
   GatekeeperResponse reenrollRsp;
@@ -297,7 +282,7 @@
  * Ensure we can update password (and get new
  * secure user_id) if we don't know old password
  */
-TEST_F(GatekeeperHidlTest, UntrustedReenroll) {
+TEST_P(GatekeeperHidlTest, UntrustedReenroll) {
   GatekeeperResponse enrollRsp;
   GatekeeperResponse reenrollRsp;
   GatekeeperResponse verifyRsp;
@@ -327,7 +312,7 @@
 /**
  * Ensure we dont get successful verify with invalid data
  */
-TEST_F(GatekeeperHidlTest, VerifyNoData) {
+TEST_P(GatekeeperHidlTest, VerifyNoData) {
   hidl_vec<uint8_t> password;
   hidl_vec<uint8_t> passwordHandle;
   GatekeeperResponse verifyRsp;
@@ -341,7 +326,7 @@
 /**
  * Ensure we can not verify password after we enrolled it and then deleted user
  */
-TEST_F(GatekeeperHidlTest, DeleteUserTest) {
+TEST_P(GatekeeperHidlTest, DeleteUserTest) {
   hidl_vec<uint8_t> password;
   GatekeeperResponse enrollRsp;
   GatekeeperResponse verifyRsp;
@@ -368,7 +353,7 @@
 /**
  * Ensure we can not delete a user that does not exist
  */
-TEST_F(GatekeeperHidlTest, DeleteInvalidUserTest) {
+TEST_P(GatekeeperHidlTest, DeleteInvalidUserTest) {
   hidl_vec<uint8_t> password;
   GatekeeperResponse enrollRsp;
   GatekeeperResponse verifyRsp;
@@ -400,7 +385,7 @@
  * Ensure we can not verify passwords after we enrolled them and then deleted
  * all users
  */
-TEST_F(GatekeeperHidlTest, DeleteAllUsersTest) {
+TEST_P(GatekeeperHidlTest, DeleteAllUsersTest) {
   struct UserData {
     uint32_t userId;
     hidl_vec<uint8_t> password;
@@ -448,11 +433,7 @@
   ALOGI("Testing deleteAllUsers done: rsp=%" PRIi32, delAllRsp.code);
 }
 
-int main(int argc, char **argv) {
-  ::testing::AddGlobalTestEnvironment(GatekeeperHidlEnvironment::Instance());
-  ::testing::InitGoogleTest(&argc, argv);
-  GatekeeperHidlEnvironment::Instance()->init(&argc, argv);
-  int status = RUN_ALL_TESTS();
-  ALOGI("Test result = %d", status);
-  return status;
-}
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, GatekeeperHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IGatekeeper::descriptor)),
+        android::hardware::PrintInstanceNameToString);
diff --git a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
index 1a80ecf..6183a1a 100644
--- a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
+++ b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
@@ -22,6 +22,7 @@
 #include <log/log.h>
 
 #include <chrono>
+#include <cmath>
 #include <condition_variable>
 #include <mutex>
 
@@ -403,6 +404,34 @@
 }
 
 /*
+ * InjectSeedLocation:
+ * Injects a seed location and ensures the injected seed location is not fused in the resulting
+ * GNSS location.
+ */
+TEST_P(GnssHalTest, InjectSeedLocation) {
+    // An arbitrary position in North Pacific Ocean (where no VTS labs will ever likely be located).
+    const double seedLatDegrees = 32.312894;
+    const double seedLngDegrees = -172.954117;
+    const float seedAccuracyMeters = 150.0;
+
+    auto result = gnss_hal_->injectLocation(seedLatDegrees, seedLngDegrees, seedAccuracyMeters);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+
+    StartAndGetSingleLocation(false);
+
+    // Ensure we don't get a location anywhere within 111km (1 degree of lat or lng) of the seed
+    // location.
+    EXPECT_TRUE(std::abs(last_location_.latitudeDegrees - seedLatDegrees) > 1.0 ||
+                std::abs(last_location_.longitudeDegrees - seedLngDegrees) > 1.0);
+
+    StopAndClearLocations();
+
+    auto resultVoid = gnss_hal_->deleteAidingData(IGnss::GnssAidingData::DELETE_POSITION);
+    ASSERT_TRUE(resultVoid.isOk());
+}
+
+/*
  * GetAllExtentions:
  * Tries getting all optional extensions, and ensures a valid return
  *   null or actual extension, no crash.
diff --git a/gnss/1.1/default/Android.bp b/gnss/1.1/default/Android.bp
index 95bd7f3..9c498d5 100644
--- a/gnss/1.1/default/Android.bp
+++ b/gnss/1.1/default/Android.bp
@@ -14,6 +14,8 @@
         "libhidlbase",
         "libutils",
         "liblog",
+        "android.hardware.gnss@2.1",
+        "android.hardware.gnss@2.0",
         "android.hardware.gnss@1.1",
         "android.hardware.gnss@1.0",
     ],
diff --git a/gnss/1.1/default/Gnss.cpp b/gnss/1.1/default/Gnss.cpp
index 4abe707..5043649 100644
--- a/gnss/1.1/default/Gnss.cpp
+++ b/gnss/1.1/default/Gnss.cpp
@@ -44,7 +44,7 @@
             auto svStatus = this->getMockSvStatus();
             this->reportSvStatus(svStatus);
 
-            auto location = Utils::getMockLocation();
+            auto location = Utils::getMockLocationV1_0();
             this->reportLocation(location);
 
             std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
@@ -197,14 +197,14 @@
 Return<GnssSvStatus> Gnss::getMockSvStatus() const {
     std::unique_lock<std::recursive_mutex> lock(mGnssConfiguration->getMutex());
     GnssSvInfo mockGnssSvInfoList[] = {
-            Utils::getSvInfo(3, GnssConstellationType::GPS, 32.5, 59.1, 166.5),
-            Utils::getSvInfo(5, GnssConstellationType::GPS, 27.0, 29.0, 56.5),
-            Utils::getSvInfo(17, GnssConstellationType::GPS, 30.5, 71.0, 77.0),
-            Utils::getSvInfo(26, GnssConstellationType::GPS, 24.1, 28.0, 253.0),
-            Utils::getSvInfo(5, GnssConstellationType::GLONASS, 20.5, 11.5, 116.0),
-            Utils::getSvInfo(17, GnssConstellationType::GLONASS, 21.5, 28.5, 186.0),
-            Utils::getSvInfo(18, GnssConstellationType::GLONASS, 28.3, 38.8, 69.0),
-            Utils::getSvInfo(10, GnssConstellationType::GLONASS, 25.0, 66.0, 247.0)};
+            Utils::getMockSvInfoV1_0(3, GnssConstellationType::GPS, 32.5, 59.1, 166.5),
+            Utils::getMockSvInfoV1_0(5, GnssConstellationType::GPS, 27.0, 29.0, 56.5),
+            Utils::getMockSvInfoV1_0(17, GnssConstellationType::GPS, 30.5, 71.0, 77.0),
+            Utils::getMockSvInfoV1_0(26, GnssConstellationType::GPS, 24.1, 28.0, 253.0),
+            Utils::getMockSvInfoV1_0(5, GnssConstellationType::GLONASS, 20.5, 11.5, 116.0),
+            Utils::getMockSvInfoV1_0(17, GnssConstellationType::GLONASS, 21.5, 28.5, 186.0),
+            Utils::getMockSvInfoV1_0(18, GnssConstellationType::GLONASS, 28.3, 38.8, 69.0),
+            Utils::getMockSvInfoV1_0(10, GnssConstellationType::GLONASS, 25.0, 66.0, 247.0)};
 
     GnssSvStatus svStatus = {.numSvs = sizeof(mockGnssSvInfoList) / sizeof(GnssSvInfo)};
     for (uint32_t i = 0; i < svStatus.numSvs; i++) {
diff --git a/gnss/1.1/vts/functional/gnss_hal_test.cpp b/gnss/1.1/vts/functional/gnss_hal_test.cpp
index 2c8a7b1..b87f558 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test.cpp
@@ -175,6 +175,48 @@
     return hasGnssHalVersion_1_1 && !hasGnssHalVersion_2_0;
 }
 
+GnssConstellationType GnssHalTest::startLocationAndGetNonGpsConstellation() {
+    const int kLocationsToAwait = 3;
+
+    gnss_cb_->location_cbq_.reset();
+    StartAndCheckLocations(kLocationsToAwait);
+    const int location_called_count = gnss_cb_->location_cbq_.calledCount();
+
+    // Tolerate 1 less sv status to handle edge cases in reporting.
+    int sv_status_cbq_size = gnss_cb_->sv_status_cbq_.size();
+    EXPECT_GE(sv_status_cbq_size + 1, kLocationsToAwait);
+    ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)", sv_status_cbq_size,
+          kLocationsToAwait, location_called_count);
+
+    // Find first non-GPS constellation to blacklist
+    const int kGnssSvStatusTimeout = 2;
+    GnssConstellationType constellation_to_blacklist = GnssConstellationType::UNKNOWN;
+    for (int i = 0; i < sv_status_cbq_size; ++i) {
+        IGnssCallback::GnssSvStatus gnss_sv_status;
+        gnss_cb_->sv_status_cbq_.retrieve(gnss_sv_status, kGnssSvStatusTimeout);
+        for (uint32_t iSv = 0; iSv < gnss_sv_status.numSvs; iSv++) {
+            const auto& gnss_sv = gnss_sv_status.gnssSvList[iSv];
+            if ((gnss_sv.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
+                (gnss_sv.constellation != GnssConstellationType::UNKNOWN) &&
+                (gnss_sv.constellation != GnssConstellationType::GPS)) {
+                // found a non-GPS constellation
+                constellation_to_blacklist = gnss_sv.constellation;
+                break;
+            }
+        }
+        if (constellation_to_blacklist != GnssConstellationType::UNKNOWN) {
+            break;
+        }
+    }
+
+    if (constellation_to_blacklist == GnssConstellationType::UNKNOWN) {
+        ALOGI("No non-GPS constellations found, constellation blacklist test less effective.");
+        // Proceed functionally to blacklist something.
+        constellation_to_blacklist = GnssConstellationType::GLONASS;
+    }
+    return constellation_to_blacklist;
+}
+
 GnssHalTest::GnssCallback::GnssCallback()
     : info_cbq_("system_info"),
       name_cbq_("name"),
diff --git a/gnss/1.1/vts/functional/gnss_hal_test.h b/gnss/1.1/vts/functional/gnss_hal_test.h
index 169cd62..b0e52be 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test.h
+++ b/gnss/1.1/vts/functional/gnss_hal_test.h
@@ -28,6 +28,7 @@
 using android::hardware::gnss::V1_0::GnssLocation;
 
 using android::hardware::gnss::common::GnssCallbackEventQueue;
+using android::hardware::gnss::V1_0::GnssConstellationType;
 using android::hardware::gnss::V1_0::GnssLocationFlags;
 using android::hardware::gnss::V1_1::IGnss;
 using android::hardware::gnss::V1_1::IGnssCallback;
@@ -139,6 +140,16 @@
      */
     bool IsGnssHalVersion_1_1() const;
 
+    /*
+     * startLocationAndGetNonGpsConstellation:
+     * 1. Start location
+     * 2. Find and return first non-GPS constellation
+     *
+     * Note that location is not stopped in this method. The client should call
+     * StopAndClearLocations() after the call.
+     */
+    GnssConstellationType startLocationAndGetNonGpsConstellation();
+
     sp<IGnss> gnss_hal_;         // GNSS HAL to call into
     sp<GnssCallback> gnss_cb_;   // Primary callback interface
 };
diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
index 79da84a..afba61f 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
@@ -352,7 +352,7 @@
 }
 
 /*
- * BlacklistConstellation:
+ * BlacklistConstellationWithLocationOff:
  *
  * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
  * GnssStatus for any non-GPS constellations.
@@ -361,50 +361,19 @@
  * GnssStatus does not use any constellation but GPS.
  * 4a & b) Clean up by turning off location, and send in empty blacklist.
  */
-TEST_P(GnssHalTest, BlacklistConstellation) {
+TEST_P(GnssHalTest, BlacklistConstellationWithLocationOff) {
     if (!IsGnssHalVersion_1_1()) {
         ALOGI("Test BlacklistConstellation skipped. GNSS HAL version is greater than 1.1.");
         return;
     }
 
     const int kLocationsToAwait = 3;
-
-    gnss_cb_->location_cbq_.reset();
-    StartAndCheckLocations(kLocationsToAwait);
-    const int location_called_count = gnss_cb_->location_cbq_.calledCount();
-
-    // Tolerate 1 less sv status to handle edge cases in reporting.
-    int sv_status_cbq_size = gnss_cb_->sv_status_cbq_.size();
-    EXPECT_GE(sv_status_cbq_size + 1, kLocationsToAwait);
-    ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)", sv_status_cbq_size,
-          kLocationsToAwait, location_called_count);
-
     // Find first non-GPS constellation to blacklist
-    const int kGnssSvStatusTimeout = 2;
-    GnssConstellationType constellation_to_blacklist = GnssConstellationType::UNKNOWN;
-    for (int i = 0; i < sv_status_cbq_size; ++i) {
-        IGnssCallback::GnssSvStatus gnss_sv_status;
-        gnss_cb_->sv_status_cbq_.retrieve(gnss_sv_status, kGnssSvStatusTimeout);
-        for (uint32_t iSv = 0; iSv < gnss_sv_status.numSvs; iSv++) {
-            const auto& gnss_sv = gnss_sv_status.gnssSvList[iSv];
-            if ((gnss_sv.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
-                (gnss_sv.constellation != GnssConstellationType::UNKNOWN) &&
-                (gnss_sv.constellation != GnssConstellationType::GPS)) {
-                // found a non-GPS constellation
-                constellation_to_blacklist = gnss_sv.constellation;
-                break;
-            }
-        }
-        if (constellation_to_blacklist != GnssConstellationType::UNKNOWN) {
-            break;
-        }
-    }
+    GnssConstellationType constellation_to_blacklist = startLocationAndGetNonGpsConstellation();
 
-    if (constellation_to_blacklist == GnssConstellationType::UNKNOWN) {
-        ALOGI("No non-GPS constellations found, constellation blacklist test less effective.");
-        // Proceed functionally to blacklist something.
-        constellation_to_blacklist = GnssConstellationType::GLONASS;
-    }
+    // Turns off location
+    StopAndClearLocations();
+
     IGnssConfiguration::BlacklistedSource source_to_blacklist;
     source_to_blacklist.constellation = constellation_to_blacklist;
     source_to_blacklist.svid = 0;  // documented wildcard for all satellites in this constellation
@@ -418,6 +387,7 @@
     sources.resize(1);
     sources[0] = source_to_blacklist;
 
+    // setBlacklist when location is off.
     auto result = gnss_configuration_hal->setBlacklist(sources);
     ASSERT_TRUE(result.isOk());
     EXPECT_TRUE(result);
@@ -429,10 +399,82 @@
     StartAndCheckLocations(kLocationsToAwait);
 
     // Tolerate 1 less sv status to handle edge cases in reporting.
-    sv_status_cbq_size = gnss_cb_->sv_status_cbq_.size();
+    int sv_status_cbq_size = gnss_cb_->sv_status_cbq_.size();
     EXPECT_GE(sv_status_cbq_size + 1, kLocationsToAwait);
     ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations", sv_status_cbq_size,
           kLocationsToAwait);
+    const int kGnssSvStatusTimeout = 2;
+    for (int i = 0; i < sv_status_cbq_size; ++i) {
+        IGnssCallback::GnssSvStatus gnss_sv_status;
+        gnss_cb_->sv_status_cbq_.retrieve(gnss_sv_status, kGnssSvStatusTimeout);
+        for (uint32_t iSv = 0; iSv < gnss_sv_status.numSvs; iSv++) {
+            const auto& gnss_sv = gnss_sv_status.gnssSvList[iSv];
+            EXPECT_FALSE((gnss_sv.constellation == source_to_blacklist.constellation) &&
+                         (gnss_sv.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX));
+        }
+    }
+
+    // clean up
+    StopAndClearLocations();
+    sources.resize(0);
+    result = gnss_configuration_hal->setBlacklist(sources);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+}
+
+/*
+ * BlacklistConstellationWithLocationOn:
+ *
+ * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
+ * GnssStatus for any non-GPS constellations.
+ * 2a & b) Turns off location, and blacklist first non-GPS constellations.
+ * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
+ * GnssStatus does not use any constellation but GPS.
+ * 4a & b) Clean up by turning off location, and send in empty blacklist.
+ */
+TEST_P(GnssHalTest, BlacklistConstellationWithLocationOn) {
+    if (!IsGnssHalVersion_1_1()) {
+        ALOGI("Test BlacklistConstellation skipped. GNSS HAL version is greater than 1.1.");
+        return;
+    }
+
+    const int kLocationsToAwait = 3;
+    // Find first non-GPS constellation to blacklist
+    GnssConstellationType constellation_to_blacklist = startLocationAndGetNonGpsConstellation();
+
+    IGnssConfiguration::BlacklistedSource source_to_blacklist;
+    source_to_blacklist.constellation = constellation_to_blacklist;
+    source_to_blacklist.svid = 0;  // documented wildcard for all satellites in this constellation
+
+    auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_1_1();
+    ASSERT_TRUE(gnss_configuration_hal_return.isOk());
+    sp<IGnssConfiguration> gnss_configuration_hal = gnss_configuration_hal_return;
+    ASSERT_NE(gnss_configuration_hal, nullptr);
+
+    hidl_vec<IGnssConfiguration::BlacklistedSource> sources;
+    sources.resize(1);
+    sources[0] = source_to_blacklist;
+
+    // setBlacklist when location is still on
+    auto result = gnss_configuration_hal->setBlacklist(sources);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+
+    // Turns off location
+    StopAndClearLocations();
+
+    // retry and ensure constellation not used
+    gnss_cb_->sv_status_cbq_.reset();
+
+    gnss_cb_->location_cbq_.reset();
+    StartAndCheckLocations(kLocationsToAwait);
+
+    // Tolerate 1 less sv status to handle edge cases in reporting.
+    int sv_status_cbq_size = gnss_cb_->sv_status_cbq_.size();
+    EXPECT_GE(sv_status_cbq_size + 1, kLocationsToAwait);
+    ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations", sv_status_cbq_size,
+          kLocationsToAwait);
+    const int kGnssSvStatusTimeout = 2;
     for (int i = 0; i < sv_status_cbq_size; ++i) {
         IGnssCallback::GnssSvStatus gnss_sv_status;
         gnss_cb_->sv_status_cbq_.retrieve(gnss_sv_status, kGnssSvStatusTimeout);
diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp
index 3ba89da..37de55d 100644
--- a/gnss/2.0/default/Android.bp
+++ b/gnss/2.0/default/Android.bp
@@ -25,7 +25,7 @@
         "AGnss.cpp",
         "AGnssRil.cpp",
         "Gnss.cpp",
-	"GnssBatching.cpp",
+        "GnssBatching.cpp",
         "GnssMeasurement.cpp",
         "GnssMeasurementCorrections.cpp",
         "GnssVisibilityControl.cpp",
@@ -35,9 +35,10 @@
         "libhidlbase",
         "libutils",
         "liblog",
-        "android.hardware.gnss@2.0",
         "android.hardware.gnss.measurement_corrections@1.0",
         "android.hardware.gnss.visibility_control@1.0",
+        "android.hardware.gnss@2.1",
+        "android.hardware.gnss@2.0",
         "android.hardware.gnss@1.0",
         "android.hardware.gnss@1.1",
     ],
diff --git a/gnss/2.0/default/Gnss.cpp b/gnss/2.0/default/Gnss.cpp
index 3d64fc3..09f2fc0 100644
--- a/gnss/2.0/default/Gnss.cpp
+++ b/gnss/2.0/default/Gnss.cpp
@@ -19,7 +19,6 @@
 #include "Gnss.h"
 
 #include <log/log.h>
-#include <utils/SystemClock.h>
 
 #include "AGnss.h"
 #include "AGnssRil.h"
@@ -47,24 +46,6 @@
 sp<V2_0::IGnssCallback> Gnss::sGnssCallback_2_0 = nullptr;
 sp<V1_1::IGnssCallback> Gnss::sGnssCallback_1_1 = nullptr;
 
-namespace {
-
-V2_0::GnssLocation getMockLocationV2_0() {
-    const ElapsedRealtime timestamp = {
-            .flags = ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
-                     ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS,
-            .timestampNs = static_cast<uint64_t>(::android::elapsedRealtimeNano()),
-            // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks.
-            // In an actual implementation provide an estimate of the synchronization uncertainty
-            // or don't set the field.
-            .timeUncertaintyNs = 1000000};
-
-    V2_0::GnssLocation location = {.v1_0 = Utils::getMockLocation(), .elapsedRealtime = timestamp};
-    return location;
-}
-
-}  // namespace
-
 Gnss::Gnss() : mMinIntervalMs(1000) {}
 
 Gnss::~Gnss() {
@@ -86,7 +67,7 @@
     mIsActive = true;
     mThread = std::thread([this]() {
         while (mIsActive == true) {
-            const auto location = getMockLocationV2_0();
+            const auto location = Utils::getMockLocationV2_0();
             this->reportLocation(location);
 
             std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
diff --git a/gnss/2.0/default/GnssMeasurement.cpp b/gnss/2.0/default/GnssMeasurement.cpp
index 1f95ff9..d778d50 100644
--- a/gnss/2.0/default/GnssMeasurement.cpp
+++ b/gnss/2.0/default/GnssMeasurement.cpp
@@ -16,6 +16,7 @@
 #define LOG_TAG "GnssMeasurement"
 
 #include "GnssMeasurement.h"
+#include "Utils.h"
 
 #include <log/log.h>
 #include <utils/SystemClock.h>
@@ -29,6 +30,7 @@
 using GnssConstellationType = V2_0::GnssConstellationType;
 using GnssMeasurementFlags = V1_0::IGnssMeasurementCallback::GnssMeasurementFlags;
 using GnssMeasurementState = V2_0::IGnssMeasurementCallback::GnssMeasurementState;
+using Utils = common::Utils;
 
 sp<V2_0::IGnssMeasurementCallback> GnssMeasurement::sCallback = nullptr;
 
@@ -81,7 +83,7 @@
     mIsActive = true;
     mThread = std::thread([this]() {
         while (mIsActive == true) {
-            auto measurement = this->getMockMeasurement();
+            auto measurement = Utils::getMockMeasurementV2_0();
             this->reportMeasurement(measurement);
 
             std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis));
@@ -97,60 +99,6 @@
     }
 }
 
-GnssData GnssMeasurement::getMockMeasurement() {
-    V1_0::IGnssMeasurementCallback::GnssMeasurement measurement_1_0 = {
-            .flags = (uint32_t)GnssMeasurementFlags::HAS_CARRIER_FREQUENCY,
-            .svid = (int16_t)6,
-            .constellation = V1_0::GnssConstellationType::UNKNOWN,
-            .timeOffsetNs = 0.0,
-            .receivedSvTimeInNs = 8195997131077,
-            .receivedSvTimeUncertaintyInNs = 15,
-            .cN0DbHz = 30.0,
-            .pseudorangeRateMps = -484.13739013671875,
-            .pseudorangeRateUncertaintyMps = 1.0379999876022339,
-            .accumulatedDeltaRangeState = (uint32_t)V1_0::IGnssMeasurementCallback::
-                    GnssAccumulatedDeltaRangeState::ADR_STATE_UNKNOWN,
-            .accumulatedDeltaRangeM = 0.0,
-            .accumulatedDeltaRangeUncertaintyM = 0.0,
-            .carrierFrequencyHz = 1.59975e+09,
-            .multipathIndicator =
-                    V1_0::IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN};
-    V1_1::IGnssMeasurementCallback::GnssMeasurement measurement_1_1 = {.v1_0 = measurement_1_0};
-    V2_0::IGnssMeasurementCallback::GnssMeasurement measurement_2_0 = {
-            .v1_1 = measurement_1_1,
-            .codeType = "C",
-            .state = GnssMeasurementState::STATE_CODE_LOCK | GnssMeasurementState::STATE_BIT_SYNC |
-                     GnssMeasurementState::STATE_SUBFRAME_SYNC |
-                     GnssMeasurementState::STATE_TOW_DECODED |
-                     GnssMeasurementState::STATE_GLO_STRING_SYNC |
-                     GnssMeasurementState::STATE_GLO_TOD_DECODED,
-            .constellation = GnssConstellationType::GLONASS,
-    };
-
-    hidl_vec<IGnssMeasurementCallback::GnssMeasurement> measurements(1);
-    measurements[0] = measurement_2_0;
-    V1_0::IGnssMeasurementCallback::GnssClock clock = {.timeNs = 2713545000000,
-                                                       .fullBiasNs = -1226701900521857520,
-                                                       .biasNs = 0.59689998626708984,
-                                                       .biasUncertaintyNs = 47514.989972114563,
-                                                       .driftNsps = -51.757811607455452,
-                                                       .driftUncertaintyNsps = 310.64968328491528,
-                                                       .hwClockDiscontinuityCount = 1};
-
-    ElapsedRealtime timestamp = {
-            .flags = ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
-                     ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS,
-            .timestampNs = static_cast<uint64_t>(::android::elapsedRealtimeNano()),
-            // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks.
-            // In an actual implementation provide an estimate of the synchronization uncertainty
-            // or don't set the field.
-            .timeUncertaintyNs = 1000000};
-
-    GnssData gnssData = {
-            .measurements = measurements, .clock = clock, .elapsedRealtime = timestamp};
-    return gnssData;
-}
-
 void GnssMeasurement::reportMeasurement(const GnssData& data) {
     ALOGD("reportMeasurement()");
     std::unique_lock<std::mutex> lock(mMutex);
diff --git a/gnss/2.0/default/GnssMeasurement.h b/gnss/2.0/default/GnssMeasurement.h
index c24c00e..d8ffd59 100644
--- a/gnss/2.0/default/GnssMeasurement.h
+++ b/gnss/2.0/default/GnssMeasurement.h
@@ -59,7 +59,6 @@
    private:
     void start();
     void stop();
-    GnssData getMockMeasurement();
     void reportMeasurement(const GnssData&);
 
     static sp<IGnssMeasurementCallback> sCallback;
diff --git a/gnss/2.0/vts/functional/Android.bp b/gnss/2.0/vts/functional/Android.bp
index 9aa1334..da5289d 100644
--- a/gnss/2.0/vts/functional/Android.bp
+++ b/gnss/2.0/vts/functional/Android.bp
@@ -28,6 +28,7 @@
         "android.hardware.gnss@1.0",
         "android.hardware.gnss@1.1",
         "android.hardware.gnss@2.0",
+        "android.hardware.gnss@2.1",
         "android.hardware.gnss@common-vts-lib",
     ],
     test_suites: ["general-tests", "vts-core"],
diff --git a/gnss/2.1/Android.bp b/gnss/2.1/Android.bp
new file mode 100644
index 0000000..8b0c374
--- /dev/null
+++ b/gnss/2.1/Android.bp
@@ -0,0 +1,25 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.gnss@2.1",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "IGnss.hal",
+        "IGnssCallback.hal",
+        "IGnssMeasurement.hal",
+        "IGnssMeasurementCallback.hal",
+        "IGnssConfiguration.hal",
+    ],
+    interfaces: [
+        "android.hardware.gnss.measurement_corrections@1.0",
+        "android.hardware.gnss.visibility_control@1.0",
+        "android.hardware.gnss@1.0",
+        "android.hardware.gnss@1.1",
+        "android.hardware.gnss@2.0",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
diff --git a/gnss/2.1/IGnss.hal b/gnss/2.1/IGnss.hal
new file mode 100644
index 0000000..2d63392
--- /dev/null
+++ b/gnss/2.1/IGnss.hal
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@2.1;
+
+import @2.0::IGnss;
+
+import IGnssCallback;
+import IGnssMeasurement;
+import IGnssConfiguration;
+
+/**
+ * Represents the standard GNSS (Global Navigation Satellite System) interface.
+ */
+interface IGnss extends @2.0::IGnss {
+    /**
+     * Opens the interface and provides the callback routines to the implementation of this
+     * interface.
+     *
+     * The framework calls this method to instruct the GPS engine to prepare for serving requests
+     * from the framework. The GNSS HAL implementation must respond to all GNSS requests from the
+     * framework upon successful return from this method until cleanup() method is called to
+     * close this interface.
+     *
+     * @param callback Callback interface for IGnss.
+     *
+     * @return success Returns true on success.
+     */
+    setCallback_2_1(IGnssCallback callback) generates (bool success);
+
+    /**
+     * This method returns the IGnssMeasurement interface.
+     *
+     * At least one of getExtensionGnssMeasurement(), getExtensionGnssMeasurement_1_1(),
+     * getExtensionGnssMeasurement_2_0(), and getExtensionGnssMeasurement_2_1() methods must return
+     * a non-null handle, and the other methods must return nullptr.
+     *
+     * @return gnssMeasurementIface Handle to the IGnssMeasurement interface.
+     */
+    getExtensionGnssMeasurement_2_1() generates (IGnssMeasurement gnssMeasurementIface);
+
+    /**
+     * This method returns the IGnssConfiguration interface.
+     *
+     * At least one of getExtensionGnssConfiguration(), getExtensionGnssConfiguration_1_1(),
+     * getExtensionGnssConfiguration_2_0(), and getExtensionGnssConfiguration_2_1() methods must
+     * return a non-null handle, and the other methods must return nullptr.
+     *
+     * @return gnssConfigurationIface Handle to the IGnssConfiguration interface.
+     */
+    getExtensionGnssConfiguration_2_1() generates (IGnssConfiguration gnssConfigurationIface);
+};
\ No newline at end of file
diff --git a/gnss/2.1/IGnssCallback.hal b/gnss/2.1/IGnssCallback.hal
new file mode 100644
index 0000000..da70742
--- /dev/null
+++ b/gnss/2.1/IGnssCallback.hal
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@2.1;
+
+import @2.0::IGnssCallback;
+
+/**
+ * This interface is required for the HAL to communicate certain information
+ * like status and location info back to the platform, the platform implements
+ * the interfaces and passes a handle to the HAL.
+ */
+interface IGnssCallback extends @2.0::IGnssCallback {
+
+    /** Extends a GnssSvInfo, adding a basebandCN0DbHz. */
+    struct GnssSvInfo {
+        /**
+         * GNSS satellite information for a single satellite and frequency.
+         */
+        @2.0::IGnssCallback.GnssSvInfo v2_0;
+
+        /**
+         * Baseband Carrier-to-noise density in dB-Hz, typically in the range [0, 63]. It contains
+         * the measured C/N0 value for the signal measured at the baseband.
+         *
+         * This is typically a few dB weaker than the value estimated for C/N0 at the antenna port,
+         * which is reported in cN0DbHz.
+         *
+         * If a signal has separate components (e.g. Pilot and Data channels) and the receiver only
+         * processes one of the components, then the reported basebandCN0DbHz reflects only the
+         * component that is processed.
+         *
+         * This value is mandatory. Like cN0DbHz, it may be reported as 0 for satellites being
+         * reported that may be searched for, but not yet tracked.
+         */
+        double basebandCN0DbHz;
+    };
+
+    /**
+     * Callback for the HAL to pass a vector of GnssSvInfo back to the client.
+     *
+     * @param svInfoList SV info list information from HAL.
+     */
+    gnssSvStatusCb_2_1(vec<GnssSvInfo> svInfoList);
+};
diff --git a/gnss/2.1/IGnssConfiguration.hal b/gnss/2.1/IGnssConfiguration.hal
new file mode 100644
index 0000000..8360ba9
--- /dev/null
+++ b/gnss/2.1/IGnssConfiguration.hal
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@2.1;
+
+import @2.0::IGnssConfiguration;
+import @2.0::GnssConstellationType;
+
+/**
+ * Extended interface for GNSS Configuration support.
+ */
+interface IGnssConfiguration extends @2.0::IGnssConfiguration {
+    /**
+     * Represents a blacklisted source, updating the GnssConstellationType to 2.0, which supports
+     * IRNSS.
+     */
+    struct BlacklistedSource {
+        /**
+         * Defines the constellation of the given satellite(s).
+         */
+        GnssConstellationType constellation;
+
+        /**
+         * Satellite (space vehicle) ID number, as defined in GnssSvInfo::svid
+         *
+         * Or 0 to blacklist all svid's for the specified constellation
+         */
+        int16_t svid;
+    };
+
+    /**
+     * Injects a vector of BlacklistedSource(s) which the HAL must not use to calculate the
+     * GNSS location output.
+     *
+     * The superset of all satellite sources provided, including wildcards, in the latest call
+     * to this method, is the set of satellites sources that must not be used in calculating
+     * location.
+     *
+     * All measurements from the specified satellites, across frequency bands, are blacklisted
+     * together.
+     *
+     * If this method is never called after the IGnssConfiguration.hal connection is made on boot,
+     * or is called with an empty vector, then no satellites are to be blacklisted as a result of
+     * this API.
+     *
+     * This blacklist must be considered as an additional source of which satellites
+     * should not be trusted for location on top of existing sources of similar information
+     * such as satellite broadcast health being unhealthy and measurement outlier removal.
+     *
+     * @param blacklist The BlacklistedSource(s) of satellites the HAL must not use.
+     *
+     * @return success Whether the HAL accepts and abides by the provided blacklist.
+     */
+    setBlacklist_2_1(vec<BlacklistedSource> blacklist) generates (bool success);
+};
\ No newline at end of file
diff --git a/gnss/2.1/IGnssMeasurement.hal b/gnss/2.1/IGnssMeasurement.hal
new file mode 100644
index 0000000..d2c76e6
--- /dev/null
+++ b/gnss/2.1/IGnssMeasurement.hal
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@2.1;
+
+import @1.0::IGnssMeasurement;
+import @1.1::IGnssMeasurement;
+import @2.0::IGnssMeasurement;
+import IGnssMeasurementCallback;
+
+/**
+ * Extended interface for GNSS Measurements support.
+ */
+interface IGnssMeasurement extends @2.0::IGnssMeasurement {
+
+    /**
+     * Initializes the interface and registers the callback routines with the HAL. After a
+     * successful call to 'setCallback_2_1' the HAL must begin to provide updates at an average
+     * output rate of 1Hz (occasional intra-measurement time offsets in the range from 0-2000msec
+     * can be tolerated.)
+     *
+     * @param callback Handle to GnssMeasurement callback interface.
+     * @param enableFullTracking If true, GNSS chipset must switch off duty cycling. In such mode
+     *     no clock discontinuities are expected and, when supported, carrier phase should be
+     *     continuous in good signal conditions. All non-blacklisted, healthy constellations,
+     *     satellites and frequency bands that the chipset supports must be reported in this mode.
+     *     The GNSS chipset is allowed to consume more power in this mode. If false, API must behave
+     *     as in HAL V1_0, optimizing power via duty cycling, constellations and frequency limits,
+     *     etc.
+     *
+     * @return initRet Returns SUCCESS if successful. Returns ERROR_ALREADY_INIT if a callback has
+     *     already been registered without a corresponding call to 'close'. Returns ERROR_GENERIC
+     *     for any other error. The HAL must not generate any other updates upon returning this
+     *     error code.
+     */
+    setCallback_2_1(IGnssMeasurementCallback callback, bool enableFullTracking)
+         generates (GnssMeasurementStatus initRet);
+};
diff --git a/gnss/2.1/IGnssMeasurementCallback.hal b/gnss/2.1/IGnssMeasurementCallback.hal
new file mode 100644
index 0000000..ca6175f
--- /dev/null
+++ b/gnss/2.1/IGnssMeasurementCallback.hal
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@2.1;
+
+import @1.0::IGnssMeasurementCallback;
+import @1.1::IGnssMeasurementCallback;
+import @2.0::IGnssMeasurementCallback;
+import @2.0::ElapsedRealtime;
+
+/** The callback interface to report measurements from the HAL. */
+interface IGnssMeasurementCallback extends @2.0::IGnssMeasurementCallback {
+
+    /**
+     * Extends a GNSS Measurement, adding a basebandCN0DbHz.
+     */
+    struct GnssMeasurement {
+        /**
+         * GNSS measurement information for a single satellite and frequency, as in the 2.0 version
+         * of the HAL.
+         */
+        @2.0::IGnssMeasurementCallback.GnssMeasurement v2_0;
+
+        /**
+         * Baseband Carrier-to-noise density in dB-Hz, typically in the range [0, 63]. It contains
+         * the measured C/N0 value for the signal measured at the baseband.
+         *
+         * This is typically a few dB weaker than the value estimated for C/N0 at the antenna port,
+         * which is reported in cN0DbHz.
+         *
+         * If a signal has separate components (e.g. Pilot and Data channels) and the receiver only
+         * processes one of the components, then the reported basebandCN0DbHz reflects only the
+         * component that is processed.
+         *
+         * This value is mandatory.
+         */
+        double basebandCN0DbHz;
+    };
+
+    /**
+     * Complete set of GNSS Measurement data, same as 2.0 with additional double (i.e.,
+     * basebandCN0DbHz) in measurements.
+     */
+    struct GnssData {
+        /** The full set of satellite measurement observations. */
+        vec<GnssMeasurement> measurements;
+
+        /** The GNSS clock time reading. */
+        GnssClock clock;
+
+        /**
+         * Timing information of the GNSS data synchronized with SystemClock.elapsedRealtimeNanos()
+         * clock.
+         */
+        ElapsedRealtime elapsedRealtime;
+    };
+
+    /**
+     * Callback for the hal to pass a GnssData structure back to the client.
+     *
+     * @param data Contains a reading of GNSS measurements.
+     */
+    gnssMeasurementCb_2_1(GnssData data);
+};
diff --git a/gnss/2.1/default/Android.bp b/gnss/2.1/default/Android.bp
new file mode 100644
index 0000000..57233aa
--- /dev/null
+++ b/gnss/2.1/default/Android.bp
@@ -0,0 +1,43 @@
+/*
+ * 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_binary {
+    name: "android.hardware.gnss@2.1-service",
+    init_rc: ["android.hardware.gnss@2.1-service.rc"],
+    relative_install_path: "hw",
+    vendor: true,
+    vintf_fragments: ["android.hardware.gnss@2.1-service.xml"],
+    srcs: [
+        "Gnss.cpp",
+        "GnssMeasurement.cpp",
+        "GnssConfiguration.cpp",
+        "service.cpp"
+    ],
+    shared_libs: [
+        "libhidlbase",
+        "libutils",
+        "liblog",
+        "android.hardware.gnss.measurement_corrections@1.0",
+        "android.hardware.gnss.visibility_control@1.0",
+        "android.hardware.gnss@2.1",
+        "android.hardware.gnss@1.0",
+        "android.hardware.gnss@1.1",
+        "android.hardware.gnss@2.0",
+    ],
+    static_libs: [
+        "android.hardware.gnss@common-default-lib",
+    ],
+}
diff --git a/gnss/2.1/default/Gnss.cpp b/gnss/2.1/default/Gnss.cpp
new file mode 100644
index 0000000..384fd49
--- /dev/null
+++ b/gnss/2.1/default/Gnss.cpp
@@ -0,0 +1,315 @@
+/*
+ * 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 "Gnss"
+
+#include "Gnss.h"
+#include "GnssMeasurement.h"
+#include "Utils.h"
+
+#include <log/log.h>
+
+using ::android::hardware::gnss::common::Utils;
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+sp<V2_1::IGnssCallback> Gnss::sGnssCallback_2_1 = nullptr;
+
+Gnss::Gnss() : mMinIntervalMs(1000), mGnssConfiguration{new GnssConfiguration()} {}
+
+Gnss::~Gnss() {
+    stop();
+}
+
+Return<bool> Gnss::start() {
+    ALOGD("start");
+    if (mIsActive) {
+        ALOGW("Gnss has started. Restarting...");
+        stop();
+    }
+
+    mIsActive = true;
+    mThread = std::thread([this]() {
+        while (mIsActive == true) {
+            auto svStatus = filterBlacklistedSatellitesV2_1(Utils::getMockSvInfoListV2_1());
+            this->reportSvStatus(svStatus);
+
+            const auto location = Utils::getMockLocationV2_0();
+            this->reportLocation(location);
+
+            std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
+        }
+    });
+    return true;
+}
+
+hidl_vec<GnssSvInfo> Gnss::filterBlacklistedSatellitesV2_1(hidl_vec<GnssSvInfo> gnssSvInfoList) {
+    for (uint32_t i = 0; i < gnssSvInfoList.size(); i++) {
+        if (mGnssConfiguration->isBlacklistedV2_1(gnssSvInfoList[i])) {
+            gnssSvInfoList[i].v2_0.v1_0.svFlag &=
+                    ~static_cast<uint8_t>(V1_0::IGnssCallback::GnssSvFlags::USED_IN_FIX);
+        }
+    }
+    return gnssSvInfoList;
+}
+
+Return<bool> Gnss::stop() {
+    ALOGD("stop");
+    mIsActive = false;
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+    return true;
+}
+
+// Methods from V1_0::IGnss follow.
+Return<bool> Gnss::setCallback(const sp<V1_0::IGnssCallback>&) {
+    // TODO implement
+    return bool{};
+}
+
+Return<void> Gnss::cleanup() {
+    // TODO implement
+    return Void();
+}
+
+Return<bool> Gnss::injectTime(int64_t, int64_t, int32_t) {
+    // TODO implement
+    return bool{};
+}
+
+Return<bool> Gnss::injectLocation(double, double, float) {
+    // TODO implement
+    return bool{};
+}
+
+Return<void> Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData) {
+    // TODO implement
+    return Void();
+}
+
+Return<bool> Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode,
+                                   V1_0::IGnss::GnssPositionRecurrence, uint32_t, uint32_t,
+                                   uint32_t) {
+    // TODO implement
+    return bool{};
+}
+
+Return<sp<V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
+    // TODO implement
+    return ::android::sp<V1_0::IAGnssRil>{};
+}
+
+Return<sp<V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
+    // TODO implement
+    return ::android::sp<V1_0::IGnssGeofencing>{};
+}
+
+Return<sp<V1_0::IAGnss>> Gnss::getExtensionAGnss() {
+    // TODO implement
+    return ::android::sp<V1_0::IAGnss>{};
+}
+
+Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi() {
+    // TODO implement
+    return ::android::sp<V1_0::IGnssNi>{};
+}
+
+Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
+    // TODO implement
+    return ::android::sp<V1_0::IGnssMeasurement>{};
+}
+
+Return<sp<V1_0::IGnssNavigationMessage>> Gnss::getExtensionGnssNavigationMessage() {
+    // TODO implement
+    return ::android::sp<V1_0::IGnssNavigationMessage>{};
+}
+
+Return<sp<V1_0::IGnssXtra>> Gnss::getExtensionXtra() {
+    // TODO implement
+    return ::android::sp<V1_0::IGnssXtra>{};
+}
+
+Return<sp<V1_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() {
+    // TODO implement
+    return ::android::sp<V1_0::IGnssConfiguration>{};
+}
+
+Return<sp<V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
+    // TODO implement
+    return ::android::sp<V1_0::IGnssDebug>{};
+}
+
+Return<sp<V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching() {
+    // TODO implement
+    return ::android::sp<V1_0::IGnssBatching>{};
+}
+
+// Methods from V1_1::IGnss follow.
+Return<bool> Gnss::setCallback_1_1(const sp<V1_1::IGnssCallback>&) {
+    // TODO implement
+    return bool{};
+}
+
+Return<bool> Gnss::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode,
+                                       V1_0::IGnss::GnssPositionRecurrence, uint32_t, uint32_t,
+                                       uint32_t, bool) {
+    return true;
+}
+
+Return<sp<V1_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_1_1() {
+    // TODO implement
+    return ::android::sp<V1_1::IGnssConfiguration>{};
+}
+
+Return<sp<V1_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_1_1() {
+    // TODO implement
+    return ::android::sp<V1_1::IGnssMeasurement>{};
+}
+
+Return<bool> Gnss::injectBestLocation(const V1_0::GnssLocation&) {
+    // TODO implement
+    return bool{};
+}
+
+// Methods from V2_0::IGnss follow.
+Return<bool> Gnss::setCallback_2_0(const sp<V2_0::IGnssCallback>&) {
+    // TODO implement
+    return bool{};
+}
+
+Return<sp<V2_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_0() {
+    // TODO implement
+    return ::android::sp<V2_0::IGnssConfiguration>{};
+}
+
+Return<sp<V2_0::IGnssDebug>> Gnss::getExtensionGnssDebug_2_0() {
+    // TODO implement
+    return ::android::sp<V2_0::IGnssDebug>{};
+}
+
+Return<sp<V2_0::IAGnss>> Gnss::getExtensionAGnss_2_0() {
+    // TODO implement
+    return ::android::sp<V2_0::IAGnss>{};
+}
+
+Return<sp<V2_0::IAGnssRil>> Gnss::getExtensionAGnssRil_2_0() {
+    // TODO implement
+    return ::android::sp<V2_0::IAGnssRil>{};
+}
+
+Return<sp<V2_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_0() {
+    // TODO implement
+    return ::android::sp<V2_0::IGnssMeasurement>{};
+}
+
+Return<sp<measurement_corrections::V1_0::IMeasurementCorrections>>
+Gnss::getExtensionMeasurementCorrections() {
+    // TODO implement
+    return ::android::sp<measurement_corrections::V1_0::IMeasurementCorrections>{};
+}
+
+Return<sp<visibility_control::V1_0::IGnssVisibilityControl>> Gnss::getExtensionVisibilityControl() {
+    // TODO implement
+    return ::android::sp<visibility_control::V1_0::IGnssVisibilityControl>{};
+}
+
+Return<sp<V2_0::IGnssBatching>> Gnss::getExtensionGnssBatching_2_0() {
+    // TODO implement
+    return ::android::sp<V2_0::IGnssBatching>{};
+}
+
+Return<bool> Gnss::injectBestLocation_2_0(const V2_0::GnssLocation&) {
+    // TODO implement
+    return bool{};
+}
+
+// Methods from V2_1::IGnss follow.
+Return<bool> Gnss::setCallback_2_1(const sp<V2_1::IGnssCallback>& callback) {
+    ALOGD("Gnss::setCallback_2_1");
+    if (callback == nullptr) {
+        ALOGE("%s: Null callback ignored", __func__);
+        return false;
+    }
+
+    sGnssCallback_2_1 = 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_1->gnssSetCapabilitiesCb_2_0(capabilities);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    V1_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2020};
+
+    ret = sGnssCallback_2_1->gnssSetSystemInfoCb(gnssInfo);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    auto gnssName = "Android Mock GNSS Implementation v2.1";
+    ret = sGnssCallback_2_1->gnssNameCb(gnssName);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    return true;
+}
+
+Return<sp<V2_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_1() {
+    ALOGD("Gnss::getExtensionGnssMeasurement_2_1");
+    return new GnssMeasurement();
+}
+
+Return<sp<V2_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_1() {
+    return mGnssConfiguration;
+}
+
+void Gnss::reportSvStatus(const hidl_vec<GnssSvInfo>& svInfoList) const {
+    std::unique_lock<std::mutex> lock(mMutex);
+    if (sGnssCallback_2_1 == nullptr) {
+        ALOGE("%s: sGnssCallback v2.1 is null.", __func__);
+        return;
+    }
+    auto ret = sGnssCallback_2_1->gnssSvStatusCb_2_1(svInfoList);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+void Gnss::reportLocation(const V2_0::GnssLocation& location) const {
+    std::unique_lock<std::mutex> lock(mMutex);
+    if (sGnssCallback_2_1 == nullptr) {
+        ALOGE("%s: sGnssCallback v2.1 is null.", __func__);
+        return;
+    }
+    auto ret = sGnssCallback_2_1->gnssLocationCb_2_0(location);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/2.1/default/Gnss.h b/gnss/2.1/default/Gnss.h
new file mode 100644
index 0000000..674b070
--- /dev/null
+++ b/gnss/2.1/default/Gnss.h
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android/hardware/gnss/2.1/IGnss.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <atomic>
+#include <mutex>
+#include <thread>
+#include "GnssConfiguration.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+
+using GnssSvInfo = IGnssCallback::GnssSvInfo;
+
+namespace implementation {
+
+struct Gnss : public IGnss {
+    Gnss();
+    ~Gnss();
+    // Methods from V1_0::IGnss follow.
+    Return<bool> setCallback(const sp<V1_0::IGnssCallback>& callback) override;
+    Return<bool> start() override;
+    Return<bool> stop() override;
+    Return<void> cleanup() override;
+    Return<bool> injectTime(int64_t timeMs, int64_t timeReferenceMs,
+                            int32_t uncertaintyMs) override;
+    Return<bool> injectLocation(double latitudeDegrees, double longitudeDegrees,
+                                float accuracyMeters) override;
+    Return<void> deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override;
+    Return<bool> setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+                                 V1_0::IGnss::GnssPositionRecurrence recurrence,
+                                 uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
+                                 uint32_t preferredTimeMs) override;
+    Return<sp<V1_0::IAGnssRil>> getExtensionAGnssRil() override;
+    Return<sp<V1_0::IGnssGeofencing>> getExtensionGnssGeofencing() override;
+    Return<sp<V1_0::IAGnss>> getExtensionAGnss() override;
+    Return<sp<V1_0::IGnssNi>> getExtensionGnssNi() override;
+    Return<sp<V1_0::IGnssMeasurement>> getExtensionGnssMeasurement() override;
+    Return<sp<V1_0::IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override;
+    Return<sp<V1_0::IGnssXtra>> getExtensionXtra() override;
+    Return<sp<V1_0::IGnssConfiguration>> getExtensionGnssConfiguration() override;
+    Return<sp<V1_0::IGnssDebug>> getExtensionGnssDebug() override;
+    Return<sp<V1_0::IGnssBatching>> getExtensionGnssBatching() override;
+
+    // Methods from V1_1::IGnss follow.
+    Return<bool> setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) override;
+    Return<bool> setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
+                                     V1_0::IGnss::GnssPositionRecurrence recurrence,
+                                     uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
+                                     uint32_t preferredTimeMs, bool lowPowerMode) override;
+    Return<sp<V1_1::IGnssConfiguration>> getExtensionGnssConfiguration_1_1() override;
+    Return<sp<V1_1::IGnssMeasurement>> getExtensionGnssMeasurement_1_1() override;
+    Return<bool> injectBestLocation(const V1_0::GnssLocation& location) override;
+
+    // Methods from V2_0::IGnss follow.
+    Return<bool> setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) override;
+    Return<sp<V2_0::IGnssConfiguration>> getExtensionGnssConfiguration_2_0() override;
+    Return<sp<V2_0::IGnssDebug>> getExtensionGnssDebug_2_0() override;
+    Return<sp<V2_0::IAGnss>> getExtensionAGnss_2_0() override;
+    Return<sp<V2_0::IAGnssRil>> getExtensionAGnssRil_2_0() override;
+    Return<sp<V2_0::IGnssMeasurement>> getExtensionGnssMeasurement_2_0() override;
+    Return<sp<measurement_corrections::V1_0::IMeasurementCorrections>>
+    getExtensionMeasurementCorrections() override;
+    Return<sp<visibility_control::V1_0::IGnssVisibilityControl>> getExtensionVisibilityControl()
+            override;
+    Return<sp<V2_0::IGnssBatching>> getExtensionGnssBatching_2_0() override;
+    Return<bool> injectBestLocation_2_0(const V2_0::GnssLocation& location) override;
+
+    // Methods from V2_1::IGnss follow.
+    Return<bool> setCallback_2_1(const sp<V2_1::IGnssCallback>& callback) override;
+    Return<sp<V2_1::IGnssMeasurement>> getExtensionGnssMeasurement_2_1() override;
+    Return<sp<V2_1::IGnssConfiguration>> getExtensionGnssConfiguration_2_1() override;
+
+  private:
+    void reportLocation(const V2_0::GnssLocation&) const;
+    void reportSvStatus(const hidl_vec<GnssSvInfo>&) const;
+
+    static sp<V2_1::IGnssCallback> sGnssCallback_2_1;
+    std::atomic<long> mMinIntervalMs;
+    sp<GnssConfiguration> mGnssConfiguration;
+    std::atomic<bool> mIsActive;
+    std::thread mThread;
+    mutable std::mutex mMutex;
+    hidl_vec<GnssSvInfo> filterBlacklistedSatellitesV2_1(hidl_vec<GnssSvInfo> gnssSvInfoList);
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/2.1/default/GnssConfiguration.cpp b/gnss/2.1/default/GnssConfiguration.cpp
new file mode 100644
index 0000000..cd8f07f
--- /dev/null
+++ b/gnss/2.1/default/GnssConfiguration.cpp
@@ -0,0 +1,106 @@
+/*
+ * 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 "GnssConfiguration"
+
+#include "GnssConfiguration.h"
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setSuplEs(bool enable) {
+    ALOGD("setSuplEs enable: %d", enable);
+    // Method deprecated in 2.0 and not expected to be called by the framework.
+    return false;
+}
+
+Return<bool> GnssConfiguration::setSuplVersion(uint32_t) {
+    return true;
+}
+
+Return<bool> GnssConfiguration::setSuplMode(hidl_bitfield<SuplMode>) {
+    return true;
+}
+
+Return<bool> GnssConfiguration::setGpsLock(hidl_bitfield<GpsLock> gpsLock) {
+    ALOGD("setGpsLock gpsLock: %hhu", static_cast<GpsLock>(gpsLock));
+    // Method deprecated in 2.0 and not expected to be called by the framework.
+    return false;
+}
+
+Return<bool> GnssConfiguration::setLppProfile(hidl_bitfield<LppProfile>) {
+    return true;
+}
+
+Return<bool> GnssConfiguration::setGlonassPositioningProtocol(hidl_bitfield<GlonassPosProtocol>) {
+    return true;
+}
+
+Return<bool> GnssConfiguration::setEmergencySuplPdn(bool) {
+    return true;
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setBlacklist(
+        const hidl_vec<V1_1::IGnssConfiguration::BlacklistedSource>&) {
+    // TODO (b/122463906): Reuse 1.1 implementation.
+    return bool{};
+}
+
+// Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setEsExtensionSec(uint32_t emergencyExtensionSeconds) {
+    ALOGD("setEsExtensionSec emergencyExtensionSeconds: %d", emergencyExtensionSeconds);
+    return true;
+}
+
+// Methods from ::android::hardware::gnss::V2_1::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setBlacklist_2_1(
+        const hidl_vec<V2_1::IGnssConfiguration::BlacklistedSource>& sourceList) {
+    std::unique_lock<std::recursive_mutex> lock(mMutex);
+    mBlacklistedConstellationSet.clear();
+    mBlacklistedSourceSet.clear();
+    for (auto source : sourceList) {
+        if (source.svid == 0) {
+            // Wildcard blacklist, i.e., blacklist entire constellation.
+            mBlacklistedConstellationSet.insert(source.constellation);
+        } else {
+            mBlacklistedSourceSet.insert(source);
+        }
+    }
+    return true;
+}
+
+Return<bool> GnssConfiguration::isBlacklistedV2_1(const GnssSvInfoV2_1& gnssSvInfo) const {
+    std::unique_lock<std::recursive_mutex> lock(mMutex);
+    if (mBlacklistedConstellationSet.find(gnssSvInfo.v2_0.constellation) !=
+        mBlacklistedConstellationSet.end()) {
+        return true;
+    }
+    BlacklistedSourceV2_1 source = {.constellation = gnssSvInfo.v2_0.constellation,
+                                    .svid = gnssSvInfo.v2_0.v1_0.svid};
+    return (mBlacklistedSourceSet.find(source) != mBlacklistedSourceSet.end());
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
\ No newline at end of file
diff --git a/gnss/2.1/default/GnssConfiguration.h b/gnss/2.1/default/GnssConfiguration.h
new file mode 100644
index 0000000..662d61d
--- /dev/null
+++ b/gnss/2.1/default/GnssConfiguration.h
@@ -0,0 +1,101 @@
+/*
+ * 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_GNSS_V2_1_GNSSCONFIGURATION_H
+#define ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
+
+#include <android/hardware/gnss/2.1/IGnssCallback.h>
+#include <android/hardware/gnss/2.1/IGnssConfiguration.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <mutex>
+#include <unordered_set>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+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 BlacklistedSourceV2_1 =
+        ::android::hardware::gnss::V2_1::IGnssConfiguration::BlacklistedSource;
+using GnssConstellationTypeV2_0 = V2_0::GnssConstellationType;
+using GnssSvInfoV2_1 = V2_1::IGnssCallback::GnssSvInfo;
+
+struct BlacklistedSourceHashV2_1 {
+    inline int operator()(const BlacklistedSourceV2_1& source) const {
+        return int(source.constellation) * 1000 + int(source.svid);
+    }
+};
+
+struct BlacklistedSourceEqualV2_1 {
+    inline bool operator()(const BlacklistedSourceV2_1& s1, const BlacklistedSourceV2_1& s2) const {
+        return (s1.constellation == s2.constellation) && (s1.svid == s2.svid);
+    }
+};
+
+using BlacklistedSourceSetV2_1 =
+        std::unordered_set<BlacklistedSourceV2_1, BlacklistedSourceHashV2_1,
+                           BlacklistedSourceEqualV2_1>;
+using BlacklistedConstellationSetV2_1 = std::unordered_set<GnssConstellationTypeV2_0>;
+
+struct GnssConfiguration : public IGnssConfiguration {
+    // Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
+    Return<bool> setSuplEs(bool enabled) override;
+    Return<bool> setSuplVersion(uint32_t version) override;
+    Return<bool> setSuplMode(hidl_bitfield<SuplMode> mode) override;
+    Return<bool> setGpsLock(hidl_bitfield<GpsLock> lock) override;
+    Return<bool> setLppProfile(hidl_bitfield<LppProfile> lppProfile) override;
+    Return<bool> setGlonassPositioningProtocol(hidl_bitfield<GlonassPosProtocol> protocol) override;
+    Return<bool> setEmergencySuplPdn(bool enable) override;
+
+    // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+    Return<bool> setBlacklist(
+            const hidl_vec<V1_1::IGnssConfiguration::BlacklistedSource>& blacklist) override;
+
+    std::recursive_mutex& getMutex() const;
+
+    // Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
+    Return<bool> setEsExtensionSec(uint32_t emergencyExtensionSeconds) override;
+
+    // Methods from ::android::hardware::gnss::V2_1::IGnssConfiguration follow.
+    Return<bool> setBlacklist_2_1(
+            const hidl_vec<V2_1::IGnssConfiguration::BlacklistedSource>& blacklist) override;
+
+    Return<bool> isBlacklistedV2_1(const GnssSvInfoV2_1& gnssSvInfo) const;
+
+  private:
+    mutable std::recursive_mutex mMutex;
+
+    BlacklistedSourceSetV2_1 mBlacklistedSourceSet;
+    BlacklistedConstellationSetV2_1 mBlacklistedConstellationSet;
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
\ No newline at end of file
diff --git a/gnss/2.1/default/GnssMeasurement.cpp b/gnss/2.1/default/GnssMeasurement.cpp
new file mode 100644
index 0000000..ebfa7dd
--- /dev/null
+++ b/gnss/2.1/default/GnssMeasurement.cpp
@@ -0,0 +1,123 @@
+/*
+ * 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 "GnssMeasurement"
+
+#include "GnssMeasurement.h"
+#include <log/log.h>
+#include "Utils.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+
+using common::Utils;
+
+namespace V2_1 {
+namespace implementation {
+
+sp<V2_1::IGnssMeasurementCallback> GnssMeasurement::sCallback = nullptr;
+
+GnssMeasurement::GnssMeasurement() : mMinIntervalMillis(1000) {}
+
+GnssMeasurement::~GnssMeasurement() {
+    stop();
+}
+
+// Methods from V1_0::IGnssMeasurement follow.
+Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback(
+        const sp<V1_0::IGnssMeasurementCallback>&) {
+    // TODO implement
+    return V1_0::IGnssMeasurement::GnssMeasurementStatus{};
+}
+
+Return<void> GnssMeasurement::close() {
+    ALOGD("close");
+    std::unique_lock<std::mutex> lock(mMutex);
+    stop();
+    sCallback = nullptr;
+    return Void();
+}
+
+// Methods from V1_1::IGnssMeasurement follow.
+Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_1_1(
+        const sp<V1_1::IGnssMeasurementCallback>&, bool) {
+    // TODO implement
+    return V1_0::IGnssMeasurement::GnssMeasurementStatus{};
+}
+
+// Methods from V2_0::IGnssMeasurement follow.
+Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_2_0(
+        const sp<V2_0::IGnssMeasurementCallback>&, bool) {
+    // TODO implement
+    return V1_0::IGnssMeasurement::GnssMeasurementStatus{};
+}
+
+// Methods from V2_1::IGnssMeasurement follow.
+Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_2_1(
+        const sp<V2_1::IGnssMeasurementCallback>& callback, bool) {
+    ALOGD("setCallback_2_1");
+    std::unique_lock<std::mutex> lock(mMutex);
+    sCallback = callback;
+
+    if (mIsActive) {
+        ALOGW("GnssMeasurement callback already set. Resetting the callback...");
+        stop();
+    }
+    start();
+
+    return V1_0::IGnssMeasurement::GnssMeasurementStatus::SUCCESS;
+}
+
+void GnssMeasurement::start() {
+    ALOGD("start");
+    mIsActive = true;
+    mThread = std::thread([this]() {
+        while (mIsActive == true) {
+            auto measurement = Utils::getMockMeasurementV2_1();
+            this->reportMeasurement(measurement);
+
+            std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis));
+        }
+    });
+}
+
+void GnssMeasurement::stop() {
+    ALOGD("stop");
+    mIsActive = false;
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+}
+
+void GnssMeasurement::reportMeasurement(const GnssDataV2_1& data) {
+    ALOGD("reportMeasurement()");
+    std::unique_lock<std::mutex> lock(mMutex);
+    if (sCallback == nullptr) {
+        ALOGE("%s: GnssMeasurement::sCallback is null.", __func__);
+        return;
+    }
+    auto ret = sCallback->gnssMeasurementCb_2_1(data);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/2.1/default/GnssMeasurement.h b/gnss/2.1/default/GnssMeasurement.h
new file mode 100644
index 0000000..ee32903
--- /dev/null
+++ b/gnss/2.1/default/GnssMeasurement.h
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android/hardware/gnss/2.1/IGnssMeasurement.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <atomic>
+#include <mutex>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using GnssDataV2_1 = V2_1::IGnssMeasurementCallback::GnssData;
+
+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;
+
+struct GnssMeasurement : public IGnssMeasurement {
+    GnssMeasurement();
+    ~GnssMeasurement();
+    // Methods from V1_0::IGnssMeasurement follow.
+    Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback(
+            const sp<V1_0::IGnssMeasurementCallback>& callback) override;
+    Return<void> close() override;
+
+    // Methods from V1_1::IGnssMeasurement follow.
+    Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback_1_1(
+            const sp<V1_1::IGnssMeasurementCallback>& callback, bool enableFullTracking) override;
+
+    // Methods from V2_0::IGnssMeasurement follow.
+    Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback_2_0(
+            const sp<V2_0::IGnssMeasurementCallback>& callback, bool enableFullTracking) override;
+
+    // Methods from V2_1::IGnssMeasurement follow.
+    Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback_2_1(
+            const sp<V2_1::IGnssMeasurementCallback>& callback, bool enableFullTracking) override;
+
+  private:
+    void start();
+    void stop();
+    void reportMeasurement(const GnssDataV2_1&);
+
+    static sp<IGnssMeasurementCallback> sCallback;
+    std::atomic<long> mMinIntervalMillis;
+    std::atomic<bool> mIsActive;
+    std::thread mThread;
+    mutable std::mutex mMutex;
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/2.1/default/OWNERS b/gnss/2.1/default/OWNERS
new file mode 100644
index 0000000..b7b4a2e
--- /dev/null
+++ b/gnss/2.1/default/OWNERS
@@ -0,0 +1,4 @@
+gomo@google.com
+smalkos@google.com
+wyattriley@google.com
+yuhany@google.com
diff --git a/gnss/2.1/default/android.hardware.gnss@2.1-service.rc b/gnss/2.1/default/android.hardware.gnss@2.1-service.rc
new file mode 100644
index 0000000..5926c77
--- /dev/null
+++ b/gnss/2.1/default/android.hardware.gnss@2.1-service.rc
@@ -0,0 +1,4 @@
+service vendor.gnss-2-1 /vendor/bin/hw/android.hardware.gnss@2.1-service
+    class hal
+    user system
+    group system
diff --git a/gnss/2.1/default/android.hardware.gnss@2.1-service.xml b/gnss/2.1/default/android.hardware.gnss@2.1-service.xml
new file mode 100644
index 0000000..12a1fdf
--- /dev/null
+++ b/gnss/2.1/default/android.hardware.gnss@2.1-service.xml
@@ -0,0 +1,12 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.gnss</name>
+        <transport>hwbinder</transport>
+        <version>2.1</version>
+        <version>1.1</version>
+        <interface>
+            <name>IGnss</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/gnss/2.1/default/service.cpp b/gnss/2.1/default/service.cpp
new file mode 100644
index 0000000..5e004d5
--- /dev/null
+++ b/gnss/2.1/default/service.cpp
@@ -0,0 +1,41 @@
+/*
+ * 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 "android.hardware.gnss@2.1-service"
+
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include "Gnss.h"
+
+using ::android::OK;
+using ::android::sp;
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::joinRpcThreadpool;
+using ::android::hardware::gnss::V2_1::IGnss;
+using ::android::hardware::gnss::V2_1::implementation::Gnss;
+
+int main(int /* argc */, char* /* argv */[]) {
+    sp<IGnss> gnss = new Gnss();
+    configureRpcThreadpool(1, true /* will join */);
+    if (gnss->registerAsService() != OK) {
+        ALOGE("Could not register gnss 2.1 service.");
+        return 1;
+    }
+    joinRpcThreadpool();
+
+    ALOGE("Service exited!");
+    return 1;
+}
\ No newline at end of file
diff --git a/gnss/2.1/vts/OWNERS b/gnss/2.1/vts/OWNERS
new file mode 100644
index 0000000..b7b4a2e
--- /dev/null
+++ b/gnss/2.1/vts/OWNERS
@@ -0,0 +1,4 @@
+gomo@google.com
+smalkos@google.com
+wyattriley@google.com
+yuhany@google.com
diff --git a/gnss/2.1/vts/functional/Android.bp b/gnss/2.1/vts/functional/Android.bp
new file mode 100644
index 0000000..8340499
--- /dev/null
+++ b/gnss/2.1/vts/functional/Android.bp
@@ -0,0 +1,35 @@
+//
+// 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: "VtsHalGnssV2_1TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "gnss_hal_test.cpp",
+        "gnss_hal_test_cases.cpp",
+        "VtsHalGnssV2_1TargetTest.cpp",
+    ],
+    static_libs: [
+        "android.hardware.gnss.measurement_corrections@1.0",
+        "android.hardware.gnss.visibility_control@1.0",
+        "android.hardware.gnss@1.0",
+        "android.hardware.gnss@1.1",
+        "android.hardware.gnss@2.0",
+        "android.hardware.gnss@2.1",
+        "android.hardware.gnss@common-vts-lib",
+    ],
+    test_suites: ["general-tests", "vts-core"],
+}
diff --git a/gnss/2.1/vts/functional/VtsHalGnssV2_1TargetTest.cpp b/gnss/2.1/vts/functional/VtsHalGnssV2_1TargetTest.cpp
new file mode 100644
index 0000000..e61d885
--- /dev/null
+++ b/gnss/2.1/vts/functional/VtsHalGnssV2_1TargetTest.cpp
@@ -0,0 +1,29 @@
+/*
+ * 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 "VtsHalGnssV2_1TargetTest"
+
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include "gnss_hal_test.h"
+
+using android::hardware::gnss::V2_1::IGnss;
+
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, GnssHalTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IGnss::descriptor)),
+        android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/gnss/2.1/vts/functional/gnss_hal_test.cpp b/gnss/2.1/vts/functional/gnss_hal_test.cpp
new file mode 100644
index 0000000..7cfe0db
--- /dev/null
+++ b/gnss/2.1/vts/functional/gnss_hal_test.cpp
@@ -0,0 +1,217 @@
+/*
+ * 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 "GnssHalTest"
+
+#include <gnss_hal_test.h>
+#include <chrono>
+#include "Utils.h"
+
+#include <gtest/gtest.h>
+
+using ::android::hardware::gnss::common::Utils;
+
+// Implementations for the main test class for GNSS HAL
+void GnssHalTest::SetUp() {
+    gnss_hal_ = IGnss::getService(GetParam());
+    ASSERT_NE(gnss_hal_, nullptr);
+
+    SetUpGnssCallback();
+}
+
+void GnssHalTest::TearDown() {
+    if (gnss_hal_ != nullptr) {
+        gnss_hal_->cleanup();
+        gnss_hal_ = nullptr;
+    }
+
+    // Set to nullptr to destruct the callback event queues and warn of any unprocessed events.
+    gnss_cb_ = nullptr;
+}
+
+void GnssHalTest::SetUpGnssCallback() {
+    gnss_cb_ = new GnssCallback();
+    ASSERT_NE(gnss_cb_, nullptr);
+
+    auto result = gnss_hal_->setCallback_2_1(gnss_cb_);
+    if (!result.isOk()) {
+        ALOGE("result of failed setCallback %s", result.description().c_str());
+    }
+
+    ASSERT_TRUE(result.isOk());
+    ASSERT_TRUE(result);
+
+    /*
+     * All capabilities, name and systemInfo callbacks should trigger
+     */
+    EXPECT_TRUE(gnss_cb_->capabilities_cbq_.retrieve(gnss_cb_->last_capabilities_, TIMEOUT_SEC));
+    EXPECT_TRUE(gnss_cb_->info_cbq_.retrieve(gnss_cb_->last_info_, TIMEOUT_SEC));
+    EXPECT_TRUE(gnss_cb_->name_cbq_.retrieve(gnss_cb_->last_name_, TIMEOUT_SEC));
+
+    EXPECT_EQ(gnss_cb_->capabilities_cbq_.calledCount(), 1);
+    EXPECT_EQ(gnss_cb_->info_cbq_.calledCount(), 1);
+    EXPECT_EQ(gnss_cb_->name_cbq_.calledCount(), 1);
+}
+
+void GnssHalTest::StopAndClearLocations() {
+    const auto result = gnss_hal_->stop();
+
+    EXPECT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+
+    /*
+     * Clear notify/waiting counter, allowing up till the timeout after
+     * the last reply for final startup messages to arrive (esp. system
+     * info.)
+     */
+    while (gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, TIMEOUT_SEC)) {
+    }
+    gnss_cb_->location_cbq_.reset();
+}
+
+void GnssHalTest::SetPositionMode(const int min_interval_msec, const bool low_power_mode) {
+    const int kPreferredAccuracy = 0;  // Ideally perfect (matches GnssLocationProvider)
+    const int kPreferredTimeMsec = 0;  // Ideally immediate
+
+    const auto result = gnss_hal_->setPositionMode_1_1(
+            IGnss::GnssPositionMode::MS_BASED, IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC,
+            min_interval_msec, kPreferredAccuracy, kPreferredTimeMsec, low_power_mode);
+
+    ASSERT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+}
+
+bool GnssHalTest::StartAndCheckFirstLocation() {
+    const auto result = gnss_hal_->start();
+
+    EXPECT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+
+    /*
+     * GnssLocationProvider support of AGPS SUPL & XtraDownloader is not available in VTS,
+     * so allow time to demodulate ephemeris over the air.
+     */
+    const int kFirstGnssLocationTimeoutSeconds = 75;
+
+    EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_,
+                                                 kFirstGnssLocationTimeoutSeconds));
+    int locationCalledCount = gnss_cb_->location_cbq_.calledCount();
+    EXPECT_EQ(locationCalledCount, 1);
+
+    if (locationCalledCount > 0) {
+        // don't require speed on first fix
+        CheckLocation(gnss_cb_->last_location_, false);
+        return true;
+    }
+    return false;
+}
+
+void GnssHalTest::CheckLocation(const GnssLocation_2_0& location, bool check_speed) {
+    const bool check_more_accuracies =
+            (gnss_cb_->info_cbq_.calledCount() > 0 && gnss_cb_->last_info_.yearOfHw >= 2017);
+
+    Utils::checkLocation(location.v1_0, check_speed, check_more_accuracies);
+}
+
+void GnssHalTest::StartAndCheckLocations(int count) {
+    const int kMinIntervalMsec = 500;
+    const int kLocationTimeoutSubsequentSec = 2;
+    const bool kLowPowerMode = false;
+
+    SetPositionMode(kMinIntervalMsec, kLowPowerMode);
+
+    EXPECT_TRUE(StartAndCheckFirstLocation());
+
+    for (int i = 1; i < count; i++) {
+        EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_,
+                                                     kLocationTimeoutSubsequentSec));
+        int locationCalledCount = gnss_cb_->location_cbq_.calledCount();
+        EXPECT_EQ(locationCalledCount, i + 1);
+        // Don't cause confusion by checking details if no location yet
+        if (locationCalledCount > 0) {
+            // Should be more than 1 location by now, but if not, still don't check first fix speed
+            CheckLocation(gnss_cb_->last_location_, locationCalledCount > 1);
+        }
+    }
+}
+
+GnssHalTest::GnssCallback::GnssCallback()
+    : info_cbq_("system_info"),
+      name_cbq_("name"),
+      capabilities_cbq_("capabilities"),
+      location_cbq_("location"),
+      sv_info_list_cbq_("sv_info") {}
+
+Return<void> GnssHalTest::GnssCallback::gnssSetSystemInfoCb(
+        const IGnssCallback_1_0::GnssSystemInfo& info) {
+    ALOGI("Info received, year %d", info.yearOfHw);
+    info_cbq_.store(info);
+    return Void();
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) {
+    ALOGI("Capabilities received %d", capabilities);
+    capabilities_cbq_.store(capabilities);
+    return Void();
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssSetCapabilitiesCb_2_0(uint32_t capabilities) {
+    ALOGI("Capabilities (v2.0) received %d", capabilities);
+    capabilities_cbq_.store(capabilities);
+    return Void();
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssNameCb(const android::hardware::hidl_string& name) {
+    ALOGI("Name received: %s", name.c_str());
+    name_cbq_.store(name);
+    return Void();
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssLocationCb(const GnssLocation_1_0& location) {
+    ALOGI("Location received");
+    GnssLocation_2_0 location_v2_0;
+    location_v2_0.v1_0 = location;
+    return gnssLocationCbImpl(location_v2_0);
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssLocationCb_2_0(const GnssLocation_2_0& location) {
+    ALOGI("Location (v2.0) received");
+    return gnssLocationCbImpl(location);
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssLocationCbImpl(const GnssLocation_2_0& location) {
+    location_cbq_.store(location);
+    return Void();
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssSvStatusCb(const IGnssCallback_1_0::GnssSvStatus&) {
+    ALOGI("gnssSvStatusCb");
+    return Void();
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssSvStatusCb_2_1(
+        const hidl_vec<IGnssCallback_2_1::GnssSvInfo>& svInfoList) {
+    ALOGI("gnssSvStatusCb_2_1. Size = %d", (int)svInfoList.size());
+    sv_info_list_cbq_.store(svInfoList);
+    return Void();
+}
+
+Return<void> GnssHalTest::GnssMeasurementCallback::gnssMeasurementCb_2_1(
+        const IGnssMeasurementCallback_2_1::GnssData& data) {
+    ALOGD("GnssMeasurement v2.1 received. Size = %d", (int)data.measurements.size());
+    measurement_cbq_.store(data);
+    return Void();
+}
diff --git a/gnss/2.1/vts/functional/gnss_hal_test.h b/gnss/2.1/vts/functional/gnss_hal_test.h
new file mode 100644
index 0000000..2e1add0
--- /dev/null
+++ b/gnss/2.1/vts/functional/gnss_hal_test.h
@@ -0,0 +1,191 @@
+/*
+ * 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 GNSS_HAL_TEST_H_
+#define GNSS_HAL_TEST_H_
+
+#include <android/hardware/gnss/2.1/IGnss.h>
+#include "GnssCallbackEventQueue.h"
+
+#include <gtest/gtest.h>
+
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+
+using android::hardware::gnss::common::GnssCallbackEventQueue;
+using android::hardware::gnss::V1_0::GnssLocationFlags;
+using android::hardware::gnss::V2_1::IGnss;
+
+using GnssLocation_1_0 = android::hardware::gnss::V1_0::GnssLocation;
+using GnssLocation_2_0 = android::hardware::gnss::V2_0::GnssLocation;
+
+using IGnssCallback_1_0 = android::hardware::gnss::V1_0::IGnssCallback;
+using IGnssCallback_2_0 = android::hardware::gnss::V2_0::IGnssCallback;
+using IGnssCallback_2_1 = android::hardware::gnss::V2_1::IGnssCallback;
+
+using IGnssMeasurementCallback_1_0 = android::hardware::gnss::V1_0::IGnssMeasurementCallback;
+using IGnssMeasurementCallback_1_1 = android::hardware::gnss::V1_1::IGnssMeasurementCallback;
+using IGnssMeasurementCallback_2_0 = android::hardware::gnss::V2_0::IGnssMeasurementCallback;
+using IGnssMeasurementCallback_2_1 = android::hardware::gnss::V2_1::IGnssMeasurementCallback;
+
+using android::sp;
+
+#define TIMEOUT_SEC 2  // for basic commands/responses
+
+// The main test class for GNSS HAL.
+class GnssHalTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override;
+
+    virtual void TearDown() override;
+
+    /* Callback class for data & Event. */
+    class GnssCallback : public IGnssCallback_2_1 {
+      public:
+        IGnssCallback_1_0::GnssSystemInfo last_info_;
+        android::hardware::hidl_string last_name_;
+        uint32_t last_capabilities_;
+        GnssLocation_2_0 last_location_;
+
+        GnssCallbackEventQueue<IGnssCallback_1_0::GnssSystemInfo> info_cbq_;
+        GnssCallbackEventQueue<android::hardware::hidl_string> name_cbq_;
+        GnssCallbackEventQueue<uint32_t> capabilities_cbq_;
+        GnssCallbackEventQueue<GnssLocation_2_0> location_cbq_;
+        GnssCallbackEventQueue<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_list_cbq_;
+
+        GnssCallback();
+        virtual ~GnssCallback() = default;
+
+        // Dummy callback handlers
+        Return<void> gnssStatusCb(const IGnssCallback_1_0::GnssStatusValue /* status */) override {
+            return Void();
+        }
+        Return<void> gnssNmeaCb(int64_t /* timestamp */,
+                                const android::hardware::hidl_string& /* nmea */) override {
+            return Void();
+        }
+        Return<void> gnssAcquireWakelockCb() override { return Void(); }
+        Return<void> gnssReleaseWakelockCb() override { return Void(); }
+        Return<void> gnssRequestLocationCb(bool /* independentFromGnss */) override {
+            return Void();
+        }
+        Return<void> gnssRequestTimeCb() override { return Void(); }
+        // Actual (test) callback handlers
+        Return<void> gnssNameCb(const android::hardware::hidl_string& name) override;
+        Return<void> gnssLocationCb(const GnssLocation_1_0& location) override;
+        Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override;
+        Return<void> gnssSetSystemInfoCb(const IGnssCallback_1_0::GnssSystemInfo& info) override;
+        Return<void> gnssSvStatusCb(const IGnssCallback_1_0::GnssSvStatus& svStatus) override;
+
+        // New in v2.0
+        Return<void> gnssLocationCb_2_0(const GnssLocation_2_0& location) override;
+        Return<void> gnssRequestLocationCb_2_0(bool /* independentFromGnss */,
+                                               bool /* isUserEmergency */) override {
+            return Void();
+        }
+        Return<void> gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override;
+        Return<void> gnssSvStatusCb_2_0(const hidl_vec<IGnssCallback_2_0::GnssSvInfo>&) override {
+            return Void();
+        }
+
+        // New in v2.1
+        Return<void> gnssSvStatusCb_2_1(
+                const hidl_vec<IGnssCallback_2_1::GnssSvInfo>& svInfoList) override;
+
+      private:
+        Return<void> gnssLocationCbImpl(const GnssLocation_2_0& location);
+    };
+
+    /* Callback class for GnssMeasurement. */
+    class GnssMeasurementCallback : public IGnssMeasurementCallback_2_1 {
+      public:
+        GnssCallbackEventQueue<IGnssMeasurementCallback_2_1::GnssData> measurement_cbq_;
+
+        GnssMeasurementCallback() : measurement_cbq_("measurement"){};
+        virtual ~GnssMeasurementCallback() = default;
+
+        // Methods from V1_0::IGnssMeasurementCallback follow.
+        Return<void> GnssMeasurementCb(const IGnssMeasurementCallback_1_0::GnssData&) override {
+            return Void();
+        }
+
+        // Methods from V1_1::IGnssMeasurementCallback follow.
+        Return<void> gnssMeasurementCb(const IGnssMeasurementCallback_1_1::GnssData&) override {
+            return Void();
+        }
+
+        // Methods from V2_0::IGnssMeasurementCallback follow.
+        Return<void> gnssMeasurementCb_2_0(const IGnssMeasurementCallback_2_0::GnssData&) override {
+            return Void();
+        }
+
+        // Methods from V2_1::IGnssMeasurementCallback follow.
+        Return<void> gnssMeasurementCb_2_1(const IGnssMeasurementCallback_2_1::GnssData&) override;
+    };
+
+    /*
+     * SetUpGnssCallback:
+     *   Set GnssCallback and verify the result.
+     */
+    void SetUpGnssCallback();
+
+    /*
+     * StartAndCheckFirstLocation:
+     *   Helper function to start location, and check the first one.
+     *
+     *   <p> Note this leaves the Location request active, to enable Stop call vs. other call
+     *   reordering tests.
+     *
+     * returns  true if a location was successfully generated
+     */
+    bool StartAndCheckFirstLocation();
+
+    /*
+     * CheckLocation:
+     *   Helper function to vet Location fields
+     *
+     *   check_speed: true if speed related fields are also verified.
+     */
+    void CheckLocation(const GnssLocation_2_0& location, const bool check_speed);
+
+    /*
+     * StartAndCheckLocations:
+     *   Helper function to collect, and check a number of
+     *   normal ~1Hz locations.
+     *
+     *   Note this leaves the Location request active, to enable Stop call vs. other call
+     *   reordering tests.
+     */
+    void StartAndCheckLocations(int count);
+
+    /*
+     * StopAndClearLocations:
+     * Helper function to stop locations, and clear any remaining notifications
+     */
+    void StopAndClearLocations();
+
+    /*
+     * SetPositionMode:
+     * Helper function to set positioning mode and verify output
+     */
+    void SetPositionMode(const int min_interval_msec, const bool low_power_mode);
+
+    sp<IGnss> gnss_hal_;        // GNSS HAL to call into
+    sp<GnssCallback> gnss_cb_;  // Primary callback interface
+};
+
+#endif  // GNSS_HAL_TEST_H_
diff --git a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
new file mode 100644
index 0000000..45a3d2a
--- /dev/null
+++ b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
@@ -0,0 +1,491 @@
+/*
+ * 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 "GnssHalTestCases"
+
+#include <gnss_hal_test.h>
+#include "Utils.h"
+
+#include <gtest/gtest.h>
+
+using android::hardware::hidl_string;
+using android::hardware::hidl_vec;
+
+using android::hardware::gnss::common::Utils;
+
+using IGnssMeasurement_2_1 = android::hardware::gnss::V2_1::IGnssMeasurement;
+using IGnssMeasurement_2_0 = android::hardware::gnss::V2_0::IGnssMeasurement;
+using IGnssMeasurement_1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
+using IGnssMeasurement_1_0 = android::hardware::gnss::V1_0::IGnssMeasurement;
+using IGnssConfiguration_2_1 = android::hardware::gnss::V2_1::IGnssConfiguration;
+using IGnssConfiguration_2_0 = android::hardware::gnss::V2_0::IGnssConfiguration;
+using IGnssConfiguration_1_1 = android::hardware::gnss::V1_1::IGnssConfiguration;
+using IGnssConfiguration_1_0 = android::hardware::gnss::V1_0::IGnssConfiguration;
+
+using android::hardware::gnss::V2_0::GnssConstellationType;
+using android::hardware::gnss::V2_1::IGnssConfiguration;
+
+/*
+ * SetupTeardownCreateCleanup:
+ * Requests the gnss HAL then calls cleanup
+ *
+ * Empty test fixture to verify basic Setup & Teardown
+ */
+TEST_P(GnssHalTest, SetupTeardownCreateCleanup) {}
+
+/*
+ * TestGnssMeasurementExtension:
+ * Gets the GnssMeasurementExtension and verifies that it returns an actual extension.
+ */
+TEST_P(GnssHalTest, TestGnssMeasurementExtension) {
+    auto gnssMeasurement_2_1 = gnss_hal_->getExtensionGnssMeasurement_2_1();
+    auto gnssMeasurement_2_0 = gnss_hal_->getExtensionGnssMeasurement_2_0();
+    auto gnssMeasurement_1_1 = gnss_hal_->getExtensionGnssMeasurement_1_1();
+    auto gnssMeasurement_1_0 = gnss_hal_->getExtensionGnssMeasurement();
+    ASSERT_TRUE(gnssMeasurement_2_1.isOk() && gnssMeasurement_2_0.isOk() &&
+                gnssMeasurement_1_1.isOk() && gnssMeasurement_1_0.isOk());
+    sp<IGnssMeasurement_2_1> iGnssMeas_2_1 = gnssMeasurement_2_1;
+    sp<IGnssMeasurement_2_0> iGnssMeas_2_0 = gnssMeasurement_2_0;
+    sp<IGnssMeasurement_1_1> iGnssMeas_1_1 = gnssMeasurement_1_1;
+    sp<IGnssMeasurement_1_0> iGnssMeas_1_0 = gnssMeasurement_1_0;
+    // At least one interface is non-null.
+    int numNonNull = (int)(iGnssMeas_2_1 != nullptr) + (int)(iGnssMeas_2_0 != nullptr) +
+                     (int)(iGnssMeas_1_1 != nullptr) + (int)(iGnssMeas_1_0 != nullptr);
+    ASSERT_TRUE(numNonNull >= 1);
+}
+
+/*
+ * TestGnssConfigurationExtension:
+ * Gets the GnssConfigurationExtension and verifies that it returns an actual extension.
+ */
+TEST_P(GnssHalTest, TestGnssConfigurationExtension) {
+    auto gnssConfiguration_2_1 = gnss_hal_->getExtensionGnssConfiguration_2_1();
+    auto gnssConfiguration_2_0 = gnss_hal_->getExtensionGnssConfiguration_2_0();
+    auto gnssConfiguration_1_1 = gnss_hal_->getExtensionGnssConfiguration_1_1();
+    auto gnssConfiguration_1_0 = gnss_hal_->getExtensionGnssConfiguration();
+    ASSERT_TRUE(gnssConfiguration_2_1.isOk() && gnssConfiguration_2_0.isOk() &&
+                gnssConfiguration_1_1.isOk() && gnssConfiguration_1_0.isOk());
+    sp<IGnssConfiguration_2_1> iGnssConfig_2_1 = gnssConfiguration_2_1;
+    sp<IGnssConfiguration_2_0> iGnssConfig_2_0 = gnssConfiguration_2_0;
+    sp<IGnssConfiguration_1_1> iGnssConfig_1_1 = gnssConfiguration_1_1;
+    sp<IGnssConfiguration_1_0> iGnssConfig_1_0 = gnssConfiguration_1_0;
+    // At least one interface is non-null.
+    int numNonNull = (int)(iGnssConfig_2_1 != nullptr) + (int)(iGnssConfig_2_0 != nullptr) +
+                     (int)(iGnssConfig_1_1 != nullptr) + (int)(iGnssConfig_1_0 != nullptr);
+    ASSERT_TRUE(numNonNull >= 1);
+}
+
+/*
+ * TestGnssMeasurementFields:
+ * Sets a GnssMeasurementCallback, waits for a measurement, and verifies
+ * 1. basebandCN0DbHz is valid
+ */
+TEST_P(GnssHalTest, TestGnssMeasurementFields) {
+    const int kFirstGnssMeasurementTimeoutSeconds = 10;
+
+    auto gnssMeasurement = gnss_hal_->getExtensionGnssMeasurement_2_1();
+    ASSERT_TRUE(gnssMeasurement.isOk());
+
+    // Skip test if GnssMeasurement v2.1 is not supported
+    sp<IGnssMeasurement_2_1> iGnssMeasurement = gnssMeasurement;
+    if (iGnssMeasurement == nullptr) {
+        return;
+    }
+
+    sp<GnssMeasurementCallback> callback = new GnssMeasurementCallback();
+    auto result = iGnssMeasurement->setCallback_2_1(callback, /* enableFullTracking= */ true);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_EQ(result, IGnssMeasurement_1_0::GnssMeasurementStatus::SUCCESS);
+
+    IGnssMeasurementCallback_2_1::GnssData lastMeasurement;
+    ASSERT_TRUE(callback->measurement_cbq_.retrieve(lastMeasurement,
+                                                    kFirstGnssMeasurementTimeoutSeconds));
+    EXPECT_EQ(callback->measurement_cbq_.calledCount(), 1);
+    ASSERT_TRUE(lastMeasurement.measurements.size() > 0);
+    for (auto measurement : lastMeasurement.measurements) {
+        // Verify basebandCn0DbHz is valid.
+        ASSERT_TRUE(measurement.basebandCN0DbHz > 0.0 && measurement.basebandCN0DbHz <= 65.0);
+    }
+
+    iGnssMeasurement->close();
+}
+
+/*
+ * TestGnssSvInfoFields:
+ * Gets 1 location and a GnssSvInfo, and verifies
+ * 1. basebandCN0DbHz is valid.
+ */
+TEST_P(GnssHalTest, TestGnssSvInfoFields) {
+    gnss_cb_->location_cbq_.reset();
+    StartAndCheckFirstLocation();
+    int location_called_count = gnss_cb_->location_cbq_.calledCount();
+
+    // Tolerate 1 less sv status to handle edge cases in reporting.
+    int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+    EXPECT_GE(sv_info_list_cbq_size, 0);
+    ALOGD("Observed %d GnssSvStatus, while awaiting one location (%d received)",
+          sv_info_list_cbq_size, location_called_count);
+
+    hidl_vec<IGnssCallback_2_1::GnssSvInfo> last_sv_info_list;
+    ASSERT_TRUE(gnss_cb_->sv_info_list_cbq_.retrieve(last_sv_info_list, 1));
+
+    bool nonZeroCn0Found = false;
+    for (auto sv_info : last_sv_info_list) {
+        ASSERT_TRUE(sv_info.basebandCN0DbHz >= 0.0 && sv_info.basebandCN0DbHz <= 65.0);
+        if (sv_info.basebandCN0DbHz > 0.0) {
+            nonZeroCn0Found = true;
+        }
+    }
+    // Assert at least one value is non-zero. Zero is ok in status as it's possibly
+    // reporting a searched but not found satellite.
+    ASSERT_TRUE(nonZeroCn0Found);
+    StopAndClearLocations();
+}
+
+/*
+ * FindStrongFrequentNonGpsSource:
+ *
+ * Search through a GnssSvStatus list for the strongest non-GPS satellite observed enough times
+ *
+ * returns the strongest source,
+ *         or a source with constellation == UNKNOWN if none are found sufficient times
+ * TODO(skz): create a template for this to reduce code duplication of v2.1 and v2.0 since both
+ * are using vectors.
+ */
+IGnssConfiguration::BlacklistedSource FindStrongFrequentNonGpsSource(
+        const std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_list,
+        const int min_observations) {
+    struct ComparableBlacklistedSource {
+        IGnssConfiguration::BlacklistedSource id;
+
+        ComparableBlacklistedSource() {
+            id.constellation = GnssConstellationType::UNKNOWN;
+            id.svid = 0;
+        }
+
+        bool operator<(const ComparableBlacklistedSource& compare) const {
+            return ((id.svid < compare.id.svid) || ((id.svid == compare.id.svid) &&
+                                                    (id.constellation < compare.id.constellation)));
+        }
+    };
+
+    struct SignalCounts {
+        int observations;
+        float max_cn0_dbhz;
+    };
+
+    std::map<ComparableBlacklistedSource, SignalCounts> mapSignals;
+
+    for (const auto& sv_info_vec : sv_info_list) {
+        for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
+            const auto& gnss_sv = sv_info_vec[iSv];
+            if ((gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX) &&
+                (gnss_sv.v2_0.constellation != GnssConstellationType::GPS)) {
+                ComparableBlacklistedSource source;
+                source.id.svid = gnss_sv.v2_0.v1_0.svid;
+                source.id.constellation = gnss_sv.v2_0.constellation;
+
+                const auto& itSignal = mapSignals.find(source);
+                if (itSignal == mapSignals.end()) {
+                    SignalCounts counts;
+                    counts.observations = 1;
+                    counts.max_cn0_dbhz = gnss_sv.v2_0.v1_0.cN0Dbhz;
+                    mapSignals.insert(
+                            std::pair<ComparableBlacklistedSource, SignalCounts>(source, counts));
+                } else {
+                    itSignal->second.observations++;
+                    if (itSignal->second.max_cn0_dbhz < gnss_sv.v2_0.v1_0.cN0Dbhz) {
+                        itSignal->second.max_cn0_dbhz = gnss_sv.v2_0.v1_0.cN0Dbhz;
+                    }
+                }
+            }
+        }
+    }
+
+    float max_cn0_dbhz_with_sufficient_count = 0.;
+    int total_observation_count = 0;
+    int blacklisted_source_count_observation = 0;
+
+    ComparableBlacklistedSource source_to_blacklist;  // initializes to zero = UNKNOWN constellation
+    for (auto const& pairSignal : mapSignals) {
+        total_observation_count += pairSignal.second.observations;
+        if ((pairSignal.second.observations >= min_observations) &&
+            (pairSignal.second.max_cn0_dbhz > max_cn0_dbhz_with_sufficient_count)) {
+            source_to_blacklist = pairSignal.first;
+            blacklisted_source_count_observation = pairSignal.second.observations;
+            max_cn0_dbhz_with_sufficient_count = pairSignal.second.max_cn0_dbhz;
+        }
+    }
+    ALOGD("Among %d observations, chose svid %d, constellation %d, "
+          "with %d observations at %.1f max CNo",
+          total_observation_count, source_to_blacklist.id.svid,
+          (int)source_to_blacklist.id.constellation, blacklisted_source_count_observation,
+          max_cn0_dbhz_with_sufficient_count);
+
+    return source_to_blacklist.id;
+}
+
+/*
+ * BlacklistIndividualSatellites:
+ *
+ * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
+ * GnssStatus for common satellites (strongest and one other.)
+ * 2a & b) Turns off location, and blacklists common satellites.
+ * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
+ * GnssStatus does not use those satellites.
+ * 4a & b) Turns off location, and send in empty blacklist.
+ * 5a) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
+ * GnssStatus does re-use at least the previously strongest satellite
+ * 5b) Retry a few times, in case GNSS search strategy takes a while to reacquire even the
+ * formerly strongest satellite
+ */
+TEST_P(GnssHalTest, BlacklistIndividualSatellites) {
+    const int kLocationsToAwait = 3;
+    const int kRetriesToUnBlacklist = 10;
+
+    gnss_cb_->location_cbq_.reset();
+    StartAndCheckLocations(kLocationsToAwait);
+    int location_called_count = gnss_cb_->location_cbq_.calledCount();
+
+    // Tolerate 1 less sv status to handle edge cases in reporting.
+    int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+    EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
+    ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
+          sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
+
+    /*
+     * Identify strongest SV seen at least kLocationsToAwait -1 times
+     * Why -1?  To avoid test flakiness in case of (plausible) slight flakiness in strongest signal
+     * observability (one epoch RF null)
+     */
+
+    const int kGnssSvInfoListTimeout = 2;
+    std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_vec_list;
+    int count = gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec_list, sv_info_list_cbq_size,
+                                                     kGnssSvInfoListTimeout);
+
+    ASSERT_EQ(count, sv_info_list_cbq_size);
+
+    IGnssConfiguration::BlacklistedSource source_to_blacklist =
+            FindStrongFrequentNonGpsSource(sv_info_vec_list, kLocationsToAwait - 1);
+
+    if (source_to_blacklist.constellation == GnssConstellationType::UNKNOWN) {
+        // Cannot find a non-GPS satellite. Let the test pass.
+        ALOGD("Cannot find a non-GPS satellite. Letting the test pass.");
+        return;
+    }
+
+    // Stop locations, blacklist the common SV
+    StopAndClearLocations();
+
+    auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_2_1();
+    ASSERT_TRUE(gnss_configuration_hal_return.isOk());
+    sp<IGnssConfiguration> gnss_configuration_hal = gnss_configuration_hal_return;
+    ASSERT_NE(gnss_configuration_hal, nullptr);
+
+    hidl_vec<IGnssConfiguration::BlacklistedSource> sources;
+    sources.resize(1);
+    sources[0] = source_to_blacklist;
+
+    auto result = gnss_configuration_hal->setBlacklist_2_1(sources);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+
+    // retry and ensure satellite not used
+    gnss_cb_->sv_info_list_cbq_.reset();
+
+    gnss_cb_->location_cbq_.reset();
+    StartAndCheckLocations(kLocationsToAwait);
+
+    // early exit if test is being run with insufficient signal
+    location_called_count = gnss_cb_->location_cbq_.calledCount();
+    if (location_called_count == 0) {
+        ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
+    }
+    ASSERT_TRUE(location_called_count > 0);
+
+    // Tolerate 1 less sv status to handle edge cases in reporting.
+    sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+    EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
+    ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
+          sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
+    for (int i = 0; i < sv_info_list_cbq_size; ++i) {
+        hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
+        gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
+        for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
+            const auto& gnss_sv = sv_info_vec[iSv];
+            EXPECT_FALSE((gnss_sv.v2_0.v1_0.svid == source_to_blacklist.svid) &&
+                         (gnss_sv.v2_0.constellation == source_to_blacklist.constellation) &&
+                         (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
+        }
+    }
+
+    // clear blacklist and restart - this time updating the blacklist while location is still on
+    sources.resize(0);
+
+    result = gnss_configuration_hal->setBlacklist_2_1(sources);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+
+    bool strongest_sv_is_reobserved = false;
+    // do several loops awaiting a few locations, allowing non-immediate reacquisition strategies
+    int unblacklist_loops_remaining = kRetriesToUnBlacklist;
+    while (!strongest_sv_is_reobserved && (unblacklist_loops_remaining-- > 0)) {
+        StopAndClearLocations();
+        gnss_cb_->sv_info_list_cbq_.reset();
+
+        gnss_cb_->location_cbq_.reset();
+        StartAndCheckLocations(kLocationsToAwait);
+
+        // early exit loop if test is being run with insufficient signal
+        location_called_count = gnss_cb_->location_cbq_.calledCount();
+        if (location_called_count == 0) {
+            ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
+        }
+        ASSERT_TRUE(location_called_count > 0);
+
+        // Tolerate 1 less sv status to handle edge cases in reporting.
+        sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+        EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
+        ALOGD("Clear blacklist, observed %d GnssSvInfo, while awaiting %d Locations"
+              ", tries remaining %d",
+              sv_info_list_cbq_size, kLocationsToAwait, unblacklist_loops_remaining);
+
+        for (int i = 0; i < sv_info_list_cbq_size; ++i) {
+            hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
+            gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
+            for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
+                const auto& gnss_sv = sv_info_vec[iSv];
+                if ((gnss_sv.v2_0.v1_0.svid == source_to_blacklist.svid) &&
+                    (gnss_sv.v2_0.constellation == source_to_blacklist.constellation) &&
+                    (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)) {
+                    strongest_sv_is_reobserved = true;
+                    break;
+                }
+            }
+            if (strongest_sv_is_reobserved) break;
+        }
+    }
+    EXPECT_TRUE(strongest_sv_is_reobserved);
+    StopAndClearLocations();
+}
+
+/*
+ * BlacklistConstellation:
+ *
+ * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
+ * GnssStatus for any non-GPS constellations.
+ * 2a & b) Turns off location, and blacklist first non-GPS constellations.
+ * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
+ * GnssStatus does not use any constellation but GPS.
+ * 4a & b) Clean up by turning off location, and send in empty blacklist.
+ */
+TEST_P(GnssHalTest, BlacklistConstellation) {
+    const int kLocationsToAwait = 3;
+
+    gnss_cb_->location_cbq_.reset();
+    StartAndCheckLocations(kLocationsToAwait);
+    const int location_called_count = gnss_cb_->location_cbq_.calledCount();
+
+    // Tolerate 1 less sv status to handle edge cases in reporting.
+    int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+    EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
+    ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
+          sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
+
+    // Find first non-GPS constellation to blacklist
+    const int kGnssSvInfoListTimeout = 2;
+    GnssConstellationType constellation_to_blacklist = GnssConstellationType::UNKNOWN;
+    for (int i = 0; i < sv_info_list_cbq_size; ++i) {
+        hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
+        gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
+        for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
+            const auto& gnss_sv = sv_info_vec[iSv];
+            if ((gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX) &&
+                (gnss_sv.v2_0.constellation != GnssConstellationType::UNKNOWN) &&
+                (gnss_sv.v2_0.constellation != GnssConstellationType::GPS)) {
+                // found a non-GPS constellation
+                constellation_to_blacklist = gnss_sv.v2_0.constellation;
+                break;
+            }
+        }
+        if (constellation_to_blacklist != GnssConstellationType::UNKNOWN) {
+            break;
+        }
+    }
+
+    // Turns off location
+    StopAndClearLocations();
+
+    if (constellation_to_blacklist == GnssConstellationType::UNKNOWN) {
+        ALOGI("No non-GPS constellations found, constellation blacklist test less effective.");
+        // Proceed functionally to blacklist something.
+        constellation_to_blacklist = GnssConstellationType::GLONASS;
+    }
+    IGnssConfiguration::BlacklistedSource source_to_blacklist_1;
+    source_to_blacklist_1.constellation = constellation_to_blacklist;
+    source_to_blacklist_1.svid = 0;  // documented wildcard for all satellites in this constellation
+
+    // IRNSS was added in 2.0. Always attempt to blacklist IRNSS to verify that the new enum is
+    // supported.
+    IGnssConfiguration::BlacklistedSource source_to_blacklist_2;
+    source_to_blacklist_2.constellation = GnssConstellationType::IRNSS;
+    source_to_blacklist_2.svid = 0;  // documented wildcard for all satellites in this constellation
+
+    auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_2_1();
+    ASSERT_TRUE(gnss_configuration_hal_return.isOk());
+    sp<IGnssConfiguration> gnss_configuration_hal = gnss_configuration_hal_return;
+    ASSERT_NE(gnss_configuration_hal, nullptr);
+
+    hidl_vec<IGnssConfiguration::BlacklistedSource> sources;
+    sources.resize(2);
+    sources[0] = source_to_blacklist_1;
+    sources[1] = source_to_blacklist_2;
+
+    auto result = gnss_configuration_hal->setBlacklist_2_1(sources);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+
+    // retry and ensure constellation not used
+    gnss_cb_->sv_info_list_cbq_.reset();
+
+    gnss_cb_->location_cbq_.reset();
+    StartAndCheckLocations(kLocationsToAwait);
+
+    // Tolerate 1 less sv status to handle edge cases in reporting.
+    sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+    EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
+    ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations", sv_info_list_cbq_size,
+          kLocationsToAwait);
+    for (int i = 0; i < sv_info_list_cbq_size; ++i) {
+        hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
+        gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
+        for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
+            const auto& gnss_sv = sv_info_vec[iSv];
+            EXPECT_FALSE((gnss_sv.v2_0.constellation == source_to_blacklist_1.constellation) &&
+                         (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
+            EXPECT_FALSE((gnss_sv.v2_0.constellation == source_to_blacklist_2.constellation) &&
+                         (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
+        }
+    }
+
+    // clean up
+    StopAndClearLocations();
+    sources.resize(0);
+    result = gnss_configuration_hal->setBlacklist_2_1(sources);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+}
\ No newline at end of file
diff --git a/gnss/common/utils/default/Android.bp b/gnss/common/utils/default/Android.bp
index 4ea97fa..577f6ae 100644
--- a/gnss/common/utils/default/Android.bp
+++ b/gnss/common/utils/default/Android.bp
@@ -28,6 +28,10 @@
     ],
     export_include_dirs: ["include"],
     shared_libs: [
+        "libhidlbase",
+        "libutils",
         "android.hardware.gnss@1.0",
+        "android.hardware.gnss@2.0",
+        "android.hardware.gnss@2.1",
     ],
 }
diff --git a/gnss/common/utils/default/Utils.cpp b/gnss/common/utils/default/Utils.cpp
index b9a06e8..ccb91b1 100644
--- a/gnss/common/utils/default/Utils.cpp
+++ b/gnss/common/utils/default/Utils.cpp
@@ -16,6 +16,7 @@
 
 #include <Constants.h>
 #include <Utils.h>
+#include <utils/SystemClock.h>
 
 namespace android {
 namespace hardware {
@@ -23,31 +24,193 @@
 namespace common {
 
 using GnssSvFlags = V1_0::IGnssCallback::GnssSvFlags;
+using GnssMeasurementFlags = V1_0::IGnssMeasurementCallback::GnssMeasurementFlags;
+using GnssMeasurementStateV2_0 = V2_0::IGnssMeasurementCallback::GnssMeasurementState;
+using ElapsedRealtime = V2_0::ElapsedRealtime;
+using ElapsedRealtimeFlags = V2_0::ElapsedRealtimeFlags;
+using GnssConstellationTypeV2_0 = V2_0::GnssConstellationType;
+using IGnssMeasurementCallbackV2_0 = V2_0::IGnssMeasurementCallback;
 
-GnssLocation Utils::getMockLocation() {
-    GnssLocation location = {.gnssLocationFlags = 0xFF,
-                             .latitudeDegrees = kMockLatitudeDegrees,
-                             .longitudeDegrees = kMockLongitudeDegrees,
-                             .altitudeMeters = kMockAltitudeMeters,
-                             .speedMetersPerSec = kMockSpeedMetersPerSec,
-                             .bearingDegrees = kMockBearingDegrees,
-                             .horizontalAccuracyMeters = kMockHorizontalAccuracyMeters,
-                             .verticalAccuracyMeters = kMockVerticalAccuracyMeters,
-                             .speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond,
-                             .bearingAccuracyDegrees = kMockBearingAccuracyDegrees,
-                             .timestamp = kMockTimestamp};
+GnssDataV2_1 Utils::getMockMeasurementV2_1() {
+    GnssDataV2_0 gnssDataV2_0 = Utils::getMockMeasurementV2_0();
+    V2_1::IGnssMeasurementCallback::GnssMeasurement gnssMeasurementV2_1 = {
+            .v2_0 = gnssDataV2_0.measurements[0],
+            .basebandCN0DbHz = 25.0,
+    };
+    hidl_vec<V2_1::IGnssMeasurementCallback::GnssMeasurement> measurements(1);
+    measurements[0] = gnssMeasurementV2_1;
+    GnssDataV2_1 gnssDataV2_1 = {
+            .measurements = measurements,
+            .clock = gnssDataV2_0.clock,
+            .elapsedRealtime = gnssDataV2_0.elapsedRealtime,
+    };
+    return gnssDataV2_1;
+}
+
+GnssDataV2_0 Utils::getMockMeasurementV2_0() {
+    V1_0::IGnssMeasurementCallback::GnssMeasurement measurement_1_0 = {
+            .flags = (uint32_t)GnssMeasurementFlags::HAS_CARRIER_FREQUENCY,
+            .svid = (int16_t)6,
+            .constellation = V1_0::GnssConstellationType::UNKNOWN,
+            .timeOffsetNs = 0.0,
+            .receivedSvTimeInNs = 8195997131077,
+            .receivedSvTimeUncertaintyInNs = 15,
+            .cN0DbHz = 30.0,
+            .pseudorangeRateMps = -484.13739013671875,
+            .pseudorangeRateUncertaintyMps = 1.0379999876022339,
+            .accumulatedDeltaRangeState = (uint32_t)V1_0::IGnssMeasurementCallback::
+                    GnssAccumulatedDeltaRangeState::ADR_STATE_UNKNOWN,
+            .accumulatedDeltaRangeM = 0.0,
+            .accumulatedDeltaRangeUncertaintyM = 0.0,
+            .carrierFrequencyHz = 1.59975e+09,
+            .multipathIndicator =
+                    V1_0::IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN};
+    V1_1::IGnssMeasurementCallback::GnssMeasurement measurement_1_1 = {.v1_0 = measurement_1_0};
+    V2_0::IGnssMeasurementCallback::GnssMeasurement measurement_2_0 = {
+            .v1_1 = measurement_1_1,
+            .codeType = "C",
+            .state = GnssMeasurementStateV2_0::STATE_CODE_LOCK |
+                     GnssMeasurementStateV2_0::STATE_BIT_SYNC |
+                     GnssMeasurementStateV2_0::STATE_SUBFRAME_SYNC |
+                     GnssMeasurementStateV2_0::STATE_TOW_DECODED |
+                     GnssMeasurementStateV2_0::STATE_GLO_STRING_SYNC |
+                     GnssMeasurementStateV2_0::STATE_GLO_TOD_DECODED,
+            .constellation = GnssConstellationTypeV2_0::GLONASS,
+    };
+
+    hidl_vec<IGnssMeasurementCallbackV2_0::GnssMeasurement> measurements(1);
+    measurements[0] = measurement_2_0;
+    V1_0::IGnssMeasurementCallback::GnssClock clock = {.timeNs = 2713545000000,
+                                                       .fullBiasNs = -1226701900521857520,
+                                                       .biasNs = 0.59689998626708984,
+                                                       .biasUncertaintyNs = 47514.989972114563,
+                                                       .driftNsps = -51.757811607455452,
+                                                       .driftUncertaintyNsps = 310.64968328491528,
+                                                       .hwClockDiscontinuityCount = 1};
+
+    ElapsedRealtime timestamp = {
+            .flags = ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
+                     ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS,
+            .timestampNs = static_cast<uint64_t>(::android::elapsedRealtimeNano()),
+            // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks.
+            // In an actual implementation provide an estimate of the synchronization uncertainty
+            // or don't set the field.
+            .timeUncertaintyNs = 1000000};
+
+    GnssDataV2_0 gnssData = {
+            .measurements = measurements, .clock = clock, .elapsedRealtime = timestamp};
+    return gnssData;
+}
+
+V2_0::GnssLocation Utils::getMockLocationV2_0() {
+    const V2_0::ElapsedRealtime timestamp = {
+            .flags = V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
+                     V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS,
+            .timestampNs = static_cast<uint64_t>(::android::elapsedRealtimeNano()),
+            // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks.
+            // In an actual implementation provide an estimate of the synchronization uncertainty
+            // or don't set the field.
+            .timeUncertaintyNs = 1000000};
+
+    V2_0::GnssLocation location = {.v1_0 = Utils::getMockLocationV1_0(),
+                                   .elapsedRealtime = timestamp};
     return location;
 }
 
-GnssSvInfo Utils::getSvInfo(int16_t svid, GnssConstellationType type, float cN0DbHz,
-                            float elevationDegrees, float azimuthDegrees) {
-    GnssSvInfo svInfo = {.svid = svid,
-                         .constellation = type,
-                         .cN0Dbhz = cN0DbHz,
-                         .elevationDegrees = elevationDegrees,
-                         .azimuthDegrees = azimuthDegrees,
-                         .svFlag = GnssSvFlags::USED_IN_FIX | GnssSvFlags::HAS_EPHEMERIS_DATA |
-                                   GnssSvFlags::HAS_ALMANAC_DATA};
+V1_0::GnssLocation Utils::getMockLocationV1_0() {
+    V1_0::GnssLocation location = {
+            .gnssLocationFlags = 0xFF,
+            .latitudeDegrees = kMockLatitudeDegrees,
+            .longitudeDegrees = kMockLongitudeDegrees,
+            .altitudeMeters = kMockAltitudeMeters,
+            .speedMetersPerSec = kMockSpeedMetersPerSec,
+            .bearingDegrees = kMockBearingDegrees,
+            .horizontalAccuracyMeters = kMockHorizontalAccuracyMeters,
+            .verticalAccuracyMeters = kMockVerticalAccuracyMeters,
+            .speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond,
+            .bearingAccuracyDegrees = kMockBearingAccuracyDegrees,
+            .timestamp = kMockTimestamp};
+    return location;
+}
+
+hidl_vec<GnssSvInfoV2_1> Utils::getMockSvInfoListV2_1() {
+    GnssSvInfoV1_0 gnssSvInfoV1_0 =
+            Utils::getMockSvInfoV1_0(3, V1_0::GnssConstellationType::GPS, 32.5, 59.1, 166.5);
+    GnssSvInfoV2_0 gnssSvInfoV2_0 =
+            Utils::getMockSvInfoV2_0(gnssSvInfoV1_0, V2_0::GnssConstellationType::GPS);
+    hidl_vec<GnssSvInfoV2_1> gnssSvInfoList = {
+            Utils::getMockSvInfoV2_1(gnssSvInfoV2_0, 27.5),
+            getMockSvInfoV2_1(
+                    getMockSvInfoV2_0(getMockSvInfoV1_0(5, V1_0::GnssConstellationType::GPS, 27.0,
+                                                        29.0, 56.5),
+                                      V2_0::GnssConstellationType::GPS),
+                    22.0),
+            getMockSvInfoV2_1(
+                    getMockSvInfoV2_0(getMockSvInfoV1_0(17, V1_0::GnssConstellationType::GPS, 30.5,
+                                                        71.0, 77.0),
+                                      V2_0::GnssConstellationType::GPS),
+                    25.5),
+            getMockSvInfoV2_1(
+                    getMockSvInfoV2_0(getMockSvInfoV1_0(26, V1_0::GnssConstellationType::GPS, 24.1,
+                                                        28.0, 253.0),
+                                      V2_0::GnssConstellationType::GPS),
+                    19.1),
+            getMockSvInfoV2_1(
+                    getMockSvInfoV2_0(getMockSvInfoV1_0(5, V1_0::GnssConstellationType::GLONASS,
+                                                        20.5, 11.5, 116.0),
+                                      V2_0::GnssConstellationType::GLONASS),
+                    15.5),
+            getMockSvInfoV2_1(
+                    getMockSvInfoV2_0(getMockSvInfoV1_0(17, V1_0::GnssConstellationType::GLONASS,
+                                                        21.5, 28.5, 186.0),
+                                      V2_0::GnssConstellationType::GLONASS),
+                    16.5),
+            getMockSvInfoV2_1(
+                    getMockSvInfoV2_0(getMockSvInfoV1_0(18, V1_0::GnssConstellationType::GLONASS,
+                                                        28.3, 38.8, 69.0),
+                                      V2_0::GnssConstellationType::GLONASS),
+                    25.3),
+            getMockSvInfoV2_1(
+                    getMockSvInfoV2_0(getMockSvInfoV1_0(10, V1_0::GnssConstellationType::GLONASS,
+                                                        25.0, 66.0, 247.0),
+                                      V2_0::GnssConstellationType::GLONASS),
+                    20.0),
+            getMockSvInfoV2_1(
+                    getMockSvInfoV2_0(getMockSvInfoV1_0(3, V1_0::GnssConstellationType::UNKNOWN,
+                                                        22.0, 35.0, 112.0),
+                                      V2_0::GnssConstellationType::IRNSS),
+                    19.7),
+    };
+    return gnssSvInfoList;
+}
+
+GnssSvInfoV2_1 Utils::getMockSvInfoV2_1(GnssSvInfoV2_0 gnssSvInfoV2_0, float basebandCN0DbHz) {
+    GnssSvInfoV2_1 gnssSvInfoV2_1 = {
+            .v2_0 = gnssSvInfoV2_0,
+            .basebandCN0DbHz = basebandCN0DbHz,
+    };
+    return gnssSvInfoV2_1;
+}
+
+GnssSvInfoV2_0 Utils::getMockSvInfoV2_0(GnssSvInfoV1_0 gnssSvInfoV1_0,
+                                        V2_0::GnssConstellationType type) {
+    GnssSvInfoV2_0 gnssSvInfoV2_0 = {
+            .v1_0 = gnssSvInfoV1_0,
+            .constellation = type,
+    };
+    return gnssSvInfoV2_0;
+}
+
+GnssSvInfoV1_0 Utils::getMockSvInfoV1_0(int16_t svid, V1_0::GnssConstellationType type,
+                                        float cN0DbHz, float elevationDegrees,
+                                        float azimuthDegrees) {
+    GnssSvInfoV1_0 svInfo = {.svid = svid,
+                             .constellation = type,
+                             .cN0Dbhz = cN0DbHz,
+                             .elevationDegrees = elevationDegrees,
+                             .azimuthDegrees = azimuthDegrees,
+                             .svFlag = GnssSvFlags::USED_IN_FIX | GnssSvFlags::HAS_EPHEMERIS_DATA |
+                                       GnssSvFlags::HAS_ALMANAC_DATA};
     return svInfo;
 }
 
diff --git a/gnss/common/utils/default/include/Utils.h b/gnss/common/utils/default/include/Utils.h
index 47c8812..e0c61a4 100644
--- a/gnss/common/utils/default/include/Utils.h
+++ b/gnss/common/utils/default/include/Utils.h
@@ -18,20 +18,34 @@
 #define android_hardware_gnss_common_default_Utils_H_
 
 #include <android/hardware/gnss/1.0/IGnss.h>
+#include <android/hardware/gnss/2.0/IGnss.h>
+#include <android/hardware/gnss/2.1/IGnss.h>
 
-using GnssConstellationType = ::android::hardware::gnss::V1_0::GnssConstellationType;
-using GnssLocation = ::android::hardware::gnss::V1_0::GnssLocation;
-using GnssSvInfo = ::android::hardware::gnss::V1_0::IGnssCallback::GnssSvInfo;
+using ::android::hardware::hidl_vec;
 
 namespace android {
 namespace hardware {
 namespace gnss {
 namespace common {
 
+using GnssDataV2_0 = V2_0::IGnssMeasurementCallback::GnssData;
+using GnssDataV2_1 = V2_1::IGnssMeasurementCallback::GnssData;
+using GnssSvInfoV1_0 = V1_0::IGnssCallback::GnssSvInfo;
+using GnssSvInfoV2_0 = V2_0::IGnssCallback::GnssSvInfo;
+using GnssSvInfoV2_1 = V2_1::IGnssCallback::GnssSvInfo;
+
 struct Utils {
-    static GnssLocation getMockLocation();
-    static GnssSvInfo getSvInfo(int16_t svid, GnssConstellationType type, float cN0DbHz,
-                                float elevationDegrees, float azimuthDegrees);
+    static GnssDataV2_0 getMockMeasurementV2_0();
+    static GnssDataV2_1 getMockMeasurementV2_1();
+    static V2_0::GnssLocation getMockLocationV2_0();
+    static V1_0::GnssLocation getMockLocationV1_0();
+    static hidl_vec<GnssSvInfoV2_1> getMockSvInfoListV2_1();
+    static GnssSvInfoV2_1 getMockSvInfoV2_1(GnssSvInfoV2_0 gnssSvInfoV2_0, float basebandCN0DbHz);
+    static GnssSvInfoV2_0 getMockSvInfoV2_0(GnssSvInfoV1_0 gnssSvInfoV1_0,
+                                            V2_0::GnssConstellationType type);
+    static GnssSvInfoV1_0 getMockSvInfoV1_0(int16_t svid, V1_0::GnssConstellationType type,
+                                            float cN0DbHz, float elevationDegrees,
+                                            float azimuthDegrees);
 };
 
 }  // namespace common
diff --git a/graphics/common/aidl/Android.bp b/graphics/common/aidl/Android.bp
new file mode 100644
index 0000000..e0c7674
--- /dev/null
+++ b/graphics/common/aidl/Android.bp
@@ -0,0 +1,21 @@
+aidl_interface {
+    name: "vintf-graphics-common",
+    host_supported: true,
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
+    srcs: [
+        "android/hardware/graphics/common/*.aidl",
+    ],
+    stability: "vintf",
+    backend: {
+        java: {
+            enabled: false,
+        },
+        cpp: {
+            enabled: false,
+        },
+    },
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/BlendMode.aidl b/graphics/common/aidl/android/hardware/graphics/common/BlendMode.aidl
new file mode 100644
index 0000000..2428135
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/BlendMode.aidl
@@ -0,0 +1,35 @@
+/**
+ * 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.
+ */
+
+package android.hardware.graphics.common;
+
+/**
+ * Blend modes, settable per layer.
+ */
+@VintfStability
+@Backing(type="int")
+enum BlendMode {
+    INVALID = 0,
+
+    /** colorOut = colorSrc */
+    NONE = 1,
+
+    /** colorOut = colorSrc + colorDst * (1 - alphaSrc) */
+    PREMULTIPLIED = 2,
+
+    /** colorOut = colorSrc * alphaSrc + colorDst * (1 - alphaSrc) */
+    COVERAGE = 3,
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/ChromaSiting.aidl b/graphics/common/aidl/android/hardware/graphics/common/ChromaSiting.aidl
new file mode 100644
index 0000000..562a664
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/ChromaSiting.aidl
@@ -0,0 +1,39 @@
+/**
+ * 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.
+ */
+
+package android.hardware.graphics.common;
+
+/**
+ * Used by IAllocator/IMapper (gralloc) to describe standard chroma siting
+ */
+@VintfStability
+@Backing(type="long")
+enum ChromaSiting {
+    /* This format does not have chroma siting. */
+    NONE = 0,
+
+    /* This format has chroma siting but the type being used is unknown. */
+    UNKNOWN = 1,
+
+    /* Cb and Cr are sited interstitially, halfway between alternate luma samples.
+     * This is used by 4:2:0 for JPEG/JFIF, H.261, MPEG-1. */
+    SITED_INTERSTITIAL = 2,
+
+    /* Cb and Cr are horizontally sited coincident with a luma sample.
+     * Cb and Cr are vertically sited interstitially.
+     * This is used by 4:2:0 for MPEG-2 frame pictures. */
+    COSITED_HORIZONTAL = 3,
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/Compression.aidl b/graphics/common/aidl/android/hardware/graphics/common/Compression.aidl
new file mode 100644
index 0000000..4cca1ba
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/Compression.aidl
@@ -0,0 +1,30 @@
+/**
+ * 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.
+ */
+
+package android.hardware.graphics.common;
+
+/**
+ * Used by IAllocator/IMapper (gralloc) to describe standard compression strategies
+ */
+@VintfStability
+@Backing(type="long")
+enum Compression {
+    /* Represents all uncompressed buffers */
+    NONE = 0,
+
+    /* VESA Display Stream Compression (DSC) */
+    DISPLAY_STREAM_COMPRESSION = 1,
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl b/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl
new file mode 100644
index 0000000..81a21ab
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl
@@ -0,0 +1,682 @@
+/**
+ * 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.
+ */
+
+package android.hardware.graphics.common;
+
+@VintfStability
+@Backing(type="int")
+enum Dataspace {
+    /**
+     * Default-assumption data space, when not explicitly specified.
+     *
+     * It is safest to assume the buffer is an image with sRGB primaries and
+     * encoding ranges, but the consumer and/or the producer of the data may
+     * simply be using defaults. No automatic gamma transform should be
+     * expected, except for a possible display gamma transform when drawn to a
+     * screen.
+     */
+    UNKNOWN = 0x0,
+
+    /**
+     * Arbitrary dataspace with manually defined characteristics.  Definition
+     * for colorspaces or other meaning must be communicated separately.
+     *
+     * This is used when specifying primaries, transfer characteristics,
+     * etc. separately.
+     *
+     * A typical use case is in video encoding parameters (e.g. for H.264),
+     * where a colorspace can have separately defined primaries, transfer
+     * characteristics, etc.
+     */
+    ARBITRARY = 0x1,
+
+    /**
+     * Color-description aspects
+     *
+     * The following aspects define various characteristics of the color
+     * specification. These represent bitfields, so that a data space value
+     * can specify each of them independently.
+     */
+
+    STANDARD_SHIFT = 16,
+
+    /**
+     * Standard aspect
+     *
+     * Defines the chromaticity coordinates of the source primaries in terms of
+     * the CIE 1931 definition of x and y specified in ISO 11664-1.
+     */
+    STANDARD_MASK = 63 << 16, // 63 << STANDARD_SHIFT = 0x3F
+
+    /**
+     * Chromacity coordinates are unknown or are determined by the application.
+     * Implementations shall use the following suggested standards:
+     *
+     * All YCbCr formats: BT709 if size is 720p or larger (since most video
+     *                    content is letterboxed this corresponds to width is
+     *                    1280 or greater, or height is 720 or greater).
+     *                    BT601_625 if size is smaller than 720p or is JPEG.
+     * All RGB formats:   BT709.
+     *
+     * For all other formats standard is undefined, and implementations should use
+     * an appropriate standard for the data represented.
+     */
+    STANDARD_UNSPECIFIED = 0 << 16, // STANDARD_SHIFT
+
+    /**
+     * Primaries:       x       y
+     *  green           0.300   0.600
+     *  blue            0.150   0.060
+     *  red             0.640   0.330
+     *  white (D65)     0.3127  0.3290
+     *
+     * Use the unadjusted KR = 0.2126, KB = 0.0722 luminance interpretation
+     * for RGB conversion.
+     */
+    STANDARD_BT709 = 1 << 16,  // 1 << STANDARD_SHIFT
+
+    /**
+     * Primaries:       x       y
+     *  green           0.290   0.600
+     *  blue            0.150   0.060
+     *  red             0.640   0.330
+     *  white (D65)     0.3127  0.3290
+     *
+     *  KR = 0.299, KB = 0.114. This adjusts the luminance interpretation
+     *  for RGB conversion from the one purely determined by the primaries
+     *  to minimize the color shift into RGB space that uses BT.709
+     *  primaries.
+     */
+    STANDARD_BT601_625 = 2 << 16, // 2 << STANDARD_SHIFT,
+
+    /**
+     * Primaries:       x       y
+     *  green           0.290   0.600
+     *  blue            0.150   0.060
+     *  red             0.640   0.330
+     *  white (D65)     0.3127  0.3290
+     *
+     * Use the unadjusted KR = 0.222, KB = 0.071 luminance interpretation
+     * for RGB conversion.
+     */
+    STANDARD_BT601_625_UNADJUSTED = 3 << 16, // 3 << STANDARD_SHIFT
+
+    /**
+     * Primaries:       x       y
+     *  green           0.310   0.595
+     *  blue            0.155   0.070
+     *  red             0.630   0.340
+     *  white (D65)     0.3127  0.3290
+     *
+     *  KR = 0.299, KB = 0.114. This adjusts the luminance interpretation
+     *  for RGB conversion from the one purely determined by the primaries
+     *  to minimize the color shift into RGB space that uses BT.709
+     *  primaries.
+     */
+    STANDARD_BT601_525 = 4 << 16, // 4 << STANDARD_SHIFT
+
+    /**
+     * Primaries:       x       y
+     *  green           0.310   0.595
+     *  blue            0.155   0.070
+     *  red             0.630   0.340
+     *  white (D65)     0.3127  0.3290
+     *
+     * Use the unadjusted KR = 0.212, KB = 0.087 luminance interpretation
+     * for RGB conversion (as in SMPTE 240M).
+     */
+    STANDARD_BT601_525_UNADJUSTED = 5 << 16, // 5 << STANDARD_SHIFT
+
+    /**
+     * Primaries:       x       y
+     *  green           0.170   0.797
+     *  blue            0.131   0.046
+     *  red             0.708   0.292
+     *  white (D65)     0.3127  0.3290
+     *
+     * Use the unadjusted KR = 0.2627, KB = 0.0593 luminance interpretation
+     * for RGB conversion.
+     */
+    STANDARD_BT2020 = 6 << 16, // 6 << STANDARD_SHIFT
+
+    /**
+     * Primaries:       x       y
+     *  green           0.170   0.797
+     *  blue            0.131   0.046
+     *  red             0.708   0.292
+     *  white (D65)     0.3127  0.3290
+     *
+     * Use the unadjusted KR = 0.2627, KB = 0.0593 luminance interpretation
+     * for RGB conversion using the linear domain.
+     */
+    STANDARD_BT2020_CONSTANT_LUMINANCE = 7 << 16, // 7 << STANDARD_SHIFT
+
+    /**
+     * Primaries:       x      y
+     *  green           0.21   0.71
+     *  blue            0.14   0.08
+     *  red             0.67   0.33
+     *  white (C)       0.310  0.316
+     *
+     * Use the unadjusted KR = 0.30, KB = 0.11 luminance interpretation
+     * for RGB conversion.
+     */
+    STANDARD_BT470M = 8 << 16, // 8 << STANDARD_SHIFT
+
+    /**
+     * Primaries:       x       y
+     *  green           0.243   0.692
+     *  blue            0.145   0.049
+     *  red             0.681   0.319
+     *  white (C)       0.310   0.316
+     *
+     * Use the unadjusted KR = 0.254, KB = 0.068 luminance interpretation
+     * for RGB conversion.
+     */
+    STANDARD_FILM = 9 << 16, // 9 << STANDARD_SHIFT
+
+    /**
+     * SMPTE EG 432-1 and SMPTE RP 431-2. (DCI-P3)
+     * Primaries:       x       y
+     *  green           0.265   0.690
+     *  blue            0.150   0.060
+     *  red             0.680   0.320
+     *  white (D65)     0.3127  0.3290
+     */
+    STANDARD_DCI_P3 = 10 << 16, // 10 << STANDARD_SHIFT
+
+    /**
+     * Adobe RGB
+     * Primaries:       x       y
+     *  green           0.210   0.710
+     *  blue            0.150   0.060
+     *  red             0.640   0.330
+     *  white (D65)     0.3127  0.3290
+     */
+    STANDARD_ADOBE_RGB = 11 << 16, // 11 << STANDARD_SHIFT
+
+
+
+    TRANSFER_SHIFT = 22,
+
+    /**
+     * Transfer aspect
+     *
+     * Transfer characteristics are the opto-electronic transfer characteristic
+     * at the source as a function of linear optical intensity (luminance).
+     *
+     * For digital signals, E corresponds to the recorded value. Normally, the
+     * transfer function is applied in RGB space to each of the R, G and B
+     * components independently. This may result in color shift that can be
+     * minized by applying the transfer function in Lab space only for the L
+     * component. Implementation may apply the transfer function in RGB space
+     * for all pixel formats if desired.
+     */
+
+    TRANSFER_MASK = 31 << 22, // 31 << TRANSFER_SHIFT = 0x1F
+
+    /**
+     * Transfer characteristics are unknown or are determined by the
+     * application.
+     *
+     * Implementations should use the following transfer functions:
+     *
+     * For YCbCr formats: use TRANSFER_SMPTE_170M
+     * For RGB formats: use TRANSFER_SRGB
+     *
+     * For all other formats transfer function is undefined, and implementations
+     * should use an appropriate standard for the data represented.
+     */
+    TRANSFER_UNSPECIFIED = 0 << 22, // 0 << TRANSFER_SHIFT
+
+    /**
+     * Transfer characteristic curve:
+     *  E = L
+     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
+     *      E - corresponding electrical signal
+     */
+    TRANSFER_LINEAR = 1 << 22, // 1 << TRANSFER_SHIFT
+
+    /**
+     * Transfer characteristic curve:
+     *
+     * E = 1.055 * L^(1/2.4) - 0.055  for 0.0031308 <= L <= 1
+     *   = 12.92 * L                  for 0 <= L < 0.0031308
+     *     L - luminance of image 0 <= L <= 1 for conventional colorimetry
+     *     E - corresponding electrical signal
+     */
+    TRANSFER_SRGB = 2 << 22, // 2 << TRANSFER_SHIFT
+
+    /**
+     * BT.601 525, BT.601 625, BT.709, BT.2020
+     *
+     * Transfer characteristic curve:
+     *  E = 1.099 * L ^ 0.45 - 0.099  for 0.018 <= L <= 1
+     *    = 4.500 * L                 for 0 <= L < 0.018
+     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
+     *      E - corresponding electrical signal
+     */
+    TRANSFER_SMPTE_170M = 3 << 22, // 3 << TRANSFER_SHIFT
+
+    /**
+     * Assumed display gamma 2.2.
+     *
+     * Transfer characteristic curve:
+     *  E = L ^ (1/2.2)
+     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
+     *      E - corresponding electrical signal
+     */
+    TRANSFER_GAMMA2_2 = 4 << 22, // 4 << TRANSFER_SHIFT
+
+    /**
+     *  display gamma 2.6.
+     *
+     * Transfer characteristic curve:
+     *  E = L ^ (1/2.6)
+     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
+     *      E - corresponding electrical signal
+     */
+    TRANSFER_GAMMA2_6 = 5 << 22, // 5 << TRANSFER_SHIFT
+
+    /**
+     *  display gamma 2.8.
+     *
+     * Transfer characteristic curve:
+     *  E = L ^ (1/2.8)
+     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
+     *      E - corresponding electrical signal
+     */
+    TRANSFER_GAMMA2_8 = 6 << 22, // 6 << TRANSFER_SHIFT
+
+    /**
+     * SMPTE ST 2084 (Dolby Perceptual Quantizer)
+     *
+     * Transfer characteristic curve:
+     *  E = ((c1 + c2 * L^n) / (1 + c3 * L^n)) ^ m
+     *  c1 = c3 - c2 + 1 = 3424 / 4096 = 0.8359375
+     *  c2 = 32 * 2413 / 4096 = 18.8515625
+     *  c3 = 32 * 2392 / 4096 = 18.6875
+     *  m = 128 * 2523 / 4096 = 78.84375
+     *  n = 0.25 * 2610 / 4096 = 0.1593017578125
+     *      L - luminance of image 0 <= L <= 1 for HDR colorimetry.
+     *          L = 1 corresponds to 10000 cd/m2
+     *      E - corresponding electrical signal
+     */
+    TRANSFER_ST2084 = 7 << 22, // 7 << TRANSFER_SHIFT
+
+    /**
+     * ARIB STD-B67 Hybrid Log Gamma
+     *
+     * Transfer characteristic curve:
+     *  E = r * L^0.5                 for 0 <= L <= 1
+     *    = a * ln(L - b) + c         for 1 < L
+     *  a = 0.17883277
+     *  b = 0.28466892
+     *  c = 0.55991073
+     *  r = 0.5
+     *      L - luminance of image 0 <= L for HDR colorimetry. L = 1 corresponds
+     *          to reference white level of 100 cd/m2
+     *      E - corresponding electrical signal
+     */
+    TRANSFER_HLG = 8 << 22, // 8 << TRANSFER_SHIFT
+
+    RANGE_SHIFT = 27,
+
+    /**
+     * Range aspect
+     *
+     * Defines the range of values corresponding to the unit range of 0-1.
+     * This is defined for YCbCr only, but can be expanded to RGB space.
+     */
+    RANGE_MASK = 7 << 27, // 7 << RANGE_SHIFT = 0x7
+
+    /**
+     * Range is unknown or are determined by the application.  Implementations
+     * shall use the following suggested ranges:
+     *
+     * All YCbCr formats: limited range.
+     * All RGB or RGBA formats (including RAW and Bayer): full range.
+     * All Y formats: full range
+     *
+     * For all other formats range is undefined, and implementations should use
+     * an appropriate range for the data represented.
+     */
+    RANGE_UNSPECIFIED = 0 << 27, // 0 << RANGE_SHIFT = 0x0
+
+    /**
+     * Full range uses all values for Y, Cb and Cr from
+     * 0 to 2^b-1, where b is the bit depth of the color format.
+     */
+    RANGE_FULL = 1 << 27, // 1 << RANGE_SHIFT = 0x8000000
+
+    /**
+     * Limited range uses values 16/256*2^b to 235/256*2^b for Y, and
+     * 1/16*2^b to 15/16*2^b for Cb, Cr, R, G and B, where b is the bit depth of
+     * the color format.
+     *
+     * E.g. For 8-bit-depth formats:
+     * Luma (Y) samples should range from 16 to 235, inclusive
+     * Chroma (Cb, Cr) samples should range from 16 to 240, inclusive
+     *
+     * For 10-bit-depth formats:
+     * Luma (Y) samples should range from 64 to 940, inclusive
+     * Chroma (Cb, Cr) samples should range from 64 to 960, inclusive
+     */
+    RANGE_LIMITED = 2 << 27, // 2 << RANGE_SHIFT = 0x10000000
+
+    /**
+     * Extended range is used for scRGB. Intended for use with
+     * floating point pixel formats. [0.0 - 1.0] is the standard
+     * sRGB space. Values outside the range 0.0 - 1.0 can encode
+     * color outside the sRGB gamut.
+     * Used to blend / merge multiple dataspaces on a single display.
+     */
+    RANGE_EXTENDED = 3 << 27, // 3 << RANGE_SHIFT = 0x18000000
+
+    /**
+     * sRGB linear encoding:
+     *
+     * The red, green, and blue components are stored in sRGB space, but
+     * are linear, not gamma-encoded.
+     * The RGB primaries and the white point are the same as BT.709.
+     *
+     * The values are encoded using the full range ([0,255] for 8-bit) for all
+     * components.
+     */
+    SRGB_LINEAR = 1 << 16 | 1 << 22 | 1 << 27, // deprecated, use V0_SRGB_LINEAR
+
+    V0_SRGB_LINEAR = 1 << 16 | 1 << 22 | 1 << 27, // STANDARD_BT709 | TRANSFER_LINEAR | RANGE_FULL
+
+
+    /**
+     * scRGB linear encoding:
+     *
+     * The red, green, and blue components are stored in extended sRGB space,
+     * but are linear, not gamma-encoded.
+     * The RGB primaries and the white point are the same as BT.709.
+     *
+     * The values are floating point.
+     * A pixel value of 1.0, 1.0, 1.0 corresponds to sRGB white (D65) at 80 nits.
+     * Values beyond the range [0.0 - 1.0] would correspond to other colors
+     * spaces and/or HDR content.
+     */
+    V0_SCRGB_LINEAR = 1 << 16 | 1 << 22 | 3 << 27, // STANDARD_BT709 | TRANSFER_LINEAR | RANGE_EXTENDED
+
+
+    /**
+     * sRGB gamma encoding:
+     *
+     * The red, green and blue components are stored in sRGB space, and
+     * converted to linear space when read, using the SRGB transfer function
+     * for each of the R, G and B components. When written, the inverse
+     * transformation is performed.
+     *
+     * The alpha component, if present, is always stored in linear space and
+     * is left unmodified when read or written.
+     *
+     * Use full range and BT.709 standard.
+     */
+    SRGB = 1 << 16 | 2 << 22 | 1 << 27, // deprecated, use V0_SRGB
+
+    V0_SRGB = 1 << 16 | 2 << 22 | 1 << 27, // STANDARD_BT709 | TRANSFER_SRGB | RANGE_FULL
+
+
+    /**
+     * scRGB:
+     *
+     * The red, green, and blue components are stored in extended sRGB space,
+     * but are linear, not gamma-encoded.
+     * The RGB primaries and the white point are the same as BT.709.
+     *
+     * The values are floating point.
+     * A pixel value of 1.0, 1.0, 1.0 corresponds to sRGB white (D65) at 80 nits.
+     * Values beyond the range [0.0 - 1.0] would correspond to other colors
+     * spaces and/or HDR content.
+     */
+    V0_SCRGB = 1 << 16 | 2 << 22 | 3 << 27, // STANDARD_BT709 | TRANSFER_SRGB | RANGE_EXTENDED
+
+    /**
+     * YCbCr Colorspaces
+     * -----------------
+     *
+     * Primaries are given using (x,y) coordinates in the CIE 1931 definition
+     * of x and y specified by ISO 11664-1.
+     *
+     * Transfer characteristics are the opto-electronic transfer characteristic
+     * at the source as a function of linear optical intensity (luminance).
+     */
+
+    /**
+     * JPEG File Interchange Format (JFIF)
+     *
+     * Same model as BT.601-625, but all values (Y, Cb, Cr) range from 0 to 255
+     *
+     * Use full range, BT.601 transfer and BT.601_625 standard.
+     */
+    JFIF = 2 << 16 | 3 << 22 | 1 << 27, // deprecated, use V0_JFIF
+
+    V0_JFIF = 2 << 16 | 3 << 22 | 1 << 27, // STANDARD_BT601_625 | TRANSFER_SMPTE_170M | RANGE_FULL
+
+    /**
+     * ITU-R Recommendation 601 (BT.601) - 625-line
+     *
+     * Standard-definition television, 625 Lines (PAL)
+     *
+     * Use limited range, BT.601 transfer and BT.601_625 standard.
+     */
+    BT601_625 = 2 << 16 | 3 << 22 | 2 << 27, // deprecated, use V0_BT601_625
+
+    V0_BT601_625 = 2 << 16 | 3 << 22 | 2 << 27, // STANDARD_BT601_625 | TRANSFER_SMPTE_170M | RANGE_LIMITED
+
+
+    /**
+     * ITU-R Recommendation 601 (BT.601) - 525-line
+     *
+     * Standard-definition television, 525 Lines (NTSC)
+     *
+     * Use limited range, BT.601 transfer and BT.601_525 standard.
+     */
+    BT601_525 = 4 << 16 | 3 << 22 | 2 << 27, // deprecated, use V0_BT601_525
+
+    V0_BT601_525 = 4 << 16 | 3 << 22 | 2 << 27, // STANDARD_BT601_525 | TRANSFER_SMPTE_170M | RANGE_LIMITED
+
+    /**
+     * ITU-R Recommendation 709 (BT.709)
+     *
+     * High-definition television
+     *
+     * Use limited range, BT.709 transfer and BT.709 standard.
+     */
+    BT709 = 1 << 16 | 3 << 22 | 2 << 27, // deprecated, use V0_BT709
+
+    V0_BT709 = 1 << 16 | 3 << 22 | 2 << 27, // STANDARD_BT709 | TRANSFER_SMPTE_170M | RANGE_LIMITED
+
+
+    /**
+     * SMPTE EG 432-1 and SMPTE RP 431-2.
+     *
+     * Digital Cinema DCI-P3
+     *
+     * Use full range, linear transfer and D65 DCI-P3 standard
+     */
+    DCI_P3_LINEAR = 10 << 16 | 1 << 22 | 1 << 27, // STANDARD_DCI_P3 | TRANSFER_LINEAR | RANGE_FULL
+
+
+    /**
+     * SMPTE EG 432-1 and SMPTE RP 431-2.
+     *
+     * Digital Cinema DCI-P3
+     *
+     * Use full range, gamma 2.6 transfer and D65 DCI-P3 standard
+     * Note: Application is responsible for gamma encoding the data as
+     * a 2.6 gamma encoding is not supported in HW.
+     */
+    DCI_P3 = 10 << 16 | 5 << 22 | 1 << 27, // STANDARD_DCI_P3 | TRANSFER_GAMMA2_6 | RANGE_FULL
+
+
+    /**
+     * Display P3
+     *
+     * Display P3 uses same primaries and white-point as DCI-P3
+     * linear transfer function makes this the same as DCI_P3_LINEAR.
+     */
+    DISPLAY_P3_LINEAR = 10 << 16 | 1 << 22 | 1 << 27, // STANDARD_DCI_P3 | TRANSFER_LINEAR | RANGE_FULL
+
+
+    /**
+     * Display P3
+     *
+     * Use same primaries and white-point as DCI-P3
+     * but sRGB transfer function.
+     */
+    DISPLAY_P3 = 10 << 16 | 2 << 22 | 1 << 27, // STANDARD_DCI_P3 | TRANSFER_SRGB | RANGE_FULL
+
+
+    /**
+     * Adobe RGB
+     *
+     * Use full range, gamma 2.2 transfer and Adobe RGB primaries
+     * Note: Application is responsible for gamma encoding the data as
+     * a 2.2 gamma encoding is not supported in HW.
+     */
+    ADOBE_RGB = 11 << 16 | 4 << 22 | 1 << 27, // STANDARD_ADOBE_RGB | TRANSFER_GAMMA2_2 | RANGE_FULL
+
+
+    /**
+     * ITU-R Recommendation 2020 (BT.2020)
+     *
+     * Ultra High-definition television
+     *
+     * Use full range, linear transfer and BT2020 standard
+     */
+    BT2020_LINEAR = 6 << 16 | 1 << 22 | 1 << 27, // STANDARD_BT2020 | TRANSFER_LINEAR | RANGE_FULL
+
+
+    /**
+     * ITU-R Recommendation 2020 (BT.2020)
+     *
+     * Ultra High-definition television
+     *
+     * Use full range, BT.709 transfer and BT2020 standard
+     */
+    BT2020 = 6 << 16 | 3 << 22 | 1 << 27, // STANDARD_BT2020 | TRANSFER_SMPTE_170M | RANGE_FULL
+
+    /**
+     * ITU-R Recommendation 2020 (BT.2020)
+     *
+     * Ultra High-definition television
+     *
+     * Use full range, SMPTE 2084 (PQ) transfer and BT2020 standard
+     */
+    BT2020_PQ = 6 << 16 | 7 << 22 | 1 << 27, // STANDARD_BT2020 | TRANSFER_ST2084 | RANGE_FULL
+
+
+    /**
+     * Data spaces for non-color formats
+     */
+
+    /**
+     * The buffer contains depth ranging measurements from a depth camera.
+     * This value is valid with formats:
+     *    HAL_PIXEL_FORMAT_Y16: 16-bit samples, consisting of a depth measurement
+     *       and an associated confidence value. The 3 MSBs of the sample make
+     *       up the confidence value, and the low 13 LSBs of the sample make up
+     *       the depth measurement.
+     *       For the confidence section, 0 means 100% confidence, 1 means 0%
+     *       confidence. The mapping to a linear float confidence value between
+     *       0.f and 1.f can be obtained with
+     *         float confidence = (((depthSample >> 13) - 1) & 0x7) / 7.0f;
+     *       The depth measurement can be extracted simply with
+     *         uint16_t range = (depthSample & 0x1FFF);
+     *    HAL_PIXEL_FORMAT_BLOB: A depth point cloud, as
+     *       a variable-length float (x,y,z, confidence) coordinate point list.
+     *       The point cloud will be represented with the android_depth_points
+     *       structure.
+     */
+    DEPTH = 0x1000,
+
+    /**
+     * The buffer contains sensor events from sensor direct report.
+     * This value is valid with formats:
+     *    HAL_PIXEL_FORMAT_BLOB: an array of sensor event structure that forms
+     *       a lock free queue. Format of sensor event structure is specified
+     *       in Sensors HAL.
+     */
+    SENSOR = 0x1001,
+
+    /**
+     * ITU-R Recommendation 2020 (BT.2020)
+     *
+     * Ultra High-definition television
+     *
+     * Use limited range, BT.709 transfer and BT2020 standard
+     */
+    BT2020_ITU = 6 << 16 | 3 << 22 | 2 << 27, // STANDARD_BT2020 | TRANSFER_SMPTE_170M | RANGE_LIMITED
+
+    /**
+     * ITU-R Recommendation 2100 (BT.2100)
+     *
+     * High dynamic range television
+     *
+     * Use limited/full range, PQ/HLG transfer, and BT2020 standard
+     * limited range is the preferred / normative definition for BT.2100
+     */
+    BT2020_ITU_PQ = 6 << 16 | 7 << 22 | 2 << 27, // STANDARD_BT2020 | TRANSFER_ST2084 | RANGE_LIMITED
+    BT2020_ITU_HLG = 6 << 16 | 8 << 22 | 2 << 27, // STANDARD_BT2020 | TRANSFER_HLG | RANGE_LIMITED
+    BT2020_HLG = 6 << 16 | 8 << 22 | 1 << 27, // STANDARD_BT2020 | TRANSFER_HLG | RANGE_FULL
+
+    /**
+     * ITU-R Recommendation 2020 (BT.2020)
+     *
+     * Ultra High-definition television
+     *
+     * Use full range, sRGB transfer and BT2020 standard
+     */
+    DISPLAY_BT2020 = 6 << 16 | 2 << 22 | 1 << 27, // STANDARD_BT2020 | TRANSFER_SRGB | RANGE_FULL
+
+    /**
+     * ISO 16684-1:2011(E)
+     *
+     * Embedded depth metadata following the dynamic depth specification.
+     */
+    DYNAMIC_DEPTH = 0x1002,
+
+    /**
+     * JPEG APP segments format as specified by JEIDA spec
+     *
+     * The buffer must only contain APP1 (Application Marker) segment followed
+     * by zero or more APPn segments, as is specified by JEITA CP-3451C section 4.5.4.
+     * The APP1 segment optionally contains a thumbnail. The buffer will not
+     * contain main compressed image.
+     *
+     * This value is valid with formats:
+     *    HAL_PIXEL_FORMAT_BLOB: JPEG APP segments optionally containing thumbnail image
+     * in APP1. BLOB buffer with this dataspace is output by HAL, and used by
+     * camera framework to encode into a HEIC image.
+     */
+    JPEG_APP_SEGMENTS = 0x1003,
+
+    /**
+     * ISO/IEC 23008-12
+     *
+     * High Efficiency Image File Format (HEIF)
+     *
+     * This value is valid with formats:
+     *    HAL_PIXEL_FORMAT_BLOB: A HEIC image encoded by HEIC or HEVC encoder
+     * according to ISO/IEC 23008-12.
+     */
+    HEIF = 0x1004,
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/ExtendableType.aidl b/graphics/common/aidl/android/hardware/graphics/common/ExtendableType.aidl
new file mode 100644
index 0000000..495693c
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/ExtendableType.aidl
@@ -0,0 +1,52 @@
+/**
+ * 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.
+ */
+
+package android.hardware.graphics.common;
+
+/**
+ * This struct is used for types that are commonly extended by vendors. For example, buffer
+ * compression is typically SoC specific. It is not possible for Android to define every possible
+ * proprietary vendor compression strategy. Instead, compression is represented using this
+ * ExtendableType that can support standard compression strategies while still allowing
+ * every vendor to easily add their own non-standard definitions.
+ */
+@VintfStability
+parcelable ExtendableType {
+    /**
+     * Name of the stable aidl interface whose value is stored in this structure.
+     *
+     * For standard types, the "name" field will be set to the stable aidl name of the type such as
+     * "android.hardware.graphics.common.Compression".
+     *
+     * For custom vendor types, the "name" field will be set to the name of the custom
+     * @VendorStability vendor AIDL interface such as
+     * "vendor.mycompanyname.graphics.common.Compression". The name of the vendor extension should
+     * contain the name of the owner of the extension. Including the company
+     * name in the "name" field prevents type collisions between different vendors.
+     */
+    @utf8InCpp String name;
+
+    /**
+     * Enum value of the from the stable aidl interface
+     *
+     * For standard types, the "value" field will be set to an enum value from that stable aidl
+     * type such as "NONE".
+     *
+     * For vendor types, the "value" field should be set to the enum value from the custom
+     * @VendorStability vendor AIDL interface extended type such as "MY_COMPRESSION_TYPE1".
+     */
+    long value = 0;
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/Interlaced.aidl b/graphics/common/aidl/android/hardware/graphics/common/Interlaced.aidl
new file mode 100644
index 0000000..a3f1baa
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/Interlaced.aidl
@@ -0,0 +1,35 @@
+/**
+ * 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.
+ */
+
+package android.hardware.graphics.common;
+
+/**
+ * Used by IAllocator/IMapper (gralloc) to describe standard interlaced strategies
+ */
+@VintfStability
+@Backing(type="long")
+enum Interlaced {
+    /* The buffer is not interlaced. */
+    NONE = 0,
+
+    /* The buffer's planes are interlaced horizontally. The height of each interlaced plane is
+     * 1/2 the height of the buffer's height. */
+    TOP_BOTTOM = 1,
+
+    /* The buffer's planes are interlaced vertically. The width of each interlaced plane is
+     * 1/2 the width of the buffer's width. */
+    RIGHT_LEFT = 2,
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/PlaneLayout.aidl b/graphics/common/aidl/android/hardware/graphics/common/PlaneLayout.aidl
new file mode 100644
index 0000000..168028d
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/PlaneLayout.aidl
@@ -0,0 +1,125 @@
+/**
+ * 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.
+ */
+
+package android.hardware.graphics.common;
+
+import android.hardware.graphics.common.PlaneLayoutComponent;
+import android.hardware.graphics.common.Rect;
+
+/**
+ * Used by IAllocator/IMapper (gralloc) to describe the plane layout of a buffer.
+ *
+ * PlaneLayout uses the following definitions:
+ *
+ * - Component - a component is one channel of a pixel. For example, an RGBA format has
+ *      four components: R, G, B and A.
+ * - Sample - a sample is comprised of all the components in a given plane. For example,
+ *      a buffer with one Y plane and one CbCr plane has one plane with a sample of Y
+ *      and one plane with a sample of CbCr.
+ * - Pixel - a pixel is comprised of all the (non-metadata/raw) components in buffer across
+ *      all planes. For example, a buffer with a plane of Y and a plane of CbCr has a pixel
+ *      of YCbCr.
+ */
+
+@VintfStability
+parcelable PlaneLayout {
+    /**
+     * An list of plane layout components. This list of components should include
+     * every component in this plane. For example, a CbCr plane should return a
+     * vector of size two with one PlaneLayoutComponent for Cb and one for Cr.
+     */
+    PlaneLayoutComponent[] components;
+
+    /**
+     * Offset to the first byte of the plane (in bytes), from the start of the allocation.
+     */
+    long offsetInBytes;
+
+    /**
+     * Bits per sample increment (aka column increment): describes the distance
+     * in bits from one sample to the next sample (to the right) on the same row for the
+     * the component plane.
+     *
+     * The default value is 0. Return the default value if the increment is undefined, unknown,
+     * or variable.
+     *
+     * This can be negative. A negative increment indicates that the samples are read from
+     * right to left.
+     */
+    long sampleIncrementInBits;
+
+    /**
+     * Horizontal stride: number of bytes between two vertically adjacent
+     * samples in given plane. This can be mathematically described by:
+     *
+     * strideInBytes = ALIGN(widthInSamples * bps / 8, alignment)
+     *
+     * where,
+     *
+     * bps: average bits per sample
+     * alignment (in bytes): dependent upon pixel format and usage
+     *
+     * strideInBytes can contain additional padding beyond the widthInSamples.
+     *
+     * The default value is 0. Return the default value if the stride is undefined, unknown,
+     * or variable.
+     *
+     * This can be negative. A negative stride indicates that the rows are read from
+     * bottom to top.
+     */
+    long strideInBytes;
+
+    /**
+     * Dimensions of plane (in samples).
+     *
+     * This is the number of samples in the plane, even if subsampled.
+     *
+     * See 'strideInBytes' for relationship between strideInBytes and widthInSamples.
+     */
+    long widthInSamples;
+    long heightInSamples;
+
+    /**
+     * Can be used to get the total size in bytes of any memory used by the plane
+     * including extra padding. This should not include any extra metadata used to describe the
+     * plane.
+     */
+    long totalSizeInBytes;
+
+    /**
+     * Horizontal and vertical subsampling. Must be a positive power of 2.
+     *
+     * These fields indicate the number of horizontally or vertically adjacent pixels that use
+     * the same pixel data. A value of 1 indicates no subsampling.
+     */
+    long horizontalSubsampling;
+    long verticalSubsampling;
+
+    /**
+     * Some buffer producers require extra padding to their output buffer; therefore the
+     * physical size of the native buffer will be larger than its logical size.
+     * The crop rectangle determines the offset and logical size of the buffer that should be
+     * read by consumers.
+     *
+     * The crop rectangle is measured in samples and is relative to the offset of the
+     * plane. Valid crop rectangles are within the boundaries of the plane:
+     * [0, 0, widthInSamples, heightInSamples].
+     *
+     * The default crop rectangle is a rectangle the same size as the plane:
+     * [0, 0, widthInSamples, heightInSamples].
+     */
+    Rect crop;
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/PlaneLayoutComponent.aidl b/graphics/common/aidl/android/hardware/graphics/common/PlaneLayoutComponent.aidl
new file mode 100644
index 0000000..3fca53b
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/PlaneLayoutComponent.aidl
@@ -0,0 +1,67 @@
+/**
+ * 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.
+ */
+
+package android.hardware.graphics.common;
+
+import android.hardware.graphics.common.ExtendableType;
+
+/**
+ * Used by IAllocator/IMapper (gralloc) to describe the type and location of a component in a
+ * buffer's plane.
+ *
+ * PlaneLayoutComponent uses the following definitions:
+ *
+ * - Component - a component is one channel of a pixel. For example, an RGBA format has
+ *      four components: R, G, B and A.
+ * - Sample - a sample is comprised of all the components in a given plane. For example,
+ *      a buffer with one Y plane and one CbCr plane has one plane with a sample of Y
+ *      and one plane with a sample of CbCr.
+ * - Pixel - a pixel is comprised of all the (non-metadata/raw) components in buffer across
+ *      all planes. For example, a buffer with a plane of Y and a plane of CbCr has a pixel
+ *      of YCbCr.
+ */
+
+@VintfStability
+parcelable PlaneLayoutComponent {
+    /**
+     * The type of this plane layout component.
+     *
+     * android.hardware.graphics.common.PlaneLayoutComponent defines the standard
+     * plane layout component types. Vendors may extend this type to include any
+     * non-standard plane layout component types. For instructions on how to
+     * create a vendor extension, refer to ExtendableType.aidl.
+     */
+    ExtendableType type;
+
+    /**
+     * Offset in bits to the first instance of this component in the plane.
+     * This is relative to the plane's offset (PlaneLayout::offset).
+     *
+     * If the offset cannot be described using a int64_t, this should be set to -1.
+     * For example, if the plane is compressed and the offset is not defined or
+     * relevant, return -1.
+     */
+    long offsetInBits;
+
+    /**
+     * The number of bits used per component in the plane.
+     *
+     * If the plane layout component cannot be described using componentSizeInBits, this
+     * should be set to -1. For example, if the component varies in size throughout
+     * the plane, return -1.
+     */
+    long sizeInBits;
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/PlaneLayoutComponentType.aidl b/graphics/common/aidl/android/hardware/graphics/common/PlaneLayoutComponentType.aidl
new file mode 100644
index 0000000..18c4a2e
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/PlaneLayoutComponentType.aidl
@@ -0,0 +1,46 @@
+/**
+ * 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.
+ */
+
+package android.hardware.graphics.common;
+
+/**
+ * Used by IAllocator/IMapper (gralloc) to describe standard plane layout component types
+ *
+ * The enum values have been taken directly from gralloc1's android_flex_component for compatiblity
+ * reasons. However, unlike gralloc1's android_flex_component, this field is NOT a bit field.
+ * A plane's components should NOT be expressed by bitwise OR-ing different
+ * PlaneLayoutComponentTypes together.
+ */
+@VintfStability
+@Backing(type="long")
+enum PlaneLayoutComponentType {
+    /* Luma */
+    Y = 1 << 0,
+    /* Chroma blue */
+    CB = 1 << 1,
+    /* Chroma red */
+    CR = 1 << 2,
+
+    /* Red */
+    R = 1 << 10,
+    /* Green */
+    G = 1 << 11,
+    /* Blue */
+    B = 1 << 12,
+
+    /* Alpha */
+    A = 1 << 30,
+}
diff --git a/vibrator/1.4/types.hal b/graphics/common/aidl/android/hardware/graphics/common/Rect.aidl
similarity index 62%
copy from vibrator/1.4/types.hal
copy to graphics/common/aidl/android/hardware/graphics/common/Rect.aidl
index acc49b1..1a3bc11 100644
--- a/vibrator/1.4/types.hal
+++ b/graphics/common/aidl/android/hardware/graphics/common/Rect.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
+/**
+ * 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
+ *     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,
@@ -14,9 +14,16 @@
  * limitations under the License.
  */
 
-package android.hardware.vibrator@1.4;
+package android.hardware.graphics.common;
 
-enum Capabilities : uint32_t {
-    ON_COMPLETION_CALLBACK = 1 << 0,
-    PERFORM_COMPLETION_CALLBACK = 1 << 1,
-};
+/**
+ * General purpose definition of a rectangle.
+ */
+
+@VintfStability
+parcelable Rect {
+    int left;
+    int top;
+    int right;
+    int bottom;
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl b/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
new file mode 100644
index 0000000..060d12c
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
@@ -0,0 +1,282 @@
+/**
+ * Copyright (c) 2019,libgralloctypes_helper 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;
+
+/**
+ * Used by IAllocator/IMapper (gralloc) to describe standard metadata types.
+ *
+ * This is an enum that defines the common types of gralloc 4 buffer metadata. The comments for
+ * each enum include a description of the metadata that is associated with the type.
+ *
+ * IMapper@4.x must support getting the following standard buffer metadata types. IMapper@4.x may
+ * support setting these standard buffer metadata types as well.
+ */
+@VintfStability
+@Backing(type="long")
+enum StandardMetadataType {
+    INVALID = 0,
+
+    /**
+     * Can be used to get the random ID of the buffer. This ID should be psuedorandom with
+     * sufficient entropy.
+     *
+     * This ID should only be used for debugging purposes. It cannot be used as a basis for any
+     * control flows.
+     *
+     * The buffer ID is determined at allocation time and should not change during the lifetime
+     * of the buffer.
+     *
+     * The buffer ID is a uint64_t.
+     *
+     * When it is encoded into a byte stream, it is represented by 8 bytes written in little endian.
+     */
+    BUFFER_ID = 1,
+
+    /**
+     * Can be used to get the name passed in by the client at allocation time in the
+     * BufferDescriptorInfo.
+     *
+     * The buffer name is determined at allocation time and should not change during the lifetime
+     * of the buffer.
+     *
+     * The buffer name is a string.
+     *
+     * When it is encoded into a byte stream, the length of the string is written using 8 bytes in
+     * little endian. It is followed by a char array of the string's
+     * characters. The array is not null-terminated.
+     */
+    NAME = 2,
+
+    /**
+     * Can be used to get the number of elements per buffer row requested at allocation time in
+     * the BufferDescriptorInfo.
+     *
+     * The width is determined at allocation time and should not change during the lifetime
+     * of the buffer.
+     *
+     * The width is a uint64_t.
+     *
+     * When it is encoded into a byte stream, it is represented by 8 bytes written in little endian.
+     */
+    WIDTH = 3,
+
+    /**
+     * Can be used to get the number of elements per buffer column requested at allocation time in
+     * the BufferDescriptorInfo.
+     *
+     * The height is determined at allocation time and should not change during the lifetime
+     * of the buffer.
+     *
+     * The height is a uint64_t.
+     *
+     * When it is encoded into a byte stream, it is represented by 8 bytes written in little endian.
+     */
+    HEIGHT = 4,
+
+    /**
+     * Can be used to get the number of layers requested at allocation time in the
+     * BufferDescriptorInfo.
+     *
+     * The layer count is determined at allocation time and should not change during the lifetime
+     * of the buffer.
+     *
+     * The layer count is a uint64_t.
+     *
+     * When it is encoded into a byte stream, it is represented by 8 bytes written in little endian.
+     */
+    LAYER_COUNT = 5,
+
+    /**
+     * Can be used to get the buffer format requested at allocation time in the
+     * BufferDescriptorInfo.
+     *
+     * The requested pixel format is determined at allocation time and should not change during
+     * the lifetime of the buffer.
+     *
+     * The requested pixel format is a android.hardware.graphics.common@1.2::PixelFormat.
+     *
+     * When it is encoded into a byte stream, it is first cast to a int32_t and then represented in
+     * the byte stream by 4 bytes written in little endian.
+     */
+    PIXEL_FORMAT_REQUESTED = 6,
+
+    /**
+     * Can be used to get the fourcc code for the format. Fourcc codes are standard across all
+     * devices of the same kernel version. Fourcc codes must follow the Linux definition of a
+     * fourcc format found in: include/uapi/drm/drm_fourcc.h.
+     *
+     * The pixel format fourcc code is represented by a uint32_t.
+     *
+     * When it is encoded into a byte stream, it is represented by 4 bytes written in little endian.
+     */
+    PIXEL_FORMAT_FOURCC = 7,
+
+    /**
+     * Can be used to get the modifier for the format. Together fourcc and modifier describe the
+     * real pixel format. Each fourcc and modifier pair is unique and must fully define the format
+     * and layout of the buffer. Modifiers can change any property of the buffer. Modifiers must
+     * follow the Linux definition of a modifier found in: include/uapi/drm/drm_fourcc.h.
+     *
+     * The pixel format modifier is represented by a uint64_t.
+     *
+     * When it is encoded into a byte stream, it is represented by 8 bytes written in little endian.
+     */
+    PIXEL_FORMAT_MODIFIER = 8,
+
+    /**
+     * Can be used to get the usage requested at allocation time in the BufferDescriptorInfo.
+     *
+     * The usage is determined at allocation time and should not change during the lifetime
+     * of the buffer.
+     *
+     * The usage is a uint64_t bit field of android.hardware.graphics.common@1.2::BufferUsage's.
+     *
+     * When it is encoded into a byte stream, it is represented by 8 bytes written in little endian.
+     */
+    USAGE = 9,
+
+    /**
+     * Can be used to get the total size in bytes of any memory used by the buffer including its
+     * metadata and extra padding. This is the total number of bytes used by the buffer allocation.
+     *
+     * The allocation size is a uint64_t.
+     *
+     * When it is encoded into a byte stream, it is represented by 8 bytes written in little endian.
+     */
+    ALLOCATION_SIZE = 10,
+
+    /**
+     * Can be used to get if a buffer has protected content. If the buffer does not have protected
+     * content, this should return 0. If a buffer has protected content, this should return 1.
+     *
+     * In future versions, this field will be extended to expose more information about the type
+     * of protected content in the buffer.
+     *
+     * The protected content is a uint64_t.
+     *
+     * When it is encoded into a byte stream, it is represented by 8 bytes written in little endian.
+     */
+    PROTECTED_CONTENT = 11,
+
+    /**
+     * Can be used to get the compression strategy of the buffer. If the device has more than one
+     * compression strategy, it should have different unique values for each compression
+     * strategy.
+     *
+     * Compression is a stable aidl android.hardware.graphics.common.ExtendableType.
+     *
+     * android.hardware.graphics.common.Compression defines the standard compression
+     * strategies. Vendors may extend this type to include any compression strategies.
+     *
+     * When it is encoded into a byte stream, the length of the name field string is written using
+     * 8 bytes in little endian. It is followed by a char array of the string's
+     * characters. The array is not null-terminated. Finally the value field is written as 8 bytes
+     * in little endian.
+     */
+    COMPRESSION = 12,
+
+    /**
+     * Can be used to get how the buffer's planes are interlaced.
+     *
+     * Interlaced is a stable aidl android.hardware.graphics.common.ExtendableType.
+     *
+     * android.hardware.graphics.common.Interlaced defines the standard interlaced
+     * strategies. Vendors may extend this type to include any non-standard interlaced
+     * strategies.
+     *
+     * When it is encoded into a byte stream, the length of the name field string is written using
+     * 8 bytes in little endian. It is followed by a char array of the string's
+     * characters. The array is not null-terminated. Finally the value field is written as 8 bytes
+     * in little endian.
+     */
+    INTERLACED = 13,
+
+    /**
+     * Can be used to get the chroma siting of a buffer.
+     *
+     * Chroma siting is a stable aidl android.hardware.graphics.common.ExtendableType.
+     *
+     * android.hardware.graphics.common.ChromaSiting defines the standard chroma
+     * sitings. Vendors may extend this type to include any non-standard chroma sitings.
+     *
+     * When it is encoded into a byte stream, the length of the name field string is written using
+     * 8 bytes in little endian. It is followed by a char array of the string's
+     * characters. The array is not null-terminated. Finally the value field is written as 8 bytes
+     * in little endian.
+     */
+    CHROMA_SITING = 14,
+
+    /**
+     * Can be used to get the PlaneLayout(s) of the buffer. There should be one PlaneLayout per
+     * plane in the buffer. For example if the buffer only has one plane, only one PlaneLayout
+     * should be returned.
+     *
+     * If the buffer has planes interlaced through time, the returned PlaneLayout structs should be
+     * ordered by time. The nth PlaneLayout should be from the same time or earlier than the
+     * n+1 PlaneLayout.
+     *
+     * The plane layout is a list of stable aidl android.hardware.graphics.common.PlaneLayout's.
+     *
+     * When it is encoded into a byte stream, the total number of PlaneLayouts is written using
+     * 8 bytes in little endian. It is followed by each PlaneLayout.
+     *
+     * To encode a PlaneLayout, write the length of its PlaneLayoutComponent[] components
+     * field as 8 bytes in little endian and then encode each of its components. Finally, write the
+     * following fields in this order each as 8 bytes in little endian: offsetInBytes,
+     * sampleIncrementInBits, strideInBytes, widthInSamples, totalSizeInBytes,
+     * horizontalSubsampling, verticalSubsampling.
+     *
+     * To encode a PlaneLayoutComponent, encode its PlaneLayoutComponentType type field. Next
+     * encode offsetInBits followed by sizeInBits each as 8 bytes in little endian.
+     *
+     * To encode a PlaneLayoutComponentType, write the length of the name field string as
+     * 8 bytes in little endian. It is followed by a char array of the string's
+     * characters. The array is not null-terminated. Finally the value field is written as 8 bytes
+     * in little endian.
+     */
+    PLANE_LAYOUTS = 15,
+
+    /**
+     * Can be used to get or set the dataspace of the buffer. The framework may attempt to set
+     * this value.
+     *
+     * The default dataspace is Dataspace::UNKNOWN. If this dataspace is set to any valid value
+     * other than Dataspace::UNKNOWN, this dataspace overrides all other dataspaces. For example,
+     * if the buffer has Dataspace::DISPLAY_P3 and it is being displayed on a composer Layer that
+     * is Dataspace::sRGB, the buffer should be treated as a DISPLAY_P3 buffer.
+     *
+     * The dataspace is a stable aidl android.hardware.graphics.common.Dataspace.
+     *
+     * When it is encoded into a byte stream, it is first cast to a int32_t and then represented in
+     * the byte stream by 4 bytes written in little endian.
+     */
+    DATASPACE = 16,
+
+    /**
+     * Can be used to get or set the BlendMode. The framework may attempt to set this value.
+     *
+     * The default blend mode is INVALID. If the BlendMode is set to any
+     * valid value other than INVALID, this BlendMode overrides all other
+     * dataspaces. For a longer description of this behavior see MetadataType::DATASPACE.
+     *
+     * The blend mode is a stable aidl android.hardware.graphics.common.BlendMode.
+     *
+     * When it is encoded into a byte stream, it is first cast to a int32_t and then represented by
+     * 4 bytes written in little endian.
+     */
+    BLEND_MODE = 17,
+}
diff --git a/graphics/composer/2.1/utils/vts/ComposerVts.cpp b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
index a0745ce..a8e1480 100644
--- a/graphics/composer/2.1/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
@@ -369,10 +369,7 @@
         accessRegion.top = accessRegionRect.top;
         accessRegion.width = accessRegionRect.width;
         accessRegion.height = accessRegionRect.height;
-        int32_t bytesPerPixel;
-        int32_t bytesPerStride;
-        return mGralloc4->lock(bufferHandle, cpuUsage, accessRegion, acquireFence, &bytesPerPixel,
-                               &bytesPerStride);
+        return mGralloc4->lock(bufferHandle, cpuUsage, accessRegion, acquireFence);
     } else if (mGralloc3) {
         IMapper3::Rect accessRegion;
         accessRegion.left = accessRegionRect.left;
diff --git a/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h b/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h
index 138d700..35162a6 100644
--- a/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h
+++ b/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h
@@ -93,17 +93,18 @@
     }
 
    protected:
-    void beginCommand_2_2(IComposerClient::Command command, uint16_t length) {
-        V2_1::CommandWriterBase::beginCommand(
-            static_cast<V2_1::IComposerClient::Command>(static_cast<int32_t>(command)), length);
-    }
-
     void writeFloatColor(const IComposerClient::FloatColor& color) {
         writeFloat(color.r);
         writeFloat(color.g);
         writeFloat(color.b);
         writeFloat(color.a);
     }
+
+  private:
+    void beginCommand_2_2(IComposerClient::Command command, uint16_t length) {
+        V2_1::CommandWriterBase::beginCommand(
+                static_cast<V2_1::IComposerClient::Command>(static_cast<int32_t>(command)), length);
+    }
 };
 
 // This class helps parse a command queue.  Note that all sizes/lengths are in
diff --git a/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h
index 93da0a5..9b3aa90 100644
--- a/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h
+++ b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h
@@ -173,6 +173,14 @@
     Error getRenderIntents(Display display, ColorMode mode,
                            std::vector<RenderIntent>* outIntents) override {
         if (!mDispatch.getRenderIntents) {
+            IComposerClient::DisplayType type;
+            if (getDisplayType(display, &type) == Error::BAD_DISPLAY) {
+                return Error::BAD_DISPLAY;
+            }
+            if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_P3) {
+                return Error::BAD_PARAMETER;
+            }
+
             *outIntents = std::vector<RenderIntent>({RenderIntent::COLORIMETRIC});
             return Error::NONE;
         }
@@ -199,6 +207,9 @@
 
     Error setColorMode_2_2(Display display, ColorMode mode, RenderIntent intent) override {
         if (!mDispatch.setColorModeWithRenderIntent) {
+            if (intent < RenderIntent::COLORIMETRIC || intent > RenderIntent::TONE_MAP_ENHANCE) {
+                return Error::BAD_PARAMETER;
+            }
             if (intent != RenderIntent::COLORIMETRIC) {
                 return Error::UNSUPPORTED;
             }
@@ -282,6 +293,7 @@
    private:
     using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>;
     using BaseType2_1::getColorModes;
+    using BaseType2_1::getDisplayType;
     using BaseType2_1::mDevice;
     using BaseType2_1::setColorMode;
     using BaseType2_1::createVirtualDisplay;
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index 21ba9f3..f987516 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -57,5 +57,6 @@
         "android.hardware.graphics.composer@2.1-command-buffer",
         "android.hardware.graphics.composer@2.2-command-buffer",
     ],
-    test_suites: ["general-tests"],
+    disable_framework: true,
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
index 6a6f7de..044bd96 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
@@ -16,14 +16,15 @@
 
 #define LOG_TAG "graphics_composer_hidl_hal_readback_tests@2.2"
 
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
 #include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
 #include <composer-vts/2.1/GraphicsComposerCallback.h>
 #include <composer-vts/2.1/TestCommandReader.h>
 #include <composer-vts/2.2/ComposerVts.h>
 #include <composer-vts/2.2/ReadbackVts.h>
 #include <composer-vts/2.2/RenderEngineVts.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/GraphicBufferAllocator.h>
 #include <ui/PixelFormat.h>
@@ -50,29 +51,12 @@
 using V2_1::vts::TestCommandReader;
 using vts::Gralloc;
 
-// Test environment for graphics.composer
-class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static GraphicsComposerHidlEnvironment* Instance() {
-        static GraphicsComposerHidlEnvironment* instance = new GraphicsComposerHidlEnvironment;
-        return instance;
-    }
-    virtual void registerTestServices() override { registerTestService<IComposer>(); }
-
-   private:
-    GraphicsComposerHidlEnvironment() {}
-    GTEST_DISALLOW_COPY_AND_ASSIGN_(GraphicsComposerHidlEnvironment);
-};
-
-class GraphicsCompositionTest : public ::testing::VtsHalHidlTargetTestBase {
+class GraphicsCompositionTestBase : public ::testing::Test {
   protected:
     using PowerMode = V2_1::IComposerClient::PowerMode;
-    void SetUp() override {
-        VtsHalHidlTargetTestBase::SetUp();
+    void SetUpBase(const std::string& service_name) {
         ASSERT_NO_FATAL_FAILURE(
-            mComposer = std::make_unique<Composer>(
-                GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
+                mComposer = std::make_unique<Composer>(IComposer::getService(service_name)));
         ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
         mComposerCallback = new V2_1::vts::GraphicsComposerCallback;
         mComposerClient->registerCallback(mComposerCallback);
@@ -132,7 +116,6 @@
             EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
             EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
         }
-        VtsHalHidlTargetTestBase::TearDown();
     }
 
     void clearCommandReaderState() {
@@ -198,7 +181,13 @@
     }
 };
 
-TEST_F(GraphicsCompositionTest, SingleSolidColorLayer) {
+class GraphicsCompositionTest : public GraphicsCompositionTestBase,
+                                public testing::WithParamInterface<std::string> {
+  public:
+    void SetUp() override { SetUpBase(GetParam()); }
+};
+
+TEST_P(GraphicsCompositionTest, SingleSolidColorLayer) {
     for (ColorMode mode : mTestColorModes) {
         std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
                   << std::endl;
@@ -260,7 +249,7 @@
     }
 }
 
-TEST_F(GraphicsCompositionTest, SetLayerBuffer) {
+TEST_P(GraphicsCompositionTest, SetLayerBuffer) {
     for (ColorMode mode : mTestColorModes) {
         std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
                   << std::endl;
@@ -332,7 +321,7 @@
     }
 }
 
-TEST_F(GraphicsCompositionTest, SetLayerBufferNoEffect) {
+TEST_P(GraphicsCompositionTest, SetLayerBufferNoEffect) {
     for (ColorMode mode : mTestColorModes) {
         std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
                   << std::endl;
@@ -394,7 +383,7 @@
     }
 }
 
-TEST_F(GraphicsCompositionTest, ClientComposition) {
+TEST_P(GraphicsCompositionTest, ClientComposition) {
     ASSERT_NO_FATAL_FAILURE(
             mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kClientTargetSlotCount));
 
@@ -511,7 +500,7 @@
     }
 }
 
-TEST_F(GraphicsCompositionTest, DeviceAndClientComposition) {
+TEST_P(GraphicsCompositionTest, DeviceAndClientComposition) {
     ASSERT_NO_FATAL_FAILURE(
             mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kClientTargetSlotCount));
 
@@ -637,7 +626,7 @@
     }
 }
 
-TEST_F(GraphicsCompositionTest, SetLayerDamage) {
+TEST_P(GraphicsCompositionTest, SetLayerDamage) {
     for (ColorMode mode : mTestColorModes) {
         std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
                   << std::endl;
@@ -722,7 +711,7 @@
     }
 }
 
-TEST_F(GraphicsCompositionTest, SetLayerPlaneAlpha) {
+TEST_P(GraphicsCompositionTest, SetLayerPlaneAlpha) {
     for (ColorMode mode : mTestColorModes) {
         std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
                   << std::endl;
@@ -783,7 +772,7 @@
     }
 }
 
-TEST_F(GraphicsCompositionTest, SetLayerSourceCrop) {
+TEST_P(GraphicsCompositionTest, SetLayerSourceCrop) {
     for (ColorMode mode : mTestColorModes) {
         std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
                   << std::endl;
@@ -854,7 +843,7 @@
     }
 }
 
-TEST_F(GraphicsCompositionTest, SetLayerZOrder) {
+TEST_P(GraphicsCompositionTest, SetLayerZOrder) {
     for (ColorMode mode : mTestColorModes) {
         std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
                   << std::endl;
@@ -941,18 +930,17 @@
     }
 }
 
-class GraphicsBlendModeCompositionTest : public GraphicsCompositionTest,
-                                         public ::testing::WithParamInterface<float> {
+class GraphicsBlendModeCompositionTest
+    : public GraphicsCompositionTestBase,
+      public testing::WithParamInterface<std::tuple<string, string>> {
   public:
     void SetUp() override {
-        GraphicsCompositionTest::SetUp();
+        SetUpBase(std::get<0>(GetParam()));
         mTestColorModes = {ColorMode::SRGB};  // TODO: add more color mode support
         mBackgroundColor = BLACK;
         mTopLayerColor = RED;
     }
 
-    void TearDown() override { GraphicsCompositionTest::TearDown(); }
-
     void setBackgroundColor(IComposerClient::Color color) { mBackgroundColor = color; }
 
     void setTopLayerColor(IComposerClient::Color color) { mTopLayerColor = color; }
@@ -977,7 +965,7 @@
         ASSERT_NO_FATAL_FAILURE(layer->setBuffer(topLayerPixelColors));
 
         layer->setBlendMode(blendMode);
-        layer->setAlpha(GetParam());
+        layer->setAlpha(std::stof(std::get<1>(GetParam())));
 
         mLayers.push_back(backgroundLayer);
         mLayers.push_back(layer);
@@ -1023,7 +1011,8 @@
     IComposerClient::Color mTopLayerColor;
 };
 
-TEST_P(GraphicsBlendModeCompositionTest, None) {
+// TODO(b/145557764): Re-enable after the bug is fixed.
+TEST_P(GraphicsBlendModeCompositionTest, DISABLED_None) {
     for (ColorMode mode : mTestColorModes) {
         std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
                   << std::endl;
@@ -1188,9 +1177,6 @@
     }
 }
 
-INSTANTIATE_TEST_CASE_P(BlendModeTest, GraphicsBlendModeCompositionTest,
-                        ::testing::Values(.2, 1.0));
-
 class GraphicsTransformCompositionTest : public GraphicsCompositionTest {
   protected:
     void SetUp() override {
@@ -1229,7 +1215,7 @@
     int mSideLength;
 };
 
-TEST_F(GraphicsTransformCompositionTest, FLIP_H) {
+TEST_P(GraphicsTransformCompositionTest, FLIP_H) {
     for (ColorMode mode : mTestColorModes) {
         std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
                   << std::endl;
@@ -1284,7 +1270,7 @@
     }
 }
 
-TEST_F(GraphicsTransformCompositionTest, FLIP_V) {
+TEST_P(GraphicsTransformCompositionTest, FLIP_V) {
     for (ColorMode mode : mTestColorModes) {
         std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
                   << std::endl;
@@ -1339,7 +1325,7 @@
     }
 }
 
-TEST_F(GraphicsTransformCompositionTest, ROT_180) {
+TEST_P(GraphicsTransformCompositionTest, ROT_180) {
     for (ColorMode mode : mTestColorModes) {
         std::cout << "---Testing Color Mode " << ReadbackHelper::getColorModeString(mode) << "---"
                   << std::endl;
@@ -1395,6 +1381,23 @@
     }
 }
 
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, GraphicsCompositionTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)),
+        android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_CASE_P(
+        BlendModeTest, GraphicsBlendModeCompositionTest,
+        testing::Combine(
+                testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)),
+                testing::Values("0.2", "1.0")),
+        android::hardware::PrintInstanceTupleNameToString<>);
+
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, GraphicsTransformCompositionTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)),
+        android::hardware::PrintInstanceNameToString);
+
 }  // anonymous namespace
 }  // namespace vts
 }  // namespace V2_2
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index 51832f9..95a0f69 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -16,12 +16,14 @@
 
 #define LOG_TAG "graphics_composer_hidl_hal_test@2.2"
 
-#include <VtsHalHidlTargetTestBase.h>
 #include <android-base/logging.h>
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
 #include <composer-vts/2.1/GraphicsComposerCallback.h>
 #include <composer-vts/2.1/TestCommandReader.h>
 #include <composer-vts/2.2/ComposerVts.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 #include <mapper-vts/2.0/MapperVts.h>
 
 namespace android {
@@ -41,29 +43,11 @@
 using common::V1_1::RenderIntent;
 using mapper::V2_0::IMapper;
 
-// Test environment for graphics.composer
-class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static GraphicsComposerHidlEnvironment* Instance() {
-        static GraphicsComposerHidlEnvironment* instance = new GraphicsComposerHidlEnvironment;
-        return instance;
-    }
-
-    virtual void registerTestServices() override { registerTestService<IComposer>(); }
-
-   private:
-    GraphicsComposerHidlEnvironment() {}
-
-    GTEST_DISALLOW_COPY_AND_ASSIGN_(GraphicsComposerHidlEnvironment);
-};
-
-class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-   protected:
+class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> {
+  protected:
     void SetUp() override {
         ASSERT_NO_FATAL_FAILURE(
-            mComposer = std::make_unique<Composer>(
-                GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
+                mComposer = std::make_unique<Composer>(IComposer::getService(GetParam())));
         ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
 
         mComposerCallback = new V2_1::vts::GraphicsComposerCallback;
@@ -188,7 +172,7 @@
 /**
  * Test IComposerClient::Command::SET_LAYER_PER_FRAME_METADATA.
  */
-TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_PER_FRAME_METADATA) {
+TEST_P(GraphicsComposerHidlCommandTest, SET_LAYER_PER_FRAME_METADATA) {
     Layer layer;
     ASSERT_NO_FATAL_FAILURE(layer =
                                 mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
@@ -239,7 +223,7 @@
 /**
  * Test IComposerClient::getPerFrameMetadataKeys.
  */
-TEST_F(GraphicsComposerHidlTest, GetPerFrameMetadataKeys) {
+TEST_P(GraphicsComposerHidlTest, GetPerFrameMetadataKeys) {
     std::vector<IComposerClient::PerFrameMetadataKey> keys;
     Error error = Error::NONE;
     mComposerClient->getRaw()->getPerFrameMetadataKeys(
@@ -261,7 +245,7 @@
  *
  * Test that virtual displays can be created and has the correct display type.
  */
-TEST_F(GraphicsComposerHidlTest, CreateVirtualDisplay_2_2) {
+TEST_P(GraphicsComposerHidlTest, CreateVirtualDisplay_2_2) {
     if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
         GTEST_SUCCEED() << "no virtual display support";
         return;
@@ -286,7 +270,7 @@
  * Test that IComposerClient::getClientTargetSupport returns true for the
  * required client targets.
  */
-TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport_2_2) {
+TEST_P(GraphicsComposerHidlTest, GetClientTargetSupport_2_2) {
     std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
     for (auto config : configs) {
         int32_t width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
@@ -310,7 +294,7 @@
  * Error::BAD_DISPLAY when passed in an invalid display handle
  */
 
-TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport_2_2BadDisplay) {
+TEST_P(GraphicsComposerHidlTest, GetClientTargetSupport_2_2BadDisplay) {
     std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
     for (auto config : configs) {
         int32_t width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
@@ -332,7 +316,7 @@
 /**
  * Test IComposerClient::setPowerMode_2_2.
  */
-TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2) {
+TEST_P(GraphicsComposerHidlTest, SetPowerMode_2_2) {
     std::vector<IComposerClient::PowerMode> modes;
     modes.push_back(IComposerClient::PowerMode::OFF);
     modes.push_back(IComposerClient::PowerMode::ON_SUSPEND);
@@ -349,7 +333,7 @@
  * Test that IComposerClient::setPowerMode_2_2 succeeds for different varations
  * of PowerMode
  */
-TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2Variations) {
+TEST_P(GraphicsComposerHidlTest, SetPowerMode_2_2Variations) {
     std::vector<IComposerClient::PowerMode> modes;
 
     modes.push_back(IComposerClient::PowerMode::OFF);
@@ -404,7 +388,7 @@
  * Tests that IComposerClient::setPowerMode_2_2 returns BAD_DISPLAY when passed an
  * invalid display handle
  */
-TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2BadDisplay) {
+TEST_P(GraphicsComposerHidlTest, SetPowerMode_2_2BadDisplay) {
     Error error = mComposerClient->getRaw()->setPowerMode_2_2(mInvalidDisplayId,
                                                               IComposerClient::PowerMode::ON);
     ASSERT_EQ(Error::BAD_DISPLAY, error);
@@ -416,7 +400,7 @@
  * Test that IComposerClient::setPowerMode_2_2 returns BAD_PARAMETER when passed
  * an invalid PowerMode
  */
-TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2BadParameter) {
+TEST_P(GraphicsComposerHidlTest, SetPowerMode_2_2BadParameter) {
     Error error = mComposerClient->getRaw()->setPowerMode_2_2(
         mPrimaryDisplay, static_cast<IComposerClient::PowerMode>(-1));
     ASSERT_EQ(Error::BAD_PARAMETER, error);
@@ -428,7 +412,7 @@
  * Test that IComposerClient::setPowerMode_2_2 returns UNSUPPORTED when passed
  * DOZE or DOZE_SUPPORT on a device that does not support these modes
  */
-TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2Unsupported) {
+TEST_P(GraphicsComposerHidlTest, SetPowerMode_2_2Unsupported) {
     if (!mComposerClient->getDozeSupport(mPrimaryDisplay)) {
         Error error = mComposerClient->getRaw()->setPowerMode_2_2(mPrimaryDisplay,
                                                                   IComposerClient::PowerMode::DOZE);
@@ -445,7 +429,7 @@
  *
  * Test IComposerClient::setReadbackBuffer
  */
-TEST_F(GraphicsComposerHidlTest, SetReadbackBuffer) {
+TEST_P(GraphicsComposerHidlTest, SetReadbackBuffer) {
     if (!mHasReadbackBuffer) {
         return;
     }
@@ -469,7 +453,7 @@
  * Test that IComposerClient::setReadbackBuffer returns an Error::BAD_DISPLAY
  * when passed an invalid display handle
  */
-TEST_F(GraphicsComposerHidlTest, SetReadbackBufferBadDisplay) {
+TEST_P(GraphicsComposerHidlTest, SetReadbackBufferBadDisplay) {
     if (!mHasReadbackBuffer) {
         return;
     }
@@ -493,7 +477,7 @@
  * Test that IComposerClient::setReadbackBuffer returns Error::BAD_PARAMETER
  * when passed an invalid buffer handle
  */
-TEST_F(GraphicsComposerHidlTest, SetReadbackBufferBadParameter) {
+TEST_P(GraphicsComposerHidlTest, SetReadbackBufferBadParameter) {
     if (!mHasReadbackBuffer) {
         return;
     }
@@ -502,7 +486,7 @@
     ASSERT_EQ(Error::BAD_PARAMETER, error);
 }
 
-TEST_F(GraphicsComposerHidlTest, GetReadbackBufferFenceInactive) {
+TEST_P(GraphicsComposerHidlTest, GetReadbackBufferFenceInactive) {
     if (!mHasReadbackBuffer) {
         return;
     }
@@ -516,7 +500,7 @@
 /**
  * Test IComposerClient::Command::SET_LAYER_FLOAT_COLOR.
  */
-TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_FLOAT_COLOR) {
+TEST_P(GraphicsComposerHidlCommandTest, SET_LAYER_FLOAT_COLOR) {
     V2_1::Layer layer;
     ASSERT_NO_FATAL_FAILURE(layer =
                                 mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
@@ -554,7 +538,7 @@
 /**
  * Test IComposerClient::getDataspaceSaturationMatrix.
  */
-TEST_F(GraphicsComposerHidlTest, GetDataspaceSaturationMatrix) {
+TEST_P(GraphicsComposerHidlTest, GetDataspaceSaturationMatrix) {
     auto matrix = mComposerClient->getDataspaceSaturationMatrix(Dataspace::SRGB_LINEAR);
     // the last row is known
     ASSERT_EQ(0.0f, matrix[12]);
@@ -570,7 +554,7 @@
  * Error::BAD_PARAMETER when passed a dataspace other than
  * Dataspace::SRGB_LINEAR
  */
-TEST_F(GraphicsComposerHidlTest, GetDataspaceSaturationMatrixBadParameter) {
+TEST_P(GraphicsComposerHidlTest, GetDataspaceSaturationMatrixBadParameter) {
     mComposerClient->getRaw()->getDataspaceSaturationMatrix(
         Dataspace::UNKNOWN,
         [&](const auto& tmpError, const auto&) { ASSERT_EQ(Error::BAD_PARAMETER, tmpError); });
@@ -579,7 +563,7 @@
 /**
  * Test IComposerClient::getColorMode_2_2.
  */
-TEST_F(GraphicsComposerHidlTest, GetColorMode_2_2) {
+TEST_P(GraphicsComposerHidlTest, GetColorMode_2_2) {
     std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
 
     auto nativeMode = std::find(modes.cbegin(), modes.cend(), ColorMode::NATIVE);
@@ -592,7 +576,7 @@
  * Test that IComposerClient::getColorMode returns Error::BAD_DISPLAY when
  * passed an invalid display handle
  */
-TEST_F(GraphicsComposerHidlTest, GetColorMode_2_2BadDisplay) {
+TEST_P(GraphicsComposerHidlTest, GetColorMode_2_2BadDisplay) {
     mComposerClient->getRaw()->getColorModes_2_2(
         mInvalidDisplayId,
         [&](const auto& tmpError, const auto&) { ASSERT_EQ(Error::BAD_DISPLAY, tmpError); });
@@ -601,7 +585,7 @@
 /**
  * Test IComposerClient::getRenderIntents.
  */
-TEST_F(GraphicsComposerHidlTest, GetRenderIntents) {
+TEST_P(GraphicsComposerHidlTest, GetRenderIntents) {
     std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
     for (auto mode : modes) {
         std::vector<RenderIntent> intents =
@@ -631,7 +615,7 @@
  * Test that IComposerClient::getRenderIntent returns Error::BAD_DISPLAY when
  * passed an invalid display handle
  */
-TEST_F(GraphicsComposerHidlTest, GetRenderIntentsBadDisplay) {
+TEST_P(GraphicsComposerHidlTest, GetRenderIntentsBadDisplay) {
     std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
     for (auto mode : modes) {
         mComposerClient->getRaw()->getRenderIntents(
@@ -646,7 +630,7 @@
  * Test that IComposerClient::getRenderIntents returns Error::BAD_PARAMETER when
  * pased either an invalid Color mode or an invalid Render Intent
  */
-TEST_F(GraphicsComposerHidlTest, GetRenderIntentsBadParameter) {
+TEST_P(GraphicsComposerHidlTest, GetRenderIntentsBadParameter) {
     mComposerClient->getRaw()->getRenderIntents(
         mPrimaryDisplay, static_cast<ColorMode>(-1),
         [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::BAD_PARAMETER, tmpError); });
@@ -655,7 +639,7 @@
 /**
  * Test IComposerClient::setColorMode_2_2.
  */
-TEST_F(GraphicsComposerHidlTest, SetColorMode_2_2) {
+TEST_P(GraphicsComposerHidlTest, SetColorMode_2_2) {
     std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
     for (auto mode : modes) {
         std::vector<RenderIntent> intents =
@@ -674,7 +658,7 @@
  * Test that IComposerClient::setColorMode_2_2 returns an Error::BAD_DISPLAY
  * when passed an invalid display handle
  */
-TEST_F(GraphicsComposerHidlTest, SetColorMode_2_2BadDisplay) {
+TEST_P(GraphicsComposerHidlTest, SetColorMode_2_2BadDisplay) {
     Error error = mComposerClient->getRaw()->setColorMode_2_2(mInvalidDisplayId, ColorMode::NATIVE,
                                                               RenderIntent::COLORIMETRIC);
 
@@ -687,7 +671,7 @@
  * Test that IComposerClient::setColorMode_2_2 returns Error::BAD_PARAMETER when
  * passed an invalid Color mode or an invalid render intent
  */
-TEST_F(GraphicsComposerHidlTest, SetColorMode_2_2BadParameter) {
+TEST_P(GraphicsComposerHidlTest, SetColorMode_2_2BadParameter) {
     Error colorModeError = mComposerClient->getRaw()->setColorMode_2_2(
         mPrimaryDisplay, static_cast<ColorMode>(-1), RenderIntent::COLORIMETRIC);
     EXPECT_EQ(Error::BAD_PARAMETER, colorModeError);
@@ -697,6 +681,16 @@
     EXPECT_EQ(Error::BAD_PARAMETER, renderIntentError);
 }
 
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, GraphicsComposerHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)),
+        android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, GraphicsComposerHidlCommandTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)),
+        android::hardware::PrintInstanceNameToString);
+
 }  // namespace
 }  // namespace vts
 }  // namespace V2_2
@@ -704,12 +698,3 @@
 }  // namespace graphics
 }  // namespace hardware
 }  // namespace android
-
-int main(int argc, char** argv) {
-    using android::hardware::graphics::composer::V2_2::vts::GraphicsComposerHidlEnvironment;
-    ::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance());
-    ::testing::InitGoogleTest(&argc, argv);
-    GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    return status;
-}
diff --git a/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h b/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h
index 11863fa..3dfda19 100644
--- a/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h
+++ b/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h
@@ -79,6 +79,7 @@
 
     void setLayerPerFrameMetadataBlobs(
         const hidl_vec<IComposerClient::PerFrameMetadataBlob>& metadata) {
+        // in units of uint32_t's
         size_t commandLength = 0;
 
         if (metadata.size() > std::numeric_limits<uint32_t>::max()) {
@@ -86,12 +87,12 @@
             return;
         }
 
-        // number of blobs
-        commandLength += metadata.size();
+        // space for numElements
+        commandLength += 1;
 
         for (auto metadataBlob : metadata) {
-            commandLength += sizeof(int32_t);  // key of metadata blob
-            commandLength += 1;                // size information of metadata blob
+            commandLength += 1;  // key of metadata blob
+            commandLength += 1;  // size information of metadata blob
 
             // metadata content size
             size_t metadataSize = metadataBlob.blob.size() / sizeof(uint32_t);
@@ -119,17 +120,18 @@
     }
 
    protected:
-    void beginCommand_2_3(IComposerClient::Command command, uint16_t length) {
-        V2_2::CommandWriterBase::beginCommand_2_2(
-            static_cast<V2_2::IComposerClient::Command>(static_cast<int32_t>(command)), length);
-    }
-
     void writeBlob(uint32_t length, const unsigned char* blob) {
         memcpy(&mData[mDataWritten], blob, length);
         uint32_t numElements = length / 4;
         mDataWritten += numElements;
         mDataWritten += (length - (numElements * 4) > 0) ? 1 : 0;
     }
+
+  private:
+    void beginCommand_2_3(IComposerClient::Command command, uint16_t length) {
+        V2_1::CommandWriterBase::beginCommand(
+                static_cast<V2_1::IComposerClient::Command>(static_cast<int32_t>(command)), length);
+    }
 };
 
 // This class helps parse a command queue.  Note that all sizes/lengths are in
diff --git a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
index 0d4e5b8..e5ac842 100644
--- a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
+++ b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
@@ -49,12 +49,10 @@
    public:
     Composer();
     explicit Composer(const std::string& name);
+    explicit Composer(const sp<IComposer>& composer);
 
     std::unique_ptr<ComposerClient> createClient();
 
-  protected:
-    explicit Composer(const sp<IComposer>& composer);
-
    private:
     const sp<IComposer> mComposer;
 };
diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp
index b729062..fa4823e 100644
--- a/graphics/composer/2.3/vts/functional/Android.bp
+++ b/graphics/composer/2.3/vts/functional/Android.bp
@@ -49,4 +49,6 @@
         "android.hardware.graphics.composer@2.2-command-buffer",
         "android.hardware.graphics.composer@2.3-command-buffer",
     ],
+    disable_framework: true,
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
index dafe587..94766af 100644
--- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
+++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
@@ -18,13 +18,15 @@
 
 #include <algorithm>
 
-#include <VtsHalHidlTargetTestBase.h>
 #include <android-base/logging.h>
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
 #include <composer-command-buffer/2.3/ComposerCommandBuffer.h>
 #include <composer-vts/2.1/GraphicsComposerCallback.h>
 #include <composer-vts/2.1/TestCommandReader.h>
 #include <composer-vts/2.3/ComposerVts.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 #include <mapper-vts/2.0/MapperVts.h>
 
 namespace android {
@@ -43,29 +45,11 @@
 using mapper::V2_0::IMapper;
 using V2_2::vts::Gralloc;
 
-// Test environment for graphics.composer
-class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static GraphicsComposerHidlEnvironment* Instance() {
-        static GraphicsComposerHidlEnvironment* instance = new GraphicsComposerHidlEnvironment;
-        return instance;
-    }
-
-    virtual void registerTestServices() override { registerTestService<IComposer>(); }
-
-   private:
-    GraphicsComposerHidlEnvironment() {}
-
-    GTEST_DISALLOW_COPY_AND_ASSIGN_(GraphicsComposerHidlEnvironment);
-};
-
-class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-   protected:
+class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> {
+  protected:
     void SetUp() override {
         ASSERT_NO_FATAL_FAILURE(
-            mComposer = std::make_unique<Composer>(
-                GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
+                mComposer = std::make_unique<Composer>(IComposer::getService(GetParam())));
         ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
 
         mComposerCallback = new V2_1::vts::GraphicsComposerCallback;
@@ -175,7 +159,7 @@
  *
  * TODO: Check that ports are unique for multiple displays.
  */
-TEST_F(GraphicsComposerHidlTest, GetDisplayIdentificationData) {
+TEST_P(GraphicsComposerHidlTest, GetDisplayIdentificationData) {
     uint8_t port0;
     std::vector<uint8_t> data0;
     if (mComposerClient->getDisplayIdentificationData(mPrimaryDisplay, &port0, &data0)) {
@@ -193,7 +177,7 @@
 /**
  * Test IComposerClient::Command::SET_LAYER_PER_FRAME_METADATA.
  */
-TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_PER_FRAME_METADATA) {
+TEST_P(GraphicsComposerHidlCommandTest, SET_LAYER_PER_FRAME_METADATA) {
     Layer layer;
     ASSERT_NO_FATAL_FAILURE(layer =
                                 mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
@@ -244,7 +228,7 @@
 /**
  * Test IComposerClient::getHdrCapabilities_2_3
  */
-TEST_F(GraphicsComposerHidlTest, GetHdrCapabilities_2_3) {
+TEST_P(GraphicsComposerHidlTest, GetHdrCapabilities_2_3) {
     float maxLuminance;
     float maxAverageLuminance;
     float minLuminance;
@@ -256,7 +240,7 @@
 /**
  * Test IComposerClient::getPerFrameMetadataKeys_2_3
  */
-TEST_F(GraphicsComposerHidlTest, GetPerFrameMetadataKeys_2_3) {
+TEST_P(GraphicsComposerHidlTest, GetPerFrameMetadataKeys_2_3) {
     std::vector<IComposerClient::PerFrameMetadataKey> keys;
     mComposerClient->getRaw()->getPerFrameMetadataKeys_2_3(
         mPrimaryDisplay, [&](const auto tmpError, const auto outKeys) {
@@ -270,7 +254,7 @@
 /**
  * TestIComposerClient::getReadbackBufferAttributes_2_3
  */
-TEST_F(GraphicsComposerHidlTest, GetReadbackBufferAttributes_2_3) {
+TEST_P(GraphicsComposerHidlTest, GetReadbackBufferAttributes_2_3) {
     Dataspace dataspace;
     PixelFormat pixelFormat;
 
@@ -288,7 +272,7 @@
 /**
  * Test IComposerClient::getClientTargetSupport_2_3
  */
-TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport_2_3) {
+TEST_P(GraphicsComposerHidlTest, GetClientTargetSupport_2_3) {
     std::vector<V2_1::Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
     for (auto config : configs) {
         int32_t width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
@@ -311,7 +295,7 @@
  * Error::BAD_DISPLAY when passed in an invalid display handle
  */
 
-TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport_2_3BadDisplay) {
+TEST_P(GraphicsComposerHidlTest, GetClientTargetSupport_2_3BadDisplay) {
     std::vector<V2_1::Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
     for (auto config : configs) {
         int32_t width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
@@ -333,7 +317,7 @@
 /**
  * Test IComposerClient::getRenderIntents_2_3
  */
-TEST_F(GraphicsComposerHidlTest, GetRenderIntents_2_3) {
+TEST_P(GraphicsComposerHidlTest, GetRenderIntents_2_3) {
     std::vector<ColorMode> modes = mComposerClient->getColorModes_2_3(mPrimaryDisplay);
     for (auto mode : modes) {
         std::vector<RenderIntent> intents =
@@ -363,7 +347,7 @@
  * Test that IComposerClient::getRenderIntents_2_3 returns Error::BAD_DISPLAY when
  * passed an invalid display handle
  */
-TEST_F(GraphicsComposerHidlTest, GetRenderIntents_2_3BadDisplay) {
+TEST_P(GraphicsComposerHidlTest, GetRenderIntents_2_3BadDisplay) {
     std::vector<ColorMode> modes = mComposerClient->getColorModes_2_3(mPrimaryDisplay);
     for (auto mode : modes) {
         mComposerClient->getRaw()->getRenderIntents_2_3(
@@ -378,7 +362,7 @@
  * Test that IComposerClient::getRenderIntents_2_3 returns Error::BAD_PARAMETER when
  * pased either an invalid Color mode or an invalid Render Intent
  */
-TEST_F(GraphicsComposerHidlTest, GetRenderIntents_2_3BadParameter) {
+TEST_P(GraphicsComposerHidlTest, GetRenderIntents_2_3BadParameter) {
     mComposerClient->getRaw()->getRenderIntents_2_3(
         mPrimaryDisplay, static_cast<ColorMode>(-1),
         [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::BAD_PARAMETER, tmpError); });
@@ -387,7 +371,7 @@
 /**
  * IComposerClient::getColorModes_2_3
  */
-TEST_F(GraphicsComposerHidlTest, GetColorModes_2_3) {
+TEST_P(GraphicsComposerHidlTest, GetColorModes_2_3) {
     std::vector<ColorMode> colorModes = mComposerClient->getColorModes_2_3(mPrimaryDisplay);
 
     auto native = std::find(colorModes.cbegin(), colorModes.cend(), ColorMode::NATIVE);
@@ -400,7 +384,7 @@
  * Test that IComposerClient::getColorModes_2_3 returns Error::BAD_DISPLAY when
  * passed an invalid display handle
  */
-TEST_F(GraphicsComposerHidlTest, GetColorMode_2_3BadDisplay) {
+TEST_P(GraphicsComposerHidlTest, GetColorMode_2_3BadDisplay) {
     mComposerClient->getRaw()->getColorModes_2_3(
         mInvalidDisplayId,
         [&](const auto& tmpError, const auto&) { ASSERT_EQ(Error::BAD_DISPLAY, tmpError); });
@@ -409,7 +393,7 @@
 /**
  * IComposerClient::setColorMode_2_3
  */
-TEST_F(GraphicsComposerHidlTest, SetColorMode_2_3) {
+TEST_P(GraphicsComposerHidlTest, SetColorMode_2_3) {
     std::vector<ColorMode> colorModes = mComposerClient->getColorModes_2_3(mPrimaryDisplay);
     for (auto mode : colorModes) {
         std::vector<RenderIntent> intents =
@@ -430,7 +414,7 @@
  * Test that IComposerClient::setColorMode_2_3 returns an Error::BAD_DISPLAY
  * when passed an invalid display handle
  */
-TEST_F(GraphicsComposerHidlTest, SetColorMode_2_3BadDisplay) {
+TEST_P(GraphicsComposerHidlTest, SetColorMode_2_3BadDisplay) {
     Error error = mComposerClient->getRaw()->setColorMode_2_3(mInvalidDisplayId, ColorMode::NATIVE,
                                                               RenderIntent::COLORIMETRIC);
 
@@ -443,7 +427,7 @@
  * Test that IComposerClient::setColorMode_2_3 returns Error::BAD_PARAMETER when
  * passed an invalid Color mode or an invalid render intent
  */
-TEST_F(GraphicsComposerHidlTest, SetColorMode_2_3BadParameter) {
+TEST_P(GraphicsComposerHidlTest, SetColorMode_2_3BadParameter) {
     Error colorModeError = mComposerClient->getRaw()->setColorMode_2_3(
         mPrimaryDisplay, static_cast<ColorMode>(-1), RenderIntent::COLORIMETRIC);
     EXPECT_EQ(Error::BAD_PARAMETER, colorModeError);
@@ -458,7 +442,7 @@
  * TODO Add color to the layer, use matrix to keep only red component,
  * and check.
  */
-TEST_F(GraphicsComposerHidlTest, SetLayerColorTransform) {
+TEST_P(GraphicsComposerHidlTest, SetLayerColorTransform) {
     Layer layer;
     ASSERT_NO_FATAL_FAILURE(layer =
                                 mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
@@ -485,7 +469,7 @@
     }
 }
 
-TEST_F(GraphicsComposerHidlTest, GetDisplayedContentSamplingAttributes) {
+TEST_P(GraphicsComposerHidlTest, GetDisplayedContentSamplingAttributes) {
     int constexpr invalid = -1;
     auto format = static_cast<PixelFormat>(invalid);
     auto dataspace = static_cast<Dataspace>(invalid);
@@ -505,7 +489,7 @@
               static_cast<hidl_bitfield<IComposerClient::FormatColorComponent>>(invalid));
 };
 
-TEST_F(GraphicsComposerHidlTest, SetDisplayedContentSamplingEnabled) {
+TEST_P(GraphicsComposerHidlTest, SetDisplayedContentSamplingEnabled) {
     auto const maxFrames = 10;
     auto const enableAllComponents = 0;
     auto error = mComposerClient->setDisplayedContentSamplingEnabled(
@@ -523,7 +507,7 @@
     EXPECT_EQ(error, Error::NONE);
 }
 
-TEST_F(GraphicsComposerHidlTest, GetDisplayedContentSample) {
+TEST_P(GraphicsComposerHidlTest, GetDisplayedContentSample) {
     int constexpr invalid = -1;
     auto format = static_cast<PixelFormat>(invalid);
     auto dataspace = static_cast<Dataspace>(invalid);
@@ -558,7 +542,7 @@
  * getDisplayCapabilities is required in composer 2.3
  * Test some constraints.
  */
-TEST_F(GraphicsComposerHidlTest, getDisplayCapabilitiesBasic) {
+TEST_P(GraphicsComposerHidlTest, getDisplayCapabilitiesBasic) {
     std::vector<IComposerClient::DisplayCapability> capabilities;
     const auto error = mComposerClient->getDisplayCapabilities(mPrimaryDisplay, &capabilities);
     ASSERT_EQ(Error::NONE, error);
@@ -572,13 +556,13 @@
     EXPECT_EQ(mComposerClient->getDisplayBrightnessSupport(mPrimaryDisplay), hasBrightnessSupport);
 }
 
-TEST_F(GraphicsComposerHidlTest, getDisplayCapabilitiesBadDisplay) {
+TEST_P(GraphicsComposerHidlTest, getDisplayCapabilitiesBadDisplay) {
     std::vector<IComposerClient::DisplayCapability> capabilities;
     const auto error = mComposerClient->getDisplayCapabilities(mInvalidDisplayId, &capabilities);
     EXPECT_EQ(Error::BAD_DISPLAY, error);
 }
 
-TEST_F(GraphicsComposerHidlTest, SetLayerPerFrameMetadataBlobs) {
+TEST_P(GraphicsComposerHidlTest, SetLayerPerFrameMetadataBlobs) {
     Layer layer;
     ASSERT_NO_FATAL_FAILURE(layer =
                                 mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
@@ -604,7 +588,7 @@
 /*
  * Test that if brightness operations are supported, setDisplayBrightness works as expected.
  */
-TEST_F(GraphicsComposerHidlTest, setDisplayBrightness) {
+TEST_P(GraphicsComposerHidlTest, setDisplayBrightness) {
     std::vector<IComposerClient::DisplayCapability> capabilities;
     const auto error = mComposerClient->getDisplayCapabilities(mPrimaryDisplay, &capabilities);
     ASSERT_EQ(Error::NONE, error);
@@ -627,6 +611,16 @@
     EXPECT_EQ(mComposerClient->setDisplayBrightness(mPrimaryDisplay, -2.0f), Error::BAD_PARAMETER);
 }
 
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, GraphicsComposerHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)),
+        android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, GraphicsComposerHidlCommandTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)),
+        android::hardware::PrintInstanceNameToString);
+
 }  // namespace
 }  // namespace vts
 }  // namespace V2_3
@@ -634,12 +628,3 @@
 }  // namespace graphics
 }  // namespace hardware
 }  // namespace android
-
-int main(int argc, char** argv) {
-    using android::hardware::graphics::composer::V2_3::vts::GraphicsComposerHidlEnvironment;
-    ::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance());
-    ::testing::InitGoogleTest(&argc, argv);
-    GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    return status;
-}
diff --git a/graphics/composer/2.4/IComposerCallback.hal b/graphics/composer/2.4/IComposerCallback.hal
index 5c3f8bd..fea24a1 100644
--- a/graphics/composer/2.4/IComposerCallback.hal
+++ b/graphics/composer/2.4/IComposerCallback.hal
@@ -32,4 +32,14 @@
      *        is expected to be called vsyncPeriodNanos nanoseconds after this call.
      */
     oneway onVsync_2_4(Display display, int64_t timestamp, VsyncPeriodNanos vsyncPeriodNanos);
+
+    /**
+     * Notifies the client that the previously reported timing for vsync period change has been
+     * updated. This may occur if the composer missed the deadline for changing the vsync period
+     * or the client submitted a refresh frame too late.
+     *
+     * @param display is the display which vsync period change is in progress
+     * @param updatedTimeline is the new timeline for the vsync period change.
+     */
+    oneway onVsyncPeriodTimingChanged(Display display, VsyncPeriodChangeTimeline updatedTimeline);
 };
diff --git a/graphics/composer/2.4/IComposerClient.hal b/graphics/composer/2.4/IComposerClient.hal
index c2102d5..f23536c 100644
--- a/graphics/composer/2.4/IComposerClient.hal
+++ b/graphics/composer/2.4/IComposerClient.hal
@@ -20,10 +20,23 @@
 import @2.1::Config;
 import @2.1::Display;
 import @2.1::Error;
+import @2.1::IComposerClient;
 import @2.3::IComposerClient;
 
 interface IComposerClient extends @2.3::IComposerClient {
     /**
+     * Display attributes queryable through getDisplayAttribute_2_4.
+     */
+    enum Attribute : @2.1::IComposerClient.Attribute {
+        /**
+         * The configuration group ID (as int32_t) this config is associated to.
+         * Switching between configurations within the same group may be done seamlessly
+         * in some conditions via setActiveConfigWithConstraints.
+         */
+        CONFIG_GROUP = 7,
+    };
+
+    /**
      * Required capabilities which are supported by the display. The
      * particular set of supported capabilities for a given display may be
      * retrieved using getDisplayCapabilities.
@@ -60,6 +73,7 @@
          * (i.e., the vsync period must not change before this time).
          */
         int64_t desiredTimeNanos;
+
         /**
          * If true, requires that the vsync period change must happen seamlessly without
          * a noticeable visual artifact.
@@ -74,7 +88,6 @@
      *
      * @param callback is the IComposerCallback object.
      */
-    @entry
     registerCallback_2_4(IComposerCallback callback);
 
     /**
@@ -99,25 +112,29 @@
     getDisplayConnectionType(Display display) generates (Error error, DisplayConnectionType type);
 
     /**
-     * Provides a list of the vsync periods supported by the display in the given configuration
+     * Returns a display attribute value for a particular display
+     * configuration.
      *
-     * @param display is the display for which the vsync periods are queried.
-     * @param config is the display configuration for which the vsync periods are queried.
-     *
+     * @param display is the display to query.
+     * @param config is the display configuration for which to return
+     *        attribute values.
      * @return error is NONE upon success. Otherwise,
-     *     BAD_DISPLAY when an invalid display handle was passed in.
-     *     BAD_CONFIG when an invalid config handle was passed in.
-     * @return supportedVsyncPeriods is a list of supported vsync periods.
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     *         BAD_CONFIG when config does not name a valid configuration for
+     *                    this display.
+     *         BAD_PARAMETER when attribute is unrecognized.
+     *         UNSUPPORTED when attribute cannot be queried for the config.
+     * @return value is the value of the attribute.
      */
-    getSupportedDisplayVsyncPeriods(Display display, Config config)
-        generates (Error error, vec<VsyncPeriodNanos> supportedVsyncPeriods);
+    getDisplayAttribute_2_4(Display display, Config config, Attribute attribute)
+        generates (Error error, int32_t value);
 
     /**
      * Retrieves which vsync period the display is currently using.
      *
      * If no display configuration is currently active, this function must
      * return BAD_CONFIG. If the vsync period is about to change due to a
-     * setActiveConfigAndVsyncPeriod call, this function must return the current vsync period
+     * setActiveConfigWithConstraints call, this function must return the current vsync period
      * until the change takes place.
      *
      * @param display is the display for which the vsync period is queried.
@@ -131,7 +148,8 @@
 
     /**
      * Sets the active configuration and the refresh rate for this display.
-     * If the config is the same as the current config, only the vsync period shall change.
+     * If the new config shares the same config group as the current config,
+     * only the vsync period shall change.
      * Upon returning, the given display configuration, except vsync period, must be active and
      * remain so until either this function is called again or the display is disconnected.
      * When the display starts to refresh at the new vsync period, onVsync_2_4 callback must be
@@ -139,21 +157,19 @@
      *
      * @param display is the display for which the active config is set.
      * @param config is the new display configuration.
-     * @param vsyncPeriodNanos is the new display vsync period.
      * @param vsyncPeriodChangeConstraints are the constraints required for changing vsync period.
      *
      * @return error is NONE upon success. Otherwise,
      *         BAD_DISPLAY when an invalid display handle was passed in.
      *         BAD_CONFIG when the configuration handle passed in is not valid
      *                    for this display.
-     *         BAD_VSYNC_PERIOD when an invalid vsync period is passed in.
+     *         SEAMLESS_NOT_ALLOWED when seamlessRequired was true but config provided doesn't
+     *                              share the same config group as the current config.
      *         SEAMLESS_NOT_POSSIBLE when seamlessRequired was true but the display cannot achieve
      *                               the vsync period change without a noticeable visual artifact.
-     * @return newVsyncAppliedTime is the time in CLOCK_MONOTONIC when the new display will start to
-     *                             refresh at the new vsync period.
+     * @return timeline is the timeline for the vsync period change.
      */
-    setActiveConfigAndVsyncPeriod(Display display, Config config,
-        VsyncPeriodNanos vsyncPeriodNanos,
+    setActiveConfigWithConstraints(Display display, Config config,
         VsyncPeriodChangeConstraints vsyncPeriodChangeConstraints)
-        generates (Error error, int64_t newVsyncAppliedTime);
+        generates (Error error, VsyncPeriodChangeTimeline timeline);
 };
diff --git a/graphics/composer/2.4/types.hal b/graphics/composer/2.4/types.hal
index b45d7a6..065f024 100644
--- a/graphics/composer/2.4/types.hal
+++ b/graphics/composer/2.4/types.hal
@@ -20,13 +20,36 @@
 
 enum Error : @2.1::Error {
     /**
-     * Invalid vsync period
+     * Seamless cannot be required for configurations that don't share a config group
      */
-    BAD_VSYNC_PERIOD = 9,
+    SEAMLESS_NOT_ALLOWED = 9,
     /**
      * Seamless requirements cannot be met
      */
     SEAMLESS_NOT_POSSIBLE = 10,
 };
 
+/**
+ * Timing for a vsync period change.
+ */
+struct VsyncPeriodChangeTimeline {
+    /**
+     * The time in CLOCK_MONOTONIC when the new display will start to refresh at
+     * the new vsync period.
+     */
+    int64_t newVsyncAppliedTimeNanos;
+
+    /**
+     * Set to true if the client is required to send a frame to be displayed before
+     * the change can take place.
+     */
+    bool refreshRequired;
+
+    /**
+     * The time in CLOCK_MONOTONIC when the client is expected to send the new frame.
+     * Should be ignored if refreshRequired is false.
+     */
+    int64_t refreshTimeNanos;
+};
+
 typedef uint32_t VsyncPeriodNanos;
diff --git a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h
index ddf209b..4160ed9 100644
--- a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h
+++ b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerClient.h
@@ -76,6 +76,13 @@
             ALOGE_IF(!ret.isOk(), "failed to send onVsync_2_4: %s", ret.description().c_str());
         }
 
+        void onVsyncPeriodTimingChanged(Display display,
+                                        const VsyncPeriodChangeTimeline& updatedTimeline) override {
+            auto ret = mCallback->onVsyncPeriodTimingChanged(display, updatedTimeline);
+            ALOGE_IF(!ret.isOk(), "failed to send onVsyncPeriodTimingChanged: %s",
+                     ret.description().c_str());
+        }
+
       protected:
         const sp<IComposerCallback> mCallback;
         V2_1::hal::ComposerResources* const mResources;
@@ -104,13 +111,12 @@
         return Void();
     }
 
-    Return<void> getSupportedDisplayVsyncPeriods(
-            Display display, Config config,
-            IComposerClient::getSupportedDisplayVsyncPeriods_cb hidl_cb) override {
-        std::vector<VsyncPeriodNanos> supportedVsyncPeriods;
-        Error error =
-                mHal->getSupportedDisplayVsyncPeriods(display, config, &supportedVsyncPeriods);
-        hidl_cb(error, supportedVsyncPeriods);
+    Return<void> getDisplayAttribute_2_4(
+            Display display, Config config, IComposerClient::Attribute attribute,
+            IComposerClient::getDisplayAttribute_2_4_cb hidl_cb) override {
+        int32_t value = 0;
+        Error error = mHal->getDisplayAttribute_2_4(display, config, attribute, &value);
+        hidl_cb(error, value);
         return Void();
     }
 
@@ -122,15 +128,14 @@
         return Void();
     }
 
-    Return<void> setActiveConfigAndVsyncPeriod(
-            Display display, Config config, VsyncPeriodNanos vsyncPeriodNanos,
+    Return<void> setActiveConfigWithConstraints(
+            Display display, Config config,
             const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
-            IComposerClient::setActiveConfigAndVsyncPeriod_cb hidl_cb) override {
-        int64_t newVsyncAppliedTime = 0;
-        Error error = mHal->setActiveConfigAndVsyncPeriod(display, config, vsyncPeriodNanos,
-                                                          vsyncPeriodChangeConstraints,
-                                                          &newVsyncAppliedTime);
-        hidl_cb(error, newVsyncAppliedTime);
+            IComposerClient::setActiveConfigWithConstraints_cb hidl_cb) override {
+        VsyncPeriodChangeTimeline timeline = {};
+        Error error = mHal->setActiveConfigWithConstraints(display, config,
+                                                           vsyncPeriodChangeConstraints, &timeline);
+        hidl_cb(error, timeline);
         return Void();
     }
 
diff --git a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h
index 0739f62..89dbe66 100644
--- a/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h
+++ b/graphics/composer/2.4/utils/hal/include/composer-hal/2.4/ComposerHal.h
@@ -47,6 +47,8 @@
         virtual void onVsync(Display display, int64_t timestamp) = 0;
         virtual void onVsync_2_4(Display display, int64_t timestamp,
                                  VsyncPeriodNanos vsyncPeriodNanos) = 0;
+        virtual void onVsyncPeriodTimingChanged(Display display,
+                                                const VsyncPeriodChangeTimeline& timeline) = 0;
     };
 
     virtual void registerEventCallback_2_4(EventCallback_2_4* callback) = 0;
@@ -57,13 +59,14 @@
             Display display, std::vector<IComposerClient::DisplayCapability>* outCapabilities) = 0;
     virtual Error getDisplayConnectionType(Display display,
                                            IComposerClient::DisplayConnectionType* outType) = 0;
-    virtual Error getSupportedDisplayVsyncPeriods(
-            Display display, Config config, std::vector<VsyncPeriodNanos>* outVsyncPeriod) = 0;
+    virtual Error getDisplayAttribute_2_4(Display display, Config config,
+                                          IComposerClient::Attribute attribute,
+                                          int32_t* outValue) = 0;
     virtual Error getDisplayVsyncPeriod(Display display, VsyncPeriodNanos* outVsyncPeriod) = 0;
-    virtual Error setActiveConfigAndVsyncPeriod(
-            Display display, Config config, VsyncPeriodNanos vsyncPeriodNanos,
+    virtual Error setActiveConfigWithConstraints(
+            Display display, Config config,
             const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
-            int64_t* outNewVsyncAppliedTime) = 0;
+            VsyncPeriodChangeTimeline* timeline) = 0;
 };
 
 }  // namespace hal
diff --git a/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h b/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h
index 3420c8c..d59d0d5 100644
--- a/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h
+++ b/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h
@@ -25,6 +25,7 @@
 #include <android/hardware/graphics/composer/2.4/IComposerClient.h>
 #include <composer-hal/2.4/ComposerHal.h>
 #include <composer-passthrough/2.3/HwcHal.h>
+#include <hardware/hwcomposer_defs.h>
 
 namespace android {
 namespace hardware {
@@ -51,14 +52,22 @@
     void registerEventCallback_2_4(hal::ComposerHal::EventCallback_2_4* callback) override {
         mEventCallback_2_4 = callback;
 
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this,
-                                   reinterpret_cast<hwc2_function_pointer_t>(hotplugHook));
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this,
-                                   reinterpret_cast<hwc2_function_pointer_t>(refreshHook));
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this,
-                                   reinterpret_cast<hwc2_function_pointer_t>(vsyncHook));
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC_2_4, this,
-                                   reinterpret_cast<hwc2_function_pointer_t>(vsync_2_4_Hook));
+        BaseType2_1::mDispatch.registerCallback(
+                mDevice, HWC2_CALLBACK_HOTPLUG, this,
+                reinterpret_cast<hwc2_function_pointer_t>(hotplugHook));
+        BaseType2_1::mDispatch.registerCallback(
+                mDevice, HWC2_CALLBACK_REFRESH, this,
+                reinterpret_cast<hwc2_function_pointer_t>(refreshHook));
+        BaseType2_1::mDispatch.registerCallback(
+                mDevice, HWC2_CALLBACK_VSYNC, this,
+                reinterpret_cast<hwc2_function_pointer_t>(vsyncHook));
+        BaseType2_1::mDispatch.registerCallback(
+                mDevice, HWC2_CALLBACK_VSYNC_2_4, this,
+                reinterpret_cast<hwc2_function_pointer_t>(vsync_2_4_Hook));
+
+        BaseType2_1::mDispatch.registerCallback(
+                mDevice, HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED, this,
+                reinterpret_cast<hwc2_function_pointer_t>(vsyncPeriodTimingChangedHook));
     }
 
     void unregisterEventCallback_2_4() override {
@@ -69,10 +78,12 @@
         //  - will never be called afterward
         //
         // which is likely incorrect
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this, nullptr);
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this, nullptr);
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this, nullptr);
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC_2_4, this, nullptr);
+        BaseType2_1::mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this, nullptr);
+        BaseType2_1::mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this, nullptr);
+        BaseType2_1::mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this, nullptr);
+        BaseType2_1::mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC_2_4, this, nullptr);
+        BaseType2_1::mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED,
+                                                this, nullptr);
 
         mEventCallback_2_4 = nullptr;
     }
@@ -106,26 +117,16 @@
         return static_cast<Error>(error);
     }
 
-    Error getSupportedDisplayVsyncPeriods(Display display, Config config,
-                                          std::vector<VsyncPeriodNanos>* outVsyncPeriods) override {
-        if (!mDispatch.getSupportedDisplayVsyncPeriods) {
-            return Error::UNSUPPORTED;
+    Error getDisplayAttribute_2_4(Display display, Config config,
+                                  IComposerClient::Attribute attribute,
+                                  int32_t* outValue) override {
+        int32_t err = BaseType2_1::mDispatch.getDisplayAttribute(
+                mDevice, display, config, static_cast<int32_t>(attribute), outValue);
+        if (err != HWC2_ERROR_NONE && *outValue == -1) {
+            // Convert the error from hwcomposer2 to IComposerClient definition
+            return Error::BAD_PARAMETER;
         }
-
-        uint32_t count = 0;
-        int32_t error = mDispatch.getSupportedDisplayVsyncPeriods(mDevice, display, config, &count,
-                                                                  nullptr);
-        if (error != HWC2_ERROR_NONE) {
-            return static_cast<Error>(error);
-        }
-        outVsyncPeriods->resize(count);
-        error = mDispatch.getSupportedDisplayVsyncPeriods(mDevice, display, config, &count,
-                                                          outVsyncPeriods->data());
-        if (error != HWC2_ERROR_NONE) {
-            *outVsyncPeriods = std::vector<VsyncPeriodNanos>();
-            return static_cast<Error>(error);
-        }
-        return Error::NONE;
+        return static_cast<Error>(err);
     }
 
     Error getDisplayVsyncPeriod(Display display, VsyncPeriodNanos* outVsyncPeriod) override {
@@ -140,11 +141,11 @@
         return Error::NONE;
     }
 
-    Error setActiveConfigAndVsyncPeriod(
-            Display display, Config config, VsyncPeriodNanos vsyncPeriodNanos,
+    Error setActiveConfigWithConstraints(
+            Display display, Config config,
             const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
-            int64_t* outNewVsyncAppliedTime) override {
-        if (!mDispatch.setActiveConfigAndVsyncPeriod) {
+            VsyncPeriodChangeTimeline* timeline) override {
+        if (!mDispatch.setActiveConfigWithConstraints) {
             return Error::UNSUPPORTED;
         }
 
@@ -154,12 +155,15 @@
         vsync_period_change_constraints.seamlessRequired =
                 vsyncPeriodChangeConstraints.seamlessRequired;
 
-        int32_t error = mDispatch.setActiveConfigAndVsyncPeriod(
-                mDevice, display, config, vsyncPeriodNanos, &vsync_period_change_constraints,
-                outNewVsyncAppliedTime);
+        hwc_vsync_period_change_timeline_t out_timeline;
+        int32_t error = mDispatch.setActiveConfigWithConstraints(
+                mDevice, display, config, &vsync_period_change_constraints, &out_timeline);
         if (error != HWC2_ERROR_NONE) {
             return static_cast<Error>(error);
         }
+        timeline->newVsyncAppliedTimeNanos = out_timeline.newVsyncAppliedTimeNanos;
+        timeline->refreshRequired = out_timeline.refreshRequired;
+        timeline->refreshTimeNanos = out_timeline.refreshTimeNanos;
         return Error::NONE;
     }
 
@@ -171,13 +175,10 @@
 
         this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_CONNECTION_TYPE,
                                    &mDispatch.getDisplayConnectionType);
-        this->initOptionalDispatch(HWC2_FUNCTION_REGISTER_CALLBACK, &mDispatch.registerCallback);
-        this->initOptionalDispatch(HWC2_FUNCTION_GET_SUPPORTED_DISPLAY_VSYNC_PERIODS,
-                                   &mDispatch.getSupportedDisplayVsyncPeriods);
         this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_VSYNC_PERIOD,
                                    &mDispatch.getDisplayVsyncPeriod);
-        this->initOptionalDispatch(HWC2_FUNCTION_SET_ACTIVE_CONFIG_AND_VSYNC_PERIOD,
-                                   &mDispatch.setActiveConfigAndVsyncPeriod);
+        this->initOptionalDispatch(HWC2_FUNCTION_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS,
+                                   &mDispatch.setActiveConfigWithConstraints);
         return true;
     }
 
@@ -205,13 +206,22 @@
         hal->mEventCallback_2_4->onVsync_2_4(display, timestamp, vsyncPeriodNanos);
     }
 
+    static void vsyncPeriodTimingChangedHook(hwc2_callback_data_t callbackData,
+                                             hwc2_display_t display,
+                                             hwc_vsync_period_change_timeline_t* updated_timeline) {
+        auto hal = static_cast<HwcHalImpl*>(callbackData);
+        VsyncPeriodChangeTimeline timeline;
+        timeline.newVsyncAppliedTimeNanos = updated_timeline->newVsyncAppliedTimeNanos;
+        timeline.refreshRequired = updated_timeline->refreshRequired;
+        timeline.refreshTimeNanos = updated_timeline->refreshTimeNanos;
+        hal->mEventCallback_2_4->onVsyncPeriodTimingChanged(display, timeline);
+    }
+
   private:
     struct {
         HWC2_PFN_GET_DISPLAY_CONNECTION_TYPE getDisplayConnectionType;
-        HWC2_PFN_REGISTER_CALLBACK registerCallback;
-        HWC2_PFN_GET_SUPPORTED_DISPLAY_VSYNC_PERIODS getSupportedDisplayVsyncPeriods;
         HWC2_PFN_GET_DISPLAY_VSYNC_PERIOD getDisplayVsyncPeriod;
-        HWC2_PFN_SET_ACTIVE_CONFIG_AND_VSYNC_PERIOD setActiveConfigAndVsyncPeriod;
+        HWC2_PFN_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS setActiveConfigWithConstraints;
     } mDispatch = {};
 
     hal::ComposerHal::EventCallback_2_4* mEventCallback_2_4 = nullptr;
diff --git a/graphics/composer/2.4/utils/vts/ComposerVts.cpp b/graphics/composer/2.4/utils/vts/ComposerVts.cpp
index b02a59a..35ac23f 100644
--- a/graphics/composer/2.4/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.4/utils/vts/ComposerVts.cpp
@@ -70,15 +70,18 @@
     return error;
 }
 
-Error ComposerClient::getSupportedDisplayVsyncPeriods(
-        Display display, Config config, std::vector<VsyncPeriodNanos>* outSupportedVsyncPeriods) {
-    Error error = Error::NONE;
-    mClient->getSupportedDisplayVsyncPeriods(
-            display, config, [&](const auto& tmpError, const auto& tmpSupportedVsyncPeriods) {
-                error = tmpError;
-                *outSupportedVsyncPeriods = tmpSupportedVsyncPeriods;
+int32_t ComposerClient::getDisplayAttribute_2_4(
+        android::hardware::graphics::composer::V2_1::Display display,
+        android::hardware::graphics::composer::V2_1::Config config,
+        IComposerClient::Attribute attribute) {
+    int32_t value = 0;
+    mClient->getDisplayAttribute_2_4(
+            display, config, attribute, [&](const auto& tmpError, const auto& tmpValue) {
+                ASSERT_EQ(Error::NONE, tmpError) << "failed to get display attribute";
+                value = tmpValue;
             });
-    return error;
+
+    return value;
 }
 
 Error ComposerClient::getDisplayVsyncPeriod(Display display, VsyncPeriodNanos* outVsyncPeriod) {
@@ -90,17 +93,16 @@
     return error;
 }
 
-Error ComposerClient::setActiveConfigAndVsyncPeriod(
-        Display display, Config config, VsyncPeriodNanos vsyncPeriodNanos,
+Error ComposerClient::setActiveConfigWithConstraints(
+        Display display, Config config,
         const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
-        int64_t* outNewVsyncAppliedTime) {
+        VsyncPeriodChangeTimeline* timeline) {
     Error error = Error::NONE;
-    mClient->setActiveConfigAndVsyncPeriod(
-            display, config, vsyncPeriodNanos, vsyncPeriodChangeConstraints,
-            [&](const auto& tmpError, const auto& tmpNewVsyncAppliedTime) {
-                error = tmpError;
-                *outNewVsyncAppliedTime = tmpNewVsyncAppliedTime;
-            });
+    mClient->setActiveConfigWithConstraints(display, config, vsyncPeriodChangeConstraints,
+                                            [&](const auto& tmpError, const auto& tmpTimeline) {
+                                                error = tmpError;
+                                                *timeline = tmpTimeline;
+                                            });
     return error;
 }
 
diff --git a/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h
index 5db3e16..83e74ed 100644
--- a/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h
+++ b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h
@@ -74,15 +74,15 @@
     Error getDisplayConnectionType(Display display,
                                    IComposerClient::DisplayConnectionType* outType);
 
-    Error getSupportedDisplayVsyncPeriods(Display display, Config config,
-                                          std::vector<VsyncPeriodNanos>* outSupportedVsyncPeriods);
+    int32_t getDisplayAttribute_2_4(Display display, Config config,
+                                    IComposerClient::Attribute attribute);
 
     Error getDisplayVsyncPeriod(Display display, VsyncPeriodNanos* outVsyncPeriods);
 
-    Error setActiveConfigAndVsyncPeriod(
-            Display display, Config config, VsyncPeriodNanos vsyncPeriodNanos,
+    Error setActiveConfigWithConstraints(
+            Display display, Config config,
             const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
-            int64_t* outNewVsyncAppliedTime);
+            VsyncPeriodChangeTimeline* timeline);
 
   private:
     const sp<IComposerClient> mClient;
diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index 2c87666..f038f55 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -114,7 +114,7 @@
 
     void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
 
-    void Test_setActiveConfigAndVsyncPeriod(
+    void Test_setActiveConfigWithConstraints(
             const IComposerClient::VsyncPeriodChangeConstraints& constraints);
 
     std::unique_ptr<Composer> mComposer;
@@ -194,42 +194,28 @@
     }
 }
 
-TEST_P(GraphicsComposerHidlTest, getSupportedDisplayVsyncPeriods_BadDisplay) {
-    std::vector<VsyncPeriodNanos> supportedVsyncPeriods;
-    EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->getSupportedDisplayVsyncPeriods(
-                                          mInvalidDisplayId, Config(0), &supportedVsyncPeriods));
-}
+TEST_P(GraphicsComposerHidlTest, GetDisplayAttribute_2_4) {
+    std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
+    for (auto config : configs) {
+        const std::array<IComposerClient::Attribute, 4> requiredAttributes = {{
+                IComposerClient::Attribute::WIDTH,
+                IComposerClient::Attribute::HEIGHT,
+                IComposerClient::Attribute::VSYNC_PERIOD,
+                IComposerClient::Attribute::CONFIG_GROUP,
+        }};
+        for (auto attribute : requiredAttributes) {
+            mComposerClient->getDisplayAttribute_2_4(mPrimaryDisplay, config, attribute);
+        }
 
-TEST_P(GraphicsComposerHidlTest, getSupportedDisplayVsyncPeriods_BadConfig) {
-    for (Display display : mComposerCallback->getDisplays()) {
-        Config invalidConfigId = GetInvalidConfigId(display);
-        std::vector<VsyncPeriodNanos> supportedVsyncPeriods;
-        EXPECT_EQ(Error::BAD_CONFIG, mComposerClient->getSupportedDisplayVsyncPeriods(
-                                             display, invalidConfigId, &supportedVsyncPeriods));
-    }
-}
-
-TEST_P(GraphicsComposerHidlTest, getSupportedDisplayVsyncPeriods) {
-    for (Display display : mComposerCallback->getDisplays()) {
-        for (Config config : mComposerClient->getDisplayConfigs(display)) {
-            std::vector<VsyncPeriodNanos> supportedVsyncPeriods;
-
-            // Get the default vsync period from the config
-            VsyncPeriodNanos defaultVsyncPeiord = mComposerClient->getDisplayAttribute(
-                    display, config, IComposerClient::Attribute::VSYNC_PERIOD);
-            // Get all supported vsync periods for this config
-            EXPECT_EQ(Error::NONE, mComposerClient->getSupportedDisplayVsyncPeriods(
-                                           display, config, &supportedVsyncPeriods));
-            // Default vsync period must be present in the list
-            EXPECT_NE(std::find(supportedVsyncPeriods.begin(), supportedVsyncPeriods.end(),
-                                defaultVsyncPeiord),
-                      supportedVsyncPeriods.end());
-
-            // Each vsync period must be unique
-            std::unordered_set<VsyncPeriodNanos> vsyncPeriodSet;
-            for (VsyncPeriodNanos vsyncPeriodNanos : supportedVsyncPeriods) {
-                EXPECT_TRUE(vsyncPeriodSet.insert(vsyncPeriodNanos).second);
-            }
+        const std::array<IComposerClient::Attribute, 2> optionalAttributes = {{
+                IComposerClient::Attribute::DPI_X,
+                IComposerClient::Attribute::DPI_Y,
+        }};
+        for (auto attribute : optionalAttributes) {
+            mComposerClient->getRaw()->getDisplayAttribute_2_4(
+                    mPrimaryDisplay, config, attribute, [&](const auto& tmpError, const auto&) {
+                        EXPECT_TRUE(tmpError == Error::NONE || tmpError == Error::UNSUPPORTED);
+                    });
         }
     }
 }
@@ -240,20 +226,40 @@
               mComposerClient->getDisplayVsyncPeriod(mInvalidDisplayId, &vsyncPeriodNanos));
 }
 
-TEST_P(GraphicsComposerHidlTest, setActiveConfigAndVsyncPeriod_BadDisplay) {
-    int64_t newVsyncAppliedTime;
+TEST_P(GraphicsComposerHidlTest, getDisplayVsyncPeriod) {
+    for (Display display : mComposerCallback->getDisplays()) {
+        for (Config config : mComposerClient->getDisplayConfigs(display)) {
+            mComposerClient->setActiveConfig(display, config);
+
+            VsyncPeriodNanos vsyncPeriodNanos;
+            VsyncPeriodNanos expectedvsyncPeriodNanos = mComposerClient->getDisplayAttribute_2_4(
+                    display, config, IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD);
+            int retryCount = 100;
+            do {
+                std::this_thread::sleep_for(10ms);
+                EXPECT_EQ(Error::NONE,
+                          mComposerClient->getDisplayVsyncPeriod(display, &vsyncPeriodNanos));
+                --retryCount;
+            } while (retryCount > 0);
+
+            EXPECT_EQ(vsyncPeriodNanos, expectedvsyncPeriodNanos);
+        }
+    }
+}
+
+TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints_BadDisplay) {
+    VsyncPeriodChangeTimeline timeline;
     IComposerClient::VsyncPeriodChangeConstraints constraints;
 
     constraints.seamlessRequired = false;
     constraints.desiredTimeNanos = systemTime();
 
-    EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->setActiveConfigAndVsyncPeriod(
-                                          mInvalidDisplayId, Config(0), VsyncPeriodNanos(0),
-                                          constraints, &newVsyncAppliedTime));
+    EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->setActiveConfigWithConstraints(
+                                          mInvalidDisplayId, Config(0), constraints, &timeline));
 }
 
-TEST_P(GraphicsComposerHidlTest, setActiveConfigAndVsyncPeriod_BadConfig) {
-    int64_t newVsyncAppliedTime;
+TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints_BadConfig) {
+    VsyncPeriodChangeTimeline timeline;
     IComposerClient::VsyncPeriodChangeConstraints constraints;
 
     constraints.seamlessRequired = false;
@@ -261,93 +267,114 @@
 
     for (Display display : mComposerCallback->getDisplays()) {
         Config invalidConfigId = GetInvalidConfigId(display);
-        EXPECT_EQ(Error::BAD_CONFIG, mComposerClient->setActiveConfigAndVsyncPeriod(
-                                             display, invalidConfigId, VsyncPeriodNanos(0),
-                                             constraints, &newVsyncAppliedTime));
+        EXPECT_EQ(Error::BAD_CONFIG, mComposerClient->setActiveConfigWithConstraints(
+                                             display, invalidConfigId, constraints, &timeline));
     }
 }
 
-TEST_P(GraphicsComposerHidlTest, setActiveConfigAndVsyncPeriod_BadVsyncPeriod) {
-    int64_t newVsyncAppliedTime;
+TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints_SeamlessNotAllowed) {
+    VsyncPeriodChangeTimeline timeline;
     IComposerClient::VsyncPeriodChangeConstraints constraints;
 
-    constraints.seamlessRequired = false;
+    constraints.seamlessRequired = true;
     constraints.desiredTimeNanos = systemTime();
 
     for (Display display : mComposerCallback->getDisplays()) {
         for (Config config : mComposerClient->getDisplayConfigs(display)) {
-            EXPECT_EQ(Error::BAD_VSYNC_PERIOD, mComposerClient->setActiveConfigAndVsyncPeriod(
-                                                       display, config, VsyncPeriodNanos(0),
-                                                       constraints, &newVsyncAppliedTime));
-        }
-    }
-}
+            int32_t configGroup = mComposerClient->getDisplayAttribute_2_4(
+                    display, config, IComposerClient::IComposerClient::Attribute::CONFIG_GROUP);
 
-void GraphicsComposerHidlTest::Test_setActiveConfigAndVsyncPeriod(
-        const IComposerClient::VsyncPeriodChangeConstraints& constraints) {
-    int64_t newVsyncAppliedTime;
-
-    for (Display display : mComposerCallback->getDisplays()) {
-        for (Config config : mComposerClient->getDisplayConfigs(display)) {
-            std::vector<VsyncPeriodNanos> supportedVsyncPeriods;
-
-            EXPECT_EQ(Error::NONE, mComposerClient->getSupportedDisplayVsyncPeriods(
-                                           display, config, &supportedVsyncPeriods));
-            for (VsyncPeriodNanos newVsyncPeriod : supportedVsyncPeriods) {
-                VsyncPeriodNanos vsyncPeriodNanos;
-                EXPECT_EQ(Error::NONE,
-                          mComposerClient->getDisplayVsyncPeriod(display, &vsyncPeriodNanos));
-
-                if (vsyncPeriodNanos == newVsyncPeriod) {
-                    continue;
+            for (Config otherConfig : mComposerClient->getDisplayConfigs(display)) {
+                int32_t otherConfigGroup = mComposerClient->getDisplayAttribute_2_4(
+                        display, otherConfig,
+                        IComposerClient::IComposerClient::Attribute::CONFIG_GROUP);
+                if (configGroup != otherConfigGroup) {
+                    mComposerClient->setActiveConfig(display, config);
+                    EXPECT_EQ(Error::SEAMLESS_NOT_ALLOWED,
+                              mComposerClient->setActiveConfigWithConstraints(
+                                      display, otherConfig, constraints, &timeline));
                 }
-
-                EXPECT_EQ(Error::NONE, mComposerClient->setActiveConfigAndVsyncPeriod(
-                                               display, config, newVsyncPeriod, constraints,
-                                               &newVsyncAppliedTime));
-
-                EXPECT_TRUE(newVsyncAppliedTime >= constraints.desiredTimeNanos);
-
-                // Refresh rate should change within a reasonable time
-                constexpr nsecs_t kReasonableTimeForChange = 1'000'000'000;  // 1 second
-                EXPECT_TRUE(newVsyncAppliedTime - constraints.desiredTimeNanos <=
-                            kReasonableTimeForChange);
-
-                while (systemTime() <= newVsyncAppliedTime) {
-                    EXPECT_EQ(Error::NONE,
-                              mComposerClient->getDisplayVsyncPeriod(display, &vsyncPeriodNanos));
-                    if (systemTime() <= constraints.desiredTimeNanos) {
-                        EXPECT_NE(vsyncPeriodNanos, newVsyncPeriod);
-                    }
-
-                    if (vsyncPeriodNanos == newVsyncPeriod) {
-                        break;
-                    }
-                    std::this_thread::sleep_for(10ms);
-                }
-                EXPECT_EQ(Error::NONE,
-                          mComposerClient->getDisplayVsyncPeriod(display, &vsyncPeriodNanos));
-                EXPECT_EQ(vsyncPeriodNanos, newVsyncPeriod);
             }
         }
     }
 }
 
-TEST_P(GraphicsComposerHidlTest, setActiveConfigAndVsyncPeriod) {
+void GraphicsComposerHidlTest::Test_setActiveConfigWithConstraints(
+        const IComposerClient::VsyncPeriodChangeConstraints& constraints) {
+    VsyncPeriodChangeTimeline timeline = {};
+
+    for (Display display : mComposerCallback->getDisplays()) {
+        for (Config config : mComposerClient->getDisplayConfigs(display)) {
+            mComposerClient->setActiveConfig(display, config);
+
+            int32_t configVsyncPeriod = mComposerClient->getDisplayAttribute_2_4(
+                    display, config, IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD);
+            for (Config otherConfig : mComposerClient->getDisplayConfigs(display)) {
+                if (config == otherConfig) {
+                    continue;
+                }
+
+                int32_t otherVsyncPeriod = mComposerClient->getDisplayAttribute_2_4(
+                        display, otherConfig,
+                        IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD);
+
+                if (configVsyncPeriod == otherVsyncPeriod) {
+                    continue;
+                }
+
+                EXPECT_EQ(Error::NONE, mComposerClient->setActiveConfigWithConstraints(
+                                               display, otherConfig, constraints, &timeline));
+
+                if (timeline.refreshRequired) {
+                    // TODO(b/143775556): handle this case;
+                    continue;
+                }
+
+                EXPECT_TRUE(timeline.newVsyncAppliedTimeNanos >= constraints.desiredTimeNanos);
+
+                // Refresh rate should change within a reasonable time
+                constexpr nsecs_t kReasonableTimeForChange = 1'000'000'000;  // 1 second
+                EXPECT_TRUE(timeline.newVsyncAppliedTimeNanos - constraints.desiredTimeNanos <=
+                            kReasonableTimeForChange);
+
+                while (systemTime() <= timeline.newVsyncAppliedTimeNanos) {
+                    VsyncPeriodNanos vsyncPeriodNanos;
+                    EXPECT_EQ(Error::NONE,
+                              mComposerClient->getDisplayVsyncPeriod(display, &vsyncPeriodNanos));
+
+                    if (systemTime() <= constraints.desiredTimeNanos) {
+                        EXPECT_NE(vsyncPeriodNanos, otherVsyncPeriod);
+                    }
+
+                    if (vsyncPeriodNanos == otherVsyncPeriod) {
+                        break;
+                    }
+                    std::this_thread::sleep_for(10ms);
+                }
+                VsyncPeriodNanos vsyncPeriodNanos;
+                EXPECT_EQ(Error::NONE,
+                          mComposerClient->getDisplayVsyncPeriod(display, &vsyncPeriodNanos));
+                EXPECT_EQ(vsyncPeriodNanos, otherVsyncPeriod);
+            }
+        }
+    }
+}
+
+TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints) {
     IComposerClient::VsyncPeriodChangeConstraints constraints;
 
     constraints.seamlessRequired = false;
     constraints.desiredTimeNanos = systemTime();
-    Test_setActiveConfigAndVsyncPeriod(constraints);
+    Test_setActiveConfigWithConstraints(constraints);
 }
 
-TEST_P(GraphicsComposerHidlTest, setActiveConfigAndVsyncPeriod_delayed) {
+TEST_P(GraphicsComposerHidlTest, setActiveConfigWithConstraints_delayed) {
     IComposerClient::VsyncPeriodChangeConstraints constraints;
 
     constexpr auto kDelayForChange = 300ms;
     constraints.seamlessRequired = false;
     constraints.desiredTimeNanos = systemTime() + kDelayForChange.count();
-    Test_setActiveConfigAndVsyncPeriod(constraints);
+    Test_setActiveConfigWithConstraints(constraints);
 }
 
 INSTANTIATE_TEST_SUITE_P(
diff --git a/graphics/mapper/2.0/utils/vts/MapperVts.cpp b/graphics/mapper/2.0/utils/vts/MapperVts.cpp
index d08ac56..d4e4dde 100644
--- a/graphics/mapper/2.0/utils/vts/MapperVts.cpp
+++ b/graphics/mapper/2.0/utils/vts/MapperVts.cpp
@@ -16,8 +16,6 @@
 
 #include <mapper-vts/2.0/MapperVts.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-
 namespace android {
 namespace hardware {
 namespace graphics {
@@ -30,10 +28,10 @@
 }
 
 void Gralloc::init(const std::string& allocatorServiceName, const std::string& mapperServiceName) {
-    mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>(allocatorServiceName);
+    mAllocator = IAllocator::getService(allocatorServiceName);
     ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
 
-    mMapper = ::testing::VtsHalHidlTargetTestBase::getService<IMapper>(mapperServiceName);
+    mMapper = IMapper::getService(mapperServiceName);
     ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service";
     ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
 }
diff --git a/graphics/mapper/2.0/utils/vts/include/mapper-vts/2.0/MapperVts.h b/graphics/mapper/2.0/utils/vts/include/mapper-vts/2.0/MapperVts.h
index 6c2c9a6..fc8a102 100644
--- a/graphics/mapper/2.0/utils/vts/include/mapper-vts/2.0/MapperVts.h
+++ b/graphics/mapper/2.0/utils/vts/include/mapper-vts/2.0/MapperVts.h
@@ -22,6 +22,7 @@
 
 #include <android/hardware/graphics/allocator/2.0/IAllocator.h>
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <gtest/gtest.h>
 #include <utils/StrongPointer.h>
 
 namespace android {
diff --git a/graphics/mapper/2.0/vts/functional/Android.bp b/graphics/mapper/2.0/vts/functional/Android.bp
index 853c2a3..a055b61 100644
--- a/graphics/mapper/2.0/vts/functional/Android.bp
+++ b/graphics/mapper/2.0/vts/functional/Android.bp
@@ -24,5 +24,5 @@
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.0-vts",
     ],
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
index 5ec0af2..b079a4b 100644
--- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
+++ b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
@@ -20,8 +20,10 @@
 #include <thread>
 #include <vector>
 
-#include <VtsHalHidlTargetTestBase.h>
 #include <android-base/logging.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 #include <mapper-vts/2.0/MapperVts.h>
 
 namespace android {
@@ -35,28 +37,12 @@
 using android::hardware::graphics::common::V1_0::BufferUsage;
 using android::hardware::graphics::common::V1_0::PixelFormat;
 
-// Test environment for graphics.mapper.
-class GraphicsMapperHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static GraphicsMapperHidlEnvironment* Instance() {
-        static GraphicsMapperHidlEnvironment* instance = new GraphicsMapperHidlEnvironment;
-        return instance;
-    }
-
-    virtual void registerTestServices() override {
-        registerTestService<IAllocator>();
-        registerTestService<IMapper>();
-    }
-};
-
-class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-   protected:
+class GraphicsMapperHidlTest
+    : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
+  protected:
     void SetUp() override {
-        ASSERT_NO_FATAL_FAILURE(
-            mGralloc = std::make_unique<Gralloc>(
-                GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>(),
-                GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>()));
+        ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>(std::get<0>(GetParam()),
+                                                                     std::get<1>(GetParam())));
 
         mDummyDescriptorInfo.width = 64;
         mDummyDescriptorInfo.height = 64;
@@ -75,14 +61,14 @@
 /**
  * Test IAllocator::dumpDebugInfo by calling it.
  */
-TEST_F(GraphicsMapperHidlTest, AllocatorDumpDebugInfo) {
+TEST_P(GraphicsMapperHidlTest, AllocatorDumpDebugInfo) {
     mGralloc->dumpDebugInfo();
 }
 
 /**
  * Test IAllocator::allocate with valid buffer descriptors.
  */
-TEST_F(GraphicsMapperHidlTest, AllocatorAllocate) {
+TEST_P(GraphicsMapperHidlTest, AllocatorAllocate) {
     BufferDescriptor descriptor;
     ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
 
@@ -105,7 +91,7 @@
 /**
  * Test IAllocator::allocate with invalid buffer descriptors.
  */
-TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNegative) {
+TEST_P(GraphicsMapperHidlTest, AllocatorAllocateNegative) {
     // this assumes any valid descriptor is non-empty
     BufferDescriptor descriptor;
     mGralloc->getAllocator()->allocate(descriptor, 1,
@@ -117,7 +103,7 @@
 /**
  * Test IAllocator::allocate does not leak.
  */
-TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNoLeak) {
+TEST_P(GraphicsMapperHidlTest, AllocatorAllocateNoLeak) {
     auto info = mDummyDescriptorInfo;
     info.width = 1024;
     info.height = 1024;
@@ -131,7 +117,7 @@
 /**
  * Test that IAllocator::allocate is thread-safe.
  */
-TEST_F(GraphicsMapperHidlTest, AllocatorAllocateThreaded) {
+TEST_P(GraphicsMapperHidlTest, AllocatorAllocateThreaded) {
     BufferDescriptor descriptor;
     ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
 
@@ -161,14 +147,14 @@
 /**
  * Test IMapper::createDescriptor with valid descriptor info.
  */
-TEST_F(GraphicsMapperHidlTest, CreateDescriptorBasic) {
+TEST_P(GraphicsMapperHidlTest, CreateDescriptorBasic) {
     ASSERT_NO_FATAL_FAILURE(mGralloc->createDescriptor(mDummyDescriptorInfo));
 }
 
 /**
  * Test IMapper::createDescriptor with invalid descriptor info.
  */
-TEST_F(GraphicsMapperHidlTest, CreateDescriptorNegative) {
+TEST_P(GraphicsMapperHidlTest, CreateDescriptorNegative) {
     auto info = mDummyDescriptorInfo;
     info.width = 0;
     mGralloc->getMapper()->createDescriptor(info, [&](const auto& tmpError, const auto&) {
@@ -179,7 +165,7 @@
 /**
  * Test IMapper::importBuffer and IMapper::freeBuffer with allocated buffers.
  */
-TEST_F(GraphicsMapperHidlTest, ImportFreeBufferBasic) {
+TEST_P(GraphicsMapperHidlTest, ImportFreeBufferBasic) {
     const native_handle_t* bufferHandle;
     ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
     ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle));
@@ -188,7 +174,7 @@
 /**
  * Test IMapper::importBuffer and IMapper::freeBuffer with cloned buffers.
  */
-TEST_F(GraphicsMapperHidlTest, ImportFreeBufferClone) {
+TEST_P(GraphicsMapperHidlTest, ImportFreeBufferClone) {
     const native_handle_t* clonedBufferHandle;
     ASSERT_NO_FATAL_FAILURE(clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
 
@@ -206,7 +192,7 @@
 /**
  * Test IMapper::importBuffer and IMapper::freeBuffer cross mapper instances.
  */
-TEST_F(GraphicsMapperHidlTest, ImportFreeBufferSingleton) {
+TEST_P(GraphicsMapperHidlTest, ImportFreeBufferSingleton) {
     const native_handle_t* rawHandle;
     ASSERT_NO_FATAL_FAILURE(rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
 
@@ -218,10 +204,8 @@
 
     // free the imported handle with another mapper
     std::unique_ptr<Gralloc> anotherGralloc;
-    ASSERT_NO_FATAL_FAILURE(
-        anotherGralloc = std::make_unique<Gralloc>(
-            GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>(),
-            GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>()));
+    ASSERT_NO_FATAL_FAILURE(anotherGralloc = std::make_unique<Gralloc>(std::get<0>(GetParam()),
+                                                                       std::get<1>(GetParam())));
     Error error = mGralloc->getMapper()->freeBuffer(importedHandle);
     ASSERT_EQ(Error::NONE, error);
 
@@ -231,7 +215,7 @@
 /**
  * Test IMapper::importBuffer and IMapper::freeBuffer do not leak.
  */
-TEST_F(GraphicsMapperHidlTest, ImportFreeBufferNoLeak) {
+TEST_P(GraphicsMapperHidlTest, ImportFreeBufferNoLeak) {
     auto info = mDummyDescriptorInfo;
     info.width = 1024;
     info.height = 1024;
@@ -245,7 +229,7 @@
 /**
  * Test IMapper::importBuffer with invalid buffers.
  */
-TEST_F(GraphicsMapperHidlTest, ImportBufferNegative) {
+TEST_P(GraphicsMapperHidlTest, ImportBufferNegative) {
     native_handle_t* invalidHandle = nullptr;
     mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError, const auto&) {
         EXPECT_EQ(Error::BAD_BUFFER, tmpError)
@@ -263,7 +247,7 @@
 /**
  * Test IMapper::freeBuffer with invalid buffers.
  */
-TEST_F(GraphicsMapperHidlTest, FreeBufferNegative) {
+TEST_P(GraphicsMapperHidlTest, FreeBufferNegative) {
     native_handle_t* invalidHandle = nullptr;
     Error error = mGralloc->getMapper()->freeBuffer(invalidHandle);
     EXPECT_EQ(Error::BAD_BUFFER, error) << "freeBuffer with nullptr did not fail with BAD_BUFFER";
@@ -286,7 +270,7 @@
 /**
  * Test IMapper::lock and IMapper::unlock.
  */
-TEST_F(GraphicsMapperHidlTest, LockUnlockBasic) {
+TEST_P(GraphicsMapperHidlTest, LockUnlockBasic) {
     const auto& info = mDummyDescriptorInfo;
 
     const native_handle_t* bufferHandle;
@@ -332,7 +316,7 @@
  * Test IMapper::lockYCbCr.  This locks a YV12 buffer, and makes sure we can
  * write to and read from it.
  */
-TEST_F(GraphicsMapperHidlTest, LockYCbCrBasic) {
+TEST_P(GraphicsMapperHidlTest, LockYCbCrBasic) {
     auto info = mDummyDescriptorInfo;
     info.format = PixelFormat::YV12;
 
@@ -391,7 +375,7 @@
 /**
  * Test IMapper::unlock with invalid buffers.
  */
-TEST_F(GraphicsMapperHidlTest, UnlockNegative) {
+TEST_P(GraphicsMapperHidlTest, UnlockNegative) {
     native_handle_t* invalidHandle = nullptr;
     mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
         EXPECT_EQ(Error::BAD_BUFFER, tmpError)
@@ -426,6 +410,14 @@
 #endif
 }
 
+INSTANTIATE_TEST_CASE_P(
+        PerInstance, GraphicsMapperHidlTest,
+        testing::Combine(
+                testing::ValuesIn(
+                        android::hardware::getAllHalInstanceNames(IAllocator::descriptor)),
+                testing::ValuesIn(android::hardware::getAllHalInstanceNames(IMapper::descriptor))),
+        android::hardware::PrintInstanceTupleNameToString<>);
+
 }  // namespace
 }  // namespace vts
 }  // namespace V2_0
@@ -433,13 +425,3 @@
 }  // namespace graphics
 }  // namespace hardware
 }  // namespace android
-
-int main(int argc, char** argv) {
-    using android::hardware::graphics::mapper::V2_0::vts::GraphicsMapperHidlEnvironment;
-    ::testing::AddGlobalTestEnvironment(GraphicsMapperHidlEnvironment::Instance());
-    ::testing::InitGoogleTest(&argc, argv);
-    GraphicsMapperHidlEnvironment::Instance()->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    LOG(INFO) << "Test result = " << status;
-    return status;
-}
diff --git a/graphics/mapper/2.1/utils/vts/Android.bp b/graphics/mapper/2.1/utils/vts/Android.bp
index ca02aad..abbe50a 100644
--- a/graphics/mapper/2.1/utils/vts/Android.bp
+++ b/graphics/mapper/2.1/utils/vts/Android.bp
@@ -16,14 +16,13 @@
 
 cc_library_static {
     name: "android.hardware.graphics.mapper@2.1-vts",
-    defaults: ["hidl_defaults"],
+    defaults: ["hidl_defaults", "VtsHalTargetTestDefaults"],
     srcs: ["MapperVts.cpp"],
     cflags: [
         "-O0",
         "-g",
     ],
     static_libs: [
-        "VtsHalHidlTargetTestBase",
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.0-vts",
diff --git a/graphics/mapper/2.1/utils/vts/MapperVts.cpp b/graphics/mapper/2.1/utils/vts/MapperVts.cpp
index 36f9cbb..239de74 100644
--- a/graphics/mapper/2.1/utils/vts/MapperVts.cpp
+++ b/graphics/mapper/2.1/utils/vts/MapperVts.cpp
@@ -16,8 +16,6 @@
 
 #include <mapper-vts/2.1/MapperVts.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-
 namespace android {
 namespace hardware {
 namespace graphics {
diff --git a/graphics/mapper/2.1/vts/functional/Android.bp b/graphics/mapper/2.1/vts/functional/Android.bp
index afd8e7f..bb76c74 100644
--- a/graphics/mapper/2.1/vts/functional/Android.bp
+++ b/graphics/mapper/2.1/vts/functional/Android.bp
@@ -26,5 +26,5 @@
         "android.hardware.graphics.mapper@2.0-vts",
         "android.hardware.graphics.mapper@2.1-vts",
     ],
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
index 5e7cf93..1185945 100644
--- a/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
+++ b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
@@ -16,9 +16,11 @@
 
 #define LOG_TAG "VtsHalGraphicsMapperV2_1TargetTest"
 
-#include <VtsHalHidlTargetTestBase.h>
 #include <android-base/logging.h>
 #include <android/hardware/graphics/mapper/2.1/IMapper.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 #include <mapper-vts/2.1/MapperVts.h>
 
 namespace android {
@@ -34,28 +36,12 @@
 using android::hardware::graphics::common::V1_1::PixelFormat;
 using V2_0::Error;
 
-// Test environment for graphics.mapper.
-class GraphicsMapperHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static GraphicsMapperHidlEnvironment* Instance() {
-        static GraphicsMapperHidlEnvironment* instance = new GraphicsMapperHidlEnvironment;
-        return instance;
-    }
-
-    virtual void registerTestServices() override {
-        registerTestService<IAllocator>();
-        registerTestService<IMapper>();
-    }
-};
-
-class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-   protected:
+class GraphicsMapperHidlTest
+    : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
+  protected:
     void SetUp() override {
-        ASSERT_NO_FATAL_FAILURE(
-            mGralloc = std::make_unique<Gralloc>(
-                GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>(),
-                GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>()));
+        ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>(std::get<0>(GetParam()),
+                                                                     std::get<1>(GetParam())));
 
         mDummyDescriptorInfo.width = 64;
         mDummyDescriptorInfo.height = 64;
@@ -74,7 +60,7 @@
 /**
  * Test that IMapper::validateBufferSize works.
  */
-TEST_F(GraphicsMapperHidlTest, ValidateBufferSizeBasic) {
+TEST_P(GraphicsMapperHidlTest, ValidateBufferSizeBasic) {
     const native_handle_t* bufferHandle;
     uint32_t stride;
     ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true, &stride));
@@ -87,7 +73,7 @@
 /**
  * Test IMapper::validateBufferSize with invalid buffers.
  */
-TEST_F(GraphicsMapperHidlTest, ValidateBufferSizeBadBuffer) {
+TEST_P(GraphicsMapperHidlTest, ValidateBufferSizeBadBuffer) {
     native_handle_t* invalidHandle = nullptr;
     Error ret = mGralloc->getMapper()->validateBufferSize(invalidHandle, mDummyDescriptorInfo,
                                                           mDummyDescriptorInfo.width);
@@ -114,7 +100,7 @@
 /**
  * Test IMapper::validateBufferSize with invalid descriptor and/or stride.
  */
-TEST_F(GraphicsMapperHidlTest, ValidateBufferSizeBadValue) {
+TEST_P(GraphicsMapperHidlTest, ValidateBufferSizeBadValue) {
     auto info = mDummyDescriptorInfo;
     info.width = 1024;
     info.height = 1024;
@@ -161,7 +147,7 @@
 /**
  * Test IMapper::getTransportSize.
  */
-TEST_F(GraphicsMapperHidlTest, GetTransportSizeBasic) {
+TEST_P(GraphicsMapperHidlTest, GetTransportSizeBasic) {
     const native_handle_t* bufferHandle;
     uint32_t numFds;
     uint32_t numInts;
@@ -173,7 +159,7 @@
 /**
  * Test IMapper::getTransportSize with invalid buffers.
  */
-TEST_F(GraphicsMapperHidlTest, GetTransportSizeBadBuffer) {
+TEST_P(GraphicsMapperHidlTest, GetTransportSizeBadBuffer) {
     native_handle_t* invalidHandle = nullptr;
     mGralloc->getMapper()->getTransportSize(
         invalidHandle, [&](const auto& tmpError, const auto&, const auto&) {
@@ -203,14 +189,14 @@
 /**
  * Test IMapper::createDescriptor with valid descriptor info.
  */
-TEST_F(GraphicsMapperHidlTest, CreateDescriptor_2_1Basic) {
+TEST_P(GraphicsMapperHidlTest, CreateDescriptor_2_1Basic) {
     ASSERT_NO_FATAL_FAILURE(mGralloc->createDescriptor(mDummyDescriptorInfo));
 }
 
 /**
  * Test IMapper::createDescriptor with invalid descriptor info.
  */
-TEST_F(GraphicsMapperHidlTest, CreateDescriptor_2_1Negative) {
+TEST_P(GraphicsMapperHidlTest, CreateDescriptor_2_1Negative) {
     auto info = mDummyDescriptorInfo;
     info.width = 0;
     mGralloc->getMapper()->createDescriptor_2_1(info, [&](const auto& tmpError, const auto&) {
@@ -218,22 +204,18 @@
     });
 }
 
+INSTANTIATE_TEST_CASE_P(
+        PerInstance, GraphicsMapperHidlTest,
+        testing::Combine(
+                testing::ValuesIn(
+                        android::hardware::getAllHalInstanceNames(IAllocator::descriptor)),
+                testing::ValuesIn(android::hardware::getAllHalInstanceNames(IMapper::descriptor))),
+        android::hardware::PrintInstanceTupleNameToString<>);
+
 }  // namespace
 }  // namespace vts
 }  // namespace V2_1
 }  // namespace mapper
 }  // namespace graphics
 }  // namespace hardware
-}  // namespace android
-
-int main(int argc, char** argv) {
-    using android::hardware::graphics::mapper::V2_1::vts::GraphicsMapperHidlEnvironment;
-    ::testing::AddGlobalTestEnvironment(GraphicsMapperHidlEnvironment::Instance());
-    ::testing::InitGoogleTest(&argc, argv);
-    GraphicsMapperHidlEnvironment::Instance()->init(&argc, argv);
-
-    int status = RUN_ALL_TESTS();
-    LOG(INFO) << "Test result = " << status;
-
-    return status;
-}
+}  // namespace android
\ No newline at end of file
diff --git a/graphics/mapper/3.0/utils/vts/MapperVts.cpp b/graphics/mapper/3.0/utils/vts/MapperVts.cpp
index c94e8db..de886a9 100644
--- a/graphics/mapper/3.0/utils/vts/MapperVts.cpp
+++ b/graphics/mapper/3.0/utils/vts/MapperVts.cpp
@@ -16,8 +16,6 @@
 
 #include <mapper-vts/3.0/MapperVts.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-
 namespace android {
 namespace hardware {
 namespace graphics {
@@ -35,19 +33,19 @@
 }
 
 void Gralloc::init(const std::string& allocatorServiceName, const std::string& mapperServiceName) {
-    mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>(allocatorServiceName);
+    mAllocator = IAllocator::getService(allocatorServiceName);
     ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
 
-    mMapper = ::testing::VtsHalHidlTargetTestBase::getService<IMapper>(mapperServiceName);
+    mMapper = IMapper::getService(mapperServiceName);
     ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service";
     ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
 }
 
 void Gralloc::initNoErr(const std::string& allocatorServiceName,
                         const std::string& mapperServiceName) {
-    mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>(allocatorServiceName);
+    mAllocator = IAllocator::getService(allocatorServiceName);
 
-    mMapper = ::testing::VtsHalHidlTargetTestBase::getService<IMapper>(mapperServiceName);
+    mMapper = IMapper::getService(mapperServiceName);
     if (mMapper.get()) {
         ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
     }
diff --git a/graphics/mapper/3.0/utils/vts/include/mapper-vts/3.0/MapperVts.h b/graphics/mapper/3.0/utils/vts/include/mapper-vts/3.0/MapperVts.h
index 1141a88..b2fbebb1 100644
--- a/graphics/mapper/3.0/utils/vts/include/mapper-vts/3.0/MapperVts.h
+++ b/graphics/mapper/3.0/utils/vts/include/mapper-vts/3.0/MapperVts.h
@@ -22,6 +22,7 @@
 
 #include <android/hardware/graphics/allocator/3.0/IAllocator.h>
 #include <android/hardware/graphics/mapper/3.0/IMapper.h>
+#include <gtest/gtest.h>
 #include <utils/StrongPointer.h>
 
 namespace android {
diff --git a/graphics/mapper/3.0/vts/functional/Android.bp b/graphics/mapper/3.0/vts/functional/Android.bp
index 77075a5..f01670e 100644
--- a/graphics/mapper/3.0/vts/functional/Android.bp
+++ b/graphics/mapper/3.0/vts/functional/Android.bp
@@ -26,5 +26,5 @@
         "android.hardware.graphics.mapper@3.0",
         "android.hardware.graphics.mapper@3.0-vts",
     ],
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp b/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp
index ff73ecf..92b5994 100644
--- a/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp
+++ b/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp
@@ -20,8 +20,10 @@
 #include <thread>
 #include <vector>
 
-#include <VtsHalHidlTargetTestBase.h>
 #include <android-base/logging.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 #include <mapper-vts/3.0/MapperVts.h>
 
 namespace android {
@@ -35,28 +37,12 @@
 using android::hardware::graphics::common::V1_2::BufferUsage;
 using android::hardware::graphics::common::V1_2::PixelFormat;
 
-// Test environment for graphics.mapper.
-class GraphicsMapperHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static GraphicsMapperHidlEnvironment* Instance() {
-        static GraphicsMapperHidlEnvironment* instance = new GraphicsMapperHidlEnvironment;
-        return instance;
-    }
-
-    virtual void registerTestServices() override {
-        registerTestService<IAllocator>();
-        registerTestService<IMapper>();
-    }
-};
-
-class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-   protected:
+class GraphicsMapperHidlTest
+    : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
+  protected:
     void SetUp() override {
-        ASSERT_NO_FATAL_FAILURE(
-            mGralloc = std::make_unique<Gralloc>(
-                GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>(),
-                GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>()));
+        ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>(std::get<0>(GetParam()),
+                                                                     std::get<1>(GetParam())));
 
         mDummyDescriptorInfo.width = 64;
         mDummyDescriptorInfo.height = 64;
@@ -75,14 +61,14 @@
 /**
  * Test IAllocator::dumpDebugInfo by calling it.
  */
-TEST_F(GraphicsMapperHidlTest, AllocatorDumpDebugInfo) {
+TEST_P(GraphicsMapperHidlTest, AllocatorDumpDebugInfo) {
     mGralloc->dumpDebugInfo();
 }
 
 /**
  * Test IAllocator::allocate with valid buffer descriptors.
  */
-TEST_F(GraphicsMapperHidlTest, AllocatorAllocate) {
+TEST_P(GraphicsMapperHidlTest, AllocatorAllocate) {
     BufferDescriptor descriptor;
     ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
 
@@ -105,7 +91,7 @@
 /**
  * Test IAllocator::allocate with invalid buffer descriptors.
  */
-TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNegative) {
+TEST_P(GraphicsMapperHidlTest, AllocatorAllocateNegative) {
     // this assumes any valid descriptor is non-empty
     BufferDescriptor descriptor;
     mGralloc->getAllocator()->allocate(descriptor, 1,
@@ -117,7 +103,7 @@
 /**
  * Test IAllocator::allocate does not leak.
  */
-TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNoLeak) {
+TEST_P(GraphicsMapperHidlTest, AllocatorAllocateNoLeak) {
     auto info = mDummyDescriptorInfo;
     info.width = 1024;
     info.height = 1024;
@@ -131,7 +117,7 @@
 /**
  * Test that IAllocator::allocate is thread-safe.
  */
-TEST_F(GraphicsMapperHidlTest, AllocatorAllocateThreaded) {
+TEST_P(GraphicsMapperHidlTest, AllocatorAllocateThreaded) {
     BufferDescriptor descriptor;
     ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
 
@@ -161,14 +147,14 @@
 /**
  * Test IMapper::createDescriptor with valid descriptor info.
  */
-TEST_F(GraphicsMapperHidlTest, CreateDescriptorBasic) {
+TEST_P(GraphicsMapperHidlTest, CreateDescriptorBasic) {
     ASSERT_NO_FATAL_FAILURE(mGralloc->createDescriptor(mDummyDescriptorInfo));
 }
 
 /**
  * Test IMapper::createDescriptor with invalid descriptor info.
  */
-TEST_F(GraphicsMapperHidlTest, CreateDescriptorNegative) {
+TEST_P(GraphicsMapperHidlTest, CreateDescriptorNegative) {
     auto info = mDummyDescriptorInfo;
     info.width = 0;
     mGralloc->getMapper()->createDescriptor(info, [&](const auto& tmpError, const auto&) {
@@ -179,7 +165,7 @@
 /**
  * Test IMapper::importBuffer and IMapper::freeBuffer with allocated buffers.
  */
-TEST_F(GraphicsMapperHidlTest, ImportFreeBufferBasic) {
+TEST_P(GraphicsMapperHidlTest, ImportFreeBufferBasic) {
     const native_handle_t* bufferHandle;
     ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
     ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle));
@@ -188,7 +174,7 @@
 /**
  * Test IMapper::importBuffer and IMapper::freeBuffer with cloned buffers.
  */
-TEST_F(GraphicsMapperHidlTest, ImportFreeBufferClone) {
+TEST_P(GraphicsMapperHidlTest, ImportFreeBufferClone) {
     const native_handle_t* clonedBufferHandle;
     ASSERT_NO_FATAL_FAILURE(clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
 
@@ -206,7 +192,7 @@
 /**
  * Test IMapper::importBuffer and IMapper::freeBuffer cross mapper instances.
  */
-TEST_F(GraphicsMapperHidlTest, ImportFreeBufferSingleton) {
+TEST_P(GraphicsMapperHidlTest, ImportFreeBufferSingleton) {
     const native_handle_t* rawHandle;
     ASSERT_NO_FATAL_FAILURE(rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
 
@@ -218,10 +204,8 @@
 
     // free the imported handle with another mapper
     std::unique_ptr<Gralloc> anotherGralloc;
-    ASSERT_NO_FATAL_FAILURE(
-        anotherGralloc = std::make_unique<Gralloc>(
-            GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>(),
-            GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>()));
+    ASSERT_NO_FATAL_FAILURE(anotherGralloc = std::make_unique<Gralloc>(std::get<0>(GetParam()),
+                                                                       std::get<1>(GetParam())));
     Error error = mGralloc->getMapper()->freeBuffer(importedHandle);
     ASSERT_EQ(Error::NONE, error);
 
@@ -231,7 +215,7 @@
 /**
  * Test IMapper::importBuffer and IMapper::freeBuffer do not leak.
  */
-TEST_F(GraphicsMapperHidlTest, ImportFreeBufferNoLeak) {
+TEST_P(GraphicsMapperHidlTest, ImportFreeBufferNoLeak) {
     auto info = mDummyDescriptorInfo;
     info.width = 1024;
     info.height = 1024;
@@ -245,7 +229,7 @@
 /**
  * Test IMapper::importBuffer with invalid buffers.
  */
-TEST_F(GraphicsMapperHidlTest, ImportBufferNegative) {
+TEST_P(GraphicsMapperHidlTest, ImportBufferNegative) {
     native_handle_t* invalidHandle = nullptr;
     mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError, const auto&) {
         EXPECT_EQ(Error::BAD_BUFFER, tmpError)
@@ -263,7 +247,7 @@
 /**
  * Test IMapper::freeBuffer with invalid buffers.
  */
-TEST_F(GraphicsMapperHidlTest, FreeBufferNegative) {
+TEST_P(GraphicsMapperHidlTest, FreeBufferNegative) {
     native_handle_t* invalidHandle = nullptr;
     Error error = mGralloc->getMapper()->freeBuffer(invalidHandle);
     EXPECT_EQ(Error::BAD_BUFFER, error) << "freeBuffer with nullptr did not fail with BAD_BUFFER";
@@ -286,7 +270,7 @@
 /**
  * Test IMapper::lock and IMapper::unlock.
  */
-TEST_F(GraphicsMapperHidlTest, LockUnlockBasic) {
+TEST_P(GraphicsMapperHidlTest, LockUnlockBasic) {
     const auto& info = mDummyDescriptorInfo;
 
     const native_handle_t* bufferHandle;
@@ -346,7 +330,7 @@
  * Test IMapper::lockYCbCr.  This locks a YV12 buffer, and makes sure we can
  * write to and read from it.
  */
-TEST_F(GraphicsMapperHidlTest, LockYCbCrBasic) {
+TEST_P(GraphicsMapperHidlTest, LockYCbCrBasic) {
     auto info = mDummyDescriptorInfo;
     info.format = PixelFormat::YV12;
 
@@ -405,7 +389,7 @@
 /**
  * Test IMapper::unlock with invalid buffers.
  */
-TEST_F(GraphicsMapperHidlTest, UnlockNegative) {
+TEST_P(GraphicsMapperHidlTest, UnlockNegative) {
     native_handle_t* invalidHandle = nullptr;
     mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
         EXPECT_EQ(Error::BAD_BUFFER, tmpError)
@@ -443,7 +427,7 @@
 /**
  * Test IMapper::isSupported with required format RGBA_8888
  */
-TEST_F(GraphicsMapperHidlTest, IsSupportedRGBA8888) {
+TEST_P(GraphicsMapperHidlTest, IsSupportedRGBA8888) {
     const auto& info = mDummyDescriptorInfo;
     bool supported = false;
 
@@ -454,7 +438,7 @@
 /**
  * Test IMapper::isSupported with required format YV12
  */
-TEST_F(GraphicsMapperHidlTest, IsSupportedYV12) {
+TEST_P(GraphicsMapperHidlTest, IsSupportedYV12) {
     auto info = mDummyDescriptorInfo;
     info.format = PixelFormat::YV12;
     bool supported = false;
@@ -466,7 +450,7 @@
 /**
  * Test IMapper::isSupported with optional format Y16
  */
-TEST_F(GraphicsMapperHidlTest, IsSupportedY16) {
+TEST_P(GraphicsMapperHidlTest, IsSupportedY16) {
     auto info = mDummyDescriptorInfo;
     info.format = PixelFormat::Y16;
     bool supported = false;
@@ -474,6 +458,14 @@
     ASSERT_NO_FATAL_FAILURE(supported = mGralloc->isSupported(info));
 }
 
+INSTANTIATE_TEST_CASE_P(
+        PerInstance, GraphicsMapperHidlTest,
+        testing::Combine(
+                testing::ValuesIn(
+                        android::hardware::getAllHalInstanceNames(IAllocator::descriptor)),
+                testing::ValuesIn(android::hardware::getAllHalInstanceNames(IMapper::descriptor))),
+        android::hardware::PrintInstanceTupleNameToString<>);
+
 }  // namespace
 }  // namespace vts
 }  // namespace V3_0
@@ -481,13 +473,3 @@
 }  // namespace graphics
 }  // namespace hardware
 }  // namespace android
-
-int main(int argc, char** argv) {
-    using android::hardware::graphics::mapper::V3_0::vts::GraphicsMapperHidlEnvironment;
-    ::testing::AddGlobalTestEnvironment(GraphicsMapperHidlEnvironment::Instance());
-    ::testing::InitGoogleTest(&argc, argv);
-    GraphicsMapperHidlEnvironment::Instance()->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    LOG(INFO) << "Test result = " << status;
-    return status;
-}
diff --git a/graphics/mapper/4.0/IMapper.hal b/graphics/mapper/4.0/IMapper.hal
index 640539f..03dfef1 100644
--- a/graphics/mapper/4.0/IMapper.hal
+++ b/graphics/mapper/4.0/IMapper.hal
@@ -35,18 +35,20 @@
          */
         uint32_t width;
 
-       /**
-        * The height specifies how many rows of pixels must be in the
-        * allocated buffer.
-        */
+        /**
+         * The height specifies how many rows of pixels must be in the
+         * allocated buffer.
+         */
         uint32_t height;
 
-       /**
-        * The number of image layers that must be in the allocated buffer.
-        */
+        /**
+         * The number of image layers that must be in the allocated buffer.
+         */
         uint32_t layerCount;
 
-        /** Buffer pixel format. */
+        /**
+         * Buffer pixel format.
+         */
         PixelFormat format;
 
         /**
@@ -54,6 +56,12 @@
          * BufferUsage.
          */
         bitfield<BufferUsage> usage;
+
+        /**
+         * The size in bytes of the reserved region associated with the buffer.
+         * See getReservedRegion for more information.
+         */
+        uint64_t reservedSize;
     };
 
     struct Rect {
@@ -69,9 +77,10 @@
      *
      * Since the buffer descriptor fully describes a buffer, any device
      * dependent or device independent checks must be performed here whenever
-     * possible. Specifically, when layered buffers are not supported, this
-     * function must return `UNSUPPORTED` if `description.layers` is great than
-     * 1.
+     * possible. When layered buffers are not supported, this function must
+     * return `UNSUPPORTED` if `description.layers` is great than 1. This
+     * function may return `UNSUPPORTED` if `description.reservedSize` is
+     * larger than a page.
      *
      * @param description Attributes of the descriptor.
      * @return error Error status of the call, which may be
@@ -197,16 +206,20 @@
      * outside of @p accessRegion is undefined, except that it must not cause
      * process termination.
      *
+     * This function can lock both single-planar and multi-planar formats. The caller
+     * should use get() to get information about the buffer they are locking.
+     * get() can be used to get information about the planes, offsets, stride,
+     * etc.
+     *
+     * This function must also work on buffers with
+     * `AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_*` if supported by the device, as well
+     * as with any other formats requested by multimedia codecs when they are
+     * configured with a flexible-YUV-compatible color format.
+     *
      * On success, @p data must be filled with a pointer to the locked buffer
      * memory. This address will represent the top-left corner of the entire
      * buffer, even if @p accessRegion does not begin at the top-left corner.
      *
-     * On success, bytesPerPixel must contain the number of bytes per pixel in
-     * the buffer. If the bytesPerPixel is unknown or variable, a value of -1
-     * should be returned. bytesPerStride must contain the bytes per stride of
-     * the buffer. If the bytesPerStride is unknown or variable, a value of -1
-     * should be returned.
-     *
      * The locked buffer must adhere to the format requested at allocation time
      * in the BufferDescriptorInfo.
      *
@@ -229,55 +242,13 @@
      *     - `NO_RESOURCES` if the buffer cannot be locked at this time. Note
      *       that locking may succeed at a later time.
      * @return data CPU-accessible pointer to the buffer data.
-     * @return bytesPerPixel the number of bytes per pixel in the buffer
-     * @return bytesPerStride the number of bytes per stride of the buffer
      */
     lock(pointer buffer,
          uint64_t cpuUsage,
          Rect accessRegion,
          handle acquireFence)
             generates (Error error,
-                       pointer data,
-                       int32_t bytesPerPixel,
-                       int32_t bytesPerStride);
-
-    /**
-     * Locks a YCbCr buffer for the specified CPU usage.
-     *
-     * This is largely the same as lock(), except that instead of returning a
-     * pointer directly to the buffer data, it returns a `YCbCrLayout` struct
-     * describing how to access the data planes.
-     *
-     * This function must work on buffers with
-     * `AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_*` if supported by the device, as well
-     * as with any other formats requested by multimedia codecs when they are
-     * configured with a flexible-YUV-compatible color format.
-     *
-     * @param buffer Buffer to lock.
-     * @param cpuUsage CPU usage flags to request. See +ndk
-     *     libnativewindow#AHardwareBuffer_UsageFlags for possible values.
-     * @param accessRegion Portion of the buffer that the client intends to
-     *     access.
-     * @param acquireFence Handle containing a file descriptor referring to a
-     *     sync fence object, which will be signaled when it is safe for the
-     *     mapper to lock the buffer. @p acquireFence may be empty if it is
-     *     already safe to lock.
-     * @return error Error status of the call, which may be
-     *     - `NONE` upon success.
-     *     - `BAD_BUFFER` if the buffer is invalid or is incompatible with this
-     *       function.
-     *     - `BAD_VALUE` if @p cpuUsage is 0, contains non-CPU usage flags, or
-     *       is incompatible with the buffer.
-     *     - `NO_RESOURCES` if the buffer cannot be locked at this time. Note
-     *       that locking may succeed at a later time.
-     * @return layout Data layout of the locked buffer.
-     */
-    lockYCbCr(pointer buffer,
-              uint64_t cpuUsage,
-              Rect accessRegion,
-              handle acquireFence)
-            generates (Error error,
-                       YCbCrLayout layout);
+                       pointer data);
 
     /**
      * Unlocks a buffer to indicate all CPU accesses to the buffer have
@@ -295,6 +266,50 @@
     unlock(pointer buffer) generates (Error error, handle releaseFence);
 
     /**
+     * Flushes the contents of a locked buffer.
+     *
+     * This function flushes the CPUs caches for the range of all the buffer's
+     * planes and metadata. This should behave similarly to unlock() except the
+     * buffer should remain mapped to the CPU.
+     *
+     * The client is still responsible for calling unlock() when it is done
+     * with all CPU accesses to the buffer.
+     *
+     * If non-CPU blocks are simultaneously writing the buffer, the locked
+     * copy should still be flushed but what happens is undefined except that
+     * it should not cause any crashes.
+     *
+     * @param buffer Buffer to flush.
+     * @return error Error status of the call, which may be
+     *     - `NONE` upon success.
+     *     - `BAD_BUFFER` if the buffer is invalid or not locked.
+     * @return releaseFence Handle containing a file descriptor referring to a
+     *     sync fence object. The sync fence object will be signaled when the
+     *     mapper has completed any pending work. @p releaseFence may be an
+     *     empty fence.
+     */
+    flushLockedBuffer(pointer buffer) generates (Error error, handle releaseFence);
+
+    /**
+     * Rereads the contents of a locked buffer.
+     *
+     * This should fetch the most recent copy of the locked buffer.
+     *
+     * It may reread locked copies of the buffer in other processes.
+     *
+     * The client is still responsible for calling unlock() when it is done
+     * with all CPU accesses to the buffer.
+     *
+     * @param buffer Buffer to reread.
+     * @return error Error status of the call, which may be
+     *     - `NONE` upon success.
+     *     - `BAD_BUFFER` if the buffer is invalid or not locked.
+     *     - `NO_RESOURCES` if the buffer cannot be reread at this time. Note
+     *       that rereading may succeed at a later time.
+     */
+    rereadLockedBuffer(pointer buffer) generates(Error error);
+
+    /**
      * Test whether the given BufferDescriptorInfo is allocatable.
      *
      * If this function returns true, it means that a buffer with the given
@@ -309,5 +324,322 @@
             generates (Error error,
                        bool supported);
 
+
+    /**
+     * Description for get(...), set(...) and getFromBufferDescriptorInfo(...)
+     *
+     * ------------ Overview -----------------------------------
+     * Gralloc 4 adds support for getting and setting buffer metadata on a buffer.
+     *
+     * To get buffer metadata, the client passes in a buffer handle and a token that
+     * represents the type of buffer metadata they would like to get. IMapper returns
+     * a byte stream that contains the buffer metadata. To set the buffer metadata, the
+     * client passes in a buffer handle and a token that represents the type of buffer
+     * metadata they would like to set and a byte stream that contains the buffer metadata
+     * they are setting.
+     *
+     * Buffer metadata is global for a buffer. When the metadata is set on the buffer
+     * in a process, the updated metadata should be available to all other processes.
+     * Please see "Storing and Propagating Metadata" below for more details.
+     *
+     * The getter and setter functions have been optimized for easy vendor extension.
+     * They do not require a formal HIDL extension to add support for getting and setting
+     * vendor defined buffer metadata. In order to allow easy extension, the types used
+     * here are not typical HIDL types. See "Buffer Metadata Token" and
+     * "Buffer Metadata Stream" below for more details.
+     *
+     * ------------ Storing and Propagating Metadata -----------
+     * Buffer metadata must be global. Any changes to the metadata must be propagated
+     * to all other processes immediately. Vendors may chose how they would like support
+     * this functionality.
+     *
+     * We recommend supporting this functionality by allocating an extra page of shared
+     * memory and storing it in the buffer's native_handle_t. The buffer metadata can
+     * be stored in the extra page of shared memory. Set operations are automatically
+     * propagated to all other processes.
+     *
+     * ------------ Buffer Metadata Synchronization ------------
+     * There are no explicit buffer metadata synchronization primitives. Many devices
+     * before gralloc 4 already support getting and setting of global buffer metadata
+     * with no explicit synchronization primitives. Adding synchronization primitives
+     * would just add unnecessary complexity.
+     *
+     * The general rule is if a process has permission to write to a buffer, they
+     * have permission to write to the buffer's metadata. If a process has permission
+     * to read from a buffer, they have permission to read the buffer's metadata.
+     *
+     * There is one exception to this rule. Fences CANNOT be used to protect a buffer's
+     * metadata. A process should finish writing to a buffer's metadata before
+     * sending the buffer to another process that will read or write to the buffer.
+     * This exception is needed because sometimes userspace needs to read the
+     * buffer's metadata before the buffer's contents are ready.
+     *
+     * As a simple example: an app renders to a buffer and then displays the buffer.
+     * In this example when the app renders to the buffer, both the buffer and its
+     * metadata need to be updated. The app's process queues up its work on the GPU
+     * and gets back an acquire fence. The app's process must update the buffer's
+     * metadata before enqueuing the buffer to SurfaceFlinger. The app process CANNOT
+     * update the buffer's metadata after enqueuing the buffer. When HardwareComposer
+     * receives the buffer, it is immediately safe to read the buffer's metadata
+     * and use it to program the display driver. To read the buffer's contents,
+     * display driver must still wait on the acquire fence.
+     *
+     * ------------ Buffer Metadata Token ----------------------
+     * In order to allow arbitrary vendor defined metadata, we could not use a
+     * HIDL enum as the buffer metadata token. Extending a HIDL enum requires a full
+     * HIDL extension. We also could not use a simple non-HIDL enum because vendor
+     * defined enums from different vendors could collide. Instead we have defined
+     * a struct that has a string representing the enum type and an int that
+     * represents the enum value. The string protects different enum values from
+     * colliding.
+     *
+     * The token struct (MetadataType) is defined as a HIDL struct since it
+     * is passed into a HIDL function. The standard buffer metadata types are NOT
+     * defined as a HIDL enum because it would have required a new IMapper version
+     * just to add future standard buffer metadata types. By putting the enum in the
+     * stable AIDL (hardware/interfaces/graphics/common/aidl/android/hardware/
+     * graphics/common/StandardMetadataType.aidl), vendors will be able to optionally
+     * choose to support future standard buffer metadata types without upgrading
+     * HIDL versions. For more information see the description of "struct MetadataType".
+     *
+     * ------------ Buffer Metadata Stream ---------------------
+     * The buffer metadata is get and set as a byte stream (vec<uint8_t>). By getting
+     * and setting buffer metadata as a byte stream, vendors can use the standard
+     * getters and setter functions defined here. Vendors do NOT need to add their own
+     * getters and setter functions for each new type of buffer metadata.
+     *
+     * Converting buffer metadata into a byte stream can be non-trivial. For the standard
+     * buffer metadata types defined in StandardMetadataType.aidl, there are also
+     * support functions that will encode the buffer metadata into a byte stream
+     * and decode the buffer metadata from a byte stream. We STRONGLY recommend using
+     * these support functions. The framework will use them when getting and setting
+     * metadata. The support functions are defined in
+     * frameworks/native/libs/gralloc/types/include/gralloctypes/Gralloc4.h.
+     */
+
+    /**
+     * MetadataType represents the different types of buffer metadata that could be
+     * associated with a buffer. It is used by IMapper to help get and set buffer metadata
+     * on the buffer's native handle.
+     *
+     * Standard buffer metadata will have the name field set to
+     * "android.hardware.graphics.common.StandardMetadataType" and will contain values
+     * from StandardMetadataType.aidl.
+     *
+     * This struct should be "extended" by devices that use a proprietary or non-standard
+     * buffer metadata. To extend the struct, first create a custom @VendorStability vendor
+     * AIDL interface that defines the new type(s) you would like to support. Set the
+     * struct's name field to the custom aidl interface's name
+     * (eg. "vendor.mycompanyname.graphics.common.MetadataType"). Set the struct's value
+     * field to the custom @VendorStabilty vendor AIDL interface.
+     *
+     * Each company should create their own StandardMetadataType.aidl extension. The name
+     * field prevents values from different companies from colliding.
+     */
+    struct MetadataType {
+        string name;
+        int64_t value;
+    };
+
+    /**
+     * Gets the buffer metadata for a given MetadataType.
+     *
+     * Buffer metadata can be changed after allocation so clients should avoid "caching"
+     * the buffer metadata. For example, if the video resolution changes and the buffers
+     * are not reallocated, several buffer metadata values may change without warning.
+     * Clients should not expect the values to be constant. They should requery them every
+     * frame. The only exception is buffer metadata that is determined at allocation
+     * time. For StandardMetadataType values, only BUFFER_ID, NAME, WIDTH,
+     * HEIGHT, LAYER_COUNT, PIXEL_FORMAT_REQUESTED and USAGE are safe to cache because
+     * they are determined at allocation time.
+     *
+     * @param buffer Buffer containing desired metadata
+     * @param metadataType MetadataType for the metadata value being queried
+     * @return error Error status of the call, which may be
+     *     - `NONE` upon success.
+     *     - `BAD_BUFFER` if the raw handle is invalid.
+     *     - `NO_RESOURCES` if the get cannot be fullfilled due to unavailability of
+     *        resources.
+     *     - `UNSUPPORTED` when metadataType is unknown/unsupported.
+     *        IMapper must support getting all StandardMetadataType.aidl values defined
+     *        at the time the device first launches.
+     * @return metadata Vector of bytes representing the buffer metadata associated with
+     *  the MetadataType.
+     */
+    get(pointer buffer, MetadataType metadataType)
+            generates (Error error,
+                       vec<uint8_t> metadata);
+
+    /**
+     * Sets the global value for a given MetadataType.
+     *
+     * Metadata fields are not required to be settable. This function can
+     * return Error::UNSUPPORTED whenever it doesn't support setting a
+     * particular Metadata field.
+     *
+     * The framework may attempt to set the following StandardMetadataType
+     * values: DATASPACE, PER_FRAME_METADATA, PER_FRAME_METADATA_BLOB and BLEND_MODE.
+     * We strongly encourage everyone to support setting as many of those fields as
+     * possible. If a device's Composer implementation supports a field, it should be
+     * supported here. Over time these metadata fields will be moved out of
+     * Composer/BufferQueue/etc. and into the buffer's Metadata fields.
+     * If a device's IMapper doesn't support setting those Metadata fields,
+     * eventually the device may not longer be able to support these fields.
+     *
+     * @param buffer Buffer receiving desired metadata
+     * @param metadataType MetadataType for the metadata value being set
+     * @param metadata Vector of bytes representing the value associated with
+     * @return error Error status of the call, which may be
+     *     - `NONE` upon success.
+     *     - `BAD_BUFFER` if the raw handle is invalid.
+     *     - `BAD_VALUE` when the field is constant and can never be set (such as
+     *       BUFFER_ID, NAME, WIDTH, HEIGHT, LAYER_COUNT, PIXEL_FORMAT_REQUESTED and
+     *       USAGE)
+     *     - `NO_RESOURCES` if the set cannot be fullfilled due to unavailability of
+     *        resources.
+     *     - `UNSUPPORTED` when metadataType is unknown/unsupported or setting
+     *       it is unsupported. Unsupported should also be returned if the metadata
+     *       is malformed.
+     */
+    set(pointer buffer, MetadataType metadataType, vec<uint8_t> metadata)
+            generates (Error error);
+
+    /**
+     * Given a BufferDescriptorInfo, gets the starting value of a given
+     * MetadataType. This can be used to query basic information about a buffer
+     * before the buffer is allocated.
+     *
+     * @param description Attributes of the descriptor.
+     * @param metadataType MetadataType for the metadata value being queried
+     * @return error Error status of the call, which may be
+     *     - `NONE` upon success.
+     *     - `BAD_VALUE` if any of the specified BufferDescriptorInfo attributes
+     *       are invalid.
+     *     - `NO_RESOURCES` if the get cannot be fullfilled due to unavailability of
+     *       resources.
+     *     - `UNSUPPORTED` when any of the description attributes are unsupported or
+     *       if the metadataType is unknown/unsupported. This should also be
+     *       returned if the requested metadata is not defined until a buffer has been
+     *       allocated.
+     * @return metadata Vector of bytes representing the value associated with
+     *  the MetadataType value.
+     */
+    getFromBufferDescriptorInfo(BufferDescriptorInfo description,
+                                MetadataType metadataType)
+            generates (Error error,
+                       vec<uint8_t> metadata);
+
+    struct MetadataTypeDescription {
+        MetadataType metadataType;
+        /**
+         * description should contain a string representation of the MetadataType.
+         *
+         * For example: "MyExampleMetadataType is a 64-bit timestamp in nanoseconds
+         * that indicates when a buffer is decoded. It is set by the media HAL after
+         * a buffer is decoded. It is used by the display HAL for hardware
+         * synchronization".
+         *
+         * This field is required for any non-StandardMetadataTypes.
+         */
+        string description;
+        /**
+         * isGettable represents if the MetadataType can be get.
+         */
+        bool isGettable;
+        /**
+         * isSettable represents if the MetadataType can be set.
+         */
+        bool isSettable;
+    };
+
+    /**
+     * Lists all the MetadataTypes supported by IMapper as well as a description
+     * of each supported MetadataType. For StandardMetadataTypes, the description
+     * string can be left empty.
+     *
+     * @return error Error status of the call, which may be
+     *     - `NONE` upon success.
+     *     - `NO_RESOURCES` if the get cannot be fullfilled due to unavailability of
+     *       resources.
+     * @return descriptions Vector of MetadataTypeDescriptions that represent the
+     *  MetadataTypes supported by the device.
+     */
+    listSupportedMetadataTypes()
+            generates (Error error, vec<MetadataTypeDescription> descriptions);
+
+    struct MetadataDump {
+        /**
+         * The type of metadata being dumped.
+         */
+        MetadataType metadataType;
+        /**
+         * The byte stream representation of the metadata. If the metadata is not
+         * gettable, the vector must be empty.
+         */
+        vec<uint8_t> metadata;
+    };
+
+    struct BufferDump {
+        /**
+         * A vector of all the metadata that is being dumped for a particular buffer.
+         */
+        vec<MetadataDump> metadataDump;
+    };
+
+    /**
+     * Dumps a buffer's metadata.
+     *
+     * @param buffer Buffer that is being dumped
+     * @return error Error status of the call, which may be
+     *     - `NONE` upon success.
+     *     - `BAD_BUFFER` if the raw handle is invalid.
+     *     - `NO_RESOURCES` if the get cannot be fullfilled due to unavailability of
+     *       resources.
+     * @return bufferDump Struct representing the metadata being dumped
+     */
+    dumpBuffer(pointer buffer)
+            generates (Error error, BufferDump bufferDump);
+
+    /**
+     * Dumps the metadata for all the buffers in the current process.
+     *
+     * @return error Error status of the call, which may be
+     *     - `NONE` upon success.
+     *     - `NO_RESOURCES` if the get cannot be fullfilled due to unavailability of
+     *       resources.
+     * @return bufferDumps Vector of structs representing the buffers being dumped
+     */
+    dumpBuffers()
+            generates (Error error, vec<BufferDump> bufferDumps);
+
+    /**
+     * Returns the region of shared memory associated with the buffer that is
+     * reserved for client use.
+     *
+     * The shared memory may be allocated from any shared memory allocator.
+     * The shared memory must be CPU-accessible and virtually contiguous. The
+     * starting address must be word-aligned.
+     *
+     * This function may only be called after importBuffer() has been called by the
+     * client. The reserved region must remain accessible until freeBuffer() has
+     * been called. After freeBuffer() has been called, the client must not access
+     * the reserved region.
+     *
+     * This reserved memory may be used in future versions of Android to
+     * help clients implement backwards compatible features without requiring
+     * IAllocator/IMapper updates.
+     *
+     * @param buffer Imported buffer handle.
+     * @return error Error status of the call, which may be
+     *     - `NONE` upon success.
+     *     - `BAD_BUFFER` if the buffer is invalid.
+     * @return reservedRegion CPU-accessible pointer to the reserved region
+     * @return reservedSize the size of the reservedRegion that was requested
+     *    in the BufferDescriptorInfo.
+     */
+    getReservedRegion(pointer buffer)
+            generates (Error error,
+                       pointer reservedRegion,
+                       uint64_t reservedSize);
 };
 
diff --git a/graphics/mapper/4.0/types.hal b/graphics/mapper/4.0/types.hal
index 2fdfa65..00b6607 100644
--- a/graphics/mapper/4.0/types.hal
+++ b/graphics/mapper/4.0/types.hal
@@ -53,32 +53,3 @@
  */
 typedef vec<uint8_t> BufferDescriptor;
 
-/**
- * Structure for describing YCbCr formats for consumption by applications.
- * This is used with PixelFormat::YCBCR_*_888.
- *
- * Buffer chroma subsampling is defined in the format.
- * e.g. PixelFormat::YCBCR_420_888 has subsampling 4:2:0.
- *
- * Buffers must have a 8 bit depth.
- *
- * y, cb, and cr point to the first byte of their respective planes.
- *
- * Stride describes the distance in bytes from the first value of one row of
- * the image to the first value of the next row. It includes the width of the
- * image plus padding.
- * yStride is the stride of the luma plane.
- * cStride is the stride of the chroma planes.
- *
- * chromaStep is the distance in bytes from one chroma pixel value to the
- * next. This is 2 bytes for semiplanar (because chroma values are interleaved
- * and each chroma value is one byte) and 1 for planar.
- */
-struct YCbCrLayout {
-    pointer y;
-    pointer cb;
-    pointer cr;
-    uint32_t yStride;
-    uint32_t cStride;
-    uint32_t chromaStep;
-};
diff --git a/graphics/mapper/4.0/utils/vts/Android.bp b/graphics/mapper/4.0/utils/vts/Android.bp
index e451584..56ff116 100644
--- a/graphics/mapper/4.0/utils/vts/Android.bp
+++ b/graphics/mapper/4.0/utils/vts/Android.bp
@@ -26,6 +26,9 @@
         "android.hardware.graphics.allocator@4.0",
         "android.hardware.graphics.mapper@4.0",
     ],
+    shared_libs: [
+        "libgralloctypes",
+    ],
     export_static_lib_headers: [
         "android.hardware.graphics.allocator@4.0",
         "android.hardware.graphics.mapper@4.0",
diff --git a/graphics/mapper/4.0/utils/vts/MapperVts.cpp b/graphics/mapper/4.0/utils/vts/MapperVts.cpp
index 056b7c9..8a5f54e 100644
--- a/graphics/mapper/4.0/utils/vts/MapperVts.cpp
+++ b/graphics/mapper/4.0/utils/vts/MapperVts.cpp
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
+#include <gralloctypes/Gralloc4.h>
 #include <mapper-vts/4.0/MapperVts.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-
 namespace android {
 namespace hardware {
 namespace graphics {
@@ -35,19 +34,19 @@
 }
 
 void Gralloc::init(const std::string& allocatorServiceName, const std::string& mapperServiceName) {
-    mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>(allocatorServiceName);
+    mAllocator = IAllocator::getService(allocatorServiceName);
     ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
 
-    mMapper = ::testing::VtsHalHidlTargetTestBase::getService<IMapper>(mapperServiceName);
+    mMapper = IMapper::getService(mapperServiceName);
     ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service";
     ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
 }
 
 void Gralloc::initNoErr(const std::string& allocatorServiceName,
                         const std::string& mapperServiceName) {
-    mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>(allocatorServiceName);
+    mAllocator = IAllocator::getService(allocatorServiceName);
 
-    mMapper = ::testing::VtsHalHidlTargetTestBase::getService<IMapper>(mapperServiceName);
+    mMapper = IMapper::getService(mapperServiceName);
     if (mMapper.get()) {
         ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
     }
@@ -92,28 +91,39 @@
 
 std::vector<const native_handle_t*> Gralloc::allocate(const BufferDescriptor& descriptor,
                                                       uint32_t count, bool import,
-                                                      uint32_t* outStride) {
+                                                      bool allowFailure, uint32_t* outStride) {
     std::vector<const native_handle_t*> bufferHandles;
     bufferHandles.reserve(count);
-    mAllocator->allocate(descriptor, count,
-                         [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
-                             ASSERT_EQ(Error::NONE, tmpError) << "failed to allocate buffers";
-                             ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array";
+    mAllocator->allocate(
+            descriptor, count,
+            [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
+                ASSERT_EQ(Error::NONE, tmpError) << "failed to allocate buffers";
+                ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array";
 
-                             for (uint32_t i = 0; i < count; i++) {
-                                 if (import) {
-                                     ASSERT_NO_FATAL_FAILURE(
-                                             bufferHandles.push_back(importBuffer(tmpBuffers[i])));
-                                 } else {
-                                     ASSERT_NO_FATAL_FAILURE(
-                                             bufferHandles.push_back(cloneBuffer(tmpBuffers[i])));
-                                 }
-                             }
+                for (uint32_t i = 0; i < count; i++) {
+                    const native_handle_t* bufferHandle = nullptr;
+                    if (import) {
+                        if (allowFailure) {
+                            bufferHandle = importBuffer(tmpBuffers[i]);
+                        } else {
+                            ASSERT_NO_FATAL_FAILURE(bufferHandle = importBuffer(tmpBuffers[i]));
+                        }
+                    } else {
+                        if (allowFailure) {
+                            bufferHandle = cloneBuffer(tmpBuffers[i]);
+                        } else {
+                            ASSERT_NO_FATAL_FAILURE(bufferHandle = cloneBuffer(tmpBuffers[i]));
+                        }
+                    }
+                    if (bufferHandle) {
+                        bufferHandles.push_back(bufferHandle);
+                    }
+                }
 
-                             if (outStride) {
-                                 *outStride = tmpStride;
-                             }
-                         });
+                if (outStride) {
+                    *outStride = tmpStride;
+                }
+            });
 
     if (::testing::Test::HasFatalFailure()) {
         bufferHandles.clear();
@@ -123,17 +133,20 @@
 }
 
 const native_handle_t* Gralloc::allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
-                                         bool import, uint32_t* outStride) {
+                                         bool import, bool allowFailure, uint32_t* outStride) {
     BufferDescriptor descriptor = createDescriptor(descriptorInfo);
     if (::testing::Test::HasFatalFailure()) {
         return nullptr;
     }
 
-    auto buffers = allocate(descriptor, 1, import, outStride);
+    auto buffers = allocate(descriptor, 1, import, allowFailure, outStride);
     if (::testing::Test::HasFatalFailure()) {
         return nullptr;
     }
 
+    if (buffers.size() != 1) {
+        return nullptr;
+    }
     return buffers[0];
 }
 
@@ -167,6 +180,10 @@
 }
 
 void Gralloc::freeBuffer(const native_handle_t* bufferHandle) {
+    if (bufferHandle == nullptr) {
+        return;
+    }
+
     auto buffer = const_cast<native_handle_t*>(bufferHandle);
 
     if (mImportedBuffers.erase(bufferHandle)) {
@@ -180,8 +197,7 @@
 }
 
 void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
-                    const IMapper::Rect& accessRegion, int acquireFence, int32_t* outBytesPerPixel,
-                    int32_t* outBytesPerStride) {
+                    const IMapper::Rect& accessRegion, int acquireFence) {
     auto buffer = const_cast<native_handle_t*>(bufferHandle);
 
     NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
@@ -192,17 +208,11 @@
         acquireFenceHandle = h;
     }
 
-    *outBytesPerPixel = -1;
-    *outBytesPerStride = -1;
-
     void* data = nullptr;
     mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
-                  [&](const auto& tmpError, const auto& tmpData, int32_t tmpBytesPerPixel,
-                      int32_t tmpBytesPerStride) {
+                  [&](const auto& tmpError, const auto& tmpData) {
                       ASSERT_EQ(Error::NONE, tmpError) << "failed to lock buffer " << buffer;
                       data = tmpData;
-                      *outBytesPerPixel = tmpBytesPerPixel;
-                      *outBytesPerStride = tmpBytesPerStride;
                   });
 
     if (acquireFence >= 0) {
@@ -212,33 +222,6 @@
     return data;
 }
 
-YCbCrLayout Gralloc::lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
-                               const IMapper::Rect& accessRegion, int acquireFence) {
-    auto buffer = const_cast<native_handle_t*>(bufferHandle);
-
-    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
-    hidl_handle acquireFenceHandle;
-    if (acquireFence >= 0) {
-        auto h = native_handle_init(acquireFenceStorage, 1, 0);
-        h->data[0] = acquireFence;
-        acquireFenceHandle = h;
-    }
-
-    YCbCrLayout layout = {};
-    mMapper->lockYCbCr(buffer, cpuUsage, accessRegion, acquireFenceHandle,
-                       [&](const auto& tmpError, const auto& tmpLayout) {
-                           ASSERT_EQ(Error::NONE, tmpError)
-                                   << "failed to lockYCbCr buffer " << buffer;
-                           layout = tmpLayout;
-                       });
-
-    if (acquireFence >= 0) {
-        close(acquireFence);
-    }
-
-    return layout;
-}
-
 int Gralloc::unlock(const native_handle_t* bufferHandle) {
     auto buffer = const_cast<native_handle_t*>(bufferHandle);
 
@@ -261,6 +244,34 @@
     return releaseFence;
 }
 
+int Gralloc::flushLockedBuffer(const native_handle_t* bufferHandle) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    int releaseFence = -1;
+    mMapper->flushLockedBuffer(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to flush locked buffer " << buffer;
+
+        auto fenceHandle = tmpReleaseFence.getNativeHandle();
+        if (fenceHandle) {
+            ASSERT_EQ(0, fenceHandle->numInts) << "invalid fence handle " << fenceHandle;
+            if (fenceHandle->numFds == 1) {
+                releaseFence = dup(fenceHandle->data[0]);
+                ASSERT_LT(0, releaseFence) << "failed to dup fence fd";
+            } else {
+                ASSERT_EQ(0, fenceHandle->numFds) << " invalid fence handle " << fenceHandle;
+            }
+        }
+    });
+
+    return releaseFence;
+}
+
+void Gralloc::rereadLockedBuffer(const native_handle_t* bufferHandle) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    ASSERT_EQ(Error::NONE, mMapper->rereadLockedBuffer(buffer));
+}
+
 bool Gralloc::validateBufferSize(const native_handle_t* bufferHandle,
                                  const IMapper::BufferDescriptorInfo& descriptorInfo,
                                  uint32_t stride) {
@@ -296,6 +307,48 @@
     return supported;
 }
 
+Error Gralloc::get(const native_handle_t* bufferHandle, const IMapper::MetadataType& metadataType,
+                   hidl_vec<uint8_t>* outVec) {
+    Error err;
+    mMapper->get(const_cast<native_handle_t*>(bufferHandle), metadataType,
+                 [&](const auto& tmpError, const hidl_vec<uint8_t>& tmpVec) {
+                     err = tmpError;
+                     *outVec = tmpVec;
+                 });
+    return err;
+}
+
+Error Gralloc::set(const native_handle_t* bufferHandle, const IMapper::MetadataType& metadataType,
+                   const hidl_vec<uint8_t>& vec) {
+    return mMapper->set(const_cast<native_handle_t*>(bufferHandle), metadataType, vec);
+}
+
+Error Gralloc::getFromBufferDescriptorInfo(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                                           const IMapper::MetadataType& metadataType,
+                                           hidl_vec<uint8_t>* outVec) {
+    Error err;
+    mMapper->getFromBufferDescriptorInfo(
+            descriptorInfo, metadataType,
+            [&](const auto& tmpError, const hidl_vec<uint8_t>& tmpVec) {
+                err = tmpError;
+                *outVec = tmpVec;
+            });
+    return err;
+}
+
+Error Gralloc::getReservedRegion(const native_handle_t* bufferHandle, void** outReservedRegion,
+                                 uint64_t* outReservedSize) {
+    Error err;
+    mMapper->getReservedRegion(
+            const_cast<native_handle_t*>(bufferHandle),
+            [&](const auto& tmpError, const auto& tmpReservedRegion, const auto& tmpReservedSize) {
+                err = tmpError;
+                *outReservedRegion = tmpReservedRegion;
+                *outReservedSize = tmpReservedSize;
+            });
+    return err;
+}
+
 }  // namespace vts
 }  // namespace V4_0
 }  // namespace mapper
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 03ce764..1c635c4 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
@@ -22,6 +22,7 @@
 
 #include <android/hardware/graphics/allocator/4.0/IAllocator.h>
 #include <android/hardware/graphics/mapper/4.0/IMapper.h>
+#include <gtest/gtest.h>
 #include <utils/StrongPointer.h>
 
 namespace android {
@@ -51,9 +52,11 @@
     //
     // Either case, the returned buffers must be freed with freeBuffer.
     std::vector<const native_handle_t*> allocate(const BufferDescriptor& descriptor, uint32_t count,
-                                                 bool import = true, uint32_t* outStride = nullptr);
+                                                 bool import = true, bool allowFailure = false,
+                                                 uint32_t* outStride = nullptr);
     const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
-                                    bool import = true, uint32_t* outStride = nullptr);
+                                    bool import = true, bool allowFailure = false,
+                                    uint32_t* outStride = nullptr);
 
     // IMapper methods
 
@@ -68,12 +71,12 @@
     // in and out of the mapper.  The ownership of the fd is always transferred
     // with each of these functions.
     void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
-               const IMapper::Rect& accessRegion, int acquireFence, int32_t* outBytesPerPixel,
-               int32_t* outBytesPerStride);
-    YCbCrLayout lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
-                          const IMapper::Rect& accessRegion, int acquireFence);
+               const IMapper::Rect& accessRegion, int acquireFence);
     int unlock(const native_handle_t* bufferHandle);
 
+    int flushLockedBuffer(const native_handle_t* bufferHandle);
+    void rereadLockedBuffer(const native_handle_t* bufferHandle);
+
     bool validateBufferSize(const native_handle_t* bufferHandle,
                             const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t stride);
     void getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
@@ -81,6 +84,19 @@
 
     bool isSupported(const IMapper::BufferDescriptorInfo& descriptorInfo);
 
+    Error get(const native_handle_t* bufferHandle, const IMapper::MetadataType& metadataType,
+              hidl_vec<uint8_t>* outVec);
+
+    Error set(const native_handle_t* bufferHandle, const IMapper::MetadataType& metadataType,
+              const hidl_vec<uint8_t>& vec);
+
+    Error getFromBufferDescriptorInfo(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                                      const IMapper::MetadataType& metadataType,
+                                      hidl_vec<uint8_t>* outVec);
+
+    Error getReservedRegion(const native_handle_t* bufferHandle, void** outReservedRegion,
+                            uint64_t* outReservedSize);
+
   private:
     void init(const std::string& allocatorServiceName, const std::string& mapperServiceName);
 
diff --git a/graphics/mapper/4.0/vts/functional/Android.bp b/graphics/mapper/4.0/vts/functional/Android.bp
index a90ee0c..926cf31 100644
--- a/graphics/mapper/4.0/vts/functional/Android.bp
+++ b/graphics/mapper/4.0/vts/functional/Android.bp
@@ -19,12 +19,20 @@
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalGraphicsMapperV4_0TargetTest.cpp"],
     static_libs: [
+        "android.hardware.graphics.mapper@4.0-vts",
+        "libgralloctypes",
+        "libsync",
+        "vintf-graphics-common-ndk_platform",
+    ],
+    shared_libs: [
         "android.hardware.graphics.allocator@4.0",
         "android.hardware.graphics.common@1.0",
         "android.hardware.graphics.common@1.1",
         "android.hardware.graphics.common@1.2",
         "android.hardware.graphics.mapper@4.0",
-        "android.hardware.graphics.mapper@4.0-vts",
     ],
-    test_suites: ["general-tests"],
+    header_libs: [
+        "libsystem_headers",
+    ],
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index 62ff613..4ca5e7e 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -16,13 +16,21 @@
 
 #define LOG_TAG "VtsHalGraphicsMapperV4_0TargetTest"
 
+#include <unistd.h>
 #include <chrono>
 #include <thread>
 #include <vector>
 
-#include <VtsHalHidlTargetTestBase.h>
+#include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
+
 #include <android-base/logging.h>
+#include <android/sync.h>
+#include <gralloctypes/Gralloc4.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 #include <mapper-vts/4.0/MapperVts.h>
+#include <system/graphics.h>
 
 namespace android {
 namespace hardware {
@@ -34,29 +42,26 @@
 
 using android::hardware::graphics::common::V1_2::BufferUsage;
 using android::hardware::graphics::common::V1_2::PixelFormat;
+using MetadataType = android::hardware::graphics::mapper::V4_0::IMapper::MetadataType;
+using aidl::android::hardware::graphics::common::BlendMode;
+using aidl::android::hardware::graphics::common::Dataspace;
+using aidl::android::hardware::graphics::common::ExtendableType;
+using aidl::android::hardware::graphics::common::PlaneLayout;
+using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
+using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
+using aidl::android::hardware::graphics::common::StandardMetadataType;
 
-// Test environment for graphics.mapper.
-class GraphicsMapperHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-  public:
-    // get the test environment singleton
-    static GraphicsMapperHidlEnvironment* Instance() {
-        static GraphicsMapperHidlEnvironment* instance = new GraphicsMapperHidlEnvironment;
-        return instance;
-    }
+using DecodeFunction = std::function<void(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                                          const hidl_vec<uint8_t>& vec)>;
 
-    virtual void registerTestServices() override {
-        registerTestService<IAllocator>();
-        registerTestService<IMapper>();
-    }
-};
-
-class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class GraphicsMapperHidlTest
+    : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
   protected:
     void SetUp() override {
-        ASSERT_NO_FATAL_FAILURE(
-                mGralloc = std::make_unique<Gralloc>(
-                        GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>(),
-                        GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>()));
+        ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>(std::get<0>(GetParam()),
+                                                                     std::get<1>(GetParam())));
+        ASSERT_NE(nullptr, mGralloc->getAllocator().get());
+        ASSERT_NE(nullptr, mGralloc->getMapper().get());
 
         mDummyDescriptorInfo.name = "dummy";
         mDummyDescriptorInfo.width = 64;
@@ -65,33 +70,260 @@
         mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
         mDummyDescriptorInfo.usage =
                 static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
+        mDummyDescriptorInfo.reservedSize = 0;
     }
 
     void TearDown() override {}
 
+    void testGet(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                 const MetadataType& metadataType, DecodeFunction decode) {
+        const native_handle_t* bufferHandle = nullptr;
+        ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(descriptorInfo, true));
+
+        hidl_vec<uint8_t> vec;
+        ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, metadataType, &vec));
+
+        ASSERT_NO_FATAL_FAILURE(decode(descriptorInfo, vec));
+    }
+
+    void testSet(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                 const MetadataType& metadataType, const hidl_vec<uint8_t>& metadata,
+                 DecodeFunction decode) {
+        const native_handle_t* bufferHandle = nullptr;
+        ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(descriptorInfo, true));
+
+        Error err = mGralloc->set(bufferHandle, metadataType, metadata);
+        if (err == Error::UNSUPPORTED) {
+            GTEST_SUCCEED() << "setting this metadata is unsupported";
+        }
+        ASSERT_EQ(err, Error::NONE);
+
+        hidl_vec<uint8_t> vec;
+        ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, metadataType, &vec));
+
+        ASSERT_NO_FATAL_FAILURE(decode(descriptorInfo, vec));
+    }
+
+    void verifyDummyDescriptorInfoPlaneLayouts(const std::vector<PlaneLayout>& planeLayouts) {
+        ASSERT_EQ(1, planeLayouts.size());
+
+        const auto& planeLayout = planeLayouts.front();
+
+        ASSERT_EQ(4, planeLayout.components.size());
+
+        int64_t offsetInBitsR = -1;
+        int64_t offsetInBitsG = -1;
+        int64_t offsetInBitsB = -1;
+        int64_t offsetInBitsA = -1;
+
+        for (const auto& component : planeLayout.components) {
+            EXPECT_EQ(GRALLOC4_PLANE_LAYOUT_COMPONENT_TYPE, component.type.name);
+            EXPECT_EQ(8, component.sizeInBits);
+            if (component.type.value == gralloc4::PlaneLayoutComponentType_R.value) {
+                offsetInBitsR = component.offsetInBits;
+            }
+            if (component.type.value == gralloc4::PlaneLayoutComponentType_G.value) {
+                offsetInBitsG = component.offsetInBits;
+            }
+            if (component.type.value == gralloc4::PlaneLayoutComponentType_B.value) {
+                offsetInBitsB = component.offsetInBits;
+            }
+            if (component.type.value == gralloc4::PlaneLayoutComponentType_A.value) {
+                offsetInBitsA = component.offsetInBits;
+            }
+        }
+
+        EXPECT_EQ(0, offsetInBitsR);
+        EXPECT_EQ(8, offsetInBitsG);
+        EXPECT_EQ(16, offsetInBitsB);
+        EXPECT_EQ(24, offsetInBitsA);
+
+        EXPECT_EQ(0, planeLayout.offsetInBytes);
+        EXPECT_EQ(8, planeLayout.sampleIncrementInBits);
+        // Skip testing stride because any stride is valid
+        EXPECT_EQ(mDummyDescriptorInfo.width, planeLayout.widthInSamples);
+        EXPECT_EQ(mDummyDescriptorInfo.height, planeLayout.heightInSamples);
+        EXPECT_LE(planeLayout.widthInSamples * planeLayout.heightInSamples * 4,
+                  planeLayout.totalSizeInBytes);
+        EXPECT_EQ(1, planeLayout.horizontalSubsampling);
+        EXPECT_EQ(1, planeLayout.verticalSubsampling);
+
+        EXPECT_EQ(0, planeLayout.crop.left);
+        EXPECT_EQ(0, planeLayout.crop.top);
+        EXPECT_EQ(planeLayout.widthInSamples, planeLayout.crop.right);
+        EXPECT_EQ(planeLayout.heightInSamples, planeLayout.crop.bottom);
+    }
+
+    void verifyBufferDump(const IMapper::BufferDump& bufferDump,
+                          const native_handle_t* bufferHandle = nullptr) {
+        std::set<StandardMetadataType> foundMetadataTypes;
+
+        const std::vector<IMapper::MetadataDump> metadataDump = bufferDump.metadataDump;
+
+        for (const auto& dump : metadataDump) {
+            const auto& metadataType = dump.metadataType;
+            const auto& metadata = dump.metadata;
+
+            if (!gralloc4::isStandardMetadataType(metadataType)) {
+                continue;
+            }
+
+            StandardMetadataType type = gralloc4::getStandardMetadataTypeValue(metadataType);
+
+            if (sRequiredMetadataTypes.find(type) == sRequiredMetadataTypes.end()) {
+                continue;
+            }
+
+            ASSERT_EQ(foundMetadataTypes.find(type), foundMetadataTypes.end());
+            foundMetadataTypes.insert(type);
+
+            if (!bufferHandle) {
+                continue;
+            }
+
+            hidl_vec<uint8_t> metadataFromGet;
+            ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, metadataType, &metadataFromGet));
+
+            ASSERT_EQ(metadataFromGet, metadata);
+        }
+
+        EXPECT_EQ(sRequiredMetadataTypes, foundMetadataTypes);
+    }
+
+    void getAndroidYCbCr(const native_handle_t* bufferHandle, uint8_t* data,
+                         android_ycbcr* outYCbCr) {
+        hidl_vec<uint8_t> vec;
+        ASSERT_EQ(Error::NONE,
+                  mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec));
+        std::vector<PlaneLayout> planeLayouts;
+        ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts));
+
+        outYCbCr->y = nullptr;
+        outYCbCr->cb = nullptr;
+        outYCbCr->cr = nullptr;
+        outYCbCr->ystride = 0;
+        outYCbCr->cstride = 0;
+        outYCbCr->chroma_step = 0;
+
+        for (const auto& planeLayout : planeLayouts) {
+            for (const auto& planeLayoutComponent : planeLayout.components) {
+                std::string componentTypeName = planeLayoutComponent.type.name;
+                if (!std::strncmp(componentTypeName.c_str(), GRALLOC4_PLANE_LAYOUT_COMPONENT_TYPE,
+                                  componentTypeName.size())) {
+                    continue;
+                }
+                ASSERT_EQ(0, planeLayoutComponent.offsetInBits % 8);
+
+                uint8_t* tmpData =
+                        data + planeLayout.offsetInBytes + (planeLayoutComponent.offsetInBits / 8);
+                uint64_t sampleIncrementInBytes;
+
+                auto type = static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value);
+                switch (type) {
+                    case PlaneLayoutComponentType::Y:
+                        ASSERT_EQ(nullptr, outYCbCr->y);
+                        ASSERT_EQ(8, planeLayoutComponent.sizeInBits);
+                        ASSERT_EQ(8, planeLayout.sampleIncrementInBits);
+                        outYCbCr->y = tmpData;
+                        outYCbCr->ystride = planeLayout.strideInBytes;
+                        break;
+
+                    case PlaneLayoutComponentType::CB:
+                    case PlaneLayoutComponentType::CR:
+                        ASSERT_EQ(0, planeLayout.sampleIncrementInBits % 8);
+
+                        sampleIncrementInBytes = planeLayout.sampleIncrementInBits / 8;
+                        ASSERT_TRUE(sampleIncrementInBytes == 1 || sampleIncrementInBytes == 2);
+
+                        if (outYCbCr->cstride == 0 && outYCbCr->chroma_step == 0) {
+                            outYCbCr->cstride = planeLayout.strideInBytes;
+                            outYCbCr->chroma_step = sampleIncrementInBytes;
+                        } else {
+                            ASSERT_EQ(outYCbCr->cstride, planeLayout.strideInBytes);
+                            ASSERT_EQ(outYCbCr->chroma_step, sampleIncrementInBytes);
+                        }
+
+                        if (type == PlaneLayoutComponentType::CB) {
+                            ASSERT_EQ(nullptr, outYCbCr->cb);
+                            outYCbCr->cb = tmpData;
+                        } else {
+                            ASSERT_EQ(nullptr, outYCbCr->cr);
+                            outYCbCr->cr = tmpData;
+                        }
+                        break;
+                    default:
+                        break;
+                };
+            }
+        }
+
+        ASSERT_NE(nullptr, outYCbCr->y);
+        ASSERT_NE(nullptr, outYCbCr->cb);
+        ASSERT_NE(nullptr, outYCbCr->cr);
+    }
+
+    void fillRGBA8888(uint8_t* data, uint32_t height, size_t strideInBytes, size_t widthInBytes,
+                      uint32_t seed = 0) {
+        for (uint32_t y = 0; y < height; y++) {
+            memset(data, y + seed, widthInBytes);
+            data += strideInBytes;
+        }
+    }
+
+    void verifyRGBA8888(uint8_t* data, uint32_t height, size_t strideInBytes, size_t widthInBytes,
+                        uint32_t seed = 0) {
+        for (uint32_t y = 0; y < height; y++) {
+            for (size_t i = 0; i < widthInBytes; i++) {
+                EXPECT_EQ(static_cast<uint8_t>(y + seed), data[i]);
+            }
+            data += strideInBytes;
+        }
+    }
+
     std::unique_ptr<Gralloc> mGralloc;
     IMapper::BufferDescriptorInfo mDummyDescriptorInfo{};
+    static const std::set<StandardMetadataType> sRequiredMetadataTypes;
+};
+
+const std::set<StandardMetadataType> GraphicsMapperHidlTest::sRequiredMetadataTypes{
+        StandardMetadataType::BUFFER_ID,
+        StandardMetadataType::NAME,
+        StandardMetadataType::WIDTH,
+        StandardMetadataType::HEIGHT,
+        StandardMetadataType::LAYER_COUNT,
+        StandardMetadataType::PIXEL_FORMAT_REQUESTED,
+        StandardMetadataType::PIXEL_FORMAT_FOURCC,
+        StandardMetadataType::PIXEL_FORMAT_MODIFIER,
+        StandardMetadataType::USAGE,
+        StandardMetadataType::ALLOCATION_SIZE,
+        StandardMetadataType::PROTECTED_CONTENT,
+        StandardMetadataType::COMPRESSION,
+        StandardMetadataType::INTERLACED,
+        StandardMetadataType::CHROMA_SITING,
+        StandardMetadataType::PLANE_LAYOUTS,
+        StandardMetadataType::DATASPACE,
+        StandardMetadataType::BLEND_MODE,
 };
 
 /**
  * Test IAllocator::dumpDebugInfo by calling it.
  */
-TEST_F(GraphicsMapperHidlTest, AllocatorDumpDebugInfo) {
+TEST_P(GraphicsMapperHidlTest, AllocatorDumpDebugInfo) {
     mGralloc->dumpDebugInfo();
 }
 
 /**
  * Test IAllocator::allocate with valid buffer descriptors.
  */
-TEST_F(GraphicsMapperHidlTest, AllocatorAllocate) {
+TEST_P(GraphicsMapperHidlTest, AllocatorAllocate) {
     BufferDescriptor descriptor;
     ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
 
     for (uint32_t count = 0; count < 5; count++) {
         std::vector<const native_handle_t*> bufferHandles;
         uint32_t stride;
-        ASSERT_NO_FATAL_FAILURE(bufferHandles =
-                                        mGralloc->allocate(descriptor, count, false, &stride));
+        ASSERT_NO_FATAL_FAILURE(
+                bufferHandles = mGralloc->allocate(descriptor, count, false, false, &stride));
 
         if (count >= 1) {
             EXPECT_LE(mDummyDescriptorInfo.width, stride) << "invalid buffer stride";
@@ -106,7 +338,7 @@
 /**
  * Test IAllocator::allocate with invalid buffer descriptors.
  */
-TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNegative) {
+TEST_P(GraphicsMapperHidlTest, AllocatorAllocateNegative) {
     // this assumes any valid descriptor is non-empty
     BufferDescriptor descriptor;
     mGralloc->getAllocator()->allocate(descriptor, 1,
@@ -118,7 +350,7 @@
 /**
  * Test IAllocator::allocate does not leak.
  */
-TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNoLeak) {
+TEST_P(GraphicsMapperHidlTest, AllocatorAllocateNoLeak) {
     auto info = mDummyDescriptorInfo;
     info.width = 1024;
     info.height = 1024;
@@ -132,7 +364,7 @@
 /**
  * Test that IAllocator::allocate is thread-safe.
  */
-TEST_F(GraphicsMapperHidlTest, AllocatorAllocateThreaded) {
+TEST_P(GraphicsMapperHidlTest, AllocatorAllocateThreaded) {
     BufferDescriptor descriptor;
     ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
 
@@ -163,14 +395,14 @@
 /**
  * Test IMapper::createDescriptor with valid descriptor info.
  */
-TEST_F(GraphicsMapperHidlTest, CreateDescriptorBasic) {
+TEST_P(GraphicsMapperHidlTest, CreateDescriptorBasic) {
     ASSERT_NO_FATAL_FAILURE(mGralloc->createDescriptor(mDummyDescriptorInfo));
 }
 
 /**
  * Test IMapper::createDescriptor with invalid descriptor info.
  */
-TEST_F(GraphicsMapperHidlTest, CreateDescriptorNegative) {
+TEST_P(GraphicsMapperHidlTest, CreateDescriptorNegative) {
     auto info = mDummyDescriptorInfo;
     info.width = 0;
     mGralloc->getMapper()->createDescriptor(info, [&](const auto& tmpError, const auto&) {
@@ -181,7 +413,7 @@
 /**
  * Test IMapper::importBuffer and IMapper::freeBuffer with allocated buffers.
  */
-TEST_F(GraphicsMapperHidlTest, ImportFreeBufferBasic) {
+TEST_P(GraphicsMapperHidlTest, ImportFreeBufferBasic) {
     const native_handle_t* bufferHandle;
     ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
     ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle));
@@ -190,7 +422,7 @@
 /**
  * Test IMapper::importBuffer and IMapper::freeBuffer with cloned buffers.
  */
-TEST_F(GraphicsMapperHidlTest, ImportFreeBufferClone) {
+TEST_P(GraphicsMapperHidlTest, ImportFreeBufferClone) {
     const native_handle_t* clonedBufferHandle;
     ASSERT_NO_FATAL_FAILURE(clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
 
@@ -208,7 +440,7 @@
 /**
  * Test IMapper::importBuffer and IMapper::freeBuffer cross mapper instances.
  */
-TEST_F(GraphicsMapperHidlTest, ImportFreeBufferSingleton) {
+TEST_P(GraphicsMapperHidlTest, ImportFreeBufferSingleton) {
     const native_handle_t* rawHandle;
     ASSERT_NO_FATAL_FAILURE(rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
 
@@ -220,10 +452,8 @@
 
     // free the imported handle with another mapper
     std::unique_ptr<Gralloc> anotherGralloc;
-    ASSERT_NO_FATAL_FAILURE(
-            anotherGralloc = std::make_unique<Gralloc>(
-                    GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>(),
-                    GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>()));
+    ASSERT_NO_FATAL_FAILURE(anotherGralloc = std::make_unique<Gralloc>(std::get<0>(GetParam()),
+                                                                       std::get<1>(GetParam())));
     Error error = mGralloc->getMapper()->freeBuffer(importedHandle);
     ASSERT_EQ(Error::NONE, error);
 
@@ -233,7 +463,7 @@
 /**
  * Test IMapper::importBuffer and IMapper::freeBuffer do not leak.
  */
-TEST_F(GraphicsMapperHidlTest, ImportFreeBufferNoLeak) {
+TEST_P(GraphicsMapperHidlTest, ImportFreeBufferNoLeak) {
     auto info = mDummyDescriptorInfo;
     info.width = 1024;
     info.height = 1024;
@@ -247,7 +477,7 @@
 /**
  * Test IMapper::importBuffer with invalid buffers.
  */
-TEST_F(GraphicsMapperHidlTest, ImportBufferNegative) {
+TEST_P(GraphicsMapperHidlTest, ImportBufferNegative) {
     native_handle_t* invalidHandle = nullptr;
     mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError, const auto&) {
         EXPECT_EQ(Error::BAD_BUFFER, tmpError)
@@ -265,7 +495,7 @@
 /**
  * Test IMapper::freeBuffer with invalid buffers.
  */
-TEST_F(GraphicsMapperHidlTest, FreeBufferNegative) {
+TEST_P(GraphicsMapperHidlTest, FreeBufferNegative) {
     native_handle_t* invalidHandle = nullptr;
     Error error = mGralloc->getMapper()->freeBuffer(invalidHandle);
     EXPECT_EQ(Error::BAD_BUFFER, error) << "freeBuffer with nullptr did not fail with BAD_BUFFER";
@@ -288,55 +518,30 @@
 /**
  * Test IMapper::lock and IMapper::unlock.
  */
-TEST_F(GraphicsMapperHidlTest, LockUnlockBasic) {
+TEST_P(GraphicsMapperHidlTest, LockUnlockBasic) {
     const auto& info = mDummyDescriptorInfo;
 
     const native_handle_t* bufferHandle;
     uint32_t stride;
-    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, &stride));
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, false, &stride));
 
     // lock buffer for writing
     const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
                                static_cast<int32_t>(info.height)};
     int fence = -1;
     uint8_t* data;
-    int32_t bytesPerPixel = -1;
-    int32_t bytesPerStride = -1;
     ASSERT_NO_FATAL_FAILURE(
-            data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence,
-                                                        &bytesPerPixel, &bytesPerStride)));
-
-    // Valid return values are -1 for unsupported or the number bytes for supported which is >=0
-    EXPECT_GT(bytesPerPixel, -1);
-    EXPECT_GT(bytesPerStride, -1);
+            data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
 
     // RGBA_8888
-    size_t strideInBytes = stride * 4;
-    size_t writeInBytes = info.width * 4;
-
-    for (uint32_t y = 0; y < info.height; y++) {
-        memset(data, y, writeInBytes);
-        data += strideInBytes;
-    }
+    fillRGBA8888(data, info.height, stride * 4, info.width * 4);
 
     ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
 
-    bytesPerPixel = -1;
-    bytesPerStride = -1;
-
     // lock again for reading
     ASSERT_NO_FATAL_FAILURE(
-            data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence,
-                                                        &bytesPerPixel, &bytesPerStride)));
-    for (uint32_t y = 0; y < info.height; y++) {
-        for (size_t i = 0; i < writeInBytes; i++) {
-            EXPECT_EQ(static_cast<uint8_t>(y), data[i]);
-        }
-        data += strideInBytes;
-    }
-
-    EXPECT_GT(bytesPerPixel, -1);
-    EXPECT_GT(bytesPerStride, -1);
+            data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
+    ASSERT_NO_FATAL_FAILURE(verifyRGBA8888(data, info.height, stride * 4, info.width * 4));
 
     ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
     if (fence >= 0) {
@@ -344,36 +549,42 @@
     }
 }
 
-/**
- * Test IMapper::lockYCbCr.  This locks a YV12 buffer, and makes sure we can
- * write to and read from it.
- */
-TEST_F(GraphicsMapperHidlTest, LockYCbCrBasic) {
+TEST_P(GraphicsMapperHidlTest, Lock_YCBCR_420_888) {
     auto info = mDummyDescriptorInfo;
-    info.format = PixelFormat::YV12;
+    info.format = PixelFormat::YCBCR_420_888;
 
     const native_handle_t* bufferHandle;
     uint32_t stride;
-    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, &stride));
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, false, &stride));
 
     // lock buffer for writing
     const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
                                static_cast<int32_t>(info.height)};
     int fence = -1;
-    YCbCrLayout layout;
-    ASSERT_NO_FATAL_FAILURE(layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
+    uint8_t* data;
 
-    auto yData = static_cast<uint8_t*>(layout.y);
-    auto cbData = static_cast<uint8_t*>(layout.cb);
-    auto crData = static_cast<uint8_t*>(layout.cr);
+    ASSERT_NO_FATAL_FAILURE(
+            data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
+
+    android_ycbcr yCbCr;
+    ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(bufferHandle, data, &yCbCr));
+
+    auto yData = static_cast<uint8_t*>(yCbCr.y);
+    auto cbData = static_cast<uint8_t*>(yCbCr.cb);
+    auto crData = static_cast<uint8_t*>(yCbCr.cr);
+    auto yStride = yCbCr.ystride;
+    auto cStride = yCbCr.cstride;
+    auto chromaStep = yCbCr.chroma_step;
+
     for (uint32_t y = 0; y < info.height; y++) {
         for (uint32_t x = 0; x < info.width; x++) {
             auto val = static_cast<uint8_t>(info.height * y + x);
 
-            yData[layout.yStride * y + x] = val;
-            if (y % 2 == 0 && x % 2 == 0) {
-                cbData[layout.cStride * y / 2 + x / 2] = val;
-                crData[layout.cStride * y / 2 + x / 2] = val;
+            yData[yStride * y + x] = val;
+
+            if (y % chromaStep && x % chromaStep == 0) {
+                cbData[cStride * y / chromaStep + x / chromaStep] = val;
+                crData[cStride * y / chromaStep + x / chromaStep] = val;
             }
         }
     }
@@ -381,19 +592,23 @@
     ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
 
     // lock again for reading
-    ASSERT_NO_FATAL_FAILURE(layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
+    ASSERT_NO_FATAL_FAILURE(
+            data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
 
-    yData = static_cast<uint8_t*>(layout.y);
-    cbData = static_cast<uint8_t*>(layout.cb);
-    crData = static_cast<uint8_t*>(layout.cr);
+    ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(bufferHandle, data, &yCbCr));
+
+    yData = static_cast<uint8_t*>(yCbCr.y);
+    cbData = static_cast<uint8_t*>(yCbCr.cb);
+    crData = static_cast<uint8_t*>(yCbCr.cr);
     for (uint32_t y = 0; y < info.height; y++) {
         for (uint32_t x = 0; x < info.width; x++) {
             auto val = static_cast<uint8_t>(info.height * y + x);
 
-            EXPECT_EQ(val, yData[layout.yStride * y + x]);
-            if (y % 2 == 0 && x % 2 == 0) {
-                EXPECT_EQ(val, cbData[layout.cStride * y / 2 + x / 2]);
-                EXPECT_EQ(val, crData[layout.cStride * y / 2 + x / 2]);
+            EXPECT_EQ(val, yData[yStride * y + x]);
+
+            if (y % chromaStep == 0 && x % chromaStep == 0) {
+                EXPECT_EQ(val, cbData[cStride * y / chromaStep + x / chromaStep]);
+                EXPECT_EQ(val, crData[cStride * y / chromaStep + x / chromaStep]);
             }
         }
     }
@@ -407,7 +622,7 @@
 /**
  * Test IMapper::unlock with bad access region
  */
-TEST_F(GraphicsMapperHidlTest, LockBadAccessRegion) {
+TEST_P(GraphicsMapperHidlTest, LockBadAccessRegion) {
     const auto& info = mDummyDescriptorInfo;
 
     const native_handle_t* bufferHandle;
@@ -427,8 +642,7 @@
 
     auto buffer = const_cast<native_handle_t*>(bufferHandle);
     mGralloc->getMapper()->lock(buffer, info.usage, accessRegion, acquireFenceHandle,
-                                [&](const auto& tmpError, const auto& /*tmpData*/,
-                                    int32_t /*tmpBytesPerPixel*/, int32_t /*tmpBytesPerStride*/) {
+                                [&](const auto& tmpError, const auto& /*tmpData*/) {
                                     EXPECT_EQ(Error::BAD_VALUE, tmpError)
                                             << "locking with a bad access region should fail";
                                 });
@@ -450,7 +664,7 @@
 /**
  * Test IMapper::unlock with invalid buffers.
  */
-TEST_F(GraphicsMapperHidlTest, UnlockNegative) {
+TEST_P(GraphicsMapperHidlTest, UnlockNegative) {
     native_handle_t* invalidHandle = nullptr;
     mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
         EXPECT_EQ(Error::BAD_BUFFER, tmpError)
@@ -486,9 +700,78 @@
 }
 
 /**
+ * Test IMapper::flush and IMapper::reread.
+ */
+TEST_P(GraphicsMapperHidlTest, FlushRereadBasic) {
+    const auto& info = mDummyDescriptorInfo;
+
+    const native_handle_t* rawHandle;
+    uint32_t stride;
+    ASSERT_NO_FATAL_FAILURE(
+            rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false, false, &stride));
+
+    const native_handle_t* writeBufferHandle;
+    const native_handle_t* readBufferHandle;
+    ASSERT_NO_FATAL_FAILURE(writeBufferHandle = mGralloc->importBuffer(rawHandle));
+    ASSERT_NO_FATAL_FAILURE(readBufferHandle = mGralloc->importBuffer(rawHandle));
+
+    // lock buffer for writing
+    const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+                               static_cast<int32_t>(info.height)};
+    uint8_t* writeData;
+    ASSERT_NO_FATAL_FAILURE(
+            writeData = static_cast<uint8_t*>(mGralloc->lock(
+                    writeBufferHandle, static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN), region,
+                    -1)));
+
+    uint8_t* readData;
+    ASSERT_NO_FATAL_FAILURE(
+            readData = static_cast<uint8_t*>(mGralloc->lock(
+                    readBufferHandle, static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN), region,
+                    -1)));
+
+    fillRGBA8888(writeData, info.height, stride * 4, info.width * 4);
+
+    int fence;
+    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->flushLockedBuffer(writeBufferHandle));
+    ASSERT_EQ(0, sync_wait(fence, 3500));
+    close(fence);
+
+    ASSERT_NO_FATAL_FAILURE(mGralloc->rereadLockedBuffer(readBufferHandle));
+
+    ASSERT_NO_FATAL_FAILURE(verifyRGBA8888(readData, info.height, stride * 4, info.width * 4));
+
+    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(readBufferHandle));
+    if (fence >= 0) {
+        close(fence);
+    }
+    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(writeBufferHandle));
+    if (fence >= 0) {
+        close(fence);
+    }
+}
+
+/**
+ * Test IMapper::flushLockedBuffer with bad buffer
+ */
+TEST_P(GraphicsMapperHidlTest, FlushLockedBufferBadBuffer) {
+    ASSERT_NO_FATAL_FAILURE(mGralloc->getMapper()->flushLockedBuffer(
+            nullptr, [&](const auto& tmpError, const auto& /*tmpReleaseFence*/) {
+                ASSERT_EQ(Error::BAD_BUFFER, tmpError);
+            }));
+}
+
+/**
+ * Test IMapper::rereadLockedBuffer with bad buffer
+ */
+TEST_P(GraphicsMapperHidlTest, RereadLockedBufferBadBuffer) {
+    ASSERT_EQ(Error::BAD_BUFFER, mGralloc->getMapper()->rereadLockedBuffer(nullptr));
+}
+
+/**
  * Test IMapper::isSupported with required format RGBA_8888
  */
-TEST_F(GraphicsMapperHidlTest, IsSupportedRGBA8888) {
+TEST_P(GraphicsMapperHidlTest, IsSupportedRGBA8888) {
     const auto& info = mDummyDescriptorInfo;
     bool supported = false;
 
@@ -499,7 +782,7 @@
 /**
  * Test IMapper::isSupported with required format YV12
  */
-TEST_F(GraphicsMapperHidlTest, IsSupportedYV12) {
+TEST_P(GraphicsMapperHidlTest, IsSupportedYV12) {
     auto info = mDummyDescriptorInfo;
     info.format = PixelFormat::YV12;
     bool supported = false;
@@ -511,7 +794,7 @@
 /**
  * Test IMapper::isSupported with optional format Y16
  */
-TEST_F(GraphicsMapperHidlTest, IsSupportedY16) {
+TEST_P(GraphicsMapperHidlTest, IsSupportedY16) {
     auto info = mDummyDescriptorInfo;
     info.format = PixelFormat::Y16;
     bool supported = false;
@@ -519,6 +802,1212 @@
     ASSERT_NO_FATAL_FAILURE(supported = mGralloc->isSupported(info));
 }
 
+/**
+ * Test IMapper::get(BufferId)
+ */
+TEST_P(GraphicsMapperHidlTest, GetBufferId) {
+    testGet(mDummyDescriptorInfo, gralloc4::MetadataType_BufferId,
+            [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                uint64_t bufferId = 0;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeBufferId(vec, &bufferId));
+            });
+}
+
+/**
+ * Test IMapper::get(Name)
+ */
+TEST_P(GraphicsMapperHidlTest, GetName) {
+    testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Name,
+            [](const IMapper::BufferDescriptorInfo& info, const hidl_vec<uint8_t>& vec) {
+                std::string name;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeName(vec, &name));
+                EXPECT_EQ(info.name, name);
+            });
+}
+
+/**
+ * Test IMapper::get(Width)
+ */
+TEST_P(GraphicsMapperHidlTest, GetWidth) {
+    testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Width,
+            [](const IMapper::BufferDescriptorInfo& info, const hidl_vec<uint8_t>& vec) {
+                uint64_t width = 0;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeWidth(vec, &width));
+                EXPECT_EQ(info.width, width);
+            });
+}
+
+/**
+ * Test IMapper::get(Height)
+ */
+TEST_P(GraphicsMapperHidlTest, GetHeight) {
+    testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Height,
+            [](const IMapper::BufferDescriptorInfo& info, const hidl_vec<uint8_t>& vec) {
+                uint64_t height = 0;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeHeight(vec, &height));
+                EXPECT_EQ(info.height, height);
+            });
+}
+
+/**
+ * Test IMapper::get(LayerCount)
+ */
+TEST_P(GraphicsMapperHidlTest, GetLayerCount) {
+    testGet(mDummyDescriptorInfo, gralloc4::MetadataType_LayerCount,
+            [](const IMapper::BufferDescriptorInfo& info, const hidl_vec<uint8_t>& vec) {
+                uint64_t layerCount = 0;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeLayerCount(vec, &layerCount));
+                EXPECT_EQ(info.layerCount, layerCount);
+            });
+}
+
+/**
+ * Test IMapper::get(PixelFormatRequested)
+ */
+TEST_P(GraphicsMapperHidlTest, GetPixelFormatRequested) {
+    testGet(mDummyDescriptorInfo, gralloc4::MetadataType_PixelFormatRequested,
+            [](const IMapper::BufferDescriptorInfo& info, const hidl_vec<uint8_t>& vec) {
+                PixelFormat pixelFormatRequested = PixelFormat::BLOB;
+                ASSERT_EQ(NO_ERROR,
+                          gralloc4::decodePixelFormatRequested(vec, &pixelFormatRequested));
+                EXPECT_EQ(info.format, pixelFormatRequested);
+            });
+}
+
+/**
+ * Test IMapper::get(PixelFormatFourCC)
+ */
+TEST_P(GraphicsMapperHidlTest, GetPixelFormatFourCC) {
+    testGet(mDummyDescriptorInfo, gralloc4::MetadataType_PixelFormatFourCC,
+            [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                uint32_t pixelFormatFourCC = 0;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodePixelFormatFourCC(vec, &pixelFormatFourCC));
+            });
+}
+
+/**
+ * Test IMapper::get(PixelFormatModifier)
+ */
+TEST_P(GraphicsMapperHidlTest, GetPixelFormatModifier) {
+    testGet(mDummyDescriptorInfo, gralloc4::MetadataType_PixelFormatModifier,
+            [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                uint64_t pixelFormatModifier = 0;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodePixelFormatModifier(vec, &pixelFormatModifier));
+            });
+}
+
+/**
+ * Test IMapper::get(Usage)
+ */
+TEST_P(GraphicsMapperHidlTest, GetUsage) {
+    testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Usage,
+            [](const IMapper::BufferDescriptorInfo& info, const hidl_vec<uint8_t>& vec) {
+                uint64_t usage = 0;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeUsage(vec, &usage));
+                EXPECT_EQ(info.usage, usage);
+            });
+}
+
+/**
+ * Test IMapper::get(AllocationSize)
+ */
+TEST_P(GraphicsMapperHidlTest, GetAllocationSize) {
+    testGet(mDummyDescriptorInfo, gralloc4::MetadataType_AllocationSize,
+            [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                uint64_t allocationSize = 0;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeAllocationSize(vec, &allocationSize));
+            });
+}
+
+/**
+ * Test IMapper::get(ProtectedContent)
+ */
+TEST_P(GraphicsMapperHidlTest, GetProtectedContent) {
+    auto info = mDummyDescriptorInfo;
+    info.usage = BufferUsage::PROTECTED | BufferUsage::COMPOSER_OVERLAY;
+
+    const native_handle_t* bufferHandle = nullptr;
+    bufferHandle = mGralloc->allocate(info, true, true);
+    if (bufferHandle) {
+        GTEST_SUCCEED() << "unable to allocate protected content";
+    }
+
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::NONE,
+              mGralloc->get(bufferHandle, gralloc4::MetadataType_ProtectedContent, &vec));
+
+    uint64_t protectedContent = 0;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodeProtectedContent(vec, &protectedContent));
+    EXPECT_EQ(1, protectedContent);
+}
+
+/**
+ * Test IMapper::get(Compression)
+ */
+TEST_P(GraphicsMapperHidlTest, GetCompression) {
+    auto info = mDummyDescriptorInfo;
+    info.usage = static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
+
+    testGet(info, gralloc4::MetadataType_Compression,
+            [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                ExtendableType compression = gralloc4::Compression_DisplayStreamCompression;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeCompression(vec, &compression));
+
+                EXPECT_EQ(gralloc4::Compression_None.name, compression.name);
+                EXPECT_EQ(gralloc4::Compression_None.value, compression.value);
+            });
+}
+
+/**
+ * Test IMapper::get(Interlaced)
+ */
+TEST_P(GraphicsMapperHidlTest, GetInterlaced) {
+    testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Interlaced,
+            [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                ExtendableType interlaced = gralloc4::Interlaced_TopBottom;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeInterlaced(vec, &interlaced));
+
+                EXPECT_EQ(gralloc4::Interlaced_None.name, interlaced.name);
+                EXPECT_EQ(gralloc4::Interlaced_None.value, interlaced.value);
+            });
+}
+
+/**
+ * Test IMapper::get(ChromaSiting)
+ */
+TEST_P(GraphicsMapperHidlTest, GetChromaSiting) {
+    testGet(mDummyDescriptorInfo, gralloc4::MetadataType_ChromaSiting,
+            [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                ExtendableType chromaSiting = gralloc4::ChromaSiting_Unknown;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeChromaSiting(vec, &chromaSiting));
+
+                EXPECT_EQ(gralloc4::ChromaSiting_None.name, chromaSiting.name);
+                EXPECT_EQ(gralloc4::ChromaSiting_None.value, chromaSiting.value);
+            });
+}
+
+/**
+ * Test IMapper::get(PlaneLayouts)
+ */
+TEST_P(GraphicsMapperHidlTest, GetPlaneLayouts) {
+    const native_handle_t* bufferHandle = nullptr;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
+
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec));
+
+    std::vector<PlaneLayout> planeLayouts;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts));
+
+    ASSERT_NO_FATAL_FAILURE(verifyDummyDescriptorInfoPlaneLayouts(planeLayouts));
+}
+
+/**
+ * Test IMapper::get(Dataspace)
+ */
+TEST_P(GraphicsMapperHidlTest, GetDataspace) {
+    testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Dataspace,
+            [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                Dataspace dataspace = Dataspace::DISPLAY_P3;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeDataspace(vec, &dataspace));
+                EXPECT_EQ(Dataspace::UNKNOWN, dataspace);
+            });
+}
+
+/**
+ * Test IMapper::get(BlendMode)
+ */
+TEST_P(GraphicsMapperHidlTest, GetBlendMode) {
+    testGet(mDummyDescriptorInfo, gralloc4::MetadataType_BlendMode,
+            [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                BlendMode blendMode = BlendMode::NONE;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeBlendMode(vec, &blendMode));
+                EXPECT_EQ(BlendMode::INVALID, blendMode);
+            });
+}
+
+/**
+ * Test IMapper::get(metadata) with a bad buffer
+ */
+TEST_P(GraphicsMapperHidlTest, GetMetadataBadValue) {
+    const native_handle_t* bufferHandle = nullptr;
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->get(bufferHandle, gralloc4::MetadataType_BufferId, &vec));
+    ASSERT_EQ(0, vec.size());
+    ASSERT_EQ(Error::BAD_BUFFER, mGralloc->get(bufferHandle, gralloc4::MetadataType_Name, &vec));
+    ASSERT_EQ(0, vec.size());
+    ASSERT_EQ(Error::BAD_BUFFER, mGralloc->get(bufferHandle, gralloc4::MetadataType_Width, &vec));
+    ASSERT_EQ(0, vec.size());
+    ASSERT_EQ(Error::BAD_BUFFER, mGralloc->get(bufferHandle, gralloc4::MetadataType_Height, &vec));
+    ASSERT_EQ(0, vec.size());
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->get(bufferHandle, gralloc4::MetadataType_LayerCount, &vec));
+    ASSERT_EQ(0, vec.size());
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->get(bufferHandle, gralloc4::MetadataType_PixelFormatRequested, &vec));
+    ASSERT_EQ(0, vec.size());
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->get(bufferHandle, gralloc4::MetadataType_PixelFormatFourCC, &vec));
+    ASSERT_EQ(0, vec.size());
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->get(bufferHandle, gralloc4::MetadataType_PixelFormatModifier, &vec));
+    ASSERT_EQ(0, vec.size());
+    ASSERT_EQ(Error::BAD_BUFFER, mGralloc->get(bufferHandle, gralloc4::MetadataType_Usage, &vec));
+    ASSERT_EQ(0, vec.size());
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->get(bufferHandle, gralloc4::MetadataType_AllocationSize, &vec));
+    ASSERT_EQ(0, vec.size());
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->get(bufferHandle, gralloc4::MetadataType_ProtectedContent, &vec));
+    ASSERT_EQ(0, vec.size());
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->get(bufferHandle, gralloc4::MetadataType_Compression, &vec));
+    ASSERT_EQ(0, vec.size());
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->get(bufferHandle, gralloc4::MetadataType_Interlaced, &vec));
+    ASSERT_EQ(0, vec.size());
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->get(bufferHandle, gralloc4::MetadataType_ChromaSiting, &vec));
+    ASSERT_EQ(0, vec.size());
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec));
+    ASSERT_EQ(0, vec.size());
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->get(bufferHandle, gralloc4::MetadataType_Dataspace, &vec));
+    ASSERT_EQ(0, vec.size());
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->get(bufferHandle, gralloc4::MetadataType_BlendMode, &vec));
+    ASSERT_EQ(0, vec.size());
+}
+
+/**
+ * Test IMapper::get(metadata) for unsupported metadata
+ */
+TEST_P(GraphicsMapperHidlTest, GetUnsupportedMetadata) {
+    const native_handle_t* bufferHandle = nullptr;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
+
+    MetadataType metadataTypeFake = {"FAKE", 1};
+
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::UNSUPPORTED, mGralloc->get(bufferHandle, metadataTypeFake, &vec));
+    ASSERT_EQ(0, vec.size());
+}
+
+/**
+ * Test IMapper::get(metadata) for unsupported standard metadata
+ */
+TEST_P(GraphicsMapperHidlTest, GetUnsupportedStandardMetadata) {
+    const native_handle_t* bufferHandle = nullptr;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
+
+    MetadataType metadataTypeFake = {GRALLOC4_STANDARD_METADATA_TYPE, 9999};
+
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::UNSUPPORTED, mGralloc->get(bufferHandle, metadataTypeFake, &vec));
+    ASSERT_EQ(0, vec.size());
+}
+
+/**
+ * Test IMapper::set(PixelFormatFourCC)
+ */
+TEST_P(GraphicsMapperHidlTest, SetPixelFormatFourCC) {
+    uint32_t pixelFormatFourCC = 0x34324142;  // DRM_FORMAT_BGRA8888
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodePixelFormatFourCC(pixelFormatFourCC, &vec));
+
+    testSet(mDummyDescriptorInfo, gralloc4::MetadataType_PixelFormatFourCC, vec,
+            [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                uint32_t realPixelFormatFourCC = 0;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodePixelFormatFourCC(vec, &realPixelFormatFourCC));
+                EXPECT_EQ(pixelFormatFourCC, realPixelFormatFourCC);
+            });
+}
+
+/**
+ * Test IMapper::set(PixelFormatModifier)
+ */
+TEST_P(GraphicsMapperHidlTest, SetPixelFormatModifier) {
+    uint64_t pixelFormatModifier = 10;
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodePixelFormatModifier(pixelFormatModifier, &vec));
+
+    testSet(mDummyDescriptorInfo, gralloc4::MetadataType_PixelFormatModifier, vec,
+            [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                uint64_t realPixelFormatModifier = 0;
+                ASSERT_EQ(NO_ERROR,
+                          gralloc4::decodePixelFormatModifier(vec, &realPixelFormatModifier));
+                EXPECT_EQ(pixelFormatModifier, realPixelFormatModifier);
+            });
+}
+
+/**
+ * Test IMapper::set(Usage) remove flag
+ */
+TEST_P(GraphicsMapperHidlTest, SetUsageRemoveBit) {
+    uint64_t usage = static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN);
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodeUsage(usage, &vec));
+
+    testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Usage, vec,
+            [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                uint64_t realUsage = 0;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeUsage(vec, &realUsage));
+                EXPECT_EQ(usage, realUsage);
+            });
+}
+/**
+ * Test IMapper::set(Usage) add flag
+ */
+TEST_P(GraphicsMapperHidlTest, SetUsageAddBit) {
+    uint64_t usage = mDummyDescriptorInfo.usage | static_cast<uint64_t>(BufferUsage::GPU_TEXTURE);
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodeUsage(usage, &vec));
+
+    testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Usage, vec,
+            [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                uint64_t realUsage = 0;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeUsage(vec, &realUsage));
+                EXPECT_EQ(usage, realUsage);
+            });
+}
+
+/**
+ * Test IMapper::set(Usage) to test protected content
+ */
+TEST_P(GraphicsMapperHidlTest, SetUsageProtected) {
+    const native_handle_t* bufferHandle = nullptr;
+    auto info = mDummyDescriptorInfo;
+    info.usage = BufferUsage::PROTECTED | BufferUsage::COMPOSER_OVERLAY;
+
+    bufferHandle = mGralloc->allocate(info, true, true);
+    if (bufferHandle) {
+        GTEST_SUCCEED() << "unable to allocate protected content";
+    }
+
+    uint64_t usage = static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY);
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodeUsage(usage, &vec));
+
+    Error err = mGralloc->set(bufferHandle, gralloc4::MetadataType_Usage, vec);
+    ASSERT_EQ(err, Error::UNSUPPORTED);
+    vec.resize(0);
+
+    uint64_t realUsage = 0;
+    ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, gralloc4::MetadataType_Usage, &vec));
+    ASSERT_EQ(NO_ERROR, gralloc4::decodeUsage(vec, &realUsage));
+    EXPECT_EQ(info.usage, realUsage);
+}
+
+/**
+ * Test IMapper::set(AllocationSize)
+ */
+TEST_P(GraphicsMapperHidlTest, SetAllocationSize) {
+    uint64_t allocationSize = 1000000;
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodeAllocationSize(allocationSize, &vec));
+
+    testSet(mDummyDescriptorInfo, gralloc4::MetadataType_AllocationSize, vec,
+            [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                uint64_t realAllocationSize = 0;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeAllocationSize(vec, &realAllocationSize));
+                EXPECT_EQ(allocationSize, realAllocationSize);
+            });
+}
+
+/**
+ * Test IMapper::set(ProtectedContent)
+ */
+TEST_P(GraphicsMapperHidlTest, SetProtectedContent) {
+    const native_handle_t* bufferHandle = nullptr;
+    auto info = mDummyDescriptorInfo;
+    info.usage = BufferUsage::PROTECTED | BufferUsage::COMPOSER_OVERLAY;
+
+    bufferHandle = mGralloc->allocate(info, true, true);
+    if (bufferHandle) {
+        GTEST_SUCCEED() << "unable to allocate protected content";
+    }
+
+    uint64_t protectedContent = 0;
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodeProtectedContent(protectedContent, &vec));
+
+    Error err = mGralloc->set(bufferHandle, gralloc4::MetadataType_ProtectedContent, vec);
+    ASSERT_EQ(err, Error::UNSUPPORTED);
+    vec.resize(0);
+
+    uint64_t realProtectedContent = 0;
+    ASSERT_EQ(Error::NONE,
+              mGralloc->get(bufferHandle, gralloc4::MetadataType_ProtectedContent, &vec));
+    ASSERT_EQ(NO_ERROR, gralloc4::decodeProtectedContent(vec, &realProtectedContent));
+    EXPECT_EQ(1, realProtectedContent);
+}
+
+/**
+ * Test IMapper::set(Compression)
+ */
+TEST_P(GraphicsMapperHidlTest, SetCompression) {
+    auto info = mDummyDescriptorInfo;
+    info.usage = static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
+
+    ExtendableType compression = gralloc4::Compression_DisplayStreamCompression;
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodeCompression(compression, &vec));
+
+    testSet(info, gralloc4::MetadataType_Compression, vec,
+            [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                ExtendableType realCompression = gralloc4::Compression_None;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeCompression(vec, &realCompression));
+
+                EXPECT_EQ(compression.name, realCompression.name);
+                EXPECT_EQ(compression.value, realCompression.value);
+            });
+}
+
+/**
+ * Test IMapper::set(Interlaced)
+ */
+TEST_P(GraphicsMapperHidlTest, SetInterlaced) {
+    ExtendableType interlaced = gralloc4::Interlaced_RightLeft;
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodeInterlaced(interlaced, &vec));
+
+    testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Interlaced, vec,
+            [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                ExtendableType realInterlaced = gralloc4::Interlaced_None;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeInterlaced(vec, &realInterlaced));
+
+                EXPECT_EQ(interlaced.name, realInterlaced.name);
+                EXPECT_EQ(interlaced.value, realInterlaced.value);
+            });
+}
+
+/**
+ * Test IMapper::set(ChromaSiting)
+ */
+TEST_P(GraphicsMapperHidlTest, SetChromaSiting) {
+    ExtendableType chromaSiting = gralloc4::ChromaSiting_SitedInterstitial;
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodeChromaSiting(chromaSiting, &vec));
+
+    testSet(mDummyDescriptorInfo, gralloc4::MetadataType_ChromaSiting, vec,
+            [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                ExtendableType realChromaSiting = gralloc4::ChromaSiting_None;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeChromaSiting(vec, &realChromaSiting));
+
+                EXPECT_EQ(chromaSiting.name, realChromaSiting.name);
+                EXPECT_EQ(chromaSiting.value, realChromaSiting.value);
+            });
+}
+
+/**
+ * Test IMapper::set(PlaneLayouts)
+ */
+TEST_P(GraphicsMapperHidlTest, SetPlaneLayouts) {
+    const native_handle_t* bufferHandle = nullptr;
+    auto info = mDummyDescriptorInfo;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true));
+
+    std::vector<PlaneLayout> planeLayouts;
+    PlaneLayout planeLayoutA;
+    PlaneLayout planeLayoutRGB;
+    PlaneLayoutComponent component;
+
+    planeLayoutA.offsetInBytes = 0;
+    planeLayoutA.sampleIncrementInBits = 8;
+    planeLayoutA.strideInBytes = info.width + 20;
+    planeLayoutA.widthInSamples = info.width;
+    planeLayoutA.heightInSamples = info.height;
+    planeLayoutA.totalSizeInBytes = planeLayoutA.strideInBytes * info.height;
+    planeLayoutA.horizontalSubsampling = 1;
+    planeLayoutA.verticalSubsampling = 1;
+    planeLayoutA.crop.left = 0;
+    planeLayoutA.crop.top = 0;
+    planeLayoutA.crop.right = info.width;
+    planeLayoutA.crop.bottom = info.height;
+
+    component.type = gralloc4::PlaneLayoutComponentType_A;
+    component.offsetInBits = 0;
+    component.sizeInBits = 8;
+    planeLayoutA.components.push_back(component);
+
+    planeLayouts.push_back(planeLayoutA);
+
+    planeLayoutRGB.offsetInBytes = 0;
+    planeLayoutRGB.sampleIncrementInBits = 32;
+    planeLayoutRGB.strideInBytes = info.width + 20;
+    planeLayoutRGB.widthInSamples = info.width;
+    planeLayoutRGB.heightInSamples = info.height;
+    planeLayoutRGB.totalSizeInBytes = planeLayoutRGB.strideInBytes * info.height;
+    planeLayoutRGB.horizontalSubsampling = 1;
+    planeLayoutRGB.verticalSubsampling = 1;
+    planeLayoutRGB.crop.left = 0;
+    planeLayoutRGB.crop.top = 0;
+    planeLayoutRGB.crop.right = info.width;
+    planeLayoutRGB.crop.bottom = info.height;
+
+    component.type = gralloc4::PlaneLayoutComponentType_R;
+    planeLayoutRGB.components.push_back(component);
+    component.type = gralloc4::PlaneLayoutComponentType_G;
+    planeLayoutRGB.components.push_back(component);
+    component.type = gralloc4::PlaneLayoutComponentType_B;
+    planeLayoutRGB.components.push_back(component);
+
+    planeLayouts.push_back(planeLayoutRGB);
+
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodePlaneLayouts(planeLayouts, &vec));
+
+    Error err = mGralloc->set(bufferHandle, gralloc4::MetadataType_PlaneLayouts, vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+    }
+    ASSERT_EQ(err, Error::NONE);
+
+    std::vector<PlaneLayout> realPlaneLayouts;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &realPlaneLayouts));
+
+    ASSERT_EQ(planeLayouts.size(), realPlaneLayouts.size());
+
+    for (int i = 0; i < realPlaneLayouts.size(); i++) {
+        const auto& planeLayout = planeLayouts[i];
+        const auto& realPlaneLayout = realPlaneLayouts[i];
+
+        EXPECT_EQ(planeLayout.offsetInBytes, realPlaneLayout.offsetInBytes);
+        EXPECT_EQ(planeLayout.sampleIncrementInBits, realPlaneLayout.sampleIncrementInBits);
+        EXPECT_EQ(planeLayout.strideInBytes, realPlaneLayout.strideInBytes);
+        EXPECT_EQ(planeLayout.widthInSamples, realPlaneLayout.widthInSamples);
+        EXPECT_EQ(planeLayout.heightInSamples, realPlaneLayout.heightInSamples);
+        EXPECT_LE(planeLayout.totalSizeInBytes, realPlaneLayout.totalSizeInBytes);
+        EXPECT_EQ(planeLayout.horizontalSubsampling, realPlaneLayout.horizontalSubsampling);
+        EXPECT_EQ(planeLayout.verticalSubsampling, realPlaneLayout.verticalSubsampling);
+
+        EXPECT_EQ(planeLayout.crop.left, realPlaneLayout.crop.left);
+        EXPECT_EQ(planeLayout.crop.top, realPlaneLayout.crop.top);
+        EXPECT_EQ(planeLayout.crop.right, realPlaneLayout.crop.right);
+        EXPECT_EQ(planeLayout.crop.bottom, realPlaneLayout.crop.bottom);
+
+        ASSERT_EQ(planeLayout.components.size(), realPlaneLayout.components.size());
+
+        for (int j = 0; j < realPlaneLayout.components.size(); j++) {
+            const auto& component = planeLayout.components[j];
+            const auto& realComponent = realPlaneLayout.components[j];
+
+            EXPECT_EQ(component.type.name, realComponent.type.name);
+            EXPECT_EQ(component.type.value, realComponent.type.value);
+            EXPECT_EQ(component.sizeInBits, realComponent.sizeInBits);
+            EXPECT_EQ(component.offsetInBits, realComponent.offsetInBits);
+        }
+    }
+}
+
+/**
+ * Test IMapper::set(Dataspace)
+ */
+TEST_P(GraphicsMapperHidlTest, SetDataspace) {
+    Dataspace dataspace = Dataspace::V0_SRGB_LINEAR;
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(dataspace, &vec));
+
+    testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Dataspace, vec,
+            [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                Dataspace realDataspace = Dataspace::UNKNOWN;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeDataspace(vec, &realDataspace));
+                EXPECT_EQ(dataspace, realDataspace);
+            });
+}
+
+/**
+ * Test IMapper::set(BlendMode)
+ */
+TEST_P(GraphicsMapperHidlTest, SetBlendMode) {
+    BlendMode blendMode = BlendMode::PREMULTIPLIED;
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodeBlendMode(blendMode, &vec));
+
+    testSet(mDummyDescriptorInfo, gralloc4::MetadataType_BlendMode, vec,
+            [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                BlendMode realBlendMode = BlendMode::INVALID;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeBlendMode(vec, &realBlendMode));
+                EXPECT_EQ(blendMode, realBlendMode);
+            });
+}
+
+/**
+ * Test IMapper::set(metadata) with a bad buffer
+ */
+TEST_P(GraphicsMapperHidlTest, SetMetadataNullBuffer) {
+    const native_handle_t* bufferHandle = nullptr;
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::BAD_BUFFER, mGralloc->set(bufferHandle, gralloc4::MetadataType_BufferId, vec));
+    ASSERT_EQ(Error::BAD_BUFFER, mGralloc->set(bufferHandle, gralloc4::MetadataType_Name, vec));
+    ASSERT_EQ(Error::BAD_BUFFER, mGralloc->set(bufferHandle, gralloc4::MetadataType_Width, vec));
+    ASSERT_EQ(Error::BAD_BUFFER, mGralloc->set(bufferHandle, gralloc4::MetadataType_Height, vec));
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_LayerCount, vec));
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatRequested, vec));
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatFourCC, vec));
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatModifier, vec));
+    ASSERT_EQ(Error::BAD_BUFFER, mGralloc->set(bufferHandle, gralloc4::MetadataType_Usage, vec));
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_AllocationSize, vec));
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_ProtectedContent, vec));
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_Compression, vec));
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_Interlaced, vec));
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_ChromaSiting, vec));
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_PlaneLayouts, vec));
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_Dataspace, vec));
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_BlendMode, vec));
+}
+
+/**
+ * Test IMapper::set(metadata) for constant metadata
+ */
+TEST_P(GraphicsMapperHidlTest, SetConstantMetadata) {
+    const native_handle_t* bufferHandle = nullptr;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
+
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_BufferId, vec));
+    ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_Name, vec));
+    ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_Width, vec));
+    ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_Height, vec));
+    ASSERT_EQ(Error::BAD_VALUE,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_LayerCount, vec));
+    ASSERT_EQ(Error::BAD_VALUE,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatRequested, vec));
+    ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_Usage, vec));
+}
+
+/**
+ * Test IMapper::set(metadata) for bad metadata
+ */
+TEST_P(GraphicsMapperHidlTest, SetBadMetadata) {
+    const native_handle_t* bufferHandle = nullptr;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
+
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::UNSUPPORTED,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_BufferId, vec));
+    ASSERT_EQ(Error::UNSUPPORTED, mGralloc->set(bufferHandle, gralloc4::MetadataType_Name, vec));
+    ASSERT_EQ(Error::UNSUPPORTED, mGralloc->set(bufferHandle, gralloc4::MetadataType_Width, vec));
+    ASSERT_EQ(Error::UNSUPPORTED, mGralloc->set(bufferHandle, gralloc4::MetadataType_Height, vec));
+    ASSERT_EQ(Error::UNSUPPORTED,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_LayerCount, vec));
+    ASSERT_EQ(Error::UNSUPPORTED,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatRequested, vec));
+    ASSERT_EQ(Error::UNSUPPORTED,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatFourCC, vec));
+    ASSERT_EQ(Error::UNSUPPORTED,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatModifier, vec));
+    ASSERT_EQ(Error::UNSUPPORTED, mGralloc->set(bufferHandle, gralloc4::MetadataType_Usage, vec));
+    ASSERT_EQ(Error::UNSUPPORTED,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_AllocationSize, vec));
+    ASSERT_EQ(Error::UNSUPPORTED,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_ProtectedContent, vec));
+    ASSERT_EQ(Error::UNSUPPORTED,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_Compression, vec));
+    ASSERT_EQ(Error::UNSUPPORTED,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_Interlaced, vec));
+    ASSERT_EQ(Error::UNSUPPORTED,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_ChromaSiting, vec));
+    ASSERT_EQ(Error::UNSUPPORTED,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_PlaneLayouts, vec));
+    ASSERT_EQ(Error::UNSUPPORTED,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_Dataspace, vec));
+    ASSERT_EQ(Error::UNSUPPORTED,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_BlendMode, vec));
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(BufferId)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoBufferId) {
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::UNSUPPORTED,
+              mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                    gralloc4::MetadataType_BufferId, &vec));
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(Name)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoName) {
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
+                                   mDummyDescriptorInfo, gralloc4::MetadataType_Name, &vec));
+
+    std::string name;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodeName(vec, &name));
+    EXPECT_EQ(mDummyDescriptorInfo.name, name);
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(Width)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoWidth) {
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
+                                   mDummyDescriptorInfo, gralloc4::MetadataType_Width, &vec));
+
+    uint64_t width = 0;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodeWidth(vec, &width));
+    EXPECT_EQ(mDummyDescriptorInfo.width, width);
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(Height)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoHeight) {
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
+                                   mDummyDescriptorInfo, gralloc4::MetadataType_Height, &vec));
+
+    uint64_t height = 0;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodeHeight(vec, &height));
+    EXPECT_EQ(mDummyDescriptorInfo.height, height);
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(PixelFormatRequested)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoPixelFormatRequested) {
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::NONE,
+              mGralloc->getFromBufferDescriptorInfo(
+                      mDummyDescriptorInfo, gralloc4::MetadataType_PixelFormatRequested, &vec));
+
+    PixelFormat pixelFormatRequested = PixelFormat::BLOB;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodePixelFormatRequested(vec, &pixelFormatRequested));
+    EXPECT_EQ(mDummyDescriptorInfo.format, pixelFormatRequested);
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(PixelFormatFourCC)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoPixelFormatFourCC) {
+    hidl_vec<uint8_t> vec;
+    Error err = mGralloc->getFromBufferDescriptorInfo(
+            mDummyDescriptorInfo, gralloc4::MetadataType_PixelFormatFourCC, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+    }
+    ASSERT_EQ(err, Error::NONE);
+
+    uint32_t pixelFormatFourCC = 0;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodePixelFormatFourCC(vec, &pixelFormatFourCC));
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(PixelFormatModifier)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoPixelFormatModifier) {
+    hidl_vec<uint8_t> vec;
+    Error err = mGralloc->getFromBufferDescriptorInfo(
+            mDummyDescriptorInfo, gralloc4::MetadataType_PixelFormatModifier, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+    }
+    ASSERT_EQ(err, Error::NONE);
+
+    uint64_t pixelFormatModifier = 0;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodePixelFormatModifier(vec, &pixelFormatModifier));
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(Usage)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoUsage) {
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
+                                   mDummyDescriptorInfo, gralloc4::MetadataType_Usage, &vec));
+
+    uint64_t usage = 0;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodeUsage(vec, &usage));
+    EXPECT_EQ(mDummyDescriptorInfo.usage, usage);
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(AllocationSize)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoAllocationSize) {
+    hidl_vec<uint8_t> vec;
+    Error err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                      gralloc4::MetadataType_AllocationSize, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+    }
+    ASSERT_EQ(err, Error::NONE);
+
+    uint64_t allocationSize = 0;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodeAllocationSize(vec, &allocationSize));
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(ProtectedContent)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoProtectedContent) {
+    auto info = mDummyDescriptorInfo;
+    info.usage = BufferUsage::PROTECTED | BufferUsage::COMPOSER_OVERLAY;
+
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
+                                   info, gralloc4::MetadataType_ProtectedContent, &vec));
+
+    uint64_t protectedContent = 0;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodeProtectedContent(vec, &protectedContent));
+    EXPECT_EQ(1, protectedContent);
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(Compression)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoCompression) {
+    auto info = mDummyDescriptorInfo;
+    info.usage = static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
+
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
+                                   info, gralloc4::MetadataType_Compression, &vec));
+
+    ExtendableType compression = gralloc4::Compression_DisplayStreamCompression;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodeCompression(vec, &compression));
+
+    EXPECT_EQ(gralloc4::Compression_None.name, compression.name);
+    EXPECT_EQ(gralloc4::Compression_None.value, compression.value);
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(Interlaced)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoInterlaced) {
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
+                                   mDummyDescriptorInfo, gralloc4::MetadataType_Interlaced, &vec));
+
+    ExtendableType interlaced = gralloc4::Interlaced_TopBottom;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodeInterlaced(vec, &interlaced));
+
+    EXPECT_EQ(gralloc4::Interlaced_None.name, interlaced.name);
+    EXPECT_EQ(gralloc4::Interlaced_None.value, interlaced.value);
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(ChromaSiting)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoChromaSiting) {
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::NONE,
+              mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                    gralloc4::MetadataType_ChromaSiting, &vec));
+
+    ExtendableType chromaSiting = gralloc4::ChromaSiting_CositedHorizontal;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodeChromaSiting(vec, &chromaSiting));
+
+    EXPECT_EQ(gralloc4::ChromaSiting_None.name, chromaSiting.name);
+    EXPECT_EQ(gralloc4::ChromaSiting_None.value, chromaSiting.value);
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(PlaneLayouts)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoPlaneLayouts) {
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::NONE,
+              mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                    gralloc4::MetadataType_PlaneLayouts, &vec));
+
+    std::vector<PlaneLayout> planeLayouts;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts));
+    ASSERT_NO_FATAL_FAILURE(verifyDummyDescriptorInfoPlaneLayouts(planeLayouts));
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(Dataspace)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoDataspace) {
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
+                                   mDummyDescriptorInfo, gralloc4::MetadataType_Dataspace, &vec));
+
+    Dataspace dataspace = Dataspace::DISPLAY_P3;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodeDataspace(vec, &dataspace));
+    EXPECT_EQ(Dataspace::UNKNOWN, dataspace);
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(BlendMode)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoBlendMode) {
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
+                                   mDummyDescriptorInfo, gralloc4::MetadataType_BlendMode, &vec));
+
+    BlendMode blendMode = BlendMode::COVERAGE;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodeBlendMode(vec, &blendMode));
+    EXPECT_EQ(BlendMode::INVALID, blendMode);
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(metadata) for unsupported metadata
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoUnsupportedMetadata) {
+    MetadataType metadataTypeFake = {"FAKE", 1};
+
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::UNSUPPORTED,
+              mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo, metadataTypeFake, &vec));
+    ASSERT_EQ(0, vec.size());
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(metadata) for unsupported standard metadata
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoUnsupportedStandardMetadata) {
+    MetadataType metadataTypeFake = {GRALLOC4_STANDARD_METADATA_TYPE, 9999};
+
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::UNSUPPORTED,
+              mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo, metadataTypeFake, &vec));
+    ASSERT_EQ(0, vec.size());
+}
+
+/**
+ * Test IMapper::listSupportedMetadataTypes()
+ */
+TEST_P(GraphicsMapperHidlTest, ListSupportedMetadataTypes) {
+    hidl_vec<IMapper::MetadataTypeDescription> descriptions;
+    mGralloc->getMapper()->listSupportedMetadataTypes(
+            [&](const auto& tmpError, const auto& tmpDescriptions) {
+                ASSERT_EQ(Error::NONE, tmpError);
+                descriptions = tmpDescriptions;
+            });
+
+    std::set<StandardMetadataType> foundMetadataTypes;
+
+    std::set<StandardMetadataType> notSettableMetadataTypes{
+            StandardMetadataType::BUFFER_ID,   StandardMetadataType::NAME,
+            StandardMetadataType::WIDTH,       StandardMetadataType::HEIGHT,
+            StandardMetadataType::LAYER_COUNT, StandardMetadataType::PIXEL_FORMAT_REQUESTED,
+            StandardMetadataType::USAGE};
+
+    ASSERT_LE(sRequiredMetadataTypes.size(), descriptions.size());
+
+    for (const auto& description : descriptions) {
+        const auto& metadataType = description.metadataType;
+
+        if (!gralloc4::isStandardMetadataType(metadataType)) {
+            EXPECT_GT(0, description.description.size());
+            continue;
+        }
+
+        StandardMetadataType type = gralloc4::getStandardMetadataTypeValue(metadataType);
+
+        if (sRequiredMetadataTypes.find(type) == sRequiredMetadataTypes.end()) {
+            continue;
+        }
+
+        ASSERT_EQ(foundMetadataTypes.find(type), foundMetadataTypes.end());
+        foundMetadataTypes.insert(type);
+
+        ASSERT_TRUE(description.isGettable);
+
+        if (notSettableMetadataTypes.find(type) != notSettableMetadataTypes.end()) {
+            ASSERT_FALSE(description.isSettable);
+        }
+    }
+
+    ASSERT_EQ(sRequiredMetadataTypes, foundMetadataTypes);
+}
+
+/**
+ * Test IMapper::dumpBuffer()
+ */
+TEST_P(GraphicsMapperHidlTest, DumpBuffer) {
+    const native_handle_t* bufferHandle = nullptr;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    IMapper::BufferDump bufferDump;
+    mGralloc->getMapper()->dumpBuffer(buffer, [&](const auto& tmpError, const auto& tmpBufferDump) {
+        ASSERT_EQ(Error::NONE, tmpError);
+        bufferDump = tmpBufferDump;
+    });
+
+    ASSERT_NO_FATAL_FAILURE(verifyBufferDump(bufferDump, buffer));
+}
+
+/**
+ * Test IMapper::dumpBuffer() with an invalid buffer
+ */
+TEST_P(GraphicsMapperHidlTest, DumpBufferNullBuffer) {
+    native_handle_t* bufferHandle = nullptr;
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    mGralloc->getMapper()->dumpBuffer(buffer,
+                                      [&](const auto& tmpError, const auto& /*tmpBufferDump*/) {
+                                          ASSERT_EQ(Error::BAD_BUFFER, tmpError);
+                                      });
+}
+
+/**
+ * Test IMapper::dumpBuffer() multiple
+ */
+TEST_P(GraphicsMapperHidlTest, DumpBuffers) {
+    size_t bufferCount = 10;
+
+    for (int i = 0; i < bufferCount; i++) {
+        ASSERT_NO_FATAL_FAILURE(mGralloc->allocate(mDummyDescriptorInfo, true));
+    }
+
+    hidl_vec<IMapper::BufferDump> bufferDump;
+    mGralloc->getMapper()->dumpBuffers([&](const auto& tmpError, const auto& tmpBufferDump) {
+        ASSERT_EQ(Error::NONE, tmpError);
+        bufferDump = tmpBufferDump;
+    });
+
+    ASSERT_EQ(bufferCount, bufferDump.size());
+
+    for (const auto& dump : bufferDump) {
+        ASSERT_NO_FATAL_FAILURE(verifyBufferDump(dump));
+    }
+}
+
+/**
+ * Test IMapper::getReservedRegion()
+ */
+TEST_P(GraphicsMapperHidlTest, GetReservedRegion) {
+    const native_handle_t* bufferHandle = nullptr;
+    auto info = mDummyDescriptorInfo;
+
+    const int pageSize = getpagesize();
+    ASSERT_GE(0, pageSize);
+    std::vector<uint64_t> requestedReservedSizes{1, 10, 333, static_cast<uint64_t>(pageSize) / 2,
+                                                 static_cast<uint64_t>(pageSize)};
+
+    for (auto requestedReservedSize : requestedReservedSizes) {
+        info.reservedSize = requestedReservedSize;
+
+        ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true));
+
+        void* reservedRegion = nullptr;
+        uint64_t reservedSize = 0;
+        ASSERT_EQ(Error::NONE,
+                  mGralloc->getReservedRegion(bufferHandle, &reservedRegion, &reservedSize));
+        ASSERT_NE(nullptr, reservedRegion);
+        ASSERT_EQ(requestedReservedSize, reservedSize);
+
+        uint8_t testValue = 1;
+        memset(reservedRegion, testValue, reservedSize);
+        for (uint64_t i = 0; i < reservedSize; i++) {
+            ASSERT_EQ(testValue, static_cast<uint8_t*>(reservedRegion)[i]);
+        }
+    }
+}
+
+/**
+ * Test IMapper::getReservedRegion() request over a page
+ */
+TEST_P(GraphicsMapperHidlTest, GetLargeReservedRegion) {
+    const native_handle_t* bufferHandle = nullptr;
+    auto info = mDummyDescriptorInfo;
+
+    const int pageSize = getpagesize();
+    ASSERT_GE(0, pageSize);
+    std::vector<uint64_t> requestedReservedSizes{static_cast<uint64_t>(pageSize) * 2,
+                                                 static_cast<uint64_t>(pageSize) * 10,
+                                                 static_cast<uint64_t>(pageSize) * 1000};
+
+    for (auto requestedReservedSize : requestedReservedSizes) {
+        info.reservedSize = requestedReservedSize;
+
+        BufferDescriptor descriptor;
+        ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(info));
+
+        Error err;
+        mGralloc->getAllocator()->allocate(
+                descriptor, 1,
+                [&](const auto& tmpError, const auto&, const auto&) { err = tmpError; });
+        if (err == Error::UNSUPPORTED) {
+            continue;
+        }
+        ASSERT_EQ(Error::NONE, err);
+
+        void* reservedRegion = nullptr;
+        uint64_t reservedSize = 0;
+        err = mGralloc->getReservedRegion(bufferHandle, &reservedRegion, &reservedSize);
+
+        ASSERT_EQ(Error::NONE, err);
+        ASSERT_NE(nullptr, reservedRegion);
+        ASSERT_EQ(requestedReservedSize, reservedSize);
+    }
+}
+
+/**
+ * Test IMapper::getReservedRegion() across multiple mappers
+ */
+TEST_P(GraphicsMapperHidlTest, GetReservedRegionMultiple) {
+    const native_handle_t* bufferHandle = nullptr;
+    auto info = mDummyDescriptorInfo;
+
+    const int pageSize = getpagesize();
+    ASSERT_GE(0, pageSize);
+    info.reservedSize = pageSize;
+
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true));
+
+    void* reservedRegion1 = nullptr;
+    uint64_t reservedSize1 = 0;
+    ASSERT_EQ(Error::NONE,
+              mGralloc->getReservedRegion(bufferHandle, &reservedRegion1, &reservedSize1));
+    ASSERT_NE(nullptr, reservedRegion1);
+    ASSERT_EQ(info.reservedSize, reservedSize1);
+
+    std::unique_ptr<Gralloc> anotherGralloc;
+    ASSERT_NO_FATAL_FAILURE(anotherGralloc = std::make_unique<Gralloc>(std::get<0>(GetParam()),
+                                                                       std::get<1>(GetParam())));
+
+    void* reservedRegion2 = nullptr;
+    uint64_t reservedSize2 = 0;
+    ASSERT_EQ(Error::NONE,
+              mGralloc->getReservedRegion(bufferHandle, &reservedRegion2, &reservedSize2));
+    ASSERT_EQ(reservedRegion1, reservedRegion2);
+    ASSERT_EQ(reservedSize1, reservedSize2);
+}
+
+/**
+ * Test IMapper::getReservedRegion() with a bad buffer
+ */
+TEST_P(GraphicsMapperHidlTest, GetReservedRegionBadBuffer) {
+    const native_handle_t* bufferHandle = nullptr;
+
+    void* reservedRegion = nullptr;
+    uint64_t reservedSize = 0;
+    ASSERT_EQ(Error::BAD_BUFFER,
+              mGralloc->getReservedRegion(bufferHandle, &reservedRegion, &reservedSize));
+    ASSERT_EQ(nullptr, reservedRegion);
+    ASSERT_EQ(0, reservedSize);
+}
+
+INSTANTIATE_TEST_CASE_P(
+        PerInstance, GraphicsMapperHidlTest,
+        testing::Combine(
+                testing::ValuesIn(
+                        android::hardware::getAllHalInstanceNames(IAllocator::descriptor)),
+                testing::ValuesIn(android::hardware::getAllHalInstanceNames(IMapper::descriptor))),
+        android::hardware::PrintInstanceTupleNameToString<>);
+
 }  // namespace
 }  // namespace vts
 }  // namespace V4_0
@@ -526,13 +2015,3 @@
 }  // namespace graphics
 }  // namespace hardware
 }  // namespace android
-
-int main(int argc, char** argv) {
-    using android::hardware::graphics::mapper::V4_0::vts::GraphicsMapperHidlEnvironment;
-    ::testing::AddGlobalTestEnvironment(GraphicsMapperHidlEnvironment::Instance());
-    ::testing::InitGoogleTest(&argc, argv);
-    GraphicsMapperHidlEnvironment::Instance()->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    LOG(INFO) << "Test result = " << status;
-    return status;
-}
diff --git a/health/1.0/default/Android.bp b/health/1.0/default/Android.bp
index 049e393..7581335 100644
--- a/health/1.0/default/Android.bp
+++ b/health/1.0/default/Android.bp
@@ -18,3 +18,55 @@
 
 }
 
+cc_library_static {
+    name: "android.hardware.health@1.0-impl-helper",
+    vendor: true,
+    srcs: ["Health.cpp"],
+
+    header_libs: [
+        "libbase_headers",
+        "libhealthd_headers",
+    ],
+
+    shared_libs: [
+        "libcutils",
+        "libhidlbase",
+        "liblog",
+        "libutils",
+        "android.hardware.health@1.0",
+    ],
+
+    static_libs: [
+        "android.hardware.health@1.0-convert",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.health@1.0-impl",
+    vendor: true,
+    relative_install_path: "hw",
+
+    static_libs: [
+        "android.hardware.health@1.0-impl-helper",
+        "android.hardware.health@1.0-convert",
+        "libhealthd.default",
+    ],
+}
+
+cc_binary {
+    name: "android.hardware.health@1.0-service",
+    vendor: true,
+    relative_install_path: "hw",
+    init_rc: ["android.hardware.health@1.0-service.rc"],
+    srcs: ["HealthService.cpp"],
+
+    shared_libs: [
+        "liblog",
+        "libcutils",
+        "libdl",
+        "libbase",
+        "libutils",
+        "libhidlbase",
+        "android.hardware.health@1.0",
+    ],
+}
diff --git a/health/1.0/default/Android.mk b/health/1.0/default/Android.mk
deleted file mode 100644
index bbf37af..0000000
--- a/health/1.0/default/Android.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.health@1.0-impl
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_C_INCLUDES := system/core/base/include
-LOCAL_SRC_FILES := \
-    Health.cpp \
-
-LOCAL_HEADER_LIBRARIES := libhealthd_headers
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    libhidlbase \
-    liblog \
-    libutils \
-    android.hardware.health@1.0 \
-
-LOCAL_STATIC_LIBRARIES := android.hardware.health@1.0-convert
-
-LOCAL_HAL_STATIC_LIBRARIES := libhealthd
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_MODULE := android.hardware.health@1.0-service
-LOCAL_INIT_RC := android.hardware.health@1.0-service.rc
-LOCAL_SRC_FILES := \
-    HealthService.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-    liblog \
-    libcutils \
-    libdl \
-    libbase \
-    libutils \
-    libhidlbase \
-    android.hardware.health@1.0 \
-
-include $(BUILD_EXECUTABLE)
-
-include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/health/1.0/default/README.md b/health/1.0/default/README.md
new file mode 100644
index 0000000..1ded7de
--- /dev/null
+++ b/health/1.0/default/README.md
@@ -0,0 +1,66 @@
+# Implement the 2.1 HAL instead!
+
+It is strongly recommended that you implement the 2.1 HAL directly. See
+`hardware/interfaces/health/2.1/README.md` for more details.
+
+# Implement Health 1.0 HAL
+
+1. Install common binderized service. The binderized service `dlopen()`s
+   passthrough implementations on the device, so there is no need to write
+   your own.
+
+    ```mk
+    # Install default binderized implementation to vendor.
+    PRODUCT_PACKAGES += android.hardware.health@1.0-service
+    ```
+
+1. Add proper VINTF manifest entry to your device manifest. Example:
+
+    ```xml
+    <hal format="hidl">
+        <name>android.hardware.health</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IHealth</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    ```
+
+1. Install the proper passthrough implemetation.
+
+    1. If you want to use the default implementation (with default `libhealthd`),
+       add the following to `device.mk`:
+
+        ```mk
+        PRODUCT_PACKAGES += \
+            android.hardware.health@1.0-impl
+        ```
+
+    1. Otherwise, if you have a customized `libhealthd.<board>`:
+
+        1. Define your passthrough implementation. Example (replace `<device>`
+           and `<board>` accordingly):
+
+            ```bp
+            cc_library_shared {
+                name: "android.hardware.health@1.0-impl-<device>",
+                vendor: true,
+                relative_install_path: "hw",
+
+                static_libs: [
+                    "android.hardware.health@1.0-impl-helper",
+                    "android.hardware.health@1.0-convert",
+                    "libhealthd.<board>",
+                ],
+            }
+            ```
+
+        1. Add to `device.mk`.
+
+            ```
+            PRODUCT_PACKAGES += android.hardware.health@1.0-impl-<device>
+            ```
+
+        1. Define appropriate SELinux permissions.
diff --git a/health/2.0/default/healthd_common_adapter.cpp b/health/2.0/default/healthd_common_adapter.cpp
index 8fc689d..0b5d869 100644
--- a/health/2.0/default/healthd_common_adapter.cpp
+++ b/health/2.0/default/healthd_common_adapter.cpp
@@ -49,11 +49,14 @@
 static std::unique_ptr<HealthLoopAdapter> health_loop;
 
 int healthd_register_event(int fd, void (*handler)(uint32_t), EventWakeup wakeup) {
+    if (!health_loop) return -1;
+
     auto wrapped_handler = [handler](auto*, uint32_t epevents) { handler(epevents); };
     return health_loop->RegisterEvent(fd, wrapped_handler, wakeup);
 }
 
 void healthd_battery_update_internal(bool charger_online) {
+    if (!health_loop) return;
     health_loop->AdjustWakealarmPeriods(charger_online);
 }
 
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index a7cbb36..4409bde 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -527,9 +527,9 @@
         HidlBuf key_blob;
         KeyCharacteristics key_characteristics;
         ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                 .RsaSigningKey(key_size, 3)
-                                                 .Digest(Digest::NONE)
-                                                 .Padding(PaddingMode::NONE),
+                                                     .RsaSigningKey(key_size, 65537)
+                                                     .Digest(Digest::NONE)
+                                                     .Padding(PaddingMode::NONE),
                                              &key_blob, &key_characteristics));
 
         ASSERT_GT(key_blob.size(), 0U);
@@ -579,11 +579,12 @@
     for (auto key_size : InvalidKeySizes(Algorithm::RSA)) {
         HidlBuf key_blob;
         KeyCharacteristics key_characteristics;
-        ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE, GenerateKey(AuthorizationSetBuilder()
-                                                                   .RsaSigningKey(key_size, 3)
-                                                                   .Digest(Digest::NONE)
-                                                                   .Padding(PaddingMode::NONE),
-                                                               &key_blob, &key_characteristics));
+        ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
+                  GenerateKey(AuthorizationSetBuilder()
+                                      .RsaSigningKey(key_size, 65537)
+                                      .Digest(Digest::NONE)
+                                      .Padding(PaddingMode::NONE),
+                              &key_blob, &key_characteristics));
     }
 }
 
@@ -4338,25 +4339,29 @@
  * to specify how many following bytes will be used to encode the length.
  */
 TEST_F(AttestationTest, AttestationApplicationIDLengthProperlyEncoded) {
-    auto creation_time = std::chrono::system_clock::now();
-    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
-                                                 .EcdsaSigningKey(EcCurve::P_256)
-                                                 .Digest(Digest::SHA_2_256)));
+    std::vector<uint32_t> app_id_lengths{143, 258};
+    for (uint32_t length : app_id_lengths) {
+        auto creation_time = std::chrono::system_clock::now();
+        ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                     .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                     .EcdsaSigningKey(EcCurve::P_256)
+                                                     .Digest(Digest::SHA_2_256)));
 
-    hidl_vec<hidl_vec<uint8_t>> cert_chain;
-    const string app_id(143, 'a');
-    ASSERT_EQ(ErrorCode::OK,
-              AttestKey(AuthorizationSetBuilder()
-                                .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
-                                .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf(app_id)),
-                        &cert_chain));
-    EXPECT_GE(cert_chain.size(), 2U);
+        hidl_vec<hidl_vec<uint8_t>> cert_chain;
+        const string app_id(length, 'a');
+        ASSERT_EQ(ErrorCode::OK,
+                  AttestKey(AuthorizationSetBuilder()
+                                    .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
+                                    .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf(app_id)),
+                            &cert_chain));
+        EXPECT_GE(cert_chain.size(), 2U);
 
-    EXPECT_TRUE(verify_attestation_record("challenge", app_id,                    //
-                                          key_characteristics_.softwareEnforced,  //
-                                          key_characteristics_.hardwareEnforced,  //
-                                          SecLevel(), cert_chain[0], creation_time));
+        EXPECT_TRUE(verify_attestation_record("challenge", app_id,                    //
+                                              key_characteristics_.softwareEnforced,  //
+                                              key_characteristics_.hardwareEnforced,  //
+                                              SecLevel(), cert_chain[0], creation_time));
+        CheckedDeleteKey();
+    }
 }
 /*
  * AttestationTest.AesAttestation
@@ -4600,6 +4605,57 @@
     }
 }
 
+typedef KeymasterHidlTest TransportLimitTest;
+
+/*
+ * TransportLimitTest.LargeFinishInput
+ *
+ * Verifies that passing large input data to finish either succeeds or fails as expected.
+ */
+TEST_F(TransportLimitTest, LargeFinishInput) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                 .AesEncryptionKey(128)
+                                                 .BlockMode(BlockMode::ECB)
+                                                 .Padding(PaddingMode::NONE)));
+
+    for (int msg_size = 10 /*1KB*/; msg_size <= 17 /*128KB*/; msg_size++) {
+        auto cipher_params =
+                AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE);
+
+        AuthorizationSet out_params;
+        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, cipher_params, &out_params));
+
+        string plain_message = std::string(1 << msg_size, 'x');
+        string encrypted_message;
+        auto rc = Finish(plain_message, &encrypted_message);
+
+        if (rc == ErrorCode::OK) {
+            EXPECT_EQ(plain_message.size(), encrypted_message.size())
+                    << "Encrypt finish returned OK, but did not consume all of the given input";
+        } else {
+            EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, rc)
+                    << "Encrypt finish failed in an unexpected way when given a large input";
+            continue;
+        }
+        cipher_params.push_back(out_params);
+
+        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, cipher_params));
+
+        string decrypted_message;
+        rc = Finish(encrypted_message, &decrypted_message);
+
+        if (rc == ErrorCode::OK) {
+            EXPECT_EQ(plain_message.size(), decrypted_message.size())
+                    << "Decrypt finish returned OK, did not consume all of the given input";
+        } else {
+            EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, rc)
+                    << "Encrypt finish failed in an unexpected way when given a large input";
+        }
+    }
+
+    CheckedDeleteKey();
+}
 
 }  // namespace test
 }  // namespace V4_0
diff --git a/vibrator/1.4/vts/functional/Android.bp b/keymaster/4.0/vts/performance/Android.bp
similarity index 65%
copy from vibrator/1.4/vts/functional/Android.bp
copy to keymaster/4.0/vts/performance/Android.bp
index 202a824..9434bc9 100644
--- a/vibrator/1.4/vts/functional/Android.bp
+++ b/keymaster/4.0/vts/performance/Android.bp
@@ -14,20 +14,16 @@
 // limitations under the License.
 //
 
-cc_test {
-    name: "VtsHalVibratorV1_4TargetTest",
+cc_benchmark {
+    name: "keymaster_benchmark",
     defaults: ["VtsHalTargetTestDefaults"],
-    srcs: ["VtsHalVibratorV1_4TargetTest.cpp"],
-    static_libs: [
-        "android.hardware.vibrator@1.0",
-        "android.hardware.vibrator@1.1",
-        "android.hardware.vibrator@1.2",
-        "android.hardware.vibrator@1.3",
-        "android.hardware.vibrator@1.4",
+    srcs: [
+        "Benchmark.cpp",
     ],
-    test_suites: [
-        "general-tests",
-        "vts-core",
+    static_libs: [
+        "android.hardware.keymaster@4.0",
+        "libkeymaster4support",
+        "libsoftkeymasterdevice",
+        "libchrome"
     ],
 }
-
diff --git a/keymaster/4.0/vts/performance/Benchmark.cpp b/keymaster/4.0/vts/performance/Benchmark.cpp
new file mode 100644
index 0000000..96ef5bf
--- /dev/null
+++ b/keymaster/4.0/vts/performance/Benchmark.cpp
@@ -0,0 +1,717 @@
+/*
+ * 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 "keymaster_benchmark"
+
+#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+#include <android/hardware/keymaster/4.0/types.h>
+#include <keymaster/keymaster_configuration.h>
+#include <keymasterV4_0/authorization_set.h>
+
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <binder/IServiceManager.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <iostream>
+
+#include <log/log.h>
+#include <utils/StrongPointer.h>
+
+#include <benchmark/benchmark.h>
+#include <hidl/Status.h>
+
+#include <base/command_line.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+namespace test {
+
+// libutils:
+using android::OK;
+using android::sp;
+using android::status_t;
+
+// libhidl:
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+
+// IKeymaster:
+using android::IServiceManager;
+using android::hardware::hidl_string;
+using android::hardware::keymaster::V4_0::AuthorizationSet;
+using android::hardware::keymaster::V4_0::AuthorizationSetBuilder;
+using android::hardware::keymaster::V4_0::BlockMode;
+using android::hardware::keymaster::V4_0::ErrorCode;
+using android::hardware::keymaster::V4_0::IKeymasterDevice;
+using android::hardware::keymaster::V4_0::KeyCharacteristics;
+using android::hardware::keymaster::V4_0::SecurityLevel;
+
+// Standard library:
+using std::cerr;
+using std::cout;
+using std::endl;
+using std::optional;
+using std::string;
+using std::unique_ptr;
+using std::vector;
+
+class HidlBuf : public hidl_vec<uint8_t> {
+    typedef hidl_vec<uint8_t> super;
+
+  public:
+    HidlBuf() {}
+    HidlBuf(const super& other) : super(other) {}
+    HidlBuf(super&& other) : super(std::move(other)) {}
+    explicit HidlBuf(const std::string& other) : HidlBuf() { *this = other; }
+
+    HidlBuf& operator=(const super& other) {
+        super::operator=(other);
+        return *this;
+    }
+
+    HidlBuf& operator=(super&& other) {
+        super::operator=(std::move(other));
+        return *this;
+    }
+
+    HidlBuf& operator=(const string& other) {
+        resize(other.size());
+        std::copy(other.begin(), other.end(), begin());
+        return *this;
+    }
+
+    string to_string() const { return string(reinterpret_cast<const char*>(data()), size()); }
+};
+
+#define SMALL_MESSAGE_SIZE 64
+#define MEDIUM_MESSAGE_SIZE 1024
+#define LARGE_MESSAGE_SIZE 131072
+
+class KeymasterWrapper {
+  private:
+    sp<IKeymasterDevice> keymaster_;
+    SecurityLevel securityLevel_;
+    hidl_string name_;
+    hidl_string author_;
+    HidlBuf key_blob_;
+    KeyCharacteristics key_characteristics_;
+    ErrorCode error_;
+    string key_transform_;
+    string keymaster_name_;
+    uint32_t os_version_;
+    uint32_t os_patch_level_;
+    std::vector<string> message_cache_;
+
+    bool GenerateKey(const AuthorizationSet& authSet) {
+        return (keymaster_
+                        ->generateKey(
+                                authSet.hidl_data(),
+                                [&](ErrorCode hidl_error, const hidl_vec<uint8_t>& hidl_key_blob,
+                                    const KeyCharacteristics& hidl_key_characteristics) {
+                                    error_ = hidl_error;
+                                    key_blob_ = hidl_key_blob;
+                                    key_characteristics_ = std::move(hidl_key_characteristics);
+                                })
+                        .isOk() &&
+                error_ == ErrorCode::OK);
+    }
+
+    bool GenerateKey(Algorithm algorithm, int keySize, Digest digest = Digest::NONE,
+                     PaddingMode padding = PaddingMode::NONE, optional<BlockMode> blockMode = {}) {
+        AuthorizationSetBuilder authSet = AuthorizationSetBuilder()
+                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                  .Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT)
+                                                  .Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT)
+                                                  .Authorization(TAG_PURPOSE, KeyPurpose::SIGN)
+                                                  .Authorization(TAG_PURPOSE, KeyPurpose::VERIFY)
+                                                  .Authorization(TAG_KEY_SIZE, keySize)
+                                                  .Authorization(TAG_ALGORITHM, algorithm)
+                                                  .Digest(digest)
+                                                  .Authorization(TAG_MIN_MAC_LENGTH, 128)
+                                                  .Padding(padding);
+        if (blockMode) {
+            authSet.BlockMode(*blockMode);
+        }
+        if (algorithm == Algorithm::RSA) {
+            authSet.Authorization(TAG_RSA_PUBLIC_EXPONENT, 65537U);
+        }
+        return GenerateKey(authSet);
+    }
+
+    KeymasterWrapper(const sp<IKeymasterDevice> keymaster) {
+        os_version_ = ::keymaster::GetOsVersion();
+        os_patch_level_ = ::keymaster::GetOsPatchlevel();
+        keymaster_ = keymaster;
+        keymaster_->getHardwareInfo([&](SecurityLevel securityLevel, const hidl_string& name,
+                                        const hidl_string& author) {
+            securityLevel_ = securityLevel;
+            name_ = name;
+            author_ = author;
+        });
+
+        message_cache_.push_back(string(SMALL_MESSAGE_SIZE, 'x'));
+        message_cache_.push_back(string(MEDIUM_MESSAGE_SIZE, 'x'));
+        message_cache_.push_back(string(LARGE_MESSAGE_SIZE, 'x'));
+    }
+
+  public:
+    static KeymasterWrapper* newInstance(const std::string& keymaster_name) {
+        auto keymaster = IKeymasterDevice::getService(keymaster_name);
+        if (!keymaster) {
+            std::cerr << "Error: unable to find keymaster service named " << keymaster_name
+                      << std::endl;
+            return nullptr;
+        }
+        return new KeymasterWrapper(keymaster);
+    }
+
+    bool GenerateKey(string transform, int keySize, bool sign = false) {
+        if (transform == key_transform_) {
+            return true;
+        } else if (key_transform_ != "") {
+            // Deleting old key first
+            if (!DeleteKey()) {
+                return false;
+            }
+        }
+        optional<Algorithm> algorithm = getAlgorithm(transform);
+        if (!algorithm) {
+            cerr << "Error: invalid algorithm " << transform << endl;
+            return false;
+        }
+        key_transform_ = transform;
+        return GenerateKey(*algorithm, keySize, getDigest(transform), getPadding(transform, sign),
+                           getBlockMode(transform));
+    }
+
+    bool DeleteKey() {
+        key_blob_ = HidlBuf();
+        key_transform_ = "";
+        return keymaster_->deleteKey(key_blob_).isOk();
+    }
+
+    AuthorizationSet getOperationParams(string transform, bool sign = false) {
+        AuthorizationSetBuilder builder = AuthorizationSetBuilder()
+                                                  .Padding(getPadding(transform, sign))
+                                                  .Authorization(TAG_MAC_LENGTH, 128)
+                                                  .Digest(getDigest(transform));
+        optional<BlockMode> blockMode = getBlockMode(transform);
+        if (blockMode) {
+            builder.BlockMode(*blockMode);
+        }
+        return std::move(builder);
+    }
+
+    optional<OperationHandle> EncryptBegin(AuthorizationSet& in_params,
+                                           AuthorizationSet* out_params = new AuthorizationSet) {
+        return Begin(KeyPurpose::ENCRYPT, in_params, out_params);
+    }
+
+    optional<OperationHandle> DecryptBegin(AuthorizationSet& in_params,
+                                           AuthorizationSet* out_params = new AuthorizationSet) {
+        return Begin(KeyPurpose::DECRYPT, in_params, out_params);
+    }
+
+    optional<OperationHandle> SignBegin(AuthorizationSet& in_params,
+                                        AuthorizationSet* out_params = new AuthorizationSet) {
+        return Begin(KeyPurpose::SIGN, in_params, out_params);
+    }
+
+    optional<OperationHandle> VerifyBegin(AuthorizationSet& in_params,
+                                          AuthorizationSet* out_params = new AuthorizationSet) {
+        return Begin(KeyPurpose::VERIFY, in_params, out_params);
+    }
+
+    optional<OperationHandle> Begin(KeyPurpose operation, const AuthorizationSet& in_params,
+                                    AuthorizationSet* out_params) {
+        OperationHandle op_handle;
+        if (!keymaster_
+                     ->begin(operation, key_blob_, in_params.hidl_data(), HardwareAuthToken(),
+                             [&](ErrorCode hidl_error,
+                                 const hidl_vec<KeyParameter>& hidl_out_params,
+                                 uint64_t hidl_op_handle) {
+                                 error_ = hidl_error;
+                                 out_params->push_back(AuthorizationSet(hidl_out_params));
+                                 op_handle = hidl_op_handle;
+                             })
+                     .isOk() ||
+            error_ != ErrorCode::OK) {
+            keymaster_->abort(op_handle);
+            return {};
+        }
+        return op_handle;
+    }
+
+    optional<string> ProcessMessage(const OperationHandle& op_handle, const string& message,
+                                    const AuthorizationSet& in_params,
+                                    AuthorizationSet* out_params = new AuthorizationSet,
+                                    const string& signature = "") {
+        static const int HIDL_BUFFER_LIMIT = 1 << 14;  // 16KB
+
+        string output;
+        size_t input_consumed = 0;
+        while (message.length() - input_consumed > 0) {
+            if (!keymaster_
+                         ->update(op_handle, in_params.hidl_data(),
+                                  HidlBuf(message.substr(input_consumed, HIDL_BUFFER_LIMIT)),
+                                  HardwareAuthToken(), VerificationToken(),
+                                  [&](ErrorCode hidl_error, uint32_t hidl_input_consumed,
+                                      const hidl_vec<KeyParameter>& hidl_out_params,
+                                      const HidlBuf& hidl_output) {
+                                      error_ = hidl_error;
+                                      out_params->push_back(AuthorizationSet(hidl_out_params));
+                                      output.append(hidl_output.to_string());
+                                      input_consumed += hidl_input_consumed;
+                                  })
+                         .isOk() ||
+                error_ != ErrorCode::OK) {
+                keymaster_->abort(op_handle);
+                return {};
+            }
+        }
+
+        if (!keymaster_
+                     ->finish(op_handle, in_params.hidl_data(),
+                              HidlBuf(message.substr(input_consumed)), HidlBuf(signature),
+                              HardwareAuthToken(), VerificationToken(),
+                              [&](ErrorCode hidl_error,
+                                  const hidl_vec<KeyParameter>& hidl_out_params,
+                                  const HidlBuf& hidl_output) {
+                                  error_ = hidl_error;
+                                  out_params->push_back(AuthorizationSet(hidl_out_params));
+                                  output.append(hidl_output.to_string());
+                              })
+                     .isOk() ||
+            error_ != ErrorCode::OK) {
+            keymaster_->abort(op_handle);
+            return {};
+        }
+
+        return output;
+    }
+
+    int getError() { return static_cast<int>(error_); }
+
+    const string getHardwareName() { return name_; }
+
+    SecurityLevel getSecurityLevel() { return securityLevel_; }
+
+    const string& GenerateMessage(int size) {
+        for (const string& message : message_cache_) {
+            if (message.size() == size) {
+                return message;
+            }
+        }
+        string message = string(size, 'x');
+        message_cache_.push_back(message);
+        return std::move(message);
+    }
+
+    optional<BlockMode> getBlockMode(string transform) {
+        if (transform.find("/ECB") != string::npos) {
+            return BlockMode::ECB;
+        } else if (transform.find("/CBC") != string::npos) {
+            return BlockMode::CBC;
+        } else if (transform.find("/CTR") != string::npos) {
+            return BlockMode::CTR;
+        } else if (transform.find("/GCM") != string::npos) {
+            return BlockMode::GCM;
+        }
+        return {};
+    }
+
+    PaddingMode getPadding(string transform, bool sign) {
+        if (transform.find("/PKCS7") != string::npos) {
+            return PaddingMode::PKCS7;
+        } else if (transform.find("/PSS") != string::npos) {
+            return PaddingMode::RSA_PSS;
+        } else if (transform.find("/OAEP") != string::npos) {
+            return PaddingMode::RSA_OAEP;
+        } else if (transform.find("/PKCS1") != string::npos) {
+            return sign ? PaddingMode::RSA_PKCS1_1_5_SIGN : PaddingMode::RSA_PKCS1_1_5_ENCRYPT;
+        } else if (sign && transform.find("RSA") != string::npos) {
+            // RSA defaults to PKCS1 for sign
+            return PaddingMode::RSA_PKCS1_1_5_SIGN;
+        }
+        return PaddingMode::NONE;
+    }
+
+    optional<Algorithm> getAlgorithm(string transform) {
+        if (transform.find("AES") != string::npos) {
+            return Algorithm::AES;
+        } else if (transform.find("Hmac") != string::npos) {
+            return Algorithm::HMAC;
+        } else if (transform.find("DESede") != string::npos) {
+            return Algorithm::TRIPLE_DES;
+        } else if (transform.find("RSA") != string::npos) {
+            return Algorithm::RSA;
+        } else if (transform.find("EC") != string::npos) {
+            return Algorithm::EC;
+        }
+        cerr << "Can't find algorithm for " << transform << endl;
+        return {};
+    }
+
+    Digest getDigest(string transform) {
+        if (transform.find("MD5") != string::npos) {
+            return Digest::MD5;
+        } else if (transform.find("SHA1") != string::npos ||
+                   transform.find("SHA-1") != string::npos) {
+            return Digest::SHA1;
+        } else if (transform.find("SHA224") != string::npos) {
+            return Digest::SHA_2_224;
+        } else if (transform.find("SHA256") != string::npos) {
+            return Digest::SHA_2_256;
+        } else if (transform.find("SHA384") != string::npos) {
+            return Digest::SHA_2_384;
+        } else if (transform.find("SHA512") != string::npos) {
+            return Digest::SHA_2_512;
+        } else if (transform.find("RSA") != string::npos &&
+                   transform.find("OAEP") != string::npos) {
+            return Digest::SHA1;
+        }
+        return Digest::NONE;
+    }
+};
+
+KeymasterWrapper* keymaster;
+
+static void settings(benchmark::internal::Benchmark* benchmark) {
+    benchmark->Unit(benchmark::kMillisecond);
+}
+
+static void addDefaultLabel(benchmark::State& state) {
+    string secLevel;
+    switch (keymaster->getSecurityLevel()) {
+        case SecurityLevel::STRONGBOX:
+            secLevel = "STRONGBOX";
+            break;
+        case SecurityLevel::SOFTWARE:
+            secLevel = "SOFTWARE";
+            break;
+        case SecurityLevel::TRUSTED_ENVIRONMENT:
+            secLevel = "TEE";
+            break;
+    }
+    state.SetLabel("hardware_name:" + keymaster->getHardwareName() + " sec_level:" + secLevel);
+}
+
+// clang-format off
+#define BENCHMARK_KM(func, transform, keySize) \
+    BENCHMARK_CAPTURE(func, transform/keySize, #transform "/" #keySize, keySize)->Apply(settings);
+#define BENCHMARK_KM_MSG(func, transform, keySize, msgSize)                                      \
+    BENCHMARK_CAPTURE(func, transform/keySize/msgSize, #transform "/" #keySize "/" #msgSize, \
+                      keySize, msgSize)                                                          \
+            ->Apply(settings);
+
+#define BENCHMARK_KM_ALL_MSGS(func, transform, keySize)             \
+    BENCHMARK_KM_MSG(func, transform, keySize, SMALL_MESSAGE_SIZE)  \
+    BENCHMARK_KM_MSG(func, transform, keySize, MEDIUM_MESSAGE_SIZE) \
+    BENCHMARK_KM_MSG(func, transform, keySize, LARGE_MESSAGE_SIZE)
+
+#define BENCHMARK_KM_CIPHER(transform, keySize, msgSize)   \
+    BENCHMARK_KM_MSG(encrypt, transform, keySize, msgSize) \
+    BENCHMARK_KM_MSG(decrypt, transform, keySize, msgSize)
+
+#define BENCHMARK_KM_CIPHER_ALL_MSGS(transform, keySize) \
+    BENCHMARK_KM_ALL_MSGS(encrypt, transform, keySize)   \
+    BENCHMARK_KM_ALL_MSGS(decrypt, transform, keySize)
+
+#define BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, keySize) \
+    BENCHMARK_KM_ALL_MSGS(sign, transform, keySize)         \
+    BENCHMARK_KM_ALL_MSGS(verify, transform, keySize)
+// clang-format on
+
+/*
+ * ============= KeyGen TESTS ==================
+ */
+static void keygen(benchmark::State& state, string transform, int keySize) {
+    addDefaultLabel(state);
+    for (auto _ : state) {
+        keymaster->GenerateKey(transform, keySize);
+        state.PauseTiming();
+        keymaster->DeleteKey();
+        state.ResumeTiming();
+    }
+}
+
+BENCHMARK_KM(keygen, AES, 128);
+BENCHMARK_KM(keygen, AES, 256);
+
+BENCHMARK_KM(keygen, RSA, 2048);
+BENCHMARK_KM(keygen, RSA, 3072);
+BENCHMARK_KM(keygen, RSA, 4096);
+
+BENCHMARK_KM(keygen, EC, 224);
+BENCHMARK_KM(keygen, EC, 256);
+BENCHMARK_KM(keygen, EC, 384);
+BENCHMARK_KM(keygen, EC, 521);
+
+BENCHMARK_KM(keygen, DESede, 168);
+
+BENCHMARK_KM(keygen, Hmac, 64);
+BENCHMARK_KM(keygen, Hmac, 128);
+BENCHMARK_KM(keygen, Hmac, 256);
+BENCHMARK_KM(keygen, Hmac, 512);
+BENCHMARK_KM(keygen, Hmac, 1024);
+BENCHMARK_KM(keygen, Hmac, 2048);
+BENCHMARK_KM(keygen, Hmac, 4096);
+BENCHMARK_KM(keygen, Hmac, 8192);
+
+/*
+ * ============= SIGNATURE TESTS ==================
+ */
+
+static void sign(benchmark::State& state, string transform, int keySize, int msgSize) {
+    addDefaultLabel(state);
+    if (!keymaster->GenerateKey(transform, keySize, true)) {
+        state.SkipWithError(
+                ("Key generation error, " + std::to_string(keymaster->getError())).c_str());
+        return;
+    }
+    auto params = keymaster->getOperationParams(transform, true);
+    string message = keymaster->GenerateMessage(msgSize);
+
+    for (auto _ : state) {
+        state.PauseTiming();
+        auto opHandle = keymaster->SignBegin(params);
+        if (!opHandle) {
+            state.SkipWithError(
+                    ("Error beginning sign, " + std::to_string(keymaster->getError())).c_str());
+            return;
+        }
+        state.ResumeTiming();
+        if (!keymaster->ProcessMessage(*opHandle, message, params)) {
+            state.SkipWithError(("Sign error, " + std::to_string(keymaster->getError())).c_str());
+            break;
+        }
+    }
+}
+
+static void verify(benchmark::State& state, string transform, int keySize, int msgSize) {
+    addDefaultLabel(state);
+    if (!keymaster->GenerateKey(transform, keySize, true)) {
+        state.SkipWithError(
+                ("Key generation error, " + std::to_string(keymaster->getError())).c_str());
+        return;
+    }
+    AuthorizationSet out_params;
+    AuthorizationSet in_params = keymaster->getOperationParams(transform, true);
+    string message = keymaster->GenerateMessage(msgSize);
+    auto opHandle = keymaster->SignBegin(in_params, &out_params);
+    if (!opHandle) {
+        state.SkipWithError(
+                ("Error beginning sign, " + std::to_string(keymaster->getError())).c_str());
+        return;
+    }
+    optional<string> signature =
+            keymaster->ProcessMessage(*opHandle, message, in_params, &out_params);
+    if (!signature) {
+        state.SkipWithError(("Sign error, " + std::to_string(keymaster->getError())).c_str());
+        return;
+    }
+    in_params.push_back(out_params);
+    for (auto _ : state) {
+        state.PauseTiming();
+        opHandle = keymaster->VerifyBegin(in_params);
+        if (!opHandle) {
+            state.SkipWithError(
+                    ("Verify begin error, " + std::to_string(keymaster->getError())).c_str());
+            return;
+        }
+        state.ResumeTiming();
+        if (!keymaster->ProcessMessage(*opHandle, message, in_params, &out_params, *signature)) {
+            state.SkipWithError(("Verify error, " + std::to_string(keymaster->getError())).c_str());
+            break;
+        }
+    }
+}
+
+// clang-format off
+#define BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(transform) \
+    BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 64)      \
+    BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 128)     \
+    BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 256)     \
+    BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 512)     \
+    BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 1024)    \
+    BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 2024)    \
+    BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 4096)    \
+    BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 8192)
+
+BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(HmacSHA1)
+BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(HmacSHA256)
+BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(HmacSHA224)
+BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(HmacSHA256)
+BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(HmacSHA384)
+BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(HmacSHA512)
+
+#define BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(transform) \
+    BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 224)      \
+    BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 256)      \
+    BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 384)      \
+    BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 521)
+
+BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(NONEwithECDSA);
+BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(SHA1withECDSA);
+BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(SHA224withECDSA);
+BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(SHA256withECDSA);
+BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(SHA384withECDSA);
+BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(SHA512withECDSA);
+
+#define BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(transform) \
+    BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 2048)   \
+    BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 3072)   \
+    BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 4096)
+
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(MD5withRSA);
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA1withRSA);
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA224withRSA);
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA384withRSA);
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA512withRSA);
+
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(MD5withRSA/PSS);
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA1withRSA/PSS);
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA224withRSA/PSS);
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA384withRSA/PSS);
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA512withRSA/PSS);
+// clang-format on
+
+/*
+ * ============= CIPHER TESTS ==================
+ */
+
+static void encrypt(benchmark::State& state, string transform, int keySize, int msgSize) {
+    addDefaultLabel(state);
+    if (!keymaster->GenerateKey(transform, keySize)) {
+        state.SkipWithError(
+                ("Key generation error, " + std::to_string(keymaster->getError())).c_str());
+        return;
+    }
+    auto params = keymaster->getOperationParams(transform);
+    string message = keymaster->GenerateMessage(msgSize);
+
+    for (auto _ : state) {
+        state.PauseTiming();
+        auto opHandle = keymaster->EncryptBegin(params);
+        if (!opHandle) {
+            state.SkipWithError(
+                    ("Encryption begin error, " + std::to_string(keymaster->getError())).c_str());
+            return;
+        }
+        state.ResumeTiming();
+        if (!keymaster->ProcessMessage(*opHandle, message, params)) {
+            state.SkipWithError(
+                    ("Encryption error, " + std::to_string(keymaster->getError())).c_str());
+            break;
+        }
+    }
+}
+
+static void decrypt(benchmark::State& state, string transform, int keySize, int msgSize) {
+    addDefaultLabel(state);
+    if (!keymaster->GenerateKey(transform, keySize)) {
+        state.SkipWithError(
+                ("Key generation error, " + std::to_string(keymaster->getError())).c_str());
+        return;
+    }
+    AuthorizationSet out_params;
+    AuthorizationSet in_params = keymaster->getOperationParams(transform);
+    string message = keymaster->GenerateMessage(msgSize);
+    auto opHandle = keymaster->EncryptBegin(in_params, &out_params);
+    if (!opHandle) {
+        state.SkipWithError(
+                ("Encryption begin error, " + std::to_string(keymaster->getError())).c_str());
+        return;
+    }
+    auto encryptedMessage = keymaster->ProcessMessage(*opHandle, message, in_params, &out_params);
+    if (!encryptedMessage) {
+        state.SkipWithError(("Encryption error, " + std::to_string(keymaster->getError())).c_str());
+        return;
+    }
+    in_params.push_back(out_params);
+    for (auto _ : state) {
+        state.PauseTiming();
+        opHandle = keymaster->DecryptBegin(in_params);
+        if (!opHandle) {
+            state.SkipWithError(
+                    ("Decryption begin error, " + std::to_string(keymaster->getError())).c_str());
+            return;
+        }
+        state.ResumeTiming();
+        if (!keymaster->ProcessMessage(*opHandle, *encryptedMessage, in_params)) {
+            state.SkipWithError(
+                    ("Decryption error, " + std::to_string(keymaster->getError())).c_str());
+            break;
+        }
+    }
+}
+
+// clang-format off
+// AES
+#define BENCHMARK_KM_CIPHER_ALL_AES_KEYS(transform) \
+    BENCHMARK_KM_CIPHER_ALL_MSGS(transform, 128)    \
+    BENCHMARK_KM_CIPHER_ALL_MSGS(transform, 256)
+
+BENCHMARK_KM_CIPHER_ALL_AES_KEYS(AES/CBC/NoPadding);
+BENCHMARK_KM_CIPHER_ALL_AES_KEYS(AES/CBC/PKCS7Padding);
+BENCHMARK_KM_CIPHER_ALL_AES_KEYS(AES/CTR/NoPadding);
+BENCHMARK_KM_CIPHER_ALL_AES_KEYS(AES/ECB/NoPadding);
+BENCHMARK_KM_CIPHER_ALL_AES_KEYS(AES/ECB/PKCS7Padding);
+BENCHMARK_KM_CIPHER_ALL_AES_KEYS(AES/GCM/NoPadding);
+
+// Triple DES
+BENCHMARK_KM_CIPHER_ALL_MSGS(DESede/CBC/NoPadding, 168);
+BENCHMARK_KM_CIPHER_ALL_MSGS(DESede/CBC/PKCS7Padding, 168);
+BENCHMARK_KM_CIPHER_ALL_MSGS(DESede/ECB/NoPadding, 168);
+BENCHMARK_KM_CIPHER_ALL_MSGS(DESede/ECB/PKCS7Padding, 168);
+
+#define BENCHMARK_KM_CIPHER_ALL_RSA_KEYS(transform, msgSize) \
+    BENCHMARK_KM_CIPHER(transform, 2048, msgSize)            \
+    BENCHMARK_KM_CIPHER(transform, 3072, msgSize)            \
+    BENCHMARK_KM_CIPHER(transform, 4096, msgSize)
+
+BENCHMARK_KM_CIPHER_ALL_RSA_KEYS(RSA/ECB/NoPadding, SMALL_MESSAGE_SIZE);
+BENCHMARK_KM_CIPHER_ALL_RSA_KEYS(RSA/ECB/PKCS1Padding, SMALL_MESSAGE_SIZE);
+BENCHMARK_KM_CIPHER_ALL_RSA_KEYS(RSA/ECB/OAEPPadding, SMALL_MESSAGE_SIZE);
+// clang-format on
+
+}  // namespace test
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
+
+int main(int argc, char** argv) {
+    ::benchmark::Initialize(&argc, argv);
+    base::CommandLine::Init(argc, argv);
+    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+    auto service_name = command_line->GetSwitchValueASCII("service_name");
+    if (service_name.empty()) {
+        service_name = "default";
+    }
+    android::hardware::keymaster::V4_0::test::keymaster =
+            android::hardware::keymaster::V4_0::test::KeymasterWrapper::newInstance(service_name);
+    if (!android::hardware::keymaster::V4_0::test::keymaster) {
+        return 1;
+    }
+    ::benchmark::RunSpecifiedBenchmarks();
+}
\ No newline at end of file
diff --git a/keymaster/4.0/vts/performance/README b/keymaster/4.0/vts/performance/README
new file mode 100644
index 0000000..57d984a
--- /dev/null
+++ b/keymaster/4.0/vts/performance/README
@@ -0,0 +1,19 @@
+# Keymaster Benchmark
+
+The Keymaster Benchmark is a standalone tool for measuring the performance of keymaster implementations.
+
+## Building
+
+Build:
+`m  keymaster_benchmark`
+
+Transfer to device/emulator:
+`adb sync data`
+
+The benchmark executable should will be located at `data/benchmarktest/keymaster_benchmark/keymaster_benchmark` on the device.
+
+## Usage
+
+Keymaster Benchmark is built on [Google microbenchmark library](https://github.com/google/benchmark).
+All of the commandline arguments provided by the microbenchmark library are valid, such as `--benchmark_filter=<regex>` or `benchmark_out_format={json|console|csv}`.
+In addition to the command line arguments provided by microbenchmark, `--service_name=<service_name>` is provided allow specification of the keymaster service name, e.g. specify `--service_name=strongbox` to benchmark strongbox.
diff --git a/keymaster/4.1/Android.bp b/keymaster/4.1/Android.bp
new file mode 100644
index 0000000..3b505d8
--- /dev/null
+++ b/keymaster/4.1/Android.bp
@@ -0,0 +1,20 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.keymaster@4.1",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IKeymasterDevice.hal",
+        "IOperation.hal",
+    ],
+    interfaces: [
+        "android.hardware.keymaster@3.0",
+        "android.hardware.keymaster@4.0",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: false,
+}
diff --git a/keymaster/4.1/IKeymasterDevice.hal b/keymaster/4.1/IKeymasterDevice.hal
new file mode 100644
index 0000000..64d2c9f
--- /dev/null
+++ b/keymaster/4.1/IKeymasterDevice.hal
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+package android.hardware.keymaster@4.1;
+
+import @4.0::ErrorCode;
+import @4.0::HardwareAuthToken;
+import @4.0::IKeymasterDevice;
+import @4.0::KeyParameter;
+import @4.0::KeyPurpose;
+import @4.0::OperationHandle;
+import IOperation;
+
+/**
+ * @4.1::IKeymasterDevice is a minor extension to @4.0::IKeymasterDevice.  It adds support for
+ *
+ * - Partial hardware enforcment of UNLOCKED_DEVICE_REQUIRED keys;
+ * - Device-unique attestaion;
+ * - Early boot only keys;
+ * - Better cleanup of operations when clients die without completing or aborting them.
+ */
+interface IKeymasterDevice extends @4.0::IKeymasterDevice {
+    /**
+     * Called by client to notify the IKeymasterDevice that the device is now locked, and keys with
+     * the UNLOCKED_DEVICE_REQUIRED tag should no longer be usable.  When this function is called,
+     * the IKeymasterDevice should note the current timestamp, and attempts to use
+     * UNLOCKED_DEVICE_REQUIRED keys must be rejected with Error::DEVICE_LOCKED until an
+     * authentication token with a later timestamp is presented.  If the `passwordOnly' argument is
+     * set to true the sufficiently-recent authentication token must indicate that the user
+     * authenticated with a password, not a biometric.
+     *
+     * @param passwordOnly specifies whether the device must be unlocked with a password, rather
+     * than a biometric, before UNLOCKED_DEVICE_REQUIRED keys can be used.
+     */
+    deviceLocked(bool passwordOnly) generates (ErrorCode error);
+
+    /**
+     * Called by client to notify the IKeymasterDevice that the device has left the early boot
+     * state, and that keys with the EARLY_BOOT_ONLY tag may no longer be used.  All attempts to use
+     * an EARLY_BOOT_ONLY key after this method is called must fail with Error::INVALID_KEY_BLOB.
+     */
+    earlyBootEnded() generates (ErrorCode error);
+
+    /**
+     * Begins a cryptographic operation.  beginOp() is a variation on begin().  beginOp() has
+     * identical functionality to begin, but instead of an OperationHandle it returns an IOperation
+     * object.  An IKeymasterDevice HAL service must call linkToDeath() on the Operation before
+     * returning it, and the provided hidl_death_recipient, if called, must abort() the operation.
+     * This is to ensure that in the event a client crashes while an operation is in progress, the
+     * operation slot is freed and available for use by other clients.
+     *
+     * @4.1::IKeymasterDevices must implement both beginOp() and begin().
+     */
+    beginOp(KeyPurpose purpose, vec<uint8_t> keyBlob, vec<KeyParameter> inParams,
+        HardwareAuthToken authToken)
+        generates (ErrorCode error, vec<KeyParameter> outParam, IOperation operation);
+};
diff --git a/keymaster/4.1/IOperation.hal b/keymaster/4.1/IOperation.hal
new file mode 100644
index 0000000..7103e9e
--- /dev/null
+++ b/keymaster/4.1/IOperation.hal
@@ -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.
+ */
+
+package android.hardware.keymaster@4.1;
+
+import @4.0::ErrorCode;
+import @4.0::OperationHandle;
+
+/**
+ * IOperation represents an in-progress IKeymasterDevice operation.  It is returned by
+ * IKeymasterDevice.beginOp().
+ */
+interface IOperation {
+    /**
+     * Returns the operation handle to be used as an authentication challenge.
+     */
+    getOperationChallenge() generates (ErrorCode error, OperationHandle operation);
+};
diff --git a/keymaster/4.1/default/Android.bp b/keymaster/4.1/default/Android.bp
new file mode 100644
index 0000000..b06878b
--- /dev/null
+++ b/keymaster/4.1/default/Android.bp
@@ -0,0 +1,38 @@
+//
+// 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_binary {
+    name: "android.hardware.keymaster@4.1-service",
+    defaults: ["hidl_defaults"],
+    relative_install_path: "hw",
+    vendor: true,
+    init_rc: ["android.hardware.keymaster@4.1-service.rc"],
+    srcs: ["service.cpp"],
+
+    shared_libs: [
+        "android.hardware.keymaster@4.0",
+        "android.hardware.keymaster@4.1",
+        "libbase",
+        "libcutils",
+        "libhardware",
+        "libhidlbase",
+        "libkeymaster4",
+        "libkeymaster41",
+        "liblog",
+        "libutils",
+    ],
+
+}
diff --git a/keymaster/4.1/default/OWNERS b/keymaster/4.1/default/OWNERS
new file mode 100644
index 0000000..335660d
--- /dev/null
+++ b/keymaster/4.1/default/OWNERS
@@ -0,0 +1,2 @@
+jdanis@google.com
+swillden@google.com
diff --git a/keymaster/4.1/default/android.hardware.keymaster@4.1-service.rc b/keymaster/4.1/default/android.hardware.keymaster@4.1-service.rc
new file mode 100644
index 0000000..740b3c2
--- /dev/null
+++ b/keymaster/4.1/default/android.hardware.keymaster@4.1-service.rc
@@ -0,0 +1,6 @@
+service vendor.keymaster-4-1 /vendor/bin/hw/android.hardware.keymaster@4.1-service
+    interface android.hardware.keymaster@4.0::IKeymasterDevice default
+    interface android.hardware.keymaster@4.1::IKeymasterDevice default
+    class early_hal
+    user system
+    group system drmrpc
diff --git a/keymaster/4.1/default/service.cpp b/keymaster/4.1/default/service.cpp
new file mode 100644
index 0000000..d79a291
--- /dev/null
+++ b/keymaster/4.1/default/service.cpp
@@ -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.
+*/
+
+#include <android-base/logging.h>
+#include <android/hardware/keymaster/4.1/IKeymasterDevice.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include <AndroidKeymaster41Device.h>
+
+using android::hardware::keymaster::V4_0::SecurityLevel;
+
+int main() {
+    ::android::hardware::configureRpcThreadpool(1, true /* willJoinThreadpool */);
+    auto keymaster = ::keymaster::V4_1::CreateKeymasterDevice(SecurityLevel::SOFTWARE);
+    auto status = keymaster->registerAsService();
+    if (status != android::OK) {
+        LOG(FATAL) << "Could not register service for Keymaster 4.1 (" << status << ")";
+    }
+
+    android::hardware::joinRpcThreadpool();
+    return -1;  // Should never get here.
+}
diff --git a/keymaster/4.1/support/Android.bp b/keymaster/4.1/support/Android.bp
new file mode 100644
index 0000000..34b6108
--- /dev/null
+++ b/keymaster/4.1/support/Android.bp
@@ -0,0 +1,32 @@
+//
+// 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 {
+    name: "libkeymaster4_1support",
+    vendor_available: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+    export_include_dirs: ["include"],
+    shared_libs: [
+        "android.hardware.keymaster@3.0",
+        "android.hardware.keymaster@4.0",
+        "android.hardware.keymaster@4.1",
+        "libkeymaster4support",
+    ]
+}
diff --git a/keymaster/4.1/support/include/keymasterV4_1/authorization_set.h b/keymaster/4.1/support/include/keymasterV4_1/authorization_set.h
new file mode 100644
index 0000000..afc0eaf
--- /dev/null
+++ b/keymaster/4.1/support/include/keymasterV4_1/authorization_set.h
@@ -0,0 +1,32 @@
+/*
+ * 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 HARDWARE_INTERFACES_KEYMASTER_V4_1_SUPPORT_INCLUDE_AUTHORIZATION_SET_H_
+#define HARDWARE_INTERFACES_KEYMASTER_V4_1_SUPPORT_INCLUDE_AUTHORIZATION_SET_H_
+
+#include <keymasterV4_0/authorization_set.h>
+
+#include <keymasterV4_1/keymaster_tags.h>
+
+namespace android::hardware::keymaster::V4_1 {
+
+using V4_0::AuthorizationSet;
+using V4_0::AuthorizationSetBuilder;
+using V4_0::KeyParameter;
+
+}  // namespace android::hardware::keymaster::V4_1
+
+#endif  // HARDWARE_INTERFACES_KEYMASTER_V4_1_SUPPORT_INCLUDE_AUTHORIZATION_SET_H_
diff --git a/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h b/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
new file mode 100644
index 0000000..6ffe8e1
--- /dev/null
+++ b/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
@@ -0,0 +1,96 @@
+/*
+ * 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 HARDWARE_INTERFACES_KEYMASTER_V4_1_SUPPORT_INCLUDE_KEYMASTER_TAGS_H_
+#define HARDWARE_INTERFACES_KEYMASTER_V4_1_SUPPORT_INCLUDE_KEYMASTER_TAGS_H_
+
+#include <android/hardware/keymaster/4.1/types.h>
+
+#include <keymasterV4_0/keymaster_tags.h>
+
+namespace android::hardware::keymaster::V4_1 {
+
+using V4_0::BlockMode;
+using V4_0::Digest;
+using V4_0::EcCurve;
+using V4_0::ErrorCode;
+using V4_0::HardwareAuthToken;
+using V4_0::KeyParameter;
+using V4_0::PaddingMode;
+using V4_0::TagType;
+using V4_0::VerificationToken;
+
+using V4_0::TypedTag;
+
+using V4_0::TAG_ACTIVE_DATETIME;
+using V4_0::TAG_ALGORITHM;
+using V4_0::TAG_ALLOW_WHILE_ON_BODY;
+using V4_0::TAG_APPLICATION_DATA;
+using V4_0::TAG_APPLICATION_ID;
+using V4_0::TAG_ASSOCIATED_DATA;
+using V4_0::TAG_ATTESTATION_APPLICATION_ID;
+using V4_0::TAG_ATTESTATION_CHALLENGE;
+using V4_0::TAG_AUTH_TIMEOUT;
+using V4_0::TAG_BLOB_USAGE_REQUIREMENTS;
+using V4_0::TAG_BLOCK_MODE;
+using V4_0::TAG_BOOT_PATCHLEVEL;
+using V4_0::TAG_BOOTLOADER_ONLY;
+using V4_0::TAG_CALLER_NONCE;
+using V4_0::TAG_CONFIRMATION_TOKEN;
+using V4_0::TAG_CREATION_DATETIME;
+using V4_0::TAG_DIGEST;
+using V4_0::TAG_EC_CURVE;
+using V4_0::TAG_HARDWARE_TYPE;
+using V4_0::TAG_INCLUDE_UNIQUE_ID;
+using V4_0::TAG_INVALID;
+using V4_0::TAG_KEY_SIZE;
+using V4_0::TAG_MAC_LENGTH;
+using V4_0::TAG_MAX_USES_PER_BOOT;
+using V4_0::TAG_MIN_MAC_LENGTH;
+using V4_0::TAG_MIN_SECONDS_BETWEEN_OPS;
+using V4_0::TAG_NO_AUTH_REQUIRED;
+using V4_0::TAG_NONCE;
+using V4_0::TAG_ORIGIN;
+using V4_0::TAG_ORIGINATION_EXPIRE_DATETIME;
+using V4_0::TAG_OS_PATCHLEVEL;
+using V4_0::TAG_OS_VERSION;
+using V4_0::TAG_PADDING;
+using V4_0::TAG_PURPOSE;
+using V4_0::TAG_RESET_SINCE_ID_ROTATION;
+using V4_0::TAG_ROLLBACK_RESISTANCE;
+using V4_0::TAG_ROOT_OF_TRUST;
+using V4_0::TAG_RSA_PUBLIC_EXPONENT;
+using V4_0::TAG_TRUSTED_CONFIRMATION_REQUIRED;
+using V4_0::TAG_TRUSTED_USER_PRESENCE_REQUIRED;
+using V4_0::TAG_UNIQUE_ID;
+using V4_0::TAG_UNLOCKED_DEVICE_REQUIRED;
+using V4_0::TAG_USAGE_EXPIRE_DATETIME;
+using V4_0::TAG_USER_AUTH_TYPE;
+using V4_0::TAG_USER_ID;
+using V4_0::TAG_USER_SECURE_ID;
+using V4_0::TAG_VENDOR_PATCHLEVEL;
+
+#define DECLARE_KM_4_1_TYPED_TAG(name)                                                   \
+    typedef typename V4_0::Tag2TypedTag<(static_cast<V4_0::Tag>(V4_1::Tag::name))>::type \
+            TAG_##name##_t;                                                              \
+    static TAG_##name##_t TAG_##name;
+
+DECLARE_KM_4_1_TYPED_TAG(EARLY_BOOT_ONLY);
+DECLARE_KM_4_1_TYPED_TAG(DEVICE_UNIQUE_ATTESTATION);
+
+}  // namespace android::hardware::keymaster::V4_1
+
+#endif  // HARDWARE_INTERFACES_KEYMASTER_V4_1_SUPPORT_INCLUDE_KEYMASTER_TAGS_H_
diff --git a/keymaster/4.1/types.hal b/keymaster/4.1/types.hal
new file mode 100644
index 0000000..bdf1731
--- /dev/null
+++ b/keymaster/4.1/types.hal
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+package android.hardware.keymaster@4.1;
+
+import @4.0::ErrorCode;
+import @4.0::Tag;
+import @4.0::TagType;
+
+enum Tag : @4.0::Tag {
+    /**
+     * Keys tagged with EARLY_BOOT_ONLY may only be used, or created, during early boot, until
+     * IKeymasterDevice::earlyBootEnded() is called.
+     */
+    EARLY_BOOT_ONLY = TagType:BOOL | 305,
+    /**
+     * DEVICE_UNIQUE_ATTESTATION is an argument to IKeymasterDevice::attestKey().  It indicates that
+     * attestation using a device-unique key is requested, rather than a batch key.  Only
+     * SecurityLevel::STRONGBOX IKeymasterDevices may support device-unique attestations.
+     * SecurityLevel::TRUSTED_ENVIRONMENT IKeymasterDevices must return ErrorCode::INVALID_ARGUMENT
+     * if they receive DEVICE_UNIQUE_ATTESTATION.  SecurityLevel::STRONGBOX IKeymasterDevices need
+     * not support DEVICE_UNIQUE_ATTESTATION, and return ErrorCode::CANNOT_ATTEST_IDS if they do not
+     * support it.
+     *
+     * IKeymasterDevice implementations that support device-unique attestation MUST add the
+     * DEVICE_UNIQUE_ATTESTATION tag to device-unique attestations.
+     */
+    DEVICE_UNIQUE_ATTESTATION = TagType:BOOL | 720,
+};
diff --git a/keymaster/4.1/vts/OWNERS b/keymaster/4.1/vts/OWNERS
new file mode 100644
index 0000000..335660d
--- /dev/null
+++ b/keymaster/4.1/vts/OWNERS
@@ -0,0 +1,2 @@
+jdanis@google.com
+swillden@google.com
diff --git a/vibrator/1.4/vts/functional/Android.bp b/keymaster/4.1/vts/functional/Android.bp
similarity index 66%
rename from vibrator/1.4/vts/functional/Android.bp
rename to keymaster/4.1/vts/functional/Android.bp
index 202a824..f5a0c9c 100644
--- a/vibrator/1.4/vts/functional/Android.bp
+++ b/keymaster/4.1/vts/functional/Android.bp
@@ -15,19 +15,16 @@
 //
 
 cc_test {
-    name: "VtsHalVibratorV1_4TargetTest",
+    name: "VtsHalKeymasterV4_1TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
-    srcs: ["VtsHalVibratorV1_4TargetTest.cpp"],
+    srcs: [
+        "EarlyBootKeyTest.cpp",
+    ],
     static_libs: [
-        "android.hardware.vibrator@1.0",
-        "android.hardware.vibrator@1.1",
-        "android.hardware.vibrator@1.2",
-        "android.hardware.vibrator@1.3",
-        "android.hardware.vibrator@1.4",
+        "android.hardware.keymaster@4.0",
+        "android.hardware.keymaster@4.1",
+        "libkeymaster4support",
+        "libkeymaster4_1support",
     ],
-    test_suites: [
-        "general-tests",
-        "vts-core",
-    ],
+    test_suites: ["vts-core"],
 }
-
diff --git a/vibrator/1.4/IVibratorCallback.hal b/keymaster/4.1/vts/functional/EarlyBootKeyTest.cpp
similarity index 80%
copy from vibrator/1.4/IVibratorCallback.hal
copy to keymaster/4.1/vts/functional/EarlyBootKeyTest.cpp
index 76281bc..4a19010 100644
--- a/vibrator/1.4/IVibratorCallback.hal
+++ b/keymaster/4.1/vts/functional/EarlyBootKeyTest.cpp
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-package android.hardware.vibrator@1.4;
+namespace android::hardware::keymaster::V4_1::test {
 
-interface IVibratorCallback {
-    oneway onComplete();
-};
+// TODO(swillden): Put tests here.
+
+}  // namespace android::hardware::keymaster::V4_1::test
diff --git a/media/c2/1.1/Android.bp b/media/c2/1.1/Android.bp
new file mode 100644
index 0000000..c3e30b2
--- /dev/null
+++ b/media/c2/1.1/Android.bp
@@ -0,0 +1,27 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.media.c2@1.1",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "IComponent.hal",
+        "IComponentStore.hal",
+    ],
+    interfaces: [
+        "android.hardware.graphics.bufferqueue@1.0",
+        "android.hardware.graphics.bufferqueue@2.0",
+        "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.common@1.1",
+        "android.hardware.graphics.common@1.2",
+        "android.hardware.media.bufferpool@2.0",
+        "android.hardware.media.c2@1.0",
+        "android.hardware.media.omx@1.0",
+        "android.hardware.media@1.0",
+        "android.hidl.base@1.0",
+        "android.hidl.safe_union@1.0",
+    ],
+    gen_java: false,
+}
diff --git a/media/c2/1.1/IComponent.hal b/media/c2/1.1/IComponent.hal
new file mode 100644
index 0000000..97382dd
--- /dev/null
+++ b/media/c2/1.1/IComponent.hal
@@ -0,0 +1,72 @@
+/*
+ * 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.media.c2@1.1;
+
+import android.hardware.media.c2@1.0::IComponent;
+import android.hardware.media.c2@1.0::Status;
+
+/**
+ * Interface for a Codec2 component corresponding to API level 1.0 or below.
+ * Components have two states: stopped and running. The running state has three
+ * sub-states: executing, tripped and error.
+ *
+ * All methods in `IComponent` must not block. If a method call cannot be
+ * completed in a timely manner, it must return `TIMED_OUT` in the return
+ * status.
+ *
+ * @note This is an extension of version 1.0 of `IComponent`. The purpose of the
+ * extension is to add support for tunneling.
+ */
+interface IComponent extends @1.0::IComponent {
+    /**
+      * Configures a component for a tunneled playback mode.
+      *
+      * A successful call to this method puts the component in the *tunneled*
+      * mode. In this mode, the output `Worklet`s returned in
+      * IComponentListener::onWorkDone() may not contain any buffers. The output
+      * buffers are passed directly to the consumer end of a buffer queue whose
+      * producer side is configured with the returned @p sidebandStream passed
+      * to IGraphicBufferProducer::setSidebandStream().
+      *
+      * The component is initially in the non-tunneled mode by default. The
+      * tunneled mode can be toggled on only before the component starts
+      * processing. Once the component is put into the tunneled mode, it shall
+      * stay in the tunneled mode until and only until reset() is called.
+      *
+      * @param avSyncHwId A resource ID for hardware sync. The generator of sync
+      *     IDs must ensure that this number is unique among all services at any
+      *     given time. For example, if both the audio HAL and the tuner HAL
+      *     support this feature, sync IDs from the audio HAL must not clash
+      *     with sync IDs from the tuner HAL.
+      * @return status Status of the call, which may be
+      *   - `OK`        - The operation completed successfully. In this case,
+      *                   @p sidebandHandle shall not be a null handle.
+      *   - `OMITTED`   - The component does not support video tunneling.
+      *   - `BAD_STATE` - The component is already running.
+      *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+      *   - `CORRUPTED` - Some unknown error occurred.
+      * @return sidebandHandle Codec-allocated sideband stream handle. This can
+      *     be passed to IGraphicBufferProducer::setSidebandStream() to
+      *     establish a direct channel to the consumer.
+      */
+     configureVideoTunnel(
+             uint32_t avSyncHwId
+         ) generates (
+             Status status,
+             handle sidebandHandle
+         );
+};
diff --git a/media/c2/1.1/IComponentStore.hal b/media/c2/1.1/IComponentStore.hal
new file mode 100644
index 0000000..38e0fc6
--- /dev/null
+++ b/media/c2/1.1/IComponentStore.hal
@@ -0,0 +1,64 @@
+/*
+ * 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.media.c2@1.1;
+
+import android.hardware.media.bufferpool@2.0::IClientManager;
+import android.hardware.media.c2@1.0::IComponentListener;
+import android.hardware.media.c2@1.0::IComponentStore;
+import android.hardware.media.c2@1.0::Status;
+
+import IComponent;
+
+/**
+ * Entry point for Codec2 HAL.
+ *
+ * All methods in `IComponentStore` must not block. If a method call cannot be
+ * completed in a timely manner, it must return `TIMED_OUT` in the return
+ * status. The only exceptions are getPoolClientManager() and getConfigurable(),
+ * which must always return immediately.
+ *
+ * @note This is an extension of version 1.0 of `IComponentStore`. The purpose
+ * of the extension is to add support for tunneling.
+ */
+interface IComponentStore extends @1.0::IComponentStore {
+    /**
+     * Creates a component by name.
+     *
+     * @param name Name of the component to create. This must match one of the
+     *     names returned by listComponents().
+     * @param listener Callback receiver.
+     * @param pool `IClientManager` object of the BufferPool in the client
+     *     process. This may be null if the client does not own a BufferPool.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The component was created successfully.
+     *   - `NOT_FOUND` - There is no component with the given name.
+     *   - `NO_MEMORY` - Not enough memory to create the component.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return comp The created component if @p status is `OK`.
+     *
+     * @sa IComponentListener.
+     */
+    createComponent_1_1(
+            string name,
+            IComponentListener listener,
+            IClientManager pool
+        ) generates (
+            Status status,
+            IComponent comp
+        );
+};
diff --git a/neuralnetworks/1.1/types.hal b/neuralnetworks/1.1/types.hal
index 3d78fb6..da7ba78 100644
--- a/neuralnetworks/1.1/types.hal
+++ b/neuralnetworks/1.1/types.hal
@@ -125,7 +125,7 @@
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
      *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
-     *      the scale and zeroPoint must be same as input0.
+     *      the scale and zeroPoint must be the same as input0.
      */
     MEAN = 31,
 
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index 837ced5..b111d96 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -1954,7 +1954,7 @@
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
      *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
-     *      the scale and zeroPoint must be same as input0.
+     *      the scale and zeroPoint must be the same as input0.
      */
     MEAN = @1.1::OperationType:MEAN,
 
@@ -2448,15 +2448,17 @@
      *       then clipping is disabled.
      *       If all the input tensors have type {@link OperandType::TENSOR_FLOAT32},
      *       this scalar must be of the type {@link OperandType::FLOAT32},
-     *       otherwise if all the input tensors have the type {@link OperandType::TENSOR_FLOAT16},
-     *       this scalar must be of type {@link OperandType::FLOAT16}.
+     *       otherwise if all the input tensors have the type
+     *       {@link OperandType::TENSOR_FLOAT16}, this scalar must be
+     *       of type {@link OperandType::FLOAT16}.
      * * 50: The clipping threshold for the output from the
      *       projection layer, such that values are bound within
      *       [-proj_clip, proj_clip]. If set to 0.0 then clipping is disabled.
      *       If all the input tensors have type {@link OperandType::TENSOR_FLOAT32},
      *       this scalar must be of the type {@link OperandType::FLOAT32},
-     *       otherwise if all the input tensors have the type {@link OperandType::TENSOR_FLOAT16},
-     *       this scalar must be of type {@link OperandType::FLOAT16}.
+     *       otherwise if all the input tensors have the type
+     *       {@link OperandType::TENSOR_FLOAT16}, this scalar must be
+     *       of type {@link OperandType::FLOAT16}.
      * * 51: merge_outputs
      *       An {@link OperandType::BOOL} scalar specifying if the outputs
      *       from forward and backward cells should be merged.
@@ -4124,7 +4126,6 @@
      * * 0: A tensor of the same type and shape as input1 and input2.
      *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
      *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
-     *
      */
     SELECT = 84,
 
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index bdca0e9..fc727b7 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -71,5 +71,5 @@
     header_libs: [
         "libneuralnetworks_headers",
     ],
-    test_suites: ["general-tests", "vts-core"],
+    test_suites: ["general-tests"],
 }
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
index aacb385..4909214 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
@@ -29,13 +29,14 @@
 #include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
 #include <android/hidl/allocator/1.0/IAllocator.h>
 #include <android/hidl/memory/1.0/IMemory.h>
+#include <gtest/gtest.h>
 #include <hidlmemory/mapping.h>
 
-#include <gtest/gtest.h>
 #include <algorithm>
 #include <chrono>
 #include <iostream>
 #include <numeric>
+#include <vector>
 
 #include "1.0/Utils.h"
 #include "1.2/Callbacks.h"
@@ -58,8 +59,20 @@
 using V1_1::ExecutionPreference;
 using HidlToken = hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
 
+namespace {
+
+enum class Executor { ASYNC, SYNC, BURST };
+
 enum class OutputType { FULLY_SPECIFIED, UNSPECIFIED, INSUFFICIENT };
 
+struct TestConfig {
+    Executor executor;
+    MeasureTiming measureTiming;
+    OutputType outputType;
+};
+
+}  // namespace
+
 Model createModel(const TestModel& testModel) {
     // Model operands.
     hidl_vec<Operand> operands(testModel.operands.size());
@@ -194,31 +207,31 @@
     return android::nn::ExecutionBurstController::create(preparedModel,
                                                          std::chrono::microseconds{0});
 }
-enum class Executor { ASYNC, SYNC, BURST };
 
 void EvaluatePreparedModel(const sp<IPreparedModel>& preparedModel, const TestModel& testModel,
-                           Executor executor, MeasureTiming measure, OutputType outputType) {
+                           const TestConfig& testConfig) {
     // If output0 does not have size larger than one byte, we can not test with insufficient buffer.
-    if (outputType == OutputType::INSUFFICIENT && !isOutputSizeGreaterThanOne(testModel, 0)) {
+    if (testConfig.outputType == OutputType::INSUFFICIENT &&
+        !isOutputSizeGreaterThanOne(testModel, 0)) {
         return;
     }
 
     Request request = createRequest(testModel);
-    if (outputType == OutputType::INSUFFICIENT) {
+    if (testConfig.outputType == OutputType::INSUFFICIENT) {
         makeOutputInsufficientSize(/*outputIndex=*/0, &request);
     }
 
     ErrorStatus executionStatus;
     hidl_vec<OutputShape> outputShapes;
     Timing timing;
-    switch (executor) {
+    switch (testConfig.executor) {
         case Executor::ASYNC: {
             SCOPED_TRACE("asynchronous");
 
             // launch execution
             sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-            Return<ErrorStatus> executionLaunchStatus =
-                    ExecutePreparedModel(preparedModel, request, measure, executionCallback);
+            Return<ErrorStatus> executionLaunchStatus = ExecutePreparedModel(
+                    preparedModel, request, testConfig.measureTiming, executionCallback);
             ASSERT_TRUE(executionLaunchStatus.isOk());
             EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
 
@@ -234,8 +247,8 @@
             SCOPED_TRACE("synchronous");
 
             // execute
-            Return<ErrorStatus> executionReturnStatus =
-                    ExecutePreparedModel(preparedModel, request, measure, &outputShapes, &timing);
+            Return<ErrorStatus> executionReturnStatus = ExecutePreparedModel(
+                    preparedModel, request, testConfig.measureTiming, &outputShapes, &timing);
             ASSERT_TRUE(executionReturnStatus.isOk());
             executionStatus = static_cast<ErrorStatus>(executionReturnStatus);
 
@@ -258,14 +271,14 @@
             // execute burst
             int n;
             std::tie(n, outputShapes, timing, std::ignore) =
-                    controller->compute(request, measure, keys);
+                    controller->compute(request, testConfig.measureTiming, keys);
             executionStatus = nn::convertResultCodeToErrorStatus(n);
 
             break;
         }
     }
 
-    if (outputType != OutputType::FULLY_SPECIFIED &&
+    if (testConfig.outputType != OutputType::FULLY_SPECIFIED &&
         executionStatus == ErrorStatus::GENERAL_FAILURE) {
         LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
                      "execute model that it does not support.";
@@ -274,7 +287,7 @@
                   << std::endl;
         GTEST_SKIP();
     }
-    if (measure == MeasureTiming::NO) {
+    if (testConfig.measureTiming == MeasureTiming::NO) {
         EXPECT_EQ(UINT64_MAX, timing.timeOnDevice);
         EXPECT_EQ(UINT64_MAX, timing.timeInDriver);
     } else {
@@ -283,7 +296,7 @@
         }
     }
 
-    switch (outputType) {
+    switch (testConfig.outputType) {
         case OutputType::FULLY_SPECIFIED:
             // If the model output operands are fully specified, outputShapes must be either
             // either empty, or have the same number of elements as the number of outputs.
@@ -321,44 +334,29 @@
 
 void EvaluatePreparedModel(const sp<IPreparedModel>& preparedModel, const TestModel& testModel,
                            bool testDynamicOutputShape) {
+    std::vector<OutputType> outputTypesList;
+    std::vector<MeasureTiming> measureTimingList;
+    std::vector<Executor> executorList;
+
     if (testDynamicOutputShape) {
-        EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::NO,
-                              OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::NO,
-                              OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::NO,
-                              OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::YES,
-                              OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::YES,
-                              OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::YES,
-                              OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::NO,
-                              OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::NO,
-                              OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::NO,
-                              OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::YES,
-                              OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::YES,
-                              OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::YES,
-                              OutputType::INSUFFICIENT);
+        outputTypesList = {OutputType::UNSPECIFIED, OutputType::INSUFFICIENT};
+        measureTimingList = {MeasureTiming::NO, MeasureTiming::YES};
+        executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST};
     } else {
-        EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::NO,
-                              OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::NO,
-                              OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::NO,
-                              OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::YES,
-                              OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::YES,
-                              OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::YES,
-                              OutputType::FULLY_SPECIFIED);
+        outputTypesList = {OutputType::FULLY_SPECIFIED};
+        measureTimingList = {MeasureTiming::NO, MeasureTiming::YES};
+        executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST};
+    }
+
+    for (const OutputType outputType : outputTypesList) {
+        for (const MeasureTiming measureTiming : measureTimingList) {
+            for (const Executor executor : executorList) {
+                const TestConfig testConfig = {.executor = executor,
+                                               .measureTiming = measureTiming,
+                                               .outputType = outputType};
+                EvaluatePreparedModel(preparedModel, testModel, testConfig);
+            }
+        }
     }
 }
 
diff --git a/neuralnetworks/1.3/types.hal b/neuralnetworks/1.3/types.hal
index 7df14b1..84c4813 100644
--- a/neuralnetworks/1.3/types.hal
+++ b/neuralnetworks/1.3/types.hal
@@ -109,6 +109,7 @@
      * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since HAL version 1.3)
      *
      * Supported tensor rank: up to 4
      *
@@ -116,7 +117,8 @@
      * * 0: A tensor.
      * * 1: A tensor of the same {@link OperandType}, and compatible dimensions
      *      as input0.
-     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scales and zeroPoint can be different from input0 scale and zeroPoint.
      * * 2: An {@link OperandType::INT32} scalar, and has to be one of the
      *      {@link FusedActivationFunc} values. Specifies the activation to
@@ -124,7 +126,8 @@
      *
      * Outputs:
      * * 0: The sum, a tensor of the same {@link OperandType} as input0.
-     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
      *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
      */
     ADD = @1.2::OperationType:ADD,
@@ -146,6 +149,7 @@
      * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since HAL version 1.3)
      *
      * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout.
      * With the default data layout NHWC, the data is stored in the order of:
@@ -207,7 +211,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, out_height, out_width, depth].
-     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scale and zeroPoint must be the same as input0.
      */
     AVERAGE_POOL_2D = @1.2::OperationType:AVERAGE_POOL_2D,
@@ -223,6 +228,7 @@
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *   (full support since HAL version 1.2, see the input section)
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since HAL version 1.3)
      *
      * Supported tensor rank: up to 4
      *
@@ -232,6 +238,9 @@
      *            Before HAL version 1.2, all input tensors of
      *            {@link OperandType::TENSOR_QUANT8_ASYMM}
      *            must have the same scale and zeroPoint as the output tensor.
+     *            Input tensors of
+     *            {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED}
+     *            are allowed to have different scale and zeroPoint.
      *            Since HAL version 1.2, zero-sized tensors are supported.
      * * n: An {@link OperandType::INT32} scalar, specifying the
      *      concatenation axis.
@@ -242,6 +251,8 @@
      *      Since HAL version 1.2, for a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
      *      the scale and zeroPoint values can be different from
      *      input tensors. Before HAL version 1.2 they have to be the same as for the input tensors.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
+     *      the scale and zeroPoint values can be different from input tensors.
      */
     CONCATENATION = @1.2::OperationType:CONCATENATION,
 
@@ -951,6 +962,7 @@
      * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since HAL version 1.3)
      *
      * Supported tensor rank: up to 4.
      *
@@ -962,6 +974,8 @@
      * * 0: The output tensor of same shape as input0.
      *      For {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the scale must be 1.f / 256 and the zeroPoint must be 0.
+     *      For {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED},
+     *      the scale must be 1.f / 256 and the zeroPoint must be -128.
      */
     LOGISTIC = @1.2::OperationType:LOGISTIC,
 
@@ -1256,6 +1270,7 @@
      * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since HAL version 1.3)
      *
      * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout.
      * With the default data layout NHWC, the data is stored in the order of:
@@ -1317,7 +1332,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, out_height, out_width, depth].
-     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scale and zeroPoint must be the same as input0.
      */
     MAX_POOL_2D = @1.2::OperationType:MAX_POOL_2D,
@@ -1345,6 +1361,7 @@
      * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since HAL version 1.3)
      *
      * Supported tensor rank: up to 4
      *
@@ -1358,7 +1375,8 @@
      *
      * Outputs:
      * * 0: The product, a tensor of the same {@link OperandType} as input0.
-     *      For output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
+     *      For output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}
+     *      and {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED},
      *      the following condition must be satisfied:
      *      output_scale > input1_scale * input2_scale.
      */
@@ -1375,6 +1393,7 @@
      * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since HAL version 1.3)
      *
      * Supported tensor rank: up to 4.
      *
@@ -1384,7 +1403,8 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
-     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scale and zeroPoint must be the same as input0.
      */
     RELU = @1.2::OperationType:RELU,
@@ -1400,6 +1420,7 @@
      * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since HAL version 1.3)
      *
      * Supported tensor rank: up to 4.
      *
@@ -1409,7 +1430,8 @@
      *
      * Outputs:
      * * 0: The output tensor of the same shape as input0.
-     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scale and zeroPoint must be the same as input0.
      */
     RELU1 = @1.2::OperationType:RELU1,
@@ -1425,6 +1447,7 @@
      * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since HAL version 1.3)
      *
      * Supported tensor rank: up to 4.
      *
@@ -1434,7 +1457,8 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
-     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scale and zeroPoint must be the same as input0.
      */
     RELU6 = @1.2::OperationType:RELU6,
@@ -1449,6 +1473,7 @@
      * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since HAL version 1.3)
      *
      * Supported tensor rank: up to 4.
      *
@@ -1465,7 +1490,8 @@
      *
      * Outputs:
      * * 0: The output tensor, of shape specified by the input shape.
-     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scale and zeroPoint must be the same as input0.
      */
     RESHAPE = @1.2::OperationType:RESHAPE,
@@ -1755,6 +1781,7 @@
      * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since HAL version 1.2)
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since HAL version 1.3)
      *
      * Supported tensor rank: up to 4.
      *
@@ -1766,6 +1793,8 @@
      * * 0: The output tensor of same shape as input0.
      *      For {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the scale must be 1.f / 128 and the zeroPoint must be 128.
+     *      For {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED},
+     *      the scale must be 1.f / 128 and the zeroPoint must be 0.
      */
     TANH = @1.2::OperationType:TANH,
 
@@ -1861,6 +1890,7 @@
      * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since HAL version 1.3)
      *
      * Supported tensor rank: up to 4
      *
@@ -1880,8 +1910,9 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
-     *      the scale and zeroPoint must be same as input0.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     MEAN = @1.2::OperationType:MEAN,
 
@@ -1988,6 +2019,7 @@
      * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since HAL version 1.3)
      *
      * Supported tensor rank: up to 4
      *
@@ -2003,7 +2035,8 @@
      * * 0: A tensor of the same {@link OperandType} as input0. Contains the
      *      same data as input, but has one or more dimensions of size 1
      *      removed.
-     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scale and zeroPoint must be the same as input0.
      */
     SQUEEZE = @1.2::OperationType:SQUEEZE,
@@ -2021,6 +2054,7 @@
      * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since HAL version 1.3)
      *
      * Supported tensor rank: up to 4
      *
@@ -2050,7 +2084,8 @@
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0 and rank (n - k),
      *      where k is the number of bits set in shrink_axis_mask.
-     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scale and zeroPoint must be the same as input0.
      */
     STRIDED_SLICE = @1.2::OperationType:STRIDED_SLICE,
@@ -2083,6 +2118,7 @@
      * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since HAL version 1.2)
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since HAL version 1.3)
      *
      * Supported tensor rank: up to 4
      *
@@ -2096,7 +2132,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
      */
     SUB = @1.2::OperationType:SUB,
@@ -2375,15 +2412,17 @@
      *       then clipping is disabled.
      *       If all the input tensors have type {@link OperandType::TENSOR_FLOAT32},
      *       this scalar must be of the type {@link OperandType::FLOAT32},
-     *       otherwise if all the input tensors have the type {@link OperandType::TENSOR_FLOAT16},
-     *       this scalar must be of type {@link OperandType::FLOAT16}.
+     *       otherwise if all the input tensors have the type
+     *       {@link OperandType::TENSOR_FLOAT16}, this scalar must be
+     *       of type {@link OperandType::FLOAT16}.
      * * 50: The clipping threshold for the output from the
      *       projection layer, such that values are bound within
      *       [-proj_clip, proj_clip]. If set to 0.0 then clipping is disabled.
      *       If all the input tensors have type {@link OperandType::TENSOR_FLOAT32},
      *       this scalar must be of the type {@link OperandType::FLOAT32},
-     *       otherwise if all the input tensors have the type {@link OperandType::TENSOR_FLOAT16},
-     *       this scalar must be of type {@link OperandType::FLOAT16}.
+     *       otherwise if all the input tensors have the type
+     *       {@link OperandType::TENSOR_FLOAT16}, this scalar must be
+     *       of type {@link OperandType::FLOAT16}.
      * * 51: merge_outputs
      *       An {@link OperandType::BOOL} scalar specifying if the outputs
      *       from forward and backward cells should be merged.
@@ -3799,6 +3838,7 @@
      * * {@link OperandType::TENSOR_FLOAT16}
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since HAL version 1.3)
      *
      * Supported tensor rank: up to 4
      *
@@ -3811,7 +3851,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scale and zeroPoint must be the same as input0.
      */
     REDUCE_MAX = @1.2::OperationType:REDUCE_MAX,
@@ -3828,6 +3869,7 @@
      * * {@link OperandType::TENSOR_FLOAT16}
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since HAL version 1.3)
      *
      * Supported tensor rank: up to 4
      *
@@ -3840,7 +3882,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scale and zeroPoint must be the same as input0.
      */
     REDUCE_MIN = @1.2::OperationType:REDUCE_MIN,
@@ -4034,6 +4077,7 @@
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_INT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since HAL version 1.3)
      *
      * Supported tensor rank: from 1
      *
@@ -4044,14 +4088,14 @@
      *      true) or input2 (if false).
      * * 1: An input tensor of the same shape as input0.
      * * 2: An input tensor of the same shape and type as input1.
-     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM}
+     *      and {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scales and zeroPoint can be different from input1 scale and zeroPoint.
      *
      * Outputs:
      * * 0: A tensor of the same type and shape as input1 and input2.
      *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
      *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
-     *
      */
     SELECT = @1.2::OperationType:SELECT,
 
diff --git a/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp
index d8a7534..60992d5 100644
--- a/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp
@@ -456,8 +456,7 @@
     }
 
     // Execute and verify results.
-    EvaluatePreparedModel(preparedModel, testModel,
-                          /*testDynamicOutputShape=*/false);
+    EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
 }
 
 TEST_P(CompilationCachingTest, CacheSavingAndRetrievalNonZeroOffset) {
@@ -519,8 +518,7 @@
     }
 
     // Execute and verify results.
-    EvaluatePreparedModel(preparedModel, testModel,
-                          /*testDynamicOutputShape=*/false);
+    EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
 }
 
 TEST_P(CompilationCachingTest, SaveToCacheInvalidNumCache) {
@@ -541,8 +539,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel,
-                              /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -566,8 +563,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel,
-                              /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -590,8 +586,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel,
-                              /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -615,8 +610,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel,
-                              /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -727,8 +721,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel,
-                              /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -752,8 +745,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel,
-                              /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -776,8 +768,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel,
-                              /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -801,8 +792,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel,
-                              /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -914,8 +904,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel,
-                              /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -937,8 +926,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel,
-                              /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -1082,8 +1070,7 @@
                 ASSERT_EQ(preparedModel, nullptr);
             } else {
                 ASSERT_NE(preparedModel, nullptr);
-                EvaluatePreparedModel(preparedModel, testModelAdd,
-                                      /*testDynamicOutputShape=*/false);
+                EvaluatePreparedModel(preparedModel, testModelAdd, /*testKind=*/TestKind::GENERAL);
             }
         }
     }
@@ -1144,8 +1131,7 @@
                 ASSERT_EQ(preparedModel, nullptr);
             } else {
                 ASSERT_NE(preparedModel, nullptr);
-                EvaluatePreparedModel(preparedModel, testModelAdd,
-                                      /*testDynamicOutputShape=*/false);
+                EvaluatePreparedModel(preparedModel, testModelAdd, /*testKind=*/TestKind::GENERAL);
             }
         }
     }
diff --git a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
index 1059bde..be894f2 100644
--- a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
@@ -34,13 +34,14 @@
 #include <android/hardware/neuralnetworks/1.3/types.h>
 #include <android/hidl/allocator/1.0/IAllocator.h>
 #include <android/hidl/memory/1.0/IMemory.h>
+#include <gtest/gtest.h>
 #include <hidlmemory/mapping.h>
 
-#include <gtest/gtest.h>
 #include <algorithm>
 #include <chrono>
 #include <iostream>
 #include <numeric>
+#include <vector>
 
 #include "1.0/Utils.h"
 #include "1.2/Callbacks.h"
@@ -69,8 +70,35 @@
 using V1_2::implementation::ExecutionCallback;
 using HidlToken = hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
 
+namespace {
+
+enum class Executor { ASYNC, SYNC, BURST };
+
 enum class OutputType { FULLY_SPECIFIED, UNSPECIFIED, INSUFFICIENT };
 
+struct TestConfig {
+    Executor executor;
+    MeasureTiming measureTiming;
+    OutputType outputType;
+    // `reportSkipping` indicates if a test should print an info message in case
+    // it is skipped. The field is set to true by default and is set to false in
+    // quantization coupling tests to suppress skipping a test
+    bool reportSkipping;
+    TestConfig(Executor executor, MeasureTiming measureTiming, OutputType outputType)
+        : executor(executor),
+          measureTiming(measureTiming),
+          outputType(outputType),
+          reportSkipping(true) {}
+    TestConfig(Executor executor, MeasureTiming measureTiming, OutputType outputType,
+               bool reportSkipping)
+        : executor(executor),
+          measureTiming(measureTiming),
+          outputType(outputType),
+          reportSkipping(reportSkipping) {}
+};
+
+}  // namespace
+
 Model createModel(const TestModel& testModel) {
     // Model operands.
     hidl_vec<Operand> operands(testModel.operands.size());
@@ -205,31 +233,34 @@
     return android::nn::ExecutionBurstController::create(preparedModel,
                                                          std::chrono::microseconds{0});
 }
-enum class Executor { ASYNC, SYNC, BURST };
 
 void EvaluatePreparedModel(const sp<IPreparedModel>& preparedModel, const TestModel& testModel,
-                           Executor executor, MeasureTiming measure, OutputType outputType) {
+                           const TestConfig& testConfig, bool* skipped = nullptr) {
+    if (skipped != nullptr) {
+        *skipped = false;
+    }
     // If output0 does not have size larger than one byte, we can not test with insufficient buffer.
-    if (outputType == OutputType::INSUFFICIENT && !isOutputSizeGreaterThanOne(testModel, 0)) {
+    if (testConfig.outputType == OutputType::INSUFFICIENT &&
+        !isOutputSizeGreaterThanOne(testModel, 0)) {
         return;
     }
 
     Request request = createRequest(testModel);
-    if (outputType == OutputType::INSUFFICIENT) {
+    if (testConfig.outputType == OutputType::INSUFFICIENT) {
         makeOutputInsufficientSize(/*outputIndex=*/0, &request);
     }
 
     ErrorStatus executionStatus;
     hidl_vec<OutputShape> outputShapes;
     Timing timing;
-    switch (executor) {
+    switch (testConfig.executor) {
         case Executor::ASYNC: {
             SCOPED_TRACE("asynchronous");
 
             // launch execution
             sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-            Return<ErrorStatus> executionLaunchStatus =
-                    ExecutePreparedModel(preparedModel, request, measure, executionCallback);
+            Return<ErrorStatus> executionLaunchStatus = ExecutePreparedModel(
+                    preparedModel, request, testConfig.measureTiming, executionCallback);
             ASSERT_TRUE(executionLaunchStatus.isOk());
             EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
 
@@ -245,8 +276,8 @@
             SCOPED_TRACE("synchronous");
 
             // execute
-            Return<ErrorStatus> executionReturnStatus =
-                    ExecutePreparedModel(preparedModel, request, measure, &outputShapes, &timing);
+            Return<ErrorStatus> executionReturnStatus = ExecutePreparedModel(
+                    preparedModel, request, testConfig.measureTiming, &outputShapes, &timing);
             ASSERT_TRUE(executionReturnStatus.isOk());
             executionStatus = static_cast<ErrorStatus>(executionReturnStatus);
 
@@ -269,15 +300,21 @@
             // execute burst
             int n;
             std::tie(n, outputShapes, timing, std::ignore) =
-                    controller->compute(request, measure, keys);
+                    controller->compute(request, testConfig.measureTiming, keys);
             executionStatus = nn::convertResultCodeToErrorStatus(n);
 
             break;
         }
     }
 
-    if (outputType != OutputType::FULLY_SPECIFIED &&
+    if (testConfig.outputType != OutputType::FULLY_SPECIFIED &&
         executionStatus == ErrorStatus::GENERAL_FAILURE) {
+        if (skipped != nullptr) {
+            *skipped = true;
+        }
+        if (!testConfig.reportSkipping) {
+            return;
+        }
         LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
                      "execute model that it does not support.";
         std::cout << "[          ]   Early termination of test because vendor service cannot "
@@ -285,7 +322,7 @@
                   << std::endl;
         GTEST_SKIP();
     }
-    if (measure == MeasureTiming::NO) {
+    if (testConfig.measureTiming == MeasureTiming::NO) {
         EXPECT_EQ(UINT64_MAX, timing.timeOnDevice);
         EXPECT_EQ(UINT64_MAX, timing.timeInDriver);
     } else {
@@ -294,7 +331,7 @@
         }
     }
 
-    switch (outputType) {
+    switch (testConfig.outputType) {
         case OutputType::FULLY_SPECIFIED:
             // If the model output operands are fully specified, outputShapes must be either
             // either empty, or have the same number of elements as the number of outputs.
@@ -331,59 +368,115 @@
 }
 
 void EvaluatePreparedModel(const sp<IPreparedModel>& preparedModel, const TestModel& testModel,
-                           bool testDynamicOutputShape) {
-    if (testDynamicOutputShape) {
-        EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::NO,
-                              OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::NO,
-                              OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::NO,
-                              OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::YES,
-                              OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::YES,
-                              OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::YES,
-                              OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::NO,
-                              OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::NO,
-                              OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::NO,
-                              OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::YES,
-                              OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::YES,
-                              OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::YES,
-                              OutputType::INSUFFICIENT);
-    } else {
-        EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::NO,
-                              OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::NO,
-                              OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::NO,
-                              OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::YES,
-                              OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::YES,
-                              OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::YES,
-                              OutputType::FULLY_SPECIFIED);
+                           TestKind testKind) {
+    std::vector<OutputType> outputTypesList;
+    std::vector<MeasureTiming> measureTimingList;
+    std::vector<Executor> executorList;
+
+    switch (testKind) {
+        case TestKind::GENERAL: {
+            outputTypesList = {OutputType::FULLY_SPECIFIED};
+            measureTimingList = {MeasureTiming::NO, MeasureTiming::YES};
+            executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST};
+        } break;
+        case TestKind::DYNAMIC_SHAPE: {
+            outputTypesList = {OutputType::UNSPECIFIED, OutputType::INSUFFICIENT};
+            measureTimingList = {MeasureTiming::NO, MeasureTiming::YES};
+            executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST};
+        } break;
+        case TestKind::QUANTIZATION_COUPLING: {
+            LOG(FATAL) << "Wrong TestKind for EvaluatePreparedModel";
+            return;
+        } break;
+    }
+
+    for (const OutputType outputType : outputTypesList) {
+        for (const MeasureTiming measureTiming : measureTimingList) {
+            for (const Executor executor : executorList) {
+                const TestConfig testConfig(executor, measureTiming, outputType);
+                EvaluatePreparedModel(preparedModel, testModel, testConfig);
+            }
+        }
     }
 }
 
-void Execute(const sp<IDevice>& device, const TestModel& testModel, bool testDynamicOutputShape) {
+void EvaluatePreparedCoupledModels(const sp<IPreparedModel>& preparedModel,
+                                   const TestModel& testModel,
+                                   const sp<IPreparedModel>& preparedCoupledModel,
+                                   const TestModel& coupledModel) {
+    const std::vector<OutputType> outputTypesList = {OutputType::FULLY_SPECIFIED};
+    const std::vector<MeasureTiming> measureTimingList = {MeasureTiming::NO, MeasureTiming::YES};
+    const std::vector<Executor> executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST};
+
+    for (const OutputType outputType : outputTypesList) {
+        for (const MeasureTiming measureTiming : measureTimingList) {
+            for (const Executor executor : executorList) {
+                const TestConfig testConfig(executor, measureTiming, outputType,
+                                            /*reportSkipping=*/false);
+                bool baseSkipped = false;
+                EvaluatePreparedModel(preparedModel, testModel, testConfig, &baseSkipped);
+                bool coupledSkipped = false;
+                EvaluatePreparedModel(preparedCoupledModel, coupledModel, testConfig,
+                                      &coupledSkipped);
+                ASSERT_EQ(baseSkipped, coupledSkipped);
+                if (baseSkipped) {
+                    LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
+                                 "execute model that it does not support.";
+                    std::cout << "[          ]   Early termination of test because vendor service "
+                                 "cannot "
+                                 "execute model that it does not support."
+                              << std::endl;
+                    GTEST_SKIP();
+                }
+            }
+        }
+    }
+}
+
+void Execute(const sp<IDevice>& device, const TestModel& testModel, TestKind testKind) {
     Model model = createModel(testModel);
-    if (testDynamicOutputShape) {
+    if (testKind == TestKind::DYNAMIC_SHAPE) {
         makeOutputDimensionsUnspecified(&model);
     }
 
     sp<IPreparedModel> preparedModel;
-    createPreparedModel(device, model, &preparedModel);
-    if (preparedModel == nullptr) return;
-
-    EvaluatePreparedModel(preparedModel, testModel, testDynamicOutputShape);
+    switch (testKind) {
+        case TestKind::GENERAL: {
+            createPreparedModel(device, model, &preparedModel);
+            if (preparedModel == nullptr) return;
+            EvaluatePreparedModel(preparedModel, testModel, TestKind::GENERAL);
+        } break;
+        case TestKind::DYNAMIC_SHAPE: {
+            createPreparedModel(device, model, &preparedModel);
+            if (preparedModel == nullptr) return;
+            EvaluatePreparedModel(preparedModel, testModel, TestKind::DYNAMIC_SHAPE);
+        } break;
+        case TestKind::QUANTIZATION_COUPLING: {
+            ASSERT_TRUE(testModel.hasQuant8AsymmOperands());
+            createPreparedModel(device, model, &preparedModel, /*reportSkipping*/ false);
+            TestModel signedQuantizedModel = convertQuant8AsymmOperandsToSigned(testModel);
+            sp<IPreparedModel> preparedCoupledModel;
+            createPreparedModel(device, createModel(signedQuantizedModel), &preparedCoupledModel,
+                                /*reportSkipping*/ false);
+            // If we couldn't prepare a model with unsigned quantization, we must
+            // fail to prepare a model with signed quantization as well.
+            if (preparedModel == nullptr) {
+                ASSERT_EQ(preparedCoupledModel, nullptr);
+                // If we failed to prepare both of the models, we can safely skip
+                // the test.
+                LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
+                             "prepare model that it does not support.";
+                std::cout
+                        << "[          ]   Early termination of test because vendor service cannot "
+                           "prepare model that it does not support."
+                        << std::endl;
+                GTEST_SKIP();
+            }
+            ASSERT_NE(preparedCoupledModel, nullptr);
+            EvaluatePreparedCoupledModels(preparedModel, testModel, preparedCoupledModel,
+                                          signedQuantizedModel);
+        } break;
+    }
 }
 
 void GeneratedTestBase::SetUp() {
@@ -406,12 +499,19 @@
 // Tag for the dynamic output shape tests
 class DynamicOutputShapeTest : public GeneratedTest {};
 
+// Tag for the dynamic output shape tests
+class DISABLED_QuantizationCouplingTest : public GeneratedTest {};
+
 TEST_P(GeneratedTest, Test) {
-    Execute(kDevice, kTestModel, /*testDynamicOutputShape=*/false);
+    Execute(kDevice, kTestModel, /*testKind=*/TestKind::GENERAL);
 }
 
 TEST_P(DynamicOutputShapeTest, Test) {
-    Execute(kDevice, kTestModel, /*testDynamicOutputShape=*/true);
+    Execute(kDevice, kTestModel, /*testKind=*/TestKind::DYNAMIC_SHAPE);
+}
+
+TEST_P(DISABLED_QuantizationCouplingTest, Test) {
+    Execute(kDevice, kTestModel, /*testKind=*/TestKind::QUANTIZATION_COUPLING);
 }
 
 INSTANTIATE_GENERATED_TEST(GeneratedTest,
@@ -420,4 +520,8 @@
 INSTANTIATE_GENERATED_TEST(DynamicOutputShapeTest,
                            [](const TestModel& testModel) { return !testModel.expectFailure; });
 
+INSTANTIATE_GENERATED_TEST(DISABLED_QuantizationCouplingTest, [](const TestModel& testModel) {
+    return testModel.hasQuant8AsymmOperands() && testModel.operations.size() == 1;
+});
+
 }  // namespace android::hardware::neuralnetworks::V1_3::vts::functional
diff --git a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h
index 45cff5b..ad6323f 100644
--- a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h
+++ b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h
@@ -57,8 +57,19 @@
 
 void PrepareModel(const sp<IDevice>& device, const Model& model, sp<IPreparedModel>* preparedModel);
 
+enum class TestKind {
+    // Runs a test model and compares the results to a golden data
+    GENERAL,
+    // Same as GENERAL but sets dimensions for the output tensors to zeros
+    DYNAMIC_SHAPE,
+    // Tests if quantized model with TENSOR_QUANT8_ASYMM produces the same result
+    // (OK/SKIPPED/FAILED) as the model with all such tensors converted to
+    // TENSOR_QUANT8_ASYMM_SIGNED.
+    QUANTIZATION_COUPLING
+};
+
 void EvaluatePreparedModel(const sp<IPreparedModel>& preparedModel,
-                           const test_helper::TestModel& testModel, bool testDynamicOutputShape);
+                           const test_helper::TestModel& testModel, TestKind testKind);
 
 }  // namespace android::hardware::neuralnetworks::V1_3::vts::functional
 
diff --git a/neuralnetworks/1.3/vts/functional/ValidateModel.cpp b/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
index 46bbd3f..6fd5407 100644
--- a/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
@@ -340,11 +340,22 @@
             case OperationType::ARGMAX:
             case OperationType::ARGMIN: {
                 if (type == OperandType::TENSOR_FLOAT16 || type == OperandType::TENSOR_FLOAT32 ||
-                    type == OperandType::TENSOR_INT32 || type == OperandType::TENSOR_QUANT8_ASYMM) {
+                    type == OperandType::TENSOR_INT32 || type == OperandType::TENSOR_QUANT8_ASYMM ||
+                    type == OperandType::TENSOR_QUANT8_ASYMM_SIGNED) {
                     return true;
                 }
             } break;
-            case OperationType::QUANTIZE:
+            case OperationType::QUANTIZE: {
+                if (operand == operation.inputs[0] &&
+                    (type == OperandType::TENSOR_FLOAT16 || type == OperandType::TENSOR_FLOAT32)) {
+                    return true;
+                }
+                if (operand == operation.outputs[0] &&
+                    (type == OperandType::TENSOR_QUANT8_ASYMM ||
+                     type == OperandType::TENSOR_QUANT8_ASYMM_SIGNED)) {
+                    return true;
+                }
+            } break;
             case OperationType::RANDOM_MULTINOMIAL: {
                 if (operand == operation.inputs[0] &&
                     (type == OperandType::TENSOR_FLOAT16 || type == OperandType::TENSOR_FLOAT32)) {
diff --git a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp
index 625913d..92d8fa7 100644
--- a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp
@@ -37,7 +37,7 @@
 
 // internal helper function
 void createPreparedModel(const sp<IDevice>& device, const Model& model,
-                         sp<IPreparedModel>* preparedModel) {
+                         sp<IPreparedModel>* preparedModel, bool reportSkipping) {
     ASSERT_NE(nullptr, preparedModel);
     *preparedModel = nullptr;
 
@@ -74,6 +74,9 @@
     // can continue.
     if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
         ASSERT_EQ(nullptr, preparedModel->get());
+        if (!reportSkipping) {
+            return;
+        }
         LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot prepare "
                      "model that it does not support.";
         std::cout << "[          ]   Early termination of test because vendor service cannot "
diff --git a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h
index 8cb42d4..4e51052 100644
--- a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h
@@ -47,7 +47,7 @@
 // Create an IPreparedModel object. If the model cannot be prepared,
 // "preparedModel" will be nullptr instead.
 void createPreparedModel(const sp<IDevice>& device, const Model& model,
-                         sp<IPreparedModel>* preparedModel);
+                         sp<IPreparedModel>* preparedModel, bool reportSkipping = true);
 
 // Utility function to get PreparedModel from callback and downcast to V1_2.
 sp<IPreparedModel> getPreparedModel_1_3(const sp<implementation::PreparedModelCallback>& callback);
diff --git a/radio/1.0/vts/functional/Android.bp b/radio/1.0/vts/functional/Android.bp
index 9dec2f2..2351d90 100644
--- a/radio/1.0/vts/functional/Android.bp
+++ b/radio/1.0/vts/functional/Android.bp
@@ -33,7 +33,8 @@
     static_libs: [
         "android.hardware.radio@1.0",
     ],
-    test_suites: ["general-tests"],
+    test_config: "vts_hal_radio_target_test.xml",
+    test_suites: ["general-tests", "vts-core"],
 }
 
 cc_test {
@@ -47,7 +48,8 @@
     static_libs: [
         "android.hardware.radio@1.0",
     ],
-    test_suites: ["general-tests"],
+    test_config: "vts_hal_sap_target_test.xml",
+    test_suites: ["general-tests", "vts-core"],
 }
 
 cc_library_static {
diff --git a/radio/1.0/vts/functional/VtsHalRadioV1_0TargetTest.cpp b/radio/1.0/vts/functional/VtsHalRadioV1_0TargetTest.cpp
index d53c062..9d61b52 100644
--- a/radio/1.0/vts/functional/VtsHalRadioV1_0TargetTest.cpp
+++ b/radio/1.0/vts/functional/VtsHalRadioV1_0TargetTest.cpp
@@ -14,12 +14,18 @@
  * limitations under the License.
  */
 
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 #include <radio_hidl_hal_utils_v1_0.h>
 
+INSTANTIATE_TEST_SUITE_P(PerInstance, RadioHidlTest,
+                         testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+                                 ::android::hardware::radio::V1_0::IRadio::descriptor)),
+                         android::hardware::PrintInstanceNameToString);
+
 int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(RadioHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
-    RadioHidlEnvironment::Instance()->init(&argc, argv);
 
     // setup seed for rand function
     int seedSrand = time(NULL);
diff --git a/radio/1.0/vts/functional/VtsHalSapV1_0TargetTest.cpp b/radio/1.0/vts/functional/VtsHalSapV1_0TargetTest.cpp
index 859e6fb..b80b971 100644
--- a/radio/1.0/vts/functional/VtsHalSapV1_0TargetTest.cpp
+++ b/radio/1.0/vts/functional/VtsHalSapV1_0TargetTest.cpp
@@ -14,12 +14,18 @@
  * limitations under the License.
  */
 
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 #include <sap_hidl_hal_utils.h>
 
+INSTANTIATE_TEST_SUITE_P(PerInstance, SapHidlTest,
+                         testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+                                 ::android::hardware::radio::V1_0::ISap::descriptor)),
+                         android::hardware::PrintInstanceNameToString);
+
 int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(SapHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
-    SapHidlEnvironment::Instance()->init(&argc, argv);
 
     // setup seed for rand function
     int seedSrand = time(NULL);
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_cell_broadcast.cpp b/radio/1.0/vts/functional/radio_hidl_hal_cell_broadcast.cpp
index 2c1eb60..125ea0c 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_cell_broadcast.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_cell_broadcast.cpp
@@ -21,7 +21,7 @@
 /*
  * Test IRadio.setGsmBroadcastConfig() for the response returned.
  */
-TEST_F(RadioHidlTest, setGsmBroadcastConfig) {
+TEST_P(RadioHidlTest, setGsmBroadcastConfig) {
     serial = GetRandomSerialNumber();
 
     // Create GsmBroadcastSmsConfigInfo #1
@@ -84,7 +84,7 @@
 /*
  * Test IRadio.getGsmBroadcastConfig() for the response returned.
  */
-TEST_F(RadioHidlTest, getGsmBroadcastConfig) {
+TEST_P(RadioHidlTest, getGsmBroadcastConfig) {
     serial = GetRandomSerialNumber();
 
     radio->getGsmBroadcastConfig(serial);
@@ -104,7 +104,7 @@
 /*
  * Test IRadio.setCdmaBroadcastConfig() for the response returned.
  */
-TEST_F(RadioHidlTest, setCdmaBroadcastConfig) {
+TEST_P(RadioHidlTest, setCdmaBroadcastConfig) {
     serial = GetRandomSerialNumber();
 
     CdmaBroadcastSmsConfigInfo cbSmsConfig;
@@ -131,7 +131,7 @@
 /*
  * Test IRadio.getCdmaBroadcastConfig() for the response returned.
  */
-TEST_F(RadioHidlTest, getCdmaBroadcastConfig) {
+TEST_P(RadioHidlTest, getCdmaBroadcastConfig) {
     serial = GetRandomSerialNumber();
 
     radio->getCdmaBroadcastConfig(serial);
@@ -149,7 +149,7 @@
 /*
  * Test IRadio.setCdmaBroadcastActivation() for the response returned.
  */
-TEST_F(RadioHidlTest, setCdmaBroadcastActivation) {
+TEST_P(RadioHidlTest, setCdmaBroadcastActivation) {
     serial = GetRandomSerialNumber();
     bool activate = false;
 
@@ -169,7 +169,7 @@
 /*
  * Test IRadio.setGsmBroadcastActivation() for the response returned.
  */
-TEST_F(RadioHidlTest, setGsmBroadcastActivation) {
+TEST_P(RadioHidlTest, setGsmBroadcastActivation) {
     serial = GetRandomSerialNumber();
     bool activate = false;
 
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_data.cpp b/radio/1.0/vts/functional/radio_hidl_hal_data.cpp
index eaef3ed..d937d74 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_data.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_data.cpp
@@ -21,7 +21,7 @@
 /*
  * Test IRadio.getDataRegistrationState() for the response returned.
  */
-TEST_F(RadioHidlTest, getDataRegistrationState) {
+TEST_P(RadioHidlTest, getDataRegistrationState) {
     serial = GetRandomSerialNumber();
 
     radio->getDataRegistrationState(serial);
@@ -99,7 +99,7 @@
 /*
  * Test IRadio.setupDataCall() for the response returned.
  */
-TEST_F(RadioHidlTest, setupDataCall) {
+TEST_P(RadioHidlTest, setupDataCall) {
     serial = GetRandomSerialNumber();
 
     RadioTechnology radioTechnology = RadioTechnology::LTE;
@@ -147,7 +147,7 @@
 /*
  * Test IRadio.deactivateDataCall() for the response returned.
  */
-TEST_F(RadioHidlTest, deactivateDataCall) {
+TEST_P(RadioHidlTest, deactivateDataCall) {
     serial = GetRandomSerialNumber();
     int cid = 1;
     bool reasonRadioShutDown = false;
@@ -169,7 +169,7 @@
 /*
  * Test IRadio.getDataCallList() for the response returned.
  */
-TEST_F(RadioHidlTest, getDataCallList) {
+TEST_P(RadioHidlTest, getDataCallList) {
     serial = GetRandomSerialNumber();
 
     radio->getDataCallList(serial);
@@ -188,7 +188,7 @@
 /*
  * Test IRadio.setInitialAttachApn() for the response returned.
  */
-TEST_F(RadioHidlTest, setInitialAttachApn) {
+TEST_P(RadioHidlTest, setInitialAttachApn) {
     serial = GetRandomSerialNumber();
 
     DataProfileInfo dataProfileInfo;
@@ -231,7 +231,7 @@
 /*
  * Test IRadio.setDataAllowed() for the response returned.
  */
-TEST_F(RadioHidlTest, setDataAllowed) {
+TEST_P(RadioHidlTest, setDataAllowed) {
     serial = GetRandomSerialNumber();
     bool allow = true;
 
@@ -249,7 +249,7 @@
 /*
  * Test IRadio.setDataProfile() for the response returned.
  */
-TEST_F(RadioHidlTest, setDataProfile) {
+TEST_P(RadioHidlTest, setDataProfile) {
     serial = GetRandomSerialNumber();
 
     // Create a dataProfileInfo
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp b/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp
index 2670d96..60cb2fe 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp
@@ -19,7 +19,7 @@
 /*
  * Test IRadio.getIccCardStatus() for the response returned.
  */
-TEST_F(RadioHidlTest, getIccCardStatus) {
+TEST_P(RadioHidlTest, getIccCardStatus) {
     EXPECT_LE(cardStatus.applications.size(), (unsigned int)RadioConst::CARD_MAX_APPS);
     EXPECT_LT(cardStatus.gsmUmtsSubscriptionAppIndex, (int)RadioConst::CARD_MAX_APPS);
     EXPECT_LT(cardStatus.cdmaSubscriptionAppIndex, (int)RadioConst::CARD_MAX_APPS);
@@ -29,7 +29,7 @@
 /*
  * Test IRadio.supplyIccPinForApp() for the response returned
  */
-TEST_F(RadioHidlTest, supplyIccPinForApp) {
+TEST_P(RadioHidlTest, supplyIccPinForApp) {
     serial = GetRandomSerialNumber();
 
     // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
@@ -54,7 +54,7 @@
 /*
  * Test IRadio.supplyIccPukForApp() for the response returned.
  */
-TEST_F(RadioHidlTest, supplyIccPukForApp) {
+TEST_P(RadioHidlTest, supplyIccPukForApp) {
     serial = GetRandomSerialNumber();
 
     // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
@@ -78,7 +78,7 @@
 /*
  * Test IRadio.supplyIccPin2ForApp() for the response returned.
  */
-TEST_F(RadioHidlTest, supplyIccPin2ForApp) {
+TEST_P(RadioHidlTest, supplyIccPin2ForApp) {
     serial = GetRandomSerialNumber();
 
     // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
@@ -104,7 +104,7 @@
 /*
  * Test IRadio.supplyIccPuk2ForApp() for the response returned.
  */
-TEST_F(RadioHidlTest, supplyIccPuk2ForApp) {
+TEST_P(RadioHidlTest, supplyIccPuk2ForApp) {
     serial = GetRandomSerialNumber();
 
     // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
@@ -128,7 +128,7 @@
 /*
  * Test IRadio.changeIccPinForApp() for the response returned.
  */
-TEST_F(RadioHidlTest, changeIccPinForApp) {
+TEST_P(RadioHidlTest, changeIccPinForApp) {
     serial = GetRandomSerialNumber();
 
     // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
@@ -153,7 +153,7 @@
 /*
  * Test IRadio.changeIccPin2ForApp() for the response returned.
  */
-TEST_F(RadioHidlTest, changeIccPin2ForApp) {
+TEST_P(RadioHidlTest, changeIccPin2ForApp) {
     serial = GetRandomSerialNumber();
 
     // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
@@ -179,7 +179,7 @@
 /*
  * Test IRadio.getImsiForApp() for the response returned.
  */
-TEST_F(RadioHidlTest, getImsiForApp) {
+TEST_P(RadioHidlTest, getImsiForApp) {
     serial = GetRandomSerialNumber();
 
     // Check success returned while getting imsi for 3GPP and 3GPP2 apps only
@@ -208,7 +208,7 @@
 /*
  * Test IRadio.iccIOForApp() for the response returned.
  */
-TEST_F(RadioHidlTest, iccIOForApp) {
+TEST_P(RadioHidlTest, iccIOForApp) {
     serial = GetRandomSerialNumber();
 
     for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
@@ -233,7 +233,7 @@
 /*
  * Test IRadio.iccTransmitApduBasicChannel() for the response returned.
  */
-TEST_F(RadioHidlTest, iccTransmitApduBasicChannel) {
+TEST_P(RadioHidlTest, iccTransmitApduBasicChannel) {
     serial = GetRandomSerialNumber();
     SimApdu msg;
     memset(&msg, 0, sizeof(msg));
@@ -250,7 +250,7 @@
 /*
  * Test IRadio.iccOpenLogicalChannel() for the response returned.
  */
-TEST_F(RadioHidlTest, iccOpenLogicalChannel) {
+TEST_P(RadioHidlTest, iccOpenLogicalChannel) {
     serial = GetRandomSerialNumber();
     int p2 = 0x04;
     // Specified in ISO 7816-4 clause 7.1.1 0x04 means that FCP template is requested.
@@ -265,7 +265,7 @@
 /*
  * Test IRadio.iccCloseLogicalChannel() for the response returned.
  */
-TEST_F(RadioHidlTest, iccCloseLogicalChannel) {
+TEST_P(RadioHidlTest, iccCloseLogicalChannel) {
     serial = GetRandomSerialNumber();
     // Try closing invalid channel and check INVALID_ARGUMENTS returned as error
     radio->iccCloseLogicalChannel(serial, 0);
@@ -279,7 +279,7 @@
 /*
  * Test IRadio.iccTransmitApduLogicalChannel() for the response returned.
  */
-TEST_F(RadioHidlTest, iccTransmitApduLogicalChannel) {
+TEST_P(RadioHidlTest, iccTransmitApduLogicalChannel) {
     serial = GetRandomSerialNumber();
     SimApdu msg;
     memset(&msg, 0, sizeof(msg));
@@ -296,7 +296,7 @@
 /*
  * Test IRadio.requestIccSimAuthentication() for the response returned.
  */
-TEST_F(RadioHidlTest, requestIccSimAuthentication) {
+TEST_P(RadioHidlTest, requestIccSimAuthentication) {
     serial = GetRandomSerialNumber();
 
     // Pass wrong challenge string and check RadioError::INVALID_ARGUMENTS
@@ -315,7 +315,7 @@
 /*
  * Test IRadio.supplyNetworkDepersonalization() for the response returned.
  */
-TEST_F(RadioHidlTest, supplyNetworkDepersonalization) {
+TEST_P(RadioHidlTest, supplyNetworkDepersonalization) {
     serial = GetRandomSerialNumber();
 
     radio->supplyNetworkDepersonalization(serial, hidl_string("test"));
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_ims.cpp b/radio/1.0/vts/functional/radio_hidl_hal_ims.cpp
index 4331c06..e253dcf 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_ims.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_ims.cpp
@@ -21,7 +21,7 @@
 /*
  * Test IRadio.getClir() for the response returned.
  */
-TEST_F(RadioHidlTest, getClir) {
+TEST_P(RadioHidlTest, getClir) {
     serial = GetRandomSerialNumber();
 
     radio->getClir(serial);
@@ -39,7 +39,7 @@
 /*
  * Test IRadio.setClir() for the response returned.
  */
-TEST_F(RadioHidlTest, setClir) {
+TEST_P(RadioHidlTest, setClir) {
     serial = GetRandomSerialNumber();
     int32_t status = 1;
 
@@ -57,7 +57,7 @@
 /*
  * Test IRadio.getFacilityLockForApp() for the response returned.
  */
-TEST_F(RadioHidlTest, getFacilityLockForApp) {
+TEST_P(RadioHidlTest, getFacilityLockForApp) {
     serial = GetRandomSerialNumber();
     std::string facility = "";
     std::string password = "";
@@ -80,7 +80,7 @@
 /*
  * Test IRadio.setFacilityLockForApp() for the response returned.
  */
-TEST_F(RadioHidlTest, setFacilityLockForApp) {
+TEST_P(RadioHidlTest, setFacilityLockForApp) {
     serial = GetRandomSerialNumber();
     std::string facility = "";
     bool lockState = false;
@@ -104,7 +104,7 @@
 /*
  * Test IRadio.setBarringPassword() for the response returned.
  */
-TEST_F(RadioHidlTest, setBarringPassword) {
+TEST_P(RadioHidlTest, setBarringPassword) {
     serial = GetRandomSerialNumber();
     std::string facility = "";
     std::string oldPassword = "";
@@ -127,7 +127,7 @@
 /*
  * Test IRadio.getClip() for the response returned.
  */
-TEST_F(RadioHidlTest, getClip) {
+TEST_P(RadioHidlTest, getClip) {
     serial = GetRandomSerialNumber();
 
     radio->getClip(serial);
@@ -145,7 +145,7 @@
 /*
  * Test IRadio.setSuppServiceNotifications() for the response returned.
  */
-TEST_F(RadioHidlTest, setSuppServiceNotifications) {
+TEST_P(RadioHidlTest, setSuppServiceNotifications) {
     serial = GetRandomSerialNumber();
     bool enable = false;
 
@@ -164,7 +164,7 @@
 /*
  * Test IRadio.requestIsimAuthentication() for the response returned.
  */
-TEST_F(RadioHidlTest, requestIsimAuthentication) {
+TEST_P(RadioHidlTest, requestIsimAuthentication) {
     serial = GetRandomSerialNumber();
     std::string challenge = "";
 
@@ -186,7 +186,7 @@
 /*
  * Test IRadio.getImsRegistrationState() for the response returned.
  */
-TEST_F(RadioHidlTest, getImsRegistrationState) {
+TEST_P(RadioHidlTest, getImsRegistrationState) {
     serial = GetRandomSerialNumber();
 
     radio->getImsRegistrationState(serial);
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp b/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
index 3499762..d04cb36 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
@@ -19,7 +19,7 @@
 /*
  * Test IRadio.getSignalStrength() for the response returned.
  */
-TEST_F(RadioHidlTest, getSignalStrength) {
+TEST_P(RadioHidlTest, getSignalStrength) {
     serial = GetRandomSerialNumber();
 
     radio->getSignalStrength(serial);
@@ -35,7 +35,7 @@
 /*
  * Test IRadio.getVoiceRegistrationState() for the response returned.
  */
-TEST_F(RadioHidlTest, getVoiceRegistrationState) {
+TEST_P(RadioHidlTest, getVoiceRegistrationState) {
     serial = GetRandomSerialNumber();
 
     radio->getVoiceRegistrationState(serial);
@@ -51,7 +51,7 @@
 /*
  * Test IRadio.getOperator() for the response returned.
  */
-TEST_F(RadioHidlTest, getOperator) {
+TEST_P(RadioHidlTest, getOperator) {
     serial = GetRandomSerialNumber();
 
     radio->getOperator(serial);
@@ -67,7 +67,7 @@
 /*
  * Test IRadio.setRadioPower() for the response returned.
  */
-TEST_F(RadioHidlTest, setRadioPower) {
+TEST_P(RadioHidlTest, setRadioPower) {
     serial = GetRandomSerialNumber();
 
     radio->setRadioPower(serial, 1);
@@ -83,7 +83,7 @@
 /*
  * Test IRadio.getNetworkSelectionMode() for the response returned.
  */
-TEST_F(RadioHidlTest, getNetworkSelectionMode) {
+TEST_P(RadioHidlTest, getNetworkSelectionMode) {
     serial = GetRandomSerialNumber();
 
     radio->getNetworkSelectionMode(serial);
@@ -99,7 +99,7 @@
 /*
  * Test IRadio.setNetworkSelectionModeAutomatic() for the response returned.
  */
-TEST_F(RadioHidlTest, setNetworkSelectionModeAutomatic) {
+TEST_P(RadioHidlTest, setNetworkSelectionModeAutomatic) {
     serial = GetRandomSerialNumber();
 
     radio->setNetworkSelectionModeAutomatic(serial);
@@ -118,7 +118,7 @@
 /*
  * Test IRadio.setNetworkSelectionModeManual() for the response returned.
  */
-TEST_F(RadioHidlTest, setNetworkSelectionModeManual) {
+TEST_P(RadioHidlTest, setNetworkSelectionModeManual) {
     serial = GetRandomSerialNumber();
 
     radio->setNetworkSelectionModeManual(serial, "123456");
@@ -137,7 +137,7 @@
 /*
  * Test IRadio.getAvailableNetworks() for the response returned.
  */
-TEST_F(RadioHidlTest, getAvailableNetworks) {
+TEST_P(RadioHidlTest, getAvailableNetworks) {
     serial = GetRandomSerialNumber();
 
     radio->getAvailableNetworks(serial);
@@ -158,7 +158,7 @@
 /*
  * Test IRadio.getBasebandVersion() for the response returned.
  */
-TEST_F(RadioHidlTest, getBasebandVersion) {
+TEST_P(RadioHidlTest, getBasebandVersion) {
     serial = GetRandomSerialNumber();
 
     radio->getBasebandVersion(serial);
@@ -174,7 +174,7 @@
 /*
  * Test IRadio.setBandMode() for the response returned.
  */
-TEST_F(RadioHidlTest, setBandMode) {
+TEST_P(RadioHidlTest, setBandMode) {
     serial = GetRandomSerialNumber();
 
     radio->setBandMode(serial, RadioBandMode::BAND_MODE_USA);
@@ -191,7 +191,7 @@
 /*
  * Test IRadio.getAvailableBandModes() for the response returned.
  */
-TEST_F(RadioHidlTest, getAvailableBandModes) {
+TEST_P(RadioHidlTest, getAvailableBandModes) {
     serial = GetRandomSerialNumber();
 
     radio->getAvailableBandModes(serial);
@@ -207,7 +207,7 @@
 /*
  * Test IRadio.setPreferredNetworkType() for the response returned.
  */
-TEST_F(RadioHidlTest, setPreferredNetworkType) {
+TEST_P(RadioHidlTest, setPreferredNetworkType) {
     serial = GetRandomSerialNumber();
 
     radio->setPreferredNetworkType(serial, PreferredNetworkType::GSM_ONLY);
@@ -224,7 +224,7 @@
 /*
  * Test IRadio.getPreferredNetworkType() for the response returned.
  */
-TEST_F(RadioHidlTest, getPreferredNetworkType) {
+TEST_P(RadioHidlTest, getPreferredNetworkType) {
     serial = GetRandomSerialNumber();
 
     radio->getPreferredNetworkType(serial);
@@ -240,7 +240,7 @@
 /*
  * Test IRadio.getNeighboringCids() for the response returned.
  */
-TEST_F(RadioHidlTest, getNeighboringCids) {
+TEST_P(RadioHidlTest, getNeighboringCids) {
     serial = GetRandomSerialNumber();
 
     radio->getNeighboringCids(serial);
@@ -258,7 +258,7 @@
 /*
  * Test IRadio.setLocationUpdates() for the response returned.
  */
-TEST_F(RadioHidlTest, setLocationUpdates) {
+TEST_P(RadioHidlTest, setLocationUpdates) {
     serial = GetRandomSerialNumber();
 
     radio->setLocationUpdates(serial, true);
@@ -275,7 +275,7 @@
 /*
  * Test IRadio.setCdmaRoamingPreference() for the response returned.
  */
-TEST_F(RadioHidlTest, setCdmaRoamingPreference) {
+TEST_P(RadioHidlTest, setCdmaRoamingPreference) {
     serial = GetRandomSerialNumber();
 
     radio->setCdmaRoamingPreference(serial, CdmaRoamingType::HOME_NETWORK);
@@ -293,7 +293,7 @@
 /*
  * Test IRadio.getCdmaRoamingPreference() for the response returned.
  */
-TEST_F(RadioHidlTest, getCdmaRoamingPreference) {
+TEST_P(RadioHidlTest, getCdmaRoamingPreference) {
     serial = GetRandomSerialNumber();
 
     radio->getCdmaRoamingPreference(serial);
@@ -312,7 +312,7 @@
 /*
  * Test IRadio.getTTYMode() for the response returned.
  */
-TEST_F(RadioHidlTest, getTTYMode) {
+TEST_P(RadioHidlTest, getTTYMode) {
     serial = GetRandomSerialNumber();
 
     radio->getTTYMode(serial);
@@ -328,7 +328,7 @@
 /*
  * Test IRadio.setTTYMode() for the response returned.
  */
-TEST_F(RadioHidlTest, setTTYMode) {
+TEST_P(RadioHidlTest, setTTYMode) {
     serial = GetRandomSerialNumber();
 
     radio->setTTYMode(serial, TtyMode::OFF);
@@ -344,7 +344,7 @@
 /*
  * Test IRadio.setPreferredVoicePrivacy() for the response returned.
  */
-TEST_F(RadioHidlTest, setPreferredVoicePrivacy) {
+TEST_P(RadioHidlTest, setPreferredVoicePrivacy) {
     serial = GetRandomSerialNumber();
 
     radio->setPreferredVoicePrivacy(serial, true);
@@ -361,7 +361,7 @@
 /*
  * Test IRadio.getPreferredVoicePrivacy() for the response returned.
  */
-TEST_F(RadioHidlTest, getPreferredVoicePrivacy) {
+TEST_P(RadioHidlTest, getPreferredVoicePrivacy) {
     serial = GetRandomSerialNumber();
 
     radio->getPreferredVoicePrivacy(serial);
@@ -378,7 +378,7 @@
 /*
  * Test IRadio.getCDMASubscription() for the response returned.
  */
-TEST_F(RadioHidlTest, getCDMASubscription) {
+TEST_P(RadioHidlTest, getCDMASubscription) {
     serial = GetRandomSerialNumber();
 
     radio->getCDMASubscription(serial);
@@ -396,7 +396,7 @@
 /*
  * Test IRadio.getDeviceIdentity() for the response returned.
  */
-TEST_F(RadioHidlTest, getDeviceIdentity) {
+TEST_P(RadioHidlTest, getDeviceIdentity) {
     serial = GetRandomSerialNumber();
 
     radio->getDeviceIdentity(serial);
@@ -413,7 +413,7 @@
 /*
  * Test IRadio.exitEmergencyCallbackMode() for the response returned.
  */
-TEST_F(RadioHidlTest, exitEmergencyCallbackMode) {
+TEST_P(RadioHidlTest, exitEmergencyCallbackMode) {
     serial = GetRandomSerialNumber();
 
     radio->exitEmergencyCallbackMode(serial);
@@ -431,7 +431,7 @@
 /*
  * Test IRadio.getCdmaSubscriptionSource() for the response returned.
  */
-TEST_F(RadioHidlTest, getCdmaSubscriptionSource) {
+TEST_P(RadioHidlTest, getCdmaSubscriptionSource) {
     serial = GetRandomSerialNumber();
 
     radio->getCdmaSubscriptionSource(serial);
@@ -449,7 +449,7 @@
 /*
  * Test IRadio.setCdmaSubscriptionSource() for the response returned.
  */
-TEST_F(RadioHidlTest, setCdmaSubscriptionSource) {
+TEST_P(RadioHidlTest, setCdmaSubscriptionSource) {
     serial = GetRandomSerialNumber();
 
     radio->setCdmaSubscriptionSource(serial, CdmaSubscriptionSource::RUIM_SIM);
@@ -468,7 +468,7 @@
 /*
  * Test IRadio.getVoiceRadioTechnology() for the response returned.
  */
-TEST_F(RadioHidlTest, getVoiceRadioTechnology) {
+TEST_P(RadioHidlTest, getVoiceRadioTechnology) {
     serial = GetRandomSerialNumber();
 
     radio->getVoiceRadioTechnology(serial);
@@ -484,7 +484,7 @@
 /*
  * Test IRadio.getCellInfoList() for the response returned.
  */
-TEST_F(RadioHidlTest, getCellInfoList) {
+TEST_P(RadioHidlTest, getCellInfoList) {
     serial = GetRandomSerialNumber();
 
     radio->getCellInfoList(serial);
@@ -502,7 +502,7 @@
 /*
  * Test IRadio.setCellInfoListRate() for the response returned.
  */
-TEST_F(RadioHidlTest, setCellInfoListRate) {
+TEST_P(RadioHidlTest, setCellInfoListRate) {
     serial = GetRandomSerialNumber();
 
     // TODO(sanketpadawe): RIL crashes with value of rate = 10
@@ -520,7 +520,7 @@
 /*
  * Test IRadio.nvReadItem() for the response returned.
  */
-TEST_F(RadioHidlTest, nvReadItem) {
+TEST_P(RadioHidlTest, nvReadItem) {
     serial = GetRandomSerialNumber();
 
     radio->nvReadItem(serial, NvItem::LTE_BAND_ENABLE_25);
@@ -537,7 +537,7 @@
 /*
  * Test IRadio.nvWriteItem() for the response returned.
  */
-TEST_F(RadioHidlTest, nvWriteItem) {
+TEST_P(RadioHidlTest, nvWriteItem) {
     serial = GetRandomSerialNumber();
     NvWriteItem item;
     memset(&item, 0, sizeof(item));
@@ -557,7 +557,7 @@
 /*
  * Test IRadio.nvWriteCdmaPrl() for the response returned.
  */
-TEST_F(RadioHidlTest, nvWriteCdmaPrl) {
+TEST_P(RadioHidlTest, nvWriteCdmaPrl) {
     serial = GetRandomSerialNumber();
     std::vector<uint8_t> prl = {1, 2, 3, 4, 5};
 
@@ -575,7 +575,7 @@
 /*
  * Test IRadio.nvResetConfig() for the response returned.
  */
-TEST_F(RadioHidlTest, nvResetConfig) {
+TEST_P(RadioHidlTest, nvResetConfig) {
     serial = GetRandomSerialNumber();
 
     radio->nvResetConfig(serial, ResetNvType::ERASE);
@@ -592,7 +592,7 @@
 /*
  * Test IRadio.setUiccSubscription() for the response returned.
  */
-TEST_F(RadioHidlTest, setUiccSubscription) {
+TEST_P(RadioHidlTest, setUiccSubscription) {
     serial = GetRandomSerialNumber();
     SelectUiccSub item;
     memset(&item, 0, sizeof(item));
@@ -614,7 +614,7 @@
 /*
  * Test IRadio.getHardwareConfig() for the response returned.
  */
-TEST_F(RadioHidlTest, getHardwareConfig) {
+TEST_P(RadioHidlTest, getHardwareConfig) {
     serial = GetRandomSerialNumber();
 
     radio->getHardwareConfig(serial);
@@ -631,7 +631,7 @@
 /*
  * Test IRadio.requestShutdown() for the response returned.
  */
-TEST_F(RadioHidlTest, requestShutdown) {
+TEST_P(RadioHidlTest, requestShutdown) {
     serial = GetRandomSerialNumber();
 
     radio->requestShutdown(serial);
@@ -648,7 +648,7 @@
 /*
  * Test IRadio.getRadioCapability() for the response returned.
  */
-TEST_F(RadioHidlTest, getRadioCapability) {
+TEST_P(RadioHidlTest, getRadioCapability) {
     serial = GetRandomSerialNumber();
 
     radio->getRadioCapability(serial);
@@ -664,7 +664,7 @@
 /*
  * Test IRadio.setRadioCapability() for the response returned.
  */
-TEST_F(RadioHidlTest, setRadioCapability) {
+TEST_P(RadioHidlTest, setRadioCapability) {
     serial = GetRandomSerialNumber();
     RadioCapability rc;
     memset(&rc, 0, sizeof(rc));
@@ -685,7 +685,7 @@
 /*
  * Test IRadio.startLceService() for the response returned.
  */
-TEST_F(RadioHidlTest, startLceService) {
+TEST_P(RadioHidlTest, startLceService) {
     serial = GetRandomSerialNumber();
 
     radio->startLceService(serial, 5, true);
@@ -704,7 +704,7 @@
 /*
  * Test IRadio.stopLceService() for the response returned.
  */
-TEST_F(RadioHidlTest, stopLceService) {
+TEST_P(RadioHidlTest, stopLceService) {
     serial = GetRandomSerialNumber();
 
     radio->stopLceService(serial);
@@ -722,7 +722,7 @@
 /*
  * Test IRadio.pullLceData() for the response returned.
  */
-TEST_F(RadioHidlTest, pullLceData) {
+TEST_P(RadioHidlTest, pullLceData) {
     serial = GetRandomSerialNumber();
 
     radio->pullLceData(serial);
@@ -741,7 +741,7 @@
 /*
  * Test IRadio.getModemActivityInfo() for the response returned.
  */
-TEST_F(RadioHidlTest, getModemActivityInfo) {
+TEST_P(RadioHidlTest, getModemActivityInfo) {
     serial = GetRandomSerialNumber();
 
     radio->getModemActivityInfo(serial);
@@ -758,7 +758,7 @@
 /*
  * Test IRadio.setAllowedCarriers() for the response returned.
  */
-TEST_F(RadioHidlTest, setAllowedCarriers) {
+TEST_P(RadioHidlTest, setAllowedCarriers) {
     serial = GetRandomSerialNumber();
     CarrierRestrictions carriers;
     memset(&carriers, 0, sizeof(carriers));
@@ -835,7 +835,7 @@
 /*
  * Test IRadio.getAllowedCarriers() for the response returned.
  */
-TEST_F(RadioHidlTest, getAllowedCarriers) {
+TEST_P(RadioHidlTest, getAllowedCarriers) {
     serial = GetRandomSerialNumber();
 
     radio->getAllowedCarriers(serial);
@@ -852,7 +852,7 @@
 /*
  * Test IRadio.sendDeviceState() for the response returned.
  */
-TEST_F(RadioHidlTest, sendDeviceState) {
+TEST_P(RadioHidlTest, sendDeviceState) {
     serial = GetRandomSerialNumber();
 
     radio->sendDeviceState(serial, DeviceStateType::POWER_SAVE_MODE, true);
@@ -871,7 +871,7 @@
 /*
  * Test IRadio.setIndicationFilter() for the response returned.
  */
-TEST_F(RadioHidlTest, setIndicationFilter) {
+TEST_P(RadioHidlTest, setIndicationFilter) {
     serial = GetRandomSerialNumber();
 
     radio->setIndicationFilter(serial, 1);
@@ -890,7 +890,7 @@
 /*
  * Test IRadio.setSimCardPower() for the response returned.
  */
-TEST_F(RadioHidlTest, setSimCardPower) {
+TEST_P(RadioHidlTest, setSimCardPower) {
     serial = GetRandomSerialNumber();
 
     radio->setSimCardPower(serial, true);
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_sms.cpp b/radio/1.0/vts/functional/radio_hidl_hal_sms.cpp
index 9e41429..58c3bbd 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_sms.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_sms.cpp
@@ -21,7 +21,7 @@
 /*
  * Test IRadio.sendSms() for the response returned.
  */
-TEST_F(RadioHidlTest, sendSms) {
+TEST_P(RadioHidlTest, sendSms) {
     serial = GetRandomSerialNumber();
     GsmSmsMessage msg;
     msg.smscPdu = "";
@@ -45,7 +45,7 @@
 /*
  * Test IRadio.sendSMSExpectMore() for the response returned.
  */
-TEST_F(RadioHidlTest, sendSMSExpectMore) {
+TEST_P(RadioHidlTest, sendSMSExpectMore) {
     serial = GetRandomSerialNumber();
     GsmSmsMessage msg;
     msg.smscPdu = "";
@@ -71,7 +71,7 @@
 /*
  * Test IRadio.acknowledgeLastIncomingGsmSms() for the response returned.
  */
-TEST_F(RadioHidlTest, acknowledgeLastIncomingGsmSms) {
+TEST_P(RadioHidlTest, acknowledgeLastIncomingGsmSms) {
     serial = GetRandomSerialNumber();
     bool success = true;
 
@@ -92,7 +92,7 @@
 /*
  * Test IRadio.acknowledgeIncomingGsmSmsWithPdu() for the response returned.
  */
-TEST_F(RadioHidlTest, acknowledgeIncomingGsmSmsWithPdu) {
+TEST_P(RadioHidlTest, acknowledgeIncomingGsmSmsWithPdu) {
     serial = GetRandomSerialNumber();
     bool success = true;
     std::string ackPdu = "";
@@ -111,7 +111,7 @@
 /*
  * Test IRadio.sendCdmaSms() for the response returned.
  */
-TEST_F(RadioHidlTest, sendCdmaSms) {
+TEST_P(RadioHidlTest, sendCdmaSms) {
     serial = GetRandomSerialNumber();
 
     // Create a CdmaSmsAddress
@@ -155,7 +155,7 @@
 /*
  * Test IRadio.acknowledgeLastIncomingCdmaSms() for the response returned.
  */
-TEST_F(RadioHidlTest, acknowledgeLastIncomingCdmaSms) {
+TEST_P(RadioHidlTest, acknowledgeLastIncomingCdmaSms) {
     serial = GetRandomSerialNumber();
 
     // Create a CdmaSmsAck
@@ -179,7 +179,7 @@
 /*
  * Test IRadio.sendImsSms() for the response returned.
  */
-TEST_F(RadioHidlTest, sendImsSms) {
+TEST_P(RadioHidlTest, sendImsSms) {
     serial = GetRandomSerialNumber();
 
     // Create a CdmaSmsAddress
@@ -229,7 +229,7 @@
 /*
  * Test IRadio.getSmscAddress() for the response returned.
  */
-TEST_F(RadioHidlTest, getSmscAddress) {
+TEST_P(RadioHidlTest, getSmscAddress) {
     serial = GetRandomSerialNumber();
 
     radio->getSmscAddress(serial);
@@ -249,7 +249,7 @@
 /*
  * Test IRadio.setSmscAddress() for the response returned.
  */
-TEST_F(RadioHidlTest, setSmscAddress) {
+TEST_P(RadioHidlTest, setSmscAddress) {
     serial = GetRandomSerialNumber();
     hidl_string address = hidl_string("smscAddress");
 
@@ -270,7 +270,7 @@
 /*
  * Test IRadio.writeSmsToSim() for the response returned.
  */
-TEST_F(RadioHidlTest, writeSmsToSim) {
+TEST_P(RadioHidlTest, writeSmsToSim) {
     serial = GetRandomSerialNumber();
     SmsWriteArgs smsWriteArgs;
     smsWriteArgs.status = SmsWriteArgsStatus::REC_UNREAD;
@@ -296,7 +296,7 @@
 /*
  * Test IRadio.deleteSmsOnSim() for the response returned.
  */
-TEST_F(RadioHidlTest, deleteSmsOnSim) {
+TEST_P(RadioHidlTest, deleteSmsOnSim) {
     serial = GetRandomSerialNumber();
     int index = 1;
 
@@ -319,7 +319,7 @@
 /*
  * Test IRadio.writeSmsToRuim() for the response returned.
  */
-TEST_F(RadioHidlTest, writeSmsToRuim) {
+TEST_P(RadioHidlTest, writeSmsToRuim) {
     serial = GetRandomSerialNumber();
 
     // Create a CdmaSmsAddress
@@ -370,7 +370,7 @@
 /*
  * Test IRadio.deleteSmsOnRuim() for the response returned.
  */
-TEST_F(RadioHidlTest, deleteSmsOnRuim) {
+TEST_P(RadioHidlTest, deleteSmsOnRuim) {
     serial = GetRandomSerialNumber();
     int index = 1;
 
@@ -421,7 +421,7 @@
 /*
  * Test IRadio.reportSmsMemoryStatus() for the response returned.
  */
-TEST_F(RadioHidlTest, reportSmsMemoryStatus) {
+TEST_P(RadioHidlTest, reportSmsMemoryStatus) {
     serial = GetRandomSerialNumber();
     bool available = true;
 
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp b/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp
index a3b5029..1170111 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp
@@ -21,7 +21,7 @@
 /*
  * Test IRadio.sendEnvelope() for the response returned.
  */
-TEST_F(RadioHidlTest, sendEnvelope) {
+TEST_P(RadioHidlTest, sendEnvelope) {
     serial = GetRandomSerialNumber();
 
     // Test with sending empty string
@@ -44,7 +44,7 @@
 /*
  * Test IRadio.sendTerminalResponseToSim() for the response returned.
  */
-TEST_F(RadioHidlTest, sendTerminalResponseToSim) {
+TEST_P(RadioHidlTest, sendTerminalResponseToSim) {
     serial = GetRandomSerialNumber();
 
     // Test with sending empty string
@@ -67,7 +67,7 @@
 /*
  * Test IRadio.handleStkCallSetupRequestFromSim() for the response returned.
  */
-TEST_F(RadioHidlTest, handleStkCallSetupRequestFromSim) {
+TEST_P(RadioHidlTest, handleStkCallSetupRequestFromSim) {
     serial = GetRandomSerialNumber();
     bool accept = false;
 
@@ -88,7 +88,7 @@
 /*
  * Test IRadio.reportStkServiceIsRunning() for the response returned.
  */
-TEST_F(RadioHidlTest, reportStkServiceIsRunning) {
+TEST_P(RadioHidlTest, reportStkServiceIsRunning) {
     serial = GetRandomSerialNumber();
 
     radio->reportStkServiceIsRunning(serial);
@@ -107,7 +107,7 @@
  * Test IRadio.sendEnvelopeWithStatus() for the response returned with empty
  * string.
  */
-TEST_F(RadioHidlTest, sendEnvelopeWithStatus) {
+TEST_P(RadioHidlTest, sendEnvelopeWithStatus) {
     serial = GetRandomSerialNumber();
 
     // Test with sending empty string
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_test.cpp b/radio/1.0/vts/functional/radio_hidl_hal_test.cpp
index 96719d6..3c833c0 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_test.cpp
@@ -17,13 +17,10 @@
 #include <radio_hidl_hal_utils_v1_0.h>
 
 void RadioHidlTest::SetUp() {
-    radio = ::testing::VtsHalHidlTargetTestBase::getService<IRadio>(
-        RadioHidlEnvironment::Instance()->getServiceName<IRadio>(hidl_string(RADIO_SERVICE_NAME)));
+    radio = IRadio::getService(GetParam());
     if (radio == NULL) {
         sleep(60);
-        radio = ::testing::VtsHalHidlTargetTestBase::getService<IRadio>(
-            RadioHidlEnvironment::Instance()->getServiceName<IRadio>(
-                hidl_string(RADIO_SERVICE_NAME)));
+        radio = IRadio::getService(GetParam());
     }
     ASSERT_NE(nullptr, radio.get());
 
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_utils_v1_0.h b/radio/1.0/vts/functional/radio_hidl_hal_utils_v1_0.h
index 23bc434..8a551f7 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_utils_v1_0.h
+++ b/radio/1.0/vts/functional/radio_hidl_hal_utils_v1_0.h
@@ -16,8 +16,6 @@
 
 #include <android-base/logging.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
 #include <chrono>
 #include <condition_variable>
 #include <mutex>
@@ -26,6 +24,7 @@
 #include <android/hardware/radio/1.0/IRadioIndication.h>
 #include <android/hardware/radio/1.0/IRadioResponse.h>
 #include <android/hardware/radio/1.0/types.h>
+#include <gtest/gtest.h>
 
 #include "vts_test_util.h"
 
@@ -515,23 +514,9 @@
                             const ::android::hardware::hidl_string& reason);
 };
 
-// Test environment for Radio HIDL HAL.
-class RadioHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static RadioHidlEnvironment* Instance() {
-        static RadioHidlEnvironment* instance = new RadioHidlEnvironment;
-        return instance;
-    }
-    virtual void registerTestServices() override { registerTestService<IRadio>(); }
-
-   private:
-    RadioHidlEnvironment() {}
-};
-
 // The main test class for Radio HIDL.
-class RadioHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-   protected:
+class RadioHidlTest : public ::testing::TestWithParam<std::string> {
+  protected:
     std::mutex mtx;
     std::condition_variable cv;
     int count;
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp b/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
index 1fce470..a192a33 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
@@ -19,7 +19,7 @@
 /*
  * Test IRadio.getCurrentCalls() for the response returned.
  */
-TEST_F(RadioHidlTest, getCurrentCalls) {
+TEST_P(RadioHidlTest, getCurrentCalls) {
     serial = GetRandomSerialNumber();
 
     radio->getCurrentCalls(serial);
@@ -35,7 +35,7 @@
 /*
  * Test IRadio.dial() for the response returned.
  */
-TEST_F(RadioHidlTest, dial) {
+TEST_P(RadioHidlTest, dial) {
     serial = GetRandomSerialNumber();
 
     Dial dialInfo;
@@ -62,7 +62,7 @@
 /*
  * Test IRadio.hangup() for the response returned.
  */
-TEST_F(RadioHidlTest, hangup) {
+TEST_P(RadioHidlTest, hangup) {
     serial = GetRandomSerialNumber();
 
     radio->hangup(serial, 1);
@@ -81,7 +81,7 @@
 /*
  * Test IRadio.hangupWaitingOrBackground() for the response returned.
  */
-TEST_F(RadioHidlTest, hangupWaitingOrBackground) {
+TEST_P(RadioHidlTest, hangupWaitingOrBackground) {
     serial = GetRandomSerialNumber();
 
     radio->hangupWaitingOrBackground(serial);
@@ -99,7 +99,7 @@
 /*
  * Test IRadio.hangupForegroundResumeBackground() for the response returned.
  */
-TEST_F(RadioHidlTest, hangupForegroundResumeBackground) {
+TEST_P(RadioHidlTest, hangupForegroundResumeBackground) {
     serial = GetRandomSerialNumber();
 
     radio->hangupForegroundResumeBackground(serial);
@@ -117,7 +117,7 @@
 /*
  * Test IRadio.switchWaitingOrHoldingAndActive() for the response returned.
  */
-TEST_F(RadioHidlTest, switchWaitingOrHoldingAndActive) {
+TEST_P(RadioHidlTest, switchWaitingOrHoldingAndActive) {
     serial = GetRandomSerialNumber();
 
     radio->switchWaitingOrHoldingAndActive(serial);
@@ -135,7 +135,7 @@
 /*
  * Test IRadio.conference() for the response returned.
  */
-TEST_F(RadioHidlTest, conference) {
+TEST_P(RadioHidlTest, conference) {
     serial = GetRandomSerialNumber();
 
     radio->conference(serial);
@@ -153,7 +153,7 @@
 /*
  * Test IRadio.rejectCall() for the response returned.
  */
-TEST_F(RadioHidlTest, rejectCall) {
+TEST_P(RadioHidlTest, rejectCall) {
     serial = GetRandomSerialNumber();
 
     radio->rejectCall(serial);
@@ -171,7 +171,7 @@
 /*
  * Test IRadio.getLastCallFailCause() for the response returned.
  */
-TEST_F(RadioHidlTest, getLastCallFailCause) {
+TEST_P(RadioHidlTest, getLastCallFailCause) {
     serial = GetRandomSerialNumber();
 
     radio->getLastCallFailCause(serial);
@@ -188,7 +188,7 @@
 /*
  * Test IRadio.sendUssd() for the response returned.
  */
-TEST_F(RadioHidlTest, sendUssd) {
+TEST_P(RadioHidlTest, sendUssd) {
     serial = GetRandomSerialNumber();
     radio->sendUssd(serial, hidl_string("test"));
     EXPECT_EQ(std::cv_status::no_timeout, wait());
@@ -206,7 +206,7 @@
 /*
  * Test IRadio.cancelPendingUssd() for the response returned.
  */
-TEST_F(RadioHidlTest, cancelPendingUssd) {
+TEST_P(RadioHidlTest, cancelPendingUssd) {
     serial = GetRandomSerialNumber();
 
     radio->cancelPendingUssd(serial);
@@ -225,7 +225,7 @@
 /*
  * Test IRadio.getCallForwardStatus() for the response returned.
  */
-TEST_F(RadioHidlTest, getCallForwardStatus) {
+TEST_P(RadioHidlTest, getCallForwardStatus) {
     serial = GetRandomSerialNumber();
     CallForwardInfo callInfo;
     memset(&callInfo, 0, sizeof(callInfo));
@@ -247,7 +247,7 @@
 /*
  * Test IRadio.setCallForward() for the response returned.
  */
-TEST_F(RadioHidlTest, setCallForward) {
+TEST_P(RadioHidlTest, setCallForward) {
     serial = GetRandomSerialNumber();
     CallForwardInfo callInfo;
     memset(&callInfo, 0, sizeof(callInfo));
@@ -269,7 +269,7 @@
 /*
  * Test IRadio.getCallWaiting() for the response returned.
  */
-TEST_F(RadioHidlTest, getCallWaiting) {
+TEST_P(RadioHidlTest, getCallWaiting) {
     serial = GetRandomSerialNumber();
 
     radio->getCallWaiting(serial, 1);
@@ -288,7 +288,7 @@
 /*
  * Test IRadio.setCallWaiting() for the response returned.
  */
-TEST_F(RadioHidlTest, setCallWaiting) {
+TEST_P(RadioHidlTest, setCallWaiting) {
     serial = GetRandomSerialNumber();
 
     radio->setCallWaiting(serial, true, 1);
@@ -307,7 +307,7 @@
 /*
  * Test IRadio.acceptCall() for the response returned.
  */
-TEST_F(RadioHidlTest, acceptCall) {
+TEST_P(RadioHidlTest, acceptCall) {
     serial = GetRandomSerialNumber();
 
     radio->acceptCall(serial);
@@ -325,7 +325,7 @@
 /*
  * Test IRadio.separateConnection() for the response returned.
  */
-TEST_F(RadioHidlTest, separateConnection) {
+TEST_P(RadioHidlTest, separateConnection) {
     serial = GetRandomSerialNumber();
 
     radio->separateConnection(serial, 1);
@@ -344,7 +344,7 @@
 /*
  * Test IRadio.explicitCallTransfer() for the response returned.
  */
-TEST_F(RadioHidlTest, explicitCallTransfer) {
+TEST_P(RadioHidlTest, explicitCallTransfer) {
     serial = GetRandomSerialNumber();
 
     radio->explicitCallTransfer(serial);
@@ -362,7 +362,7 @@
 /*
  * Test IRadio.sendCDMAFeatureCode() for the response returned.
  */
-TEST_F(RadioHidlTest, sendCDMAFeatureCode) {
+TEST_P(RadioHidlTest, sendCDMAFeatureCode) {
     serial = GetRandomSerialNumber();
 
     radio->sendCDMAFeatureCode(serial, hidl_string());
@@ -382,7 +382,7 @@
 /*
  * Test IRadio.sendDtmf() for the response returned.
  */
-TEST_F(RadioHidlTest, sendDtmf) {
+TEST_P(RadioHidlTest, sendDtmf) {
     serial = GetRandomSerialNumber();
 
     radio->sendDtmf(serial, "1");
@@ -402,7 +402,7 @@
 /*
  * Test IRadio.startDtmf() for the response returned.
  */
-TEST_F(RadioHidlTest, startDtmf) {
+TEST_P(RadioHidlTest, startDtmf) {
     serial = GetRandomSerialNumber();
 
     radio->startDtmf(serial, "1");
@@ -422,7 +422,7 @@
 /*
  * Test IRadio.stopDtmf() for the response returned.
  */
-TEST_F(RadioHidlTest, stopDtmf) {
+TEST_P(RadioHidlTest, stopDtmf) {
     serial = GetRandomSerialNumber();
 
     radio->stopDtmf(serial);
@@ -441,7 +441,7 @@
 /*
  * Test IRadio.setMute() for the response returned.
  */
-TEST_F(RadioHidlTest, setMute) {
+TEST_P(RadioHidlTest, setMute) {
     serial = GetRandomSerialNumber();
 
     radio->setMute(serial, true);
@@ -459,7 +459,7 @@
 /*
  * Test IRadio.getMute() for the response returned.
  */
-TEST_F(RadioHidlTest, getMute) {
+TEST_P(RadioHidlTest, getMute) {
     serial = GetRandomSerialNumber();
 
     radio->getMute(serial);
@@ -475,7 +475,7 @@
 /*
  * Test IRadio.sendBurstDtmf() for the response returned.
  */
-TEST_F(RadioHidlTest, sendBurstDtmf) {
+TEST_P(RadioHidlTest, sendBurstDtmf) {
     serial = GetRandomSerialNumber();
 
     radio->sendBurstDtmf(serial, "1", 0, 0);
diff --git a/radio/1.0/vts/functional/sap_hidl_hal_api.cpp b/radio/1.0/vts/functional/sap_hidl_hal_api.cpp
index 1d79ff6..6bd2c88 100644
--- a/radio/1.0/vts/functional/sap_hidl_hal_api.cpp
+++ b/radio/1.0/vts/functional/sap_hidl_hal_api.cpp
@@ -19,7 +19,7 @@
 /*
  * Test ISap.connectReq() for the response returned.
  */
-TEST_F(SapHidlTest, connectReq) {
+TEST_P(SapHidlTest, connectReq) {
     token = GetRandomSerialNumber();
     int32_t maxMsgSize = 100;
 
@@ -35,7 +35,7 @@
 /*
  * Test IRadio.disconnectReq() for the response returned
  */
-TEST_F(SapHidlTest, disconnectReq) {
+TEST_P(SapHidlTest, disconnectReq) {
     token = GetRandomSerialNumber();
 
     sap->disconnectReq(token);
@@ -46,7 +46,7 @@
 /*
  * Test IRadio.apduReq() for the response returned.
  */
-TEST_F(SapHidlTest, apduReq) {
+TEST_P(SapHidlTest, apduReq) {
     token = GetRandomSerialNumber();
     SapApduType sapApduType = SapApduType::APDU;
     android::hardware::hidl_vec<uint8_t> command = {};
@@ -64,7 +64,7 @@
 /*
  * Test IRadio.transferAtrReq() for the response returned.
  */
-TEST_F(SapHidlTest, transferAtrReq) {
+TEST_P(SapHidlTest, transferAtrReq) {
     token = GetRandomSerialNumber();
 
     sap->transferAtrReq(token);
@@ -80,7 +80,7 @@
 /*
  * Test IRadio.powerReq() for the response returned.
  */
-TEST_F(SapHidlTest, powerReq) {
+TEST_P(SapHidlTest, powerReq) {
     token = GetRandomSerialNumber();
     bool state = true;
 
@@ -97,7 +97,7 @@
 /*
  * Test IRadio.resetSimReq() for the response returned.
  */
-TEST_F(SapHidlTest, resetSimReq) {
+TEST_P(SapHidlTest, resetSimReq) {
     token = GetRandomSerialNumber();
 
     sap->resetSimReq(token);
@@ -113,7 +113,7 @@
 /*
  * Test IRadio.transferCardReaderStatusReq() for the response returned.
  */
-TEST_F(SapHidlTest, transferCardReaderStatusReq) {
+TEST_P(SapHidlTest, transferCardReaderStatusReq) {
     token = GetRandomSerialNumber();
 
     sap->transferCardReaderStatusReq(token);
@@ -127,7 +127,7 @@
 /*
  * Test IRadio.setTransferProtocolReq() for the response returned.
  */
-TEST_F(SapHidlTest, setTransferProtocolReq) {
+TEST_P(SapHidlTest, setTransferProtocolReq) {
     token = GetRandomSerialNumber();
     SapTransferProtocol sapTransferProtocol = SapTransferProtocol::T0;
 
diff --git a/radio/1.0/vts/functional/sap_hidl_hal_test.cpp b/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
index 65b344b..fe10587 100644
--- a/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
+++ b/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
@@ -17,8 +17,7 @@
 #include <sap_hidl_hal_utils.h>
 
 void SapHidlTest::SetUp() {
-    sap = ::testing::VtsHalHidlTargetTestBase::getService<ISap>(
-        SapHidlEnvironment::Instance()->getServiceName<ISap>(hidl_string(SAP_SERVICE_NAME)));
+    sap = ISap::getService(GetParam());
     ASSERT_NE(sap, nullptr);
 
     sapCb = new SapCallback(*this);
diff --git a/radio/1.0/vts/functional/sap_hidl_hal_utils.h b/radio/1.0/vts/functional/sap_hidl_hal_utils.h
index f432932..2fc9ae3 100644
--- a/radio/1.0/vts/functional/sap_hidl_hal_utils.h
+++ b/radio/1.0/vts/functional/sap_hidl_hal_utils.h
@@ -16,8 +16,6 @@
 
 #include <android-base/logging.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
 #include <chrono>
 #include <condition_variable>
 #include <mutex>
@@ -25,6 +23,7 @@
 #include <android/hardware/radio/1.0/ISap.h>
 #include <android/hardware/radio/1.0/ISapCallback.h>
 #include <android/hardware/radio/1.0/types.h>
+#include <gtest/gtest.h>
 
 #include "vts_test_util.h"
 
@@ -80,23 +79,9 @@
     Return<void> transferProtocolResponse(int32_t token, SapResultCode resultCode);
 };
 
-// Test environment for Sap HIDL HAL.
-class SapHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static SapHidlEnvironment* Instance() {
-        static SapHidlEnvironment* instance = new SapHidlEnvironment;
-        return instance;
-    }
-    virtual void registerTestServices() override { registerTestService<ISap>(); }
-
-   private:
-    SapHidlEnvironment() {}
-};
-
 // The main test class for Sap HIDL.
-class SapHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-   private:
+class SapHidlTest : public ::testing::TestWithParam<std::string> {
+  private:
     std::mutex mtx;
     std::condition_variable cv;
     int count;
diff --git a/radio/1.0/vts/functional/vts_hal_radio_target_test.xml b/radio/1.0/vts/functional/vts_hal_radio_target_test.xml
new file mode 100644
index 0000000..5e4a1cd
--- /dev/null
+++ b/radio/1.0/vts/functional/vts_hal_radio_target_test.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalRadioV1_0TargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.MultiSimPreparer" />
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="VtsHalRadioV1_0TargetTest->/data/local/tmp/VtsHalRadioV1_0TargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalRadioV1_0TargetTest" />
+    </test>
+</configuration>
diff --git a/radio/1.0/vts/functional/vts_hal_sap_target_test.xml b/radio/1.0/vts/functional/vts_hal_sap_target_test.xml
new file mode 100644
index 0000000..457d700
--- /dev/null
+++ b/radio/1.0/vts/functional/vts_hal_sap_target_test.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalSapV1_0TargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.MultiSimPreparer" />
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="VtsHalSapV1_0TargetTest->/data/local/tmp/VtsHalSapV1_0TargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalSapV1_0TargetTest" />
+    </test>
+</configuration>
diff --git a/radio/1.0/vts/functional/vts_test_util.h b/radio/1.0/vts/functional/vts_test_util.h
index 826f0de..05b47c9 100644
--- a/radio/1.0/vts/functional/vts_test_util.h
+++ b/radio/1.0/vts/functional/vts_test_util.h
@@ -16,9 +16,8 @@
 
 #include <android-base/logging.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-
 #include <android/hardware/radio/1.0/types.h>
+#include <gtest/gtest.h>
 
 using ::android::hardware::radio::V1_0::RadioError;
 using ::android::hardware::radio::V1_0::SapResultCode;
diff --git a/radio/1.1/vts/functional/Android.bp b/radio/1.1/vts/functional/Android.bp
index 5695c6b..58aa67e 100644
--- a/radio/1.1/vts/functional/Android.bp
+++ b/radio/1.1/vts/functional/Android.bp
@@ -30,5 +30,5 @@
     header_libs: [
         "radio.util.header@1.0",
     ],
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/radio/1.1/vts/functional/AndroidTest.xml b/radio/1.1/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..5badadd
--- /dev/null
+++ b/radio/1.1/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalRadioV1_1TargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.MultiSimPreparer" />
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="VtsHalRadioV1_1TargetTest->/data/local/tmp/VtsHalRadioV1_1TargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalRadioV1_1TargetTest" />
+    </test>
+</configuration>
diff --git a/radio/1.1/vts/functional/VtsHalRadioV1_1TargetTest.cpp b/radio/1.1/vts/functional/VtsHalRadioV1_1TargetTest.cpp
index 83564ee..98dbf62 100644
--- a/radio/1.1/vts/functional/VtsHalRadioV1_1TargetTest.cpp
+++ b/radio/1.1/vts/functional/VtsHalRadioV1_1TargetTest.cpp
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 #include <radio_hidl_hal_utils_v1_1.h>
 
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(RadioHidlEnvironment::Instance());
-    ::testing::InitGoogleTest(&argc, argv);
-    RadioHidlEnvironment::Instance()->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    LOG(INFO) << "Test result = " << status;
-    return status;
-}
+INSTANTIATE_TEST_SUITE_P(PerInstance, RadioHidlTest_v1_1,
+                         testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+                                 ::android::hardware::radio::V1_1::IRadio::descriptor)),
+                         android::hardware::PrintInstanceNameToString);
diff --git a/radio/1.1/vts/functional/radio_hidl_hal_api.cpp b/radio/1.1/vts/functional/radio_hidl_hal_api.cpp
index 33347c5..75abbbf 100644
--- a/radio/1.1/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.1/vts/functional/radio_hidl_hal_api.cpp
@@ -20,7 +20,7 @@
 /*
  * Test IRadio.setSimCardPower() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_1, setSimCardPower_1_1) {
+TEST_P(RadioHidlTest_v1_1, setSimCardPower_1_1) {
     /* Record the sim card state for the testing environment */
     CardState cardStateForTest = cardStatus.cardState;
 
@@ -81,7 +81,7 @@
 /*
  * Test IRadio.startNetworkScan() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_1, startNetworkScan) {
+TEST_P(RadioHidlTest_v1_1, startNetworkScan) {
     serial = GetRandomSerialNumber();
 
     NetworkScanRequest request;
@@ -115,7 +115,7 @@
 /*
  * Test IRadio.startNetworkScan() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_1, startNetworkScan_InvalidArgument) {
+TEST_P(RadioHidlTest_v1_1, startNetworkScan_InvalidArgument) {
     serial = GetRandomSerialNumber();
 
     NetworkScanRequest request;
@@ -139,7 +139,7 @@
 /*
  * Test IRadio.stopNetworkScan() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_1, stopNetworkScan) {
+TEST_P(RadioHidlTest_v1_1, stopNetworkScan) {
     serial = GetRandomSerialNumber();
 
     radio_v1_1->stopNetworkScan(serial);
@@ -158,7 +158,7 @@
 /*
  * Test IRadio.setCarrierInfoForImsiEncryption() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_1, setCarrierInfoForImsiEncryption) {
+TEST_P(RadioHidlTest_v1_1, setCarrierInfoForImsiEncryption) {
     serial = GetRandomSerialNumber();
     ImsiEncryptionInfo imsiInfo;
     imsiInfo.mcc = "310";
@@ -181,7 +181,7 @@
 /*
  * Test IRadio.startKeepalive() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_1, startKeepalive) {
+TEST_P(RadioHidlTest_v1_1, startKeepalive) {
     std::vector<KeepaliveRequest> requests = {
         {
             // Invalid IPv4 source address
@@ -279,7 +279,7 @@
 /*
  * Test IRadio.stopKeepalive() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_1, stopKeepalive) {
+TEST_P(RadioHidlTest_v1_1, stopKeepalive) {
     serial = GetRandomSerialNumber();
 
     radio_v1_1->stopKeepalive(serial, 0xBAD);
diff --git a/radio/1.1/vts/functional/radio_hidl_hal_test.cpp b/radio/1.1/vts/functional/radio_hidl_hal_test.cpp
index 2f657b4..020168e 100644
--- a/radio/1.1/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.1/vts/functional/radio_hidl_hal_test.cpp
@@ -17,18 +17,10 @@
 #include <radio_hidl_hal_utils_v1_1.h>
 
 void RadioHidlTest_v1_1::SetUp() {
-    radio_v1_1 =
-        ::testing::VtsHalHidlTargetTestBase::getService<::android::hardware::radio::V1_1::IRadio>(
-            RadioHidlEnvironment::Instance()
-                ->getServiceName<::android::hardware::radio::V1_1::IRadio>(
-                    hidl_string(RADIO_SERVICE_NAME)));
+    radio_v1_1 = ::android::hardware::radio::V1_1::IRadio::getService(GetParam());
     if (radio_v1_1 == NULL) {
         sleep(60);
-        radio_v1_1 = ::testing::VtsHalHidlTargetTestBase::getService<
-            ::android::hardware::radio::V1_1::IRadio>(
-            RadioHidlEnvironment::Instance()
-                ->getServiceName<::android::hardware::radio::V1_1::IRadio>(
-                    hidl_string(RADIO_SERVICE_NAME)));
+        radio_v1_1 = ::android::hardware::radio::V1_1::IRadio::getService(GetParam());
     }
     ASSERT_NE(nullptr, radio_v1_1.get());
 
diff --git a/radio/1.1/vts/functional/radio_hidl_hal_utils_v1_1.h b/radio/1.1/vts/functional/radio_hidl_hal_utils_v1_1.h
index 925f4fc..b81ee13 100644
--- a/radio/1.1/vts/functional/radio_hidl_hal_utils_v1_1.h
+++ b/radio/1.1/vts/functional/radio_hidl_hal_utils_v1_1.h
@@ -16,8 +16,7 @@
 
 #include <android-base/logging.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
+#include <log/log.h>
 #include <chrono>
 #include <condition_variable>
 #include <mutex>
@@ -26,6 +25,7 @@
 #include <android/hardware/radio/1.1/IRadioIndication.h>
 #include <android/hardware/radio/1.1/IRadioResponse.h>
 #include <android/hardware/radio/1.1/types.h>
+#include <gtest/gtest.h>
 
 #include "vts_test_util.h"
 
@@ -535,25 +535,9 @@
                             const ::android::hardware::hidl_string& reason);
 };
 
-// Test environment for Radio HIDL HAL.
-class RadioHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static RadioHidlEnvironment* Instance() {
-        static RadioHidlEnvironment* instance = new RadioHidlEnvironment;
-        return instance;
-    }
-    virtual void registerTestServices() override {
-        registerTestService<::android::hardware::radio::V1_1::IRadio>();
-    }
-
-   private:
-    RadioHidlEnvironment() {}
-};
-
 // The main test class for Radio HIDL.
-class RadioHidlTest_v1_1 : public ::testing::VtsHalHidlTargetTestBase {
-   protected:
+class RadioHidlTest_v1_1 : public ::testing::TestWithParam<std::string> {
+  protected:
     std::mutex mtx;
     std::condition_variable cv;
     int count;
diff --git a/radio/1.2/vts/functional/Android.bp b/radio/1.2/vts/functional/Android.bp
index c5838a8..f7189a8 100644
--- a/radio/1.2/vts/functional/Android.bp
+++ b/radio/1.2/vts/functional/Android.bp
@@ -34,5 +34,5 @@
         "android.hardware.radio.config@1.1",
     ],
     header_libs: ["radio.util.header@1.0"],
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/radio/1.2/vts/functional/AndroidTest.xml b/radio/1.2/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..5d92248
--- /dev/null
+++ b/radio/1.2/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalRadioV1_2TargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.MultiSimPreparer" />
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="VtsHalRadioV1_2TargetTest->/data/local/tmp/VtsHalRadioV1_2TargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalRadioV1_2TargetTest" />
+    </test>
+</configuration>
diff --git a/radio/1.2/vts/functional/VtsHalRadioV1_2TargetTest.cpp b/radio/1.2/vts/functional/VtsHalRadioV1_2TargetTest.cpp
index c1a2f3d..400e394 100644
--- a/radio/1.2/vts/functional/VtsHalRadioV1_2TargetTest.cpp
+++ b/radio/1.2/vts/functional/VtsHalRadioV1_2TargetTest.cpp
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 #include <radio_hidl_hal_utils_v1_2.h>
 
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(RadioHidlEnvironment::Instance());
-    ::testing::InitGoogleTest(&argc, argv);
-    RadioHidlEnvironment::Instance()->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    LOG(INFO) << "Test result = " << status;
-    return status;
-}
+INSTANTIATE_TEST_SUITE_P(PerInstance, RadioHidlTest_v1_2,
+                         testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+                                 ::android::hardware::radio::V1_2::IRadio::descriptor)),
+                         android::hardware::PrintInstanceNameToString);
diff --git a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
index a98f22a..7464307 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
@@ -31,7 +31,7 @@
 /*
  * Test IRadio.startNetworkScan() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_2, startNetworkScan) {
+TEST_P(RadioHidlTest_v1_2, startNetworkScan) {
     serial = GetRandomSerialNumber();
 
     if (radioConfig != NULL && DDS_LOGICAL_SLOT_INDEX != logicalSlotId) {
@@ -82,7 +82,7 @@
 /*
  * Test IRadio.startNetworkScan() with invalid specifier.
  */
-TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidArgument) {
+TEST_P(RadioHidlTest_v1_2, startNetworkScan_InvalidArgument) {
     serial = GetRandomSerialNumber();
 
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {.type = ScanType::ONE_SHOT,
@@ -109,7 +109,7 @@
 /*
  * Test IRadio.startNetworkScan() with invalid interval (lower boundary).
  */
-TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidInterval1) {
+TEST_P(RadioHidlTest_v1_2, startNetworkScan_InvalidInterval1) {
     serial = GetRandomSerialNumber();
 
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
@@ -141,7 +141,7 @@
 /*
  * Test IRadio.startNetworkScan() with invalid interval (upper boundary).
  */
-TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidInterval2) {
+TEST_P(RadioHidlTest_v1_2, startNetworkScan_InvalidInterval2) {
     serial = GetRandomSerialNumber();
 
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
@@ -173,7 +173,7 @@
 /*
  * Test IRadio.startNetworkScan() with invalid max search time (lower boundary).
  */
-TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidMaxSearchTime1) {
+TEST_P(RadioHidlTest_v1_2, startNetworkScan_InvalidMaxSearchTime1) {
     serial = GetRandomSerialNumber();
 
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
@@ -205,7 +205,7 @@
 /*
  * Test IRadio.startNetworkScan() with invalid max search time (upper boundary).
  */
-TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidMaxSearchTime2) {
+TEST_P(RadioHidlTest_v1_2, startNetworkScan_InvalidMaxSearchTime2) {
     serial = GetRandomSerialNumber();
 
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
@@ -237,7 +237,7 @@
 /*
  * Test IRadio.startNetworkScan() with invalid periodicity (lower boundary).
  */
-TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidPeriodicity1) {
+TEST_P(RadioHidlTest_v1_2, startNetworkScan_InvalidPeriodicity1) {
     serial = GetRandomSerialNumber();
 
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
@@ -269,7 +269,7 @@
 /*
  * Test IRadio.startNetworkScan() with invalid periodicity (upper boundary).
  */
-TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidPeriodicity2) {
+TEST_P(RadioHidlTest_v1_2, startNetworkScan_InvalidPeriodicity2) {
     serial = GetRandomSerialNumber();
 
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
@@ -301,7 +301,7 @@
 /*
  * Test IRadio.startNetworkScan() with valid periodicity
  */
-TEST_F(RadioHidlTest_v1_2, startNetworkScan_GoodRequest1) {
+TEST_P(RadioHidlTest_v1_2, startNetworkScan_GoodRequest1) {
     serial = GetRandomSerialNumber();
 
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
@@ -335,7 +335,7 @@
 /*
  * Test IRadio.startNetworkScan() with valid periodicity and plmns
  */
-TEST_F(RadioHidlTest_v1_2, startNetworkScan_GoodRequest2) {
+TEST_P(RadioHidlTest_v1_2, startNetworkScan_GoodRequest2) {
     serial = GetRandomSerialNumber();
 
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
@@ -370,7 +370,7 @@
 /*
  * Test IRadio.setIndicationFilter_1_2()
  */
-TEST_F(RadioHidlTest_v1_2, setIndicationFilter_1_2) {
+TEST_P(RadioHidlTest_v1_2, setIndicationFilter_1_2) {
     serial = GetRandomSerialNumber();
 
     Return<void> res = radio_v1_2->setIndicationFilter_1_2(
@@ -388,7 +388,7 @@
 /*
  * Test IRadio.setSignalStrengthReportingCriteria() with invalid hysteresisDb
  */
-TEST_F(RadioHidlTest_v1_2, setSignalStrengthReportingCriteria_invalidHysteresisDb) {
+TEST_P(RadioHidlTest_v1_2, setSignalStrengthReportingCriteria_invalidHysteresisDb) {
     serial = GetRandomSerialNumber();
 
     Return<void> res = radio_v1_2->setSignalStrengthReportingCriteria(
@@ -408,7 +408,7 @@
 /*
  * Test IRadio.setSignalStrengthReportingCriteria() with empty parameters
  */
-TEST_F(RadioHidlTest_v1_2, setSignalStrengthReportingCriteria_EmptyParams) {
+TEST_P(RadioHidlTest_v1_2, setSignalStrengthReportingCriteria_EmptyParams) {
     serial = GetRandomSerialNumber();
 
     Return<void> res = radio_v1_2->setSignalStrengthReportingCriteria(
@@ -426,7 +426,7 @@
 /*
  * Test IRadio.setSignalStrengthReportingCriteria() for GERAN
  */
-TEST_F(RadioHidlTest_v1_2, setSignalStrengthReportingCriteria_Geran) {
+TEST_P(RadioHidlTest_v1_2, setSignalStrengthReportingCriteria_Geran) {
     serial = GetRandomSerialNumber();
 
     Return<void> res = radio_v1_2->setSignalStrengthReportingCriteria(
@@ -445,7 +445,7 @@
 /*
  * Test IRadio.setSignalStrengthReportingCriteria() for UTRAN
  */
-TEST_F(RadioHidlTest_v1_2, setSignalStrengthReportingCriteria_Utran) {
+TEST_P(RadioHidlTest_v1_2, setSignalStrengthReportingCriteria_Utran) {
     serial = GetRandomSerialNumber();
 
     Return<void> res = radio_v1_2->setSignalStrengthReportingCriteria(
@@ -464,7 +464,7 @@
 /*
  * Test IRadio.setSignalStrengthReportingCriteria() for EUTRAN
  */
-TEST_F(RadioHidlTest_v1_2, setSignalStrengthReportingCriteria_Eutran) {
+TEST_P(RadioHidlTest_v1_2, setSignalStrengthReportingCriteria_Eutran) {
     serial = GetRandomSerialNumber();
 
     Return<void> res = radio_v1_2->setSignalStrengthReportingCriteria(
@@ -483,7 +483,7 @@
 /*
  * Test IRadio.setSignalStrengthReportingCriteria() for CDMA2000
  */
-TEST_F(RadioHidlTest_v1_2, setSignalStrengthReportingCriteria_Cdma2000) {
+TEST_P(RadioHidlTest_v1_2, setSignalStrengthReportingCriteria_Cdma2000) {
     serial = GetRandomSerialNumber();
 
     Return<void> res = radio_v1_2->setSignalStrengthReportingCriteria(
@@ -502,7 +502,7 @@
 /*
  * Test IRadio.setLinkCapacityReportingCriteria() invalid hysteresisDlKbps
  */
-TEST_F(RadioHidlTest_v1_2, setLinkCapacityReportingCriteria_invalidHysteresisDlKbps) {
+TEST_P(RadioHidlTest_v1_2, setLinkCapacityReportingCriteria_invalidHysteresisDlKbps) {
     serial = GetRandomSerialNumber();
 
     Return<void> res = radio_v1_2->setLinkCapacityReportingCriteria(
@@ -527,7 +527,7 @@
 /*
  * Test IRadio.setLinkCapacityReportingCriteria() invalid hysteresisUlKbps
  */
-TEST_F(RadioHidlTest_v1_2, setLinkCapacityReportingCriteria_invalidHysteresisUlKbps) {
+TEST_P(RadioHidlTest_v1_2, setLinkCapacityReportingCriteria_invalidHysteresisUlKbps) {
     serial = GetRandomSerialNumber();
 
     Return<void> res = radio_v1_2->setLinkCapacityReportingCriteria(
@@ -552,7 +552,7 @@
 /*
  * Test IRadio.setLinkCapacityReportingCriteria() empty params
  */
-TEST_F(RadioHidlTest_v1_2, setLinkCapacityReportingCriteria_emptyParams) {
+TEST_P(RadioHidlTest_v1_2, setLinkCapacityReportingCriteria_emptyParams) {
     serial = GetRandomSerialNumber();
 
     Return<void> res = radio_v1_2->setLinkCapacityReportingCriteria(
@@ -573,7 +573,7 @@
 /*
  * Test IRadio.setLinkCapacityReportingCriteria() GERAN
  */
-TEST_F(RadioHidlTest_v1_2, setLinkCapacityReportingCriteria_Geran) {
+TEST_P(RadioHidlTest_v1_2, setLinkCapacityReportingCriteria_Geran) {
     serial = GetRandomSerialNumber();
 
     Return<void> res = radio_v1_2->setLinkCapacityReportingCriteria(
@@ -595,7 +595,7 @@
 /*
  * Test IRadio.setupDataCall_1_2() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_2, setupDataCall_1_2) {
+TEST_P(RadioHidlTest_v1_2, setupDataCall_1_2) {
     serial = GetRandomSerialNumber();
 
     ::android::hardware::radio::V1_2::AccessNetwork accessNetwork =
@@ -655,7 +655,7 @@
 /*
  * Test IRadio.deactivateDataCall_1_2() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_2, deactivateDataCall_1_2) {
+TEST_P(RadioHidlTest_v1_2, deactivateDataCall_1_2) {
     serial = GetRandomSerialNumber();
     int cid = 1;
     ::android::hardware::radio::V1_2::DataRequestReason reason =
@@ -686,7 +686,7 @@
 /*
  * Test IRadio.getCellInfoList() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_2, getCellInfoList_1_2) {
+TEST_P(RadioHidlTest_v1_2, getCellInfoList_1_2) {
     serial = GetRandomSerialNumber();
 
     Return<void> res = radio_v1_2->getCellInfoList(serial);
@@ -704,7 +704,7 @@
 /*
  * Test IRadio.getVoiceRegistrationState() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_2, getVoiceRegistrationState) {
+TEST_P(RadioHidlTest_v1_2, getVoiceRegistrationState) {
     serial = GetRandomSerialNumber();
 
     Return<void> res = radio_v1_2->getVoiceRegistrationState(serial);
@@ -722,7 +722,7 @@
 /*
  * Test IRadio.getDataRegistrationState() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_2, getDataRegistrationState) {
+TEST_P(RadioHidlTest_v1_2, getDataRegistrationState) {
     serial = GetRandomSerialNumber();
 
     Return<void> res = radio_v1_2->getDataRegistrationState(serial);
@@ -797,7 +797,7 @@
 /*
  * Test IRadio.getAvailableBandModes() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_2, getAvailableBandModes) {
+TEST_P(RadioHidlTest_v1_2, getAvailableBandModes) {
     serial = GetRandomSerialNumber();
 
     Return<void> res = radio_v1_2->getAvailableBandModes(serial);
diff --git a/radio/1.2/vts/functional/radio_hidl_hal_test.cpp b/radio/1.2/vts/functional/radio_hidl_hal_test.cpp
index 21caddb..4845c7f 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.2/vts/functional/radio_hidl_hal_test.cpp
@@ -17,18 +17,10 @@
 #include <radio_hidl_hal_utils_v1_2.h>
 
 void RadioHidlTest_v1_2::SetUp() {
-    radio_v1_2 =
-        ::testing::VtsHalHidlTargetTestBase::getService<::android::hardware::radio::V1_2::IRadio>(
-            RadioHidlEnvironment::Instance()
-                ->getServiceName<::android::hardware::radio::V1_2::IRadio>(
-                    hidl_string(RADIO_SERVICE_NAME)));
+    radio_v1_2 = ::android::hardware::radio::V1_2::IRadio::getService(GetParam());
     if (radio_v1_2 == NULL) {
         sleep(60);
-        radio_v1_2 = ::testing::VtsHalHidlTargetTestBase::getService<
-            ::android::hardware::radio::V1_2::IRadio>(
-            RadioHidlEnvironment::Instance()
-                ->getServiceName<::android::hardware::radio::V1_2::IRadio>(
-                    hidl_string(RADIO_SERVICE_NAME)));
+        radio_v1_2 = ::android::hardware::radio::V1_2::IRadio::getService(GetParam());
     }
     ASSERT_NE(nullptr, radio_v1_2.get());
 
@@ -51,8 +43,7 @@
     /* Enforce Vts Testing with Sim Status Present only. */
     EXPECT_EQ(CardState::PRESENT, cardStatus.base.cardState);
 
-    radioConfig = ::testing::VtsHalHidlTargetTestBase::getService<
-            ::android::hardware::radio::config::V1_1::IRadioConfig>();
+    radioConfig = ::android::hardware::radio::config::V1_1::IRadioConfig::getService();
 
     /* Enforce Vts tesing with RadioConfig for network scan excemption. */
     // Some devices can only perform network scan on logical modem that currently used for packet
diff --git a/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h b/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h
index 2db1cac..479340c 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h
+++ b/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h
@@ -16,8 +16,7 @@
 
 #include <android-base/logging.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
+#include <log/log.h>
 #include <chrono>
 #include <condition_variable>
 #include <mutex>
@@ -30,6 +29,7 @@
 #include <android/hardware/radio/1.2/IRadioIndication.h>
 #include <android/hardware/radio/1.2/IRadioResponse.h>
 #include <android/hardware/radio/1.2/types.h>
+#include <gtest/gtest.h>
 
 #include "vts_test_util.h"
 
@@ -631,25 +631,9 @@
                             const ::android::hardware::hidl_string& reason);
 };
 
-// Test environment for Radio HIDL HAL.
-class RadioHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static RadioHidlEnvironment* Instance() {
-        static RadioHidlEnvironment* instance = new RadioHidlEnvironment;
-        return instance;
-    }
-    virtual void registerTestServices() override {
-        registerTestService<::android::hardware::radio::V1_2::IRadio>();
-    }
-
-   private:
-    RadioHidlEnvironment() {}
-};
-
 // The main test class for Radio HIDL.
-class RadioHidlTest_v1_2 : public ::testing::VtsHalHidlTargetTestBase {
-   protected:
+class RadioHidlTest_v1_2 : public ::testing::TestWithParam<std::string> {
+  protected:
     std::mutex mtx_;
     std::condition_variable cv_;
     int count_;
diff --git a/radio/1.3/vts/functional/Android.bp b/radio/1.3/vts/functional/Android.bp
index 67aff6e..2301732 100644
--- a/radio/1.3/vts/functional/Android.bp
+++ b/radio/1.3/vts/functional/Android.bp
@@ -32,5 +32,5 @@
         "android.hardware.radio@1.0",
     ],
     header_libs: ["radio.util.header@1.0"],
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/radio/1.3/vts/functional/AndroidTest.xml b/radio/1.3/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..c910047
--- /dev/null
+++ b/radio/1.3/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalRadioV1_3TargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.MultiSimPreparer" />
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="VtsHalRadioV1_3TargetTest->/data/local/tmp/VtsHalRadioV1_3TargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalRadioV1_3TargetTest" />
+    </test>
+</configuration>
diff --git a/radio/1.3/vts/functional/VtsHalRadioV1_3TargetTest.cpp b/radio/1.3/vts/functional/VtsHalRadioV1_3TargetTest.cpp
index 7d2623e..2622bbc 100644
--- a/radio/1.3/vts/functional/VtsHalRadioV1_3TargetTest.cpp
+++ b/radio/1.3/vts/functional/VtsHalRadioV1_3TargetTest.cpp
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 #include <radio_hidl_hal_utils_v1_3.h>
 
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(RadioHidlEnvironment::Instance());
-    ::testing::InitGoogleTest(&argc, argv);
-    RadioHidlEnvironment::Instance()->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    LOG(INFO) << "Test result = " << status;
-    return status;
-}
+INSTANTIATE_TEST_SUITE_P(PerInstance, RadioHidlTest_v1_3,
+                         testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+                                 ::android::hardware::radio::V1_3::IRadio::descriptor)),
+                         android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/radio/1.3/vts/functional/radio_hidl_hal_api.cpp b/radio/1.3/vts/functional/radio_hidl_hal_api.cpp
index 813dd13..4e48141 100644
--- a/radio/1.3/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.3/vts/functional/radio_hidl_hal_api.cpp
@@ -22,7 +22,7 @@
 /*
  * Test IRadio.enableMddem() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_3, enableModem) {
+TEST_P(RadioHidlTest_v1_3, enableModem) {
     serial = GetRandomSerialNumber();
 
     bool responseToggle = radioRsp_v1_3->enableModemResponseToggle;
@@ -61,7 +61,7 @@
 /*
  * Test IRadio.getModemStackStatus() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_3, getModemStackStatus) {
+TEST_P(RadioHidlTest_v1_3, getModemStackStatus) {
     serial = GetRandomSerialNumber();
 
     Return<void> res = radio_v1_3->getModemStackStatus(serial);
@@ -81,7 +81,7 @@
  *
  * This test is excluded from manifest, due to non-implementation in Q. Tracked by b/130254624.
  */
-TEST_F(RadioHidlTest_v1_3, setSystemSelectionChannels) {
+TEST_P(RadioHidlTest_v1_3, setSystemSelectionChannels) {
     serial = GetRandomSerialNumber();
 
     RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
diff --git a/radio/1.3/vts/functional/radio_hidl_hal_test.cpp b/radio/1.3/vts/functional/radio_hidl_hal_test.cpp
index a876b1a..4581350 100644
--- a/radio/1.3/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.3/vts/functional/radio_hidl_hal_test.cpp
@@ -17,18 +17,10 @@
 #include <radio_hidl_hal_utils_v1_3.h>
 
 void RadioHidlTest_v1_3::SetUp() {
-    radio_v1_3 = ::testing::VtsHalHidlTargetTestBase::getService<
-            ::android::hardware::radio::V1_3::IRadio>(
-            RadioHidlEnvironment::Instance()
-                    ->getServiceName<::android::hardware::radio::V1_3::IRadio>(
-                            hidl_string(RADIO_SERVICE_NAME)));
+    radio_v1_3 = ::android::hardware::radio::V1_3::IRadio::getService(GetParam());
     if (radio_v1_3 == NULL) {
         sleep(60);
-        radio_v1_3 = ::testing::VtsHalHidlTargetTestBase::getService<
-                ::android::hardware::radio::V1_3::IRadio>(
-                RadioHidlEnvironment::Instance()
-                        ->getServiceName<::android::hardware::radio::V1_3::IRadio>(
-                                hidl_string(RADIO_SERVICE_NAME)));
+        radio_v1_3 = ::android::hardware::radio::V1_3::IRadio::getService(GetParam());
     }
     ASSERT_NE(nullptr, radio_v1_3.get());
 
diff --git a/radio/1.3/vts/functional/radio_hidl_hal_utils_v1_3.h b/radio/1.3/vts/functional/radio_hidl_hal_utils_v1_3.h
index 1d03a99..893eac5 100644
--- a/radio/1.3/vts/functional/radio_hidl_hal_utils_v1_3.h
+++ b/radio/1.3/vts/functional/radio_hidl_hal_utils_v1_3.h
@@ -16,8 +16,7 @@
 
 #include <android-base/logging.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
+#include <log/log.h>
 #include <chrono>
 #include <condition_variable>
 #include <mutex>
@@ -609,25 +608,9 @@
                             const ::android::hardware::hidl_string& reason);
 };
 
-// Test environment for Radio HIDL HAL.
-class RadioHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static RadioHidlEnvironment* Instance() {
-        static RadioHidlEnvironment* instance = new RadioHidlEnvironment;
-        return instance;
-    }
-    virtual void registerTestServices() override {
-        registerTestService<::android::hardware::radio::V1_3::IRadio>();
-    }
-
-   private:
-    RadioHidlEnvironment() {}
-};
-
 // The main test class for Radio HIDL.
-class RadioHidlTest_v1_3 : public ::testing::VtsHalHidlTargetTestBase {
-   protected:
+class RadioHidlTest_v1_3 : public ::testing::TestWithParam<std::string> {
+  protected:
     std::mutex mtx_;
     std::condition_variable cv_;
     int count_;
diff --git a/radio/1.4/vts/functional/Android.bp b/radio/1.4/vts/functional/Android.bp
index 6827132..8284404 100644
--- a/radio/1.4/vts/functional/Android.bp
+++ b/radio/1.4/vts/functional/Android.bp
@@ -35,5 +35,5 @@
         "android.hardware.radio.config@1.1",
     ],
     header_libs: ["radio.util.header@1.0"],
-    test_suites: ["general-tests"]
+    test_suites: ["general-tests", "vts-core"]
 }
diff --git a/radio/1.4/vts/functional/AndroidTest.xml b/radio/1.4/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..c910047
--- /dev/null
+++ b/radio/1.4/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalRadioV1_3TargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.MultiSimPreparer" />
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="VtsHalRadioV1_3TargetTest->/data/local/tmp/VtsHalRadioV1_3TargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalRadioV1_3TargetTest" />
+    </test>
+</configuration>
diff --git a/radio/1.4/vts/functional/VtsHalRadioV1_4TargetTest.cpp b/radio/1.4/vts/functional/VtsHalRadioV1_4TargetTest.cpp
index d6330e6..23ec011 100644
--- a/radio/1.4/vts/functional/VtsHalRadioV1_4TargetTest.cpp
+++ b/radio/1.4/vts/functional/VtsHalRadioV1_4TargetTest.cpp
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 #include <radio_hidl_hal_utils_v1_4.h>
 
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(RadioHidlEnvironment::Instance());
-    ::testing::InitGoogleTest(&argc, argv);
-    RadioHidlEnvironment::Instance()->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    LOG(INFO) << "Test result = " << status;
-    return status;
-}
\ No newline at end of file
+INSTANTIATE_TEST_SUITE_P(PerInstance, RadioHidlTest_v1_4,
+                         testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+                                 ::android::hardware::radio::V1_4::IRadio::descriptor)),
+                         android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
index a4953d7..95136bb 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
@@ -21,7 +21,7 @@
 /*
  * Test IRadio.emergencyDial() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_4, emergencyDial) {
+TEST_P(RadioHidlTest_v1_4, emergencyDial) {
     serial = GetRandomSerialNumber();
 
     ::android::hardware::radio::V1_0::Dial dialInfo;
@@ -52,7 +52,7 @@
 /*
  * Test IRadio.emergencyDial() with specified service and its response returned.
  */
-TEST_F(RadioHidlTest_v1_4, emergencyDial_withServices) {
+TEST_P(RadioHidlTest_v1_4, emergencyDial_withServices) {
     serial = GetRandomSerialNumber();
 
     ::android::hardware::radio::V1_0::Dial dialInfo;
@@ -84,7 +84,7 @@
 /*
  * Test IRadio.emergencyDial() with known emergency call routing and its response returned.
  */
-TEST_F(RadioHidlTest_v1_4, emergencyDial_withEmergencyRouting) {
+TEST_P(RadioHidlTest_v1_4, emergencyDial_withEmergencyRouting) {
     serial = GetRandomSerialNumber();
 
     ::android::hardware::radio::V1_0::Dial dialInfo;
@@ -116,7 +116,7 @@
 /*
  * Test IRadio.getPreferredNetworkTypeBitmap() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_4, getPreferredNetworkTypeBitmap) {
+TEST_P(RadioHidlTest_v1_4, getPreferredNetworkTypeBitmap) {
     serial = GetRandomSerialNumber();
 
     Return<void> res = radio_v1_4->getPreferredNetworkTypeBitmap(serial);
@@ -130,7 +130,7 @@
     EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error);
 }
 
-TEST_F(RadioHidlTest_v1_4, setPreferredNetworkTypeBitmap) {
+TEST_P(RadioHidlTest_v1_4, setPreferredNetworkTypeBitmap) {
     serial = GetRandomSerialNumber();
     ::android::hardware::hidl_bitfield<::android::hardware::radio::V1_4::RadioAccessFamily>
             network_type_bitmap{};
@@ -175,7 +175,7 @@
  * REQUEST_NOT_SUPPORTED will be disallowed for all tests. Modems have "GSM" rat scan need to
  * support scanning requests combined with some parameters.
  */
-TEST_F(RadioHidlTest_v1_4, startNetworkScan) {
+TEST_P(RadioHidlTest_v1_4, startNetworkScan) {
     serial = GetRandomSerialNumber();
 
     RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
@@ -218,7 +218,7 @@
 /*
  * Test IRadio.startNetworkScan() with invalid specifier.
  */
-TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidArgument) {
+TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidArgument) {
     serial = GetRandomSerialNumber();
 
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {.type = ScanType::ONE_SHOT,
@@ -246,7 +246,7 @@
 /*
  * Test IRadio.startNetworkScan() with invalid interval (lower boundary).
  */
-TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidInterval1) {
+TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidInterval1) {
     serial = GetRandomSerialNumber();
 
     RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
@@ -283,7 +283,7 @@
 /*
  * Test IRadio.startNetworkScan() with invalid interval (upper boundary).
  */
-TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidInterval2) {
+TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidInterval2) {
     serial = GetRandomSerialNumber();
 
     RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
@@ -319,7 +319,7 @@
 /*
  * Test IRadio.startNetworkScan() with invalid max search time (lower boundary).
  */
-TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidMaxSearchTime1) {
+TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidMaxSearchTime1) {
     serial = GetRandomSerialNumber();
 
     RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
@@ -355,7 +355,7 @@
 /*
  * Test IRadio.startNetworkScan() with invalid max search time (upper boundary).
  */
-TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidMaxSearchTime2) {
+TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidMaxSearchTime2) {
     serial = GetRandomSerialNumber();
 
     RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
@@ -391,7 +391,7 @@
 /*
  * Test IRadio.startNetworkScan() with invalid periodicity (lower boundary).
  */
-TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidPeriodicity1) {
+TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidPeriodicity1) {
     serial = GetRandomSerialNumber();
 
     RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
@@ -427,7 +427,7 @@
 /*
  * Test IRadio.startNetworkScan() with invalid periodicity (upper boundary).
  */
-TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidPeriodicity2) {
+TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidPeriodicity2) {
     serial = GetRandomSerialNumber();
 
     RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
@@ -463,7 +463,7 @@
 /*
  * Test IRadio.startNetworkScan() with valid periodicity
  */
-TEST_F(RadioHidlTest_v1_4, startNetworkScan_GoodRequest1) {
+TEST_P(RadioHidlTest_v1_4, startNetworkScan_GoodRequest1) {
     serial = GetRandomSerialNumber();
 
     RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
@@ -502,7 +502,7 @@
 /*
  * Test IRadio.startNetworkScan() with valid periodicity and plmns
  */
-TEST_F(RadioHidlTest_v1_4, startNetworkScan_GoodRequest2) {
+TEST_P(RadioHidlTest_v1_4, startNetworkScan_GoodRequest2) {
     serial = GetRandomSerialNumber();
 
     RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
@@ -543,7 +543,7 @@
 /*
  * Test IRadio.getSignalStrength_1_4() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_4, getSignalStrength_1_4) {
+TEST_P(RadioHidlTest_v1_4, getSignalStrength_1_4) {
     serial = GetRandomSerialNumber();
 
     radio_v1_4->getSignalStrength_1_4(serial);
@@ -562,7 +562,7 @@
 /*
  * Test IRadio.setupDataCall_1_4() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_4, setupDataCall_1_4) {
+TEST_P(RadioHidlTest_v1_4, setupDataCall_1_4) {
     serial = GetRandomSerialNumber();
 
     ::android::hardware::radio::V1_4::AccessNetwork accessNetwork =
@@ -617,7 +617,7 @@
 /*
  * Test IRadio.getAllowedCarriers_1_4() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_4, getAllowedCarriers_1_4) {
+TEST_P(RadioHidlTest_v1_4, getAllowedCarriers_1_4) {
     serial = GetRandomSerialNumber();
 
     radio_v1_4->getAllowedCarriers_1_4(serial);
@@ -632,7 +632,7 @@
 /**
  * Test IRadio.setAllowedCarriers_1_4() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_4, setAllowedCarriers_1_4) {
+TEST_P(RadioHidlTest_v1_4, setAllowedCarriers_1_4) {
     serial = GetRandomSerialNumber();
     CarrierRestrictionsWithPriority carrierRestrictions;
     memset(&carrierRestrictions, 0, sizeof(carrierRestrictions));
@@ -727,7 +727,7 @@
     }
 }
 
-TEST_F(RadioHidlTest_v1_4, setDataProfile_1_4) {
+TEST_P(RadioHidlTest_v1_4, setDataProfile_1_4) {
     serial = GetRandomSerialNumber();
 
     // Create a dataProfileInfo
@@ -770,7 +770,7 @@
     }
 }
 
-TEST_F(RadioHidlTest_v1_4, setInitialAttachApn_1_4) {
+TEST_P(RadioHidlTest_v1_4, setInitialAttachApn_1_4) {
     serial = GetRandomSerialNumber();
 
     // Create a dataProfileInfo
@@ -812,7 +812,7 @@
 /*
  * Test IRadio.getDataRegistrationStateResponse_1_4() for the response returned.
  */
-TEST_F(RadioHidlTest_v1_4, getDataRegistrationState_1_4) {
+TEST_P(RadioHidlTest_v1_4, getDataRegistrationState_1_4) {
     int rat;
     serial = GetRandomSerialNumber();
 
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
index f27749b..15a0b24 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
@@ -17,18 +17,11 @@
 #include <radio_hidl_hal_utils_v1_4.h>
 
 void RadioHidlTest_v1_4::SetUp() {
-    radio_v1_4 = ::testing::VtsHalHidlTargetTestBase::getService<
-            ::android::hardware::radio::V1_4::IRadio>(
-            RadioHidlEnvironment::Instance()
-                    ->getServiceName<::android::hardware::radio::V1_4::IRadio>(
-                            hidl_string(RADIO_SERVICE_NAME)));
+    radio_v1_4 = ::android::hardware::radio::V1_4::IRadio::getService(GetParam());
+
     if (radio_v1_4 == NULL) {
         sleep(60);
-        radio_v1_4 = ::testing::VtsHalHidlTargetTestBase::getService<
-                ::android::hardware::radio::V1_4::IRadio>(
-                RadioHidlEnvironment::Instance()
-                        ->getServiceName<::android::hardware::radio::V1_4::IRadio>(
-                                hidl_string(RADIO_SERVICE_NAME)));
+        radio_v1_4 = ::android::hardware::radio::V1_4::IRadio::getService(GetParam());
     }
     ASSERT_NE(nullptr, radio_v1_4.get());
 
@@ -48,8 +41,7 @@
     EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error);
 
     sp<::android::hardware::radio::config::V1_1::IRadioConfig> radioConfig =
-            ::testing::VtsHalHidlTargetTestBase::getService<
-                    ::android::hardware::radio::config::V1_1::IRadioConfig>();
+            ::android::hardware::radio::config::V1_1::IRadioConfig::getService();
 
     /* Enforce Vts tesing with RadioConfig is existed. */
     ASSERT_NE(nullptr, radioConfig.get());
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
index b07f9c3..31b7e13 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
+++ b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
@@ -16,8 +16,7 @@
 
 #include <android-base/logging.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
+#include <log/log.h>
 #include <chrono>
 #include <condition_variable>
 #include <mutex>
@@ -28,6 +27,7 @@
 #include <android/hardware/radio/1.4/IRadioIndication.h>
 #include <android/hardware/radio/1.4/IRadioResponse.h>
 #include <android/hardware/radio/1.4/types.h>
+#include <gtest/gtest.h>
 
 #include "vts_test_util.h"
 
@@ -705,25 +705,9 @@
                             const ::android::hardware::hidl_string& reason);
 };
 
-// Test environment for Radio HIDL HAL.
-class RadioHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static RadioHidlEnvironment* Instance() {
-        static RadioHidlEnvironment* instance = new RadioHidlEnvironment;
-        return instance;
-    }
-    virtual void registerTestServices() override {
-        registerTestService<::android::hardware::radio::V1_4::IRadio>();
-    }
-
-   private:
-    RadioHidlEnvironment() {}
-};
-
 // The main test class for Radio HIDL.
-class RadioHidlTest_v1_4 : public ::testing::VtsHalHidlTargetTestBase {
-   protected:
+class RadioHidlTest_v1_4 : public ::testing::TestWithParam<std::string> {
+  protected:
     std::mutex mtx_;
     std::condition_variable cv_;
     int count_;
diff --git a/radio/1.5/Android.bp b/radio/1.5/Android.bp
index de9ec6e..06a2a6e 100644
--- a/radio/1.5/Android.bp
+++ b/radio/1.5/Android.bp
@@ -19,6 +19,7 @@
         "android.hardware.radio@1.3",
         "android.hardware.radio@1.4",
         "android.hidl.base@1.0",
+        "android.hidl.safe_union@1.0",
     ],
     gen_java: true,
 }
diff --git a/radio/1.5/IRadio.hal b/radio/1.5/IRadio.hal
index 74ec56d..aa93ef3 100644
--- a/radio/1.5/IRadio.hal
+++ b/radio/1.5/IRadio.hal
@@ -18,6 +18,8 @@
 
 import @1.4::IRadio;
 import @1.5::AccessNetwork;
+import @1.5::NetworkScanRequest;
+import @1.5::RadioAccessSpecifier;
 import @1.5::SignalThresholdInfo;
 
 /**
@@ -29,7 +31,6 @@
  * setResponseFunctions must work with @1.5::IRadioResponse and @1.5::IRadioIndication.
  */
 interface IRadio extends @1.4::IRadio {
-
     /**
      * Sets the signal strength reporting criteria.
      *
@@ -41,18 +42,91 @@
      * -EUTRAN   - RSRP/RSRQ/RSSNR
      * -NGRAN    - SSRSRP/SSRSRQ/SSSINR
      *
-     * Note: Reporting criteria must be individually set for each RAN. For any unset reporting
-     * criteria, the value is implementation-defined.
+     * Note: Reporting criteria must be individually set for each RAN. For each RAN, if none of
+     * reporting criteria of any measurement is set enabled
+     * (see @1.5::SignalThresholdInfo.isEnabled), the reporting criteria for this RAN is
+     * implementation-defined. For each RAN, if any of reporting criteria of any measure is set
+     * enabled, the reporting criteria of the other measures in this RAN are set disabled
+     * (see @1.5::SignalThresholdInfo.isEnabled) until they are set enabled.
      *
      * Response callback is
      * IRadioResponse.setSignalStrengthReportingCriteriaResponse_1_5()
      *
      * @param serial Serial number of request.
      * @param signalThresholdInfo Signal threshold info including the threshold values,
-     *                            hysteresisDb, and hysteresisMs. See @1.5::SignalThresholdInfo
-     *                            for details.
+     *                            hysteresisDb, hysteresisMs and isEnabled.
+     *                            See @1.5::SignalThresholdInfo for details.
      * @param accessNetwork The type of network for which to apply these thresholds.
      */
     oneway setSignalStrengthReportingCriteria_1_5(int32_t serial,
             SignalThresholdInfo signalThresholdInfo, AccessNetwork accessNetwork);
+
+    /**
+     * Enable or disable UiccApplications on the SIM. If disabled:
+     *  - Modem will not register on any network.
+     *  - SIM must be PRESENT, and the IccId of the SIM must still be accessible.
+     *  - The corresponding modem stack is still functional, e.g. able to make emergency calls or
+     *    do network scan.
+     * By default if this API is not called, the uiccApplications must be enabled automatically.
+     * It must work for both single SIM and DSDS cases for UX consistency.
+     * The preference is per SIM, and must be remembered over power cycle, modem reboot, or SIM
+     * insertion / unplug.
+     *
+     * @param serial: Serial number of request.
+     * @param enable: true if to enable uiccApplications, false to disable.
+
+     * Response callback is IRadioResponse.enableUiccApplicationsResponse()
+     */
+    oneway enableUiccApplications(int32_t serial, bool enable);
+
+    /**
+     * Whether uiccApplications are enabled, or disabled.
+     *
+     * By default uiccApplications must be enabled, unless enableUiccApplications() with enable
+     * being false is called.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response callback is IRadioResponse.areUiccApplicationsEnabledResponse()
+     */
+    oneway areUiccApplicationsEnabled(int32_t serial);
+
+    /**
+     * Query whether disabling and enabling UiccApplications functionality is supported. If not,
+     * calling enableUiccApplications with a different value will return
+     * RadioError:REQUEST_NOT_SUPPORTED.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response callback is IRadioResponse.canToggleUiccApplicationsEnablementResponse()
+     */
+    oneway canToggleUiccApplicationsEnablement(int32_t serial);
+
+    /**
+     * Specify which bands modem's background scan must act on.
+     * If specifyChannels is true, it only scans bands specified in specifiers.
+     * If specifyChannels is false, it scans all bands.
+     *
+     * For example, CBRS is only on LTE band 48. By specifying this band,
+     * modem saves more power.
+     *
+     * @param serial Serial number of request.
+     * @param specifyChannels whether to scan bands defined in specifiers.
+     * @param specifiers which bands to scan. Only used if specifyChannels is true.
+     *
+     * Response callback is IRadioResponse.setSystemSelectionChannelsResponse()
+     */
+    oneway setSystemSelectionChannels_1_5(int32_t serial, bool specifyChannels,
+            vec<RadioAccessSpecifier> specifiers);
+
+    /**
+     * Starts a network scan
+     *
+     * @param serial Serial number of request.
+     * @param request Defines the radio networks/bands/channels which need to be scanned.
+     *
+     * Same API as @1.4::IRadio.startNetworkScan_1_4, except using
+     * 1.5 version of NetworkScanRequest
+     */
+    oneway startNetworkScan_1_5(int32_t serial, NetworkScanRequest request);
 };
diff --git a/radio/1.5/IRadioIndication.hal b/radio/1.5/IRadioIndication.hal
index d488404..81452ab 100644
--- a/radio/1.5/IRadioIndication.hal
+++ b/radio/1.5/IRadioIndication.hal
@@ -23,4 +23,11 @@
  * Interface declaring unsolicited radio indications.
  */
 interface IRadioIndication extends @1.4::IRadioIndication {
+    /**
+     * Report change of whether uiccApplications are enabled, or disabled.
+     *
+     * @param type Type of radio indication
+     * @param enabled whether uiccApplications are enabled, or disabled
+     */
+    oneway uiccApplicationsEnablementChanged(RadioIndicationType type, bool enabled);
 };
diff --git a/radio/1.5/IRadioResponse.hal b/radio/1.5/IRadioResponse.hal
index 91dc1e0..e7a3852 100644
--- a/radio/1.5/IRadioResponse.hal
+++ b/radio/1.5/IRadioResponse.hal
@@ -32,4 +32,65 @@
      *   RadioError:RADIO_NOT_AVAILABLE
      */
     oneway setSignalStrengthReportingCriteriaResponse_1_5(RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:SIM_ABSENT
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:BUSY
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    oneway enableUiccApplicationsResponse(RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param enabled whether Uicc applications are enabled.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:SIM_ABSENT
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    oneway areUiccApplicationsEnabledResponse(RadioResponseInfo info, bool enabled);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param canToggle whether toggling UiccApplications functionality is supported.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     */
+    oneway canToggleUiccApplicationsEnablementResponse(RadioResponseInfo info, bool canToggle);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     */
+    oneway setSystemSelectionChannelsResponse_1_5(RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:DEVICE_IN_USE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     */
+    oneway startNetworkScanResponse_1_5(RadioResponseInfo info);
 };
diff --git a/radio/1.5/types.hal b/radio/1.5/types.hal
index 216ca1f..04a9bcf 100644
--- a/radio/1.5/types.hal
+++ b/radio/1.5/types.hal
@@ -16,6 +16,13 @@
 
 package android.hardware.radio@1.5;
 
+import @1.1::EutranBands;
+import @1.1::GeranBands;
+import @1.1::RadioAccessNetworks;
+import @1.1::RadioAccessSpecifier;
+import @1.1::ScanType;
+import @1.1::UtranBands;
+import @1.2::NetworkScanRequest;
 import @1.4::AccessNetwork;
 
 /**
@@ -52,9 +59,11 @@
     RSRQ = 4,
     /**
      * Reference Signal Signal to Noise Ratio
-     * Range: -20 dB to -30 dB;
+     * Range: -20 dB to 30 dB;
      * Used RAN: EUTRAN
-     * Reference: 3GPP TS 36.101 8.1.1
+     * Note: this field is optional; how to support it can be decided by the
+     * corresponding vendor. Though the response code is not enforced,
+     * vendor's implementation must ensure this interface not crashing.
      */
     RSSNR = 5,
     /**
@@ -104,6 +113,15 @@
      * A vector size of 0 disables the use of thresholds for reporting.
      */
     vec<int32_t> thresholds;
+
+    /**
+     * Indicates whether the reporting criteria of the corresponding measurement is enabled
+     * (isEnabled==true) or disabled (isEnabled==false).
+     *
+     * If enabled, modem must trigger the report based on the criteria.
+     * If disabled, modem must not trigger the report based on the criteria.
+     */
+    bool isEnabled;
 };
 
 enum AccessNetwork : @1.4::AccessNetwork {
@@ -111,4 +129,142 @@
      *  Next-Generation Radio Access Network (NGRAN)
      */
     NGRAN = 6,
-};
\ No newline at end of file
+};
+
+enum RadioAccessNetworks : @1.1::RadioAccessNetworks {
+    NGRAN = 4,
+};
+
+/**
+ * Overwritten from @1.1::RadioAccessSpecifier to add NGRAN and NgranBands
+ */
+struct RadioAccessSpecifier {
+    /**
+     * The type of network to scan.
+     */
+    RadioAccessNetworks radioAccessNetwork;
+
+    /**
+     * The frequency bands to scan.
+     * Maximum length of the vector is 8.
+     */
+    safe_union Bands {
+        /** Valid only if radioAccessNetwork = GERAN. */
+        vec<GeranBands> geranBands;
+        /** Valid only if radioAccessNetwork = UTRAN. */
+        vec<UtranBands> utranBands;
+        /** Valid only if radioAccessNetwork = EUTRAN. */
+        vec<EutranBands> eutranBands;
+        /** Valid only if radioAccessNetwork = NGRAN. */
+        vec<NgranBands> ngranBands;
+    } bands;
+
+    /**
+     * The radio channels to scan as defined in 3GPP TS 25.101 and 36.101.
+     * Maximum length of the vector is 32.
+     */
+    vec<int32_t> channels;
+};
+
+enum NgranBands : int32_t {
+    /** 3GPP TS 38.101-1, Table 5.2-1: FR1 bands */
+    BAND_1 = 1,
+    BAND_2 = 2,
+    BAND_3 = 3,
+    BAND_5 = 5,
+    BAND_7 = 7,
+    BAND_8 = 8,
+    BAND_12 = 12,
+    BAND_14 = 14,
+    BAND_18 = 18,
+    BAND_20 = 20,
+    BAND_25 = 25,
+    BAND_28 = 28,
+    BAND_29 = 29,
+    BAND_30 = 30,
+    BAND_34 = 34,
+    BAND_38 = 38,
+    BAND_39 = 39,
+    BAND_40 = 40,
+    BAND_41 = 41,
+    BAND_48 = 48,
+    BAND_50 = 50,
+    BAND_51 = 51,
+    BAND_65 = 65,
+    BAND_66 = 66,
+    BAND_70 = 70,
+    BAND_71 = 71,
+    BAND_74 = 74,
+    BAND_75 = 75,
+    BAND_76 = 76,
+    BAND_77 = 77,
+    BAND_78 = 78,
+    BAND_79 = 79,
+    BAND_80 = 80,
+    BAND_81 = 81,
+    BAND_82 = 82,
+    BAND_83 = 83,
+    BAND_84 = 84,
+    BAND_86 = 86,
+    BAND_90 = 90,
+    /** 3GPP TS 38.101-2, Table 5.2-1: FR2 bands */
+    BAND_257 = 257,
+    BAND_258 = 258,
+    BAND_260 = 260,
+    BAND_261 = 261,
+};
+
+/**
+ * Overwritten from @1.2::NetworkScanRequest to update
+ * RadioAccessSpecifier to 1.5 version
+ */
+struct NetworkScanRequest {
+    ScanType type;
+
+    /**
+     * Time interval in seconds between the completion of one scan and the start of
+     * a subsequent scan.
+     * Implementations may ignore this field unless the 'type' is 'PERIODIC'.
+     * Range: ScanIntervalRange:MIN to ScanIntervalRange:MAX
+     */
+    int32_t interval;
+
+    /**
+     * Networks with bands/channels to scan
+     * Maximum length of the vector is RadioConst:RADIO_ACCESS_SPECIFIER_MAX_SIZE
+     */
+    vec<RadioAccessSpecifier> specifiers;
+
+    /**
+     * Maximum duration of the periodic search (in seconds).
+     * If the search lasts maxSearchTime, it must be terminated.
+     * Range: MaxSearchTimeRange:MIN to MaxSearchTimeRange:MAX
+     */
+    int32_t maxSearchTime;
+
+    /**
+     * Indicates whether the modem must report incremental results of the network scan
+     * to the client.
+     * FALSE – Incremental results must not be reported.
+     * TRUE  – Incremental must be reported.
+     */
+    bool incrementalResults;
+
+    /**
+     * Indicates the periodicity with which the modem must report incremental results to
+     * the client (in seconds).
+     * Implementations may ignore this value if the incremental results are not requested.
+     * This value must be less than or equal to maxSearchTime.
+     * Range: IncrementalResultsPeriodicityRange:MIN to IncrementalResultsPeriodicityRange:MAX
+     */
+    int32_t incrementalResultsPeriodicity;
+
+    /**
+     * Describes the List of PLMN ids (MCC-MNC)
+     * If any PLMN of this list is found, search must end at that point and results with all
+     * PLMN found until that point should be sent as response.
+     * If the list is not sent, search to be completed until end and all PLMNs found to be
+     * reported.
+     */
+    vec<string> mccMncs;
+};
diff --git a/radio/1.5/vts/functional/VtsHalRadioV1_5TargetTest.cpp b/radio/1.5/vts/functional/VtsHalRadioV1_5TargetTest.cpp
index b72febd..5f11d19 100644
--- a/radio/1.5/vts/functional/VtsHalRadioV1_5TargetTest.cpp
+++ b/radio/1.5/vts/functional/VtsHalRadioV1_5TargetTest.cpp
@@ -23,4 +23,4 @@
     int status = RUN_ALL_TESTS();
     LOG(INFO) << "Test result = " << status;
     return status;
-}
\ No newline at end of file
+}
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
index 650ede4..6bf8170 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
@@ -29,6 +29,7 @@
     signalThresholdInfo.hysteresisMs = 5000;
     signalThresholdInfo.hysteresisDb = 10;  // hysteresisDb too large given threshold list deltas
     signalThresholdInfo.thresholds = {-109, -103, -97, -89};
+    signalThresholdInfo.isEnabled = true;
 
     Return<void> res = radio_v1_5->setSignalStrengthReportingCriteria_1_5(
             serial, signalThresholdInfo, ::android::hardware::radio::V1_5::AccessNetwork::GERAN);
@@ -52,6 +53,7 @@
     signalThresholdInfo.signalMeasurement = SignalMeasurementType::RSSI;
     signalThresholdInfo.hysteresisMs = 0;
     signalThresholdInfo.hysteresisDb = 0;
+    signalThresholdInfo.isEnabled = true;
 
     Return<void> res = radio_v1_5->setSignalStrengthReportingCriteria_1_5(
             serial, signalThresholdInfo, ::android::hardware::radio::V1_5::AccessNetwork::GERAN);
@@ -76,6 +78,7 @@
     signalThresholdInfo.hysteresisMs = 5000;
     signalThresholdInfo.hysteresisDb = 2;
     signalThresholdInfo.thresholds = {-109, -103, -97, -89};
+    signalThresholdInfo.isEnabled = true;
 
     Return<void> res = radio_v1_5->setSignalStrengthReportingCriteria_1_5(
             serial, signalThresholdInfo, ::android::hardware::radio::V1_5::AccessNetwork::GERAN);
@@ -100,6 +103,7 @@
     signalThresholdInfo.hysteresisMs = 5000;
     signalThresholdInfo.hysteresisDb = 2;
     signalThresholdInfo.thresholds = {-110, -97, -73, -49, -25};
+    signalThresholdInfo.isEnabled = true;
 
     Return<void> res = radio_v1_5->setSignalStrengthReportingCriteria_1_5(
             serial, signalThresholdInfo, ::android::hardware::radio::V1_5::AccessNetwork::UTRAN);
@@ -124,6 +128,7 @@
     signalThresholdInfo.hysteresisMs = 5000;
     signalThresholdInfo.hysteresisDb = 2;
     signalThresholdInfo.thresholds = {-128, -108, -88, -68};
+    signalThresholdInfo.isEnabled = true;
 
     Return<void> res = radio_v1_5->setSignalStrengthReportingCriteria_1_5(
             serial, signalThresholdInfo, ::android::hardware::radio::V1_5::AccessNetwork::EUTRAN);
@@ -148,6 +153,7 @@
     signalThresholdInfo.hysteresisMs = 5000;
     signalThresholdInfo.hysteresisDb = 2;
     signalThresholdInfo.thresholds = {-27, -20, -13, -6};
+    signalThresholdInfo.isEnabled = true;
 
     Return<void> res = radio_v1_5->setSignalStrengthReportingCriteria_1_5(
             serial, signalThresholdInfo, ::android::hardware::radio::V1_5::AccessNetwork::EUTRAN);
@@ -172,6 +178,7 @@
     signalThresholdInfo.hysteresisMs = 5000;
     signalThresholdInfo.hysteresisDb = 2;
     signalThresholdInfo.thresholds = {-10, 0, 10, 20};
+    signalThresholdInfo.isEnabled = true;
 
     Return<void> res = radio_v1_5->setSignalStrengthReportingCriteria_1_5(
             serial, signalThresholdInfo, ::android::hardware::radio::V1_5::AccessNetwork::EUTRAN);
@@ -179,10 +186,6 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
-
-    ALOGI("setSignalStrengthReportingCriteria_1_5_Eutran, rspInfo.error = %s\n",
-          toString(radioRsp_v1_5->rspInfo.error).c_str());
-    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error, {RadioError::NONE}));
 }
 
 /*
@@ -196,6 +199,7 @@
     signalThresholdInfo.hysteresisMs = 5000;
     signalThresholdInfo.hysteresisDb = 2;
     signalThresholdInfo.thresholds = {-105, -90, -75, -65};
+    signalThresholdInfo.isEnabled = true;
 
     Return<void> res = radio_v1_5->setSignalStrengthReportingCriteria_1_5(
             serial, signalThresholdInfo, ::android::hardware::radio::V1_5::AccessNetwork::CDMA2000);
@@ -220,6 +224,7 @@
     signalThresholdInfo.hysteresisMs = 5000;
     signalThresholdInfo.hysteresisDb = 0;
     signalThresholdInfo.thresholds = {-105, -90, -75, -65};
+    signalThresholdInfo.isEnabled = true;
 
     Return<void> res = radio_v1_5->setSignalStrengthReportingCriteria_1_5(
             serial, signalThresholdInfo, ::android::hardware::radio::V1_5::AccessNetwork::NGRAN);
@@ -244,6 +249,7 @@
     signalThresholdInfo.hysteresisMs = 5000;
     signalThresholdInfo.hysteresisDb = 0;
     signalThresholdInfo.thresholds = {-15, -10, -5, -4};
+    signalThresholdInfo.isEnabled = true;
 
     Return<void> res = radio_v1_5->setSignalStrengthReportingCriteria_1_5(
             serial, signalThresholdInfo, ::android::hardware::radio::V1_5::AccessNetwork::NGRAN);
@@ -258,6 +264,27 @@
 }
 
 /*
+ * Test IRadio.setSignalStrengthReportingCriteria_1_5() for EUTRAN
+ */
+TEST_F(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_Disable_RSSNR) {
+    serial = GetRandomSerialNumber();
+
+    ::android::hardware::radio::V1_5::SignalThresholdInfo signalThresholdInfo;
+    signalThresholdInfo.signalMeasurement = SignalMeasurementType::RSSNR;
+    signalThresholdInfo.hysteresisMs = 5000;
+    signalThresholdInfo.hysteresisDb = 2;
+    signalThresholdInfo.thresholds = {-10, 0, 10, 20};
+    signalThresholdInfo.isEnabled = false;
+
+    Return<void> res = radio_v1_5->setSignalStrengthReportingCriteria_1_5(
+            serial, signalThresholdInfo, ::android::hardware::radio::V1_5::AccessNetwork::EUTRAN);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+}
+
+/*
  * Test IRadio.setSignalStrengthReportingCriteria_1_5() for NGRAN_SSSINR
  */
 TEST_F(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_NGRAN_SSSINR) {
@@ -268,6 +295,7 @@
     signalThresholdInfo.hysteresisMs = 5000;
     signalThresholdInfo.hysteresisDb = 0;
     signalThresholdInfo.thresholds = {-10, 3, 16, 18};
+    signalThresholdInfo.isEnabled = true;
 
     Return<void> res = radio_v1_5->setSignalStrengthReportingCriteria_1_5(
             serial, signalThresholdInfo, ::android::hardware::radio::V1_5::AccessNetwork::NGRAN);
@@ -279,4 +307,593 @@
     ALOGI("setSignalStrengthReportingCriteria_1_5_NGRAN_SSSINR, rspInfo.error = %s\n",
           toString(radioRsp_v1_5->rspInfo.error).c_str());
     ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error, {RadioError::NONE}));
-}
\ No newline at end of file
+}
+
+/*
+ * Test IRadio.enableUiccApplications() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_5, togglingUiccApplicationsNotSupported) {
+    serial = GetRandomSerialNumber();
+
+    radio_v1_5->canToggleUiccApplicationsEnablement(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    // No error should happen.
+    EXPECT_EQ(RadioError::NONE, radioRsp_v1_5->rspInfo.error);
+
+    // Supported case will be tested by other test cases.
+    if (radioRsp_v1_5->canToggleUiccApplicationsEnablement) return;
+
+    // Enabling UiccApplications should still work as it should be enabled by default.
+    serial = GetRandomSerialNumber();
+    radio_v1_5->enableUiccApplications(serial, true);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    EXPECT_EQ(RadioError::NONE, radioRsp_v1_5->rspInfo.error);
+
+    // Disabling UiccApplications should return REQUEST_NOT_SUPPORTED error.
+    serial = GetRandomSerialNumber();
+    radio_v1_5->enableUiccApplications(serial, false);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    EXPECT_EQ(RadioError::REQUEST_NOT_SUPPORTED, radioRsp_v1_5->rspInfo.error);
+
+    // Query areUiccApplicationsEnabled should return true.
+    serial = GetRandomSerialNumber();
+    radio_v1_5->areUiccApplicationsEnabled(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    EXPECT_EQ(RadioError::NONE, radioRsp_v1_5->rspInfo.error);
+    ASSERT_TRUE(radioRsp_v1_5->areUiccApplicationsEnabled);
+}
+
+/*
+ * Test IRadio.enableUiccApplications() for the response returned.
+ * For SIM ABSENT case.
+ */
+TEST_F(RadioHidlTest_v1_5, togglingUiccApplicationsSupportedSimAbsent) {
+    serial = GetRandomSerialNumber();
+
+    radio_v1_5->canToggleUiccApplicationsEnablement(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    // No error should happen.
+    EXPECT_EQ(RadioError::NONE, radioRsp_v1_5->rspInfo.error);
+    // Not supported case will be tested by togglingUiccApplicationsNotSupported test case.
+    if (!radioRsp_v1_5->canToggleUiccApplicationsEnablement) return;
+
+    // This test case only test SIM ABSENT case.
+    if (cardStatus.base.base.cardState != CardState::ABSENT) return;
+
+    // Disable Uicc applications.
+    serial = GetRandomSerialNumber();
+    radio_v1_5->enableUiccApplications(serial, false);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    // As SIM is absent, RadioError::SIM_ABSENT should be thrown.
+    EXPECT_EQ(RadioError::SIM_ABSENT, radioRsp_v1_5->rspInfo.error);
+
+    // Query Uicc application enablement.
+    serial = GetRandomSerialNumber();
+    radio_v1_5->areUiccApplicationsEnabled(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    // As SIM is absent, RadioError::SIM_ABSENT should be thrown.
+    EXPECT_EQ(RadioError::SIM_ABSENT, radioRsp_v1_5->rspInfo.error);
+}
+
+/*
+ * Test IRadio.enableUiccApplications() for the response returned.
+ * For SIM PRESENT case.
+ */
+TEST_F(RadioHidlTest_v1_5, togglingUiccApplicationsSupportedSimPresent) {
+    serial = GetRandomSerialNumber();
+
+    radio_v1_5->canToggleUiccApplicationsEnablement(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    // No error should happen.
+    EXPECT_EQ(RadioError::NONE, radioRsp_v1_5->rspInfo.error);
+    // Not supported case will be tested by disablingUiccApplicationsNotSupported test case.
+    if (!radioRsp_v1_5->canToggleUiccApplicationsEnablement) return;
+
+    // This test case only test SIM ABSENT case.
+    if (cardStatus.base.base.cardState != CardState::PRESENT) return;
+
+    // Disable Uicc applications.
+    serial = GetRandomSerialNumber();
+    radio_v1_5->enableUiccApplications(serial, false);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    // As SIM is present, there shouldn't be error.
+    EXPECT_EQ(RadioError::NONE, radioRsp_v1_5->rspInfo.error);
+
+    // Query Uicc application enablement.
+    serial = GetRandomSerialNumber();
+    radio_v1_5->areUiccApplicationsEnabled(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    // As SIM is present, there shouldn't be error.
+    EXPECT_EQ(RadioError::NONE, radioRsp_v1_5->rspInfo.error);
+    ASSERT_FALSE(radioRsp_v1_5->areUiccApplicationsEnabled);
+
+    // Enable Uicc applications.
+    serial = GetRandomSerialNumber();
+    radio_v1_5->enableUiccApplications(serial, true);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    // As SIM is present, there shouldn't be error.
+    EXPECT_EQ(RadioError::NONE, radioRsp_v1_5->rspInfo.error);
+
+    // Query Uicc application enablement.
+    serial = GetRandomSerialNumber();
+    radio_v1_5->areUiccApplicationsEnabled(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    // As SIM is present, there shouldn't be error.
+    EXPECT_EQ(RadioError::NONE, radioRsp_v1_5->rspInfo.error);
+    ASSERT_TRUE(radioRsp_v1_5->areUiccApplicationsEnabled);
+}
+
+/*
+ * Test IRadio.areUiccApplicationsEnabled() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_5, areUiccApplicationsEnabled) {
+    serial = GetRandomSerialNumber();
+
+    radio_v1_5->canToggleUiccApplicationsEnablement(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    // No error should happen.
+    EXPECT_EQ(RadioError::NONE, radioRsp_v1_5->rspInfo.error);
+
+    // Not supported case will be tested by togglingUiccApplicationsNotSupported test case.
+    if (!radioRsp_v1_5->canToggleUiccApplicationsEnablement) return;
+
+    // Disable Uicc applications.
+    serial = GetRandomSerialNumber();
+    radio_v1_5->areUiccApplicationsEnabled(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+
+    // If SIM is absent, RadioError::SIM_ABSENT should be thrown. Otherwise there shouldn't be any
+    // error.
+    if (cardStatus.base.base.cardState == CardState::ABSENT) {
+        EXPECT_EQ(RadioError::SIM_ABSENT, radioRsp_v1_5->rspInfo.error);
+    } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+        EXPECT_EQ(RadioError::NONE, radioRsp_v1_5->rspInfo.error);
+    }
+}
+
+/*
+ * Test IRadio.setSystemSelectionChannels_1_5() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_5, setSystemSelectionChannels_1_5) {
+    serial = GetRandomSerialNumber();
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = rasBands,
+            .channels = {1, 2}};
+
+    Return<void> res = radio_v1_5->setSystemSelectionChannels_1_5(serial, true, {specifier});
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    ALOGI("setSystemSelectionChannels, rspInfo.error = %s\n",
+          toString(radioRsp_v1_5->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_v1_5->rspInfo.error,
+            {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR}));
+
+    if (radioRsp_v1_5->rspInfo.error == RadioError::NONE) {
+        serial = GetRandomSerialNumber();
+        Return<void> res = radio_v1_5->setSystemSelectionChannels_1_5(serial, false, {specifier});
+        ASSERT_OK(res);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+        EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+        ALOGI("setSystemSelectionChannels, rspInfo.error = %s\n",
+              toString(radioRsp_v1_5->rspInfo.error).c_str());
+        EXPECT_EQ(RadioError::NONE, radioRsp_v1_5->rspInfo.error);
+    }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan) {
+    serial = GetRandomSerialNumber();
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = rasBands,
+            .channels = {1, 2}};
+
+    ::android::hardware::radio::V1_5::NetworkScanRequest request = {
+            .type = ScanType::ONE_SHOT,
+            .interval = 60,
+            .specifiers = {specifier},
+            .maxSearchTime = 60,
+            .incrementalResults = false,
+            .incrementalResultsPeriodicity = 1};
+
+    Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    ALOGI("startNetworkScan, rspInfo.error = %s\n", toString(radioRsp_v1_5->rspInfo.error).c_str());
+
+    if (cardStatus.base.base.cardState == CardState::ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error, {RadioError::SIM_ABSENT}));
+    } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+        // OPERATION_NOT_ALLOWED should not be allowed; however, some vendors do
+        // not support the required manual GSM search functionality. This is
+        // tracked in b/112206766. Modems have "GSM" rat scan need to
+        // support scanning requests combined with some parameters.
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                                     {RadioError::NONE, RadioError::OPERATION_NOT_ALLOWED}));
+    }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() with invalid specifier.
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidArgument) {
+    serial = GetRandomSerialNumber();
+
+    ::android::hardware::radio::V1_5::NetworkScanRequest request = {.type = ScanType::ONE_SHOT,
+                                                                    .interval = 60};
+
+    Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    ALOGI("startNetworkScan_InvalidArgument, rspInfo.error = %s\n",
+          toString(radioRsp_v1_5->rspInfo.error).c_str());
+
+    if (cardStatus.base.base.cardState == CardState::ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+    } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_v1_5->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() with invalid interval (lower boundary).
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidInterval1) {
+    serial = GetRandomSerialNumber();
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = rasBands,
+            .channels = {1, 2}};
+
+    ::android::hardware::radio::V1_5::NetworkScanRequest request = {
+            .type = ScanType::ONE_SHOT,
+            .interval = 4,
+            .specifiers = {specifier},
+            .maxSearchTime = 60,
+            .incrementalResults = false,
+            .incrementalResultsPeriodicity = 1};
+
+    Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    ALOGI("startNetworkScan_InvalidInterval1, rspInfo.error = %s\n",
+          toString(radioRsp_v1_5->rspInfo.error).c_str());
+    if (cardStatus.base.base.cardState == CardState::ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+    } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_v1_5->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() with invalid interval (upper boundary).
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidInterval2) {
+    serial = GetRandomSerialNumber();
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = rasBands,
+            .channels = {1, 2}};
+
+    ::android::hardware::radio::V1_5::NetworkScanRequest request = {
+            .type = ScanType::ONE_SHOT,
+            .interval = 301,
+            .specifiers = {specifier},
+            .maxSearchTime = 60,
+            .incrementalResults = false,
+            .incrementalResultsPeriodicity = 1};
+
+    Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    ALOGI("startNetworkScan_InvalidInterval2, rspInfo.error = %s\n",
+          toString(radioRsp_v1_5->rspInfo.error).c_str());
+    if (cardStatus.base.base.cardState == CardState::ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+    } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_v1_5->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() with invalid max search time (lower boundary).
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidMaxSearchTime1) {
+    serial = GetRandomSerialNumber();
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = rasBands,
+            .channels = {1, 2}};
+
+    ::android::hardware::radio::V1_5::NetworkScanRequest request = {
+            .type = ScanType::ONE_SHOT,
+            .interval = 60,
+            .specifiers = {specifier},
+            .maxSearchTime = 59,
+            .incrementalResults = false,
+            .incrementalResultsPeriodicity = 1};
+
+    Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    ALOGI("startNetworkScan_InvalidMaxSearchTime1, rspInfo.error = %s\n",
+          toString(radioRsp_v1_5->rspInfo.error).c_str());
+    if (cardStatus.base.base.cardState == CardState::ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+    } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_v1_5->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() with invalid max search time (upper boundary).
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidMaxSearchTime2) {
+    serial = GetRandomSerialNumber();
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = rasBands,
+            .channels = {1, 2}};
+
+    ::android::hardware::radio::V1_5::NetworkScanRequest request = {
+            .type = ScanType::ONE_SHOT,
+            .interval = 60,
+            .specifiers = {specifier},
+            .maxSearchTime = 3601,
+            .incrementalResults = false,
+            .incrementalResultsPeriodicity = 1};
+
+    Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    ALOGI("startNetworkScan_InvalidMaxSearchTime2, rspInfo.error = %s\n",
+          toString(radioRsp_v1_5->rspInfo.error).c_str());
+    if (cardStatus.base.base.cardState == CardState::ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+    } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_v1_5->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() with invalid periodicity (lower boundary).
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidPeriodicity1) {
+    serial = GetRandomSerialNumber();
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = rasBands,
+            .channels = {1, 2}};
+
+    ::android::hardware::radio::V1_5::NetworkScanRequest request = {
+            .type = ScanType::ONE_SHOT,
+            .interval = 60,
+            .specifiers = {specifier},
+            .maxSearchTime = 600,
+            .incrementalResults = true,
+            .incrementalResultsPeriodicity = 0};
+
+    Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    ALOGI("startNetworkScan_InvalidPeriodicity1, rspInfo.error = %s\n",
+          toString(radioRsp_v1_5->rspInfo.error).c_str());
+    if (cardStatus.base.base.cardState == CardState::ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+    } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_v1_5->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() with invalid periodicity (upper boundary).
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan_InvalidPeriodicity2) {
+    serial = GetRandomSerialNumber();
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = rasBands,
+            .channels = {1, 2}};
+
+    ::android::hardware::radio::V1_5::NetworkScanRequest request = {
+            .type = ScanType::ONE_SHOT,
+            .interval = 60,
+            .specifiers = {specifier},
+            .maxSearchTime = 600,
+            .incrementalResults = true,
+            .incrementalResultsPeriodicity = 11};
+
+    Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    ALOGI("startNetworkScan_InvalidPeriodicity2, rspInfo.error = %s\n",
+          toString(radioRsp_v1_5->rspInfo.error).c_str());
+    if (cardStatus.base.base.cardState == CardState::ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+    } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_v1_5->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() with valid periodicity
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan_GoodRequest1) {
+    serial = GetRandomSerialNumber();
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = rasBands,
+            .channels = {1, 2}};
+
+    ::android::hardware::radio::V1_5::NetworkScanRequest request = {
+            .type = ScanType::ONE_SHOT,
+            .interval = 60,
+            .specifiers = {specifier},
+            .maxSearchTime = 360,
+            .incrementalResults = false,
+            .incrementalResultsPeriodicity = 10};
+
+    Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    ALOGI("startNetworkScan_GoodRequest1, rspInfo.error = %s\n",
+          toString(radioRsp_v1_5->rspInfo.error).c_str());
+    if (cardStatus.base.base.cardState == CardState::ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                                     {RadioError::NONE, RadioError::SIM_ABSENT}));
+    } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+                                      RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+}
+
+/*
+ * Test IRadio.startNetworkScan_1_5() with valid periodicity and plmns
+ */
+TEST_F(RadioHidlTest_v1_5, startNetworkScan_GoodRequest2) {
+    serial = GetRandomSerialNumber();
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
+    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
+
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = rasBands,
+            .channels = {1, 2}};
+
+    ::android::hardware::radio::V1_5::NetworkScanRequest request = {
+            .type = ScanType::ONE_SHOT,
+            .interval = 60,
+            .specifiers = {specifier},
+            .maxSearchTime = 360,
+            .incrementalResults = false,
+            .incrementalResultsPeriodicity = 10,
+            .mccMncs = {"310410"}};
+
+    Return<void> res = radio_v1_5->startNetworkScan_1_5(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+    ALOGI("startNetworkScan_GoodRequest2, rspInfo.error = %s\n",
+          toString(radioRsp_v1_5->rspInfo.error).c_str());
+    if (cardStatus.base.base.cardState == CardState::ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                                     {RadioError::NONE, RadioError::SIM_ABSENT}));
+    } else if (cardStatus.base.base.cardState == CardState::PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+                                      RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+}
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h b/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
index 683fdfc..01bda69 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
+++ b/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
@@ -53,7 +53,7 @@
 class RadioHidlTest_v1_5;
 extern ::android::hardware::radio::V1_4::CardStatus cardStatus;
 
-/* Callback class for radio respons v1_5 */
+/* Callback class for radio response v1_5 */
 class RadioResponse_v1_5 : public ::android::hardware::radio::V1_5::IRadioResponse {
   protected:
     RadioHidlTest_v1_5& parent_v1_5;
@@ -80,6 +80,12 @@
     ::android::hardware::radio::V1_4::CarrierRestrictionsWithPriority carrierRestrictionsResp;
     ::android::hardware::radio::V1_4::SimLockMultiSimPolicy multiSimPolicyResp;
 
+    // Whether toggling uicc applications operation is supported.
+    bool canToggleUiccApplicationsEnablement;
+
+    // Whether Uicc applications are enabled or not.
+    bool areUiccApplicationsEnabled;
+
     RadioResponse_v1_5(RadioHidlTest_v1_5& parent_v1_5);
     virtual ~RadioResponse_v1_5() = default;
 
@@ -524,6 +530,17 @@
 
     /* 1.5 Api */
     Return<void> setSignalStrengthReportingCriteriaResponse_1_5(const RadioResponseInfo& info);
+
+    Return<void> enableUiccApplicationsResponse(const RadioResponseInfo& info);
+
+    Return<void> areUiccApplicationsEnabledResponse(const RadioResponseInfo& info, bool enabled);
+
+    Return<void> canToggleUiccApplicationsEnablementResponse(const RadioResponseInfo& info,
+                                                             bool canToggle);
+
+    Return<void> setSystemSelectionChannelsResponse_1_5(const RadioResponseInfo& info);
+
+    Return<void> startNetworkScanResponse_1_5(const RadioResponseInfo& info);
 };
 
 /* Callback class for radio indication */
@@ -535,6 +552,9 @@
     RadioIndication_v1_5(RadioHidlTest_v1_5& parent_v1_5);
     virtual ~RadioIndication_v1_5() = default;
 
+    /* 1.5 Api */
+    Return<void> uiccApplicationsEnablementChanged(RadioIndicationType type, bool enabled);
+
     /* 1.4 Api */
     Return<void> currentEmergencyNumberList(
             RadioIndicationType type,
diff --git a/radio/1.5/vts/functional/radio_indication.cpp b/radio/1.5/vts/functional/radio_indication.cpp
index b63b745..acffbbe 100644
--- a/radio/1.5/vts/functional/radio_indication.cpp
+++ b/radio/1.5/vts/functional/radio_indication.cpp
@@ -328,3 +328,8 @@
                                               const ::android::hardware::hidl_string& /*reason*/) {
     return Void();
 }
+
+Return<void> RadioIndication_v1_5::uiccApplicationsEnablementChanged(RadioIndicationType /*type*/,
+                                                                     bool /*enabled*/) {
+    return Void();
+}
diff --git a/radio/1.5/vts/functional/radio_response.cpp b/radio/1.5/vts/functional/radio_response.cpp
index 29a9250..5964c96 100644
--- a/radio/1.5/vts/functional/radio_response.cpp
+++ b/radio/1.5/vts/functional/radio_response.cpp
@@ -892,4 +892,39 @@
     rspInfo = info;
     parent_v1_5.notify(info.serial);
     return Void();
-}
\ No newline at end of file
+}
+
+Return<void> RadioResponse_v1_5::enableUiccApplicationsResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_5.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_5::areUiccApplicationsEnabledResponse(const RadioResponseInfo& info,
+                                                                    bool enabled) {
+    rspInfo = info;
+    areUiccApplicationsEnabled = enabled;
+    parent_v1_5.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_5::canToggleUiccApplicationsEnablementResponse(
+        const RadioResponseInfo& info, bool canToggle) {
+    rspInfo = info;
+    canToggleUiccApplicationsEnablement = canToggle;
+    parent_v1_5.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_5::setSystemSelectionChannelsResponse_1_5(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_5.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_5::startNetworkScanResponse_1_5(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_5.notify(info.serial);
+    return Void();
+}
diff --git a/radio/config/1.0/vts/functional/radio_config_hidl_hal_utils.h b/radio/config/1.0/vts/functional/radio_config_hidl_hal_utils.h
index 6bc1b65..2722afe 100644
--- a/radio/config/1.0/vts/functional/radio_config_hidl_hal_utils.h
+++ b/radio/config/1.0/vts/functional/radio_config_hidl_hal_utils.h
@@ -27,6 +27,7 @@
 #include <gtest/gtest.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
+#include <log/log.h>
 
 #include "vts_test_util.h"
 
diff --git a/radio/config/1.1/vts/functional/radio_config_hidl_hal_utils.h b/radio/config/1.1/vts/functional/radio_config_hidl_hal_utils.h
index e9951dc..4cdeb06 100644
--- a/radio/config/1.1/vts/functional/radio_config_hidl_hal_utils.h
+++ b/radio/config/1.1/vts/functional/radio_config_hidl_hal_utils.h
@@ -26,6 +26,7 @@
 #include <gtest/gtest.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
+#include <log/log.h>
 
 #include "vts_test_util.h"
 
diff --git a/radio/config/1.2/vts/functional/radio_config_hidl_hal_utils.h b/radio/config/1.2/vts/functional/radio_config_hidl_hal_utils.h
index e9cbcbd..ba3f02e 100644
--- a/radio/config/1.2/vts/functional/radio_config_hidl_hal_utils.h
+++ b/radio/config/1.2/vts/functional/radio_config_hidl_hal_utils.h
@@ -28,6 +28,7 @@
 #include <gtest/gtest.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
+#include <log/log.h>
 
 #include "vts_test_util.h"
 
@@ -98,20 +99,6 @@
             const ::android::hardware::hidl_vec<SimSlotStatus>& slotStatus);
 };
 
-// Test environment for Radio HIDL HAL.
-class RadioConfigHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-  public:
-    // get the test environment singleton
-    static RadioConfigHidlEnvironment* Instance() {
-        static RadioConfigHidlEnvironment* instance = new RadioConfigHidlEnvironment;
-        return instance;
-    }
-    virtual void registerTestServices() override { registerTestService<IRadioConfig>(); }
-
-  private:
-    RadioConfigHidlEnvironment() {}
-};
-
 // The main test class for Radio config HIDL.
 class RadioConfigHidlTest : public ::testing::TestWithParam<std::string> {
   protected:
diff --git a/radio/config/1.3/Android.bp b/radio/config/1.3/Android.bp
new file mode 100644
index 0000000..88de666
--- /dev/null
+++ b/radio/config/1.3/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.radio.config@1.3",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IRadioConfig.hal",
+        "IRadioConfigIndication.hal",
+        "IRadioConfigResponse.hal",
+    ],
+    interfaces: [
+        "android.hardware.radio.config@1.0",
+        "android.hardware.radio.config@1.1",
+        "android.hardware.radio.config@1.2",
+        "android.hardware.radio@1.0",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
diff --git a/radio/config/1.3/IRadioConfig.hal b/radio/config/1.3/IRadioConfig.hal
new file mode 100644
index 0000000..a0ce6e0
--- /dev/null
+++ b/radio/config/1.3/IRadioConfig.hal
@@ -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.
+ */
+
+package android.hardware.radio.config@1.3;
+
+import @1.1::IRadioConfig;
+
+/**
+ * This interface is used by telephony and telecom to talk to cellular radio for the purpose of
+ * radio configuration, and it is not associated with any specific modem or slot.
+ * All the functions have minimum one parameter:
+ * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
+ * duration of a method call. If clients provide colliding serials (including passing the same
+ * serial to different methods), multiple responses (one for each method call) must still be served.
+ */
+interface IRadioConfig extends @1.1::IRadioConfig {
+
+};
diff --git a/vibrator/1.4/types.hal b/radio/config/1.3/IRadioConfigIndication.hal
similarity index 73%
copy from vibrator/1.4/types.hal
copy to radio/config/1.3/IRadioConfigIndication.hal
index acc49b1..9ef496c 100644
--- a/vibrator/1.4/types.hal
+++ b/radio/config/1.3/IRadioConfigIndication.hal
@@ -14,9 +14,13 @@
  * limitations under the License.
  */
 
-package android.hardware.vibrator@1.4;
+package android.hardware.radio.config@1.3;
 
-enum Capabilities : uint32_t {
-    ON_COMPLETION_CALLBACK = 1 << 0,
-    PERFORM_COMPLETION_CALLBACK = 1 << 1,
+import @1.2::IRadioConfigIndication;
+
+/**
+ * Interface declaring unsolicited radio config indications.
+ */
+interface IRadioConfigIndication extends @1.2::IRadioConfigIndication {
+
 };
diff --git a/vibrator/1.4/types.hal b/radio/config/1.3/IRadioConfigResponse.hal
similarity index 72%
copy from vibrator/1.4/types.hal
copy to radio/config/1.3/IRadioConfigResponse.hal
index acc49b1..9c4c971 100644
--- a/vibrator/1.4/types.hal
+++ b/radio/config/1.3/IRadioConfigResponse.hal
@@ -14,9 +14,13 @@
  * limitations under the License.
  */
 
-package android.hardware.vibrator@1.4;
+package android.hardware.radio.config@1.3;
 
-enum Capabilities : uint32_t {
-    ON_COMPLETION_CALLBACK = 1 << 0,
-    PERFORM_COMPLETION_CALLBACK = 1 << 1,
+import @1.2::IRadioConfigResponse;
+
+/**
+ * Interface declaring response functions to solicited radio config requests.
+ */
+interface IRadioConfigResponse extends @1.2::IRadioConfigResponse {
+
 };
diff --git a/radio/config/1.3/default/Android.bp b/radio/config/1.3/default/Android.bp
new file mode 100644
index 0000000..163c5c5
--- /dev/null
+++ b/radio/config/1.3/default/Android.bp
@@ -0,0 +1,28 @@
+cc_binary {
+    name: "android.hardware.radio.config@1.3-service",
+    init_rc: ["android.hardware.radio.config@1.3-service.rc"],
+    relative_install_path: "hw",
+    vintf_fragments: ["radio-config-default.xml"],
+    vendor: true,
+    srcs: [
+        "RadioConfig.cpp",
+        "RadioConfigIndication.cpp",
+        "RadioConfigResponse.cpp",
+        "service.cpp",
+    ],
+    shared_libs: [
+        "libhidlbase",
+        "liblog",
+        "libutils",
+        "android.hardware.radio.config@1.0",
+        "android.hardware.radio.config@1.1",
+        "android.hardware.radio.config@1.2",
+        "android.hardware.radio.config@1.3",
+        "android.hardware.radio@1.0",
+        "android.hardware.radio@1.1",
+        "android.hardware.radio@1.2",
+        "android.hardware.radio@1.3",
+        "android.hardware.radio@1.4",
+        "android.hardware.radio@1.5",
+    ],
+}
diff --git a/radio/config/1.3/default/RadioConfig.cpp b/radio/config/1.3/default/RadioConfig.cpp
new file mode 100644
index 0000000..c28119c
--- /dev/null
+++ b/radio/config/1.3/default/RadioConfig.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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 "RadioConfig.h"
+
+namespace android {
+namespace hardware {
+namespace radio {
+namespace config {
+namespace V1_3 {
+namespace implementation {
+
+using namespace ::android::hardware::radio::V1_0;
+using namespace ::android::hardware::radio::config;
+
+// Methods from ::android::hardware::radio::config::V1_0::IRadioConfig follow.
+Return<void> RadioConfig::setResponseFunctions(
+        const sp<V1_0::IRadioConfigResponse>& radioConfigResponse,
+        const sp<V1_0::IRadioConfigIndication>& radioConfigIndication) {
+    mRadioConfigResponse = radioConfigResponse;
+    mRadioConfigIndication = radioConfigIndication;
+
+    mRadioConfigResponseV1_3 =
+            V1_3::IRadioConfigResponse::castFrom(mRadioConfigResponse).withDefault(nullptr);
+    mRadioConfigIndicationV1_3 =
+            V1_3::IRadioConfigIndication::castFrom(mRadioConfigIndication).withDefault(nullptr);
+    if (mRadioConfigResponseV1_3 == nullptr || mRadioConfigIndicationV1_3 == nullptr) {
+        mRadioConfigResponseV1_3 = nullptr;
+        mRadioConfigIndicationV1_3 = nullptr;
+    }
+
+    mRadioConfigResponseV1_2 =
+            V1_2::IRadioConfigResponse::castFrom(mRadioConfigResponse).withDefault(nullptr);
+    mRadioConfigIndicationV1_2 =
+            V1_2::IRadioConfigIndication::castFrom(mRadioConfigIndication).withDefault(nullptr);
+    if (mRadioConfigResponseV1_2 == nullptr || mRadioConfigIndicationV1_2 == nullptr) {
+        mRadioConfigResponseV1_2 = nullptr;
+        mRadioConfigIndicationV1_2 = nullptr;
+    }
+
+    mRadioConfigResponseV1_1 =
+            V1_1::IRadioConfigResponse::castFrom(mRadioConfigResponse).withDefault(nullptr);
+    mRadioConfigIndicationV1_1 =
+            V1_1::IRadioConfigIndication::castFrom(mRadioConfigIndication).withDefault(nullptr);
+    if (mRadioConfigResponseV1_1 == nullptr || mRadioConfigIndicationV1_1 == nullptr) {
+        mRadioConfigResponseV1_1 = nullptr;
+        mRadioConfigIndicationV1_1 = nullptr;
+    }
+
+    return Void();
+}
+
+Return<void> RadioConfig::getSimSlotsStatus(int32_t /* serial */) {
+    hidl_vec<V1_0::SimSlotStatus> slotStatus;
+    RadioResponseInfo info;
+    mRadioConfigResponse->getSimSlotsStatusResponse(info, slotStatus);
+    return Void();
+}
+
+Return<void> RadioConfig::setSimSlotsMapping(int32_t /* serial */,
+                                             const hidl_vec<uint32_t>& /* slotMap */) {
+    RadioResponseInfo info;
+    mRadioConfigResponse->setSimSlotsMappingResponse(info);
+    return Void();
+}
+
+// Methods from ::android::hardware::radio::config::V1_1::IRadioConfig follow.
+Return<void> RadioConfig::getPhoneCapability(int32_t /* serial */) {
+    V1_1::PhoneCapability phoneCapability;
+    RadioResponseInfo info;
+    mRadioConfigResponseV1_1->getPhoneCapabilityResponse(info, phoneCapability);
+    return Void();
+}
+
+Return<void> RadioConfig::setPreferredDataModem(int32_t /* serial */, uint8_t /* modemId */) {
+    RadioResponseInfo info;
+    mRadioConfigResponseV1_1->setPreferredDataModemResponse(info);
+    return Void();
+}
+
+Return<void> RadioConfig::setModemsConfig(int32_t /* serial */,
+                                          const V1_1::ModemsConfig& /* modemsConfig */) {
+    RadioResponseInfo info;
+    mRadioConfigResponseV1_1->setModemsConfigResponse(info);
+    return Void();
+}
+
+Return<void> RadioConfig::getModemsConfig(int32_t /* serial */) {
+    V1_1::ModemsConfig modemsConfig;
+    RadioResponseInfo info;
+    mRadioConfigResponseV1_1->getModemsConfigResponse(info, modemsConfig);
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_3
+}  // namespace config
+}  // namespace radio
+}  // namespace hardware
+}  // namespace android
diff --git a/radio/config/1.3/default/RadioConfig.h b/radio/config/1.3/default/RadioConfig.h
new file mode 100644
index 0000000..00585e6
--- /dev/null
+++ b/radio/config/1.3/default/RadioConfig.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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_RADIO_CONFIG_V1_3_RADIOCONFIG_H
+#define ANDROID_HARDWARE_RADIO_CONFIG_V1_3_RADIOCONFIG_H
+
+#include <android/hardware/radio/config/1.3/IRadioConfig.h>
+#include <android/hardware/radio/config/1.3/IRadioConfigIndication.h>
+#include <android/hardware/radio/config/1.3/IRadioConfigResponse.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace radio {
+namespace config {
+namespace V1_3 {
+namespace implementation {
+
+using namespace ::android::hardware::radio::config;
+
+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;
+
+struct RadioConfig : public V1_3::IRadioConfig {
+    sp<V1_0::IRadioConfigResponse> mRadioConfigResponse;
+    sp<V1_0::IRadioConfigIndication> mRadioConfigIndication;
+    sp<V1_1::IRadioConfigResponse> mRadioConfigResponseV1_1;
+    sp<V1_1::IRadioConfigIndication> mRadioConfigIndicationV1_1;
+    sp<V1_2::IRadioConfigResponse> mRadioConfigResponseV1_2;
+    sp<V1_2::IRadioConfigIndication> mRadioConfigIndicationV1_2;
+    sp<V1_3::IRadioConfigResponse> mRadioConfigResponseV1_3;
+    sp<V1_3::IRadioConfigIndication> mRadioConfigIndicationV1_3;
+
+    // Methods from ::android::hardware::radio::config::V1_0::IRadioConfig follow.
+    Return<void> setResponseFunctions(
+            const sp<V1_0::IRadioConfigResponse>& radioConfigResponse,
+            const sp<V1_0::IRadioConfigIndication>& radioConfigIndication);
+    Return<void> getSimSlotsStatus(int32_t serial);
+    Return<void> setSimSlotsMapping(int32_t serial, const hidl_vec<uint32_t>& slotMap);
+
+    // Methods from ::android::hardware::radio::config::V1_1::IRadioConfig follow.
+    Return<void> getPhoneCapability(int32_t serial);
+    Return<void> setPreferredDataModem(int32_t serial, uint8_t modemId);
+    Return<void> setModemsConfig(int32_t serial, const V1_1::ModemsConfig& modemsConfig);
+    Return<void> getModemsConfig(int32_t serial);
+};
+
+}  // namespace implementation
+}  // namespace V1_3
+}  // namespace config
+}  // namespace radio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_RADIO_CONFIG_V1_3_RADIOCONFIG_H
diff --git a/radio/config/1.3/default/RadioConfigIndication.cpp b/radio/config/1.3/default/RadioConfigIndication.cpp
new file mode 100644
index 0000000..eb77a48
--- /dev/null
+++ b/radio/config/1.3/default/RadioConfigIndication.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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 "RadioConfigIndication.h"
+
+namespace android {
+namespace hardware {
+namespace radio {
+namespace config {
+namespace V1_3 {
+namespace implementation {
+
+using namespace ::android::hardware::radio::V1_0;
+using namespace ::android::hardware::radio::config::V1_0;
+using namespace ::android::hardware::radio::config::V1_2;
+
+// Methods from ::android::hardware::radio::config::V1_0::IRadioConfigIndication follow.
+Return<void> RadioConfigIndication::simSlotsStatusChanged(
+        RadioIndicationType /* type */, const hidl_vec<V1_0::SimSlotStatus>& /* slotStatus */) {
+    // TODO implement
+    return Void();
+}
+
+// Methods from ::android::hardware::radio::config::V1_2::IRadioConfigIndication follow.
+Return<void> RadioConfigIndication::simSlotsStatusChanged_1_2(
+        RadioIndicationType /* type */, const hidl_vec<V1_2::SimSlotStatus>& /* slotStatus */) {
+    // TODO implement
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_3
+}  // namespace config
+}  // namespace radio
+}  // namespace hardware
+}  // namespace android
diff --git a/radio/config/1.3/default/RadioConfigIndication.h b/radio/config/1.3/default/RadioConfigIndication.h
new file mode 100644
index 0000000..3697492
--- /dev/null
+++ b/radio/config/1.3/default/RadioConfigIndication.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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_RADIO_CONFIG_V1_3_RADIOCONFIGINDICATION_H
+#define ANDROID_HARDWARE_RADIO_CONFIG_V1_3_RADIOCONFIGINDICATION_H
+
+#include <android/hardware/radio/config/1.3/IRadioConfigIndication.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace radio {
+namespace config {
+namespace V1_3 {
+namespace implementation {
+
+using namespace ::android::hardware::radio::V1_0;
+using namespace ::android::hardware::radio::config;
+
+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;
+
+struct RadioConfigIndication : public IRadioConfigIndication {
+    // Methods from ::android::hardware::radio::config::V1_0::IRadioConfigIndication follow.
+    Return<void> simSlotsStatusChanged(RadioIndicationType type,
+                                       const hidl_vec<V1_0::SimSlotStatus>& slotStatus) override;
+
+    // Methods from ::android::hardware::radio::config::V1_2::IRadioConfigIndication follow.
+    Return<void> simSlotsStatusChanged_1_2(
+            RadioIndicationType type, const hidl_vec<V1_2::SimSlotStatus>& slotStatus) override;
+};
+
+}  // namespace implementation
+}  // namespace V1_3
+}  // namespace config
+}  // namespace radio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_RADIO_CONFIG_V1_3_RADIOCONFIGINDICATION_H
diff --git a/radio/config/1.3/default/RadioConfigResponse.cpp b/radio/config/1.3/default/RadioConfigResponse.cpp
new file mode 100644
index 0000000..48e81da
--- /dev/null
+++ b/radio/config/1.3/default/RadioConfigResponse.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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 "RadioConfigResponse.h"
+
+namespace android {
+namespace hardware {
+namespace radio {
+namespace config {
+namespace V1_3 {
+namespace implementation {
+
+using namespace ::android::hardware::radio::V1_0;
+using namespace ::android::hardware::radio::config::V1_0;
+using namespace ::android::hardware::radio::config::V1_1;
+using namespace ::android::hardware::radio::config::V1_2;
+
+// Methods from ::android::hardware::radio::config::V1_0::IRadioConfigResponse follow.
+Return<void> RadioConfigResponse::getSimSlotsStatusResponse(
+        const RadioResponseInfo& /* info */,
+        const hidl_vec<V1_0::SimSlotStatus>& /* slotStatus */) {
+    // TODO implement
+    return Void();
+}
+
+Return<void> RadioConfigResponse::setSimSlotsMappingResponse(const RadioResponseInfo& /* info */) {
+    // TODO implement
+    return Void();
+}
+
+// Methods from ::android::hardware::radio::config::V1_1::IRadioConfigResponse follow.
+Return<void> RadioConfigResponse::getPhoneCapabilityResponse(
+        const RadioResponseInfo& /* info */, const V1_1::PhoneCapability& /* phoneCapability */) {
+    // TODO implement
+    return Void();
+}
+
+Return<void> RadioConfigResponse::setPreferredDataModemResponse(
+        const RadioResponseInfo& /* info */) {
+    // TODO implement
+    return Void();
+}
+
+Return<void> RadioConfigResponse::setModemsConfigResponse(const RadioResponseInfo& /* info */) {
+    // TODO implement
+    return Void();
+}
+
+Return<void> RadioConfigResponse::getModemsConfigResponse(
+        const RadioResponseInfo& /* info */, const V1_1::ModemsConfig& /* modemsConfig */) {
+    // TODO implement
+    return Void();
+}
+
+// Methods from ::android::hardware::radio::config::V1_2::IRadioConfigResponse follow.
+Return<void> RadioConfigResponse::getSimSlotsStatusResponse_1_2(
+        const RadioResponseInfo& /* info */,
+        const hidl_vec<V1_2::SimSlotStatus>& /* slotStatus */) {
+    // TODO implement
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_3
+}  // namespace config
+}  // namespace radio
+}  // namespace hardware
+}  // namespace android
diff --git a/radio/config/1.3/default/RadioConfigResponse.h b/radio/config/1.3/default/RadioConfigResponse.h
new file mode 100644
index 0000000..0f0033f
--- /dev/null
+++ b/radio/config/1.3/default/RadioConfigResponse.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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_RADIO_CONFIG_V1_3_RADIOCONFIGRESPONSE_H
+#define ANDROID_HARDWARE_RADIO_CONFIG_V1_3_RADIOCONFIGRESPONSE_H
+
+#include <android/hardware/radio/config/1.3/IRadioConfigResponse.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace radio {
+namespace config {
+namespace V1_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;
+
+struct RadioConfigResponse : public IRadioConfigResponse {
+    // Methods from ::android::hardware::radio::config::V1_0::IRadioConfigResponse follow.
+    Return<void> getSimSlotsStatusResponse(
+            const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+            const hidl_vec<::android::hardware::radio::config::V1_0::SimSlotStatus>& slotStatus)
+            override;
+    Return<void> setSimSlotsMappingResponse(
+            const ::android::hardware::radio::V1_0::RadioResponseInfo& info) override;
+
+    // Methods from ::android::hardware::radio::config::V1_1::IRadioConfigResponse follow.
+    Return<void> getPhoneCapabilityResponse(
+            const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+            const ::android::hardware::radio::config::V1_1::PhoneCapability& phoneCapability)
+            override;
+    Return<void> setPreferredDataModemResponse(
+            const ::android::hardware::radio::V1_0::RadioResponseInfo& info) override;
+    Return<void> setModemsConfigResponse(
+            const ::android::hardware::radio::V1_0::RadioResponseInfo& info) override;
+    Return<void> getModemsConfigResponse(
+            const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+            const ::android::hardware::radio::config::V1_1::ModemsConfig& modemsConfig) override;
+
+    // Methods from ::android::hardware::radio::config::V1_2::IRadioConfigResponse follow.
+    Return<void> getSimSlotsStatusResponse_1_2(
+            const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+            const hidl_vec<::android::hardware::radio::config::V1_2::SimSlotStatus>& slotStatus)
+            override;
+
+    // Methods from ::android::hidl::base::V1_0::IBase follow.
+};
+
+}  // namespace implementation
+}  // namespace V1_3
+}  // namespace config
+}  // namespace radio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_RADIO_CONFIG_V1_3_RADIOCONFIGRESPONSE_H
diff --git a/radio/config/1.3/default/android.hardware.radio.config@1.3-service.rc b/radio/config/1.3/default/android.hardware.radio.config@1.3-service.rc
new file mode 100644
index 0000000..6df9b52
--- /dev/null
+++ b/radio/config/1.3/default/android.hardware.radio.config@1.3-service.rc
@@ -0,0 +1,7 @@
+service vendor.radio-config-hal-1-3 /vendor/bin/hw/android.hardware.radio.config@1.3-service
+    interface android.hardware.radio.config@1.0::IRadioConfig default
+    interface android.hardware.radio.config@1.1::IRadioConfig default
+    interface android.hardware.radio.config@1.3::IRadioConfig default
+    class hal
+    user system
+    group system
diff --git a/radio/config/1.3/default/radio-config-default.xml b/radio/config/1.3/default/radio-config-default.xml
new file mode 100644
index 0000000..72f363e
--- /dev/null
+++ b/radio/config/1.3/default/radio-config-default.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** 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.
+*/
+-->
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.radio.config</name>
+        <transport>hwbinder</transport>
+        <version>1.3</version>
+        <interface>
+            <name>IRadioConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/radio/config/1.3/default/service.cpp b/radio/config/1.3/default/service.cpp
new file mode 100644
index 0000000..b1e6736
--- /dev/null
+++ b/radio/config/1.3/default/service.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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 "android.hardware.radio.config@1.3-service"
+
+#include <android/hardware/radio/config/1.3/IRadioConfig.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "RadioConfig.h"
+
+using android::OK;
+using android::sp;
+using android::status_t;
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::radio::config::V1_3::IRadioConfig;
+using android::hardware::radio::config::V1_3::implementation::RadioConfig;
+
+int main() {
+    configureRpcThreadpool(1, true);
+    sp<IRadioConfig> radioConfig = new RadioConfig;
+    const status_t status = radioConfig->registerAsService();
+    ALOGW_IF(status != OK, "Could not register IRadioConfig 1.3");
+    ALOGD("Default service is ready.");
+
+    joinRpcThreadpool();
+    return 1;
+}
diff --git a/vibrator/1.4/IVibratorCallback.hal b/radio/config/1.3/types.hal
similarity index 85%
copy from vibrator/1.4/IVibratorCallback.hal
copy to radio/config/1.3/types.hal
index 76281bc..866002a 100644
--- a/vibrator/1.4/IVibratorCallback.hal
+++ b/radio/config/1.3/types.hal
@@ -14,8 +14,4 @@
  * limitations under the License.
  */
 
-package android.hardware.vibrator@1.4;
-
-interface IVibratorCallback {
-    oneway onComplete();
-};
+package android.hardware.radio.config@1.3;
diff --git a/radio/config/1.3/vts/functional/Android.bp b/radio/config/1.3/vts/functional/Android.bp
new file mode 100644
index 0000000..6b28faf
--- /dev/null
+++ b/radio/config/1.3/vts/functional/Android.bp
@@ -0,0 +1,35 @@
+//
+// 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: "VtsHalRadioConfigV1_3TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "radio_config_hidl_hal_api.cpp",
+        "radio_config_hidl_hal_test.cpp",
+        "radio_config_response.cpp",
+        "VtsHalRadioConfigV1_3TargetTest.cpp",
+    ],
+    static_libs: [
+        "RadioVtsTestUtilBase",
+        "android.hardware.radio.config@1.0",
+        "android.hardware.radio.config@1.1",
+        "android.hardware.radio.config@1.2",
+        "android.hardware.radio.config@1.3",
+    ],
+    header_libs: ["radio.util.header@1.0"],
+    test_suites: ["general-tests", "vts-core"],
+}
diff --git a/vibrator/1.4/types.hal b/radio/config/1.3/vts/functional/VtsHalRadioConfigV1_3TargetTest.cpp
similarity index 65%
copy from vibrator/1.4/types.hal
copy to radio/config/1.3/vts/functional/VtsHalRadioConfigV1_3TargetTest.cpp
index acc49b1..3bacacf 100644
--- a/vibrator/1.4/types.hal
+++ b/radio/config/1.3/vts/functional/VtsHalRadioConfigV1_3TargetTest.cpp
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-package android.hardware.vibrator@1.4;
+#include <radio_config_hidl_hal_utils.h>
 
-enum Capabilities : uint32_t {
-    ON_COMPLETION_CALLBACK = 1 << 0,
-    PERFORM_COMPLETION_CALLBACK = 1 << 1,
-};
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, RadioConfigHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+                ::android::hardware::radio::config::V1_3::IRadioConfig::descriptor)),
+        android::hardware::PrintInstanceNameToString);
diff --git a/vibrator/1.4/IVibratorCallback.hal b/radio/config/1.3/vts/functional/radio_config_hidl_hal_api.cpp
similarity index 85%
rename from vibrator/1.4/IVibratorCallback.hal
rename to radio/config/1.3/vts/functional/radio_config_hidl_hal_api.cpp
index 76281bc..07e9ede 100644
--- a/vibrator/1.4/IVibratorCallback.hal
+++ b/radio/config/1.3/vts/functional/radio_config_hidl_hal_api.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-package android.hardware.vibrator@1.4;
+#include <radio_config_hidl_hal_utils.h>
 
-interface IVibratorCallback {
-    oneway onComplete();
-};
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
diff --git a/radio/config/1.3/vts/functional/radio_config_hidl_hal_test.cpp b/radio/config/1.3/vts/functional/radio_config_hidl_hal_test.cpp
new file mode 100644
index 0000000..dbb4bf4
--- /dev/null
+++ b/radio/config/1.3/vts/functional/radio_config_hidl_hal_test.cpp
@@ -0,0 +1,58 @@
+/*
+ * 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 <radio_config_hidl_hal_utils.h>
+
+void RadioConfigHidlTest::SetUp() {
+    radioConfig = ::android::hardware::radio::config::V1_3::IRadioConfig::getService(GetParam());
+    ASSERT_NE(nullptr, radioConfig.get());
+
+    radioConfigRsp = new (std::nothrow) RadioConfigResponse(*this);
+    ASSERT_NE(nullptr, radioConfigRsp.get());
+
+    count_ = 0;
+
+    radioConfig->setResponseFunctions(radioConfigRsp, nullptr);
+}
+
+/*
+ * Notify that the response message is received.
+ */
+void RadioConfigHidlTest::notify(int receivedSerial) {
+    std::unique_lock<std::mutex> lock(mtx_);
+    if (serial == receivedSerial) {
+        count_++;
+        cv_.notify_one();
+    }
+}
+
+/*
+ * Wait till the response message is notified or till TIMEOUT_PERIOD.
+ */
+std::cv_status RadioConfigHidlTest::wait() {
+    std::unique_lock<std::mutex> lock(mtx_);
+
+    std::cv_status status = std::cv_status::no_timeout;
+    auto now = std::chrono::system_clock::now();
+    while (count_ == 0) {
+        status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+        if (status == std::cv_status::timeout) {
+            return status;
+        }
+    }
+    count_--;
+    return status;
+}
diff --git a/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h b/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h
new file mode 100644
index 0000000..9b78c04
--- /dev/null
+++ b/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h
@@ -0,0 +1,128 @@
+/*
+ * 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 <android-base/logging.h>
+
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+
+#include <android/hardware/radio/config/1.3/IRadioConfig.h>
+#include <android/hardware/radio/config/1.3/IRadioConfigIndication.h>
+#include <android/hardware/radio/config/1.3/IRadioConfigResponse.h>
+#include <android/hardware/radio/config/1.3/types.h>
+
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include "vts_test_util.h"
+
+using namespace ::android::hardware::radio::config::V1_1;
+using namespace ::android::hardware::radio::config::V1_2;
+using namespace ::android::hardware::radio::config::V1_3;
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+using ::android::hardware::radio::V1_0::RadioResponseInfo;
+using ::android::hardware::radio::V1_0::RadioResponseType;
+
+#define TIMEOUT_PERIOD 75
+
+class RadioConfigHidlTest;
+
+/* Callback class for radio config response */
+class RadioConfigResponse : public ::android::hardware::radio::config::V1_3::IRadioConfigResponse {
+  protected:
+    RadioConfigHidlTest& parent;
+
+  public:
+    RadioResponseInfo rspInfo;
+    PhoneCapability phoneCap;
+
+    RadioConfigResponse(RadioConfigHidlTest& parent);
+    virtual ~RadioConfigResponse() = default;
+
+    /* 1.0 Api */
+    Return<void> getSimSlotsStatusResponse(
+            const RadioResponseInfo& info,
+            const hidl_vec<::android::hardware::radio::config::V1_0::SimSlotStatus>& slotStatus);
+
+    Return<void> setSimSlotsMappingResponse(const RadioResponseInfo& info);
+
+    /* 1.1 Api */
+    Return<void> getPhoneCapabilityResponse(const RadioResponseInfo& info,
+                                            const PhoneCapability& phoneCapability);
+
+    Return<void> setPreferredDataModemResponse(const RadioResponseInfo& info);
+
+    Return<void> getModemsConfigResponse(const RadioResponseInfo& info,
+                                         const ModemsConfig& mConfig);
+
+    Return<void> setModemsConfigResponse(const RadioResponseInfo& info);
+
+    /* 1.2 Api */
+    Return<void> getSimSlotsStatusResponse_1_2(const RadioResponseInfo& info,
+                                               const hidl_vec<SimSlotStatus>& slotStatus);
+};
+
+/* Callback class for radio config indication */
+class RadioConfigIndication
+    : public ::android::hardware::radio::config::V1_3::IRadioConfigIndication {
+  protected:
+    RadioConfigHidlTest& parent;
+
+  public:
+    RadioConfigIndication(RadioConfigHidlTest& parent);
+    virtual ~RadioConfigIndication() = default;
+
+    /* 1.2 Api */
+    Return<void> simSlotsStatusChanged_1_2(
+            ::android::hardware::radio::V1_0::RadioIndicationType type,
+            const hidl_vec<SimSlotStatus>& slotStatus);
+};
+
+// The main test class for Radio config HIDL.
+class RadioConfigHidlTest : public ::testing::TestWithParam<std::string> {
+  protected:
+    std::mutex mtx_;
+    std::condition_variable cv_;
+    int count_;
+
+  public:
+    virtual void SetUp() override;
+
+    /* Used as a mechanism to inform the test about data/event callback */
+    void notify(int receivedSerial);
+
+    /* Test code calls this function to wait for response */
+    std::cv_status wait();
+
+    void updateSimCardStatus();
+
+    /* Serial number for radio request */
+    int serial;
+
+    /* radio config service handle */
+    sp<::android::hardware::radio::config::V1_3::IRadioConfig> radioConfig;
+
+    /* radio config response handle */
+    sp<RadioConfigResponse> radioConfigRsp;
+};
diff --git a/radio/config/1.3/vts/functional/radio_config_response.cpp b/radio/config/1.3/vts/functional/radio_config_response.cpp
new file mode 100644
index 0000000..1ca960e
--- /dev/null
+++ b/radio/config/1.3/vts/functional/radio_config_response.cpp
@@ -0,0 +1,65 @@
+/*
+ * 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 <radio_config_hidl_hal_utils.h>
+
+using ::android::hardware::radio::V1_0::RadioResponseInfo;
+
+// SimSlotStatus slotStatus;
+
+RadioConfigResponse::RadioConfigResponse(RadioConfigHidlTest& parent) : parent(parent) {}
+
+/* 1.0 Apis */
+Return<void> RadioConfigResponse::getSimSlotsStatusResponse(
+        const RadioResponseInfo& /* info */,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::config::V1_0::SimSlotStatus>& /* slotStatus */) {
+    return Void();
+}
+
+Return<void> RadioConfigResponse::setSimSlotsMappingResponse(const RadioResponseInfo& /* info */) {
+    return Void();
+}
+
+/* 1.1 Apis */
+Return<void> RadioConfigResponse::getPhoneCapabilityResponse(
+        const RadioResponseInfo& info, const PhoneCapability& phoneCapability) {
+    rspInfo = info;
+    phoneCap = phoneCapability;
+    parent.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioConfigResponse::setPreferredDataModemResponse(
+        const RadioResponseInfo& /* info */) {
+    return Void();
+}
+
+Return<void> RadioConfigResponse::getModemsConfigResponse(const RadioResponseInfo& /* info */,
+                                                          const ModemsConfig& /* mConfig */) {
+    return Void();
+}
+
+Return<void> RadioConfigResponse::setModemsConfigResponse(const RadioResponseInfo& /* info */) {
+    return Void();
+}
+
+/* 1.2 Apis */
+Return<void> RadioConfigResponse::getSimSlotsStatusResponse_1_2(
+        const RadioResponseInfo& /* info */,
+        const ::android::hardware::hidl_vec<SimSlotStatus>& /* slotStatus */) {
+    return Void();
+}
\ No newline at end of file
diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
index 7bb992b..1167fd4 100644
--- a/sensors/1.0/vts/functional/Android.bp
+++ b/sensors/1.0/vts/functional/Android.bp
@@ -31,6 +31,6 @@
         "android.hardware.sensors@1.0",
         "VtsHalSensorsTargetTestUtils",
     ],
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "vts-core"],
 }
 
diff --git a/sensors/1.0/vts/functional/AndroidTest.xml b/sensors/1.0/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..fb0d64c
--- /dev/null
+++ b/sensors/1.0/vts/functional/AndroidTest.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalSensorsV1_0TargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="stop"/>
+        <option name="teardown-command" value="start"/>
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="VtsHalSensorsV1_0TargetTest->/data/local/tmp/VtsHalSensorsV1_0TargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-timeout" value="900000" />
+        <option name="runtime-hint" value="300000"/>
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalSensorsV1_0TargetTest" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
index 00207b1..1e5e886 100644
--- a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
+++ b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
@@ -35,8 +35,7 @@
         // this do ... while is for easy error handling
         do {
             step = "getService()";
-            sensors = ISensors::getService(
-                SensorsHidlEnvironmentV1_0::Instance()->getServiceName<ISensors>());
+            sensors = ISensors::getService(mServiceName);
             if (sensors == nullptr) {
                 break;
             }
diff --git a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
index 0a9e59f..29bfa50 100644
--- a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
+++ b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
@@ -32,23 +32,14 @@
 class SensorsHidlEnvironmentV1_0 : public SensorsHidlEnvironmentBase {
    public:
     using Event = ::android::hardware::sensors::V1_0::Event;
-    // get the test environment singleton
-    static SensorsHidlEnvironmentV1_0* Instance() {
-        static SensorsHidlEnvironmentV1_0* instance = new SensorsHidlEnvironmentV1_0();
-        return instance;
-    }
+    SensorsHidlEnvironmentV1_0(const std::string& service_name)
+        : SensorsHidlEnvironmentBase(service_name) {}
 
-    virtual void registerTestServices() override {
-        registerTestService<android::hardware::sensors::V1_0::ISensors>();
-    }
-
-   private:
+  private:
     friend SensorsHidlTest;
     // sensors hidl service
     sp<android::hardware::sensors::V1_0::ISensors> sensors;
 
-    SensorsHidlEnvironmentV1_0() {}
-
     bool resetHal() override;
     void startPollingThread() override;
     static void pollingThread(SensorsHidlEnvironmentV1_0* env, std::atomic_bool& stop);
diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
index 5453ef6..2cad54d 100644
--- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
+++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
@@ -19,6 +19,8 @@
 
 #include <android/hardware/sensors/1.0/ISensors.h>
 #include <android/hardware/sensors/1.0/types.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 #include <log/log.h>
 #include <utils/SystemClock.h>
 
@@ -33,7 +35,17 @@
 // The main test class for SENSORS HIDL HAL.
 
 class SensorsHidlTest : public SensorsHidlTestBase {
-   protected:
+  public:
+    virtual void SetUp() override {
+        mEnvironment = new SensorsHidlEnvironmentV1_0(GetParam());
+        mEnvironment->HidlSetUp();
+        // Ensure that we have a valid environment before performing tests
+        ASSERT_NE(S(), nullptr);
+    }
+
+    virtual void TearDown() override { mEnvironment->HidlTearDown(); }
+
+  protected:
     SensorInfo defaultSensorByType(SensorType type) override;
     std::vector<SensorInfo> getSensorsList();
     // implementation wrapper
@@ -66,11 +78,13 @@
         return S()->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb);
     }
 
-    inline sp<ISensors>& S() { return SensorsHidlEnvironmentV1_0::Instance()->sensors; }
+    inline sp<ISensors>& S() { return mEnvironment->sensors; }
 
-    SensorsHidlEnvironmentBase* getEnvironment() override {
-        return SensorsHidlEnvironmentV1_0::Instance();
-    }
+    SensorsHidlEnvironmentBase* getEnvironment() override { return mEnvironment; }
+
+  private:
+    // Test environment for sensors HAL.
+    SensorsHidlEnvironmentV1_0* mEnvironment;
 };
 
 Return<Result> SensorsHidlTest::activate(int32_t sensorHandle, bool enabled) {
@@ -133,55 +147,52 @@
 }
 
 // Test if sensor list returned is valid
-TEST_F(SensorsHidlTest, SensorListValid) {
-  S()->getSensorsList(
-      [&] (const auto &list) {
+TEST_P(SensorsHidlTest, SensorListValid) {
+    S()->getSensorsList([&](const auto& list) {
         const size_t count = list.size();
         for (size_t i = 0; i < count; ++i) {
-          const auto &s = list[i];
-          SCOPED_TRACE(::testing::Message() << i << "/" << count << ": "
-                       << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
-                       << s.sensorHandle << std::dec
-                       << " type=" << static_cast<int>(s.type)
-                       << " name=" << s.name);
+            const auto& s = list[i];
+            SCOPED_TRACE(::testing::Message()
+                         << i << "/" << count << ": "
+                         << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+                         << s.sensorHandle << std::dec << " type=" << static_cast<int>(s.type)
+                         << " name=" << s.name);
 
-          // Test non-empty type string
-          EXPECT_FALSE(s.typeAsString.empty());
+            // Test non-empty type string
+            EXPECT_FALSE(s.typeAsString.empty());
 
-          // Test defined type matches defined string type
-          EXPECT_NO_FATAL_FAILURE(assertTypeMatchStringType(s.type, s.typeAsString));
+            // Test defined type matches defined string type
+            EXPECT_NO_FATAL_FAILURE(assertTypeMatchStringType(s.type, s.typeAsString));
 
-          // Test if all sensor has name and vendor
-          EXPECT_FALSE(s.name.empty());
-          EXPECT_FALSE(s.vendor.empty());
+            // Test if all sensor has name and vendor
+            EXPECT_FALSE(s.name.empty());
+            EXPECT_FALSE(s.vendor.empty());
 
-          // Test power > 0, maxRange > 0
-          EXPECT_LE(0, s.power);
-          EXPECT_LT(0, s.maxRange);
+            // Test power > 0, maxRange > 0
+            EXPECT_LE(0, s.power);
+            EXPECT_LT(0, s.maxRange);
 
-          // Info type, should have no sensor
-          EXPECT_FALSE(
-              s.type == SensorType::ADDITIONAL_INFO
-              || s.type == SensorType::META_DATA);
+            // Info type, should have no sensor
+            EXPECT_FALSE(s.type == SensorType::ADDITIONAL_INFO || s.type == SensorType::META_DATA);
 
-          // Test fifoMax >= fifoReserved
-          EXPECT_GE(s.fifoMaxEventCount, s.fifoReservedEventCount)
-              << "max=" << s.fifoMaxEventCount << " reserved=" << s.fifoReservedEventCount;
+            // Test fifoMax >= fifoReserved
+            EXPECT_GE(s.fifoMaxEventCount, s.fifoReservedEventCount)
+                    << "max=" << s.fifoMaxEventCount << " reserved=" << s.fifoReservedEventCount;
 
-          // Test Reporting mode valid
-          EXPECT_NO_FATAL_FAILURE(assertTypeMatchReportMode(s.type, extractReportMode(s.flags)));
+            // Test Reporting mode valid
+            EXPECT_NO_FATAL_FAILURE(assertTypeMatchReportMode(s.type, extractReportMode(s.flags)));
 
-          // Test min max are in the right order
-          EXPECT_LE(s.minDelay, s.maxDelay);
-          // Test min/max delay matches reporting mode
-          EXPECT_NO_FATAL_FAILURE(
-              assertDelayMatchReportMode(s.minDelay, s.maxDelay, extractReportMode(s.flags)));
+            // Test min max are in the right order
+            EXPECT_LE(s.minDelay, s.maxDelay);
+            // Test min/max delay matches reporting mode
+            EXPECT_NO_FATAL_FAILURE(
+                    assertDelayMatchReportMode(s.minDelay, s.maxDelay, extractReportMode(s.flags)));
         }
-      });
+    });
 }
 
 // Test if sensor list returned is valid
-TEST_F(SensorsHidlTest, SetOperationMode) {
+TEST_P(SensorsHidlTest, SetOperationMode) {
     std::vector<SensorInfo> sensorList = getSensorsList();
 
     bool needOperationModeSupport =
@@ -199,7 +210,7 @@
 }
 
 // Test if sensor list returned is valid
-TEST_F(SensorsHidlTest, InjectSensorEventData) {
+TEST_P(SensorsHidlTest, InjectSensorEventData) {
     std::vector<SensorInfo> sensorList = getSensorsList();
     std::vector<SensorInfo> sensorSupportInjection;
 
@@ -244,224 +255,202 @@
 }
 
 // Test if sensor hal can do UI speed accelerometer streaming properly
-TEST_F(SensorsHidlTest, AccelerometerStreamingOperationSlow) {
-  testStreamingOperation(SensorType::ACCELEROMETER,
-                         std::chrono::milliseconds(200),
-                         std::chrono::seconds(5),
-                         sAccelNormChecker);
+TEST_P(SensorsHidlTest, AccelerometerStreamingOperationSlow) {
+    testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(200),
+                           std::chrono::seconds(5), sAccelNormChecker);
 }
 
 // Test if sensor hal can do normal speed accelerometer streaming properly
-TEST_F(SensorsHidlTest, AccelerometerStreamingOperationNormal) {
-  testStreamingOperation(SensorType::ACCELEROMETER,
-                         std::chrono::milliseconds(20),
-                         std::chrono::seconds(5),
-                         sAccelNormChecker);
+TEST_P(SensorsHidlTest, AccelerometerStreamingOperationNormal) {
+    testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(20),
+                           std::chrono::seconds(5), sAccelNormChecker);
 }
 
 // Test if sensor hal can do game speed accelerometer streaming properly
-TEST_F(SensorsHidlTest, AccelerometerStreamingOperationFast) {
-  testStreamingOperation(SensorType::ACCELEROMETER,
-                         std::chrono::milliseconds(5),
-                         std::chrono::seconds(5),
-                         sAccelNormChecker);
+TEST_P(SensorsHidlTest, AccelerometerStreamingOperationFast) {
+    testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(5),
+                           std::chrono::seconds(5), sAccelNormChecker);
 }
 
 // Test if sensor hal can do UI speed gyroscope streaming properly
-TEST_F(SensorsHidlTest, GyroscopeStreamingOperationSlow) {
-  testStreamingOperation(SensorType::GYROSCOPE,
-                         std::chrono::milliseconds(200),
-                         std::chrono::seconds(5),
-                         sGyroNormChecker);
+TEST_P(SensorsHidlTest, GyroscopeStreamingOperationSlow) {
+    testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(200),
+                           std::chrono::seconds(5), sGyroNormChecker);
 }
 
 // Test if sensor hal can do normal speed gyroscope streaming properly
-TEST_F(SensorsHidlTest, GyroscopeStreamingOperationNormal) {
-  testStreamingOperation(SensorType::GYROSCOPE,
-                         std::chrono::milliseconds(20),
-                         std::chrono::seconds(5),
-                         sGyroNormChecker);
+TEST_P(SensorsHidlTest, GyroscopeStreamingOperationNormal) {
+    testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(20),
+                           std::chrono::seconds(5), sGyroNormChecker);
 }
 
 // Test if sensor hal can do game speed gyroscope streaming properly
-TEST_F(SensorsHidlTest, GyroscopeStreamingOperationFast) {
-  testStreamingOperation(SensorType::GYROSCOPE,
-                         std::chrono::milliseconds(5),
-                         std::chrono::seconds(5),
-                         sGyroNormChecker);
+TEST_P(SensorsHidlTest, GyroscopeStreamingOperationFast) {
+    testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(5),
+                           std::chrono::seconds(5), sGyroNormChecker);
 }
 
 // Test if sensor hal can do UI speed magnetometer streaming properly
-TEST_F(SensorsHidlTest, MagnetometerStreamingOperationSlow) {
-  testStreamingOperation(SensorType::MAGNETIC_FIELD,
-                         std::chrono::milliseconds(200),
-                         std::chrono::seconds(5),
-                         NullChecker());
+TEST_P(SensorsHidlTest, MagnetometerStreamingOperationSlow) {
+    testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(200),
+                           std::chrono::seconds(5), NullChecker());
 }
 
 // Test if sensor hal can do normal speed magnetometer streaming properly
-TEST_F(SensorsHidlTest, MagnetometerStreamingOperationNormal) {
-  testStreamingOperation(SensorType::MAGNETIC_FIELD,
-                         std::chrono::milliseconds(20),
-                         std::chrono::seconds(5),
-                         NullChecker());
+TEST_P(SensorsHidlTest, MagnetometerStreamingOperationNormal) {
+    testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(20),
+                           std::chrono::seconds(5), NullChecker());
 }
 
 // Test if sensor hal can do game speed magnetometer streaming properly
-TEST_F(SensorsHidlTest, MagnetometerStreamingOperationFast) {
-  testStreamingOperation(SensorType::MAGNETIC_FIELD,
-                         std::chrono::milliseconds(5),
-                         std::chrono::seconds(5),
-                         NullChecker());
+TEST_P(SensorsHidlTest, MagnetometerStreamingOperationFast) {
+    testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(5),
+                           std::chrono::seconds(5), NullChecker());
 }
 
 // Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active
-TEST_F(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) {
-  testSamplingRateHotSwitchOperation(SensorType::ACCELEROMETER);
-  testSamplingRateHotSwitchOperation(SensorType::ACCELEROMETER, false /*fastToSlow*/);
+TEST_P(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) {
+    testSamplingRateHotSwitchOperation(SensorType::ACCELEROMETER);
+    testSamplingRateHotSwitchOperation(SensorType::ACCELEROMETER, false /*fastToSlow*/);
 }
 
 // Test if sensor hal can do gyroscope sampling rate switch properly when sensor is active
-TEST_F(SensorsHidlTest, GyroscopeSamplingPeriodHotSwitchOperation) {
-  testSamplingRateHotSwitchOperation(SensorType::GYROSCOPE);
-  testSamplingRateHotSwitchOperation(SensorType::GYROSCOPE, false /*fastToSlow*/);
+TEST_P(SensorsHidlTest, GyroscopeSamplingPeriodHotSwitchOperation) {
+    testSamplingRateHotSwitchOperation(SensorType::GYROSCOPE);
+    testSamplingRateHotSwitchOperation(SensorType::GYROSCOPE, false /*fastToSlow*/);
 }
 
 // Test if sensor hal can do magnetometer sampling rate switch properly when sensor is active
-TEST_F(SensorsHidlTest, MagnetometerSamplingPeriodHotSwitchOperation) {
-  testSamplingRateHotSwitchOperation(SensorType::MAGNETIC_FIELD);
-  testSamplingRateHotSwitchOperation(SensorType::MAGNETIC_FIELD, false /*fastToSlow*/);
+TEST_P(SensorsHidlTest, MagnetometerSamplingPeriodHotSwitchOperation) {
+    testSamplingRateHotSwitchOperation(SensorType::MAGNETIC_FIELD);
+    testSamplingRateHotSwitchOperation(SensorType::MAGNETIC_FIELD, false /*fastToSlow*/);
 }
 
 // Test if sensor hal can do accelerometer batching properly
-TEST_F(SensorsHidlTest, AccelerometerBatchingOperation) {
-  testBatchingOperation(SensorType::ACCELEROMETER);
+TEST_P(SensorsHidlTest, AccelerometerBatchingOperation) {
+    testBatchingOperation(SensorType::ACCELEROMETER);
 }
 
 // Test if sensor hal can do gyroscope batching properly
-TEST_F(SensorsHidlTest, GyroscopeBatchingOperation) {
-  testBatchingOperation(SensorType::GYROSCOPE);
+TEST_P(SensorsHidlTest, GyroscopeBatchingOperation) {
+    testBatchingOperation(SensorType::GYROSCOPE);
 }
 
 // Test if sensor hal can do magnetometer batching properly
-TEST_F(SensorsHidlTest, MagnetometerBatchingOperation) {
-  testBatchingOperation(SensorType::MAGNETIC_FIELD);
+TEST_P(SensorsHidlTest, MagnetometerBatchingOperation) {
+    testBatchingOperation(SensorType::MAGNETIC_FIELD);
 }
 
 // Test sensor event direct report with ashmem for accel sensor at normal rate
-TEST_F(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) {
-  testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::NORMAL,
-                            sAccelNormChecker);
+TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) {
+    testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::NORMAL,
+                              sAccelNormChecker);
 }
 
 // Test sensor event direct report with ashmem for accel sensor at fast rate
-TEST_F(SensorsHidlTest, AccelerometerAshmemDirectReportOperationFast) {
-  testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::FAST,
-                            sAccelNormChecker);
+TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationFast) {
+    testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::FAST,
+                              sAccelNormChecker);
 }
 
 // Test sensor event direct report with ashmem for accel sensor at very fast rate
-TEST_F(SensorsHidlTest, AccelerometerAshmemDirectReportOperationVeryFast) {
-  testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::VERY_FAST,
-                            sAccelNormChecker);
+TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM,
+                              RateLevel::VERY_FAST, sAccelNormChecker);
 }
 
 // Test sensor event direct report with ashmem for gyro sensor at normal rate
-TEST_F(SensorsHidlTest, GyroscopeAshmemDirectReportOperationNormal) {
-  testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::NORMAL,
-                            sGyroNormChecker);
+TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationNormal) {
+    testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::NORMAL,
+                              sGyroNormChecker);
 }
 
 // Test sensor event direct report with ashmem for gyro sensor at fast rate
-TEST_F(SensorsHidlTest, GyroscopeAshmemDirectReportOperationFast) {
-  testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::FAST,
-                            sGyroNormChecker);
+TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationFast) {
+    testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::FAST,
+                              sGyroNormChecker);
 }
 
 // Test sensor event direct report with ashmem for gyro sensor at very fast rate
-TEST_F(SensorsHidlTest, GyroscopeAshmemDirectReportOperationVeryFast) {
-  testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::VERY_FAST,
-                            sGyroNormChecker);
+TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::VERY_FAST,
+                              sGyroNormChecker);
 }
 
 // Test sensor event direct report with ashmem for mag sensor at normal rate
-TEST_F(SensorsHidlTest, MagnetometerAshmemDirectReportOperationNormal) {
-  testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::NORMAL,
-                            NullChecker());
+TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationNormal) {
+    testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::NORMAL,
+                              NullChecker());
 }
 
 // Test sensor event direct report with ashmem for mag sensor at fast rate
-TEST_F(SensorsHidlTest, MagnetometerAshmemDirectReportOperationFast) {
-  testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::FAST,
-                            NullChecker());
+TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationFast) {
+    testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::FAST,
+                              NullChecker());
 }
 
 // Test sensor event direct report with ashmem for mag sensor at very fast rate
-TEST_F(SensorsHidlTest, MagnetometerAshmemDirectReportOperationVeryFast) {
-  testDirectReportOperation(
-      SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::VERY_FAST, NullChecker());
+TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM,
+                              RateLevel::VERY_FAST, NullChecker());
 }
 
 // Test sensor event direct report with gralloc for accel sensor at normal rate
-TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) {
-  testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::NORMAL,
-                            sAccelNormChecker);
+TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) {
+    testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::NORMAL,
+                              sAccelNormChecker);
 }
 
 // Test sensor event direct report with gralloc for accel sensor at fast rate
-TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationFast) {
-  testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::FAST,
-                            sAccelNormChecker);
+TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationFast) {
+    testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::FAST,
+                              sAccelNormChecker);
 }
 
 // Test sensor event direct report with gralloc for accel sensor at very fast rate
-TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationVeryFast) {
-  testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::VERY_FAST,
-                            sAccelNormChecker);
+TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC,
+                              RateLevel::VERY_FAST, sAccelNormChecker);
 }
 
 // Test sensor event direct report with gralloc for gyro sensor at normal rate
-TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) {
-  testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::NORMAL,
-                            sGyroNormChecker);
+TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) {
+    testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::NORMAL,
+                              sGyroNormChecker);
 }
 
 // Test sensor event direct report with gralloc for gyro sensor at fast rate
-TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationFast) {
-  testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::FAST,
-                            sGyroNormChecker);
+TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationFast) {
+    testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::FAST,
+                              sGyroNormChecker);
 }
 
 // Test sensor event direct report with gralloc for gyro sensor at very fast rate
-TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationVeryFast) {
-  testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::VERY_FAST,
-                            sGyroNormChecker);
+TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::VERY_FAST,
+                              sGyroNormChecker);
 }
 
 // Test sensor event direct report with gralloc for mag sensor at normal rate
-TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationNormal) {
-  testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::NORMAL,
-                            NullChecker());
+TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationNormal) {
+    testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::NORMAL,
+                              NullChecker());
 }
 
 // Test sensor event direct report with gralloc for mag sensor at fast rate
-TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationFast) {
-  testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::FAST,
-                            NullChecker());
+TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationFast) {
+    testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::FAST,
+                              NullChecker());
 }
 
 // Test sensor event direct report with gralloc for mag sensor at very fast rate
-TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) {
-  testDirectReportOperation(
-      SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::VERY_FAST, NullChecker());
+TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC,
+                              RateLevel::VERY_FAST, NullChecker());
 }
 
-int main(int argc, char **argv) {
-    ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironmentV1_0::Instance());
-    ::testing::InitGoogleTest(&argc, argv);
-    SensorsHidlEnvironmentV1_0::Instance()->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    ALOGI("Test result = %d", status);
-    return status;
-}
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, SensorsHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(ISensors::descriptor)),
+        android::hardware::PrintInstanceNameToString);
 // vim: set ts=2 sw=2
diff --git a/sensors/2.0/multihal/Android.bp b/sensors/2.0/multihal/Android.bp
index c13eaf2..811c455 100644
--- a/sensors/2.0/multihal/Android.bp
+++ b/sensors/2.0/multihal/Android.bp
@@ -43,10 +43,10 @@
     srcs: [
         "service.cpp",
         "HalProxy.cpp",
-        "ScopedWakelock.cpp",
     ],
     init_rc: ["android.hardware.sensors@2.0-service-multihal.rc"],
     vintf_fragments: ["android.hardware.sensors@2.0-multihal.xml"],
+    shared_libs: ["android.hardware.sensors@2.0-ScopedWakelock"]
 }
 
 cc_library_headers {
@@ -55,19 +55,40 @@
     export_include_dirs: ["include"],
 }
 
+cc_library_shared {
+    name: "android.hardware.sensors@2.0-ScopedWakelock",
+    defaults: [
+        "hidl_defaults",
+        "android.hardware.sensors@2.0-multihal-defaults",
+    ],
+    srcs: [
+        "ScopedWakelock.cpp",
+    ],
+    vendor_available: true,
+    export_header_lib_headers: [
+        "android.hardware.sensors@2.0-multihal.header"
+    ]
+}
+
 // The below targets should only be used for testing.
 cc_test_library {
     name: "android.hardware.sensors@2.0-HalProxy",
-    defaults: ["android.hardware.sensors@2.0-multihal-defaults"],
+    defaults: [
+        "hidl_defaults",
+        "android.hardware.sensors@2.0-multihal-defaults",
+    ],
     vendor_available: true,
     srcs: [
         "HalProxy.cpp",
-        "ScopedWakelock.cpp",
     ],
     export_header_lib_headers: [
         "android.hardware.sensors@2.0-multihal.header",
     ],
+    export_shared_lib_headers: [
+	"android.hardware.sensors@2.0-ScopedWakelock",
+    ],
     shared_libs: [
         "libutils",
+        "android.hardware.sensors@2.0-ScopedWakelock",
     ],
 }
diff --git a/sensors/2.0/multihal/android.hardware.sensors@2.0-multihal.xml b/sensors/2.0/multihal/android.hardware.sensors@2.0-multihal.xml
index a771100..1acc8e6 100644
--- a/sensors/2.0/multihal/android.hardware.sensors@2.0-multihal.xml
+++ b/sensors/2.0/multihal/android.hardware.sensors@2.0-multihal.xml
@@ -5,7 +5,7 @@
         <version>2.0</version>
         <interface>
             <name>ISensors</name>
-            <instance>multihal</instance>
+            <instance>default</instance>
         </interface>
     </hal>
 </manifest>
diff --git a/sensors/2.0/multihal/tests/Android.bp b/sensors/2.0/multihal/tests/Android.bp
index e7f9499..1637312 100644
--- a/sensors/2.0/multihal/tests/Android.bp
+++ b/sensors/2.0/multihal/tests/Android.bp
@@ -25,6 +25,7 @@
     shared_libs: [
         "android.hardware.sensors@1.0",
         "android.hardware.sensors@2.0",
+	"android.hardware.sensors@2.0-ScopedWakelock",
         "libcutils",
         "libfmq",
         "libhardware",
@@ -83,6 +84,7 @@
     shared_libs: [
         "android.hardware.sensors@1.0",
         "android.hardware.sensors@2.0",
+        "android.hardware.sensors@2.0-ScopedWakelock",
         "libbase",
         "libcutils",
         "libfmq",
diff --git a/sensors/2.0/vts/functional/AndroidTest.xml b/sensors/2.0/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..b710ed0
--- /dev/null
+++ b/sensors/2.0/vts/functional/AndroidTest.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalSensorsV2_0TargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="stop"/>
+        <option name="teardown-command" value="start"/>
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="VtsHalSensorsV2_0TargetTest->/data/local/tmp/VtsHalSensorsV2_0TargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-timeout" value="900000" />
+        <option name="runtime-hint" value="300000"/>
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalSensorsV2_0TargetTest" />
+    </test>
+</configuration>
diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
index dc54f27..81db5a0 100644
--- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
+++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
@@ -58,8 +58,7 @@
 bool SensorsHidlEnvironmentV2_0::resetHal() {
     bool succeed = false;
     do {
-        mSensors = ISensors::getService(
-            SensorsHidlEnvironmentV2_0::Instance()->getServiceName<ISensors>());
+        mSensors = ISensors::getService(mServiceName);
         if (mSensors == nullptr) {
             break;
         }
diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h
index b0dbd90..819cdd4 100644
--- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h
+++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h
@@ -42,22 +42,12 @@
 class SensorsHidlEnvironmentV2_0 : public SensorsHidlEnvironmentBase {
    public:
     using Event = ::android::hardware::sensors::V1_0::Event;
-    // get the test environment singleton
-    static SensorsHidlEnvironmentV2_0* Instance() {
-        static SensorsHidlEnvironmentV2_0* instance = new SensorsHidlEnvironmentV2_0();
-        return instance;
-    }
-
-    virtual void registerTestServices() override {
-        registerTestService<android::hardware::sensors::V2_0::ISensors>();
-    }
-
     virtual void HidlTearDown() override;
 
    protected:
     friend SensorsHidlTest;
-
-    SensorsHidlEnvironmentV2_0() : mEventQueueFlag(nullptr) {}
+    SensorsHidlEnvironmentV2_0(const std::string& service_name)
+        : SensorsHidlEnvironmentBase(service_name), mEventQueueFlag(nullptr) {}
 
     /**
      * Resets the HAL with new FMQs and a new Event Flag
diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
index 8364ba9..c5eb442 100644
--- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
+++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
@@ -20,6 +20,8 @@
 
 #include <android/hardware/sensors/2.0/ISensors.h>
 #include <android/hardware/sensors/2.0/types.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 #include <log/log.h>
 #include <utils/SystemClock.h>
 
@@ -120,10 +122,14 @@
 class SensorsHidlTest : public SensorsHidlTestBase {
   public:
     virtual void SetUp() override {
+        mEnvironment = new SensorsHidlEnvironmentV2_0(GetParam());
+        mEnvironment->HidlSetUp();
         // Ensure that we have a valid environment before performing tests
         ASSERT_NE(getSensors(), nullptr);
     }
 
+    virtual void TearDown() override { mEnvironment->HidlTearDown(); }
+
   protected:
     SensorInfo defaultSensorByType(SensorType type) override;
     std::vector<SensorInfo> getSensorsList();
@@ -160,12 +166,10 @@
     }
 
     inline sp<::android::hardware::sensors::V2_0::ISensors>& getSensors() {
-        return SensorsHidlEnvironmentV2_0::Instance()->mSensors;
+        return mEnvironment->mSensors;
     }
 
-    SensorsHidlEnvironmentBase* getEnvironment() override {
-        return SensorsHidlEnvironmentV2_0::Instance();
-    }
+    SensorsHidlEnvironmentBase* getEnvironment() override { return mEnvironment; }
 
     // Test helpers
     void runSingleFlushTest(const std::vector<SensorInfo>& sensors, bool activateSensor,
@@ -191,6 +195,10 @@
     void checkRateLevel(const SensorInfo& sensor, int32_t directChannelHandle, RateLevel rateLevel);
     void queryDirectChannelSupport(SharedMemType memType, bool* supportsSharedMemType,
                                    bool* supportsAnyDirectChannel);
+
+  private:
+    // Test environment for sensors HAL.
+    SensorsHidlEnvironmentV2_0* mEnvironment;
 };
 
 Return<Result> SensorsHidlTest::activate(int32_t sensorHandle, bool enabled) {
@@ -301,7 +309,7 @@
 }
 
 // Test if sensor list returned is valid
-TEST_F(SensorsHidlTest, SensorListValid) {
+TEST_P(SensorsHidlTest, SensorListValid) {
     getSensors()->getSensorsList([&](const auto& list) {
         const size_t count = list.size();
         for (size_t i = 0; i < count; ++i) {
@@ -346,7 +354,7 @@
 }
 
 // Test that SetOperationMode returns the expected value
-TEST_F(SensorsHidlTest, SetOperationMode) {
+TEST_P(SensorsHidlTest, SetOperationMode) {
     std::vector<SensorInfo> sensors = getInjectEventSensors();
     if (getInjectEventSensors().size() > 0) {
         ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL));
@@ -358,7 +366,7 @@
 }
 
 // Test that an injected event is written back to the Event FMQ
-TEST_F(SensorsHidlTest, InjectSensorEventData) {
+TEST_P(SensorsHidlTest, InjectSensorEventData) {
     std::vector<SensorInfo> sensors = getInjectEventSensors();
     if (sensors.size() == 0) {
         return;
@@ -414,196 +422,196 @@
 }
 
 // Test if sensor hal can do UI speed accelerometer streaming properly
-TEST_F(SensorsHidlTest, AccelerometerStreamingOperationSlow) {
+TEST_P(SensorsHidlTest, AccelerometerStreamingOperationSlow) {
     testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(200),
                            std::chrono::seconds(5), sAccelNormChecker);
 }
 
 // Test if sensor hal can do normal speed accelerometer streaming properly
-TEST_F(SensorsHidlTest, AccelerometerStreamingOperationNormal) {
+TEST_P(SensorsHidlTest, AccelerometerStreamingOperationNormal) {
     testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(20),
                            std::chrono::seconds(5), sAccelNormChecker);
 }
 
 // Test if sensor hal can do game speed accelerometer streaming properly
-TEST_F(SensorsHidlTest, AccelerometerStreamingOperationFast) {
+TEST_P(SensorsHidlTest, AccelerometerStreamingOperationFast) {
     testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(5),
                            std::chrono::seconds(5), sAccelNormChecker);
 }
 
 // Test if sensor hal can do UI speed gyroscope streaming properly
-TEST_F(SensorsHidlTest, GyroscopeStreamingOperationSlow) {
+TEST_P(SensorsHidlTest, GyroscopeStreamingOperationSlow) {
     testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(200),
                            std::chrono::seconds(5), sGyroNormChecker);
 }
 
 // Test if sensor hal can do normal speed gyroscope streaming properly
-TEST_F(SensorsHidlTest, GyroscopeStreamingOperationNormal) {
+TEST_P(SensorsHidlTest, GyroscopeStreamingOperationNormal) {
     testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(20),
                            std::chrono::seconds(5), sGyroNormChecker);
 }
 
 // Test if sensor hal can do game speed gyroscope streaming properly
-TEST_F(SensorsHidlTest, GyroscopeStreamingOperationFast) {
+TEST_P(SensorsHidlTest, GyroscopeStreamingOperationFast) {
     testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(5),
                            std::chrono::seconds(5), sGyroNormChecker);
 }
 
 // Test if sensor hal can do UI speed magnetometer streaming properly
-TEST_F(SensorsHidlTest, MagnetometerStreamingOperationSlow) {
+TEST_P(SensorsHidlTest, MagnetometerStreamingOperationSlow) {
     testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(200),
                            std::chrono::seconds(5), NullChecker());
 }
 
 // Test if sensor hal can do normal speed magnetometer streaming properly
-TEST_F(SensorsHidlTest, MagnetometerStreamingOperationNormal) {
+TEST_P(SensorsHidlTest, MagnetometerStreamingOperationNormal) {
     testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(20),
                            std::chrono::seconds(5), NullChecker());
 }
 
 // Test if sensor hal can do game speed magnetometer streaming properly
-TEST_F(SensorsHidlTest, MagnetometerStreamingOperationFast) {
+TEST_P(SensorsHidlTest, MagnetometerStreamingOperationFast) {
     testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(5),
                            std::chrono::seconds(5), NullChecker());
 }
 
 // Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active
-TEST_F(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) {
+TEST_P(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) {
     testSamplingRateHotSwitchOperation(SensorType::ACCELEROMETER);
     testSamplingRateHotSwitchOperation(SensorType::ACCELEROMETER, false /*fastToSlow*/);
 }
 
 // Test if sensor hal can do gyroscope sampling rate switch properly when sensor is active
-TEST_F(SensorsHidlTest, GyroscopeSamplingPeriodHotSwitchOperation) {
+TEST_P(SensorsHidlTest, GyroscopeSamplingPeriodHotSwitchOperation) {
     testSamplingRateHotSwitchOperation(SensorType::GYROSCOPE);
     testSamplingRateHotSwitchOperation(SensorType::GYROSCOPE, false /*fastToSlow*/);
 }
 
 // Test if sensor hal can do magnetometer sampling rate switch properly when sensor is active
-TEST_F(SensorsHidlTest, MagnetometerSamplingPeriodHotSwitchOperation) {
+TEST_P(SensorsHidlTest, MagnetometerSamplingPeriodHotSwitchOperation) {
     testSamplingRateHotSwitchOperation(SensorType::MAGNETIC_FIELD);
     testSamplingRateHotSwitchOperation(SensorType::MAGNETIC_FIELD, false /*fastToSlow*/);
 }
 
 // Test if sensor hal can do accelerometer batching properly
-TEST_F(SensorsHidlTest, AccelerometerBatchingOperation) {
+TEST_P(SensorsHidlTest, AccelerometerBatchingOperation) {
     testBatchingOperation(SensorType::ACCELEROMETER);
 }
 
 // Test if sensor hal can do gyroscope batching properly
-TEST_F(SensorsHidlTest, GyroscopeBatchingOperation) {
+TEST_P(SensorsHidlTest, GyroscopeBatchingOperation) {
     testBatchingOperation(SensorType::GYROSCOPE);
 }
 
 // Test if sensor hal can do magnetometer batching properly
-TEST_F(SensorsHidlTest, MagnetometerBatchingOperation) {
+TEST_P(SensorsHidlTest, MagnetometerBatchingOperation) {
     testBatchingOperation(SensorType::MAGNETIC_FIELD);
 }
 
 // Test sensor event direct report with ashmem for accel sensor at normal rate
-TEST_F(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) {
+TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) {
     testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::NORMAL,
                               sAccelNormChecker);
 }
 
 // Test sensor event direct report with ashmem for accel sensor at fast rate
-TEST_F(SensorsHidlTest, AccelerometerAshmemDirectReportOperationFast) {
+TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationFast) {
     testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::FAST,
                               sAccelNormChecker);
 }
 
 // Test sensor event direct report with ashmem for accel sensor at very fast rate
-TEST_F(SensorsHidlTest, AccelerometerAshmemDirectReportOperationVeryFast) {
+TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationVeryFast) {
     testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM,
                               RateLevel::VERY_FAST, sAccelNormChecker);
 }
 
 // Test sensor event direct report with ashmem for gyro sensor at normal rate
-TEST_F(SensorsHidlTest, GyroscopeAshmemDirectReportOperationNormal) {
+TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationNormal) {
     testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::NORMAL,
                               sGyroNormChecker);
 }
 
 // Test sensor event direct report with ashmem for gyro sensor at fast rate
-TEST_F(SensorsHidlTest, GyroscopeAshmemDirectReportOperationFast) {
+TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationFast) {
     testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::FAST,
                               sGyroNormChecker);
 }
 
 // Test sensor event direct report with ashmem for gyro sensor at very fast rate
-TEST_F(SensorsHidlTest, GyroscopeAshmemDirectReportOperationVeryFast) {
+TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationVeryFast) {
     testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::VERY_FAST,
                               sGyroNormChecker);
 }
 
 // Test sensor event direct report with ashmem for mag sensor at normal rate
-TEST_F(SensorsHidlTest, MagnetometerAshmemDirectReportOperationNormal) {
+TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationNormal) {
     testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::NORMAL,
                               NullChecker());
 }
 
 // Test sensor event direct report with ashmem for mag sensor at fast rate
-TEST_F(SensorsHidlTest, MagnetometerAshmemDirectReportOperationFast) {
+TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationFast) {
     testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::FAST,
                               NullChecker());
 }
 
 // Test sensor event direct report with ashmem for mag sensor at very fast rate
-TEST_F(SensorsHidlTest, MagnetometerAshmemDirectReportOperationVeryFast) {
+TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationVeryFast) {
     testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM,
                               RateLevel::VERY_FAST, NullChecker());
 }
 
 // Test sensor event direct report with gralloc for accel sensor at normal rate
-TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) {
+TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) {
     testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::NORMAL,
                               sAccelNormChecker);
 }
 
 // Test sensor event direct report with gralloc for accel sensor at fast rate
-TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationFast) {
+TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationFast) {
     testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::FAST,
                               sAccelNormChecker);
 }
 
 // Test sensor event direct report with gralloc for accel sensor at very fast rate
-TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationVeryFast) {
+TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationVeryFast) {
     testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC,
                               RateLevel::VERY_FAST, sAccelNormChecker);
 }
 
 // Test sensor event direct report with gralloc for gyro sensor at normal rate
-TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) {
+TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) {
     testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::NORMAL,
                               sGyroNormChecker);
 }
 
 // Test sensor event direct report with gralloc for gyro sensor at fast rate
-TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationFast) {
+TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationFast) {
     testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::FAST,
                               sGyroNormChecker);
 }
 
 // Test sensor event direct report with gralloc for gyro sensor at very fast rate
-TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationVeryFast) {
+TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationVeryFast) {
     testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::VERY_FAST,
                               sGyroNormChecker);
 }
 
 // Test sensor event direct report with gralloc for mag sensor at normal rate
-TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationNormal) {
+TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationNormal) {
     testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::NORMAL,
                               NullChecker());
 }
 
 // Test sensor event direct report with gralloc for mag sensor at fast rate
-TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationFast) {
+TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationFast) {
     testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::FAST,
                               NullChecker());
 }
 
 // Test sensor event direct report with gralloc for mag sensor at very fast rate
-TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) {
+TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) {
     testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC,
                               RateLevel::VERY_FAST, NullChecker());
 }
@@ -619,9 +627,13 @@
 
 // Test that if initialize is called twice, then the HAL writes events to the FMQs from the second
 // call to the function.
-TEST_F(SensorsHidlTest, CallInitializeTwice) {
+TEST_P(SensorsHidlTest, CallInitializeTwice) {
     // Create a helper class so that a second environment is able to be instantiated
-    class SensorsHidlEnvironmentTest : public SensorsHidlEnvironmentV2_0 {};
+    class SensorsHidlEnvironmentTest : public SensorsHidlEnvironmentV2_0 {
+      public:
+        SensorsHidlEnvironmentTest(const std::string& service_name)
+            : SensorsHidlEnvironmentV2_0(service_name) {}
+    };
 
     if (getSensorsList().size() == 0) {
         // No sensors
@@ -633,7 +645,7 @@
 
     // Create a new environment that calls initialize()
     std::unique_ptr<SensorsHidlEnvironmentTest> newEnv =
-        std::make_unique<SensorsHidlEnvironmentTest>();
+            std::make_unique<SensorsHidlEnvironmentTest>(GetParam());
     newEnv->HidlSetUp();
     if (HasFatalFailure()) {
         return;  // Exit early if setting up the new environment failed
@@ -662,7 +674,7 @@
     activateAllSensors(false);
 }
 
-TEST_F(SensorsHidlTest, CleanupConnectionsOnInitialize) {
+TEST_P(SensorsHidlTest, CleanupConnectionsOnInitialize) {
     activateAllSensors(true);
 
     // Verify that events are received
@@ -731,7 +743,7 @@
     }
 }
 
-TEST_F(SensorsHidlTest, FlushSensor) {
+TEST_P(SensorsHidlTest, FlushSensor) {
     // Find a sensor that is not a one-shot sensor
     std::vector<SensorInfo> sensors = getNonOneShotSensors();
     if (sensors.size() == 0) {
@@ -743,7 +755,7 @@
     runFlushTest(sensors, true /* activateSensor */, kFlushes, kFlushes, Result::OK);
 }
 
-TEST_F(SensorsHidlTest, FlushOneShotSensor) {
+TEST_P(SensorsHidlTest, FlushOneShotSensor) {
     // Find a sensor that is a one-shot sensor
     std::vector<SensorInfo> sensors = getOneShotSensors();
     if (sensors.size() == 0) {
@@ -754,7 +766,7 @@
                        Result::BAD_VALUE);
 }
 
-TEST_F(SensorsHidlTest, FlushInactiveSensor) {
+TEST_P(SensorsHidlTest, FlushInactiveSensor) {
     // Attempt to find a non-one shot sensor, then a one-shot sensor if necessary
     std::vector<SensorInfo> sensors = getNonOneShotSensors();
     if (sensors.size() == 0) {
@@ -768,7 +780,7 @@
                        Result::BAD_VALUE);
 }
 
-TEST_F(SensorsHidlTest, FlushNonexistentSensor) {
+TEST_P(SensorsHidlTest, FlushNonexistentSensor) {
     SensorInfo sensor;
     std::vector<SensorInfo> sensors = getNonOneShotSensors();
     if (sensors.size() == 0) {
@@ -783,7 +795,7 @@
                        0 /* expectedFlushCount */, Result::BAD_VALUE);
 }
 
-TEST_F(SensorsHidlTest, Batch) {
+TEST_P(SensorsHidlTest, Batch) {
     if (getSensorsList().size() == 0) {
         return;
     }
@@ -815,7 +827,7 @@
               Result::BAD_VALUE);
 }
 
-TEST_F(SensorsHidlTest, Activate) {
+TEST_P(SensorsHidlTest, Activate) {
     if (getSensorsList().size() == 0) {
         return;
     }
@@ -841,7 +853,7 @@
     ASSERT_EQ(activate(invalidHandle, false), Result::BAD_VALUE);
 }
 
-TEST_F(SensorsHidlTest, NoStaleEvents) {
+TEST_P(SensorsHidlTest, NoStaleEvents) {
     constexpr milliseconds kFiveHundredMs(500);
     constexpr milliseconds kOneSecond(1000);
 
@@ -1021,11 +1033,11 @@
     }
 }
 
-TEST_F(SensorsHidlTest, DirectChannelAshmem) {
+TEST_P(SensorsHidlTest, DirectChannelAshmem) {
     verifyDirectChannel(SharedMemType::ASHMEM);
 }
 
-TEST_F(SensorsHidlTest, DirectChannelGralloc) {
+TEST_P(SensorsHidlTest, DirectChannelGralloc) {
     verifyDirectChannel(SharedMemType::GRALLOC);
 }
 
@@ -1064,7 +1076,7 @@
     return found;
 }
 
-TEST_F(SensorsHidlTest, ConfigureDirectChannelWithInvalidHandle) {
+TEST_P(SensorsHidlTest, ConfigureDirectChannelWithInvalidHandle) {
     SensorInfo sensor;
     SharedMemType memType;
     RateLevel rate;
@@ -1078,7 +1090,7 @@
     });
 }
 
-TEST_F(SensorsHidlTest, CleanupDirectConnectionOnInitialize) {
+TEST_P(SensorsHidlTest, CleanupDirectConnectionOnInitialize) {
     constexpr size_t kNumEvents = 1;
     constexpr size_t kMemSize = kNumEvents * kEventSize;
 
@@ -1124,12 +1136,8 @@
     mDirectChannelHandles = handles;
 }
 
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironmentV2_0::Instance());
-    ::testing::InitGoogleTest(&argc, argv);
-    SensorsHidlEnvironmentV2_0::Instance()->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    ALOGI("Test result = %d", status);
-    return status;
-}
+INSTANTIATE_TEST_SUITE_P(PerInstance, SensorsHidlTest,
+                         testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+                                 android::hardware::sensors::V2_0::ISensors::descriptor)),
+                         android::hardware::PrintInstanceNameToString);
 // vim: set ts=2 sw=2
diff --git a/sensors/common/vts/utils/Android.bp b/sensors/common/vts/utils/Android.bp
index 02dc608..bb4d329 100644
--- a/sensors/common/vts/utils/Android.bp
+++ b/sensors/common/vts/utils/Android.bp
@@ -16,6 +16,7 @@
 
 cc_library_static {
     name: "VtsHalSensorsTargetTestUtils",
+    defaults: ["VtsHalTargetTestDefaults"],
     cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""],
     srcs: [
         "GrallocWrapper.cpp",
@@ -36,6 +37,5 @@
         "android.hardware.graphics.mapper@2.1",
         "android.hardware.graphics.mapper@3.0",
         "android.hardware.sensors@1.0",
-        "VtsHalHidlTargetTestBase",
     ],
 }
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
index 6499fba..dbc9392 100644
--- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
@@ -17,9 +17,8 @@
 #ifndef ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H
 #define ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H
 
-#include <VtsHalHidlTargetTestEnvBase.h>
-
 #include <android/hardware/sensors/1.0/types.h>
+#include <gtest/gtest.h>
 
 #include <atomic>
 #include <memory>
@@ -33,11 +32,11 @@
     virtual void onEvent(const ::android::hardware::sensors::V1_0::Event& event) = 0;
 };
 
-class SensorsHidlEnvironmentBase : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
+class SensorsHidlEnvironmentBase {
+  public:
     using Event = ::android::hardware::sensors::V1_0::Event;
-    virtual void HidlSetUp() override;
-    virtual void HidlTearDown() override;
+    virtual void HidlSetUp();
+    virtual void HidlTearDown();
 
     // Get and clear all events collected so far (like "cat" shell command).
     // If output is nullptr, it clears all collected events.
@@ -50,22 +49,27 @@
     void unregisterCallback();
 
    protected:
-    SensorsHidlEnvironmentBase() : mCollectionEnabled(false), mCallback(nullptr) {}
+     SensorsHidlEnvironmentBase(const std::string& service_name)
+         : mCollectionEnabled(false), mCallback(nullptr) {
+         mServiceName = service_name;
+     }
+     virtual ~SensorsHidlEnvironmentBase(){};
 
-    void addEvent(const Event& ev);
+     void addEvent(const Event& ev);
 
-    virtual void startPollingThread() = 0;
-    virtual bool resetHal() = 0;
+     virtual void startPollingThread() = 0;
+     virtual bool resetHal() = 0;
 
-    bool mCollectionEnabled;
-    std::atomic_bool mStopThread;
-    std::thread mPollThread;
-    std::vector<Event> mEvents;
-    std::mutex mEventsMutex;
+     std::string mServiceName;
+     bool mCollectionEnabled;
+     std::atomic_bool mStopThread;
+     std::thread mPollThread;
+     std::vector<Event> mEvents;
+     std::mutex mEventsMutex;
 
-    IEventCallback* mCallback;
+     IEventCallback* mCallback;
 
-    GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentBase);
+     GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentBase);
 };
 
 #endif  // ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H
\ No newline at end of file
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
index 6fd9a2b..5fb6c5c 100644
--- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
@@ -23,6 +23,7 @@
 #include <VtsHalHidlTargetTestBase.h>
 #include <android/hardware/sensors/1.0/ISensors.h>
 #include <android/hardware/sensors/1.0/types.h>
+#include <gtest/gtest.h>
 
 #include <unordered_set>
 #include <vector>
@@ -44,8 +45,8 @@
 using ::android::hardware::sensors::V1_0::SharedMemInfo;
 using ::android::hardware::sensors::V1_0::SharedMemType;
 
-class SensorsHidlTestBase : public ::testing::VtsHalHidlTargetTestBase {
-   public:
+class SensorsHidlTestBase : public testing::TestWithParam<std::string> {
+  public:
     virtual SensorsHidlEnvironmentBase* getEnvironment() = 0;
     virtual void SetUp() override {}
 
diff --git a/soundtrigger/2.1/Android.bp b/soundtrigger/2.1/Android.bp
index 68e425b..30173cb 100644
--- a/soundtrigger/2.1/Android.bp
+++ b/soundtrigger/2.1/Android.bp
@@ -15,5 +15,5 @@
         "android.hardware.soundtrigger@2.0",
         "android.hidl.base@1.0",
     ],
-    gen_java: false,
+    gen_java: true,
 }
diff --git a/soundtrigger/2.2/Android.bp b/soundtrigger/2.2/Android.bp
index 43898c7..7556aa4 100644
--- a/soundtrigger/2.2/Android.bp
+++ b/soundtrigger/2.2/Android.bp
@@ -15,5 +15,5 @@
         "android.hardware.soundtrigger@2.1",
         "android.hidl.base@1.0",
     ],
-    gen_java: false,
+    gen_java: true,
 }
diff --git a/tests/extension/vibrator/aidl/Android.bp b/tests/extension/vibrator/aidl/Android.bp
new file mode 100644
index 0000000..ef9b39b
--- /dev/null
+++ b/tests/extension/vibrator/aidl/Android.bp
@@ -0,0 +1,29 @@
+aidl_interface {
+    // This is an example test interface showing how to add functionality
+    // with setExtension/getExtension
+    name: "test-vintf-vibrator-ext",
+    vendor_available: true,
+    srcs: [
+        // Using android.hardware as the package because this is in
+        // hardware/interfaces. For custom interfaces, normally you
+        // would use a different package.
+        "android/hardware/tests/extension/vibrator/Directionality.aidl",
+        "android/hardware/tests/extension/vibrator/ICustomVibrator.aidl",
+        "android/hardware/tests/extension/vibrator/VendorEffect.aidl",
+    ],
+
+    // This is agreeing to keep the interface stable.
+    stability: "vintf",
+
+    // This happens to use types from a core interface, so we import it, but
+    // this won't always be needed.
+    imports: [
+        "vintf-vibrator",
+    ],
+
+    backend: {
+        java: {
+            enabled: false,
+        },
+    },
+}
diff --git a/vibrator/1.4/types.hal b/tests/extension/vibrator/aidl/android/hardware/tests/extension/vibrator/Directionality.aidl
similarity index 60%
copy from vibrator/1.4/types.hal
copy to tests/extension/vibrator/aidl/android/hardware/tests/extension/vibrator/Directionality.aidl
index acc49b1..72bfd66 100644
--- a/vibrator/1.4/types.hal
+++ b/tests/extension/vibrator/aidl/android/hardware/tests/extension/vibrator/Directionality.aidl
@@ -13,10 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package android.hardware.tests.extension.vibrator;
 
-package android.hardware.vibrator@1.4;
-
-enum Capabilities : uint32_t {
-    ON_COMPLETION_CALLBACK = 1 << 0,
-    PERFORM_COMPLETION_CALLBACK = 1 << 1,
-};
+/**
+ * Can add custom enums. If these need to be extended further, new values can
+ * simply be added.
+ */
+@Backing(type="int")
+@VintfStability
+enum Directionality {
+    NONE,
+    /** vibrations should be transverse wrt primary screen */
+    TRANSVERSE,
+    /** vibrations should be longitudinal wrt primary screen */
+    LONGITUDINAL,
+}
diff --git a/tests/extension/vibrator/aidl/android/hardware/tests/extension/vibrator/ICustomVibrator.aidl b/tests/extension/vibrator/aidl/android/hardware/tests/extension/vibrator/ICustomVibrator.aidl
new file mode 100644
index 0000000..0b21f46
--- /dev/null
+++ b/tests/extension/vibrator/aidl/android/hardware/tests/extension/vibrator/ICustomVibrator.aidl
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+package android.hardware.tests.extension.vibrator;
+
+// it's fine to use types from other interfaces
+import android.hardware.vibrator.IVibratorCallback;
+import android.hardware.tests.extension.vibrator.Directionality;
+import android.hardware.tests.extension.vibrator.VendorEffect;
+
+/**
+ * This is an example of an AIDL interface extension. Notice that it does not
+ * inherit from any other extension. Instead, it will be tagged onto that
+ * extension at runtime.
+ */
+@VintfStability
+interface ICustomVibrator {
+    /**
+     * Avoid conflicting with vendor properties. Giving this as an example
+     * because the core vibrator interface uses capabilities. In reality,
+     * since this is only one capability, it's probably not needed to construct
+     * a bitfield.
+     *
+     * This is for longitudinal/transverse waves, see setDirectionality.
+     */
+    const int CAP_VENDOR_DIRECTIONALITY = 1 << 0;
+
+    /**
+     * Any new methods can be added, this returns CAP_VENDOR_*.
+     */
+    int getVendorCapabilities();
+
+    /**
+     * Arbitrary new functionality can be added.
+     */
+    void setDirectionality(Directionality directionality);
+
+    /**
+     * Perform a custom vendor effect. Note, this is a separate effect enum to
+     * avoid conflicting with core types.
+     */
+    int perform(VendorEffect effect, IVibratorCallback callback);
+}
diff --git a/vibrator/1.4/types.hal b/tests/extension/vibrator/aidl/android/hardware/tests/extension/vibrator/VendorEffect.aidl
similarity index 74%
copy from vibrator/1.4/types.hal
copy to tests/extension/vibrator/aidl/android/hardware/tests/extension/vibrator/VendorEffect.aidl
index acc49b1..968532c 100644
--- a/vibrator/1.4/types.hal
+++ b/tests/extension/vibrator/aidl/android/hardware/tests/extension/vibrator/VendorEffect.aidl
@@ -13,10 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package android.hardware.tests.extension.vibrator;
 
-package android.hardware.vibrator@1.4;
-
-enum Capabilities : uint32_t {
-    ON_COMPLETION_CALLBACK = 1 << 0,
-    PERFORM_COMPLETION_CALLBACK = 1 << 1,
-};
+/**
+ * Extending enum separately to avoid conflicts w/ upstream.
+ */
+@Backing(type="int")
+@VintfStability
+enum VendorEffect {
+    CRACKLE,
+    WIGGLE,
+}
diff --git a/tests/extension/vibrator/aidl/client/Android.bp b/tests/extension/vibrator/aidl/client/Android.bp
new file mode 100644
index 0000000..f7b71f7
--- /dev/null
+++ b/tests/extension/vibrator/aidl/client/Android.bp
@@ -0,0 +1,26 @@
+
+// This example client is written as a test, but it is executing from a system
+// context. All this code would look the same if it was running in system
+// server for example.
+
+cc_test {
+    name: "test-vintf-vibrator-ext-client",
+    srcs: [
+         // system code has the option to use the unstable C++ libbinder API
+         // or the NDK one. For maximum code portability, using the ndk client
+         // makes the most sense, but both are provided here as an example.
+         "test-cpp-client.cpp",
+         "test-ndk-client.cpp",
+    ],
+    shared_libs: [
+         "libbinder",
+         "libutils",
+         "vintf-vibrator-cpp",
+         "test-vintf-vibrator-ext-cpp",
+
+         "libbinder_ndk",
+         "vintf-vibrator-ndk_platform",
+         "test-vintf-vibrator-ext-ndk_platform",
+    ],
+}
+
diff --git a/tests/extension/vibrator/aidl/client/test-cpp-client.cpp b/tests/extension/vibrator/aidl/client/test-cpp-client.cpp
new file mode 100644
index 0000000..015a345
--- /dev/null
+++ b/tests/extension/vibrator/aidl/client/test-cpp-client.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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 <android/hardware/tests/extension/vibrator/ICustomVibrator.h>
+#include <android/hardware/vibrator/IVibrator.h>
+#include <binder/IInterface.h>
+#include <binder/IServiceManager.h>
+#include <gtest/gtest.h>
+
+using android::checked_interface_cast;
+using android::IBinder;
+using android::IInterface;
+using android::OK;
+using android::sp;
+using android::waitForVintfService;
+using android::hardware::tests::extension::vibrator::Directionality;
+using android::hardware::tests::extension::vibrator::ICustomVibrator;
+using android::hardware::vibrator::IVibrator;
+
+TEST(Cpp, CallRootMethod) {
+    sp<IVibrator> vib = waitForVintfService<IVibrator>();
+    ASSERT_NE(nullptr, vib.get());
+    ASSERT_TRUE(vib->off().isOk());
+}
+
+TEST(Cpp, CallExtMethod) {
+    // normally you would want to cache this
+    sp<IVibrator> vib = waitForVintfService<IVibrator>();
+    ASSERT_NE(nullptr, vib.get());
+
+    // getting the extension
+    sp<IBinder> ext;
+    ASSERT_EQ(OK, IInterface::asBinder(vib)->getExtension(&ext));
+    sp<ICustomVibrator> cvib = checked_interface_cast<ICustomVibrator>(ext);
+    ASSERT_NE(nullptr, cvib.get());
+
+    // calling extension method
+    ASSERT_TRUE(cvib->setDirectionality(Directionality::TRANSVERSE).isOk());
+}
diff --git a/tests/extension/vibrator/aidl/client/test-ndk-client.cpp b/tests/extension/vibrator/aidl/client/test-ndk-client.cpp
new file mode 100644
index 0000000..c846495
--- /dev/null
+++ b/tests/extension/vibrator/aidl/client/test-ndk-client.cpp
@@ -0,0 +1,55 @@
+/*
+ * 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 <aidl/android/hardware/tests/extension/vibrator/ICustomVibrator.h>
+#include <aidl/android/hardware/vibrator/IVibrator.h>
+#include <android/binder_manager.h>
+
+#include <gtest/gtest.h>
+
+using aidl::android::hardware::tests::extension::vibrator::Directionality;
+using aidl::android::hardware::tests::extension::vibrator::ICustomVibrator;
+using aidl::android::hardware::vibrator::IVibrator;
+using ndk::SpAIBinder;
+
+static const std::string kInstance = std::string() + IVibrator::descriptor + "/default";
+
+TEST(Ndk, CallRootMethod) {
+    SpAIBinder vibBinder = SpAIBinder(AServiceManager_getService(kInstance.c_str()));
+    ASSERT_NE(nullptr, vibBinder.get());
+    std::shared_ptr<IVibrator> vib = IVibrator::fromBinder(vibBinder);
+    ASSERT_NE(nullptr, vib.get());
+    ASSERT_TRUE(vib->off().isOk());
+}
+
+TEST(Ndk, CallExtMethod) {
+    // normally you would want to cache this
+    //
+    SpAIBinder vibBinder = SpAIBinder(AServiceManager_getService(kInstance.c_str()));
+    ASSERT_NE(nullptr, vibBinder.get());
+    std::shared_ptr<IVibrator> vib = IVibrator::fromBinder(vibBinder);
+    ASSERT_NE(nullptr, vib.get());
+
+    // getting the extension
+    SpAIBinder cvibBinder;
+    ASSERT_EQ(STATUS_OK, AIBinder_getExtension(vibBinder.get(), cvibBinder.getR()));
+    ASSERT_NE(nullptr, cvibBinder.get());
+    std::shared_ptr<ICustomVibrator> cvib = ICustomVibrator::fromBinder(cvibBinder);
+    ASSERT_NE(nullptr, cvib.get());
+
+    // calling extension method
+    ASSERT_TRUE(cvib->setDirectionality(Directionality::TRANSVERSE).isOk());
+}
diff --git a/tests/extension/vibrator/aidl/default/Android.bp b/tests/extension/vibrator/aidl/default/Android.bp
new file mode 100644
index 0000000..9869657
--- /dev/null
+++ b/tests/extension/vibrator/aidl/default/Android.bp
@@ -0,0 +1,25 @@
+cc_binary {
+    name: "android.hardware.tests.extension.vibrator-service.example",
+    relative_install_path: "hw",
+    // normally you implement a service directly, but we are using an implementation
+    // from a library to attach our extension to.
+    static_libs: [
+        "libvibratorexampleimpl",
+    ],
+
+    // need to add this in the manifest and to init as well to use, see
+    // android.hardware.vibrator-service.example. This binary is being tested
+    // by running it manually as root.
+
+    vendor: true,
+    srcs: [
+        "service.cpp",
+        "CustomVibrator.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "vintf-vibrator-ndk_platform",
+        "test-vintf-vibrator-ext-ndk_platform",
+    ],
+}
diff --git a/tests/extension/vibrator/aidl/default/CustomVibrator.cpp b/tests/extension/vibrator/aidl/default/CustomVibrator.cpp
new file mode 100644
index 0000000..2f3dfcb
--- /dev/null
+++ b/tests/extension/vibrator/aidl/default/CustomVibrator.cpp
@@ -0,0 +1,60 @@
+/*
+ * 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 "CustomVibrator.h"
+
+#include <android-base/logging.h>
+#include <thread>
+
+namespace aidl::android::hardware::tests::extension::vibrator {
+
+ndk::ScopedAStatus CustomVibrator::getVendorCapabilities(int32_t* _aidl_return) {
+    *_aidl_return = ICustomVibrator::CAP_VENDOR_DIRECTIONALITY;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus CustomVibrator::setDirectionality(Directionality directionality) {
+    LOG(INFO) << "Custom vibrator set directionality";
+    // do something cool in hardware
+    (void)directionality;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus CustomVibrator::perform(VendorEffect effect,
+                                           const std::shared_ptr<IVibratorCallback>& callback,
+                                           int32_t* _aidl_return) {
+    LOG(INFO) << "Custom vibrator perform";
+
+    if (effect != VendorEffect::CRACKLE && effect != VendorEffect::WIGGLE) {
+        return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+    }
+
+    constexpr size_t kEffectMillis = 100;
+
+    if (callback != nullptr) {
+        std::thread([=] {
+            LOG(INFO) << "Starting vendor perform on another thread";
+            usleep(kEffectMillis * 1000);
+            LOG(INFO) << "Notifying vendor perform complete";
+            callback->onComplete();
+        }).detach();
+    }
+
+    *_aidl_return = kEffectMillis;
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::tests::extension::vibrator
diff --git a/tests/extension/vibrator/aidl/default/CustomVibrator.h b/tests/extension/vibrator/aidl/default/CustomVibrator.h
new file mode 100644
index 0000000..6dc5743
--- /dev/null
+++ b/tests/extension/vibrator/aidl/default/CustomVibrator.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/tests/extension/vibrator/BnCustomVibrator.h>
+#include <aidl/android/hardware/vibrator/IVibratorCallback.h>
+
+namespace aidl::android::hardware::tests::extension::vibrator {
+
+using aidl::android::hardware::vibrator::IVibratorCallback;
+
+class CustomVibrator : public BnCustomVibrator {
+    ndk::ScopedAStatus getVendorCapabilities(int32_t* _aidl_return) override;
+    ndk::ScopedAStatus setDirectionality(Directionality directionality) override;
+    ndk::ScopedAStatus perform(VendorEffect effect,
+                               const std::shared_ptr<IVibratorCallback>& callback,
+                               int32_t* _aidl_return) override;
+};
+
+}  // namespace aidl::android::hardware::tests::extension::vibrator
diff --git a/tests/extension/vibrator/aidl/default/service.cpp b/tests/extension/vibrator/aidl/default/service.cpp
new file mode 100644
index 0000000..16290df
--- /dev/null
+++ b/tests/extension/vibrator/aidl/default/service.cpp
@@ -0,0 +1,47 @@
+/*
+ * 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 <vibrator-impl/Vibrator.h>
+#include "CustomVibrator.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using aidl::android::hardware::tests::extension::vibrator::CustomVibrator;
+using aidl::android::hardware::vibrator::Vibrator;
+
+int main() {
+    // these are threads in addition to the one we are joining below, so this
+    // service will have a single thread
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+
+    // making the core service
+    std::shared_ptr<Vibrator> vib = ndk::SharedRefBase::make<Vibrator>();
+    ndk::SpAIBinder vibBinder = vib->asBinder();
+
+    // making the extension service
+    std::shared_ptr<CustomVibrator> cvib = ndk::SharedRefBase::make<CustomVibrator>();
+
+    // need to attach the extension to the same binder we will be registering
+    CHECK(STATUS_OK == AIBinder_setExtension(vibBinder.get(), cvib->asBinder().get()));
+
+    const std::string instance = std::string() + Vibrator::descriptor + "/default";
+    CHECK(STATUS_OK == AServiceManager_addService(vibBinder.get(), instance.c_str()));
+
+    ABinderProcess_joinThreadPool();
+    return EXIT_FAILURE;  // should not reach
+}
diff --git a/tests/memory/1.0/Android.bp b/tests/memory/1.0/Android.bp
index 29f6be7..6612e31 100644
--- a/tests/memory/1.0/Android.bp
+++ b/tests/memory/1.0/Android.bp
@@ -11,5 +11,5 @@
         "android.hidl.memory.block@1.0",
         "android.hidl.memory.token@1.0",
     ],
-    gen_java: false,
+    gen_java: true,
 }
diff --git a/tests/memory/2.0/.hidl_for_test b/tests/memory/2.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/memory/2.0/.hidl_for_test
diff --git a/tests/memory/2.0/Android.bp b/tests/memory/2.0/Android.bp
new file mode 100644
index 0000000..d24bd21
--- /dev/null
+++ b/tests/memory/2.0/Android.bp
@@ -0,0 +1,14 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.tests.memory@2.0",
+    root: "android.hardware",
+    srcs: [
+        "types.hal",
+        "IMemoryInterface.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
diff --git a/tests/memory/2.0/IMemoryInterface.hal b/tests/memory/2.0/IMemoryInterface.hal
new file mode 100644
index 0000000..2c824bf
--- /dev/null
+++ b/tests/memory/2.0/IMemoryInterface.hal
@@ -0,0 +1,12 @@
+package android.hardware.tests.memory@2.0;
+
+interface IMemoryInterface {
+    // Flips all the bits in the given memory buffer.
+    bitwiseNot(memory mem);
+    // Returns a read-only buffer of size 8, containing the bytes 0..7.
+    getTestMem() generates(memory mem);
+    // Given two memory regions of the same size, returns two memory fields of
+    // equal size, the first contains the byte-wise sum and the other the byte-
+    // wise difference.
+    getSumDiff(TwoMemory in) generates(TwoMemory out);
+};
diff --git a/tests/memory/2.0/types.hal b/tests/memory/2.0/types.hal
new file mode 100644
index 0000000..9ec357b
--- /dev/null
+++ b/tests/memory/2.0/types.hal
@@ -0,0 +1,6 @@
+package android.hardware.tests.memory@2.0;
+
+struct TwoMemory {
+    memory mem1;
+    memory mem2;
+};
diff --git a/tv/tuner/1.0/IDemux.hal b/tv/tuner/1.0/IDemux.hal
index 9e799b4..16fc392 100644
--- a/tv/tuner/1.0/IDemux.hal
+++ b/tv/tuner/1.0/IDemux.hal
@@ -25,7 +25,6 @@
 /**
  * Demultiplexer(Demux) takes a single multiplexed input and splits it into
  * one or more output.
- *
  */
 interface IDemux {
     /**
@@ -134,4 +133,30 @@
      */
     openDvr(DvrType type, uint32_t bufferSize, IDvrCallback cb)
         generates (Result result, IDvr dvr);
+
+    /**
+     * Connect Conditional Access Modules (CAM) through Common Interface (CI)
+     *
+     * It is used by the client to connect CI-CAM. The demux uses the output
+     * from the frontend as the input by default, and must change to use the
+     * output from CI-CAM as the input after this call take place.
+     *
+     * @param ciCamId specify CI-CAM Id to connect.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    connectCiCam(uint32_t ciCamId) generates (Result result);
+
+    /**
+     * Disconnect Conditional Access Modules (CAM)
+     *
+     * It is used by the client to disconnect CI-CAM. The demux will use the
+     * output from the frontend as the input after this call take place.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    disconnectCiCam() generates (Result result);
 };
diff --git a/tv/tuner/1.0/IFilter.hal b/tv/tuner/1.0/IFilter.hal
index deaf3d4..3ed09f6 100644
--- a/tv/tuner/1.0/IFilter.hal
+++ b/tv/tuner/1.0/IFilter.hal
@@ -113,6 +113,21 @@
     getId() generates (Result result, uint32_t filterId);
 
     /**
+     * Release the handle reported by the HAL for AV memory.
+     *
+     * It is used by the client to notify the HAL that the AV handle won't be
+     * used any more in client side, so that the HAL can mark the memory
+     * presented by file descripor in the handle as released.
+     *
+     * @param avMemory A handle associated to the memory for audio or video.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_ARGUMENT if failed for wrong parameter.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    releaseAvHandle(handle avMemory) generates (Result result);
+
+    /**
      * Set the filter's data source.
      *
      * A filter uses demux as data source by default. If the data was packetized
diff --git a/tv/tuner/1.0/default/Demux.cpp b/tv/tuner/1.0/default/Demux.cpp
index c5921f7..71a26ab 100644
--- a/tv/tuner/1.0/default/Demux.cpp
+++ b/tv/tuner/1.0/default/Demux.cpp
@@ -147,6 +147,20 @@
     return Void();
 }
 
+Return<Result> Demux::connectCiCam(uint32_t ciCamId) {
+    ALOGV("%s", __FUNCTION__);
+
+    mCiCamId = ciCamId;
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Demux::disconnectCiCam() {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
 Result Demux::removeFilter(uint32_t filterId) {
     ALOGV("%s", __FUNCTION__);
 
diff --git a/tv/tuner/1.0/default/Demux.h b/tv/tuner/1.0/default/Demux.h
index a9756cc..037429d 100644
--- a/tv/tuner/1.0/default/Demux.h
+++ b/tv/tuner/1.0/default/Demux.h
@@ -76,6 +76,10 @@
     virtual Return<void> openDvr(DvrType type, uint32_t bufferSize, const sp<IDvrCallback>& cb,
                                  openDvr_cb _hidl_cb) override;
 
+    virtual Return<Result> connectCiCam(uint32_t ciCamId) override;
+
+    virtual Return<Result> disconnectCiCam() override;
+
     // Functions interacts with Tuner Service
     void stopBroadcastInput();
     Result removeFilter(uint32_t filterId);
@@ -118,6 +122,7 @@
     void startTsFilter(vector<uint8_t> data);
 
     uint32_t mDemuxId;
+    uint32_t mCiCamId;
     /**
      * Record the last used filter id. Initial value is -1.
      * Filter Id starts with 0.
diff --git a/tv/tuner/1.0/default/Filter.cpp b/tv/tuner/1.0/default/Filter.cpp
index 3d8a977..befd1e6 100644
--- a/tv/tuner/1.0/default/Filter.cpp
+++ b/tv/tuner/1.0/default/Filter.cpp
@@ -120,6 +120,12 @@
     return Result::SUCCESS;
 }
 
+Return<Result> Filter::releaseAvHandle(const hidl_handle& /*avMemory*/) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
 Return<Result> Filter::close() {
     ALOGV("%s", __FUNCTION__);
 
@@ -289,6 +295,9 @@
                 case DemuxTsFilterType::RECORD:
                     startRecordFilterHandler();
                     break;
+                case DemuxTsFilterType::TEMI:
+                    startTemiFilterHandler();
+                    break;
             }
             break;
         case DemuxFilterMainType::MMTP:
@@ -419,6 +428,11 @@
     return Result::SUCCESS;
 }
 
+Result Filter::startTemiFilterHandler() {
+    // TODO handle starting TEMI filter
+    return Result::SUCCESS;
+}
+
 bool Filter::writeSectionsAndCreateEvent(vector<uint8_t> data) {
     // TODO check how many sections has been read
     ALOGD("[Filter] section hander");
@@ -453,4 +467,4 @@
 }  // namespace tuner
 }  // namespace tv
 }  // namespace hardware
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/tv/tuner/1.0/default/Filter.h b/tv/tuner/1.0/default/Filter.h
index 21d4297..fbd965a 100644
--- a/tv/tuner/1.0/default/Filter.h
+++ b/tv/tuner/1.0/default/Filter.h
@@ -68,6 +68,8 @@
 
     virtual Return<Result> flush() override;
 
+    virtual Return<Result> releaseAvHandle(const hidl_handle& avMemory) override;
+
     virtual Return<Result> close() override;
 
     /**
@@ -129,6 +131,7 @@
     Result startMediaFilterHandler();
     Result startRecordFilterHandler();
     Result startPcrFilterHandler();
+    Result startTemiFilterHandler();
     Result startFilterLoop();
 
     void deleteEventFlag();
@@ -176,4 +179,4 @@
 }  // namespace hardware
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_TV_TUNER_V1_0_FILTER_H_
\ No newline at end of file
+#endif  // ANDROID_HARDWARE_TV_TUNER_V1_0_FILTER_H_
diff --git a/tv/tuner/1.0/types.hal b/tv/tuner/1.0/types.hal
index fa00a6e..707f5df 100644
--- a/tv/tuner/1.0/types.hal
+++ b/tv/tuner/1.0/types.hal
@@ -1759,6 +1759,12 @@
      * buffer of the record.
      */
     RECORD,
+    /**
+     * A filter to filter out Timed External Media Information (TEMI) according
+     * to ISO/IEC 13818-1:2013/ DAM 6 from input stream, and send TEMI event to
+     * client through onFilterEvent.
+     */
+    TEMI,
 };
 
 /**
@@ -2170,7 +2176,8 @@
 
     safe_union FilterSettings {
         /**
-         * Not additional parameters. it's used by PCR, TS subtype filters.
+         * Not additional parameters. it's used by PCR, TS, TEMI subtype
+         * filters.
          */
         Monostate noinit;
 
@@ -2461,6 +2468,27 @@
 };
 
 /**
+ *  Filter Event for Timed External Media Information (TEMI) data.
+ */
+struct DemuxFilterTemiEvent {
+    /**
+     * Presentation Time Stamp for audio or video frame. It based on 90KHz has
+     * the same format as PTS (Presentation Time Stamp) in ISO/IEC 13818-1.
+     */
+    uint64_t pts;
+
+    /**
+     * TEMI Descriptor Tag
+     */
+    uint8_t descrTag;
+
+    /**
+     * TEMI Descriptor
+     */
+    vec<uint8_t> descrData;
+};
+
+/**
  *  Filter Event for MMTP Record data.
  */
 struct DemuxFilterMmtpRecordEvent {
@@ -2521,6 +2549,8 @@
         DemuxFilterDownloadEvent download;
 
         DemuxFilterIpPayloadEvent ipPayload;
+
+        DemuxFilterTemiEvent temi;
     };
 
     /**
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index c666226..da3e300 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -159,6 +159,7 @@
     RECORD,
     MMTPRECORD,
     DOWNLOAD,
+    TEMI,
 };
 
 struct PlaybackConf {
@@ -821,6 +822,9 @@
                 case DemuxTsFilterType::RECORD:
                     eventType = FilterEventType::RECORD;
                     break;
+                case DemuxTsFilterType::TEMI:
+                    eventType = FilterEventType::TEMI;
+                    break;
             }
             break;
         case DemuxFilterMainType::MMTP:
diff --git a/usb/1.0/vts/functional/Android.bp b/usb/1.0/vts/functional/Android.bp
index 683ee17..1a3b56b 100644
--- a/usb/1.0/vts/functional/Android.bp
+++ b/usb/1.0/vts/functional/Android.bp
@@ -19,5 +19,5 @@
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalUsbV1_0TargetTest.cpp"],
     static_libs: ["android.hardware.usb@1.0"],
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp b/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp
index ee7ef1b..bba75c8 100644
--- a/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp
+++ b/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp
@@ -20,9 +20,10 @@
 #include <android/hardware/usb/1.0/IUsb.h>
 #include <android/hardware/usb/1.0/IUsbCallback.h>
 #include <android/hardware/usb/1.0/types.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
 #include <log/log.h>
 #include <stdlib.h>
 #include <chrono>
@@ -49,20 +50,8 @@
 using ::android::hardware::Void;
 using ::android::sp;
 
-// Test environment for Usb HIDL HAL.
-class UsbHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
-  // get the test environment singleton
-  static UsbHidlEnvironment* Instance() {
-    static UsbHidlEnvironment* instance = new UsbHidlEnvironment;
-    return instance;
-  }
-
-  virtual void registerTestServices() override { registerTestService<IUsb>(); }
-};
-
 // The main test class for the USB hidl HAL
-class UsbHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class UsbHidlTest : public testing::TestWithParam<std::string> {
  public:
   // Callback class for the USB HIDL hal.
   // Usb Hal will call this object upon role switch or port query.
@@ -109,8 +98,7 @@
 
   virtual void SetUp() override {
     ALOGI("Setup");
-    usb = ::testing::VtsHalHidlTargetTestBase::getService<IUsb>(
-        UsbHidlEnvironment::Instance()->getServiceName<IUsb>());
+    usb = IUsb::getService(GetParam());
     ASSERT_NE(usb, nullptr);
 
     usb_cb_2 = new UsbCallback(*this, 2);
@@ -182,7 +170,7 @@
  * Callback oject is created and registered.
  * Check to see if the hidl transaction succeeded.
  */
-TEST_F(UsbHidlTest, setCallback) {
+TEST_P(UsbHidlTest, setCallback) {
   usb_cb_1 = new UsbCallback(*this, 1);
   ASSERT_NE(usb_cb_1, nullptr);
   Return<void> ret = usb->setCallback(usb_cb_1);
@@ -193,7 +181,7 @@
  * Check to see if querying type-c
  * port status succeeds.
  */
-TEST_F(UsbHidlTest, queryPortStatus) {
+TEST_P(UsbHidlTest, queryPortStatus) {
   Return<void> ret = usb->queryPortStatus();
   ASSERT_TRUE(ret.isOk());
   EXPECT_EQ(std::cv_status::no_timeout, wait());
@@ -206,7 +194,7 @@
  * This test case tried to switch the port with empty
  * name which is expected to fail.
  */
-TEST_F(UsbHidlTest, switchEmptyPort) {
+TEST_P(UsbHidlTest, switchEmptyPort) {
   struct PortRole role;
   role.type = PortRoleType::DATA_ROLE;
 
@@ -218,52 +206,6 @@
 }
 
 /*
- * Test switching the mode of usb port.
- * Test case queries the usb ports present in device.
- * If there is atleast one usb port, a mode switch
- * to DFP is attempted for the port.
- * The callback parametes are checked to see if the mode
- * switch was successfull. Upon success, Status::SUCCESS
- * is expected to be returned.
- */
-TEST_F(UsbHidlTest, switchModetoDFP) {
-  struct PortRole role;
-  role.type = PortRoleType::MODE;
-  role.role = static_cast<uint32_t>(PortMode::DFP);
-
-  Return<void> ret = usb->queryPortStatus();
-  ASSERT_TRUE(ret.isOk());
-  EXPECT_EQ(std::cv_status::no_timeout, wait());
-  EXPECT_EQ(2, usb_last_cookie);
-
-  if (!usb_last_port_status.portName.empty()) {
-    hidl_string portBeingSwitched = usb_last_port_status.portName;
-    ALOGI("mode portname:%s", portBeingSwitched.c_str());
-    usb_role_switch_done = false;
-    Return<void> ret = usb->switchRole(portBeingSwitched.c_str(), role);
-    ASSERT_TRUE(ret.isOk());
-
-    std::cv_status waitStatus = wait();
-    while (waitStatus == std::cv_status::no_timeout &&
-           usb_role_switch_done == false)
-      waitStatus = wait();
-
-    EXPECT_EQ(std::cv_status::no_timeout, waitStatus);
-    EXPECT_EQ(2, usb_last_cookie);
-
-    EXPECT_EQ(static_cast<uint32_t>(PortRoleType::MODE),
-              static_cast<uint32_t>(usb_last_port_role.type));
-    if (usb_last_status == Status::SUCCESS) {
-      EXPECT_EQ(static_cast<uint32_t>(PortMode::DFP),
-                static_cast<uint32_t>(usb_last_port_role.role));
-    } else {
-      EXPECT_NE(static_cast<uint32_t>(PortMode::UFP),
-                static_cast<uint32_t>(usb_last_port_role.role));
-    }
-  }
-}
-
-/*
  * Test switching the power role of usb port.
  * Test case queries the usb ports present in device.
  * If there is atleast one usb port, a power role switch
@@ -273,7 +215,7 @@
  * is expected to be returned.
  */
 
-TEST_F(UsbHidlTest, switchPowerRole) {
+TEST_P(UsbHidlTest, switchPowerRole) {
   struct PortRole role;
   role.type = PortRoleType::POWER_ROLE;
   role.role = static_cast<uint32_t>(PortPowerRole::SOURCE);
@@ -319,7 +261,7 @@
  * switch was successfull. Upon success, Status::SUCCESS
  * is expected to be returned.
  */
-TEST_F(UsbHidlTest, switchDataRole) {
+TEST_P(UsbHidlTest, switchDataRole) {
   struct PortRole role;
   role.type = PortRoleType::DATA_ROLE;
   role.role = static_cast<uint32_t>(PortDataRole::HOST);
@@ -356,11 +298,7 @@
   }
 }
 
-int main(int argc, char** argv) {
-  ::testing::AddGlobalTestEnvironment(UsbHidlEnvironment::Instance());
-  ::testing::InitGoogleTest(&argc, argv);
-  UsbHidlEnvironment::Instance()->init(&argc, argv);
-  int status = RUN_ALL_TESTS();
-  ALOGI("Test result = %d", status);
-  return status;
-}
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, UsbHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IUsb::descriptor)),
+        android::hardware::PrintInstanceNameToString);
diff --git a/vibrator/1.4/Android.bp b/vibrator/1.4/Android.bp
deleted file mode 100644
index acfc795..0000000
--- a/vibrator/1.4/Android.bp
+++ /dev/null
@@ -1,19 +0,0 @@
-// This file is autogenerated by hidl-gen -Landroidbp.
-
-hidl_interface {
-    name: "android.hardware.vibrator@1.4",
-    root: "android.hardware",
-    srcs: [
-        "types.hal",
-        "IVibrator.hal",
-        "IVibratorCallback.hal",
-    ],
-    interfaces: [
-        "android.hardware.vibrator@1.0",
-        "android.hardware.vibrator@1.1",
-        "android.hardware.vibrator@1.2",
-        "android.hardware.vibrator@1.3",
-        "android.hidl.base@1.0",
-    ],
-    gen_java: true,
-}
diff --git a/vibrator/1.4/IVibrator.hal b/vibrator/1.4/IVibrator.hal
deleted file mode 100644
index 913abe3..0000000
--- a/vibrator/1.4/IVibrator.hal
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.
- */
-
-package android.hardware.vibrator@1.4;
-
-import @1.0::EffectStrength;
-import @1.3::Effect;
-import @1.0::Status;
-import @1.3::IVibrator;
-import IVibratorCallback;
-
-interface IVibrator extends @1.3::IVibrator {
-    /**
-     * Determine capabilities of the vibrator HAL.
-     */
-    getCapabilities() generates (bitfield<Capabilities> capabilities);
-
-    /**
-     * Turn on vibrator
-     *
-     * This function must only be called after the previous timeout has expired or
-     * was canceled (through off()).
-     * @param timeoutMs number of milliseconds to vibrate.
-     * @param callback A callback used to inform Frameworks of state change, if supported.
-     * @return vibratorOnRet whether vibrator command was successful or not.
-     */
-    on_1_4(uint32_t timeoutMs, IVibratorCallback callback) generates (Status vibratorOnRet);
-
-    /**
-     * Fire off a predefined haptic event.
-     *
-     * @param effect The type of haptic event to trigger.
-     * @param strength The intensity of haptic event to trigger.
-     * @param callback A callback used to inform Frameworks of state change, if supported.
-     * @return status Whether the effect was successfully performed or not. Must
-     *     return Status::UNSUPPORTED_OPERATION if the effect is not supported.
-     * @return lengthMs The length of time the event is expected to take in
-     *     milliseconds. This doesn't need to be perfectly accurate, but should be a reasonable
-     *     approximation. Should be a positive, non-zero value if the returned status is Status::OK,
-     *     and set to 0 otherwise.
-     */
-    perform_1_4(Effect effect, EffectStrength strength, IVibratorCallback callback)
-        generates (Status status, uint32_t lengthMs);
-};
diff --git a/vibrator/1.4/vts/functional/VtsHalVibratorV1_4TargetTest.cpp b/vibrator/1.4/vts/functional/VtsHalVibratorV1_4TargetTest.cpp
deleted file mode 100644
index 1b6abe9..0000000
--- a/vibrator/1.4/vts/functional/VtsHalVibratorV1_4TargetTest.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * 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 "vibrator_hidl_hal_test"
-
-#include <android-base/logging.h>
-#include <android/hardware/vibrator/1.0/types.h>
-#include <android/hardware/vibrator/1.4/IVibrator.h>
-#include <gtest/gtest.h>
-#include <hidl/GtestPrinter.h>
-#include <hidl/ServiceManagement.h>
-
-#include <getopt.h>
-#include <unistd.h>
-
-#include <future>
-
-using ::android::sp;
-using ::android::hardware::hidl_bitfield;
-using ::android::hardware::hidl_enum_range;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::vibrator::V1_0::EffectStrength;
-using ::android::hardware::vibrator::V1_0::Status;
-using ::android::hardware::vibrator::V1_3::Effect;
-using ::android::hardware::vibrator::V1_4::Capabilities;
-using ::android::hardware::vibrator::V1_4::IVibrator;
-using ::android::hardware::vibrator::V1_4::IVibratorCallback;
-
-static uint32_t sCompletionLimitMs = UINT32_MAX;
-
-#define EXPECT_OK(ret) ASSERT_TRUE((ret).isOk())
-
-class CompletionCallback : public IVibratorCallback {
-  public:
-    CompletionCallback(std::function<void()> callback) : mCallback(callback) {}
-    Return<void> onComplete() override {
-        mCallback();
-        return Void();
-    }
-
-  private:
-    std::function<void()> mCallback;
-};
-
-class VibratorHidlTest_1_4 : public testing::TestWithParam<std::string> {
-  public:
-    virtual void SetUp() override {
-        vibrator = IVibrator::getService(GetParam());
-        ASSERT_NE(vibrator, nullptr);
-        capabilities = vibrator->getCapabilities();
-    }
-
-    virtual void TearDown() override {}
-
-    sp<IVibrator> vibrator;
-    hidl_bitfield<Capabilities> capabilities;
-};
-
-TEST_P(VibratorHidlTest_1_4, OnWithCallback) {
-    if (capabilities & Capabilities::ON_COMPLETION_CALLBACK) {
-        std::promise<void> completionPromise;
-        std::future<void> completionFuture{completionPromise.get_future()};
-        sp<CompletionCallback> callback =
-                new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
-        uint32_t duration = 250;
-        std::chrono::milliseconds timeout{duration * 2};
-        EXPECT_EQ(Status::OK, vibrator->on_1_4(duration, callback));
-        EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
-        vibrator->off();
-    }
-}
-
-static void validatePerformEffectUnsupportedOperation(Status status, uint32_t lengthMs) {
-    ASSERT_EQ(Status::UNSUPPORTED_OPERATION, status);
-    ASSERT_EQ(static_cast<uint32_t>(0), lengthMs)
-            << "Effects that return UNSUPPORTED_OPERATION must have a duration of zero";
-}
-
-static void validatePerformEffect(Status status, uint32_t lengthMs) {
-    ASSERT_TRUE(status == Status::OK || status == Status::UNSUPPORTED_OPERATION);
-    if (status == Status::OK) {
-        ASSERT_LT(static_cast<uint32_t>(0), lengthMs)
-                << "Effects that return OK must return a positive duration";
-    } else {
-        validatePerformEffectUnsupportedOperation(status, lengthMs);
-    }
-}
-
-/*
- * Test to make sure effects within the valid range return are either supported and return OK with
- * a valid duration, or are unsupported and return UNSUPPORTED_OPERATION with a duration of 0.
- */
-TEST_P(VibratorHidlTest_1_4, PerformEffect_1_4) {
-    Status performStatus;
-    uint32_t performLength;
-    auto validateWrapper = [&](Status status, uint32_t lengthMs) {
-        performStatus = status;
-        performLength = lengthMs;
-        validatePerformEffect(status, lengthMs);
-    };
-    for (const auto& effect : hidl_enum_range<Effect>()) {
-        for (const auto& strength : hidl_enum_range<EffectStrength>()) {
-            std::promise<void> completionPromise;
-            std::future<void> completionFuture{completionPromise.get_future()};
-            sp<CompletionCallback> callback =
-                    new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
-            EXPECT_OK(vibrator->perform_1_4(effect, strength, callback, validateWrapper));
-            if (performStatus == Status::OK && performLength < sCompletionLimitMs &&
-                (capabilities & Capabilities::PERFORM_COMPLETION_CALLBACK)) {
-                std::chrono::milliseconds timeout{performLength * 2};
-                EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
-            }
-        }
-    }
-}
-
-/*
- * Test to make sure effect values above the valid range are rejected.
- */
-TEST_P(VibratorHidlTest_1_4, PerformEffect_1_4_BadEffects_AboveValidRange) {
-    Effect effect = *std::prev(hidl_enum_range<Effect>().end());
-    Effect badEffect = static_cast<Effect>(static_cast<int32_t>(effect) + 1);
-    EXPECT_OK(vibrator->perform_1_4(badEffect, EffectStrength::LIGHT, nullptr,
-                                    validatePerformEffectUnsupportedOperation));
-}
-
-/*
- * Test to make sure effect values below the valid range are rejected.
- */
-TEST_P(VibratorHidlTest_1_4, PerformEffect_1_4_BadEffects_BelowValidRange) {
-    Effect effect = *hidl_enum_range<Effect>().begin();
-    Effect badEffect = static_cast<Effect>(static_cast<int32_t>(effect) - 1);
-    EXPECT_OK(vibrator->perform_1_4(badEffect, EffectStrength::LIGHT, nullptr,
-                                    validatePerformEffectUnsupportedOperation));
-}
-
-/*
- * Test to make sure strength values above the valid range are rejected.
- */
-TEST_P(VibratorHidlTest_1_4, PerformEffect_1_4_BadStrength_AboveValidRange) {
-    EffectStrength strength = *std::prev(hidl_enum_range<EffectStrength>().end());
-    EffectStrength badStrength = static_cast<EffectStrength>(static_cast<int32_t>(strength) + 1);
-    EXPECT_OK(vibrator->perform_1_4(Effect::THUD, badStrength, nullptr,
-                                    validatePerformEffectUnsupportedOperation));
-}
-
-/*
- * Test to make sure strength values below the valid range are rejected.
- */
-TEST_P(VibratorHidlTest_1_4, PerformEffect_1_4_BadStrength_BelowValidRange) {
-    EffectStrength strength = *hidl_enum_range<EffectStrength>().begin();
-    EffectStrength badStrength = static_cast<EffectStrength>(static_cast<int32_t>(strength) - 1);
-    EXPECT_OK(vibrator->perform_1_4(Effect::THUD, badStrength, nullptr,
-                                    validatePerformEffectUnsupportedOperation));
-}
-
-INSTANTIATE_TEST_SUITE_P(
-        PerInstance, VibratorHidlTest_1_4,
-        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IVibrator::descriptor)),
-        android::hardware::PrintInstanceNameToString);
-
-enum {
-    OPTION_COMPLETION_LIMIT_MS,
-};
-
-int main(int argc, char** argv) {
-    struct option options[] = {
-            {"completion-limit-ms", required_argument, 0, OPTION_COMPLETION_LIMIT_MS}, {}};
-
-    printf("Running main() from %s\n", __FILE__);
-    testing::InitGoogleTest(&argc, argv);
-
-    while (true) {
-        int opt = getopt_long(argc, argv, "", options, nullptr);
-        if (opt == -1) {
-            break;
-        }
-        switch (opt) {
-            case OPTION_COMPLETION_LIMIT_MS:
-                std::istringstream(optarg) >> sCompletionLimitMs;
-                break;
-            default:
-                printf("Unrecognized option\n");
-                return -EINVAL;
-        }
-    }
-
-    return RUN_ALL_TESTS();
-}
diff --git a/vibrator/aidl/Android.bp b/vibrator/aidl/Android.bp
index 18468ef..1eec1da 100644
--- a/vibrator/aidl/Android.bp
+++ b/vibrator/aidl/Android.bp
@@ -7,8 +7,12 @@
     stability: "vintf",
     backend: {
         java: {
-            enabled: false,
+            platform_apis: true,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
         },
     },
 }
-
diff --git a/vibrator/1.4/types.hal b/vibrator/aidl/android/hardware/vibrator/CompositeEffect.aidl
similarity index 67%
copy from vibrator/1.4/types.hal
copy to vibrator/aidl/android/hardware/vibrator/CompositeEffect.aidl
index acc49b1..84556b5 100644
--- a/vibrator/1.4/types.hal
+++ b/vibrator/aidl/android/hardware/vibrator/CompositeEffect.aidl
@@ -14,9 +14,15 @@
  * limitations under the License.
  */
 
-package android.hardware.vibrator@1.4;
+package android.hardware.vibrator;
 
-enum Capabilities : uint32_t {
-    ON_COMPLETION_CALLBACK = 1 << 0,
-    PERFORM_COMPLETION_CALLBACK = 1 << 1,
-};
+import android.hardware.vibrator.CompositePrimitive;
+
+@VintfStability
+parcelable CompositeEffect {
+    /* Period of silence preceding primitive. */
+    int delayMs;
+    CompositePrimitive primitive;
+    /* 0.0 (exclusive) - 1.0 (inclusive) */
+    float scale;
+}
diff --git a/vibrator/1.4/types.hal b/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
similarity index 76%
rename from vibrator/1.4/types.hal
rename to vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
index acc49b1..2a9d0be 100644
--- a/vibrator/1.4/types.hal
+++ b/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
@@ -14,9 +14,16 @@
  * limitations under the License.
  */
 
-package android.hardware.vibrator@1.4;
+package android.hardware.vibrator;
 
-enum Capabilities : uint32_t {
-    ON_COMPLETION_CALLBACK = 1 << 0,
-    PERFORM_COMPLETION_CALLBACK = 1 << 1,
-};
+@VintfStability
+@Backing(type="int")
+enum CompositePrimitive {
+    NOOP,
+    CLICK,
+    THUD,
+    SPIN,
+    QUICK_RISE,
+    SLOW_RISE,
+    QUICK_FALL,
+}
diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
index 8c4fd05..ebf5faa 100644
--- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
@@ -19,6 +19,8 @@
 import android.hardware.vibrator.IVibratorCallback;
 import android.hardware.vibrator.Effect;
 import android.hardware.vibrator.EffectStrength;
+import android.hardware.vibrator.CompositeEffect;
+import android.hardware.vibrator.CompositePrimitive;
 
 @VintfStability
 interface IVibrator {
@@ -42,6 +44,10 @@
      * Whether setAmplitude is supported (when external control is enabled)
      */
     const int CAP_EXTERNAL_AMPLITUDE_CONTROL = 1 << 4;
+    /**
+     * Whether compose is supported.
+     */
+    const int CAP_COMPOSE_EFFECTS = 1 << 5;
 
     /**
      * Determine capabilities of the vibrator HAL (CAP_* mask)
@@ -107,11 +113,10 @@
      * CAP_EXTERNAL_AMPLITUDE_CONTROL.
      *
      * @param amplitude The unitless force setting. Note that this number must
-     *                  be between 1 and 255, inclusive. If the motor does not
-     *                  have exactly 255 steps, it must do it's best to map it
-     *                  onto the number of steps it does have.
+     *                  be between 0.0 (exclusive) and 1.0 (inclusive). It must
+     *                  do it's best to map it onto the number of steps it does have.
      */
-    void setAmplitude(in int amplitude);
+    void setAmplitude(in float amplitude);
 
     /**
      * Enables/disables control override of vibrator to audio.
@@ -128,4 +133,36 @@
      * @param enabled Whether external control should be enabled or disabled.
      */
     void setExternalControl(in boolean enabled);
+
+    /**
+     * Retrieve composition delay limit.
+     *
+     * Support is reflected in getCapabilities (CAP_COMPOSE_EFFECTS).
+     *
+     * @return Maximum delay for a single CompositeEffect[] entry.
+     */
+    int getCompositionDelayMax();
+
+    /**
+     * Retrieve composition size limit.
+     *
+     * Support is reflected in getCapabilities (CAP_COMPOSE_EFFECTS).
+     *
+     * @return Maximum number of entries in CompositeEffect[].
+     * @param maxDelayMs Maximum delay for a single CompositeEffect[] entry.
+     */
+    int getCompositionSizeMax();
+
+    /**
+     * Fire off a string of effect primitives, combined to perform richer effects.
+     *
+     * Support is reflected in getCapabilities (CAP_COMPOSE_EFFECTS).
+     *
+     * Doing this operation while the vibrator is already on is undefined behavior. Clients should
+     * explicitly call off.
+     *
+     * @param composite Array of composition parameters.
+     */
+    void compose(in CompositeEffect[] composite, in IVibratorCallback callback);
+
 }
diff --git a/vibrator/aidl/default/Android.bp b/vibrator/aidl/default/Android.bp
index f399887..dc8867f 100644
--- a/vibrator/aidl/default/Android.bp
+++ b/vibrator/aidl/default/Android.bp
@@ -1,3 +1,19 @@
+cc_library_static {
+    name: "libvibratorexampleimpl",
+    vendor: true,
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "vintf-vibrator-ndk_platform",
+    ],
+    export_include_dirs: ["include"],
+    srcs: ["Vibrator.cpp"],
+    visibility: [
+         ":__subpackages__",
+         "//hardware/interfaces/tests/extension/vibrator:__subpackages__",
+    ],
+}
+
 cc_binary {
     name: "android.hardware.vibrator-service.example",
     relative_install_path: "hw",
@@ -9,5 +25,8 @@
         "libbinder_ndk",
         "vintf-vibrator-ndk_platform",
     ],
-    srcs: ["main.cpp", "Vibrator.cpp"],
+    static_libs: [
+        "libvibratorexampleimpl",
+    ],
+    srcs: ["main.cpp"],
 }
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index 18be1a6..befdeab 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "Vibrator.h"
+#include "vibrator-impl/Vibrator.h"
 
 #include <android-base/logging.h>
 #include <thread>
@@ -24,11 +24,14 @@
 namespace hardware {
 namespace vibrator {
 
+static constexpr int32_t kComposeDelayMaxMs = 1000;
+static constexpr int32_t kComposeSizeMax = 256;
+
 ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) {
     LOG(INFO) << "Vibrator reporting capabilities";
     *_aidl_return = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK |
                     IVibrator::CAP_AMPLITUDE_CONTROL | IVibrator::CAP_EXTERNAL_CONTROL |
-                    IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL;
+                    IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL | IVibrator::CAP_COMPOSE_EFFECTS;
     return ndk::ScopedAStatus::ok();
 }
 
@@ -45,7 +48,9 @@
             LOG(INFO) << "Starting on on another thread";
             usleep(timeoutMs * 1000);
             LOG(INFO) << "Notifying on complete";
-            callback->onComplete();
+            if (!callback->onComplete().isOk()) {
+                LOG(ERROR) << "Failed to call onComplete";
+            }
         }).detach();
     }
     return ndk::ScopedAStatus::ok();
@@ -84,9 +89,9 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Vibrator::setAmplitude(int32_t amplitude) {
+ndk::ScopedAStatus Vibrator::setAmplitude(float amplitude) {
     LOG(INFO) << "Vibrator set amplitude: " << amplitude;
-    if (amplitude <= 0 || amplitude > 255) {
+    if (amplitude <= 0.0f || amplitude > 1.0f) {
         return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_ARGUMENT));
     }
     return ndk::ScopedAStatus::ok();
@@ -97,6 +102,55 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus Vibrator::getCompositionDelayMax(int32_t* maxDelayMs) {
+    *maxDelayMs = kComposeDelayMaxMs;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::getCompositionSizeMax(int32_t* maxSize) {
+    *maxSize = kComposeSizeMax;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::compose(const std::vector<CompositeEffect>& composite,
+                                     const std::shared_ptr<IVibratorCallback>& callback) {
+    if (composite.size() > kComposeSizeMax) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+
+    for (auto& e : composite) {
+        if (e.delayMs > kComposeDelayMaxMs) {
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+        if (e.scale <= 0.0f || e.scale > 1.0f) {
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+        if (e.primitive < CompositePrimitive::NOOP ||
+            e.primitive > CompositePrimitive::QUICK_FALL) {
+            return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+        }
+    }
+
+    std::thread([=] {
+        LOG(INFO) << "Starting compose on another thread";
+
+        for (auto& e : composite) {
+            if (e.delayMs) {
+                usleep(e.delayMs * 1000);
+            }
+            LOG(INFO) << "triggering primitive " << static_cast<int>(e.primitive) << " @ scale "
+                      << e.scale;
+        }
+
+        if (callback != nullptr) {
+            LOG(INFO) << "Notifying perform complete";
+            callback->onComplete();
+        }
+    }).detach();
+
+    return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace vibrator
 }  // namespace hardware
 }  // namespace android
diff --git a/vibrator/aidl/default/Vibrator.h b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
similarity index 80%
rename from vibrator/aidl/default/Vibrator.h
rename to vibrator/aidl/default/include/vibrator-impl/Vibrator.h
index 14e7292..817ec80 100644
--- a/vibrator/aidl/default/Vibrator.h
+++ b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
@@ -32,8 +32,12 @@
                                const std::shared_ptr<IVibratorCallback>& callback,
                                int32_t* _aidl_return) override;
     ndk::ScopedAStatus getSupportedEffects(std::vector<Effect>* _aidl_return) override;
-    ndk::ScopedAStatus setAmplitude(int32_t amplitude) override;
+    ndk::ScopedAStatus setAmplitude(float amplitude) override;
     ndk::ScopedAStatus setExternalControl(bool enabled) override;
+    ndk::ScopedAStatus getCompositionDelayMax(int32_t* maxDelayMs);
+    ndk::ScopedAStatus getCompositionSizeMax(int32_t* maxSize);
+    ndk::ScopedAStatus compose(const std::vector<CompositeEffect>& composite,
+                               const std::shared_ptr<IVibratorCallback>& callback) override;
 };
 
 }  // namespace vibrator
diff --git a/vibrator/aidl/default/main.cpp b/vibrator/aidl/default/main.cpp
index d1619ff..ebb0905 100644
--- a/vibrator/aidl/default/main.cpp
+++ b/vibrator/aidl/default/main.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "Vibrator.h"
+#include "vibrator-impl/Vibrator.h"
 
 #include <android-base/logging.h>
 #include <android/binder_manager.h>
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index b6aa9e2..6f9ba1a 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -28,6 +28,8 @@
 using android::String16;
 using android::binder::Status;
 using android::hardware::vibrator::BnVibratorCallback;
+using android::hardware::vibrator::CompositeEffect;
+using android::hardware::vibrator::CompositePrimitive;
 using android::hardware::vibrator::Effect;
 using android::hardware::vibrator::EffectStrength;
 using android::hardware::vibrator::IVibrator;
@@ -55,6 +57,20 @@
         static_cast<EffectStrength>(static_cast<int8_t>(kEffectStrengths.back()) + 1),
 };
 
+// TODO(b/143992652): autogenerate
+const std::vector<CompositePrimitive> kCompositePrimitives = {
+        CompositePrimitive::NOOP,       CompositePrimitive::CLICK,
+        CompositePrimitive::THUD,       CompositePrimitive::SPIN,
+        CompositePrimitive::QUICK_RISE, CompositePrimitive::SLOW_RISE,
+        CompositePrimitive::QUICK_FALL,
+};
+// TODO(b/143992652): autogenerate
+
+const std::vector<CompositePrimitive> kInvalidPrimitives = {
+        static_cast<CompositePrimitive>(static_cast<int32_t>(kCompositePrimitives.front()) - 1),
+        static_cast<CompositePrimitive>(static_cast<int32_t>(kCompositePrimitives.back()) + 1),
+};
+
 class CompletionCallback : public BnVibratorCallback {
   public:
     CompletionCallback(const std::function<void()>& callback) : mCallback(callback) {}
@@ -119,13 +135,12 @@
             Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
 
             if (isEffectSupported) {
-                EXPECT_TRUE(status.isOk())
-                        << static_cast<int>(effect) << " " << static_cast<int>(strength);
+                EXPECT_TRUE(status.isOk()) << toString(effect) << " " << toString(strength);
                 EXPECT_GT(lengthMs, 0);
                 usleep(lengthMs * 1000);
             } else {
                 EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
-                        << static_cast<int>(effect) << " " << static_cast<int>(strength);
+                        << toString(effect) << " " << toString(strength);
                 EXPECT_EQ(lengthMs, 0);
             }
         }
@@ -186,7 +201,7 @@
             int32_t lengthMs;
             Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
             EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
-                    << static_cast<int>(effect) << " " << static_cast<int>(strength);
+                    << toString(effect) << " " << toString(strength);
         }
     }
     for (Effect effect : kEffects) {
@@ -194,18 +209,18 @@
             int32_t lengthMs;
             Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
             EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
-                    << static_cast<int>(effect) << " " << static_cast<int>(strength);
+                    << toString(effect) << " " << toString(strength);
         }
     }
 }
 
 TEST_P(VibratorAidl, ChangeVibrationAmplitude) {
     if (capabilities & IVibrator::CAP_AMPLITUDE_CONTROL) {
-        EXPECT_TRUE(vibrator->setAmplitude(1).isOk());
+        EXPECT_EQ(Status::EX_NONE, vibrator->setAmplitude(0.1f).exceptionCode());
         EXPECT_TRUE(vibrator->on(2000, nullptr /*callback*/).isOk());
-        EXPECT_TRUE(vibrator->setAmplitude(128).isOk());
+        EXPECT_EQ(Status::EX_NONE, vibrator->setAmplitude(0.5f).exceptionCode());
         sleep(1);
-        EXPECT_TRUE(vibrator->setAmplitude(255).isOk());
+        EXPECT_EQ(Status::EX_NONE, vibrator->setAmplitude(1.0f).exceptionCode());
         sleep(1);
     }
 }
@@ -214,7 +229,7 @@
     if (capabilities & IVibrator::CAP_AMPLITUDE_CONTROL) {
         EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->setAmplitude(-1).exceptionCode());
         EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->setAmplitude(0).exceptionCode());
-        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->setAmplitude(256).exceptionCode());
+        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, vibrator->setAmplitude(1.1).exceptionCode());
     }
 }
 
@@ -240,7 +255,7 @@
     if (capabilities & IVibrator::CAP_EXTERNAL_CONTROL) {
         EXPECT_TRUE(vibrator->setExternalControl(true).isOk());
 
-        Status amplitudeStatus = vibrator->setAmplitude(128);
+        Status amplitudeStatus = vibrator->setAmplitude(0.5);
         if (supportsExternalAmplitudeControl) {
             EXPECT_TRUE(amplitudeStatus.isOk());
         } else {
@@ -259,6 +274,102 @@
     }
 }
 
+TEST_P(VibratorAidl, ComposeValidPrimitives) {
+    if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
+        int32_t maxDelay, maxSize;
+
+        EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionDelayMax(&maxDelay).exceptionCode());
+        EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionSizeMax(&maxSize).exceptionCode());
+
+        std::vector<CompositeEffect> composite;
+
+        for (auto primitive : kCompositePrimitives) {
+            CompositeEffect effect;
+
+            effect.delayMs = std::rand() % (maxDelay + 1);
+            effect.primitive = primitive;
+            effect.scale = static_cast<float>(std::rand()) / RAND_MAX ?: 1.0f;
+            composite.emplace_back(effect);
+
+            if (composite.size() == maxSize) {
+                EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
+                composite.clear();
+                vibrator->off();
+            }
+        }
+
+        if (composite.size() != 0) {
+            EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
+            vibrator->off();
+        }
+    }
+}
+
+TEST_P(VibratorAidl, ComposeUnsupportedPrimitives) {
+    if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
+        for (auto primitive : kInvalidPrimitives) {
+            std::vector<CompositeEffect> composite(1);
+
+            for (auto& effect : composite) {
+                effect.delayMs = 0;
+                effect.primitive = primitive;
+                effect.scale = 1.0f;
+            }
+            EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,
+                      vibrator->compose(composite, nullptr).exceptionCode());
+            vibrator->off();
+        }
+    }
+}
+
+TEST_P(VibratorAidl, CompseDelayBoundary) {
+    if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
+        int32_t maxDelay;
+
+        EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionDelayMax(&maxDelay).exceptionCode());
+
+        std::vector<CompositeEffect> composite(1);
+        CompositeEffect effect;
+
+        effect.delayMs = 1;
+        effect.primitive = CompositePrimitive::CLICK;
+        effect.scale = 1.0f;
+
+        std::fill(composite.begin(), composite.end(), effect);
+        EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
+
+        effect.delayMs = maxDelay + 1;
+
+        std::fill(composite.begin(), composite.end(), effect);
+        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+                  vibrator->compose(composite, nullptr).exceptionCode());
+        vibrator->off();
+    }
+}
+
+TEST_P(VibratorAidl, CompseSizeBoundary) {
+    if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
+        int32_t maxSize;
+
+        EXPECT_EQ(Status::EX_NONE, vibrator->getCompositionSizeMax(&maxSize).exceptionCode());
+
+        std::vector<CompositeEffect> composite(maxSize);
+        CompositeEffect effect;
+
+        effect.delayMs = 1;
+        effect.primitive = CompositePrimitive::CLICK;
+        effect.scale = 1.0f;
+
+        std::fill(composite.begin(), composite.end(), effect);
+        EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
+
+        composite.emplace_back(effect);
+        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+                  vibrator->compose(composite, nullptr).exceptionCode());
+        vibrator->off();
+    }
+}
+
 INSTANTIATE_TEST_SUITE_P(Vibrator, VibratorAidl,
                          testing::ValuesIn(android::getAidlHalInstanceNames(IVibrator::descriptor)),
                          android::PrintInstanceNameToString);
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
index f3068f2..bf77503 100644
--- a/wifi/1.0/vts/functional/Android.bp
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -52,7 +52,7 @@
         "android.hardware.wifi@1.3",
         "libwifi-system-iface"
     ],
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "vts-core"],
 }
 
 // These tests are split out so that they can be conditioned on presence of the
@@ -70,7 +70,7 @@
         "android.hardware.wifi@1.0",
         "libwifi-system-iface"
     ],
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "vts-core"],
 }
 
 // These tests are split out so that they can be conditioned on presence of
@@ -88,5 +88,5 @@
         "android.hardware.wifi@1.0",
         "libwifi-system-iface"
     ],
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/wifi/1.0/vts/functional/VtsHalWifiV1_0TargetTest.cpp b/wifi/1.0/vts/functional/VtsHalWifiV1_0TargetTest.cpp
index 9d25014..128dae5 100644
--- a/wifi/1.0/vts/functional/VtsHalWifiV1_0TargetTest.cpp
+++ b/wifi/1.0/vts/functional/VtsHalWifiV1_0TargetTest.cpp
@@ -14,34 +14,8 @@
  * limitations under the License.
  */
 
-#include <android-base/logging.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 
-#include "wifi_hidl_test_utils.h"
-
-class WifiVtsHidlEnvironment_1_0 : public WifiHidlEnvironment {
-   public:
-    // get the test environment singleton
-    static WifiVtsHidlEnvironment_1_0* Instance() {
-        static WifiVtsHidlEnvironment_1_0* instance =
-            new WifiVtsHidlEnvironment_1_0;
-        return instance;
-    }
-
-    virtual void registerTestServices() override {
-        registerTestService<android::hardware::wifi::V1_0::IWifi>();
-    }
-
-   private:
-    WifiVtsHidlEnvironment_1_0() {}
-};
-
-WifiHidlEnvironment* gEnv = WifiVtsHidlEnvironment_1_0::Instance();
-
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(gEnv);
-    ::testing::InitGoogleTest(&argc, argv);
-    gEnv->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    LOG(INFO) << "Test result = " << status;
-    return status;
-}
+// TODO(b/143892896): Remove this file after wifi_hidl_test_utils.cpp is
+// updated.
+::testing::VtsHalHidlTargetTestEnvBase* gEnv = nullptr;
\ No newline at end of file
diff --git a/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
index c55221d..8be8a0c 100644
--- a/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
@@ -16,35 +16,37 @@
 
 #include <android-base/logging.h>
 
+#include <android/hardware/wifi/1.0/IWifi.h>
 #include <android/hardware/wifi/1.0/IWifiApIface.h>
-
-#include <VtsHalHidlTargetTestBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include "wifi_hidl_call_util.h"
 #include "wifi_hidl_test_utils.h"
 
+using ::android::sp;
 using ::android::hardware::wifi::V1_0::IfaceType;
+using ::android::hardware::wifi::V1_0::IWifi;
 using ::android::hardware::wifi::V1_0::IWifiApIface;
 using ::android::hardware::wifi::V1_0::WifiBand;
 using ::android::hardware::wifi::V1_0::WifiStatusCode;
-using ::android::sp;
 
 /**
  * Fixture to use for all AP Iface HIDL interface tests.
  */
-class WifiApIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class WifiApIfaceHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
-        wifi_ap_iface_ = getWifiApIface();
+        wifi_ap_iface_ = getWifiApIface(GetInstanceName());
         ASSERT_NE(nullptr, wifi_ap_iface_.get());
     }
 
-    virtual void TearDown() override {
-        stopWifi();
-    }
+    virtual void TearDown() override { stopWifi(GetInstanceName()); }
 
    protected:
     sp<IWifiApIface> wifi_ap_iface_;
+    std::string GetInstanceName() { return GetParam(); }
 };
 
 /*
@@ -52,16 +54,15 @@
  * Ensures that an instance of the IWifiApIface proxy object is
  * successfully created.
  */
-TEST(WifiApIfaceHidlTestNoFixture, Create) {
-    EXPECT_NE(nullptr, getWifiApIface().get());
-    stopWifi();
+TEST_P(WifiApIfaceHidlTest, Create) {
+    // The creation of a proxy object is tested as part of SetUp method.
 }
 
 /*
  * GetType:
  * Ensures that the correct interface type is returned for AP interface.
  */
-TEST_F(WifiApIfaceHidlTest, GetType) {
+TEST_P(WifiApIfaceHidlTest, GetType) {
     const auto& status_and_type = HIDL_INVOKE(wifi_ap_iface_, getType);
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_type.first.code);
     EXPECT_EQ(IfaceType::AP, status_and_type.second);
@@ -72,7 +73,7 @@
  * Ensures that a call to set the country code will return with a success
  * status code.
  */
-TEST_F(WifiApIfaceHidlTest, SetCountryCode) {
+TEST_P(WifiApIfaceHidlTest, SetCountryCode) {
     const android::hardware::hidl_array<int8_t, 2> kCountryCode{
         std::array<int8_t, 2>{{0x55, 0x53}}};
     EXPECT_EQ(WifiStatusCode::SUCCESS,
@@ -83,9 +84,15 @@
  * GetValidFrequenciesForBand:
  * Ensures that we can retrieve valid frequencies for 2.4 GHz band.
  */
-TEST_F(WifiApIfaceHidlTest, GetValidFrequenciesForBand) {
+TEST_P(WifiApIfaceHidlTest, GetValidFrequenciesForBand) {
     const auto& status_and_freqs = HIDL_INVOKE(
         wifi_ap_iface_, getValidFrequenciesForBand, WifiBand::BAND_24GHZ);
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_freqs.first.code);
     EXPECT_GT(status_and_freqs.second.size(), 0u);
 }
+
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, WifiApIfaceHidlTest,
+    testing::ValuesIn(
+        android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
+    android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp b/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp
index 232ffdd..33817d5 100644
--- a/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp
@@ -16,9 +16,11 @@
 
 #include <android-base/logging.h>
 
+#include <android/hardware/wifi/1.0/IWifi.h>
 #include <android/hardware/wifi/1.0/IWifiChip.h>
-
-#include <VtsHalHidlTargetTestBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include "wifi_hidl_call_util.h"
 #include "wifi_hidl_test_utils.h"
@@ -26,6 +28,7 @@
 using ::android::sp;
 using ::android::hardware::wifi::V1_0::ChipModeId;
 using ::android::hardware::wifi::V1_0::IfaceType;
+using ::android::hardware::wifi::V1_0::IWifi;
 using ::android::hardware::wifi::V1_0::IWifiApIface;
 using ::android::hardware::wifi::V1_0::IWifiChip;
 using ::android::hardware::wifi::V1_0::IWifiIface;
@@ -35,14 +38,14 @@
 /**
  * Fixture for IWifiChip tests that are conditioned on SoftAP support.
  */
-class WifiChipHidlApTest : public ::testing::VtsHalHidlTargetTestBase {
+class WifiChipHidlApTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
-        wifi_chip_ = getWifiChip();
+        wifi_chip_ = getWifiChip(GetInstanceName());
         ASSERT_NE(nullptr, wifi_chip_.get());
     }
 
-    virtual void TearDown() override { stopWifi(); }
+    virtual void TearDown() override { stopWifi(GetInstanceName()); }
 
    protected:
     // Helper function to configure the Chip in one of the supported modes.
@@ -72,6 +75,9 @@
     }
 
     sp<IWifiChip> wifi_chip_;
+
+   private:
+    std::string GetInstanceName() { return GetParam(); }
 };
 
 /*
@@ -79,7 +85,7 @@
  * Configures the chip in AP mode and ensures that at least 1 iface creation
  * succeeds.
  */
-TEST_F(WifiChipHidlApTest, CreateApIface) {
+TEST_P(WifiChipHidlApTest, CreateApIface) {
     configureChipForIfaceType(IfaceType::AP, true);
 
     sp<IWifiApIface> iface;
@@ -93,7 +99,7 @@
  * before creating the iface. Then, create the iface and ensure that
  * iface name is returned via the list.
  */
-TEST_F(WifiChipHidlApTest, GetApIfaceNames) {
+TEST_P(WifiChipHidlApTest, GetApIfaceNames) {
     configureChipForIfaceType(IfaceType::AP, true);
 
     const auto& status_and_iface_names1 =
@@ -125,7 +131,7 @@
  * the iface object using the correct name and ensure any other name
  * doesn't retrieve an iface object.
  */
-TEST_F(WifiChipHidlApTest, GetApIface) {
+TEST_P(WifiChipHidlApTest, GetApIface) {
     configureChipForIfaceType(IfaceType::AP, true);
 
     sp<IWifiApIface> ap_iface;
@@ -151,7 +157,7 @@
  * the iface object using the correct name and ensure any other name
  * doesn't remove the iface.
  */
-TEST_F(WifiChipHidlApTest, RemoveApIface) {
+TEST_P(WifiChipHidlApTest, RemoveApIface) {
     configureChipForIfaceType(IfaceType::AP, true);
 
     sp<IWifiApIface> ap_iface;
@@ -166,3 +172,9 @@
     // No such iface exists now. So, this should return failure.
     EXPECT_EQ(WifiStatusCode::ERROR_INVALID_ARGS, removeApIface(iface_name));
 }
+
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, WifiChipHidlApTest,
+    testing::ValuesIn(
+        android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
+    android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/wifi/1.0/vts/functional/wifi_chip_hidl_nan_test.cpp b/wifi/1.0/vts/functional/wifi_chip_hidl_nan_test.cpp
index 595f23a..95f223d 100644
--- a/wifi/1.0/vts/functional/wifi_chip_hidl_nan_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_chip_hidl_nan_test.cpp
@@ -16,9 +16,11 @@
 
 #include <android-base/logging.h>
 
+#include <android/hardware/wifi/1.0/IWifi.h>
 #include <android/hardware/wifi/1.0/IWifiChip.h>
-
-#include <VtsHalHidlTargetTestBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include "wifi_hidl_call_util.h"
 #include "wifi_hidl_test_utils.h"
@@ -26,6 +28,7 @@
 using ::android::sp;
 using ::android::hardware::wifi::V1_0::ChipModeId;
 using ::android::hardware::wifi::V1_0::IfaceType;
+using ::android::hardware::wifi::V1_0::IWifi;
 using ::android::hardware::wifi::V1_0::IWifiChip;
 using ::android::hardware::wifi::V1_0::IWifiIface;
 using ::android::hardware::wifi::V1_0::IWifiNanIface;
@@ -35,14 +38,14 @@
 /**
  * Fixture for IWifiChip tests that are conditioned on NAN support.
  */
-class WifiChipHidlNanTest : public ::testing::VtsHalHidlTargetTestBase {
+class WifiChipHidlNanTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
-        wifi_chip_ = getWifiChip();
+        wifi_chip_ = getWifiChip(GetInstanceName());
         ASSERT_NE(nullptr, wifi_chip_.get());
     }
 
-    virtual void TearDown() override { stopWifi(); }
+    virtual void TearDown() override { stopWifi(GetInstanceName()); }
 
    protected:
     // Helper function to configure the Chip in one of the supported modes.
@@ -72,6 +75,9 @@
     }
 
     sp<IWifiChip> wifi_chip_;
+
+   private:
+    std::string GetInstanceName() { return GetParam(); }
 };
 
 /*
@@ -79,7 +85,7 @@
  * Configures the chip in NAN mode and ensures that at least 1 iface creation
  * succeeds.
  */
-TEST_F(WifiChipHidlNanTest, CreateNanIface) {
+TEST_P(WifiChipHidlNanTest, CreateNanIface) {
     configureChipForIfaceType(IfaceType::NAN, true);
 
     sp<IWifiNanIface> iface;
@@ -93,7 +99,7 @@
  * before creating the iface. Then, create the iface and ensure that
  * iface name is returned via the list.
  */
-TEST_F(WifiChipHidlNanTest, GetNanIfaceNames) {
+TEST_P(WifiChipHidlNanTest, GetNanIfaceNames) {
     configureChipForIfaceType(IfaceType::NAN, true);
 
     const auto& status_and_iface_names1 =
@@ -125,7 +131,7 @@
  * the iface object using the correct name and ensure any other name
  * doesn't retrieve an iface object.
  */
-TEST_F(WifiChipHidlNanTest, GetNanIface) {
+TEST_P(WifiChipHidlNanTest, GetNanIface) {
     configureChipForIfaceType(IfaceType::NAN, true);
 
     sp<IWifiNanIface> nan_iface;
@@ -151,7 +157,7 @@
  * the iface object using the correct name and ensure any other name
  * doesn't remove the iface.
  */
-TEST_F(WifiChipHidlNanTest, RemoveNanIface) {
+TEST_P(WifiChipHidlNanTest, RemoveNanIface) {
     configureChipForIfaceType(IfaceType::NAN, true);
 
     sp<IWifiNanIface> nan_iface;
@@ -167,3 +173,9 @@
     // No such iface exists now. So, this should return failure.
     EXPECT_EQ(WifiStatusCode::ERROR_INVALID_ARGS, removeNanIface(iface_name));
 }
+
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, WifiChipHidlNanTest,
+    testing::ValuesIn(
+        android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
+    android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
index 2601b78..ec96fcf 100644
--- a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
@@ -16,10 +16,12 @@
 
 #include <android-base/logging.h>
 
+#include <android/hardware/wifi/1.0/IWifi.h>
 #include <android/hardware/wifi/1.0/IWifiChip.h>
 #include <android/hardware/wifi/1.3/IWifiChip.h>
-
-#include <VtsHalHidlTargetTestBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include "wifi_hidl_call_util.h"
 #include "wifi_hidl_test_utils.h"
@@ -27,19 +29,20 @@
 using ::android::sp;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
-using ::android::hardware::wifi::V1_0::IfaceType;
 using ::android::hardware::wifi::V1_0::ChipId;
 using ::android::hardware::wifi::V1_0::ChipModeId;
-using ::android::hardware::wifi::V1_0::WifiDebugRingBufferStatus;
-using ::android::hardware::wifi::V1_0::WifiDebugRingBufferVerboseLevel;
-using ::android::hardware::wifi::V1_0::WifiDebugHostWakeReasonStats;
-using ::android::hardware::wifi::V1_0::WifiStatus;
-using ::android::hardware::wifi::V1_0::WifiStatusCode;
+using ::android::hardware::wifi::V1_0::IfaceType;
+using ::android::hardware::wifi::V1_0::IWifi;
 using ::android::hardware::wifi::V1_0::IWifiChip;
 using ::android::hardware::wifi::V1_0::IWifiIface;
 using ::android::hardware::wifi::V1_0::IWifiP2pIface;
 using ::android::hardware::wifi::V1_0::IWifiRttController;
 using ::android::hardware::wifi::V1_0::IWifiStaIface;
+using ::android::hardware::wifi::V1_0::WifiDebugHostWakeReasonStats;
+using ::android::hardware::wifi::V1_0::WifiDebugRingBufferStatus;
+using ::android::hardware::wifi::V1_0::WifiDebugRingBufferVerboseLevel;
+using ::android::hardware::wifi::V1_0::WifiStatus;
+using ::android::hardware::wifi::V1_0::WifiStatusCode;
 
 extern WifiHidlEnvironment* gEnv;
 
@@ -67,14 +70,14 @@
  * Tests that require SoftAP or NAN support should go into WifiChipHidlApTest or
  * WifiChipHidlNanTest respectively.
  */
-class WifiChipHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class WifiChipHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
-        wifi_chip_ = getWifiChip();
+        wifi_chip_ = getWifiChip(GetInstanceName());
         ASSERT_NE(nullptr, wifi_chip_.get());
     }
 
-    virtual void TearDown() override { stopWifi(); }
+    virtual void TearDown() override { stopWifi(GetInstanceName()); }
 
    protected:
     // Helper function to configure the Chip in one of the supported modes.
@@ -136,6 +139,9 @@
     }
 
     sp<IWifiChip> wifi_chip_;
+
+   protected:
+    std::string GetInstanceName() { return GetParam(); }
 };
 
 /*
@@ -143,15 +149,14 @@
  * Ensures that an instance of the IWifiChip proxy object is
  * successfully created.
  */
-TEST(WifiChipHidlTestNoFixture, Create) {
-    EXPECT_NE(nullptr, getWifiChip().get());
-    stopWifi();
+TEST_P(WifiChipHidlTest, Create) {
+    // The creation of a proxy object is tested as part of SetUp method.
 }
 
 /*
  * GetId:
  */
-TEST_F(WifiChipHidlTest, GetId) {
+TEST_P(WifiChipHidlTest, GetId) {
     EXPECT_EQ(WifiStatusCode::SUCCESS,
               HIDL_INVOKE(wifi_chip_, getId).first.code);
 }
@@ -159,7 +164,7 @@
 /*
  * GetAvailableMode:
  */
-TEST_F(WifiChipHidlTest, GetAvailableModes) {
+TEST_P(WifiChipHidlTest, GetAvailableModes) {
     const auto& status_and_modes = HIDL_INVOKE(wifi_chip_, getAvailableModes);
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_modes.first.code);
     EXPECT_LT(0u, status_and_modes.second.size());
@@ -168,17 +173,17 @@
 /*
  * ConfigureChip:
  */
-TEST_F(WifiChipHidlTest, ConfigureChip) {
+TEST_P(WifiChipHidlTest, ConfigureChip) {
     const auto& status_and_modes = HIDL_INVOKE(wifi_chip_, getAvailableModes);
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_modes.first.code);
     EXPECT_LT(0u, status_and_modes.second.size());
     for (const auto& mode : status_and_modes.second) {
         // configureChip() requires to be called with a fresh IWifiChip object.
-        wifi_chip_ = getWifiChip();
+        wifi_chip_ = getWifiChip(GetInstanceName());
         ASSERT_NE(nullptr, wifi_chip_.get());
         EXPECT_EQ(WifiStatusCode::SUCCESS,
                   HIDL_INVOKE(wifi_chip_, configureChip, mode.id).code);
-        stopWifi();
+        stopWifi(GetInstanceName());
         // Sleep for 5 milliseconds between each wifi state toggle.
         usleep(5000);
     }
@@ -187,7 +192,7 @@
 /*
  * GetCapabilities:
  */
-TEST_F(WifiChipHidlTest, GetCapabilities) {
+TEST_P(WifiChipHidlTest, GetCapabilities) {
     configureChipForIfaceType(IfaceType::STA, true);
     const auto& status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities);
     if (status_and_caps.first.code != WifiStatusCode::SUCCESS) {
@@ -200,7 +205,7 @@
 /*
  * GetMode:
  */
-TEST_F(WifiChipHidlTest, GetMode) {
+TEST_P(WifiChipHidlTest, GetMode) {
     ChipModeId chip_mode_id = configureChipForIfaceType(IfaceType::STA, true);
     const auto& status_and_mode = HIDL_INVOKE(wifi_chip_, getMode);
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_mode.first.code);
@@ -210,7 +215,7 @@
 /*
  * RequestChipDebugInfo:
  */
-TEST_F(WifiChipHidlTest, RequestChipDebugInfo) {
+TEST_P(WifiChipHidlTest, RequestChipDebugInfo) {
     configureChipForIfaceType(IfaceType::STA, true);
     const auto& status_and_chip_info =
         HIDL_INVOKE(wifi_chip_, requestChipDebugInfo);
@@ -222,7 +227,7 @@
 /*
  * RequestFirmwareDebugDump
  */
-TEST_F(WifiChipHidlTest, RequestFirmwareDebugDump) {
+TEST_P(WifiChipHidlTest, RequestFirmwareDebugDump) {
     uint32_t caps = configureChipForStaIfaceAndGetCapabilities();
     const auto& status_and_firmware_dump =
         HIDL_INVOKE(wifi_chip_, requestFirmwareDebugDump);
@@ -237,7 +242,7 @@
 /*
  * RequestDriverDebugDump
  */
-TEST_F(WifiChipHidlTest, RequestDriverDebugDump) {
+TEST_P(WifiChipHidlTest, RequestDriverDebugDump) {
     uint32_t caps = configureChipForStaIfaceAndGetCapabilities();
     const auto& status_and_driver_dump =
         HIDL_INVOKE(wifi_chip_, requestDriverDebugDump);
@@ -254,7 +259,7 @@
 /*
  * GetDebugRingBuffersStatus
  */
-TEST_F(WifiChipHidlTest, GetDebugRingBuffersStatus) {
+TEST_P(WifiChipHidlTest, GetDebugRingBuffersStatus) {
     uint32_t caps = configureChipForStaIfaceAndGetCapabilities();
     const auto& status_and_ring_buffer_status =
         HIDL_INVOKE(wifi_chip_, getDebugRingBuffersStatus);
@@ -273,7 +278,7 @@
 /*
  * StartLoggingToDebugRingBuffer
  */
-TEST_F(WifiChipHidlTest, StartLoggingToDebugRingBuffer) {
+TEST_P(WifiChipHidlTest, StartLoggingToDebugRingBuffer) {
     uint32_t caps = configureChipForStaIfaceAndGetCapabilities();
     std::string ring_name;
     const auto& status_and_ring_buffer_status =
@@ -301,7 +306,7 @@
 /*
  * ForceDumpToDebugRingBuffer
  */
-TEST_F(WifiChipHidlTest, ForceDumpToDebugRingBuffer) {
+TEST_P(WifiChipHidlTest, ForceDumpToDebugRingBuffer) {
     uint32_t caps = configureChipForStaIfaceAndGetCapabilities();
     std::string ring_name;
     const auto& status_and_ring_buffer_status =
@@ -327,7 +332,7 @@
 /*
  * GetDebugHostWakeReasonStats
  */
-TEST_F(WifiChipHidlTest, GetDebugHostWakeReasonStats) {
+TEST_P(WifiChipHidlTest, GetDebugHostWakeReasonStats) {
     uint32_t caps = configureChipForStaIfaceAndGetCapabilities();
     const auto& status_and_debug_wake_reason =
         HIDL_INVOKE(wifi_chip_, getDebugHostWakeReasonStats);
@@ -345,7 +350,7 @@
  * Configures the chip in P2P mode and ensures that at least 1 iface creation
  * succeeds.
  */
-TEST_F(WifiChipHidlTest, CreateP2pIface) {
+TEST_P(WifiChipHidlTest, CreateP2pIface) {
     configureChipForIfaceType(IfaceType::P2P, true);
 
     sp<IWifiP2pIface> iface;
@@ -359,7 +364,7 @@
  * before creating the iface. Then, create the iface and ensure that
  * iface name is returned via the list.
  */
-TEST_F(WifiChipHidlTest, GetP2pIfaceNames) {
+TEST_P(WifiChipHidlTest, GetP2pIfaceNames) {
     configureChipForIfaceType(IfaceType::P2P, true);
 
     const auto& status_and_iface_names1 =
@@ -391,7 +396,7 @@
  * the iface object using the correct name and ensure any other name
  * doesn't retrieve an iface object.
  */
-TEST_F(WifiChipHidlTest, GetP2pIface) {
+TEST_P(WifiChipHidlTest, GetP2pIface) {
     configureChipForIfaceType(IfaceType::P2P, true);
 
     sp<IWifiP2pIface> p2p_iface;
@@ -417,7 +422,7 @@
  * the iface object using the correct name and ensure any other name
  * doesn't remove the iface.
  */
-TEST_F(WifiChipHidlTest, RemoveP2pIface) {
+TEST_P(WifiChipHidlTest, RemoveP2pIface) {
     configureChipForIfaceType(IfaceType::P2P, true);
 
     sp<IWifiP2pIface> p2p_iface;
@@ -438,7 +443,7 @@
  * Configures the chip in STA mode and ensures that at least 1 iface creation
  * succeeds.
  */
-TEST_F(WifiChipHidlTest, CreateStaIface) {
+TEST_P(WifiChipHidlTest, CreateStaIface) {
     configureChipForIfaceType(IfaceType::STA, true);
 
     sp<IWifiStaIface> iface;
@@ -452,7 +457,7 @@
  * before creating the iface. Then, create the iface and ensure that
  * iface name is returned via the list.
  */
-TEST_F(WifiChipHidlTest, GetStaIfaceNames) {
+TEST_P(WifiChipHidlTest, GetStaIfaceNames) {
     configureChipForIfaceType(IfaceType::STA, true);
 
     const auto& status_and_iface_names1 =
@@ -484,7 +489,7 @@
  * the iface object using the correct name and ensure any other name
  * doesn't retrieve an iface object.
  */
-TEST_F(WifiChipHidlTest, GetStaIface) {
+TEST_P(WifiChipHidlTest, GetStaIface) {
     configureChipForIfaceType(IfaceType::STA, true);
 
     sp<IWifiStaIface> sta_iface;
@@ -510,7 +515,7 @@
  * the iface object using the correct name and ensure any other name
  * doesn't remove the iface.
  */
-TEST_F(WifiChipHidlTest, RemoveStaIface) {
+TEST_P(WifiChipHidlTest, RemoveStaIface) {
     configureChipForIfaceType(IfaceType::STA, true);
 
     sp<IWifiStaIface> sta_iface;
@@ -529,7 +534,7 @@
 /*
  * CreateRttController
  */
-TEST_F(WifiChipHidlTest, CreateRttController) {
+TEST_P(WifiChipHidlTest, CreateRttController) {
     configureChipForIfaceType(IfaceType::STA, true);
 
     sp<IWifiStaIface> iface;
@@ -541,3 +546,9 @@
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_rtt_controller.first.code);
     EXPECT_NE(nullptr, status_and_rtt_controller.second.get());
 }
+
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, WifiChipHidlTest,
+    testing::ValuesIn(
+        android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
+    android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_hidl_test.cpp
index b8e501c..512701a 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_hidl_test.cpp
@@ -18,7 +18,9 @@
 
 #include <android/hardware/wifi/1.0/IWifi.h>
 
-#include <VtsHalHidlTargetTestBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include "wifi_hidl_test_utils.h"
 
@@ -28,13 +30,14 @@
 /**
  * Fixture to use for all root Wifi HIDL interface tests.
  */
-class WifiHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class WifiHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {}
 
-    virtual void TearDown() override { stopWifi(); }
+    virtual void TearDown() override { stopWifi(GetInstanceName()); }
 
    protected:
+    std::string GetInstanceName() { return GetParam(); }
 };
 
 /*
@@ -42,7 +45,12 @@
  * Ensures that an instance of the IWifi proxy object is
  * successfully created.
  */
-TEST(WifiHidlTestNoFixture, Create) {
-    EXPECT_NE(nullptr, getWifi().get());
-    stopWifi();
+TEST_P(WifiHidlTest, Create) {
+    // The creation of a proxy object is tested as part of SetUp method.
 }
+
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, WifiHidlTest,
+    testing::ValuesIn(
+        android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
+    android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
index 45454bf..d584d4b 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
@@ -214,7 +214,7 @@
     if (!wifi_chip.get()) {
         return nullptr;
     }
-    sp<IWifiStaIface> wifi_sta_iface = getWifiStaIface();
+    sp<IWifiStaIface> wifi_sta_iface = getWifiStaIface(instance_name);
     if (!wifi_sta_iface.get()) {
         return nullptr;
     }
diff --git a/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp
index 64b4fb6..422e3f6 100644
--- a/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp
@@ -16,10 +16,12 @@
 
 #include <android-base/logging.h>
 
+#include <android/hardware/wifi/1.0/IWifi.h>
 #include <android/hardware/wifi/1.0/IWifiNanIface.h>
 #include <android/hardware/wifi/1.0/IWifiNanIfaceEventCallback.h>
-
-#include <VtsHalHidlTargetTestBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 #include <chrono>
 #include <condition_variable>
 #include <mutex>
@@ -29,27 +31,28 @@
 
 using namespace ::android::hardware::wifi::V1_0;
 
+using ::android::sp;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using ::android::sp;
+using ::android::hardware::wifi::V1_0::IWifi;
 
 #define TIMEOUT_PERIOD 10
 
 /**
  * Fixture to use for all NAN Iface HIDL interface tests.
  */
-class WifiNanIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-  public:
+class WifiNanIfaceHidlTest : public ::testing::TestWithParam<std::string> {
+   public:
     virtual void SetUp() override {
-      iwifiNanIface = getWifiNanIface();
-      ASSERT_NE(nullptr, iwifiNanIface.get());
-      ASSERT_EQ(WifiStatusCode::SUCCESS, HIDL_INVOKE(iwifiNanIface, registerEventCallback,
-            new WifiNanIfaceEventCallback(*this)).code);
+        iwifiNanIface = getWifiNanIface(GetInstanceName());
+        ASSERT_NE(nullptr, iwifiNanIface.get());
+        ASSERT_EQ(WifiStatusCode::SUCCESS,
+                  HIDL_INVOKE(iwifiNanIface, registerEventCallback,
+                              new WifiNanIfaceEventCallback(*this))
+                      .code);
     }
 
-    virtual void TearDown() override {
-      stopWifi();
-    }
+    virtual void TearDown() override { stopWifi(GetInstanceName()); }
 
     /* Used as a mechanism to inform the test about data/event callback */
     inline void notify() {
@@ -438,6 +441,8 @@
       NanFollowupReceivedInd nanFollowupReceivedInd;
       NanDataPathRequestInd nanDataPathRequestInd;
       NanDataPathConfirmInd nanDataPathConfirmInd;
+
+      std::string GetInstanceName() { return GetParam(); }
 };
 
 /*
@@ -445,9 +450,8 @@
  * Ensures that an instance of the IWifiNanIface proxy object is
  * successfully created.
  */
-TEST(WifiNanIfaceHidlTestNoFixture, Create) {
-  ASSERT_NE(nullptr, getWifiNanIface().get());
-  stopWifi();
+TEST_P(WifiNanIfaceHidlTest, Create) {
+    // The creation of a proxy object is tested as part of SetUp method.
 }
 
 /*
@@ -455,41 +459,51 @@
  * Ensure that API calls fail with ERROR_WIFI_IFACE_INVALID when using an interface once wifi
  * is disabled.
  */
-TEST(WifiNanIfaceHidlTestNoFixture, FailOnIfaceInvalid) {
-  android::sp<IWifiNanIface> iwifiNanIface = getWifiNanIface();
-  ASSERT_NE(nullptr, iwifiNanIface.get());
-  stopWifi();
-  sleep(5); // make sure that all chips/interfaces are invalidated
-  ASSERT_EQ(WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-          HIDL_INVOKE(iwifiNanIface, getCapabilitiesRequest, 0).code);
+TEST_P(WifiNanIfaceHidlTest, FailOnIfaceInvalid) {
+    stopWifi(GetInstanceName());
+    android::sp<IWifiNanIface> iwifiNanIface =
+        getWifiNanIface(GetInstanceName());
+    ASSERT_NE(nullptr, iwifiNanIface.get());
+    stopWifi(GetInstanceName());
+    sleep(5);  // make sure that all chips/interfaces are invalidated
+    ASSERT_EQ(WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+              HIDL_INVOKE(iwifiNanIface, getCapabilitiesRequest, 0).code);
 }
 
 /*
  * getCapabilitiesRequest: validate that returns capabilities.
  */
-TEST_F(WifiNanIfaceHidlTest, getCapabilitiesRequest) {
-  uint16_t inputCmdId = 10;
-  callbackType = INVALID;
-  ASSERT_EQ(WifiStatusCode::SUCCESS,
+TEST_P(WifiNanIfaceHidlTest, getCapabilitiesRequest) {
+    uint16_t inputCmdId = 10;
+    callbackType = INVALID;
+    ASSERT_EQ(
+        WifiStatusCode::SUCCESS,
         HIDL_INVOKE(iwifiNanIface, getCapabilitiesRequest, inputCmdId).code);
-  // wait for a callback
-  ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_CAPABILITIES_RESPONSE));
-  ASSERT_EQ(NOTIFY_CAPABILITIES_RESPONSE, callbackType);
-  ASSERT_EQ(id, inputCmdId);
+    // wait for a callback
+    ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_CAPABILITIES_RESPONSE));
+    ASSERT_EQ(NOTIFY_CAPABILITIES_RESPONSE, callbackType);
+    ASSERT_EQ(id, inputCmdId);
 
-  // check for reasonable capability values
-  EXPECT_GT(capabilities.maxConcurrentClusters, (unsigned int) 0);
-  EXPECT_GT(capabilities.maxPublishes, (unsigned int) 0);
-  EXPECT_GT(capabilities.maxSubscribes, (unsigned int) 0);
-  EXPECT_EQ(capabilities.maxServiceNameLen, (unsigned int) 255);
-  EXPECT_EQ(capabilities.maxMatchFilterLen, (unsigned int) 255);
-  EXPECT_GT(capabilities.maxTotalMatchFilterLen, (unsigned int) 255);
-  EXPECT_EQ(capabilities.maxServiceSpecificInfoLen, (unsigned int) 255);
-  EXPECT_GE(capabilities.maxExtendedServiceSpecificInfoLen, (unsigned int) 255);
-  EXPECT_GT(capabilities.maxNdiInterfaces, (unsigned int) 0);
-  EXPECT_GT(capabilities.maxNdpSessions, (unsigned int) 0);
-  EXPECT_GT(capabilities.maxAppInfoLen, (unsigned int) 0);
-  EXPECT_GT(capabilities.maxQueuedTransmitFollowupMsgs, (unsigned int) 0);
-  EXPECT_GT(capabilities.maxSubscribeInterfaceAddresses, (unsigned int) 0);
-  EXPECT_NE(capabilities.supportedCipherSuites, (unsigned int) 0);
+    // check for reasonable capability values
+    EXPECT_GT(capabilities.maxConcurrentClusters, (unsigned int)0);
+    EXPECT_GT(capabilities.maxPublishes, (unsigned int)0);
+    EXPECT_GT(capabilities.maxSubscribes, (unsigned int)0);
+    EXPECT_EQ(capabilities.maxServiceNameLen, (unsigned int)255);
+    EXPECT_EQ(capabilities.maxMatchFilterLen, (unsigned int)255);
+    EXPECT_GT(capabilities.maxTotalMatchFilterLen, (unsigned int)255);
+    EXPECT_EQ(capabilities.maxServiceSpecificInfoLen, (unsigned int)255);
+    EXPECT_GE(capabilities.maxExtendedServiceSpecificInfoLen,
+              (unsigned int)255);
+    EXPECT_GT(capabilities.maxNdiInterfaces, (unsigned int)0);
+    EXPECT_GT(capabilities.maxNdpSessions, (unsigned int)0);
+    EXPECT_GT(capabilities.maxAppInfoLen, (unsigned int)0);
+    EXPECT_GT(capabilities.maxQueuedTransmitFollowupMsgs, (unsigned int)0);
+    EXPECT_GT(capabilities.maxSubscribeInterfaceAddresses, (unsigned int)0);
+    EXPECT_NE(capabilities.supportedCipherSuites, (unsigned int)0);
 }
+
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, WifiNanIfaceHidlTest,
+    testing::ValuesIn(
+        android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
+    android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/wifi/1.0/vts/functional/wifi_p2p_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_p2p_iface_hidl_test.cpp
index 269eb6c..8f33271 100644
--- a/wifi/1.0/vts/functional/wifi_p2p_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_p2p_iface_hidl_test.cpp
@@ -16,25 +16,29 @@
 
 #include <android-base/logging.h>
 
+#include <android/hardware/wifi/1.0/IWifi.h>
 #include <android/hardware/wifi/1.0/IWifiP2pIface.h>
-
-#include <VtsHalHidlTargetTestBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include "wifi_hidl_test_utils.h"
 
-using ::android::hardware::wifi::V1_0::IWifiP2pIface;
 using ::android::sp;
+using ::android::hardware::wifi::V1_0::IWifi;
+using ::android::hardware::wifi::V1_0::IWifiP2pIface;
 
 /**
  * Fixture to use for all P2P Iface HIDL interface tests.
  */
-class WifiP2pIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class WifiP2pIfaceHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {}
 
-    virtual void TearDown() override { stopWifi(); }
+    virtual void TearDown() override { stopWifi(GetInstanceName()); }
 
    protected:
+    std::string GetInstanceName() { return GetParam(); }
 };
 
 /*
@@ -42,7 +46,13 @@
  * Ensures that an instance of the IWifiP2pIface proxy object is
  * successfully created.
  */
-TEST(WifiP2pIfaceHidlTestNoFixture, Create) {
-    EXPECT_NE(nullptr, getWifiP2pIface().get());
-    stopWifi();
+TEST_P(WifiP2pIfaceHidlTest, Create) {
+    stopWifi(GetInstanceName());
+    EXPECT_NE(nullptr, getWifiP2pIface(GetInstanceName()).get());
 }
+
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, WifiP2pIfaceHidlTest,
+    testing::ValuesIn(
+        android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
+    android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/wifi/1.0/vts/functional/wifi_rtt_controller_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_rtt_controller_hidl_test.cpp
index e13086d..e1ee34f 100644
--- a/wifi/1.0/vts/functional/wifi_rtt_controller_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_rtt_controller_hidl_test.cpp
@@ -16,25 +16,29 @@
 
 #include <android-base/logging.h>
 
+#include <android/hardware/wifi/1.0/IWifi.h>
 #include <android/hardware/wifi/1.0/IWifiRttController.h>
-
-#include <VtsHalHidlTargetTestBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include "wifi_hidl_test_utils.h"
 
-using ::android::hardware::wifi::V1_0::IWifiRttController;
 using ::android::sp;
+using ::android::hardware::wifi::V1_0::IWifi;
+using ::android::hardware::wifi::V1_0::IWifiRttController;
 
 /**
  * Fixture to use for all RTT controller HIDL interface tests.
  */
-class WifiRttControllerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class WifiRttControllerHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {}
 
-    virtual void TearDown() override { stopWifi(); }
+    virtual void TearDown() override { stopWifi(GetInstanceName()); }
 
    protected:
+    std::string GetInstanceName() { return GetParam(); }
 };
 
 /*
@@ -42,7 +46,13 @@
  * Ensures that an instance of the IWifiRttController proxy object is
  * successfully created.
  */
-TEST(WifiRttControllerHidlTestNoFixture, Create) {
-    EXPECT_NE(nullptr, getWifiRttController().get());
-    stopWifi();
+TEST_P(WifiRttControllerHidlTest, Create) {
+    stopWifi(GetInstanceName());
+    EXPECT_NE(nullptr, getWifiRttController(GetInstanceName()).get());
 }
+
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, WifiRttControllerHidlTest,
+    testing::ValuesIn(
+        android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
+    android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
index a413863..30b6fba 100644
--- a/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
@@ -16,10 +16,12 @@
 
 #include <android-base/logging.h>
 
+#include <android/hardware/wifi/1.0/IWifi.h>
 #include <android/hardware/wifi/1.0/IWifiStaIface.h>
 #include <android/hardware/wifi/1.3/IWifiStaIface.h>
-
-#include <VtsHalHidlTargetTestBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include "wifi_hidl_call_util.h"
 #include "wifi_hidl_test_utils.h"
@@ -28,6 +30,7 @@
 using ::android::hardware::wifi::V1_0::Bssid;
 using ::android::hardware::wifi::V1_0::CommandId;
 using ::android::hardware::wifi::V1_0::IfaceType;
+using ::android::hardware::wifi::V1_0::IWifi;
 using ::android::hardware::wifi::V1_0::IWifiStaIface;
 using ::android::hardware::wifi::V1_0::Rssi;
 using ::android::hardware::wifi::V1_0::Ssid;
@@ -41,14 +44,14 @@
 /**
  * Fixture to use for all STA Iface HIDL interface tests.
  */
-class WifiStaIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class WifiStaIfaceHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
-        wifi_sta_iface_ = getWifiStaIface();
+        wifi_sta_iface_ = getWifiStaIface(GetInstanceName());
         ASSERT_NE(nullptr, wifi_sta_iface_.get());
     }
 
-    virtual void TearDown() override { stopWifi(); }
+    virtual void TearDown() override { stopWifi(GetInstanceName()); }
 
    protected:
     bool isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask cap_mask) {
@@ -59,6 +62,7 @@
     }
 
     sp<IWifiStaIface> wifi_sta_iface_;
+    std::string GetInstanceName() { return GetParam(); }
 };
 
 /*
@@ -66,15 +70,14 @@
  * Ensures that an instance of the IWifiStaIface proxy object is
  * successfully created.
  */
-TEST(WifiStaIfaceHidlTestNoFixture, Create) {
-    EXPECT_NE(nullptr, getWifiStaIface().get());
-    stopWifi();
+TEST_P(WifiStaIfaceHidlTest, Create) {
+    // The creation of a proxy object is tested as part of SetUp method.
 }
 
 /*
  * GetCapabilities:
  */
-TEST_F(WifiStaIfaceHidlTest, GetCapabilities) {
+TEST_P(WifiStaIfaceHidlTest, GetCapabilities) {
     const auto& status_and_caps = HIDL_INVOKE(wifi_sta_iface_, getCapabilities);
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
     EXPECT_GT(status_and_caps.second, 0u);
@@ -84,7 +87,7 @@
  * GetType:
  * Ensures that the correct interface type is returned for station interface.
  */
-TEST_F(WifiStaIfaceHidlTest, GetType) {
+TEST_P(WifiStaIfaceHidlTest, GetType) {
     const auto& status_and_type = HIDL_INVOKE(wifi_sta_iface_, getType);
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_type.first.code);
     EXPECT_EQ(IfaceType::STA, status_and_type.second);
@@ -94,7 +97,7 @@
  * GetApfPacketFilterCapabilities:
  * Ensures that we can retrieve APF packet filter capabilites.
  */
-TEST_F(WifiStaIfaceHidlTest, GetApfPacketFilterCapabilities) {
+TEST_P(WifiStaIfaceHidlTest, GetApfPacketFilterCapabilities) {
     if (!isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask::APF)) {
         // No-op if APF packet filer is not supported.
         return;
@@ -109,7 +112,7 @@
  * GetBackgroundScanCapabilities:
  * Ensures that we can retrieve background scan capabilities.
  */
-TEST_F(WifiStaIfaceHidlTest, GetBackgroundScanCapabilities) {
+TEST_P(WifiStaIfaceHidlTest, GetBackgroundScanCapabilities) {
     if (!isCapabilitySupported(
             IWifiStaIface::StaIfaceCapabilityMask::BACKGROUND_SCAN)) {
         // No-op if background scan is not supported.
@@ -125,7 +128,7 @@
  * GetValidFrequenciesForBand:
  * Ensures that we can retrieve valid frequencies for 2.4 GHz band.
  */
-TEST_F(WifiStaIfaceHidlTest, GetValidFrequenciesForBand) {
+TEST_P(WifiStaIfaceHidlTest, GetValidFrequenciesForBand) {
     const auto& status_and_freqs = HIDL_INVOKE(
         wifi_sta_iface_, getValidFrequenciesForBand, WifiBand::BAND_24GHZ);
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_freqs.first.code);
@@ -137,7 +140,7 @@
  * Ensures that calls to enable, disable, and retrieve link layer stats
  * will return a success status code.
  */
-TEST_F(WifiStaIfaceHidlTest, LinkLayerStatsCollection) {
+TEST_P(WifiStaIfaceHidlTest, LinkLayerStatsCollection) {
     if (!isCapabilitySupported(
             IWifiStaIface::StaIfaceCapabilityMask::LINK_LAYER_STATS)) {
         // No-op if link layer stats is not supported.
@@ -172,7 +175,7 @@
  * Ensures that calls to disable RSSI monitoring will return an error status
  * code if RSSI monitoring is not enabled.
  */
-TEST_F(WifiStaIfaceHidlTest, RSSIMonitoring) {
+TEST_P(WifiStaIfaceHidlTest, RSSIMonitoring) {
     if (!isCapabilitySupported(
             IWifiStaIface::StaIfaceCapabilityMask::RSSI_MONITOR)) {
         // No-op if RSSI monitor is not supported.
@@ -197,7 +200,7 @@
  * Ensures that calls to configure and enable roaming will return a success
  * status code.
  */
-TEST_F(WifiStaIfaceHidlTest, RoamingControl) {
+TEST_P(WifiStaIfaceHidlTest, RoamingControl) {
     if (!isCapabilitySupported(
             IWifiStaIface::StaIfaceCapabilityMask::CONTROL_ROAMING)) {
         // No-op if roaming control is not supported.
@@ -242,9 +245,9 @@
  * Ensures that calls to enable neighbor discovery offload will return a success
  * status code.
  */
-TEST_F(WifiStaIfaceHidlTest, EnableNDOffload) {
-   if (!isCapabilitySupported(
-           IWifiStaIface::StaIfaceCapabilityMask::ND_OFFLOAD)) {
+TEST_P(WifiStaIfaceHidlTest, EnableNDOffload) {
+    if (!isCapabilitySupported(
+            IWifiStaIface::StaIfaceCapabilityMask::ND_OFFLOAD)) {
         // No-op if nd offload is not supported.
         return;
     }
@@ -257,7 +260,7 @@
  * Ensures that calls to set scanning MAC OUI will return a success status
  * code.
  */
-TEST_F(WifiStaIfaceHidlTest, SetScanningMacOui) {
+TEST_P(WifiStaIfaceHidlTest, SetScanningMacOui) {
     if (!isCapabilitySupported(
             IWifiStaIface::StaIfaceCapabilityMask::SCAN_RAND)) {
         // No-op if SetScanningMacOui is not supported.
@@ -274,9 +277,9 @@
  * Ensures that calls to start packet fate monitoring and retrieve TX/RX
  * packets will return a success status code.
  */
-TEST_F(WifiStaIfaceHidlTest, PacketFateMonitoring) {
-   if (!isCapabilitySupported(
-           IWifiStaIface::StaIfaceCapabilityMask::DEBUG_PACKET_FATE)) {
+TEST_P(WifiStaIfaceHidlTest, PacketFateMonitoring) {
+    if (!isCapabilitySupported(
+            IWifiStaIface::StaIfaceCapabilityMask::DEBUG_PACKET_FATE)) {
         // No-op if packet fate monitor is not supported.
         return;
     }
@@ -291,3 +294,9 @@
     EXPECT_EQ(WifiStatusCode::SUCCESS,
               HIDL_INVOKE(wifi_sta_iface_, getDebugRxPacketFates).first.code);
 }
+
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, WifiStaIfaceHidlTest,
+    testing::ValuesIn(
+        android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
+    android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/wifi/1.1/vts/functional/Android.bp b/wifi/1.1/vts/functional/Android.bp
index 6d7635d..775031e 100644
--- a/wifi/1.1/vts/functional/Android.bp
+++ b/wifi/1.1/vts/functional/Android.bp
@@ -28,5 +28,5 @@
         "android.hardware.wifi@1.3",
         "libwifi-system-iface"
     ],
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/wifi/1.1/vts/functional/VtsHalWifiV1_1TargetTest.cpp b/wifi/1.1/vts/functional/VtsHalWifiV1_1TargetTest.cpp
index 673fed3..4b62b15 100644
--- a/wifi/1.1/vts/functional/VtsHalWifiV1_1TargetTest.cpp
+++ b/wifi/1.1/vts/functional/VtsHalWifiV1_1TargetTest.cpp
@@ -14,34 +14,8 @@
  * limitations under the License.
  */
 
-#include <android-base/logging.h>
-#include <android/hardware/wifi/1.1/IWifi.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 
-#include "wifi_hidl_test_utils.h"
-
-class WifiHidlEnvironment_1_1 : public WifiHidlEnvironment {
-   public:
-    // get the test environment singleton
-    static WifiHidlEnvironment_1_1* Instance() {
-        static WifiHidlEnvironment_1_1* instance = new WifiHidlEnvironment_1_1;
-        return instance;
-    }
-
-    virtual void registerTestServices() override {
-        registerTestService<android::hardware::wifi::V1_1::IWifi>();
-    }
-
-   private:
-    WifiHidlEnvironment_1_1() {}
-};
-
-WifiHidlEnvironment* gEnv = WifiHidlEnvironment_1_1::Instance();
-
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(gEnv);
-    ::testing::InitGoogleTest(&argc, argv);
-    gEnv->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    LOG(INFO) << "Test result = " << status;
-    return status;
-}
+// TODO(b/143892896): Remove this file after wifi_hidl_test_utils.cpp is
+// updated.
+::testing::VtsHalHidlTargetTestEnvBase* gEnv = nullptr;
diff --git a/wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp
index 6323547..08de240 100644
--- a/wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp
+++ b/wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp
@@ -19,8 +19,9 @@
 #include <android/hardware/wifi/1.1/IWifi.h>
 #include <android/hardware/wifi/1.1/IWifiChip.h>
 #include <android/hardware/wifi/1.3/IWifiChip.h>
-
-#include <VtsHalHidlTargetTestBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include "wifi_hidl_call_util.h"
 #include "wifi_hidl_test_utils.h"
@@ -45,14 +46,14 @@
 /**
  * Fixture to use for all Wifi chip HIDL interface tests.
  */
-class WifiChipHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class WifiChipHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
-        wifi_chip_ = IWifiChip::castFrom(getWifiChip());
+        wifi_chip_ = IWifiChip::castFrom(getWifiChip(GetInstanceName()));
         ASSERT_NE(nullptr, wifi_chip_.get());
     }
 
-    virtual void TearDown() override { stopWifi(); }
+    virtual void TearDown() override { stopWifi(GetInstanceName()); }
 
    protected:
     uint32_t configureChipForStaIfaceAndGetCapabilities() {
@@ -77,12 +78,15 @@
     }
 
     sp<IWifiChip> wifi_chip_;
+
+   private:
+    std::string GetInstanceName() { return GetParam(); }
 };
 
 /*
  * SelectTxPowerScenario
  */
-TEST_F(WifiChipHidlTest, SelectTxPowerScenario) {
+TEST_P(WifiChipHidlTest, SelectTxPowerScenario) {
     uint32_t caps = configureChipForStaIfaceAndGetCapabilities();
     const auto& status =
         HIDL_INVOKE(wifi_chip_, selectTxPowerScenario, kFakePowerScenario);
@@ -96,7 +100,7 @@
 /*
  * ResetTxPowerScenario
  */
-TEST_F(WifiChipHidlTest, ResetTxPowerScenario) {
+TEST_P(WifiChipHidlTest, ResetTxPowerScenario) {
     uint32_t caps = configureChipForStaIfaceAndGetCapabilities();
     const auto& status =
         HIDL_INVOKE(wifi_chip_, resetTxPowerScenario);
@@ -106,3 +110,9 @@
         EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, status.code);
     }
 }
+
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, WifiChipHidlTest,
+    testing::ValuesIn(
+        android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
+    android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/wifi/1.2/vts/functional/Android.bp b/wifi/1.2/vts/functional/Android.bp
index 97853d0..f43e49e 100644
--- a/wifi/1.2/vts/functional/Android.bp
+++ b/wifi/1.2/vts/functional/Android.bp
@@ -30,7 +30,8 @@
         "android.hardware.wifi@1.3",
         "libwifi-system-iface"
     ],
-    test_suites: ["general-tests"],
+    disable_framework: true,
+    test_suites: ["general-tests", "vts-core"],
 }
 
 cc_test {
@@ -47,5 +48,6 @@
         "android.hardware.wifi@1.2",
         "libwifi-system-iface"
     ],
-    test_suites: ["general-tests"],
+    disable_framework: true,
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/wifi/1.2/vts/functional/VtsHalWifiV1_2TargetTest.cpp b/wifi/1.2/vts/functional/VtsHalWifiV1_2TargetTest.cpp
index c765cdc..52c7a4a 100644
--- a/wifi/1.2/vts/functional/VtsHalWifiV1_2TargetTest.cpp
+++ b/wifi/1.2/vts/functional/VtsHalWifiV1_2TargetTest.cpp
@@ -14,35 +14,8 @@
  * limitations under the License.
  */
 
-#include <android-base/logging.h>
-#include <android/hardware/wifi/1.2/IWifi.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 
-#include "wifi_hidl_test_utils.h"
-
-using ::android::hardware::wifi::V1_2::IWifi;
-
-// Test environment for Wifi HIDL HAL.
-class WifiHidlEnvironment_1_2 : public WifiHidlEnvironment {
-   public:
-    // get the test environment singleton
-    static WifiHidlEnvironment_1_2* Instance() {
-        static WifiHidlEnvironment_1_2* instance = new WifiHidlEnvironment_1_2;
-        return instance;
-    }
-
-    virtual void registerTestServices() override { registerTestService<IWifi>(); }
-
-   private:
-    WifiHidlEnvironment_1_2() {}
-};
-
-WifiHidlEnvironment_1_2* gEnv = WifiHidlEnvironment_1_2::Instance();
-
-int main(int argc, char** argv) {
-  ::testing::AddGlobalTestEnvironment(gEnv);
-  ::testing::InitGoogleTest(&argc, argv);
-  gEnv->init(&argc, argv);
-  int status = RUN_ALL_TESTS();
-  LOG(INFO) << "Test result = " << status;
-  return status;
-}
+// TODO(b/143892896): Remove this file after wifi_hidl_test_utils.cpp is
+// updated.
+::testing::VtsHalHidlTargetTestEnvBase* gEnv = nullptr;
\ No newline at end of file
diff --git a/wifi/1.2/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.2/vts/functional/wifi_chip_hidl_test.cpp
index 9d567fe..47faec8 100644
--- a/wifi/1.2/vts/functional/wifi_chip_hidl_test.cpp
+++ b/wifi/1.2/vts/functional/wifi_chip_hidl_test.cpp
@@ -16,12 +16,14 @@
 
 #include <android-base/logging.h>
 
+#include <android/hardware/wifi/1.2/IWifi.h>
 #include <android/hardware/wifi/1.2/IWifiChip.h>
 #include <android/hardware/wifi/1.2/IWifiChipEventCallback.h>
 #include <android/hardware/wifi/1.3/IWifiChip.h>
-
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 #include <VtsHalHidlTargetCallbackBase.h>
-#include <VtsHalHidlTargetTestBase.h>
 
 #include "wifi_hidl_call_util.h"
 #include "wifi_hidl_test_utils.h"
@@ -50,14 +52,14 @@
 /**
  * Fixture to use for all Wifi chip HIDL interface tests.
  */
-class WifiChipHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class WifiChipHidlTest : public ::testing::TestWithParam<std::string> {
  public:
   virtual void SetUp() override {
-    wifi_chip_ = IWifiChip::castFrom(getWifiChip());
+    wifi_chip_ = IWifiChip::castFrom(getWifiChip(GetInstanceName()));
     ASSERT_NE(nullptr, wifi_chip_.get());
   }
 
-  virtual void TearDown() override { stopWifi(); }
+  virtual void TearDown() override { stopWifi(GetInstanceName()); }
 
   // A simple test implementation of WifiChipEventCallback.
   class WifiChipEventCallback
@@ -123,6 +125,9 @@
   }
 
   sp<IWifiChip> wifi_chip_;
+
+ private:
+  std::string GetInstanceName() { return GetParam(); }
 };
 
 /*
@@ -130,7 +135,7 @@
  * This test case tests the selectTxPowerScenario_1_2() API with SAR scenarios
  * newly defined in 1.2
  */
-TEST_F(WifiChipHidlTest, SelectTxPowerScenario_1_2_body) {
+TEST_P(WifiChipHidlTest, SelectTxPowerScenario_1_2_body) {
   uint32_t caps = configureChipForStaIfaceAndGetCapabilities();
   const auto& status =
       HIDL_INVOKE(wifi_chip_, selectTxPowerScenario_1_2, kPowerScenarioBody);
@@ -147,7 +152,7 @@
  * This test case tests the selectTxPowerScenario_1_2() API with previously
  * defined SAR scenarios
  */
-TEST_F(WifiChipHidlTest, SelectTxPowerScenario_1_2_voiceCall) {
+TEST_P(WifiChipHidlTest, SelectTxPowerScenario_1_2_voiceCall) {
   uint32_t caps = configureChipForStaIfaceAndGetCapabilities();
   const auto& status =
       HIDL_INVOKE(wifi_chip_, selectTxPowerScenario_1_2, kPowerScenarioVoiceCall);
@@ -167,9 +172,15 @@
  * since event is triggered internally in the HAL implementation, and can not be
  * triggered from the test case
  */
-TEST_F(WifiChipHidlTest, registerEventCallback_1_2) {
+TEST_P(WifiChipHidlTest, registerEventCallback_1_2) {
     sp<WifiChipEventCallback> wifiChipEventCallback = new WifiChipEventCallback();
     const auto& status =
         HIDL_INVOKE(wifi_chip_, registerEventCallback_1_2, wifiChipEventCallback);
     EXPECT_EQ(WifiStatusCode::SUCCESS, status.code);
 }
+
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, WifiChipHidlTest,
+    testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+        ::android::hardware::wifi::V1_2::IWifi::descriptor)),
+    android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp
index 4dbc82b..f3f76e1 100644
--- a/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp
+++ b/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp
@@ -16,10 +16,12 @@
 
 #include <android-base/logging.h>
 
+#include <android/hardware/wifi/1.2/IWifi.h>
 #include <android/hardware/wifi/1.2/IWifiNanIface.h>
 #include <android/hardware/wifi/1.2/IWifiNanIfaceEventCallback.h>
-
-#include <VtsHalHidlTargetTestBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 #include <chrono>
 #include <condition_variable>
 #include <mutex>
@@ -36,19 +38,19 @@
 
 #define TIMEOUT_PERIOD 10
 
-android::sp<android::hardware::wifi::V1_2::IWifiNanIface>
-getWifiNanIface_1_2() {
+android::sp<android::hardware::wifi::V1_2::IWifiNanIface> getWifiNanIface_1_2(
+    const std::string& instance_name) {
     return android::hardware::wifi::V1_2::IWifiNanIface::castFrom(
-        getWifiNanIface());
+        getWifiNanIface(instance_name));
 }
 
 /**
  * Fixture to use for all NAN Iface HIDL interface tests.
  */
-class WifiNanIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class WifiNanIfaceHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
-        iwifiNanIface = getWifiNanIface_1_2();
+        iwifiNanIface = getWifiNanIface_1_2(GetInstanceName());
         ASSERT_NE(nullptr, iwifiNanIface.get());
         ASSERT_EQ(WifiStatusCode::SUCCESS,
                   HIDL_INVOKE(iwifiNanIface, registerEventCallback_1_2,
@@ -56,7 +58,7 @@
                       .code);
     }
 
-    virtual void TearDown() override { stopWifi(); }
+    virtual void TearDown() override { stopWifi(GetInstanceName()); }
 
     /* Used as a mechanism to inform the test about data/event callback */
     inline void notify() {
@@ -458,6 +460,8 @@
     ::android::hardware::wifi::V1_2::NanDataPathConfirmInd
         nanDataPathConfirmInd_1_2;
     NanDataPathScheduleUpdateInd nanDataPathScheduleUpdateInd;
+
+    std::string GetInstanceName() { return GetParam(); }
 };
 
 /*
@@ -465,15 +469,14 @@
  * Ensures that an instance of the IWifiNanIface proxy object is
  * successfully created.
  */
-TEST(WifiNanIfaceHidlTestNoFixture, Create) {
-    ASSERT_NE(nullptr, getWifiNanIface_1_2().get());
-    stopWifi();
+TEST_P(WifiNanIfaceHidlTest, Create) {
+    // The creation of a proxy object is tested as part of SetUp method.
 }
 
 /*
  * enableRequest_1_2InvalidArgs: validate that fails with invalid arguments
  */
-TEST_F(WifiNanIfaceHidlTest, enableRequest_1_2InvalidArgs) {
+TEST_P(WifiNanIfaceHidlTest, enableRequest_1_2InvalidArgs) {
     uint16_t inputCmdId = 10;
     callbackType = INVALID;
     NanEnableRequest nanEnableRequest = {};
@@ -493,7 +496,7 @@
  * enableRequest_1_2ShimInvalidArgs: validate that fails with invalid arguments
  * to the shim
  */
-TEST_F(WifiNanIfaceHidlTest, enableRequest_1_2ShimInvalidArgs) {
+TEST_P(WifiNanIfaceHidlTest, enableRequest_1_2ShimInvalidArgs) {
     uint16_t inputCmdId = 10;
     NanEnableRequest nanEnableRequest = {};
     nanEnableRequest.configParams.numberOfPublishServiceIdsInBeacon =
@@ -508,7 +511,7 @@
 /*
  * configRequest_1_2InvalidArgs: validate that fails with invalid arguments
  */
-TEST_F(WifiNanIfaceHidlTest, configRequest_1_2InvalidArgs) {
+TEST_P(WifiNanIfaceHidlTest, configRequest_1_2InvalidArgs) {
     uint16_t inputCmdId = 10;
     callbackType = INVALID;
     NanConfigRequest nanConfigRequest = {};
@@ -528,7 +531,7 @@
  * configRequest_1_2ShimInvalidArgs: validate that fails with invalid arguments
  * to the shim
  */
-TEST_F(WifiNanIfaceHidlTest, configRequest_1_2ShimInvalidArgs) {
+TEST_P(WifiNanIfaceHidlTest, configRequest_1_2ShimInvalidArgs) {
     uint16_t inputCmdId = 10;
     NanConfigRequest nanConfigRequest = {};
     nanConfigRequest.numberOfPublishServiceIdsInBeacon = 128;  // must be <= 127
@@ -538,3 +541,9 @@
                           nanConfigRequest, nanConfigRequestSupp)
                   .code);
 }
+
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, WifiNanIfaceHidlTest,
+    testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+        ::android::hardware::wifi::V1_2::IWifi::descriptor)),
+    android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/wifi/1.2/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.2/vts/functional/wifi_sta_iface_hidl_test.cpp
index 92f5d14..1b907b2 100644
--- a/wifi/1.2/vts/functional/wifi_sta_iface_hidl_test.cpp
+++ b/wifi/1.2/vts/functional/wifi_sta_iface_hidl_test.cpp
@@ -19,9 +19,11 @@
 
 #include <android-base/logging.h>
 
+#include <android/hardware/wifi/1.2/IWifi.h>
 #include <android/hardware/wifi/1.2/IWifiStaIface.h>
-
-#include <VtsHalHidlTargetTestBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include "wifi_hidl_call_util.h"
 #include "wifi_hidl_test_utils.h"
@@ -34,14 +36,15 @@
 /**
  * Fixture to use for all STA Iface HIDL interface tests.
  */
-class WifiStaIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class WifiStaIfaceHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
-        wifi_sta_iface_ = IWifiStaIface::castFrom(getWifiStaIface());
+        wifi_sta_iface_ =
+            IWifiStaIface::castFrom(getWifiStaIface(GetInstanceName()));
         ASSERT_NE(nullptr, wifi_sta_iface_.get());
     }
 
-    virtual void TearDown() override { stopWifi(); }
+    virtual void TearDown() override { stopWifi(GetInstanceName()); }
 
    protected:
     bool isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask cap_mask) {
@@ -52,6 +55,9 @@
     }
 
     sp<IWifiStaIface> wifi_sta_iface_;
+
+   private:
+    std::string GetInstanceName() { return GetParam(); }
 };
 
 /*
@@ -59,7 +65,7 @@
  * Ensures that calls to set MAC address will return a success status
  * code.
  */
-TEST_F(WifiStaIfaceHidlTest, SetMacAddress) {
+TEST_P(WifiStaIfaceHidlTest, SetMacAddress) {
     const android::hardware::hidl_array<uint8_t, 6> kMac{
         std::array<uint8_t, 6>{{0x12, 0x22, 0x33, 0x52, 0x10, 0x41}}};
     EXPECT_EQ(WifiStatusCode::SUCCESS,
@@ -76,7 +82,7 @@
  * TODO: We can't execute APF opcodes from this test because there's no way
  * to loop test packets through the wifi firmware (b/73804303#comment29).
  */
-TEST_F(WifiStaIfaceHidlTest, DISABLED_ReadApfPacketFilterData) {
+TEST_P(WifiStaIfaceHidlTest, DISABLED_ReadApfPacketFilterData) {
     if (!isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask::APF)) {
         // Disable test if APF packet filer is not supported.
         LOG(WARNING) << "TEST SKIPPED: APF packet filtering not supported";
@@ -107,3 +113,9 @@
 
     EXPECT_EQ(status_and_data.second, data);
 }
+
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, WifiStaIfaceHidlTest,
+    testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+        ::android::hardware::wifi::V1_2::IWifi::descriptor)),
+    android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/wifi/1.3/vts/functional/Android.bp b/wifi/1.3/vts/functional/Android.bp
index 9ffda8b..fe9c791 100644
--- a/wifi/1.3/vts/functional/Android.bp
+++ b/wifi/1.3/vts/functional/Android.bp
@@ -30,4 +30,6 @@
         "android.hardware.wifi@1.3",
         "libwifi-system-iface"
     ],
+    disable_framework: true,
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/wifi/1.3/vts/functional/VtsHalWifiV1_3TargetTest.cpp b/wifi/1.3/vts/functional/VtsHalWifiV1_3TargetTest.cpp
index faf426e..52c7a4a 100644
--- a/wifi/1.3/vts/functional/VtsHalWifiV1_3TargetTest.cpp
+++ b/wifi/1.3/vts/functional/VtsHalWifiV1_3TargetTest.cpp
@@ -14,37 +14,8 @@
  * limitations under the License.
  */
 
-#include <android-base/logging.h>
-#include <android/hardware/wifi/1.3/IWifi.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 
-#include "wifi_hidl_test_utils.h"
-
-using ::android::hardware::wifi::V1_3::IWifi;
-
-// Test environment for Wifi HIDL HAL.
-class WifiHidlEnvironment_1_3 : public WifiHidlEnvironment {
-   public:
-    // get the test environment singleton
-    static WifiHidlEnvironment_1_3* Instance() {
-        static WifiHidlEnvironment_1_3* instance = new WifiHidlEnvironment_1_3;
-        return instance;
-    }
-
-    virtual void registerTestServices() override {
-        registerTestService<android::hardware::wifi::V1_3::IWifi>();
-    }
-
-   private:
-    WifiHidlEnvironment_1_3() {}
-};
-
-WifiHidlEnvironment_1_3* gEnv = WifiHidlEnvironment_1_3::Instance();
-
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(gEnv);
-    ::testing::InitGoogleTest(&argc, argv);
-    gEnv->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    LOG(INFO) << "Test result = " << status;
-    return status;
-}
+// TODO(b/143892896): Remove this file after wifi_hidl_test_utils.cpp is
+// updated.
+::testing::VtsHalHidlTargetTestEnvBase* gEnv = nullptr;
\ No newline at end of file
diff --git a/wifi/1.3/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.3/vts/functional/wifi_chip_hidl_test.cpp
index d980fcb..db93967 100644
--- a/wifi/1.3/vts/functional/wifi_chip_hidl_test.cpp
+++ b/wifi/1.3/vts/functional/wifi_chip_hidl_test.cpp
@@ -16,9 +16,11 @@
 
 #include <android-base/logging.h>
 
+#include <android/hardware/wifi/1.3/IWifi.h>
 #include <android/hardware/wifi/1.3/IWifiChip.h>
-
-#include <VtsHalHidlTargetTestBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include "wifi_hidl_call_util.h"
 #include "wifi_hidl_test_utils.h"
@@ -39,14 +41,14 @@
 /**
  * Fixture to use for all Wifi chip HIDL interface tests.
  */
-class WifiChipHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class WifiChipHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
-        wifi_chip_ = IWifiChip::castFrom(getWifiChip());
+        wifi_chip_ = IWifiChip::castFrom(getWifiChip(GetInstanceName()));
         ASSERT_NE(nullptr, wifi_chip_.get());
     }
 
-    virtual void TearDown() override { stopWifi(); }
+    virtual void TearDown() override { stopWifi(GetInstanceName()); }
 
    protected:
     // Helper function to configure the Chip in one of the supported modes.
@@ -70,6 +72,9 @@
     }
 
     sp<IWifiChip> wifi_chip_;
+
+   private:
+    std::string GetInstanceName() { return GetParam(); }
 };
 
 /*
@@ -77,7 +82,7 @@
  * This test case tests the setLatencyMode() API with
  * Latency mode NORMAL
  */
-TEST_F(WifiChipHidlTest, SetLatencyMode_normal) {
+TEST_P(WifiChipHidlTest, SetLatencyMode_normal) {
     uint32_t caps = configureChipForStaIfaceAndGetCapabilities();
     const auto& status =
         HIDL_INVOKE(wifi_chip_, setLatencyMode, kLatencyModeNormal);
@@ -92,7 +97,7 @@
  * SetLatencyMode_low
  * This test case tests the setLatencyMode() API with Latency mode LOW
  */
-TEST_F(WifiChipHidlTest, SetLatencyMode_low) {
+TEST_P(WifiChipHidlTest, SetLatencyMode_low) {
     uint32_t caps = configureChipForStaIfaceAndGetCapabilities();
     const auto& status =
         HIDL_INVOKE(wifi_chip_, setLatencyMode, kLatencyModeLow);
@@ -106,7 +111,7 @@
 /*
  * GetCapabilities_1_3
  */
-TEST_F(WifiChipHidlTest, GetCapabilities_1_3) {
+TEST_P(WifiChipHidlTest, GetCapabilities_1_3) {
     configureChipForIfaceType(IfaceType::STA, true);
     const auto& status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities_1_3);
     if (status_and_caps.first.code != WifiStatusCode::SUCCESS) {
@@ -116,3 +121,9 @@
     }
     EXPECT_NE(0u, status_and_caps.second);
 }
+
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, WifiChipHidlTest,
+    testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+        ::android::hardware::wifi::V1_3::IWifi::descriptor)),
+    android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/wifi/1.3/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.3/vts/functional/wifi_sta_iface_hidl_test.cpp
index d382f30..c5acc3c 100644
--- a/wifi/1.3/vts/functional/wifi_sta_iface_hidl_test.cpp
+++ b/wifi/1.3/vts/functional/wifi_sta_iface_hidl_test.cpp
@@ -19,9 +19,11 @@
 
 #include <android-base/logging.h>
 
+#include <android/hardware/wifi/1.3/IWifi.h>
 #include <android/hardware/wifi/1.3/IWifiStaIface.h>
-
-#include <VtsHalHidlTargetTestBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include "wifi_hidl_call_util.h"
 #include "wifi_hidl_test_utils.h"
@@ -35,14 +37,15 @@
 /**
  * Fixture to use for all STA Iface HIDL interface tests.
  */
-class WifiStaIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class WifiStaIfaceHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
-        wifi_sta_iface_ = IWifiStaIface::castFrom(getWifiStaIface());
+        wifi_sta_iface_ =
+            IWifiStaIface::castFrom(getWifiStaIface(GetInstanceName()));
         ASSERT_NE(nullptr, wifi_sta_iface_.get());
     }
 
-    virtual void TearDown() override { stopWifi(); }
+    virtual void TearDown() override { stopWifi(GetInstanceName()); }
 
    protected:
     bool isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask cap_mask) {
@@ -53,6 +56,9 @@
     }
 
     sp<IWifiStaIface> wifi_sta_iface_;
+
+   private:
+    std::string GetInstanceName() { return GetParam(); }
 };
 
 /*
@@ -60,7 +66,7 @@
  * Ensures that calls to get factory MAC address will retrieve a non-zero MAC
  * and return a success status code.
  */
-TEST_F(WifiStaIfaceHidlTest, GetFactoryMacAddress) {
+TEST_P(WifiStaIfaceHidlTest, GetFactoryMacAddress) {
     std::pair<WifiStatus, hidl_array<uint8_t, 6> > status_and_mac =
         HIDL_INVOKE(wifi_sta_iface_, getFactoryMacAddress);
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_mac.first.code);
@@ -73,7 +79,7 @@
  * Ensures that calls to get link layer stats V1_3 will retrieve a non-empty
  * StaLinkLayerStats after link layer stats collection is enabled.
  */
-TEST_F(WifiStaIfaceHidlTest, GetLinkLayerStats_1_3) {
+TEST_P(WifiStaIfaceHidlTest, GetLinkLayerStats_1_3) {
     if (!isCapabilitySupported(
             IWifiStaIface::StaIfaceCapabilityMask::LINK_LAYER_STATS)) {
         // No-op if link layer stats is not supported.
@@ -94,3 +100,9 @@
         WifiStatusCode::SUCCESS,
         HIDL_INVOKE(wifi_sta_iface_, disableLinkLayerStatsCollection).code);
 }
+
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, WifiStaIfaceHidlTest,
+    testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+        ::android::hardware::wifi::V1_3::IWifi::descriptor)),
+    android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/wifi/1.4/Android.bp b/wifi/1.4/Android.bp
index e197859..b443230 100644
--- a/wifi/1.4/Android.bp
+++ b/wifi/1.4/Android.bp
@@ -11,8 +11,11 @@
         "IWifi.hal",
         "IWifiApIface.hal",
         "IWifiChip.hal",
+        "IWifiChipEventCallback.hal",
+        "IWifiNanIface.hal",
         "IWifiRttController.hal",
         "IWifiRttControllerEventCallback.hal",
+        "IWifiStaIface.hal",
     ],
     interfaces: [
         "android.hardware.wifi@1.0",
diff --git a/wifi/1.4/IWifiChip.hal b/wifi/1.4/IWifiChip.hal
index d269427..07f4a65 100644
--- a/wifi/1.4/IWifiChip.hal
+++ b/wifi/1.4/IWifiChip.hal
@@ -19,6 +19,7 @@
 import @1.0::WifiStatus;
 import @1.0::IWifiIface;
 import @1.3::IWifiChip;
+import IWifiChipEventCallback;
 import IWifiRttController;
 
 /**
@@ -26,6 +27,21 @@
  */
 interface IWifiChip extends @1.3::IWifiChip {
     /**
+     * Requests notifications of significant events on this chip. Multiple calls
+     * to this must register multiple callbacks each of which must receive all
+     * events.
+     *
+     * @param callback An instance of the |IWifiChipEventCallback| HIDL interface
+     *        object.
+     * @return status WifiStatus of the operation.
+     *         Possible status codes:
+     *         |WifiStatusCode.SUCCESS|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|
+     */
+    registerEventCallback_1_4(IWifiChipEventCallback callback) generates (WifiStatus status);
+
+    /**
      * Create a RTTController instance.
      *
      * RTT controller can be either:
diff --git a/wifi/1.4/IWifiChipEventCallback.hal b/wifi/1.4/IWifiChipEventCallback.hal
new file mode 100644
index 0000000..9ead344
--- /dev/null
+++ b/wifi/1.4/IWifiChipEventCallback.hal
@@ -0,0 +1,69 @@
+/*
+ * 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.2::IWifiChipEventCallback;
+import WifiBand;
+
+/**
+ * Wifi chip event callbacks.
+ */
+interface IWifiChipEventCallback extends @1.2::IWifiChipEventCallback {
+    /**
+     * Struct describing the state of each hardware radio chain (hardware MAC)
+     * on the device.
+     */
+    struct RadioModeInfo {
+        /**
+         * Identifier for this radio chain. This is vendor dependent & used
+         * only for debugging purposes.
+         */
+        uint32_t radioId;
+
+        /**
+         * List of bands on which this radio chain is operating.
+         * Can be one of:
+         * a) WifiBand.BAND_24GHZ => 2.4Ghz.
+         * b) WifiBand.BAND_5GHZ => 5Ghz.
+         * c) WifiBand.BAND_24GHZ_5GHZ = 2.4Ghz + 5Ghz (Radio is time sharing
+         * across the 2 bands).
+         * d) WifiBand.BAND_6GHZ => 6Ghz.
+         * e) WifiBand.BAND_5GHZ_6GHZ => 5Ghz + 6Ghz (Radio is time sharing
+         * across the 2 bands).
+         * f) WifiBand.BAND_24GHZ_5GHZ_6GHZ => 2.4Ghz + 5Ghz + 6Ghz (Radio is
+         * time sharing across the 3 bands).
+         */
+        WifiBand bandInfo;
+
+        /**
+         * List of interfaces on this radio chain (hardware MAC).
+         */
+        vec<IfaceInfo> ifaceInfos;
+    };
+
+    /**
+     * Asynchronous callback indicating a radio mode change.
+     * Radio mode change could be a result of:
+     * a) Bringing up concurrent interfaces (For ex: STA + AP).
+     * b) Change in operating band of one of the concurrent interfaces (For ex:
+     * STA connection moved from 2.4G to 5G)
+     *
+     * @param radioModeInfos List of RadioModeInfo structures for each
+     * radio chain (hardware MAC) on the device.
+     */
+    oneway onRadioModeChange_1_4(vec<RadioModeInfo> radioModeInfos);
+};
diff --git a/wifi/1.4/IWifiNanIface.hal b/wifi/1.4/IWifiNanIface.hal
new file mode 100644
index 0000000..881d06c
--- /dev/null
+++ b/wifi/1.4/IWifiNanIface.hal
@@ -0,0 +1,78 @@
+/*
+ * 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::CommandIdShort;
+import @1.0::WifiStatus;
+import @1.2::IWifiNanIface;
+import @1.2::NanConfigRequestSupplemental;
+import NanConfigRequest;
+import NanEnableRequest;
+
+/**
+ * Interface used to represent a single NAN (Neighbour Aware Network) iface.
+ *
+ * References to "NAN Spec" are to the Wi-Fi Alliance "Wi-Fi Neighbor Awareness
+ * Networking (NAN) Technical Specification".
+ */
+interface IWifiNanIface extends @1.2::IWifiNanIface {
+    /**
+     * Enable NAN: configures and activates NAN clustering (does not start
+     * a discovery session or set up data-interfaces or data-paths). Use the
+     * |IWifiNanIface.configureRequest| method to change the configuration of an already enabled
+     * NAN interface.
+     * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyEnableResponse|.
+     *
+     * Note: supersedes the @1.2::IWifiNanIface.enableRequest() method which is deprecated as of
+     * HAL version 1.4.
+     *
+     * @param cmdId command Id to use for this invocation.
+     * @param msg1 Instance of |NanEnableRequest|.
+     * @param msg2 Instance of |NanConfigRequestSupplemental|.
+     * @return status WifiStatus of the operation.
+     *         Possible status codes:
+     *         |WifiStatusCode.SUCCESS|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    enableRequest_1_4(CommandIdShort cmdId, NanEnableRequest msg1,
+        NanConfigRequestSupplemental msg2) generates (WifiStatus status);
+
+    /**
+     * Configure NAN: configures an existing NAN functionality (i.e. assumes
+     * |IWifiNanIface.enableRequest| already submitted and succeeded).
+     * Asynchronous response is with |IWifiNanIfaceEventCallback.notifyConfigResponse|.
+     *
+     * Note: supersedes the @1.2::IWifiNanIface.configRequest() method which is deprecated as of
+     * HAL version 1.4.
+     *
+     * @param cmdId command Id to use for this invocation.
+     * @param msg1 Instance of |NanConfigRequest|.
+     * @param msg1 Instance of |NanConfigRequestSupplemental|.
+     * @return status WifiStatus of the operation.
+     *         Possible status codes:
+     *         |WifiStatusCode.SUCCESS|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    configRequest_1_4(CommandIdShort cmdId, NanConfigRequest msg1,
+        NanConfigRequestSupplemental msg2) generates (WifiStatus status);
+};
diff --git a/wifi/1.4/IWifiStaIface.hal b/wifi/1.4/IWifiStaIface.hal
new file mode 100644
index 0000000..8bb0de8
--- /dev/null
+++ b/wifi/1.4/IWifiStaIface.hal
@@ -0,0 +1,48 @@
+/*
+ * 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 61f311e..a7c5686 100644
--- a/wifi/1.4/default/hidl_struct_util.cpp
+++ b/wifi/1.4/default/hidl_struct_util.cpp
@@ -91,7 +91,7 @@
 }
 
 IWifiStaIface::StaIfaceCapabilityMask
-convertLegacyFeatureToHidlStaIfaceCapability(uint32_t feature) {
+convertLegacyFeatureToHidlStaIfaceCapability(uint64_t feature) {
     using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask;
     switch (feature) {
         case WIFI_FEATURE_GSCAN:
@@ -120,6 +120,8 @@
             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 {};
@@ -314,7 +316,7 @@
 
 bool convertLegacyWifiMacInfoToHidl(
     const legacy_hal::WifiMacInfo& legacy_mac_info,
-    V1_2::IWifiChipEventCallback::RadioModeInfo* hidl_radio_mode_info) {
+    IWifiChipEventCallback::RadioModeInfo* hidl_radio_mode_info) {
     if (!hidl_radio_mode_info) {
         return false;
     }
@@ -323,8 +325,17 @@
     hidl_radio_mode_info->radioId = legacy_mac_info.wlan_mac_id;
     // Convert from bitmask of bands in the legacy HAL to enum value in
     // the HIDL interface.
-    if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND &&
-        legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) {
+    if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND &&
+        legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND &&
+        legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND) {
+        hidl_radio_mode_info->bandInfo = WifiBand::BAND_24GHZ_5GHZ_6GHZ;
+    } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND &&
+               legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) {
+        hidl_radio_mode_info->bandInfo = WifiBand::BAND_5GHZ_6GHZ;
+    } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND) {
+        hidl_radio_mode_info->bandInfo = WifiBand::BAND_6GHZ;
+    } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND &&
+               legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) {
         hidl_radio_mode_info->bandInfo = WifiBand::BAND_24GHZ_5GHZ;
     } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND) {
         hidl_radio_mode_info->bandInfo = WifiBand::BAND_24GHZ;
@@ -346,15 +357,14 @@
 
 bool convertLegacyWifiMacInfosToHidl(
     const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos,
-    std::vector<V1_2::IWifiChipEventCallback::RadioModeInfo>*
-        hidl_radio_mode_infos) {
+    std::vector<IWifiChipEventCallback::RadioModeInfo>* hidl_radio_mode_infos) {
     if (!hidl_radio_mode_infos) {
         return false;
     }
     *hidl_radio_mode_infos = {};
 
     for (const auto& legacy_mac_info : legacy_mac_infos) {
-        V1_2::IWifiChipEventCallback::RadioModeInfo hidl_radio_mode_info;
+        IWifiChipEventCallback::RadioModeInfo hidl_radio_mode_info;
         if (!convertLegacyWifiMacInfoToHidl(legacy_mac_info,
                                             &hidl_radio_mode_info)) {
             return false;
@@ -365,7 +375,7 @@
 }
 
 bool convertLegacyFeaturesToHidlStaCapabilities(
-    uint32_t legacy_feature_set, uint32_t legacy_logger_feature_set,
+    uint64_t legacy_feature_set, uint32_t legacy_logger_feature_set,
     uint32_t* hidl_caps) {
     if (!hidl_caps) {
         return false;
@@ -384,7 +394,8 @@
           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_CONFIG_NDO, WIFI_FEATURE_MKEEP_ALIVE,
+          WIFI_FEATURE_INFRA_6G}) {
         if (feature & legacy_feature_set) {
             *hidl_caps |= convertLegacyFeatureToHidlStaIfaceCapability(feature);
         }
@@ -446,21 +457,21 @@
     return true;
 }
 
-legacy_hal::wifi_band convertHidlWifiBandToLegacy(WifiBand band) {
+legacy_hal::wifi_band convertHidlWifiBandToLegacy(V1_0::WifiBand band) {
     switch (band) {
-        case WifiBand::BAND_UNSPECIFIED:
+        case V1_0::WifiBand::BAND_UNSPECIFIED:
             return legacy_hal::WIFI_BAND_UNSPECIFIED;
-        case WifiBand::BAND_24GHZ:
+        case V1_0::WifiBand::BAND_24GHZ:
             return legacy_hal::WIFI_BAND_BG;
-        case WifiBand::BAND_5GHZ:
+        case V1_0::WifiBand::BAND_5GHZ:
             return legacy_hal::WIFI_BAND_A;
-        case WifiBand::BAND_5GHZ_DFS:
+        case V1_0::WifiBand::BAND_5GHZ_DFS:
             return legacy_hal::WIFI_BAND_A_DFS;
-        case WifiBand::BAND_5GHZ_WITH_DFS:
+        case V1_0::WifiBand::BAND_5GHZ_WITH_DFS:
             return legacy_hal::WIFI_BAND_A_WITH_DFS;
-        case WifiBand::BAND_24GHZ_5GHZ:
+        case V1_0::WifiBand::BAND_24GHZ_5GHZ:
             return legacy_hal::WIFI_BAND_ABG;
-        case WifiBand::BAND_24GHZ_5GHZ_WITH_DFS:
+        case V1_0::WifiBand::BAND_24GHZ_5GHZ_WITH_DFS:
             return legacy_hal::WIFI_BAND_ABG_WITH_DFS;
     };
     CHECK(false);
@@ -1259,16 +1270,20 @@
         hidl_request.debugConfigs
             .useSdfInBandVal[(size_t)NanBandIndex::NAN_BAND_5GHZ];
 
+    /* TODO: b/145609058
+     * Missing updates needed to legacy_hal::NanEnableRequest and conversion to
+     * it for 6GHz band */
+
     return true;
 }
 
-bool convertHidlNanEnableRequest_1_2ToLegacy(
+bool convertHidlNanEnableRequest_1_4ToLegacy(
     const NanEnableRequest& hidl_request1,
     const V1_2::NanConfigRequestSupplemental& hidl_request2,
     legacy_hal::NanEnableRequest* legacy_request) {
     if (!legacy_request) {
         LOG(ERROR)
-            << "convertHidlNanEnableRequest_1_2ToLegacy: null legacy_request";
+            << "convertHidlNanEnableRequest_1_4ToLegacy: null legacy_request";
         return false;
     }
 
@@ -1769,16 +1784,19 @@
     legacy_request->config_dw.dw_5g_interval_val =
         hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
             .discoveryWindowIntervalVal;
+    /* TODO: b/145609058
+     * Missing updates needed to legacy_hal::NanConfigRequest and conversion to
+     * it for 6GHz band */
 
     return true;
 }
 
-bool convertHidlNanConfigRequest_1_2ToLegacy(
+bool convertHidlNanConfigRequest_1_4ToLegacy(
     const NanConfigRequest& hidl_request1,
     const V1_2::NanConfigRequestSupplemental& hidl_request2,
     legacy_hal::NanConfigRequest* legacy_request) {
     if (!legacy_request) {
-        LOG(ERROR) << "convertHidlNanConfigRequest_1_2ToLegacy: legacy_request "
+        LOG(ERROR) << "convertHidlNanConfigRequest_1_4ToLegacy: legacy_request "
                       "is null";
         return false;
     }
@@ -1819,7 +1837,13 @@
         convertHidlNanDataPathChannelCfgToLegacy(
             hidl_request.channelRequestType);
     legacy_request->channel = hidl_request.channel;
-    strcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str());
+    if (strnlen(hidl_request.ifaceName.c_str(), IFNAMSIZ + 1) == IFNAMSIZ + 1) {
+        LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: "
+                      "ifaceName too long";
+        return false;
+    }
+    strncpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str(),
+            IFNAMSIZ + 1);
     legacy_request->ndp_cfg.security_cfg =
         (hidl_request.securityConfig.securityType !=
          NanDataPathSecurityType::OPEN)
@@ -1900,7 +1924,13 @@
                                    ? legacy_hal::NAN_DP_REQUEST_ACCEPT
                                    : legacy_hal::NAN_DP_REQUEST_REJECT;
     legacy_request->ndp_instance_id = hidl_request.ndpInstanceId;
-    strcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str());
+    if (strnlen(hidl_request.ifaceName.c_str(), IFNAMSIZ + 1) == IFNAMSIZ + 1) {
+        LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: "
+                      "ifaceName too long";
+        return false;
+    }
+    strncpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str(),
+            IFNAMSIZ + 1);
     legacy_request->ndp_cfg.security_cfg =
         (hidl_request.securityConfig.securityType !=
          NanDataPathSecurityType::OPEN)
diff --git a/wifi/1.4/default/hidl_struct_util.h b/wifi/1.4/default/hidl_struct_util.h
index a99c1ac..160870a 100644
--- a/wifi/1.4/default/hidl_struct_util.h
+++ b/wifi/1.4/default/hidl_struct_util.h
@@ -21,10 +21,11 @@
 
 #include <android/hardware/wifi/1.0/IWifiChip.h>
 #include <android/hardware/wifi/1.0/types.h>
-#include <android/hardware/wifi/1.2/IWifiChipEventCallback.h>
 #include <android/hardware/wifi/1.2/types.h>
 #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"
@@ -64,12 +65,11 @@
     V1_2::IWifiChip::TxPowerScenario hidl_scenario);
 bool convertLegacyWifiMacInfosToHidl(
     const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos,
-    std::vector<V1_2::IWifiChipEventCallback::RadioModeInfo>*
-        hidl_radio_mode_infos);
+    std::vector<IWifiChipEventCallback::RadioModeInfo>* hidl_radio_mode_infos);
 
 // STA iface conversion methods.
 bool convertLegacyFeaturesToHidlStaCapabilities(
-    uint32_t legacy_feature_set, uint32_t legacy_logger_feature_set,
+    uint64_t legacy_feature_set, uint32_t legacy_logger_feature_set,
     uint32_t* hidl_caps);
 bool convertLegacyApfCapabilitiesToHidl(
     const legacy_hal::PacketFilterCapabilities& legacy_caps,
@@ -77,7 +77,7 @@
 bool convertLegacyGscanCapabilitiesToHidl(
     const legacy_hal::wifi_gscan_capabilities& legacy_caps,
     StaBackgroundScanCapabilities* hidl_caps);
-legacy_hal::wifi_band convertHidlWifiBandToLegacy(WifiBand band);
+legacy_hal::wifi_band convertHidlWifiBandToLegacy(V1_0::WifiBand band);
 bool convertHidlGscanParamsToLegacy(
     const StaBackgroundScanParameters& hidl_scan_params,
     legacy_hal::wifi_scan_cmd_params* legacy_scan_params);
@@ -118,11 +118,11 @@
 bool convertHidlNanConfigRequestToLegacy(
     const NanConfigRequest& hidl_request,
     legacy_hal::NanConfigRequest* legacy_request);
-bool convertHidlNanEnableRequest_1_2ToLegacy(
+bool convertHidlNanEnableRequest_1_4ToLegacy(
     const NanEnableRequest& hidl_request1,
     const V1_2::NanConfigRequestSupplemental& hidl_request2,
     legacy_hal::NanEnableRequest* legacy_request);
-bool convertHidlNanConfigRequest_1_2ToLegacy(
+bool convertHidlNanConfigRequest_1_4ToLegacy(
     const NanConfigRequest& hidl_request1,
     const V1_2::NanConfigRequestSupplemental& hidl_request2,
     legacy_hal::NanConfigRequest* legacy_request);
diff --git a/wifi/1.4/default/tests/hidl_struct_util_unit_tests.cpp b/wifi/1.4/default/tests/hidl_struct_util_unit_tests.cpp
index 14a1504..b71d549 100644
--- a/wifi/1.4/default/tests/hidl_struct_util_unit_tests.cpp
+++ b/wifi/1.4/default/tests/hidl_struct_util_unit_tests.cpp
@@ -55,8 +55,7 @@
     legacy_mac_info1.iface_infos.push_back(legacy_iface_info2);
     legacy_mac_infos.push_back(legacy_mac_info1);
 
-    std::vector<V1_2::IWifiChipEventCallback::RadioModeInfo>
-        hidl_radio_mode_infos;
+    std::vector<IWifiChipEventCallback::RadioModeInfo> hidl_radio_mode_infos;
     ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl(
         legacy_mac_infos, &hidl_radio_mode_infos));
 
@@ -90,20 +89,18 @@
     legacy_mac_info2.iface_infos.push_back(legacy_iface_info2);
     legacy_mac_infos.push_back(legacy_mac_info2);
 
-    std::vector<V1_2::IWifiChipEventCallback::RadioModeInfo>
-        hidl_radio_mode_infos;
+    std::vector<IWifiChipEventCallback::RadioModeInfo> hidl_radio_mode_infos;
     ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl(
         legacy_mac_infos, &hidl_radio_mode_infos));
 
     ASSERT_EQ(2u, hidl_radio_mode_infos.size());
 
     // Find mac info 1.
-    const auto hidl_radio_mode_info1 =
-        std::find_if(hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
-                     [&legacy_mac_info1](
-                         const V1_2::IWifiChipEventCallback::RadioModeInfo& x) {
-                         return x.radioId == legacy_mac_info1.wlan_mac_id;
-                     });
+    const auto hidl_radio_mode_info1 = std::find_if(
+        hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
+        [&legacy_mac_info1](const IWifiChipEventCallback::RadioModeInfo& x) {
+            return x.radioId == legacy_mac_info1.wlan_mac_id;
+        });
     ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info1);
     EXPECT_EQ(WifiBand::BAND_5GHZ, hidl_radio_mode_info1->bandInfo);
     ASSERT_EQ(1u, hidl_radio_mode_info1->ifaceInfos.size());
@@ -113,12 +110,11 @@
               hidl_iface_info1.channel);
 
     // Find mac info 2.
-    const auto hidl_radio_mode_info2 =
-        std::find_if(hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
-                     [&legacy_mac_info2](
-                         const V1_2::IWifiChipEventCallback::RadioModeInfo& x) {
-                         return x.radioId == legacy_mac_info2.wlan_mac_id;
-                     });
+    const auto hidl_radio_mode_info2 = std::find_if(
+        hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
+        [&legacy_mac_info2](const IWifiChipEventCallback::RadioModeInfo& x) {
+            return x.radioId == legacy_mac_info2.wlan_mac_id;
+        });
     ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info2);
     EXPECT_EQ(WifiBand::BAND_24GHZ, hidl_radio_mode_info2->bandInfo);
     ASSERT_EQ(1u, hidl_radio_mode_info2->ifaceInfos.size());
diff --git a/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp
index 90e81e1..d35adbc 100644
--- a/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp
@@ -720,13 +720,16 @@
             ASSERT_EQ(iface_names[0], "wlan0");
         });
     // Retrieve the exact iface object.
-    sp<IWifiNanIface> nan_iface;
-    chip_->getNanIface("wlan0", [&nan_iface](const WifiStatus& status,
-                                             const sp<IWifiNanIface>& iface) {
-        ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
-        ASSERT_NE(iface.get(), nullptr);
-        nan_iface = iface;
-    });
+    sp<android::hardware::wifi::V1_0::IWifiNanIface> nan_iface;
+    chip_->getNanIface(
+        "wlan0",
+        [&nan_iface](
+            const WifiStatus& status,
+            const sp<android::hardware::wifi::V1_0::IWifiNanIface>& iface) {
+            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+            ASSERT_NE(iface.get(), nullptr);
+            nan_iface = iface;
+        });
 
     // Remove the STA iface.
     removeIface(IfaceType::STA, "wlan0");
diff --git a/wifi/1.4/default/tests/wifi_nan_iface_unit_tests.cpp b/wifi/1.4/default/tests/wifi_nan_iface_unit_tests.cpp
index 8aefa92..9022792 100644
--- a/wifi/1.4/default/tests/wifi_nan_iface_unit_tests.cpp
+++ b/wifi/1.4/default/tests/wifi_nan_iface_unit_tests.cpp
@@ -41,6 +41,9 @@
 namespace V1_4 {
 namespace implementation {
 
+using android::hardware::wifi::V1_2::IWifiNanIfaceEventCallback;
+using android::hardware::wifi::V1_2::NanDataPathConfirmInd;
+
 bool CaptureIfaceEventHandlers(
     const std::string& /* iface_name*/,
     iface_util::IfaceEventHandlers in_iface_event_handlers,
@@ -96,9 +99,15 @@
                  Return<void>(uint16_t, const WifiNanStatus&));
     MOCK_METHOD1(eventDataPathRequest,
                  Return<void>(const NanDataPathRequestInd&));
-    MOCK_METHOD1(eventDataPathConfirm,
-                 Return<void>(const NanDataPathConfirmInd&));
+    MOCK_METHOD1(
+        eventDataPathConfirm,
+        Return<void>(
+            const android::hardware::wifi::V1_0::NanDataPathConfirmInd&));
     MOCK_METHOD1(eventDataPathTerminated, Return<void>(uint32_t));
+    MOCK_METHOD1(eventDataPathConfirm_1_2,
+                 Return<void>(const NanDataPathConfirmInd&));
+    MOCK_METHOD1(eventDataPathScheduleUpdate,
+                 Return<void>(const NanDataPathScheduleUpdateInd&));
 };
 
 class WifiNanIfaceTest : public Test {
diff --git a/wifi/1.4/default/wifi_ap_iface.cpp b/wifi/1.4/default/wifi_ap_iface.cpp
index e677f19..8777a4c 100644
--- a/wifi/1.4/default/wifi_ap_iface.cpp
+++ b/wifi/1.4/default/wifi_ap_iface.cpp
@@ -64,7 +64,7 @@
 }
 
 Return<void> WifiApIface::getValidFrequenciesForBand(
-    WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) {
+    V1_0::WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
                            &WifiApIface::getValidFrequenciesForBandInternal,
                            hidl_status_cb, band);
@@ -100,7 +100,7 @@
 }
 
 std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
-WifiApIface::getValidFrequenciesForBandInternal(WifiBand band) {
+WifiApIface::getValidFrequenciesForBandInternal(V1_0::WifiBand band) {
     static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t),
                   "Size mismatch");
     legacy_hal::wifi_error legacy_status;
diff --git a/wifi/1.4/default/wifi_ap_iface.h b/wifi/1.4/default/wifi_ap_iface.h
index 4f3438c..bf16d5e 100644
--- a/wifi/1.4/default/wifi_ap_iface.h
+++ b/wifi/1.4/default/wifi_ap_iface.h
@@ -49,7 +49,8 @@
     Return<void> setCountryCode(const hidl_array<int8_t, 2>& code,
                                 setCountryCode_cb hidl_status_cb) override;
     Return<void> getValidFrequenciesForBand(
-        WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) override;
+        V1_0::WifiBand band,
+        getValidFrequenciesForBand_cb hidl_status_cb) override;
     Return<void> setMacAddress(const hidl_array<uint8_t, 6>& mac,
                                setMacAddress_cb hidl_status_cb) override;
     Return<void> getFactoryMacAddress(
@@ -61,7 +62,7 @@
     std::pair<WifiStatus, IfaceType> getTypeInternal();
     WifiStatus setCountryCodeInternal(const std::array<int8_t, 2>& code);
     std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
-    getValidFrequenciesForBandInternal(WifiBand band);
+    getValidFrequenciesForBandInternal(V1_0::WifiBand band);
     WifiStatus setMacAddressInternal(const std::array<uint8_t, 6>& mac);
     std::pair<WifiStatus, std::array<uint8_t, 6>>
     getFactoryMacAddressInternal();
diff --git a/wifi/1.4/default/wifi_chip.cpp b/wifi/1.4/default/wifi_chip.cpp
index 7685ac6..2b015d3 100644
--- a/wifi/1.4/default/wifi_chip.cpp
+++ b/wifi/1.4/default/wifi_chip.cpp
@@ -341,7 +341,7 @@
 
 bool WifiChip::isValid() { return is_valid_; }
 
-std::set<sp<V1_2::IWifiChipEventCallback>> WifiChip::getEventCallbacks() {
+std::set<sp<IWifiChipEventCallback>> WifiChip::getEventCallbacks() {
     return event_cb_handler_.getCallbacks();
 }
 
@@ -628,6 +628,14 @@
                            hidl_status_cb, bound_iface);
 }
 
+Return<void> WifiChip::registerEventCallback_1_4(
+    const sp<IWifiChipEventCallback>& event_callback,
+    registerEventCallback_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::registerEventCallbackInternal_1_4,
+                           hidl_status_cb, event_callback);
+}
+
 void WifiChip::invalidateAndRemoveAllIfaces() {
     invalidateAndClearAll(ap_ifaces_);
     invalidateAndClearAll(nan_ifaces_);
@@ -1021,6 +1029,12 @@
             max_interval_in_sec, min_data_size_in_bytes);
     ringbuffer_map_.insert(std::pair<std::string, Ringbuffer>(
         ring_name, Ringbuffer(kMaxBufferSizeBytes)));
+    // if verbose logging enabled, turn up HAL daemon logging as well.
+    if (verbose_level < WifiDebugRingBufferVerboseLevel::VERBOSE) {
+        android::base::SetMinimumLogSeverity(android::base::DEBUG);
+    } else {
+        android::base::SetMinimumLogSeverity(android::base::VERBOSE);
+    }
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
@@ -1119,11 +1133,9 @@
 }
 
 WifiStatus WifiChip::registerEventCallbackInternal_1_2(
-    const sp<V1_2::IWifiChipEventCallback>& event_callback) {
-    if (!event_cb_handler_.addCallback(event_callback)) {
-        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
-    }
-    return createWifiStatus(WifiStatusCode::SUCCESS);
+    const sp<V1_2::IWifiChipEventCallback>& /* event_callback */) {
+    // Deprecated support for this callback.
+    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
 }
 
 WifiStatus WifiChip::selectTxPowerScenarioInternal_1_2(
@@ -1173,6 +1185,14 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), rtt};
 }
 
+WifiStatus WifiChip::registerEventCallbackInternal_1_4(
+    const sp<IWifiChipEventCallback>& event_callback) {
+    if (!event_cb_handler_.addCallback(event_callback)) {
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
 WifiStatus WifiChip::handleChipConfiguration(
     /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
     ChipModeId mode_id) {
@@ -1275,7 +1295,7 @@
                 LOG(ERROR) << "Callback invoked on an invalid object";
                 return;
             }
-            std::vector<V1_2::IWifiChipEventCallback::RadioModeInfo>
+            std::vector<IWifiChipEventCallback::RadioModeInfo>
                 hidl_radio_mode_infos;
             if (!hidl_struct_util::convertLegacyWifiMacInfosToHidl(
                     mac_infos, &hidl_radio_mode_infos)) {
@@ -1283,9 +1303,9 @@
                 return;
             }
             for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-                if (!callback->onRadioModeChange(hidl_radio_mode_infos)
+                if (!callback->onRadioModeChange_1_4(hidl_radio_mode_infos)
                          .isOk()) {
-                    LOG(ERROR) << "Failed to invoke onRadioModeChange"
+                    LOG(ERROR) << "Failed to invoke onRadioModeChange_1_4"
                                << " callback on: " << toString(callback);
                 }
             }
diff --git a/wifi/1.4/default/wifi_chip.h b/wifi/1.4/default/wifi_chip.h
index 3bf1847..c76eabf 100644
--- a/wifi/1.4/default/wifi_chip.h
+++ b/wifi/1.4/default/wifi_chip.h
@@ -71,7 +71,7 @@
     // marked valid before processing them.
     void invalidate();
     bool isValid();
-    std::set<sp<V1_2::IWifiChipEventCallback>> getEventCallbacks();
+    std::set<sp<IWifiChipEventCallback>> getEventCallbacks();
 
     // HIDL methods exposed.
     Return<void> getId(getId_cb hidl_status_cb) override;
@@ -156,6 +156,9 @@
     Return<void> createRttController_1_4(
         const sp<IWifiIface>& bound_iface,
         createRttController_1_4_cb hidl_status_cb) override;
+    Return<void> registerEventCallback_1_4(
+        const sp<IWifiChipEventCallback>& event_callback,
+        registerEventCallback_1_4_cb hidl_status_cb) override;
 
    private:
     void invalidateAndRemoveAllIfaces();
@@ -223,6 +226,9 @@
     std::pair<WifiStatus, uint32_t> getCapabilitiesInternal_1_3();
     std::pair<WifiStatus, sp<IWifiRttController>>
     createRttControllerInternal_1_4(const sp<IWifiIface>& bound_iface);
+    WifiStatus registerEventCallbackInternal_1_4(
+        const sp<IWifiChipEventCallback>& event_callback);
+
     WifiStatus handleChipConfiguration(
         std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id);
     WifiStatus registerDebugRingBufferCallback();
@@ -271,7 +277,7 @@
     // registration mechanism. Use this to check if we have already
     // registered a callback.
     bool debug_ring_buffer_cb_registered_;
-    hidl_callback_util::HidlCallbackHandler<V1_2::IWifiChipEventCallback>
+    hidl_callback_util::HidlCallbackHandler<IWifiChipEventCallback>
         event_cb_handler_;
 
     DISALLOW_COPY_AND_ASSIGN(WifiChip);
diff --git a/wifi/1.4/default/wifi_legacy_hal.cpp b/wifi/1.4/default/wifi_legacy_hal.cpp
index 8139253..ae3c447 100644
--- a/wifi/1.4/default/wifi_legacy_hal.cpp
+++ b/wifi/1.4/default/wifi_legacy_hal.cpp
@@ -479,7 +479,7 @@
 std::pair<wifi_error, uint32_t> WifiLegacyHal::getSupportedFeatureSet(
     const std::string& iface_name) {
     feature_set set;
-    static_assert(sizeof(set) == sizeof(uint32_t),
+    static_assert(sizeof(set) == sizeof(uint64_t),
                   "Some feature_flags can not be represented in output");
     wifi_error status = global_func_table_.wifi_get_supported_feature_set(
         getIfaceHandle(iface_name), &set);
diff --git a/wifi/1.4/default/wifi_nan_iface.cpp b/wifi/1.4/default/wifi_nan_iface.cpp
index 981acb2..073101c 100644
--- a/wifi/1.4/default/wifi_nan_iface.cpp
+++ b/wifi/1.4/default/wifi_nan_iface.cpp
@@ -576,7 +576,7 @@
 }
 
 Return<void> WifiNanIface::enableRequest(uint16_t cmd_id,
-                                         const NanEnableRequest& msg,
+                                         const V1_0::NanEnableRequest& msg,
                                          enableRequest_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
                            &WifiNanIface::enableRequestInternal, hidl_status_cb,
@@ -584,7 +584,7 @@
 }
 
 Return<void> WifiNanIface::configRequest(uint16_t cmd_id,
-                                         const NanConfigRequest& msg,
+                                         const V1_0::NanConfigRequest& msg,
                                          configRequest_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
                            &WifiNanIface::configRequestInternal, hidl_status_cb,
@@ -687,7 +687,7 @@
 }
 
 Return<void> WifiNanIface::enableRequest_1_2(
-    uint16_t cmd_id, const NanEnableRequest& msg1,
+    uint16_t cmd_id, const V1_0::NanEnableRequest& msg1,
     const V1_2::NanConfigRequestSupplemental& msg2,
     enableRequest_1_2_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
@@ -696,7 +696,7 @@
 }
 
 Return<void> WifiNanIface::configRequest_1_2(
-    uint16_t cmd_id, const NanConfigRequest& msg1,
+    uint16_t cmd_id, const V1_0::NanConfigRequest& msg1,
     const V1_2::NanConfigRequestSupplemental& msg2,
     configRequest_1_2_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
@@ -704,6 +704,24 @@
                            hidl_status_cb, cmd_id, msg1, msg2);
 }
 
+Return<void> WifiNanIface::enableRequest_1_4(
+    uint16_t cmd_id, const NanEnableRequest& msg1,
+    const V1_2::NanConfigRequestSupplemental& msg2,
+    enableRequest_1_4_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::enableRequest_1_4Internal,
+                           hidl_status_cb, cmd_id, msg1, msg2);
+}
+
+Return<void> WifiNanIface::configRequest_1_4(
+    uint16_t cmd_id, const NanConfigRequest& msg1,
+    const V1_2::NanConfigRequestSupplemental& msg2,
+    configRequest_1_4_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::configRequest_1_4Internal,
+                           hidl_status_cb, cmd_id, msg1, msg2);
+}
+
 std::pair<WifiStatus, std::string> WifiNanIface::getNameInternal() {
     return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
 }
@@ -727,12 +745,12 @@
 }
 
 WifiStatus WifiNanIface::enableRequestInternal(
-    uint16_t /* cmd_id */, const NanEnableRequest& /* msg */) {
+    uint16_t /* cmd_id */, const V1_0::NanEnableRequest& /* msg */) {
     return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
 }
 
 WifiStatus WifiNanIface::configRequestInternal(
-    uint16_t /* cmd_id */, const NanConfigRequest& /* msg */) {
+    uint16_t /* cmd_id */, const V1_0::NanConfigRequest& /* msg */) {
     return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
 }
 
@@ -855,10 +873,22 @@
 }
 
 WifiStatus WifiNanIface::enableRequest_1_2Internal(
+    uint16_t /* cmd_id */, const V1_0::NanEnableRequest& /* msg1 */,
+    const V1_2::NanConfigRequestSupplemental& /*msg2 */) {
+    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
+}
+
+WifiStatus WifiNanIface::configRequest_1_2Internal(
+    uint16_t /* cmd_id */, const V1_0::NanConfigRequest& /* msg1 */,
+    const V1_2::NanConfigRequestSupplemental& /* msg2 */) {
+    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
+}
+
+WifiStatus WifiNanIface::enableRequest_1_4Internal(
     uint16_t cmd_id, const NanEnableRequest& msg1,
     const V1_2::NanConfigRequestSupplemental& msg2) {
     legacy_hal::NanEnableRequest legacy_msg;
-    if (!hidl_struct_util::convertHidlNanEnableRequest_1_2ToLegacy(
+    if (!hidl_struct_util::convertHidlNanEnableRequest_1_4ToLegacy(
             msg1, msg2, &legacy_msg)) {
         return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
     }
@@ -867,11 +897,11 @@
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
-WifiStatus WifiNanIface::configRequest_1_2Internal(
+WifiStatus WifiNanIface::configRequest_1_4Internal(
     uint16_t cmd_id, const NanConfigRequest& msg1,
     const V1_2::NanConfigRequestSupplemental& msg2) {
     legacy_hal::NanConfigRequest legacy_msg;
-    if (!hidl_struct_util::convertHidlNanConfigRequest_1_2ToLegacy(
+    if (!hidl_struct_util::convertHidlNanConfigRequest_1_4ToLegacy(
             msg1, msg2, &legacy_msg)) {
         return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
     }
diff --git a/wifi/1.4/default/wifi_nan_iface.h b/wifi/1.4/default/wifi_nan_iface.h
index e3a5c34..c16628b 100644
--- a/wifi/1.4/default/wifi_nan_iface.h
+++ b/wifi/1.4/default/wifi_nan_iface.h
@@ -19,7 +19,7 @@
 
 #include <android-base/macros.h>
 #include <android/hardware/wifi/1.0/IWifiNanIfaceEventCallback.h>
-#include <android/hardware/wifi/1.2/IWifiNanIface.h>
+#include <android/hardware/wifi/1.4/IWifiNanIface.h>
 
 #include "hidl_callback_util.h"
 #include "wifi_iface_util.h"
@@ -31,11 +31,12 @@
 namespace V1_4 {
 namespace implementation {
 using namespace android::hardware::wifi::V1_0;
+using namespace android::hardware::wifi::V1_2;
 
 /**
  * HIDL interface object used to control a NAN Iface instance.
  */
-class WifiNanIface : public V1_2::IWifiNanIface {
+class WifiNanIface : public V1_4::IWifiNanIface {
    public:
     WifiNanIface(const std::string& ifname,
                  const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
@@ -53,9 +54,11 @@
         registerEventCallback_cb hidl_status_cb) override;
     Return<void> getCapabilitiesRequest(
         uint16_t cmd_id, getCapabilitiesRequest_cb hidl_status_cb) override;
-    Return<void> enableRequest(uint16_t cmd_id, const NanEnableRequest& msg,
+    Return<void> enableRequest(uint16_t cmd_id,
+                               const V1_0::NanEnableRequest& msg,
                                enableRequest_cb hidl_status_cb) override;
-    Return<void> configRequest(uint16_t cmd_id, const NanConfigRequest& msg,
+    Return<void> configRequest(uint16_t cmd_id,
+                               const V1_0::NanConfigRequest& msg,
                                configRequest_cb hidl_status_cb) override;
     Return<void> disableRequest(uint16_t cmd_id,
                                 disableRequest_cb hidl_status_cb) override;
@@ -94,10 +97,18 @@
         const sp<V1_2::IWifiNanIfaceEventCallback>& callback,
         registerEventCallback_1_2_cb hidl_status_cb) override;
     Return<void> enableRequest_1_2(
-        uint16_t cmd_id, const NanEnableRequest& msg1,
+        uint16_t cmd_id, const V1_0::NanEnableRequest& msg1,
         const V1_2::NanConfigRequestSupplemental& msg2,
         enableRequest_1_2_cb hidl_status_cb) override;
     Return<void> configRequest_1_2(
+        uint16_t cmd_id, const V1_0::NanConfigRequest& msg1,
+        const V1_2::NanConfigRequestSupplemental& msg2,
+        configRequest_1_2_cb hidl_status_cb) override;
+    Return<void> enableRequest_1_4(
+        uint16_t cmd_id, const NanEnableRequest& msg1,
+        const V1_2::NanConfigRequestSupplemental& msg2,
+        enableRequest_1_2_cb hidl_status_cb) override;
+    Return<void> configRequest_1_4(
         uint16_t cmd_id, const NanConfigRequest& msg1,
         const V1_2::NanConfigRequestSupplemental& msg2,
         configRequest_1_2_cb hidl_status_cb) override;
@@ -110,9 +121,9 @@
         const sp<V1_0::IWifiNanIfaceEventCallback>& callback);
     WifiStatus getCapabilitiesRequestInternal(uint16_t cmd_id);
     WifiStatus enableRequestInternal(uint16_t cmd_id,
-                                     const NanEnableRequest& msg);
+                                     const V1_0::NanEnableRequest& msg);
     WifiStatus configRequestInternal(uint16_t cmd_id,
-                                     const NanConfigRequest& msg);
+                                     const V1_0::NanConfigRequest& msg);
     WifiStatus disableRequestInternal(uint16_t cmd_id);
     WifiStatus startPublishRequestInternal(uint16_t cmd_id,
                                            const NanPublishRequest& msg);
@@ -136,9 +147,15 @@
     WifiStatus registerEventCallback_1_2Internal(
         const sp<V1_2::IWifiNanIfaceEventCallback>& callback);
     WifiStatus enableRequest_1_2Internal(
-        uint16_t cmd_id, const NanEnableRequest& msg1,
+        uint16_t cmd_id, const V1_0::NanEnableRequest& msg1,
         const V1_2::NanConfigRequestSupplemental& msg2);
     WifiStatus configRequest_1_2Internal(
+        uint16_t cmd_id, const V1_0::NanConfigRequest& msg,
+        const V1_2::NanConfigRequestSupplemental& msg2);
+    WifiStatus enableRequest_1_4Internal(
+        uint16_t cmd_id, const NanEnableRequest& msg1,
+        const V1_2::NanConfigRequestSupplemental& msg2);
+    WifiStatus configRequest_1_4Internal(
         uint16_t cmd_id, const NanConfigRequest& msg,
         const V1_2::NanConfigRequestSupplemental& msg2);
 
diff --git a/wifi/1.4/default/wifi_sta_iface.cpp b/wifi/1.4/default/wifi_sta_iface.cpp
index 3e0127e..68c989d 100644
--- a/wifi/1.4/default/wifi_sta_iface.cpp
+++ b/wifi/1.4/default/wifi_sta_iface.cpp
@@ -113,7 +113,7 @@
 }
 
 Return<void> WifiStaIface::getValidFrequenciesForBand(
-    WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) {
+    V1_0::WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
                            &WifiStaIface::getValidFrequenciesForBandInternal,
                            hidl_status_cb, band);
@@ -266,6 +266,13 @@
                            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_};
 }
@@ -283,26 +290,7 @@
 }
 
 std::pair<WifiStatus, uint32_t> WifiStaIface::getCapabilitiesInternal() {
-    legacy_hal::wifi_error legacy_status;
-    uint32_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};
+    return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), 0};
 }
 
 std::pair<WifiStatus, StaApfPacketFilterCapabilities>
@@ -356,7 +344,7 @@
 }
 
 std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
-WifiStaIface::getValidFrequenciesForBandInternal(WifiBand band) {
+WifiStaIface::getValidFrequenciesForBandInternal(V1_0::WifiBand band) {
     static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t),
                   "Size mismatch");
     legacy_hal::wifi_error legacy_status;
@@ -640,6 +628,29 @@
     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 d8f7a01..e85e39d 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.3/IWifiStaIface.h>
+#include <android/hardware/wifi/1.4/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_3::IWifiStaIface {
+class WifiStaIface : public V1_4::IWifiStaIface {
    public:
     WifiStaIface(const std::string& ifname,
                  const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
@@ -63,7 +63,8 @@
     Return<void> getBackgroundScanCapabilities(
         getBackgroundScanCapabilities_cb hidl_status_cb) override;
     Return<void> getValidFrequenciesForBand(
-        WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) override;
+        V1_0::WifiBand band,
+        getValidFrequenciesForBand_cb hidl_status_cb) override;
     Return<void> startBackgroundScan(
         uint32_t cmd_id, const StaBackgroundScanParameters& params,
         startBackgroundScan_cb hidl_status_cb) override;
@@ -111,6 +112,8 @@
                                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.
@@ -128,7 +131,7 @@
     std::pair<WifiStatus, StaBackgroundScanCapabilities>
     getBackgroundScanCapabilitiesInternal();
     std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
-    getValidFrequenciesForBandInternal(WifiBand band);
+    getValidFrequenciesForBandInternal(V1_0::WifiBand band);
     WifiStatus startBackgroundScanInternal(
         uint32_t cmd_id, const StaBackgroundScanParameters& params);
     WifiStatus stopBackgroundScanInternal(uint32_t cmd_id);
@@ -159,6 +162,7 @@
     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/types.hal b/wifi/1.4/types.hal
index 232e26f..4f1d22e 100644
--- a/wifi/1.4/types.hal
+++ b/wifi/1.4/types.hal
@@ -17,6 +17,8 @@
 package android.hardware.wifi@1.4;
 
 import @1.0::MacAddress;
+import @1.0::NanBandIndex;
+import @1.0::NanBandSpecificConfig;
 import @1.0::Rssi;
 import @1.0::RttBw;
 import @1.0::RttConfig;
@@ -26,13 +28,47 @@
 import @1.0::RttType;
 import @1.0::TimeSpanInPs;
 import @1.0::TimeStampInUs;
+import @1.0::WifiBand;
 import @1.0::WifiChannelInfo;
+import @1.0::WifiChannelInMhz;
 import @1.0::WifiChannelWidthInMhz;
 import @1.0::WifiInformationElement;
 import @1.0::WifiRateNss;
 import @1.0::WifiRatePreamble;
 
 /**
+ * Wifi bands defined in 80211 spec.
+ */
+enum WifiBand : @1.0::WifiBand {
+    /**
+     * 6 GHz.
+     */
+    BAND_6GHZ = 8,
+    /**
+     * 5 GHz no DFS + 6 GHz.
+     */
+    BAND_5GHZ_6GHZ = 10,
+    /**
+     * 2.4 GHz + 5 GHz no DFS + 6 GHz.
+     */
+    BAND_24GHZ_5GHZ_6GHZ = 11,
+    /**
+     * 2.4 GHz + 5 GHz with DFS + 6 GHz.
+     */
+    BAND_24GHZ_5GHZ_WITH_DFS_6GHZ = 15,
+};
+
+/**
+ * The discovery bands supported by NAN.
+ */
+enum NanBandIndex : @1.0::NanBandIndex {
+    /**
+     * Index for 6 GHz band.
+     */
+    NAN_BAND_6GHZ = 2,
+};
+
+/**
  * Wifi Rate Preamble
  */
 enum WifiRatePreamble : @1.0::WifiRatePreamble {
@@ -53,6 +89,183 @@
 };
 
 /**
+ * Debug configuration parameters. Many of these allow non-standard-compliant operation and are
+ * not intended for normal operational mode.
+ */
+struct NanDebugConfig {
+    /**
+     * Specification of the lower 2 bytes of the cluster ID. The cluster ID is 50-60-9a-01-00-00 to
+     * 50-60-9a-01-FF-FF. Configuration of the bottom and top values of the range (which defaults to
+     * 0x0000 and 0xFFFF respectively).
+     * Configuration is only used if |validClusterIdVals| is set to true.
+     */
+    bool validClusterIdVals;
+
+    uint16_t clusterIdBottomRangeVal;
+
+    uint16_t clusterIdTopRangeVal;
+
+    /**
+     * NAN management interface address, if specified (|validIntfAddrVal| is true) then overrides any
+     * other configuration (specifically the default randomization configured by
+     * |NanConfigRequest.macAddressRandomizationIntervalSec|).
+     */
+    bool validIntfAddrVal;
+
+    MacAddress intfAddrVal;
+
+    /**
+     * Combination of the 24 bit Organizationally Unique ID (OUI) and the 8 bit OUI Type.
+     * Used if |validOuiVal| is set to true.
+     */
+    bool validOuiVal;
+
+    uint32_t ouiVal;
+
+    /**
+     * Force the Random Factor to the specified value for all transmitted Sync/Discovery beacons.
+     * Used if |validRandomFactorForceVal| is set to true.
+     * NAN Spec: Master Indication Attribute / Random Factor
+     */
+    bool validRandomFactorForceVal;
+
+    uint8_t randomFactorForceVal;
+
+    /**
+     * Forces the hop-count for all transmitted Sync and Discovery Beacons NO matter the real
+     * hop-count being received over the air. Used if the |validHopCountForceVal}| flag is set to
+     * true.
+     * NAN Spec: Cluster Attribute / Anchor Master Information / Hop Count to Anchor Master
+     */
+    bool validHopCountForceVal;
+
+    uint8_t hopCountForceVal;
+
+    /**
+     * Frequency in MHz to of the discovery channel in the specified band. Indexed by |NanBandIndex|.
+     * Used if the |validDiscoveryChannelVal| is set to true.
+     */
+    bool validDiscoveryChannelVal;
+
+    WifiChannelInMhz[3] discoveryChannelMhzVal;
+
+    /**
+     * Specifies whether sync/discovery beacons are transmitted in the specified band. Indexed by
+     * |NanBandIndex|. Used if the |validUseBeaconsInBandVal| is set to true.
+     */
+    bool validUseBeaconsInBandVal;
+
+    bool[3] useBeaconsInBandVal;
+
+    /**
+     * Specifies whether SDF (service discovery frames) are transmitted in the specified band. Indexed
+     * by |NanBandIndex|. Used if the |validUseSdfInBandVal| is set to true.
+     */
+    bool validUseSdfInBandVal;
+
+    bool[3] useSdfInBandVal;
+};
+
+/**
+ * Configuration parameters of NAN: used when enabling and re-configuring a NAN cluster.
+ */
+struct NanConfigRequest {
+    /**
+     * Master preference of this device.
+     * NAN Spec: Master Indication Attribute / Master Preference
+     */
+    uint8_t masterPref;
+
+    /**
+     * Controls whether or not the |IWifiNanIfaceEventCallback.eventClusterEvent| will be delivered
+     * for |NanClusterEventType.DISCOVERY_MAC_ADDRESS_CHANGED|.
+     */
+    bool disableDiscoveryAddressChangeIndication;
+
+    /**
+     * Controls whether or not the |IWifiNanIfaceEventCallback.eventClusterEvent| will be delivered
+     * for |NanClusterEventType.STARTED_CLUSTER|.
+     */
+    bool disableStartedClusterIndication;
+
+    /**
+     * Controls whether or not the |IWifiNanIfaceEventCallback.eventClusterEvent| will be delivered
+     * for |NanClusterEventType.JOINED_CLUSTER|.
+     */
+    bool disableJoinedClusterIndication;
+
+    /**
+     * Control whether publish service IDs are included in Sync/Discovery beacons.
+     * NAN Spec: Service ID List Attribute
+     */
+    bool includePublishServiceIdsInBeacon;
+
+    /**
+     * If |includePublishServiceIdsInBeacon| is true then specifies the number of publish service IDs
+     * to include in the Sync/Discovery beacons:
+     *  Value = 0: include as many service IDs as will fit into the maximum allowed beacon frame size.
+     *  Value must fit within 7 bits - i.e. <= 127.
+     */
+    uint8_t numberOfPublishServiceIdsInBeacon;
+
+    /**
+     * Control whether subscribe service IDs are included in Sync/Discovery beacons.
+     * Spec: Subscribe Service ID List Attribute
+     */
+    bool includeSubscribeServiceIdsInBeacon;
+
+    /**
+     * If |includeSubscribeServiceIdsInBeacon| is true then specifies the number of subscribe service
+     * IDs to include in the Sync/Discovery beacons:
+     *  Value = 0: include as many service IDs as will fit into the maximum allowed beacon frame size.
+     *  Value must fit within 7 bits - i.e. <= 127.
+     */
+    uint8_t numberOfSubscribeServiceIdsInBeacon;
+
+    /**
+     * Number of samples used to calculate RSSI.
+     */
+    uint16_t rssiWindowSize;
+
+    /**
+     * Specifies the interval in seconds that the NAN management interface MAC address is randomized.
+     * A value of 0 is used to disable the MAC address randomization
+     */
+    uint32_t macAddressRandomizationIntervalSec;
+
+    /**
+     * Additional configuration provided per band: indexed by |NanBandIndex|.
+     */
+    NanBandSpecificConfig[3] bandSpecificConfig;
+};
+
+/**
+ * Enable requests for NAN: start-up configuration |IWifiNanIface.enableRequest|.
+ */
+struct NanEnableRequest {
+    /**
+     * Enable operation in a specific band: indexed by |NanBandIndex|.
+     */
+    bool[3] operateInBand;
+
+    /**
+     * Specify extent of cluster by specifying the max hop count.
+     */
+    uint8_t hopCountMax;
+
+    /**
+     * Configurations of NAN cluster operation. Can also be modified at run-time using
+     * |IWifiNanIface.configRequest|.
+     */
+    NanConfigRequest configParams;
+
+    /**
+     * Non-standard configurations of NAN cluster operation - useful for debugging operations.
+     */
+    NanDebugConfig debugConfigs;
+};
+
+/**
  * RTT configuration.
  */
 struct RttConfig {
diff --git a/wifi/1.4/vts/functional/Android.bp b/wifi/1.4/vts/functional/Android.bp
index 215a810..46ac3ee 100644
--- a/wifi/1.4/vts/functional/Android.bp
+++ b/wifi/1.4/vts/functional/Android.bp
@@ -21,6 +21,8 @@
     srcs: [
         "VtsHalWifiV1_4TargetTest.cpp",
         "wifi_ap_iface_hidl_test.cpp",
+        "wifi_chip_hidl_test.cpp",
+		"wifi_nan_iface_hidl_test.cpp"
     ],
     static_libs: [
         "VtsHalWifiV1_0TargetTestUtil",
@@ -31,4 +33,5 @@
         "android.hardware.wifi@1.4",
         "libwifi-system-iface"
     ],
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/wifi/1.4/vts/functional/VtsHalWifiV1_4TargetTest.cpp b/wifi/1.4/vts/functional/VtsHalWifiV1_4TargetTest.cpp
index deac0fa..7e0f3cd 100644
--- a/wifi/1.4/vts/functional/VtsHalWifiV1_4TargetTest.cpp
+++ b/wifi/1.4/vts/functional/VtsHalWifiV1_4TargetTest.cpp
@@ -14,37 +14,8 @@
  * limitations under the License.
  */
 
-#include <android-base/logging.h>
-#include <android/hardware/wifi/1.4/IWifi.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 
-#include "wifi_hidl_test_utils.h"
-
-using ::android::hardware::wifi::V1_4::IWifi;
-
-// Test environment for Wifi HIDL HAL.
-class WifiHidlEnvironment_1_4 : public WifiHidlEnvironment {
-   public:
-    // get the test environment singleton
-    static WifiHidlEnvironment_1_4* Instance() {
-        static WifiHidlEnvironment_1_4* instance = new WifiHidlEnvironment_1_4;
-        return instance;
-    }
-
-    virtual void registerTestServices() override {
-        registerTestService<android::hardware::wifi::V1_4::IWifi>();
-    }
-
-   private:
-    WifiHidlEnvironment_1_4() {}
-};
-
-WifiHidlEnvironment_1_4* gEnv = WifiHidlEnvironment_1_4::Instance();
-
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(gEnv);
-    ::testing::InitGoogleTest(&argc, argv);
-    gEnv->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    LOG(INFO) << "Test result = " << status;
-    return status;
-}
+// TODO(b/143892896): Remove this file after wifi_hidl_test_utils.cpp is
+// updated.
+::testing::VtsHalHidlTargetTestEnvBase* gEnv = nullptr;
\ No newline at end of file
diff --git a/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp
index 68e9bbb..017ecb6 100644
--- a/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp
+++ b/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp
@@ -14,9 +14,11 @@
  * limitations under the License.
  */
 
+#include <android/hardware/wifi/1.4/IWifi.h>
 #include <android/hardware/wifi/1.4/IWifiApIface.h>
-
-#include <VtsHalHidlTargetTestBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include "wifi_hidl_call_util.h"
 #include "wifi_hidl_test_utils.h"
@@ -25,6 +27,7 @@
 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::IWifi;
 using ::android::hardware::wifi::V1_4::IWifiApIface;
 
 extern WifiHidlEnvironment* gEnv;
@@ -32,19 +35,21 @@
 /**
  * Fixture to use for all STA Iface HIDL interface tests.
  */
-class WifiApIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class WifiApIfaceHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
-        wifi_ap_iface_ = IWifiApIface::castFrom(getWifiApIface());
+        wifi_ap_iface_ =
+            IWifiApIface::castFrom(getWifiApIface(GetInstanceName()));
         ASSERT_NE(nullptr, wifi_ap_iface_.get());
     }
 
-    virtual void TearDown() override {
-        stopWifi();
-    }
+    virtual void TearDown() override { stopWifi(GetInstanceName()); }
 
    protected:
     sp<IWifiApIface> wifi_ap_iface_;
+
+   private:
+    std::string GetInstanceName() { return GetParam(); }
 };
 
 /*
@@ -52,7 +57,7 @@
  * Ensures that calls to set MAC address will return a success status
  * code.
  */
-TEST_F(WifiApIfaceHidlTest, SetMacAddress) {
+TEST_P(WifiApIfaceHidlTest, SetMacAddress) {
     const hidl_array<uint8_t, 6> kMac{{0x12, 0x22, 0x33, 0x52, 0x10, 0x41}};
     EXPECT_EQ(WifiStatusCode::SUCCESS,
               HIDL_INVOKE(wifi_ap_iface_, setMacAddress, kMac).code);
@@ -63,10 +68,16 @@
  * Ensures that calls to get factory MAC address will retrieve a non-zero MAC
  * and return a success status code.
  */
-TEST_F(WifiApIfaceHidlTest, GetFactoryMacAddress) {
+TEST_P(WifiApIfaceHidlTest, GetFactoryMacAddress) {
     std::pair<WifiStatus, hidl_array<uint8_t, 6> > status_and_mac =
         HIDL_INVOKE(wifi_ap_iface_, getFactoryMacAddress);
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_mac.first.code);
     hidl_array<uint8_t, 6> all_zero{};
     EXPECT_NE(all_zero, status_and_mac.second);
 }
+
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance, WifiApIfaceHidlTest,
+    testing::ValuesIn(
+        android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
+    android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/wifi/1.4/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_chip_hidl_test.cpp
new file mode 100644
index 0000000..8ca5214
--- /dev/null
+++ b/wifi/1.4/vts/functional/wifi_chip_hidl_test.cpp
@@ -0,0 +1,135 @@
+/*
+ * 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 <VtsHalHidlTargetCallbackBase.h>
+#include <android-base/logging.h>
+
+#undef NAN  // NAN is defined in bionic/libc/include/math.h:38
+
+#include <android/hardware/wifi/1.4/IWifi.h>
+#include <android/hardware/wifi/1.4/IWifiChip.h>
+#include <android/hardware/wifi/1.4/IWifiChipEventCallback.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include "wifi_hidl_call_util.h"
+#include "wifi_hidl_test_utils.h"
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::wifi::V1_0::IfaceType;
+using ::android::hardware::wifi::V1_0::WifiDebugRingBufferStatus;
+using ::android::hardware::wifi::V1_0::WifiStatus;
+using ::android::hardware::wifi::V1_0::WifiStatusCode;
+using ::android::hardware::wifi::V1_4::IWifiChip;
+using ::android::hardware::wifi::V1_4::IWifiChipEventCallback;
+
+/**
+ * Fixture to use for all Wifi chip HIDL interface tests.
+ */
+class WifiChipHidlTest : public ::testing::TestWithParam<std::string> {
+   public:
+    virtual void SetUp() override {
+        wifi_chip_ = IWifiChip::castFrom(getWifiChip(GetInstanceName()));
+        ASSERT_NE(nullptr, wifi_chip_.get());
+    }
+
+    virtual void TearDown() override { stopWifi(GetInstanceName()); }
+
+    // A simple test implementation of WifiChipEventCallback.
+    class WifiChipEventCallback
+        : public ::testing::VtsHalHidlTargetCallbackBase<WifiChipHidlTest>,
+          public IWifiChipEventCallback {
+       public:
+        WifiChipEventCallback(){};
+
+        virtual ~WifiChipEventCallback() = default;
+
+        Return<void> onChipReconfigured(uint32_t modeId __unused) {
+            return Void();
+        };
+
+        Return<void> onChipReconfigureFailure(
+            const WifiStatus& status __unused) {
+            return Void();
+        };
+
+        Return<void> onIfaceAdded(IfaceType type __unused,
+                                  const hidl_string& name __unused) {
+            return Void();
+        };
+
+        Return<void> onIfaceRemoved(IfaceType type __unused,
+                                    const hidl_string& name __unused) {
+            return Void();
+        };
+
+        Return<void> onDebugRingBufferDataAvailable(
+            const WifiDebugRingBufferStatus& status __unused,
+            const hidl_vec<uint8_t>& data __unused) {
+            return Void();
+        };
+
+        Return<void> onDebugErrorAlert(int32_t errorCode __unused,
+                                       const hidl_vec<uint8_t>& debugData
+                                           __unused) {
+            return Void();
+        };
+
+        Return<void> onRadioModeChange(
+            const hidl_vec<::android::hardware::wifi::V1_2::
+                               IWifiChipEventCallback::RadioModeInfo>&
+                radioModeInfos __unused) {
+            return Void();
+        };
+
+        Return<void> onRadioModeChange_1_4(
+            const hidl_vec<RadioModeInfo>& radioModeInfos __unused) {
+            return Void();
+        };
+    };
+
+   protected:
+    sp<IWifiChip> wifi_chip_;
+
+   private:
+    std::string GetInstanceName() { return GetParam(); }
+};
+
+/*
+ * registerEventCallback_1_4
+ * This test case tests the registerEventCallback_1_4() API which registers
+ * a call back function with the hal implementation
+ *
+ * Note: it is not feasible to test the invocation of the call back function
+ * since event is triggered internally in the HAL implementation, and can not be
+ * triggered from the test case
+ */
+TEST_P(WifiChipHidlTest, registerEventCallback_1_4) {
+    sp<WifiChipEventCallback> wifiChipEventCallback =
+        new WifiChipEventCallback();
+    const auto& status = HIDL_INVOKE(wifi_chip_, registerEventCallback_1_4,
+                                     wifiChipEventCallback);
+
+    if (status.code != WifiStatusCode::SUCCESS) {
+        EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, status.code);
+        return;
+    }
+}
diff --git a/wifi/1.4/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_nan_iface_hidl_test.cpp
new file mode 100644
index 0000000..245e906
--- /dev/null
+++ b/wifi/1.4/vts/functional/wifi_nan_iface_hidl_test.cpp
@@ -0,0 +1,544 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Nanache 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.2/IWifiNanIfaceEventCallback.h>
+#include <android/hardware/wifi/1.4/IWifi.h>
+#include <android/hardware/wifi/1.4/IWifiNanIface.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+
+#include "wifi_hidl_call_util.h"
+#include "wifi_hidl_test_utils.h"
+
+using namespace ::android::hardware::wifi::V1_0;
+using namespace ::android::hardware::wifi::V1_2;
+using namespace ::android::hardware::wifi::V1_4;
+
+using ::android::sp;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+#define TIMEOUT_PERIOD 10
+
+android::sp<android::hardware::wifi::V1_4::IWifiNanIface> getWifiNanIface_1_4(
+    const std::string& instance_name) {
+    return android::hardware::wifi::V1_4::IWifiNanIface::castFrom(
+        getWifiNanIface(instance_name));
+}
+
+/**
+ * Fixture to use for all NAN Iface HIDL interface tests.
+ */
+class WifiNanIfaceHidlTest : public ::testing::TestWithParam<std::string> {
+   public:
+    virtual void SetUp() override {
+        iwifiNanIface = getWifiNanIface_1_4(GetInstanceName());
+        ASSERT_NE(nullptr, iwifiNanIface.get());
+        ASSERT_EQ(WifiStatusCode::SUCCESS,
+                  HIDL_INVOKE(iwifiNanIface, registerEventCallback_1_2,
+                              new WifiNanIfaceEventCallback(*this))
+                      .code);
+    }
+
+    virtual void TearDown() override { stopWifi(GetInstanceName()); }
+
+    /* Used as a mechanism to inform the test about data/event callback */
+    inline void notify() {
+        std::unique_lock<std::mutex> lock(mtx_);
+        count_++;
+        cv_.notify_one();
+    }
+
+    enum CallbackType {
+        INVALID = -2,
+        ANY_CALLBACK = -1,
+
+        NOTIFY_CAPABILITIES_RESPONSE = 0,
+        NOTIFY_ENABLE_RESPONSE,
+        NOTIFY_CONFIG_RESPONSE,
+        NOTIFY_DISABLE_RESPONSE,
+        NOTIFY_START_PUBLISH_RESPONSE,
+        NOTIFY_STOP_PUBLISH_RESPONSE,
+        NOTIFY_START_SUBSCRIBE_RESPONSE,
+        NOTIFY_STOP_SUBSCRIBE_RESPONSE,
+        NOTIFY_TRANSMIT_FOLLOWUP_RESPONSE,
+        NOTIFY_CREATE_DATA_INTERFACE_RESPONSE,
+        NOTIFY_DELETE_DATA_INTERFACE_RESPONSE,
+        NOTIFY_INITIATE_DATA_PATH_RESPONSE,
+        NOTIFY_RESPOND_TO_DATA_PATH_INDICATION_RESPONSE,
+        NOTIFY_TERMINATE_DATA_PATH_RESPONSE,
+
+        EVENT_CLUSTER_EVENT,
+        EVENT_DISABLED,
+        EVENT_PUBLISH_TERMINATED,
+        EVENT_SUBSCRIBE_TERMINATED,
+        EVENT_MATCH,
+        EVENT_MATCH_EXPIRED,
+        EVENT_FOLLOWUP_RECEIVED,
+        EVENT_TRANSMIT_FOLLOWUP,
+        EVENT_DATA_PATH_REQUEST,
+        EVENT_DATA_PATH_CONFIRM,
+        EVENT_DATA_PATH_TERMINATED,
+        EVENT_DATA_PATH_CONFIRM_1_2,
+        EVENT_DATA_PATH_SCHEDULE_UPDATE
+    };
+
+    /* Test code calls this function to wait for data/event callback */
+    /* Must set callbackType = INVALID before call this function */
+    inline std::cv_status wait(CallbackType waitForCallbackType) {
+        std::unique_lock<std::mutex> lock(mtx_);
+
+        EXPECT_NE(INVALID, waitForCallbackType);  // can't ASSERT in a
+                                                  // non-void-returning method
+
+        std::cv_status status = std::cv_status::no_timeout;
+        auto now = std::chrono::system_clock::now();
+        while (count_ == 0) {
+            status = cv_.wait_until(lock,
+                                    now + std::chrono::seconds(TIMEOUT_PERIOD));
+            if (status == std::cv_status::timeout) return status;
+            if (waitForCallbackType != ANY_CALLBACK &&
+                callbackType != INVALID &&
+                callbackType != waitForCallbackType) {
+                count_--;
+            }
+        }
+        count_--;
+        return status;
+    }
+
+    class WifiNanIfaceEventCallback
+        : public ::android::hardware::wifi::V1_2::IWifiNanIfaceEventCallback {
+        WifiNanIfaceHidlTest& parent_;
+
+       public:
+        WifiNanIfaceEventCallback(WifiNanIfaceHidlTest& parent)
+            : parent_(parent){};
+
+        virtual ~WifiNanIfaceEventCallback() = default;
+
+        Return<void> notifyCapabilitiesResponse(
+            uint16_t id, const WifiNanStatus& status,
+            const NanCapabilities& capabilities) override {
+            parent_.callbackType = NOTIFY_CAPABILITIES_RESPONSE;
+
+            parent_.id = id;
+            parent_.status = status;
+            parent_.capabilities = capabilities;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> notifyEnableResponse(
+            uint16_t id, const WifiNanStatus& status) override {
+            parent_.callbackType = NOTIFY_ENABLE_RESPONSE;
+
+            parent_.id = id;
+            parent_.status = status;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> notifyConfigResponse(
+            uint16_t id, const WifiNanStatus& status) override {
+            parent_.callbackType = NOTIFY_CONFIG_RESPONSE;
+
+            parent_.id = id;
+            parent_.status = status;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> notifyDisableResponse(
+            uint16_t id, const WifiNanStatus& status) override {
+            parent_.callbackType = NOTIFY_DISABLE_RESPONSE;
+
+            parent_.id = id;
+            parent_.status = status;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> notifyStartPublishResponse(uint16_t id,
+                                                const WifiNanStatus& status,
+                                                uint8_t sessionId) override {
+            parent_.callbackType = NOTIFY_START_PUBLISH_RESPONSE;
+
+            parent_.id = id;
+            parent_.status = status;
+            parent_.sessionId = sessionId;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> notifyStopPublishResponse(
+            uint16_t id, const WifiNanStatus& status) override {
+            parent_.callbackType = NOTIFY_STOP_PUBLISH_RESPONSE;
+
+            parent_.id = id;
+            parent_.status = status;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> notifyStartSubscribeResponse(uint16_t id,
+                                                  const WifiNanStatus& status,
+                                                  uint8_t sessionId) override {
+            parent_.callbackType = NOTIFY_START_SUBSCRIBE_RESPONSE;
+
+            parent_.id = id;
+            parent_.status = status;
+            parent_.sessionId = sessionId;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> notifyStopSubscribeResponse(
+            uint16_t id, const WifiNanStatus& status) override {
+            parent_.callbackType = NOTIFY_STOP_SUBSCRIBE_RESPONSE;
+
+            parent_.id = id;
+            parent_.status = status;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> notifyTransmitFollowupResponse(
+            uint16_t id, const WifiNanStatus& status) override {
+            parent_.callbackType = NOTIFY_TRANSMIT_FOLLOWUP_RESPONSE;
+
+            parent_.id = id;
+            parent_.status = status;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> notifyCreateDataInterfaceResponse(
+            uint16_t id, const WifiNanStatus& status) override {
+            parent_.callbackType = NOTIFY_CREATE_DATA_INTERFACE_RESPONSE;
+
+            parent_.id = id;
+            parent_.status = status;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> notifyDeleteDataInterfaceResponse(
+            uint16_t id, const WifiNanStatus& status) override {
+            parent_.callbackType = NOTIFY_DELETE_DATA_INTERFACE_RESPONSE;
+
+            parent_.id = id;
+            parent_.status = status;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> notifyInitiateDataPathResponse(
+            uint16_t id, const WifiNanStatus& status,
+            uint32_t ndpInstanceId) override {
+            parent_.callbackType = NOTIFY_INITIATE_DATA_PATH_RESPONSE;
+
+            parent_.id = id;
+            parent_.status = status;
+            parent_.ndpInstanceId = ndpInstanceId;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> notifyRespondToDataPathIndicationResponse(
+            uint16_t id, const WifiNanStatus& status) override {
+            parent_.callbackType =
+                NOTIFY_RESPOND_TO_DATA_PATH_INDICATION_RESPONSE;
+
+            parent_.id = id;
+            parent_.status = status;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> notifyTerminateDataPathResponse(
+            uint16_t id, const WifiNanStatus& status) override {
+            parent_.callbackType = NOTIFY_TERMINATE_DATA_PATH_RESPONSE;
+
+            parent_.id = id;
+            parent_.status = status;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> eventClusterEvent(
+            const NanClusterEventInd& event) override {
+            parent_.callbackType = EVENT_CLUSTER_EVENT;
+
+            parent_.nanClusterEventInd = event;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> eventDisabled(const WifiNanStatus& status) override {
+            parent_.callbackType = EVENT_DISABLED;
+
+            parent_.status = status;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> eventPublishTerminated(
+            uint8_t sessionId, const WifiNanStatus& status) override {
+            parent_.callbackType = EVENT_PUBLISH_TERMINATED;
+
+            parent_.sessionId = sessionId;
+            parent_.status = status;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> eventSubscribeTerminated(
+            uint8_t sessionId, const WifiNanStatus& status) override {
+            parent_.callbackType = EVENT_SUBSCRIBE_TERMINATED;
+
+            parent_.sessionId = sessionId;
+            parent_.status = status;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> eventMatch(const NanMatchInd& event) override {
+            parent_.callbackType = EVENT_MATCH;
+
+            parent_.nanMatchInd = event;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> eventMatchExpired(uint8_t discoverySessionId,
+                                       uint32_t peerId) override {
+            parent_.callbackType = EVENT_MATCH_EXPIRED;
+
+            parent_.sessionId = discoverySessionId;
+            parent_.peerId = peerId;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> eventFollowupReceived(
+            const NanFollowupReceivedInd& event) override {
+            parent_.callbackType = EVENT_FOLLOWUP_RECEIVED;
+
+            parent_.nanFollowupReceivedInd = event;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> eventTransmitFollowup(
+            uint16_t id, const WifiNanStatus& status) override {
+            parent_.callbackType = EVENT_TRANSMIT_FOLLOWUP;
+
+            parent_.id = id;
+            parent_.status = status;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> eventDataPathRequest(
+            const NanDataPathRequestInd& event) override {
+            parent_.callbackType = EVENT_DATA_PATH_REQUEST;
+
+            parent_.nanDataPathRequestInd = event;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> eventDataPathConfirm(
+            const ::android::hardware::wifi::V1_0::NanDataPathConfirmInd& event)
+            override {
+            parent_.callbackType = EVENT_DATA_PATH_CONFIRM;
+
+            parent_.nanDataPathConfirmInd = event;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> eventDataPathTerminated(uint32_t ndpInstanceId) override {
+            parent_.callbackType = EVENT_DATA_PATH_TERMINATED;
+
+            parent_.ndpInstanceId = ndpInstanceId;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> eventDataPathConfirm_1_2(
+            const ::android::hardware::wifi::V1_2::NanDataPathConfirmInd& event)
+            override {
+            parent_.callbackType = EVENT_DATA_PATH_CONFIRM_1_2;
+
+            parent_.nanDataPathConfirmInd_1_2 = event;
+
+            parent_.notify();
+            return Void();
+        }
+
+        Return<void> eventDataPathScheduleUpdate(
+            const NanDataPathScheduleUpdateInd& event) override {
+            parent_.callbackType = EVENT_DATA_PATH_SCHEDULE_UPDATE;
+
+            parent_.nanDataPathScheduleUpdateInd = event;
+
+            parent_.notify();
+            return Void();
+        }
+    };
+
+   private:
+    // synchronization objects
+    std::mutex mtx_;
+    std::condition_variable cv_;
+    int count_;
+
+   protected:
+    android::sp<::android::hardware::wifi::V1_4::IWifiNanIface> iwifiNanIface;
+
+    // Data from IWifiNanIfaceEventCallback callbacks: this is the collection of
+    // all arguments to all callbacks. They are set by the callback
+    // (notifications or events) and can be retrieved by tests.
+    CallbackType callbackType;
+    uint16_t id;
+    WifiNanStatus status;
+    NanCapabilities capabilities;
+    uint8_t sessionId;
+    uint32_t ndpInstanceId;
+    NanClusterEventInd nanClusterEventInd;
+    NanMatchInd nanMatchInd;
+    uint32_t peerId;
+    NanFollowupReceivedInd nanFollowupReceivedInd;
+    NanDataPathRequestInd nanDataPathRequestInd;
+    ::android::hardware::wifi::V1_0::NanDataPathConfirmInd
+        nanDataPathConfirmInd;
+    ::android::hardware::wifi::V1_2::NanDataPathConfirmInd
+        nanDataPathConfirmInd_1_2;
+    NanDataPathScheduleUpdateInd nanDataPathScheduleUpdateInd;
+
+    std::string GetInstanceName() { return GetParam(); }
+};
+
+/*
+ * Create:
+ * Ensures that an instance of the IWifiNanIface proxy object is
+ * successfully created.
+ */
+TEST_P(WifiNanIfaceHidlTest, Create) {
+    // The creation of a proxy object is tested as part of SetUp method.
+}
+
+/*
+ * enableRequest_1_4InvalidArgs: validate that fails with invalid arguments
+ */
+TEST_P(WifiNanIfaceHidlTest, enableRequest_1_4InvalidArgs) {
+    uint16_t inputCmdId = 10;
+    callbackType = INVALID;
+    ::android::hardware::wifi::V1_4::NanEnableRequest nanEnableRequest = {};
+    NanConfigRequestSupplemental nanConfigRequestSupp = {};
+    ASSERT_EQ(WifiStatusCode::SUCCESS,
+              HIDL_INVOKE(iwifiNanIface, enableRequest_1_4, inputCmdId,
+                          nanEnableRequest, nanConfigRequestSupp)
+                  .code);
+    // wait for a callback
+    ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_ENABLE_RESPONSE));
+    ASSERT_EQ(NOTIFY_ENABLE_RESPONSE, callbackType);
+    ASSERT_EQ(id, inputCmdId);
+    ASSERT_EQ(status.status, NanStatusType::INVALID_ARGS);
+}
+
+/*
+ * enableRequest_1_4ShimInvalidArgs: validate that fails with invalid arguments
+ * to the shim
+ */
+TEST_P(WifiNanIfaceHidlTest, enableRequest_1_4ShimInvalidArgs) {
+    uint16_t inputCmdId = 10;
+    ::android::hardware::wifi::V1_4::NanEnableRequest nanEnableRequest = {};
+    nanEnableRequest.configParams.numberOfPublishServiceIdsInBeacon =
+        128;  // must be <= 127
+    NanConfigRequestSupplemental nanConfigRequestSupp = {};
+    ASSERT_EQ(WifiStatusCode::ERROR_INVALID_ARGS,
+              HIDL_INVOKE(iwifiNanIface, enableRequest_1_4, inputCmdId,
+                          nanEnableRequest, nanConfigRequestSupp)
+                  .code);
+}
+
+/*
+ * configRequest_1_4InvalidArgs: validate that fails with invalid arguments
+ */
+TEST_P(WifiNanIfaceHidlTest, configRequest_1_4InvalidArgs) {
+    uint16_t inputCmdId = 10;
+    callbackType = INVALID;
+    ::android::hardware::wifi::V1_4::NanConfigRequest nanConfigRequest = {};
+    NanConfigRequestSupplemental nanConfigRequestSupp = {};
+    ASSERT_EQ(WifiStatusCode::SUCCESS,
+              HIDL_INVOKE(iwifiNanIface, configRequest_1_4, inputCmdId,
+                          nanConfigRequest, nanConfigRequestSupp)
+                  .code);
+    // wait for a callback
+    ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_CONFIG_RESPONSE));
+    ASSERT_EQ(NOTIFY_CONFIG_RESPONSE, callbackType);
+    ASSERT_EQ(id, inputCmdId);
+    ASSERT_EQ(status.status, NanStatusType::INVALID_ARGS);
+}
+
+/*
+ * configRequest_1_4ShimInvalidArgs: validate that fails with invalid arguments
+ * to the shim
+ */
+TEST_P(WifiNanIfaceHidlTest, configRequest_1_4ShimInvalidArgs) {
+    uint16_t inputCmdId = 10;
+    ::android::hardware::wifi::V1_4::NanConfigRequest nanConfigRequest = {};
+    nanConfigRequest.numberOfPublishServiceIdsInBeacon = 128;  // must be <= 127
+    NanConfigRequestSupplemental nanConfigRequestSupp = {};
+    ASSERT_EQ(WifiStatusCode::ERROR_INVALID_ARGS,
+              HIDL_INVOKE(iwifiNanIface, configRequest_1_4, inputCmdId,
+                          nanConfigRequest, nanConfigRequestSupp)
+                  .code);
+}
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
new file mode 100644
index 0000000..ec4b2c9
--- /dev/null
+++ b/wifi/1.4/vts/functional/wifi_sta_iface_hidl_test.cpp
@@ -0,0 +1,62 @@
+/*
+ * 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);
+}
diff --git a/wifi/hostapd/1.2/Android.bp b/wifi/hostapd/1.2/Android.bp
new file mode 100644
index 0000000..3dcad71
--- /dev/null
+++ b/wifi/hostapd/1.2/Android.bp
@@ -0,0 +1,20 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.wifi.hostapd@1.2",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IHostapd.hal",
+    ],
+    interfaces: [
+        "android.hardware.wifi.hostapd@1.0",
+        "android.hardware.wifi.hostapd@1.1",
+        "android.hardware.wifi.supplicant@1.0",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
diff --git a/wifi/hostapd/1.2/IHostapd.hal b/wifi/hostapd/1.2/IHostapd.hal
new file mode 100644
index 0000000..31ade13
--- /dev/null
+++ b/wifi/hostapd/1.2/IHostapd.hal
@@ -0,0 +1,42 @@
+/*
+ * 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.hostapd@1.2;
+
+import @1.1::IHostapd;
+import HostapdStatus;
+import MacAddress;
+import Ieee80211ReasonCode;
+
+/**
+ * Top-level object for managing SoftAPs.
+ */
+interface IHostapd extends @1.1::IHostapd {
+    /**
+     * force one of the hotspot clients disconnect..
+     *
+     * @param ifaceName Name of the interface.
+     * @param clientAddress Mac Address of the hotspot client.
+     * @param reasonCode One of disconnect reason code which defined by 802.11.
+     * @return status Status of the operation.
+     *         Possible status codes:
+     *         |HostapdStatusCode.SUCCESS|,
+     *         |HostapdStatusCode.FAILURE_IFACE_UNKNOWN|
+     *         |HostapdStatusCode.FAILURE_CLIENT_UNKNOWN|
+     */
+    forceClientDisconnect(string ifaceName, MacAddress clientAddress,
+        Ieee80211ReasonCode reasonCode) generates (HostapdStatus status);
+};
diff --git a/wifi/hostapd/1.2/types.hal b/wifi/hostapd/1.2/types.hal
new file mode 100644
index 0000000..06e890b
--- /dev/null
+++ b/wifi/hostapd/1.2/types.hal
@@ -0,0 +1,55 @@
+/*
+ * 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.hostapd@1.2;
+
+import @1.0::HostapdStatusCode;
+
+/**
+ * Enum values indicating the status of any hostapd operation.
+ */
+enum HostapdStatusCode : @1.0::HostapdStatusCode {
+    /**
+     * Failure because unknown the client.
+     */
+    FAILURE_CLIENT_UNKNOWN,
+};
+
+/**
+ * Enum values indicating the reason code for disconnect packet.
+ * Reason codes (IEEE Std 802.11-2016, 9.4.1.7, Table 9-45).
+ */
+enum Ieee80211ReasonCode : uint16_t {
+    WLAN_REASON_UNSPECIFIED = 1,
+    WLAN_REASON_PREV_AUTH_NOT_VALID = 2,
+    WLAN_REASON_DISASSOC_AP_BUSY = 5,
+};
+
+typedef uint8_t[6] MacAddress;
+
+/**
+ * Generic structure to return the status of any hostapd operation.
+ */
+struct HostapdStatus {
+    HostapdStatusCode code;
+
+    /**
+     * A vendor-specific error message to provide more information beyond the
+     * status code.
+     * This must be used for debugging purposes only.
+     */
+    string debugMessage;
+};
diff --git a/wifi/hostapd/1.2/vts/OWNERS b/wifi/hostapd/1.2/vts/OWNERS
new file mode 100644
index 0000000..8bfb148
--- /dev/null
+++ b/wifi/hostapd/1.2/vts/OWNERS
@@ -0,0 +1,2 @@
+rpius@google.com
+etancohen@google.com
diff --git a/wifi/hostapd/1.2/vts/functional/Android.bp b/wifi/hostapd/1.2/vts/functional/Android.bp
new file mode 100644
index 0000000..50cfdee
--- /dev/null
+++ b/wifi/hostapd/1.2/vts/functional/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_test {
+    name: "VtsHalWifiHostapdV1_2TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "VtsHalWifiHostapdV1_2TargetTest.cpp",
+        "hostapd_hidl_test.cpp",
+    ],
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
+        "VtsHalWifiHostapdV1_0TargetTestUtil",
+        "android.hardware.wifi.hostapd@1.0",
+        "android.hardware.wifi.hostapd@1.1",
+	"android.hardware.wifi.hostapd@1.2",
+        "android.hardware.wifi@1.0",
+        "libgmock",
+        "libwifi-system",
+        "libwifi-system-iface",
+    ],
+    test_suites: ["general-tests", "vts-core"],
+}
+
diff --git a/vibrator/1.4/types.hal b/wifi/hostapd/1.2/vts/functional/VtsHalWifiHostapdV1_2TargetTest.cpp
similarity index 76%
copy from vibrator/1.4/types.hal
copy to wifi/hostapd/1.2/vts/functional/VtsHalWifiHostapdV1_2TargetTest.cpp
index acc49b1..7e0f3cd 100644
--- a/vibrator/1.4/types.hal
+++ b/wifi/hostapd/1.2/vts/functional/VtsHalWifiHostapdV1_2TargetTest.cpp
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-package android.hardware.vibrator@1.4;
+#include <VtsHalHidlTargetTestEnvBase.h>
 
-enum Capabilities : uint32_t {
-    ON_COMPLETION_CALLBACK = 1 << 0,
-    PERFORM_COMPLETION_CALLBACK = 1 << 1,
-};
+// TODO(b/143892896): Remove this file after wifi_hidl_test_utils.cpp is
+// updated.
+::testing::VtsHalHidlTargetTestEnvBase* gEnv = nullptr;
\ No newline at end of file
diff --git a/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
new file mode 100644
index 0000000..0d37221
--- /dev/null
+++ b/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
@@ -0,0 +1,140 @@
+/*
+ * 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 <android-base/logging.h>
+#include <cutils/properties.h>
+
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include <android/hardware/wifi/1.0/IWifi.h>
+#include <android/hardware/wifi/hostapd/1.2/IHostapd.h>
+
+#include "hostapd_hidl_call_util.h"
+#include "hostapd_hidl_test_utils.h"
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::wifi::hostapd::V1_2::HostapdStatusCode;
+using ::android::hardware::wifi::hostapd::V1_2::Ieee80211ReasonCode;
+using ::android::hardware::wifi::hostapd::V1_2::IHostapd;
+using ::android::hardware::wifi::V1_0::IWifi;
+
+namespace {
+constexpr unsigned char kNwSsid[] = {'t', 'e', 's', 't', '1',
+                                     '2', '3', '4', '5'};
+constexpr int kIfaceChannel = 6;
+constexpr uint8_t kTestZeroMacAddr[] = {[0 ... 5] = 0x0};
+constexpr Ieee80211ReasonCode kTestDisconnectReasonCode =
+    Ieee80211ReasonCode::WLAN_REASON_UNSPECIFIED;
+}  // namespace
+
+class HostapdHidlTest
+    : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
+   public:
+    virtual void SetUp() override {
+        wifi_instance_name_ = std::get<0>(GetParam());
+        hostapd_instance_name_ = std::get<1>(GetParam());
+        stopSupplicantIfNeeded(wifi_instance_name_);
+        startHostapdAndWaitForHidlService(wifi_instance_name_,
+                                          hostapd_instance_name_);
+        hostapd_ = IHostapd::getService(hostapd_instance_name_);
+        ASSERT_NE(hostapd_.get(), nullptr);
+    }
+
+    virtual void TearDown() override { stopHostapd(wifi_instance_name_); }
+
+   protected:
+    std::string getPrimaryWlanIfaceName() {
+        std::array<char, PROPERTY_VALUE_MAX> buffer;
+        auto res = property_get("ro.vendor.wifi.sap.interface", buffer.data(),
+                                nullptr);
+        if (res > 0) return buffer.data();
+        property_get("wifi.interface", buffer.data(), "wlan0");
+        return buffer.data();
+    }
+
+    IHostapd::IfaceParams getIfaceParamsWithoutAcs() {
+        ::android::hardware::wifi::hostapd::V1_0::IHostapd::IfaceParams
+            iface_params;
+        IHostapd::IfaceParams iface_params_1_1;
+
+        iface_params.ifaceName = getPrimaryWlanIfaceName();
+        iface_params.hwModeParams.enable80211N = true;
+        iface_params.hwModeParams.enable80211AC = false;
+        iface_params.channelParams.enableAcs = false;
+        iface_params.channelParams.acsShouldExcludeDfs = false;
+        iface_params.channelParams.channel = kIfaceChannel;
+        iface_params.channelParams.band = IHostapd::Band::BAND_2_4_GHZ;
+        iface_params_1_1.V1_0 = iface_params;
+        return iface_params_1_1;
+    }
+
+    IHostapd::NetworkParams getOpenNwParams() {
+        IHostapd::NetworkParams nw_params;
+        nw_params.ssid =
+            std::vector<uint8_t>(kNwSsid, kNwSsid + sizeof(kNwSsid));
+        nw_params.isHidden = false;
+        nw_params.encryptionType = IHostapd::EncryptionType::NONE;
+        return nw_params;
+    }
+
+    // IHostapd object used for all tests in this fixture.
+    sp<IHostapd> hostapd_;
+    std::string wifi_instance_name_;
+    std::string hostapd_instance_name_;
+};
+
+/**
+ * forceClientDisconnect should return FAILURE_IFACE_UNKNOWN
+ * when hotspot interface doesn't init..
+ */
+TEST_P(HostapdHidlTest, DisconnectClientWhenIfaceNotAvailable) {
+    auto status =
+        HIDL_INVOKE(hostapd_, forceClientDisconnect, getPrimaryWlanIfaceName(),
+                    kTestZeroMacAddr, kTestDisconnectReasonCode);
+    EXPECT_EQ(HostapdStatusCode::FAILURE_IFACE_UNKNOWN, status.code);
+}
+
+/**
+ * forceClientDisconnect should return FAILURE_CLIENT_UNKNOWN
+ * when hotspot interface available.
+ */
+TEST_P(HostapdHidlTest, DisconnectClientWhenIfacAvailable) {
+    auto status_1_0 =
+        HIDL_INVOKE(hostapd_, addAccessPoint_1_1, getIfaceParamsWithoutAcs(),
+                    getOpenNwParams());
+    EXPECT_EQ(
+        android::hardware::wifi::hostapd::V1_0::HostapdStatusCode::SUCCESS,
+        status_1_0.code);
+
+    auto status_1_2 =
+        HIDL_INVOKE(hostapd_, forceClientDisconnect, getPrimaryWlanIfaceName(),
+                    kTestZeroMacAddr, kTestDisconnectReasonCode);
+    EXPECT_EQ(HostapdStatusCode::FAILURE_CLIENT_UNKNOWN, status_1_2.code);
+}
+
+INSTANTIATE_TEST_CASE_P(
+    PerInstance, HostapdHidlTest,
+    testing::Combine(
+        testing::ValuesIn(
+            android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+            android::hardware::wifi::hostapd::V1_2::IHostapd::descriptor))),
+    android::hardware::PrintInstanceTupleNameToString<>);
diff --git a/wifi/supplicant/1.0/vts/functional/Android.bp b/wifi/supplicant/1.0/vts/functional/Android.bp
index ba79738..15525bb 100644
--- a/wifi/supplicant/1.0/vts/functional/Android.bp
+++ b/wifi/supplicant/1.0/vts/functional/Android.bp
@@ -51,7 +51,7 @@
         "libwifi-system",
         "libwifi-system-iface",
     ],
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "vts-core"],
 }
 
 cc_test {
@@ -71,4 +71,5 @@
         "libwifi-system",
         "libwifi-system-iface",
     ],
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/wifi/supplicant/1.0/vts/functional/VtsHalWifiSupplicantV1_0TargetTest.cpp b/wifi/supplicant/1.0/vts/functional/VtsHalWifiSupplicantV1_0TargetTest.cpp
index 6ca0546..f582cc1 100644
--- a/wifi/supplicant/1.0/vts/functional/VtsHalWifiSupplicantV1_0TargetTest.cpp
+++ b/wifi/supplicant/1.0/vts/functional/VtsHalWifiSupplicantV1_0TargetTest.cpp
@@ -14,40 +14,8 @@
  * limitations under the License.
  */
 
-#include <android-base/logging.h>
-
 #include "supplicant_hidl_test_utils.h"
-#include "wifi_hidl_test_utils.h"
 
-class WifiSupplicantHidlEnvironment_1_0 : public WifiSupplicantHidlEnvironment {
-   public:
-    // get the test environment singleton
-    static WifiSupplicantHidlEnvironment_1_0* Instance() {
-        static WifiSupplicantHidlEnvironment_1_0* instance =
-            new WifiSupplicantHidlEnvironment_1_0;
-        return instance;
-    }
-    virtual void registerTestServices() override {
-        registerTestService<::android::hardware::wifi::V1_0::IWifi>();
-        registerTestService<
-            ::android::hardware::wifi::supplicant::V1_0::ISupplicant>();
-    }
-
-   private:
-    WifiSupplicantHidlEnvironment_1_0() {}
-};
-
-WifiSupplicantHidlEnvironment* gEnv =
-    WifiSupplicantHidlEnvironment_1_0::Instance();
-
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(gEnv);
-    ::testing::InitGoogleTest(&argc, argv);
-    gEnv->init(&argc, argv);
-    int status = gEnv->initFromOptions(argc, argv);
-    if (status == 0) {
-        int status = RUN_ALL_TESTS();
-        LOG(INFO) << "Test result = " << status;
-    }
-    return status;
-}
+// TODO(b/143892896): Remove this file after wifi_hidl_test_utils.cpp is
+// updated.
+WifiSupplicantHidlEnvironment* gEnv = nullptr;
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_call_util.h b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_call_util.h
index 1c0fcec..3fa6f9d 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_call_util.h
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_call_util.h
@@ -25,8 +25,6 @@
 #include <type_traits>
 #include <utility>
 
-#include <VtsHalHidlTargetTestBase.h>
-
 namespace {
 namespace detail {
 template <typename>
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test.cpp
index 436b88b..4f25465 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test.cpp
@@ -16,35 +16,47 @@
 
 #include <android-base/logging.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-
+#include <VtsCoreUtil.h>
+#include <android/hardware/wifi/1.0/IWifi.h>
 #include <android/hardware/wifi/supplicant/1.0/ISupplicant.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include "supplicant_hidl_test_utils.h"
 
 using ::android::sp;
 using ::android::hardware::hidl_vec;
+using ::android::hardware::wifi::supplicant::V1_0::IfaceType;
 using ::android::hardware::wifi::supplicant::V1_0::ISupplicant;
 using ::android::hardware::wifi::supplicant::V1_0::ISupplicantIface;
 using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
 using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
-using ::android::hardware::wifi::supplicant::V1_0::IfaceType;
+using ::android::hardware::wifi::V1_0::IWifi;
 
-extern WifiSupplicantHidlEnvironment* gEnv;
-
-class SupplicantHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class SupplicantHidlTest
+    : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
    public:
     virtual void SetUp() override {
-        startSupplicantAndWaitForHidlService();
-        supplicant_ = getSupplicant();
+        wifi_instance_name_ = std::get<0>(GetParam());
+        supplicant_instance_name_ = std::get<1>(GetParam());
+        stopSupplicant(wifi_instance_name_);
+        startSupplicantAndWaitForHidlService(wifi_instance_name_,
+                                             supplicant_instance_name_);
+        isP2pOn_ =
+            testing::deviceSupportsFeature("android.hardware.wifi.direct");
+        supplicant_ = getSupplicant(supplicant_instance_name_, isP2pOn_);
         ASSERT_NE(supplicant_.get(), nullptr);
     }
 
-    virtual void TearDown() override { stopSupplicant(); }
+    virtual void TearDown() override { stopSupplicant(wifi_instance_name_); }
 
    protected:
     // ISupplicant object used for all tests in this fixture.
     sp<ISupplicant> supplicant_;
+    bool isP2pOn_ = false;
+    std::string wifi_instance_name_;
+    std::string supplicant_instance_name_;
 };
 
 /*
@@ -52,16 +64,19 @@
  * Ensures that an instance of the ISupplicant proxy object is
  * successfully created.
  */
-TEST(SupplicantHidlTestNoFixture, Create) {
-    startSupplicantAndWaitForHidlService();
-    EXPECT_NE(nullptr, getSupplicant().get());
-    stopSupplicant();
+TEST_P(SupplicantHidlTest, Create) {
+    // Stop the proxy object created in setup.
+    stopSupplicant(wifi_instance_name_);
+    startSupplicantAndWaitForHidlService(wifi_instance_name_,
+                                         supplicant_instance_name_);
+    EXPECT_NE(nullptr,
+              getSupplicant(supplicant_instance_name_, isP2pOn_).get());
 }
 
 /*
  * ListInterfaces
  */
-TEST_F(SupplicantHidlTest, ListInterfaces) {
+TEST_P(SupplicantHidlTest, ListInterfaces) {
     std::vector<ISupplicant::IfaceInfo> ifaces;
     supplicant_->listInterfaces(
         [&](const SupplicantStatus& status,
@@ -74,7 +89,7 @@
               std::find_if(ifaces.begin(), ifaces.end(), [](const auto& iface) {
                   return iface.type == IfaceType::STA;
               }));
-    if (gEnv->isP2pOn) {
+    if (isP2pOn_) {
         EXPECT_NE(
             ifaces.end(),
             std::find_if(ifaces.begin(), ifaces.end(), [](const auto& iface) {
@@ -86,7 +101,7 @@
 /*
  * GetInterface
  */
-TEST_F(SupplicantHidlTest, GetInterface) {
+TEST_P(SupplicantHidlTest, GetInterface) {
     std::vector<ISupplicant::IfaceInfo> ifaces;
     supplicant_->listInterfaces(
         [&](const SupplicantStatus& status,
@@ -107,7 +122,7 @@
 /*
  * SetDebugParams
  */
-TEST_F(SupplicantHidlTest, SetDebugParams) {
+TEST_P(SupplicantHidlTest, SetDebugParams) {
     bool show_timestamp = true;
     bool show_keys = true;
     ISupplicant::DebugLevel level = ISupplicant::DebugLevel::EXCESSIVE;
@@ -124,7 +139,7 @@
 /*
  * GetDebugLevel
  */
-TEST_F(SupplicantHidlTest, GetDebugLevel) {
+TEST_P(SupplicantHidlTest, GetDebugLevel) {
     bool show_timestamp = true;
     bool show_keys = true;
     ISupplicant::DebugLevel level = ISupplicant::DebugLevel::EXCESSIVE;
@@ -142,7 +157,7 @@
 /*
  * IsDebugShowTimestampEnabled
  */
-TEST_F(SupplicantHidlTest, IsDebugShowTimestampEnabled) {
+TEST_P(SupplicantHidlTest, IsDebugShowTimestampEnabled) {
     bool show_timestamp = true;
     bool show_keys = true;
     ISupplicant::DebugLevel level = ISupplicant::DebugLevel::EXCESSIVE;
@@ -160,7 +175,7 @@
 /*
  * IsDebugShowKeysEnabled
  */
-TEST_F(SupplicantHidlTest, IsDebugShowKeysEnabled) {
+TEST_P(SupplicantHidlTest, IsDebugShowKeysEnabled) {
     bool show_timestamp = true;
     bool show_keys = true;
     ISupplicant::DebugLevel level = ISupplicant::DebugLevel::EXCESSIVE;
@@ -178,15 +193,24 @@
 /*
  * SetConcurrenyPriority
  */
-TEST_F(SupplicantHidlTest, SetConcurrencyPriority) {
+TEST_P(SupplicantHidlTest, SetConcurrencyPriority) {
     supplicant_->setConcurrencyPriority(
         IfaceType::STA, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
         });
-    if (gEnv->isP2pOn) {
+    if (isP2pOn_) {
         supplicant_->setConcurrencyPriority(
             IfaceType::P2P, [](const SupplicantStatus& status) {
                 EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
             });
     }
 }
+
+INSTANTIATE_TEST_CASE_P(
+    PerInstance, SupplicantHidlTest,
+    testing::Combine(
+        testing::ValuesIn(
+            android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+            ISupplicant::descriptor))),
+    android::hardware::PrintInstanceTupleNameToString<>);
\ No newline at end of file
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
index 7bd04dc..d47e42f 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
@@ -56,8 +56,8 @@
 
 // Helper function to initialize the driver and firmware to STA mode
 // using the vendor HAL HIDL interface.
-void initilializeDriverAndFirmware() {
-    sp<IWifiChip> wifi_chip = getWifiChip();
+void initilializeDriverAndFirmware(const std::string& wifi_instance_name) {
+    sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
     ChipModeId mode_id;
     EXPECT_TRUE(configureChipToSupportIfaceType(
         wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::STA, &mode_id));
@@ -65,7 +65,9 @@
 
 // Helper function to deinitialize the driver and firmware
 // using the vendor HAL HIDL interface.
-void deInitilializeDriverAndFirmware() { stopWifi(); }
+void deInitilializeDriverAndFirmware(const std::string& wifi_instance_name) {
+    stopWifi(wifi_instance_name);
+}
 
 // Helper function to find any iface of the desired type exposed.
 bool findIfaceOfType(sp<ISupplicant> supplicant, IfaceType desired_type,
@@ -154,28 +156,38 @@
     std::condition_variable condition_;
 };
 
-void stopSupplicant() {
+void stopSupplicant() { stopSupplicant(""); }
+
+void stopSupplicant(const std::string& wifi_instance_name) {
     SupplicantManager supplicant_manager;
 
     ASSERT_TRUE(supplicant_manager.StopSupplicant());
-    deInitilializeDriverAndFirmware();
+    deInitilializeDriverAndFirmware(wifi_instance_name);
     ASSERT_FALSE(supplicant_manager.IsSupplicantRunning());
 }
 
+// TODO(b/143892896): Remove old APIs after all supplicant tests are updated.
 void startSupplicantAndWaitForHidlService() {
-    initilializeDriverAndFirmware();
+    startSupplicantAndWaitForHidlService("",
+                                         gEnv->getServiceName<ISupplicant>());
+}
+
+void startSupplicantAndWaitForHidlService(
+    const std::string& wifi_instance_name,
+    const std::string& supplicant_instance_name) {
+    initilializeDriverAndFirmware(wifi_instance_name);
 
     android::sp<ServiceNotificationListener> notification_listener =
         new ServiceNotificationListener();
-    string service_name = gEnv->getServiceName<ISupplicant>();
     ASSERT_TRUE(notification_listener->registerForHidlServiceNotifications(
-        service_name));
+        supplicant_instance_name));
 
     SupplicantManager supplicant_manager;
     ASSERT_TRUE(supplicant_manager.StartSupplicant());
     ASSERT_TRUE(supplicant_manager.IsSupplicantRunning());
 
-    ASSERT_TRUE(notification_listener->waitForHidlService(500, service_name));
+    ASSERT_TRUE(notification_listener->waitForHidlService(
+        500, supplicant_instance_name));
 }
 
 bool is_1_1(const sp<ISupplicant>& supplicant) {
@@ -218,6 +230,7 @@
         });
 }
 
+// TODO(b/143892896): Remove old APIs after all supplicant tests are updated.
 sp<ISupplicant> getSupplicant() {
     sp<ISupplicant> supplicant =
         ::testing::VtsHalHidlTargetTestBase::getService<ISupplicant>(
@@ -232,8 +245,28 @@
     return supplicant;
 }
 
+sp<ISupplicant> getSupplicant(const std::string& supplicant_instance_name,
+                              bool isP2pOn) {
+    sp<ISupplicant> supplicant =
+        ISupplicant::getService(supplicant_instance_name);
+    // For 1.1 supplicant, we need to add interfaces at initialization.
+    if (is_1_1(supplicant)) {
+        addSupplicantStaIface_1_1(supplicant);
+        if (isP2pOn) {
+            addSupplicantP2pIface_1_1(supplicant);
+        }
+    }
+    return supplicant;
+}
+
+// TODO(b/143892896): Remove old APIs after all supplicant tests are updated.
 sp<ISupplicantStaIface> getSupplicantStaIface() {
     sp<ISupplicant> supplicant = getSupplicant();
+    return getSupplicantStaIface(supplicant);
+}
+
+sp<ISupplicantStaIface> getSupplicantStaIface(
+    const sp<ISupplicant>& supplicant) {
     if (!supplicant.get()) {
         return nullptr;
     }
@@ -257,8 +290,14 @@
     return sta_iface;
 }
 
+// TODO(b/143892896): Remove old APIs after all supplicant tests are updated.
 sp<ISupplicantStaNetwork> createSupplicantStaNetwork() {
-    sp<ISupplicantStaIface> sta_iface = getSupplicantStaIface();
+    return createSupplicantStaNetwork(getSupplicant());
+}
+
+sp<ISupplicantStaNetwork> createSupplicantStaNetwork(
+    const sp<ISupplicant>& supplicant) {
+    sp<ISupplicantStaIface> sta_iface = getSupplicantStaIface(supplicant);
     if (!sta_iface.get()) {
         return nullptr;
     }
@@ -278,8 +317,13 @@
     return sta_network;
 }
 
+// TODO(b/143892896): Remove old APIs after all supplicant tests are updated.
 sp<ISupplicantP2pIface> getSupplicantP2pIface() {
-    sp<ISupplicant> supplicant = getSupplicant();
+    return getSupplicantP2pIface(getSupplicant());
+}
+
+sp<ISupplicantP2pIface> getSupplicantP2pIface(
+    const sp<ISupplicant>& supplicant) {
     if (!supplicant.get()) {
         return nullptr;
     }
@@ -303,8 +347,12 @@
     return p2p_iface;
 }
 
+// TODO(b/143892896): Remove old APIs after all supplicant tests are updated.
 bool turnOnExcessiveLogging() {
-    sp<ISupplicant> supplicant = getSupplicant();
+    return turnOnExcessiveLogging(getSupplicant());
+}
+
+bool turnOnExcessiveLogging(const sp<ISupplicant>& supplicant) {
     if (!supplicant.get()) {
         return false;
     }
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h
index 21a1ae6..40ad695 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h
@@ -25,21 +25,47 @@
 
 #include <getopt.h>
 
-#include <VtsHalHidlTargetTestEnvBase.h>
+#include "wifi_hidl_test_utils.h"
 
 // Used to stop the android wifi framework before every test.
 void stopWifiFramework();
+void stopWifiFramework(const std::string& wifi_instance_name);
 void startWifiFramework();
+void startWifiFramework(const std::string& wifi_instance_name);
+
 void stopSupplicant();
+void stopSupplicant(const std::string& wifi_instance_name);
 // Used to configure the chip, driver and start wpa_supplicant before every
 // test.
-void startSupplicantAndWaitForHidlService();
+void startSupplicantAndWaitForHidlService(
+    const std::string& wifi_instance_name,
+    const std::string& supplicant_instance_name);
 
 // Helper functions to obtain references to the various HIDL interface objects.
 // Note: We only have a single instance of each of these objects currently.
 // These helper functions should be modified to return vectors if we support
 // multiple instances.
 android::sp<android::hardware::wifi::supplicant::V1_0::ISupplicant>
+getSupplicant(const std::string& supplicant_instance_name, bool isP2pOn);
+android::sp<android::hardware::wifi::supplicant::V1_0::ISupplicantStaIface>
+getSupplicantStaIface(
+    const android::sp<android::hardware::wifi::supplicant::V1_0::ISupplicant>&
+        supplicant);
+android::sp<android::hardware::wifi::supplicant::V1_0::ISupplicantStaNetwork>
+createSupplicantStaNetwork(
+    const android::sp<android::hardware::wifi::supplicant::V1_0::ISupplicant>&
+        supplicant);
+android::sp<android::hardware::wifi::supplicant::V1_0::ISupplicantP2pIface>
+getSupplicantP2pIface(
+    const android::sp<android::hardware::wifi::supplicant::V1_0::ISupplicant>&
+        supplicant);
+bool turnOnExcessiveLogging(
+    const android::sp<android::hardware::wifi::supplicant::V1_0::ISupplicant>&
+        supplicant);
+
+// TODO(b/143892896): Remove old APIs after all supplicant tests are updated.
+void startSupplicantAndWaitForHidlService();
+android::sp<android::hardware::wifi::supplicant::V1_0::ISupplicant>
 getSupplicant();
 android::sp<android::hardware::wifi::supplicant::V1_0::ISupplicantStaIface>
 getSupplicantStaIface();
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
index 0181f7b..8d6f38d 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
@@ -15,9 +15,12 @@
  */
 
 #include <android-base/logging.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-
+#include <VtsCoreUtil.h>
+#include <android/hardware/wifi/1.0/IWifi.h>
 #include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pIface.h>
 
 #include "supplicant_hidl_call_util.h"
@@ -30,11 +33,13 @@
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::hardware::wifi::supplicant::V1_0::IfaceType;
+using ::android::hardware::wifi::supplicant::V1_0::ISupplicant;
 using ::android::hardware::wifi::supplicant::V1_0::ISupplicantP2pIface;
 using ::android::hardware::wifi::supplicant::V1_0::ISupplicantP2pIfaceCallback;
 using ::android::hardware::wifi::supplicant::V1_0::SupplicantNetworkId;
 using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
 using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
+using ::android::hardware::wifi::V1_0::IWifi;
 
 namespace {
 constexpr uint8_t kTestSsidPostfix[] = {'t', 'e', 's', 't'};
@@ -66,26 +71,38 @@
 constexpr SupplicantNetworkId kTestNetworkId = 5;
 }  // namespace
 
-class SupplicantP2pIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class SupplicantP2pIfaceHidlTest
+    : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
    public:
     virtual void SetUp() override {
-        startSupplicantAndWaitForHidlService();
-        EXPECT_TRUE(turnOnExcessiveLogging());
-        p2p_iface_ = getSupplicantP2pIface();
+        wifi_instance_name_ = std::get<0>(GetParam());
+        supplicant_instance_name_ = std::get<1>(GetParam());
+        stopSupplicant(wifi_instance_name_);
+        startSupplicantAndWaitForHidlService(wifi_instance_name_,
+                                             supplicant_instance_name_);
+        isP2pOn_ =
+            testing::deviceSupportsFeature("android.hardware.wifi.direct");
+        supplicant_ = getSupplicant(supplicant_instance_name_, isP2pOn_);
+        EXPECT_TRUE(turnOnExcessiveLogging(supplicant_));
+        p2p_iface_ = getSupplicantP2pIface(supplicant_);
         ASSERT_NE(p2p_iface_.get(), nullptr);
 
         memcpy(mac_addr_.data(), kTestMacAddr, mac_addr_.size());
         memcpy(peer_mac_addr_.data(), kTestPeerMacAddr, peer_mac_addr_.size());
     }
 
-    virtual void TearDown() override { stopSupplicant(); }
+    virtual void TearDown() override { stopSupplicant(wifi_instance_name_); }
 
    protected:
+    bool isP2pOn_ = false;
+    sp<ISupplicant> supplicant_;
     // ISupplicantP2pIface object used for all tests in this fixture.
     sp<ISupplicantP2pIface> p2p_iface_;
     // MAC address to use for various tests.
     std::array<uint8_t, 6> mac_addr_;
     std::array<uint8_t, 6> peer_mac_addr_;
+    std::string wifi_instance_name_;
+    std::string supplicant_instance_name_;
 };
 
 class IfaceCallback : public ISupplicantP2pIfaceCallback {
@@ -177,16 +194,20 @@
  * Ensures that an instance of the ISupplicantP2pIface proxy object is
  * successfully created.
  */
-TEST(SupplicantP2pIfaceHidlTestNoFixture, Create) {
-    startSupplicantAndWaitForHidlService();
-    EXPECT_NE(nullptr, getSupplicantP2pIface().get());
-    stopSupplicant();
+TEST_P(SupplicantP2pIfaceHidlTest, Create) {
+    stopSupplicant(wifi_instance_name_);
+    startSupplicantAndWaitForHidlService(wifi_instance_name_,
+                                         supplicant_instance_name_);
+    sp<ISupplicantP2pIface> p2p_iface = getSupplicantP2pIface(
+        getSupplicant(supplicant_instance_name_, isP2pOn_));
+
+    EXPECT_NE(nullptr, p2p_iface.get());
 }
 
 /*
  * RegisterCallback
  */
-TEST_F(SupplicantP2pIfaceHidlTest, RegisterCallback) {
+TEST_P(SupplicantP2pIfaceHidlTest, RegisterCallback) {
     p2p_iface_->registerCallback(
         new IfaceCallback(), [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -196,7 +217,7 @@
 /*
  * GetName
  */
-TEST_F(SupplicantP2pIfaceHidlTest, GetName) {
+TEST_P(SupplicantP2pIfaceHidlTest, GetName) {
     const auto& status_and_interface_name = HIDL_INVOKE(p2p_iface_, getName);
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
               status_and_interface_name.first.code);
@@ -206,7 +227,7 @@
 /*
  * GetType
  */
-TEST_F(SupplicantP2pIfaceHidlTest, GetType) {
+TEST_P(SupplicantP2pIfaceHidlTest, GetType) {
     const auto& status_and_interface_type = HIDL_INVOKE(p2p_iface_, getType);
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
               status_and_interface_type.first.code);
@@ -216,7 +237,7 @@
 /*
  * GetDeviceAddress
  */
-TEST_F(SupplicantP2pIfaceHidlTest, GetDeviceAddress) {
+TEST_P(SupplicantP2pIfaceHidlTest, GetDeviceAddress) {
     p2p_iface_->getDeviceAddress(
         [](const SupplicantStatus& status,
            const hidl_array<uint8_t, 6>& /* mac_addr */) {
@@ -227,7 +248,7 @@
 /*
  * SetSsidPostfix
  */
-TEST_F(SupplicantP2pIfaceHidlTest, SetSsidPostfix) {
+TEST_P(SupplicantP2pIfaceHidlTest, SetSsidPostfix) {
     std::vector<uint8_t> ssid(kTestSsidPostfix,
                               kTestSsidPostfix + sizeof(kTestSsidPostfix));
     p2p_iface_->setSsidPostfix(ssid, [](const SupplicantStatus& status) {
@@ -238,7 +259,7 @@
 /*
  * Find
  */
-TEST_F(SupplicantP2pIfaceHidlTest, Find) {
+TEST_P(SupplicantP2pIfaceHidlTest, Find) {
     p2p_iface_->find(kTestFindTimeout, [](const SupplicantStatus& status) {
         EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
     });
@@ -247,7 +268,7 @@
 /*
  * StopFind
  */
-TEST_F(SupplicantP2pIfaceHidlTest, StopFind) {
+TEST_P(SupplicantP2pIfaceHidlTest, StopFind) {
     p2p_iface_->find(kTestFindTimeout, [](const SupplicantStatus& status) {
         EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
     });
@@ -260,7 +281,7 @@
 /*
  * Flush
  */
-TEST_F(SupplicantP2pIfaceHidlTest, Flush) {
+TEST_P(SupplicantP2pIfaceHidlTest, Flush) {
     p2p_iface_->flush([](const SupplicantStatus& status) {
         EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
     });
@@ -269,7 +290,7 @@
 /*
  * Connect
  */
-TEST_F(SupplicantP2pIfaceHidlTest, Connect) {
+TEST_P(SupplicantP2pIfaceHidlTest, Connect) {
     p2p_iface_->connect(
         mac_addr_, ISupplicantP2pIface::WpsProvisionMethod::PBC,
         kTestConnectPin, false, false, kTestConnectGoIntent,
@@ -282,7 +303,7 @@
 /*
  * CancelConnect
  */
-TEST_F(SupplicantP2pIfaceHidlTest, CancelConnect) {
+TEST_P(SupplicantP2pIfaceHidlTest, CancelConnect) {
     p2p_iface_->connect(
         mac_addr_, ISupplicantP2pIface::WpsProvisionMethod::PBC,
         kTestConnectPin, false, false, kTestConnectGoIntent,
@@ -299,7 +320,7 @@
 /*
  * ProvisionDiscovery
  */
-TEST_F(SupplicantP2pIfaceHidlTest, ProvisionDiscovery) {
+TEST_P(SupplicantP2pIfaceHidlTest, ProvisionDiscovery) {
     p2p_iface_->provisionDiscovery(
         mac_addr_, ISupplicantP2pIface::WpsProvisionMethod::PBC,
         [](const SupplicantStatus& status) {
@@ -311,7 +332,7 @@
 /*
  * AddGroup
  */
-TEST_F(SupplicantP2pIfaceHidlTest, AddGroup) {
+TEST_P(SupplicantP2pIfaceHidlTest, AddGroup) {
     p2p_iface_->addGroup(false, kTestNetworkId,
                          [](const SupplicantStatus& /* status */) {
                              // TODO: Figure out the initialization sequence for
@@ -324,7 +345,7 @@
 /*
  * RemoveGroup
  */
-TEST_F(SupplicantP2pIfaceHidlTest, RemoveGroup) {
+TEST_P(SupplicantP2pIfaceHidlTest, RemoveGroup) {
     // This is not going to work with fake values.
     EXPECT_NE(SupplicantStatusCode::SUCCESS,
               HIDL_INVOKE(p2p_iface_, removeGroup, kTestGroupIfName).code);
@@ -333,7 +354,7 @@
 /*
  * Reject
  */
-TEST_F(SupplicantP2pIfaceHidlTest, Reject) {
+TEST_P(SupplicantP2pIfaceHidlTest, Reject) {
     p2p_iface_->reject(mac_addr_, [](const SupplicantStatus& status) {
         // This is not going to work with fake values.
         EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code);
@@ -343,7 +364,7 @@
 /*
  * Invite
  */
-TEST_F(SupplicantP2pIfaceHidlTest, Invite) {
+TEST_P(SupplicantP2pIfaceHidlTest, Invite) {
     p2p_iface_->invite(kTestGroupIfName, mac_addr_, peer_mac_addr_,
                        [](const SupplicantStatus& status) {
                            // This is not going to work with fake values.
@@ -355,7 +376,7 @@
 /*
  * Reinvoke
  */
-TEST_F(SupplicantP2pIfaceHidlTest, Reinvoke) {
+TEST_P(SupplicantP2pIfaceHidlTest, Reinvoke) {
     p2p_iface_->reinvoke(
         kTestNetworkId, mac_addr_, [](const SupplicantStatus& status) {
             // This is not going to work with fake values.
@@ -367,7 +388,7 @@
 /*
  * ConfigureExtListen
  */
-TEST_F(SupplicantP2pIfaceHidlTest, ConfigureExtListen) {
+TEST_P(SupplicantP2pIfaceHidlTest, ConfigureExtListen) {
     p2p_iface_->configureExtListen(kTestExtListenPeriod, kTestExtListenInterval,
                                    [](const SupplicantStatus& status) {
                                        EXPECT_EQ(SupplicantStatusCode::SUCCESS,
@@ -378,7 +399,7 @@
 /*
  * SetListenChannel
  */
-TEST_F(SupplicantP2pIfaceHidlTest, SetListenChannel) {
+TEST_P(SupplicantP2pIfaceHidlTest, SetListenChannel) {
     p2p_iface_->setListenChannel(
         kTestChannel, kTestOperatingClass, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -388,7 +409,7 @@
 /*
  * SetDisallowedFrequencies
  */
-TEST_F(SupplicantP2pIfaceHidlTest, SetDisallowedFrequencies) {
+TEST_P(SupplicantP2pIfaceHidlTest, SetDisallowedFrequencies) {
     std::vector<ISupplicantP2pIface::FreqRange> ranges = {
         {kTestFreqRange[0], kTestFreqRange[1]}};
     p2p_iface_->setDisallowedFrequencies(
@@ -400,7 +421,7 @@
 /*
  * GetSsid
  */
-TEST_F(SupplicantP2pIfaceHidlTest, GetSsid) {
+TEST_P(SupplicantP2pIfaceHidlTest, GetSsid) {
     std::array<uint8_t, 6> mac_addr;
     memcpy(mac_addr.data(), kTestMacAddr, mac_addr.size());
     p2p_iface_->getSsid(mac_addr, [](const SupplicantStatus& status,
@@ -413,7 +434,7 @@
 /*
  * GetGroupCapability
  */
-TEST_F(SupplicantP2pIfaceHidlTest, GetGroupCapability) {
+TEST_P(SupplicantP2pIfaceHidlTest, GetGroupCapability) {
     std::array<uint8_t, 6> mac_addr;
     memcpy(mac_addr.data(), kTestMacAddr, mac_addr.size());
     p2p_iface_->getGroupCapability(
@@ -426,7 +447,7 @@
 /*
  * FlushServices
  */
-TEST_F(SupplicantP2pIfaceHidlTest, FlushServices) {
+TEST_P(SupplicantP2pIfaceHidlTest, FlushServices) {
     p2p_iface_->flushServices([](const SupplicantStatus& status) {
         EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
     });
@@ -435,7 +456,7 @@
 /*
  * SetMiracastMode
  */
-TEST_F(SupplicantP2pIfaceHidlTest, SetMiracastMode) {
+TEST_P(SupplicantP2pIfaceHidlTest, SetMiracastMode) {
     p2p_iface_->setMiracastMode(ISupplicantP2pIface::MiracastMode::DISABLED,
                                 [](const SupplicantStatus& status) {
                                     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
@@ -456,7 +477,7 @@
 /*
  * SetGroupIdle
  */
-TEST_F(SupplicantP2pIfaceHidlTest, SetGroupIdle) {
+TEST_P(SupplicantP2pIfaceHidlTest, SetGroupIdle) {
     // This is not going to work with fake values.
     EXPECT_NE(SupplicantStatusCode::SUCCESS,
               HIDL_INVOKE(p2p_iface_, setGroupIdle, kTestGroupIfName,
@@ -467,7 +488,7 @@
 /*
  * SetPowerSave
  */
-TEST_F(SupplicantP2pIfaceHidlTest, SetPowerSave) {
+TEST_P(SupplicantP2pIfaceHidlTest, SetPowerSave) {
     // This is not going to work with fake values.
     EXPECT_NE(
         SupplicantStatusCode::SUCCESS,
@@ -481,7 +502,7 @@
 /*
  * SetWpsDeviceName
  */
-TEST_F(SupplicantP2pIfaceHidlTest, SetWpsDeviceName) {
+TEST_P(SupplicantP2pIfaceHidlTest, SetWpsDeviceName) {
     EXPECT_EQ(
         SupplicantStatusCode::SUCCESS,
         HIDL_INVOKE(p2p_iface_, setWpsDeviceName, kTestWpsDeviceName).code);
@@ -490,7 +511,7 @@
 /*
  * SetWpsDeviceType
  */
-TEST_F(SupplicantP2pIfaceHidlTest, SetWpsDeviceType) {
+TEST_P(SupplicantP2pIfaceHidlTest, SetWpsDeviceType) {
     EXPECT_EQ(
         SupplicantStatusCode::SUCCESS,
         HIDL_INVOKE(p2p_iface_, setWpsDeviceType, kTestWpsDeviceType).code);
@@ -499,7 +520,7 @@
 /*
  * SetWpsManufacturer
  */
-TEST_F(SupplicantP2pIfaceHidlTest, SetWpsManufacturer) {
+TEST_P(SupplicantP2pIfaceHidlTest, SetWpsManufacturer) {
     EXPECT_EQ(
         SupplicantStatusCode::SUCCESS,
         HIDL_INVOKE(p2p_iface_, setWpsManufacturer, kTestWpsManufacturer).code);
@@ -508,7 +529,7 @@
 /*
  * SetWpsModelName
  */
-TEST_F(SupplicantP2pIfaceHidlTest, SetWpsModelName) {
+TEST_P(SupplicantP2pIfaceHidlTest, SetWpsModelName) {
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
               HIDL_INVOKE(p2p_iface_, setWpsModelName, kTestWpsModelName).code);
 }
@@ -516,7 +537,7 @@
 /*
  * SetWpsModelNumber
  */
-TEST_F(SupplicantP2pIfaceHidlTest, SetWpsModelNumber) {
+TEST_P(SupplicantP2pIfaceHidlTest, SetWpsModelNumber) {
     EXPECT_EQ(
         SupplicantStatusCode::SUCCESS,
         HIDL_INVOKE(p2p_iface_, setWpsModelNumber, kTestWpsModelNumber).code);
@@ -525,7 +546,7 @@
 /*
  * SetWpsSerialNumber
  */
-TEST_F(SupplicantP2pIfaceHidlTest, SetWpsSerialNumber) {
+TEST_P(SupplicantP2pIfaceHidlTest, SetWpsSerialNumber) {
     EXPECT_EQ(
         SupplicantStatusCode::SUCCESS,
         HIDL_INVOKE(p2p_iface_, setWpsSerialNumber, kTestWpsSerialNumber).code);
@@ -534,7 +555,7 @@
 /*
  * SetWpsConfigMethods
  */
-TEST_F(SupplicantP2pIfaceHidlTest, SetWpsConfigMethods) {
+TEST_P(SupplicantP2pIfaceHidlTest, SetWpsConfigMethods) {
     EXPECT_EQ(
         SupplicantStatusCode::SUCCESS,
         HIDL_INVOKE(p2p_iface_, setWpsConfigMethods, kTestWpsConfigMethods)
@@ -548,7 +569,7 @@
  * This also tests that removeBonjourSerive() returns error when there is no
  * existing bonjour service with the same query data.
  */
-TEST_F(SupplicantP2pIfaceHidlTest, AddAndRemoveBonjourService) {
+TEST_P(SupplicantP2pIfaceHidlTest, AddAndRemoveBonjourService) {
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
               HIDL_INVOKE(
                   p2p_iface_, addBonjourService,
@@ -584,7 +605,7 @@
  * This also tests that removeUpnpService() returns error when there is no
  * exsiting upnp service with the same service name.
  */
-TEST_F(SupplicantP2pIfaceHidlTest, AddAndRemoveUpnpService) {
+TEST_P(SupplicantP2pIfaceHidlTest, AddAndRemoveUpnpService) {
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
               HIDL_INVOKE(p2p_iface_, addUpnpService, 0 /* version */,
                           kTestUpnpServiceName)
@@ -604,7 +625,7 @@
 /*
  * EnableWfd
  */
-TEST_F(SupplicantP2pIfaceHidlTest, EnableWfd) {
+TEST_P(SupplicantP2pIfaceHidlTest, EnableWfd) {
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
               HIDL_INVOKE(p2p_iface_, enableWfd, true).code);
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
@@ -614,8 +635,17 @@
 /*
  * SetWfdDeviceInfo
  */
-TEST_F(SupplicantP2pIfaceHidlTest, SetWfdDeviceInfo) {
+TEST_P(SupplicantP2pIfaceHidlTest, SetWfdDeviceInfo) {
     EXPECT_EQ(
         SupplicantStatusCode::SUCCESS,
         HIDL_INVOKE(p2p_iface_, setWfdDeviceInfo, kTestWfdDeviceInfo).code);
 }
+
+INSTANTIATE_TEST_CASE_P(
+    PerInstance, SupplicantP2pIfaceHidlTest,
+    testing::Combine(
+        testing::ValuesIn(
+            android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+            ISupplicant::descriptor))),
+    android::hardware::PrintInstanceTupleNameToString<>);
\ No newline at end of file
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp
index ec102d5..089b3cd 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -15,9 +15,12 @@
  */
 
 #include <android-base/logging.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-
+#include <VtsCoreUtil.h>
+#include <android/hardware/wifi/1.0/IWifi.h>
 #include <android/hardware/wifi/supplicant/1.0/ISupplicantStaIface.h>
 
 #include "supplicant_hidl_call_util.h"
@@ -30,12 +33,14 @@
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::hardware::wifi::supplicant::V1_0::IfaceType;
+using ::android::hardware::wifi::supplicant::V1_0::ISupplicant;
 using ::android::hardware::wifi::supplicant::V1_0::ISupplicantStaIface;
 using ::android::hardware::wifi::supplicant::V1_0::ISupplicantStaIfaceCallback;
 using ::android::hardware::wifi::supplicant::V1_0::ISupplicantStaNetwork;
 using ::android::hardware::wifi::supplicant::V1_0::SupplicantNetworkId;
 using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
 using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
+using ::android::hardware::wifi::V1_0::IWifi;
 
 namespace {
 constexpr uint8_t kTestMacAddr[] = {0x56, 0x67, 0x67, 0xf4, 0x56, 0x92};
@@ -61,24 +66,36 @@
 constexpr uint16_t kTestWpsConfigMethods = 0xffff;
 }  // namespace
 
-class SupplicantStaIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class SupplicantStaIfaceHidlTest
+    : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
    public:
     virtual void SetUp() override {
-        startSupplicantAndWaitForHidlService();
-        EXPECT_TRUE(turnOnExcessiveLogging());
-        sta_iface_ = getSupplicantStaIface();
+        wifi_instance_name_ = std::get<0>(GetParam());
+        supplicant_instance_name_ = std::get<1>(GetParam());
+        stopSupplicant(wifi_instance_name_);
+        startSupplicantAndWaitForHidlService(wifi_instance_name_,
+                                             supplicant_instance_name_);
+        isP2pOn_ =
+            testing::deviceSupportsFeature("android.hardware.wifi.direct");
+        supplicant_ = getSupplicant(supplicant_instance_name_, isP2pOn_);
+        EXPECT_TRUE(turnOnExcessiveLogging(supplicant_));
+        sta_iface_ = getSupplicantStaIface(supplicant_);
         ASSERT_NE(sta_iface_.get(), nullptr);
 
         memcpy(mac_addr_.data(), kTestMacAddr, mac_addr_.size());
     }
 
-    virtual void TearDown() override { stopSupplicant(); }
+    virtual void TearDown() override { stopSupplicant(wifi_instance_name_); }
 
    protected:
+    bool isP2pOn_ = false;
+    sp<ISupplicant> supplicant_;
     // ISupplicantStaIface object used for all tests in this fixture.
     sp<ISupplicantStaIface> sta_iface_;
     // MAC address to use for various tests.
     std::array<uint8_t, 6> mac_addr_;
+    std::string wifi_instance_name_;
+    std::string supplicant_instance_name_;
 };
 
 class IfaceCallback : public ISupplicantStaIfaceCallback {
@@ -159,16 +176,19 @@
  * Ensures that an instance of the ISupplicantStaIface proxy object is
  * successfully created.
  */
-TEST(SupplicantStaIfaceHidlTestNoFixture, Create) {
-    startSupplicantAndWaitForHidlService();
-    EXPECT_NE(nullptr, getSupplicantStaIface().get());
-    stopSupplicant();
+TEST_P(SupplicantStaIfaceHidlTest, Create) {
+    stopSupplicant(wifi_instance_name_);
+    startSupplicantAndWaitForHidlService(wifi_instance_name_,
+                                         supplicant_instance_name_);
+    EXPECT_NE(nullptr, getSupplicantStaIface(
+                           getSupplicant(supplicant_instance_name_, isP2pOn_))
+                           .get());
 }
 
 /*
  * RegisterCallback
  */
-TEST_F(SupplicantStaIfaceHidlTest, RegisterCallback) {
+TEST_P(SupplicantStaIfaceHidlTest, RegisterCallback) {
     sta_iface_->registerCallback(
         new IfaceCallback(), [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -178,7 +198,7 @@
 /*
  * GetName
  */
-TEST_F(SupplicantStaIfaceHidlTest, GetName) {
+TEST_P(SupplicantStaIfaceHidlTest, GetName) {
     const auto& status_and_interface_name = HIDL_INVOKE(sta_iface_, getName);
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
               status_and_interface_name.first.code);
@@ -188,7 +208,7 @@
 /*
  * GetType
  */
-TEST_F(SupplicantStaIfaceHidlTest, GetType) {
+TEST_P(SupplicantStaIfaceHidlTest, GetType) {
     const auto& status_and_interface_type = HIDL_INVOKE(sta_iface_, getType);
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
               status_and_interface_type.first.code);
@@ -198,14 +218,15 @@
 /*
  * listNetworks.
  */
-TEST_F(SupplicantStaIfaceHidlTest, listNetworks) {
+TEST_P(SupplicantStaIfaceHidlTest, listNetworks) {
     sta_iface_->listNetworks([](const SupplicantStatus& status,
                                 const hidl_vec<SupplicantNetworkId>& ids) {
         EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
         EXPECT_EQ(0u, ids.size());
     });
 
-    sp<ISupplicantStaNetwork> sta_network = createSupplicantStaNetwork();
+    sp<ISupplicantStaNetwork> sta_network =
+        createSupplicantStaNetwork(supplicant_);
     EXPECT_NE(nullptr, sta_network.get());
 
     sta_iface_->listNetworks([](const SupplicantStatus& status,
@@ -218,7 +239,7 @@
 /*
  * Reassociate.
  */
-TEST_F(SupplicantStaIfaceHidlTest, Reassociate) {
+TEST_P(SupplicantStaIfaceHidlTest, Reassociate) {
     sta_iface_->reassociate([](const SupplicantStatus& status) {
         EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
     });
@@ -227,7 +248,7 @@
 /*
  * Reconnect.
  */
-TEST_F(SupplicantStaIfaceHidlTest, Reconnect) {
+TEST_P(SupplicantStaIfaceHidlTest, Reconnect) {
     sta_iface_->reconnect([](const SupplicantStatus& status) {
         EXPECT_EQ(SupplicantStatusCode::FAILURE_IFACE_NOT_DISCONNECTED,
                   status.code);
@@ -237,7 +258,7 @@
 /*
  * Disconnect.
  */
-TEST_F(SupplicantStaIfaceHidlTest, Disconnect) {
+TEST_P(SupplicantStaIfaceHidlTest, Disconnect) {
     sta_iface_->disconnect([](const SupplicantStatus& status) {
         EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
     });
@@ -246,7 +267,7 @@
 /*
  * SetPowerSave.
  */
-TEST_F(SupplicantStaIfaceHidlTest, SetPowerSave) {
+TEST_P(SupplicantStaIfaceHidlTest, SetPowerSave) {
     sta_iface_->setPowerSave(true, [](const SupplicantStatus& status) {
         EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
     });
@@ -258,7 +279,7 @@
 /*
  * InitiateTdlsDiscover.
  */
-TEST_F(SupplicantStaIfaceHidlTest, InitiateTdlsDiscover) {
+TEST_P(SupplicantStaIfaceHidlTest, InitiateTdlsDiscover) {
     sta_iface_->initiateTdlsDiscover(
         mac_addr_, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -268,7 +289,7 @@
 /*
  * InitiateTdlsSetup.
  */
-TEST_F(SupplicantStaIfaceHidlTest, InitiateTdlsSetup) {
+TEST_P(SupplicantStaIfaceHidlTest, InitiateTdlsSetup) {
     sta_iface_->initiateTdlsSetup(
         mac_addr_, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -278,7 +299,7 @@
 /*
  * InitiateTdlsTeardown.
  */
-TEST_F(SupplicantStaIfaceHidlTest, InitiateTdlsTeardown) {
+TEST_P(SupplicantStaIfaceHidlTest, InitiateTdlsTeardown) {
     sta_iface_->initiateTdlsTeardown(
         mac_addr_, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -288,7 +309,7 @@
 /*
  * InitiateAnqpQuery.
  */
-TEST_F(SupplicantStaIfaceHidlTest, InitiateAnqpQuery) {
+TEST_P(SupplicantStaIfaceHidlTest, InitiateAnqpQuery) {
     std::vector<ISupplicantStaIface::AnqpInfoId> anqp_ids(
         kTestAnqpInfoIds, kTestAnqpInfoIds + sizeof(kTestAnqpInfoIds));
     std::vector<ISupplicantStaIface::Hs20AnqpSubtypes> hs_types(
@@ -304,7 +325,7 @@
 /*
  * InitiateHs20IconQuery.
  */
-TEST_F(SupplicantStaIfaceHidlTest, InitiateHs20IconQuery) {
+TEST_P(SupplicantStaIfaceHidlTest, InitiateHs20IconQuery) {
     sta_iface_->initiateHs20IconQuery(
         mac_addr_, kTestHs20IconFile, [](const SupplicantStatus& status) {
             // These requests will fail unless the BSSID mentioned is actually
@@ -316,7 +337,7 @@
 /*
  * GetMacAddress.
  */
-TEST_F(SupplicantStaIfaceHidlTest, GetMacAddress) {
+TEST_P(SupplicantStaIfaceHidlTest, GetMacAddress) {
     sta_iface_->getMacAddress([](const SupplicantStatus& status,
                                  const hidl_array<uint8_t, 6>& mac_addr) {
         EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -328,7 +349,7 @@
 /*
  * StartRxFilter.
  */
-TEST_F(SupplicantStaIfaceHidlTest, StartRxFilter) {
+TEST_P(SupplicantStaIfaceHidlTest, StartRxFilter) {
     sta_iface_->startRxFilter([](const SupplicantStatus& status) {
         EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
     });
@@ -337,7 +358,7 @@
 /*
  * StopRxFilter.
  */
-TEST_F(SupplicantStaIfaceHidlTest, StopRxFilter) {
+TEST_P(SupplicantStaIfaceHidlTest, StopRxFilter) {
     sta_iface_->stopRxFilter([](const SupplicantStatus& status) {
         EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
     });
@@ -346,7 +367,7 @@
 /*
  * AddRxFilter.
  */
-TEST_F(SupplicantStaIfaceHidlTest, AddRxFilter) {
+TEST_P(SupplicantStaIfaceHidlTest, AddRxFilter) {
     sta_iface_->addRxFilter(ISupplicantStaIface::RxFilterType::V4_MULTICAST,
                             [](const SupplicantStatus& status) {
                                 EXPECT_EQ(SupplicantStatusCode::SUCCESS,
@@ -362,7 +383,7 @@
 /*
  * RemoveRxFilter.
  */
-TEST_F(SupplicantStaIfaceHidlTest, RemoveRxFilter) {
+TEST_P(SupplicantStaIfaceHidlTest, RemoveRxFilter) {
     sta_iface_->removeRxFilter(ISupplicantStaIface::RxFilterType::V4_MULTICAST,
                                [](const SupplicantStatus& status) {
                                    EXPECT_EQ(SupplicantStatusCode::SUCCESS,
@@ -378,7 +399,7 @@
 /*
  * SetBtCoexistenceMode.
  */
-TEST_F(SupplicantStaIfaceHidlTest, SetBtCoexistenceMode) {
+TEST_P(SupplicantStaIfaceHidlTest, SetBtCoexistenceMode) {
     sta_iface_->setBtCoexistenceMode(
         ISupplicantStaIface::BtCoexistenceMode::ENABLED,
         [](const SupplicantStatus& status) {
@@ -399,7 +420,7 @@
 /*
  * SetBtCoexistenceScanModeEnabled.
  */
-TEST_F(SupplicantStaIfaceHidlTest, SetBtCoexistenceScanModeEnabled) {
+TEST_P(SupplicantStaIfaceHidlTest, SetBtCoexistenceScanModeEnabled) {
     sta_iface_->setBtCoexistenceScanModeEnabled(
         true, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -413,7 +434,7 @@
 /*
  * SetSuspendModeEnabled.
  */
-TEST_F(SupplicantStaIfaceHidlTest, SetSuspendModeEnabled) {
+TEST_P(SupplicantStaIfaceHidlTest, SetSuspendModeEnabled) {
     sta_iface_->setSuspendModeEnabled(true, [](const SupplicantStatus& status) {
         EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
     });
@@ -426,7 +447,7 @@
 /*
  * SetCountryCode.
  */
-TEST_F(SupplicantStaIfaceHidlTest, SetCountryCode) {
+TEST_P(SupplicantStaIfaceHidlTest, SetCountryCode) {
     sta_iface_->setCountryCode(
         kTestCountryCode, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -436,7 +457,7 @@
 /*
  * SetWpsDeviceName
  */
-TEST_F(SupplicantStaIfaceHidlTest, SetWpsDeviceName) {
+TEST_P(SupplicantStaIfaceHidlTest, SetWpsDeviceName) {
     EXPECT_EQ(
         SupplicantStatusCode::SUCCESS,
         HIDL_INVOKE(sta_iface_, setWpsDeviceName, kTestWpsDeviceName).code);
@@ -445,7 +466,7 @@
 /*
  * SetWpsDeviceType
  */
-TEST_F(SupplicantStaIfaceHidlTest, SetWpsDeviceType) {
+TEST_P(SupplicantStaIfaceHidlTest, SetWpsDeviceType) {
     EXPECT_EQ(
         SupplicantStatusCode::SUCCESS,
         HIDL_INVOKE(sta_iface_, setWpsDeviceType, kTestWpsDeviceType).code);
@@ -454,7 +475,7 @@
 /*
  * SetWpsManufacturer
  */
-TEST_F(SupplicantStaIfaceHidlTest, SetWpsManufacturer) {
+TEST_P(SupplicantStaIfaceHidlTest, SetWpsManufacturer) {
     EXPECT_EQ(
         SupplicantStatusCode::SUCCESS,
         HIDL_INVOKE(sta_iface_, setWpsManufacturer, kTestWpsManufacturer).code);
@@ -463,7 +484,7 @@
 /*
  * SetWpsModelName
  */
-TEST_F(SupplicantStaIfaceHidlTest, SetWpsModelName) {
+TEST_P(SupplicantStaIfaceHidlTest, SetWpsModelName) {
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
               HIDL_INVOKE(sta_iface_, setWpsModelName, kTestWpsModelName).code);
 }
@@ -471,7 +492,7 @@
 /*
  * SetWpsModelNumber
  */
-TEST_F(SupplicantStaIfaceHidlTest, SetWpsModelNumber) {
+TEST_P(SupplicantStaIfaceHidlTest, SetWpsModelNumber) {
     EXPECT_EQ(
         SupplicantStatusCode::SUCCESS,
         HIDL_INVOKE(sta_iface_, setWpsModelNumber, kTestWpsModelNumber).code);
@@ -480,7 +501,7 @@
 /*
  * SetWpsSerialNumber
  */
-TEST_F(SupplicantStaIfaceHidlTest, SetWpsSerialNumber) {
+TEST_P(SupplicantStaIfaceHidlTest, SetWpsSerialNumber) {
     EXPECT_EQ(
         SupplicantStatusCode::SUCCESS,
         HIDL_INVOKE(sta_iface_, setWpsSerialNumber, kTestWpsSerialNumber).code);
@@ -489,7 +510,7 @@
 /*
  * SetWpsConfigMethods
  */
-TEST_F(SupplicantStaIfaceHidlTest, SetWpsConfigMethods) {
+TEST_P(SupplicantStaIfaceHidlTest, SetWpsConfigMethods) {
     EXPECT_EQ(
         SupplicantStatusCode::SUCCESS,
         HIDL_INVOKE(sta_iface_, setWpsConfigMethods, kTestWpsConfigMethods)
@@ -499,7 +520,7 @@
 /*
  * SetExternalSim
  */
-TEST_F(SupplicantStaIfaceHidlTest, SetExternalSim) {
+TEST_P(SupplicantStaIfaceHidlTest, SetExternalSim) {
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
               HIDL_INVOKE(sta_iface_, setExternalSim, true).code);
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
@@ -509,7 +530,7 @@
 /*
  * AddExtRadioWork
  */
-TEST_F(SupplicantStaIfaceHidlTest, AddExtRadioWork) {
+TEST_P(SupplicantStaIfaceHidlTest, AddExtRadioWork) {
     const auto& status_and_radio_work_id =
         HIDL_INVOKE(sta_iface_, addExtRadioWork, kTestRadioWorkName,
                     kTestRadioWorkFrequency, kTestRadioWorkTimeout);
@@ -524,9 +545,18 @@
 /*
  * RemoveExtRadioWork
  */
-TEST_F(SupplicantStaIfaceHidlTest, RemoveExtRadioWork) {
+TEST_P(SupplicantStaIfaceHidlTest, RemoveExtRadioWork) {
     // This fails because there is no on going radio work with kTestRadioWorkId.
     EXPECT_NE(
         SupplicantStatusCode::SUCCESS,
         HIDL_INVOKE(sta_iface_, removeExtRadioWork, kTestRadioWorkId).code);
 }
+
+INSTANTIATE_TEST_CASE_P(
+    PerInstance, SupplicantStaIfaceHidlTest,
+    testing::Combine(
+        testing::ValuesIn(
+            android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+            ISupplicant::descriptor))),
+    android::hardware::PrintInstanceTupleNameToString<>);
\ No newline at end of file
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp
index 832dd41..52f77a1 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp
@@ -16,14 +16,16 @@
 
 #include <android-base/logging.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-
+#include <VtsCoreUtil.h>
+#include <android/hardware/wifi/1.0/IWifi.h>
 #include <android/hardware/wifi/supplicant/1.0/ISupplicantStaNetwork.h>
-
-#include <android/hardware/wifi/supplicant/1.0/ISupplicantStaNetwork.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include "supplicant_hidl_call_util.h"
 #include "supplicant_hidl_test_utils.h"
+#include "wifi_hidl_test_utils.h"
 
 using ::android::sp;
 using ::android::hardware::hidl_array;
@@ -32,12 +34,14 @@
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::hardware::wifi::supplicant::V1_0::IfaceType;
+using ::android::hardware::wifi::supplicant::V1_0::ISupplicant;
 using ::android::hardware::wifi::supplicant::V1_0::ISupplicantStaIface;
 using ::android::hardware::wifi::supplicant::V1_0::ISupplicantStaNetwork;
 using ::android::hardware::wifi::supplicant::V1_0::
     ISupplicantStaNetworkCallback;
 using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
 using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
+using ::android::hardware::wifi::V1_0::IWifi;
 
 namespace {
 constexpr char kTestSsidStr[] = "TestSsid1234";
@@ -74,37 +78,50 @@
      ISupplicantStaNetwork::PairwiseCipherMask::TKIP);
 }  // namespace
 
-class SupplicantStaNetworkHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class SupplicantStaNetworkHidlTest
+    : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
    public:
     virtual void SetUp() override {
-        startSupplicantAndWaitForHidlService();
-        EXPECT_TRUE(turnOnExcessiveLogging());
-        sta_network_ = createSupplicantStaNetwork();
+        wifi_instance_name_ = std::get<0>(GetParam());
+        supplicant_instance_name_ = std::get<1>(GetParam());
+        stopSupplicant(wifi_instance_name_);
+        startSupplicantAndWaitForHidlService(wifi_instance_name_,
+                                             supplicant_instance_name_);
+        isP2pOn_ =
+            testing::deviceSupportsFeature("android.hardware.wifi.direct");
+        supplicant_ = getSupplicant(supplicant_instance_name_, isP2pOn_);
+        EXPECT_TRUE(turnOnExcessiveLogging(supplicant_));
+        sta_network_ = createSupplicantStaNetwork(supplicant_);
         ASSERT_NE(sta_network_.get(), nullptr);
 
         ssid_.assign(kTestSsidStr, kTestSsidStr + strlen(kTestSsidStr));
     }
 
-    virtual void TearDown() override { stopSupplicant(); }
+    virtual void TearDown() override { stopSupplicant(wifi_instance_name_); }
 
    protected:
     void removeNetwork() {
-      sp<ISupplicantStaIface> sta_iface = getSupplicantStaIface();
-      ASSERT_NE(nullptr, sta_iface.get());
-      uint32_t net_id;
-      sta_network_->getId([&](const SupplicantStatus& status, int network_id) {
-              ASSERT_EQ(SupplicantStatusCode::SUCCESS, status.code);
-              net_id = network_id;
-          });
-      sta_iface->removeNetwork(net_id, [](const SupplicantStatus& status) {
-              ASSERT_EQ(SupplicantStatusCode::SUCCESS, status.code);
-          });
+        sp<ISupplicantStaIface> sta_iface = getSupplicantStaIface(supplicant_);
+        ASSERT_NE(nullptr, sta_iface.get());
+        uint32_t net_id;
+        sta_network_->getId(
+            [&](const SupplicantStatus& status, int network_id) {
+                ASSERT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+                net_id = network_id;
+            });
+        sta_iface->removeNetwork(net_id, [](const SupplicantStatus& status) {
+            ASSERT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        });
     }
 
+    bool isP2pOn_ = false;
+    sp<ISupplicant> supplicant_;
     // ISupplicantStaNetwork object used for all tests in this fixture.
     sp<ISupplicantStaNetwork> sta_network_;
     // SSID to use for various tests.
     std::vector<uint8_t> ssid_;
+    std::string wifi_instance_name_;
+    std::string supplicant_instance_name_;
 };
 
 class NetworkCallback : public ISupplicantStaNetworkCallback {
@@ -126,16 +143,20 @@
  * Ensures that an instance of the ISupplicantStaNetwork proxy object is
  * successfully created.
  */
-TEST(SupplicantStaNetworkHidlTestNoFixture, Create) {
-    startSupplicantAndWaitForHidlService();
-    EXPECT_NE(nullptr, createSupplicantStaNetwork().get());
-    stopSupplicant();
+TEST_P(SupplicantStaNetworkHidlTest, Create) {
+    stopSupplicant(wifi_instance_name_);
+    startSupplicantAndWaitForHidlService(wifi_instance_name_,
+                                         supplicant_instance_name_);
+    sp<ISupplicant> supplicant =
+        getSupplicant(supplicant_instance_name_, isP2pOn_);
+    EXPECT_TRUE(turnOnExcessiveLogging(supplicant));
+    EXPECT_NE(nullptr, createSupplicantStaNetwork(supplicant).get());
 }
 
 /*
  * RegisterCallback
  */
-TEST_F(SupplicantStaNetworkHidlTest, RegisterCallback) {
+TEST_P(SupplicantStaNetworkHidlTest, RegisterCallback) {
     sta_network_->registerCallback(
         new NetworkCallback(), [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -145,7 +166,7 @@
 /*
  * GetInterfaceName
  */
-TEST_F(SupplicantStaNetworkHidlTest, GetInterfaceName) {
+TEST_P(SupplicantStaNetworkHidlTest, GetInterfaceName) {
     const auto& status_and_interface_name =
         HIDL_INVOKE(sta_network_, getInterfaceName);
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
@@ -156,7 +177,7 @@
 /*
  * GetType
  */
-TEST_F(SupplicantStaNetworkHidlTest, GetType) {
+TEST_P(SupplicantStaNetworkHidlTest, GetType) {
     const auto& status_and_interface_type = HIDL_INVOKE(sta_network_, getType);
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
               status_and_interface_type.first.code);
@@ -167,7 +188,7 @@
 /*
  * SetGetSsid
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetSsid) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetSsid) {
     sta_network_->setSsid(ssid_, [](const SupplicantStatus& status) {
         EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
     });
@@ -181,7 +202,7 @@
 /*
  * SetGetBssid
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetBssid) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetBssid) {
     std::array<uint8_t, 6> set_bssid;
     memcpy(set_bssid.data(), kTestBssid, set_bssid.size());
     sta_network_->setBssid(set_bssid, [](const SupplicantStatus& status) {
@@ -199,7 +220,7 @@
 /*
  * SetGetKeyMgmt
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetKeyMgmt) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetKeyMgmt) {
     sta_network_->setKeyMgmt(kTestKeyMgmt, [](const SupplicantStatus& status) {
         EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
     });
@@ -213,7 +234,7 @@
 /*
  * SetGetProto
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetProto) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetProto) {
     sta_network_->setProto(kTestProto, [](const SupplicantStatus& status) {
         EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
     });
@@ -226,7 +247,7 @@
 /*
  * SetGetKeyAuthAlg
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetAuthAlg) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetAuthAlg) {
     sta_network_->setAuthAlg(kTestAuthAlg, [](const SupplicantStatus& status) {
         EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
     });
@@ -240,7 +261,7 @@
 /*
  * SetGetGroupCipher
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetGroupCipher) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetGroupCipher) {
     sta_network_->setGroupCipher(
         kTestGroupCipher, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -255,7 +276,7 @@
 /*
  * SetGetPairwiseCipher
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetPairwiseCipher) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetPairwiseCipher) {
     sta_network_->setPairwiseCipher(
         kTestPairwiseCipher, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -270,7 +291,7 @@
 /*
  * SetGetPskPassphrase
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetPskPassphrase) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetPskPassphrase) {
     sta_network_->setPskPassphrase(
         kTestPskPassphrase, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -285,7 +306,7 @@
 /*
  * SetGetPsk
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetPsk) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetPsk) {
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
               HIDL_INVOKE(sta_network_, setPsk, kTestPsk).code);
     const auto& status_and_psk = HIDL_INVOKE(sta_network_, getPsk);
@@ -297,7 +318,7 @@
 /*
  * SetGetWepKeys
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetWepTxKeyIdx) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetWepTxKeyIdx) {
     sta_network_->setWepTxKeyIdx(
         kTestWepTxKeyIdx, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -312,7 +333,7 @@
 /*
  * SetGetWepKeys
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetWepKeys) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetWepKeys) {
     for (uint32_t i = 0;
          i < static_cast<uint32_t>(
                  ISupplicantStaNetwork::ParamSizeLimits::WEP_KEYS_MAX_NUM);
@@ -334,7 +355,7 @@
 /*
  * SetGetScanSsid
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetScanSsid) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetScanSsid) {
     sta_network_->setScanSsid(
         true, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -349,7 +370,7 @@
 /*
  * SetGetRequirePmf
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetRequirePmf) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetRequirePmf) {
     sta_network_->setRequirePmf(
         true, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -364,7 +385,7 @@
 /*
  * SetGetIdStr
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetIdStr) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetIdStr) {
     sta_network_->setIdStr(
         kTestIdStr, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -376,11 +397,10 @@
         });
 }
 
-
 /*
  * SetGetEapMethod
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetEapMethod) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetEapMethod) {
     ISupplicantStaNetwork::EapMethod set_eap_method =
         ISupplicantStaNetwork::EapMethod::PEAP;
     sta_network_->setEapMethod(
@@ -398,7 +418,7 @@
 /*
  * SetGetEapPhase2Method
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetEapPhase2Method) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetEapPhase2Method) {
     ISupplicantStaNetwork::EapMethod set_eap_method =
         ISupplicantStaNetwork::EapMethod::PEAP;
     sta_network_->setEapMethod(
@@ -422,7 +442,7 @@
 /*
  * SetGetEapIdentity
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetEapIdentity) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetEapIdentity) {
     std::vector<uint8_t> set_identity(kTestIdentity, kTestIdentity + sizeof(kTestIdentity));
     sta_network_->setEapIdentity(
         set_identity, [](const SupplicantStatus& status) {
@@ -438,7 +458,7 @@
 /*
  * SetGetEapAnonymousIdentity
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetEapAnonymousIdentity) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetEapAnonymousIdentity) {
     std::vector<uint8_t> set_identity(kTestIdentity, kTestIdentity + sizeof(kTestIdentity));
     sta_network_->setEapAnonymousIdentity(
         set_identity, [](const SupplicantStatus& status) {
@@ -454,7 +474,7 @@
 /*
  * SetGetEapPassword
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetEapPassword) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetEapPassword) {
     std::vector<uint8_t> set_eap_passwd(
         kTestEapPasswdStr, kTestEapPasswdStr + strlen(kTestEapPasswdStr));
     sta_network_->setEapPassword(
@@ -471,7 +491,7 @@
 /*
  * SetGetEapCACert
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetEapCACert) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetEapCACert) {
     sta_network_->setEapCACert(
         kTestEapCert, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -486,7 +506,7 @@
 /*
  * SetGetEapCAPath
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetEapCAPath) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetEapCAPath) {
     sta_network_->setEapCAPath(
         kTestEapCert, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -501,7 +521,7 @@
 /*
  * SetGetEapClientCert
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetEapClientCert) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetEapClientCert) {
     sta_network_->setEapClientCert(
         kTestEapCert, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -516,7 +536,7 @@
 /*
  * SetGetEapPrivateKeyId
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetEapPrivateKeyId) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetEapPrivateKeyId) {
     sta_network_->setEapPrivateKeyId(
         kTestEapPrivateKeyId, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -531,7 +551,7 @@
 /*
  * SetGetEapAltSubjectMatch
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetEapAltSubjectMatch) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetEapAltSubjectMatch) {
     sta_network_->setEapAltSubjectMatch(
         kTestEapMatch, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -546,7 +566,7 @@
 /*
  * SetGetEapSubjectMatch
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetEapSubjectMatch) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetEapSubjectMatch) {
     EXPECT_EQ(
         SupplicantStatusCode::SUCCESS,
         HIDL_INVOKE(sta_network_, setEapSubjectMatch, kTestEapMatch).code);
@@ -561,7 +581,7 @@
 /*
  * SetGetEapDomainSuffixMatch
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetEapDomainSuffixMatch) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetEapDomainSuffixMatch) {
     sta_network_->setEapDomainSuffixMatch(
         kTestEapMatch, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -576,7 +596,7 @@
 /*
  * SetGetEapEngine
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetEapEngine) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetEapEngine) {
     sta_network_->setEapEngine(
         true, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -591,7 +611,7 @@
 /*
  * SetGetEapEngineID
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetGetEapEngineID) {
+TEST_P(SupplicantStaNetworkHidlTest, SetGetEapEngineID) {
     sta_network_->setEapEngineID(
         kTestEapEngineID, [](const SupplicantStatus& status) {
             EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
@@ -606,7 +626,7 @@
 /*
  * Enable
  */
-TEST_F(SupplicantStaNetworkHidlTest, Enable) {
+TEST_P(SupplicantStaNetworkHidlTest, Enable) {
     // wpa_supplicant doesn't perform any connection initiation
     // unless atleast the Ssid and Ket mgmt params are set.
     sta_network_->setSsid(ssid_, [](const SupplicantStatus& status) {
@@ -633,7 +653,7 @@
 /*
  * Disable
  */
-TEST_F(SupplicantStaNetworkHidlTest, Disable) {
+TEST_P(SupplicantStaNetworkHidlTest, Disable) {
     // wpa_supplicant doesn't perform any connection initiation
     // unless atleast the Ssid and Ket mgmt params are set.
     sta_network_->setSsid(ssid_, [](const SupplicantStatus& status) {
@@ -656,7 +676,7 @@
 /*
  * Select.
  */
-TEST_F(SupplicantStaNetworkHidlTest, Select) {
+TEST_P(SupplicantStaNetworkHidlTest, Select) {
     // wpa_supplicant doesn't perform any connection initiation
     // unless atleast the Ssid and Ket mgmt params are set.
     sta_network_->setSsid(ssid_, [](const SupplicantStatus& status) {
@@ -679,7 +699,7 @@
 /*
  * SendNetworkEapSimGsmAuthResponse
  */
-TEST_F(SupplicantStaNetworkHidlTest, SendNetworkEapSimGsmAuthResponse) {
+TEST_P(SupplicantStaNetworkHidlTest, SendNetworkEapSimGsmAuthResponse) {
     std::vector<ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams>
         params;
     ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams param;
@@ -695,7 +715,7 @@
 /*
  * SendNetworkEapSimGsmAuthFailure
  */
-TEST_F(SupplicantStaNetworkHidlTest, SendNetworkEapSimGsmAuthFailure) {
+TEST_P(SupplicantStaNetworkHidlTest, SendNetworkEapSimGsmAuthFailure) {
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
               HIDL_INVOKE(sta_network_, sendNetworkEapSimGsmAuthFailure).code);
 }
@@ -703,7 +723,7 @@
 /*
  * SendNetworkEapSimUmtsAuthResponse
  */
-TEST_F(SupplicantStaNetworkHidlTest, SendNetworkEapSimUmtsAuthResponse) {
+TEST_P(SupplicantStaNetworkHidlTest, SendNetworkEapSimUmtsAuthResponse) {
     ISupplicantStaNetwork::NetworkResponseEapSimUmtsAuthParams params;
     params.res = std::vector<uint8_t>(kTestRes, kTestRes + sizeof(kTestRes));
     memcpy(params.ik.data(), kTestIk, params.ik.size());
@@ -717,7 +737,7 @@
 /*
  * SendNetworkEapSimUmtsAuthFailure
  */
-TEST_F(SupplicantStaNetworkHidlTest, SendNetworkEapSimUmtsAuthFailure) {
+TEST_P(SupplicantStaNetworkHidlTest, SendNetworkEapSimUmtsAuthFailure) {
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
               HIDL_INVOKE(sta_network_, sendNetworkEapSimUmtsAuthFailure).code);
 }
@@ -725,7 +745,7 @@
 /*
  * SendNetworkEapSimUmtsAutsResponse
  */
-TEST_F(SupplicantStaNetworkHidlTest, SendNetworkEapSimUmtsAutsResponse) {
+TEST_P(SupplicantStaNetworkHidlTest, SendNetworkEapSimUmtsAutsResponse) {
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
               HIDL_INVOKE(sta_network_, sendNetworkEapSimUmtsAutsResponse,
                           kTestAutParam)
@@ -735,7 +755,7 @@
 /*
  * SendNetworkEapIdentityResponse
  */
-TEST_F(SupplicantStaNetworkHidlTest, SendNetworkEapIdentityResponse) {
+TEST_P(SupplicantStaNetworkHidlTest, SendNetworkEapIdentityResponse) {
     sta_network_->sendNetworkEapIdentityResponse(
         std::vector<uint8_t>(kTestIdentity,
                              kTestIdentity + sizeof(kTestIdentity)),
@@ -747,7 +767,7 @@
 /*
  * SetUpdateIdentifier
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetUpdateIdentifier) {
+TEST_P(SupplicantStaNetworkHidlTest, SetUpdateIdentifier) {
     EXPECT_EQ(
         SupplicantStatusCode::SUCCESS,
         HIDL_INVOKE(sta_network_, setUpdateIdentifier, kTestUpdateIdentifier)
@@ -757,7 +777,7 @@
 /*
  * SetProactiveKeyCaching
  */
-TEST_F(SupplicantStaNetworkHidlTest, SetProactiveKeyCaching) {
+TEST_P(SupplicantStaNetworkHidlTest, SetProactiveKeyCaching) {
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
               HIDL_INVOKE(sta_network_, setProactiveKeyCaching, true).code);
     EXPECT_EQ(SupplicantStatusCode::SUCCESS,
@@ -767,7 +787,7 @@
 /*
  * GetWpsNfcConfigurationToken
  */
-TEST_F(SupplicantStaNetworkHidlTest, GetWpsNfcConfigurationToken) {
+TEST_P(SupplicantStaNetworkHidlTest, GetWpsNfcConfigurationToken) {
     ASSERT_EQ(SupplicantStatusCode::SUCCESS,
               HIDL_INVOKE(sta_network_, setSsid, ssid_).code);
     ASSERT_EQ(SupplicantStatusCode::SUCCESS,
@@ -780,3 +800,12 @@
     EXPECT_EQ(SupplicantStatusCode::SUCCESS, status_and_token.first.code);
     EXPECT_FALSE(0 == status_and_token.second.size());
 }
+
+INSTANTIATE_TEST_CASE_P(
+    PerInstance, SupplicantStaNetworkHidlTest,
+    testing::Combine(
+        testing::ValuesIn(
+            android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+            ISupplicant::descriptor))),
+    android::hardware::PrintInstanceTupleNameToString<>);
\ No newline at end of file