Merge "Audio HAL: Add API to attach an effect to a device"
diff --git a/audio/core/all-versions/default/Device.cpp b/audio/core/all-versions/default/Device.cpp
index 525349f..ad841ca 100644
--- a/audio/core/all-versions/default/Device.cpp
+++ b/audio/core/all-versions/default/Device.cpp
@@ -86,26 +86,29 @@
         ALOGW("Can not set a master volume (%f) outside [0,1]", volume);
         return Result::INVALID_ARGUMENTS;
     }
-    return analyzeStatus("set_master_volume", mDevice->set_master_volume(mDevice, volume));
+    return analyzeStatus("set_master_volume", mDevice->set_master_volume(mDevice, volume),
+                         {ENOSYS} /*ignore*/);
 }
 
 Return<void> Device::getMasterVolume(getMasterVolume_cb _hidl_cb) {
     Result retval(Result::NOT_SUPPORTED);
     float volume = 0;
     if (mDevice->get_master_volume != NULL) {
-        retval = analyzeStatus("get_master_volume", mDevice->get_master_volume(mDevice, &volume));
+        retval = analyzeStatus("get_master_volume", mDevice->get_master_volume(mDevice, &volume),
+                               {ENOSYS} /*ignore*/);
     }
     _hidl_cb(retval, volume);
     return Void();
 }
 
 Return<Result> Device::setMicMute(bool mute) {
-    return analyzeStatus("set_mic_mute", mDevice->set_mic_mute(mDevice, mute));
+    return analyzeStatus("set_mic_mute", mDevice->set_mic_mute(mDevice, mute), {ENOSYS} /*ignore*/);
 }
 
 Return<void> Device::getMicMute(getMicMute_cb _hidl_cb) {
     bool mute = false;
-    Result retval = analyzeStatus("get_mic_mute", mDevice->get_mic_mute(mDevice, &mute));
+    Result retval = analyzeStatus("get_mic_mute", mDevice->get_mic_mute(mDevice, &mute),
+                                  {ENOSYS} /*ignore*/);
     _hidl_cb(retval, mute);
     return Void();
 }
@@ -113,7 +116,8 @@
 Return<Result> Device::setMasterMute(bool mute) {
     Result retval(Result::NOT_SUPPORTED);
     if (mDevice->set_master_mute != NULL) {
-        retval = analyzeStatus("set_master_mute", mDevice->set_master_mute(mDevice, mute));
+        retval = analyzeStatus("set_master_mute", mDevice->set_master_mute(mDevice, mute),
+                               {ENOSYS} /*ignore*/);
     }
     return retval;
 }
@@ -122,7 +126,8 @@
     Result retval(Result::NOT_SUPPORTED);
     bool mute = false;
     if (mDevice->get_master_mute != NULL) {
-        retval = analyzeStatus("get_master_mute", mDevice->get_master_mute(mDevice, &mute));
+        retval = analyzeStatus("get_master_mute", mDevice->get_master_mute(mDevice, &mute),
+                               {ENOSYS} /*ignore*/);
     }
     _hidl_cb(retval, mute);
     return Void();
diff --git a/audio/core/all-versions/default/StreamOut.cpp b/audio/core/all-versions/default/StreamOut.cpp
index 396d354..1a2a764 100644
--- a/audio/core/all-versions/default/StreamOut.cpp
+++ b/audio/core/all-versions/default/StreamOut.cpp
@@ -318,7 +318,8 @@
         ALOGW("Can not set a stream output volume {%f, %f} outside [0,1]", left, right);
         return Result::INVALID_ARGUMENTS;
     }
-    return Stream::analyzeStatus("set_volume", mStream->set_volume(mStream, left, right));
+    return Stream::analyzeStatus("set_volume", mStream->set_volume(mStream, left, right),
+                                 {ENOSYS} /*ignore*/);
 }
 
 Return<void> StreamOut::prepareForWriting(uint32_t frameSize, uint32_t framesCount,
@@ -403,7 +404,8 @@
 Return<void> StreamOut::getRenderPosition(getRenderPosition_cb _hidl_cb) {
     uint32_t halDspFrames;
     Result retval = Stream::analyzeStatus("get_render_position",
-                                          mStream->get_render_position(mStream, &halDspFrames));
+                                          mStream->get_render_position(mStream, &halDspFrames),
+                                          {ENOSYS} /*ignore*/);
     _hidl_cb(retval, halDspFrames);
     return Void();
 }
@@ -413,7 +415,8 @@
     int64_t timestampUs = 0;
     if (mStream->get_next_write_timestamp != NULL) {
         retval = Stream::analyzeStatus("get_next_write_timestamp",
-                                       mStream->get_next_write_timestamp(mStream, &timestampUs));
+                                       mStream->get_next_write_timestamp(mStream, &timestampUs),
+                                       {ENOSYS} /*ignore*/);
     }
     _hidl_cb(retval, timestampUs);
     return Void();
@@ -427,7 +430,7 @@
     if (result == 0) {
         mCallback = callback;
     }
-    return Stream::analyzeStatus("set_callback", result);
+    return Stream::analyzeStatus("set_callback", result, {ENOSYS} /*ignore*/);
 }
 
 Return<Result> StreamOut::clearCallback() {
@@ -473,13 +476,15 @@
 }
 
 Return<Result> StreamOut::pause() {
-    return mStream->pause != NULL ? Stream::analyzeStatus("pause", mStream->pause(mStream))
-                                  : Result::NOT_SUPPORTED;
+    return mStream->pause != NULL
+                   ? Stream::analyzeStatus("pause", mStream->pause(mStream), {ENOSYS} /*ignore*/)
+                   : Result::NOT_SUPPORTED;
 }
 
 Return<Result> StreamOut::resume() {
-    return mStream->resume != NULL ? Stream::analyzeStatus("resume", mStream->resume(mStream))
-                                   : Result::NOT_SUPPORTED;
+    return mStream->resume != NULL
+                   ? Stream::analyzeStatus("resume", mStream->resume(mStream), {ENOSYS} /*ignore*/)
+                   : Result::NOT_SUPPORTED;
 }
 
 Return<bool> StreamOut::supportsDrain() {
@@ -488,14 +493,17 @@
 
 Return<Result> StreamOut::drain(AudioDrain type) {
     return mStream->drain != NULL
-               ? Stream::analyzeStatus(
-                     "drain", mStream->drain(mStream, static_cast<audio_drain_type_t>(type)))
-               : Result::NOT_SUPPORTED;
+                   ? Stream::analyzeStatus(
+                             "drain",
+                             mStream->drain(mStream, static_cast<audio_drain_type_t>(type)),
+                             {ENOSYS} /*ignore*/)
+                   : Result::NOT_SUPPORTED;
 }
 
 Return<Result> StreamOut::flush() {
-    return mStream->flush != NULL ? Stream::analyzeStatus("flush", mStream->flush(mStream))
-                                  : Result::NOT_SUPPORTED;
+    return mStream->flush != NULL
+                   ? Stream::analyzeStatus("flush", mStream->flush(mStream), {ENOSYS} /*ignore*/)
+                   : Result::NOT_SUPPORTED;
 }
 
 // static
@@ -505,7 +513,7 @@
     // to return it sometimes. EAGAIN may be returned by A2DP audio HAL
     // implementation. ENODATA can also be reported while the writer is
     // continuously querying it, but the stream has been stopped.
-    static const std::vector<int> ignoredErrors{EINVAL, EAGAIN, ENODATA};
+    static const std::vector<int> ignoredErrors{EINVAL, EAGAIN, ENODATA, ENOSYS};
     Result retval(Result::NOT_SUPPORTED);
     if (stream->get_presentation_position == NULL) return retval;
     struct timespec halTimeStamp;
diff --git a/automotive/can/1.0/default/CanBus.cpp b/automotive/can/1.0/default/CanBus.cpp
index 42d2e3c..86df5dc 100644
--- a/automotive/can/1.0/default/CanBus.cpp
+++ b/automotive/can/1.0/default/CanBus.cpp
@@ -22,6 +22,8 @@
 #include <libnetdevice/can.h>
 #include <libnetdevice/libnetdevice.h>
 #include <linux/can.h>
+#include <linux/can/error.h>
+#include <linux/can/raw.h>
 
 namespace android {
 namespace hardware {
@@ -220,6 +222,21 @@
 }
 
 /**
+ * Helper function to determine if a flag meets the requirements of a
+ * FilterFlag. See definition of FilterFlag in types.hal
+ *
+ * \param filterFlag FilterFlag object to match flag against
+ * \param flag bool object from CanMessage object
+ */
+static bool satisfiesFilterFlag(FilterFlag filterFlag, bool flag) {
+    // TODO(b/144458917) add testing for this to VTS tests
+    if (filterFlag == FilterFlag::DONT_CARE) return true;
+    if (filterFlag == FilterFlag::REQUIRE) return flag;
+    if (filterFlag == FilterFlag::EXCLUDE) return !flag;
+    return false;
+}
+
+/**
  * Match the filter set against message id.
  *
  * For details on the filters syntax, please see CanMessageFilter at
@@ -229,13 +246,16 @@
  * \param id Message id to filter
  * \return true if the message id matches the filter, false otherwise
  */
-static bool match(const hidl_vec<CanMessageFilter>& filter, CanMessageId id) {
+static bool match(const hidl_vec<CanMessageFilter>& filter, CanMessageId id, bool isExtendedId,
+                  bool isRtr) {
     if (filter.size() == 0) return true;
 
     bool anyNonInvertedPresent = false;
     bool anyNonInvertedSatisfied = false;
     for (auto& rule : filter) {
-        const bool satisfied = ((id & rule.mask) == rule.id) == !rule.inverted;
+        const bool satisfied = ((id & rule.mask) == rule.id) == !rule.inverted &&
+                               satisfiesFilterFlag(rule.rtr, isRtr) &&
+                               satisfiesFilterFlag(rule.extendedFormat, isExtendedId);
         if (rule.inverted) {
             // Any inverted (blacklist) rule not being satisfied invalidates the whole filter set.
             if (!satisfied) return false;
@@ -247,11 +267,54 @@
     return !anyNonInvertedPresent || anyNonInvertedSatisfied;
 }
 
+void CanBus::notifyErrorListeners(ErrorEvent err, bool isFatal) {
+    std::lock_guard<std::mutex> lck(mErrListenersGuard);
+    for (auto& listener : mErrListeners) {
+        if (!listener->onError(err, isFatal).isOk()) {
+            LOG(WARNING) << "Failed to notify listener about error";
+        }
+    }
+}
+
+static ErrorEvent parseErrorFrame(const struct canfd_frame& frame) {
+    // decode error frame (to a degree)
+    if ((frame.can_id & (CAN_ERR_BUSERROR | CAN_ERR_BUSOFF)) != 0) {
+        return ErrorEvent::BUS_ERROR;
+    }
+    if ((frame.data[1] & CAN_ERR_CRTL_TX_OVERFLOW) != 0) {
+        return ErrorEvent::TX_OVERFLOW;
+    }
+    if ((frame.data[1] & CAN_ERR_CRTL_RX_OVERFLOW) != 0) {
+        return ErrorEvent::RX_OVERFLOW;
+    }
+    if ((frame.data[2] & CAN_ERR_PROT_OVERLOAD) != 0) {
+        return ErrorEvent::BUS_OVERLOAD;
+    }
+    if ((frame.can_id & CAN_ERR_PROT) != 0) {
+        return ErrorEvent::MALFORMED_INPUT;
+    }
+    if ((frame.can_id & (CAN_ERR_CRTL | CAN_ERR_TRX | CAN_ERR_RESTARTED)) != 0) {
+        // "controller restarted" constitutes a HARDWARE_ERROR imo
+        return ErrorEvent::HARDWARE_ERROR;
+    }
+    return ErrorEvent::UNKNOWN_ERROR;
+}
+
 void CanBus::onRead(const struct canfd_frame& frame, std::chrono::nanoseconds timestamp) {
+    if ((frame.can_id & CAN_ERR_FLAG) != 0) {
+        // error bit is set
+        LOG(WARNING) << "CAN Error frame received";
+        // TODO(b/144458917) consider providing different values for isFatal, depending on error
+        notifyErrorListeners(parseErrorFrame(frame), false);
+        return;
+    }
+
     CanMessage message = {};
-    message.id = frame.can_id;
+    message.id = frame.can_id & CAN_EFF_MASK;  // mask out eff/rtr/err flags
     message.payload = hidl_vec<uint8_t>(frame.data, frame.data + frame.len);
     message.timestamp = timestamp.count();
+    message.isExtendedId = (frame.can_id & CAN_EFF_FLAG) != 0;
+    message.remoteTransmissionRequest = (frame.can_id & CAN_RTR_FLAG) != 0;
 
     if (UNLIKELY(kSuperVerbose)) {
         LOG(VERBOSE) << "Got message " << toString(message);
@@ -259,7 +322,9 @@
 
     std::lock_guard<std::mutex> lck(mMsgListenersGuard);
     for (auto& listener : mMsgListeners) {
-        if (!match(listener.filter, message.id)) continue;
+        if (!match(listener.filter, message.id, message.remoteTransmissionRequest,
+                   message.isExtendedId))
+            continue;
         if (!listener.callback->onReceive(message).isOk() && !listener.failedOnce) {
             listener.failedOnce = true;
             LOG(WARNING) << "Failed to notify listener about message";
@@ -274,15 +339,7 @@
         mDownAfterUse = false;
         eventType = ErrorEvent::INTERFACE_DOWN;
     }
-
-    {
-        std::lock_guard<std::mutex> lck(mErrListenersGuard);
-        for (auto& listener : mErrListeners) {
-            if (!listener->onError(eventType, true).isOk()) {
-                LOG(WARNING) << "Failed to notify listener about error";
-            }
-        }
-    }
+    notifyErrorListeners(eventType, true);
 
     const auto errcb = mErrCb;
     if (errcb != nullptr) errcb();
diff --git a/automotive/can/1.0/default/CanBus.h b/automotive/can/1.0/default/CanBus.h
index 365e90c..da3fc5a 100644
--- a/automotive/can/1.0/default/CanBus.h
+++ b/automotive/can/1.0/default/CanBus.h
@@ -89,6 +89,8 @@
     void clearMsgListeners();
     void clearErrListeners();
 
+    void notifyErrorListeners(ErrorEvent err, bool isFatal);
+
     void onRead(const struct canfd_frame& frame, std::chrono::nanoseconds timestamp);
     void onError(int errnoVal);
 
diff --git a/automotive/can/1.0/default/libnetdevice/can.cpp b/automotive/can/1.0/default/libnetdevice/can.cpp
index 87617dd..6452d9b 100644
--- a/automotive/can/1.0/default/libnetdevice/can.cpp
+++ b/automotive/can/1.0/default/libnetdevice/can.cpp
@@ -24,12 +24,16 @@
 #include <android-base/unique_fd.h>
 
 #include <linux/can.h>
+#include <linux/can/error.h>
 #include <linux/can/netlink.h>
+#include <linux/can/raw.h>
 
 namespace android {
 namespace netdevice {
 namespace can {
 
+static constexpr can_err_mask_t kErrMask = CAN_ERR_MASK;
+
 base::unique_fd socket(const std::string& ifname) {
     struct sockaddr_can addr = {};
     addr.can_family = AF_CAN;
@@ -45,6 +49,11 @@
         return {};
     }
 
+    if (setsockopt(sock.get(), SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &kErrMask, sizeof(kErrMask)) < 0) {
+        LOG(ERROR) << "Can't receive error frames, CAN setsockpt failed: " << strerror(errno);
+        return {};
+    }
+
     if (0 != fcntl(sock.get(), F_SETFL, O_RDWR | O_NONBLOCK)) {
         LOG(ERROR) << "Couldn't put CAN socket in non-blocking mode";
         return {};
diff --git a/automotive/can/1.0/tools/canhaldump.cpp b/automotive/can/1.0/tools/canhaldump.cpp
index 99fd14a..55b2a34 100644
--- a/automotive/can/1.0/tools/canhaldump.cpp
+++ b/automotive/can/1.0/tools/canhaldump.cpp
@@ -20,6 +20,7 @@
 #include <android/hidl/manager/1.2/IServiceManager.h>
 #include <hidl-utils/hidl-utils.h>
 
+#include <linux/can.h>
 #include <chrono>
 #include <iomanip>
 #include <iostream>
@@ -42,12 +43,14 @@
     CanMessageListener(std::string name) : name(name) {}
 
     virtual Return<void> onReceive(const V1_0::CanMessage& message) {
-        std::cout << "  " << name << "  " << std::hex << std::uppercase << std::setw(3)
+        int msgIdWidth = 3;
+        if (message.isExtendedId) msgIdWidth = 8;
+        std::cout << "  " << name << "  " << std::hex << std::uppercase << std::setw(msgIdWidth)
                   << std::setfill('0') << message.id << std::setw(0);
+        std::cout << "   [" << message.payload.size() << "] ";
         if (message.remoteTransmissionRequest) {
-            std::cout << " RTR";
+            std::cout << "remote request";
         } else {
-            std::cout << "   [" << message.payload.size() << "] ";
             for (const auto byte : message.payload) {
                 std::cout << " " << std::setfill('0') << std::setw(2) << unsigned(byte);
             }
diff --git a/automotive/can/1.0/types.hal b/automotive/can/1.0/types.hal
index 6f690f7..f09c940 100644
--- a/automotive/can/1.0/types.hal
+++ b/automotive/can/1.0/types.hal
@@ -58,6 +58,15 @@
      * If this flag is set, payload must be empty.
      */
     bool remoteTransmissionRequest;
+
+    /**
+     * Flag indicating if the message has an extended ID.
+     *
+     * Extended ID's are 29 bits long, as opposed to the standard 11 bit ID.
+     * It can not simply be inferred from the length of the ID itself, as the
+     * message ID 0x00000123 !=  message ID 0x123.
+     */
+    bool isExtendedId;
 };
 
 /**
@@ -70,11 +79,30 @@
  * one) and all inverted filters must match. In other words:
  *  - a single matching non-inverted filter makes the whole set matching;
  *  - a single non-matching inverted filter makes the whole set non-matching.
+ *
+ * Additional less common options for filtering include:
+ * rtr - Remote Transmission Request; another ECU requests DLC bytes of data on this message ID
+ * extendedFormat - 29 bit message ID is used instead of 11 bits
  */
 struct CanMessageFilter {
     CanMessageId id;
     uint32_t mask;
     bool inverted;
+    FilterFlag rtr;
+    FilterFlag extendedFormat;
+};
+
+
+/**
+ * Types of filter that can be applied to a CanMessageFilter
+ */
+enum FilterFlag : uint8_t {
+    /** Default, FilterFlag doesn't effect what messages filtered */
+    DONT_CARE = 0,
+    /** This FilterFlag MUST be present in received messages to pass though the filter */
+    REQUIRE,
+    /** This FilterFlag must NOT be present in received messages to pass though the filter */
+    EXCLUDE,
 };
 
 enum Result : uint8_t {
diff --git a/automotive/can/1.0/vts/functional/VtsHalCanBusV1_0TargetTest.cpp b/automotive/can/1.0/vts/functional/VtsHalCanBusV1_0TargetTest.cpp
index 1a05716..250caf2 100644
--- a/automotive/can/1.0/vts/functional/VtsHalCanBusV1_0TargetTest.cpp
+++ b/automotive/can/1.0/vts/functional/VtsHalCanBusV1_0TargetTest.cpp
@@ -123,9 +123,9 @@
 
 TEST_F(CanBusHalTest, ListenSomeFilter) {
     hidl_vec<CanMessageFilter> filters = {
-            {0x123, 0x1FF, false},
-            {0x001, 0x00F, true},
-            {0x200, 0x100, false},
+            {0x123, 0x1FF, false, FilterFlag::DONT_CARE, FilterFlag::DONT_CARE},
+            {0x001, 0x00F, true, FilterFlag::DONT_CARE, FilterFlag::DONT_CARE},
+            {0x200, 0x100, false, FilterFlag::DONT_CARE, FilterFlag::DONT_CARE},
     };
 
     const auto [result, closeHandle] = listen(filters, new CanMessageListener());
diff --git a/automotive/can/1.0/vts/functional/VtsHalCanBusVirtualV1_0TargetTest.cpp b/automotive/can/1.0/vts/functional/VtsHalCanBusVirtualV1_0TargetTest.cpp
index 225984d..695b9fb 100644
--- a/automotive/can/1.0/vts/functional/VtsHalCanBusVirtualV1_0TargetTest.cpp
+++ b/automotive/can/1.0/vts/functional/VtsHalCanBusVirtualV1_0TargetTest.cpp
@@ -244,14 +244,14 @@
     auto bus2 = makeBus();
 
     hidl_vec<CanMessageFilter> filterPositive = {
-            {0x101, 0x100, false},
-            {0x010, 0x0F0, false},
+            {0x101, 0x100, false, FilterFlag::DONT_CARE, FilterFlag::DONT_CARE},
+            {0x010, 0x0F0, false, FilterFlag::DONT_CARE, FilterFlag::DONT_CARE},
     };
     auto listenerPositive = bus2.listen(filterPositive);
 
     hidl_vec<CanMessageFilter> filterNegative = {
-            {0x123, 0x0FF, true},
-            {0x004, 0x00F, true},
+            {0x123, 0x0FF, true, FilterFlag::DONT_CARE, FilterFlag::DONT_CARE},
+            {0x004, 0x00F, true, FilterFlag::DONT_CARE, FilterFlag::DONT_CARE},
     };
     auto listenerNegative = bus2.listen(filterNegative);
 
diff --git a/automotive/evs/common/utils/default/Android.bp b/automotive/evs/common/utils/default/Android.bp
index 7734f5c..776ef81 100644
--- a/automotive/evs/common/utils/default/Android.bp
+++ b/automotive/evs/common/utils/default/Android.bp
@@ -15,6 +15,7 @@
 //
 
 cc_library_static {
+    host_supported: true,
     name: "android.hardware.automotive.evs@common-default-lib",
     vendor_available: true,
     relative_install_path: "hw",
diff --git a/automotive/evs/common/utils/default/test/fuzz/Android.bp b/automotive/evs/common/utils/default/test/fuzz/Android.bp
new file mode 100644
index 0000000..105ec68
--- /dev/null
+++ b/automotive/evs/common/utils/default/test/fuzz/Android.bp
@@ -0,0 +1,99 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_fuzz {
+    host_supported: true,
+    name : "FormatConvertFuzzer_copyNV21toRGB32",
+    srcs: [
+        "FormatConvertFuzzer.cpp",
+    ],
+    static_libs: [
+        "android.hardware.automotive.evs@common-default-lib"
+    ],
+    cflags: [
+        "-DCOPY_NV21_TO_RGB32",
+    ],
+}
+
+cc_fuzz {
+    host_supported: true,
+    name : "FormatConvertFuzzer_copyNV21toBGR32",
+    srcs: [
+        "FormatConvertFuzzer.cpp",
+    ],
+    static_libs: [
+        "android.hardware.automotive.evs@common-default-lib"
+    ],
+    cflags: [
+        "-DCOPY_NV21_TO_BGR32",
+    ],
+}
+
+cc_fuzz {
+    host_supported: true,
+    name : "FormatConvertFuzzer_copyYV12toRGB32",
+    srcs: [
+        "FormatConvertFuzzer.cpp",
+    ],
+    static_libs: [
+        "android.hardware.automotive.evs@common-default-lib"
+    ],
+    cflags: [
+        "-DCOPY_YV12_TO_RGB32",
+    ],
+}
+
+cc_fuzz {
+    host_supported: true,
+    name : "FormatConvertFuzzer_copyYV12toBGR32",
+    srcs: [
+        "FormatConvertFuzzer.cpp",
+    ],
+    static_libs: [
+        "android.hardware.automotive.evs@common-default-lib"
+    ],
+    cflags: [
+        "-DCOPY_YV12_TO_BGR32",
+    ],
+}
+
+cc_fuzz {
+    host_supported: true,
+    name : "FormatConvertFuzzer_copyYUYVtoRGB32",
+    srcs: [
+        "FormatConvertFuzzer.cpp",
+    ],
+    static_libs: [
+        "android.hardware.automotive.evs@common-default-lib"
+    ],
+    cflags: [
+        "-DCOPY_YUYV_TO_RGB32",
+    ],
+}
+
+cc_fuzz {
+    host_supported: true,
+    name : "FormatConvertFuzzer_copyYUYVtoBGR32",
+    srcs: [
+        "FormatConvertFuzzer.cpp",
+    ],
+    static_libs: [
+        "android.hardware.automotive.evs@common-default-lib"
+    ],
+    cflags: [
+        "-DCOPY_YUYV_TO_BGR32",
+    ],
+}
diff --git a/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp b/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
new file mode 100644
index 0000000..583a455
--- /dev/null
+++ b/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cmath>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include "FormatConvert.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, std::size_t size) {
+    if (size < 256) {
+        return 0;
+    }
+
+    std::srand(std::time(nullptr));  // use current time as seed for random generator
+    int random_variable = std::rand() % 10;
+    int width = (int)sqrt(size);
+    int height = width * ((float)random_variable / 10.0);
+
+    uint8_t* src = (uint8_t*)malloc(sizeof(uint8_t) * size);
+    memcpy(src, data, sizeof(uint8_t) * (size));
+    uint32_t* tgt = (uint32_t*)malloc(sizeof(uint32_t) * size);
+
+#ifdef COPY_NV21_TO_RGB32
+    android::hardware::automotive::evs::common::Utils::copyNV21toRGB32(width, height, src, tgt, 0);
+#elif COPY_NV21_TO_BGR32
+    android::hardware::automotive::evs::common::Utils::copyNV21toBGR32(width, height, src, tgt, 0);
+#elif COPY_YV12_TO_RGB32
+    android::hardware::automotive::evs::common::Utils::copyYV12toRGB32(width, height, src, tgt, 0);
+#elif COPY_YV12_TO_BGR32
+    android::hardware::automotive::evs::common::Utils::copyYV12toBGR32(width, height, src, tgt, 0);
+#elif COPY_YUYV_TO_RGB32
+    android::hardware::automotive::evs::common::Utils::copyYUYVtoRGB32(width, height, src, 0, tgt,
+                                                                       0);
+#elif COPY_YUYV_TO_BGR32
+    android::hardware::automotive::evs::common::Utils::copyYUYVtoBGR32(width, height, src, 0, tgt,
+                                                                       0);
+#endif
+
+    free(src);
+    free(tgt);
+
+    return 0;
+}
diff --git a/broadcastradio/2.0/vts/OWNERS b/broadcastradio/2.0/vts/OWNERS
index 12adf57..1ff7407 100644
--- a/broadcastradio/2.0/vts/OWNERS
+++ b/broadcastradio/2.0/vts/OWNERS
@@ -3,5 +3,4 @@
 twasilczyk@google.com
 
 # VTS team
-yuexima@google.com
-yim@google.com
+dshi@google.com
diff --git a/broadcastradio/2.0/vts/functional/Android.bp b/broadcastradio/2.0/vts/functional/Android.bp
index 3e18a54..49bb665 100644
--- a/broadcastradio/2.0/vts/functional/Android.bp
+++ b/broadcastradio/2.0/vts/functional/Android.bp
@@ -17,9 +17,6 @@
 cc_test {
     name: "VtsHalBroadcastradioV2_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
-    cppflags: [
-        "-std=c++1z",
-    ],
     srcs: ["VtsHalBroadcastradioV2_0TargetTest.cpp"],
     static_libs: [
         "android.hardware.broadcastradio@2.0",
@@ -28,5 +25,8 @@
         "android.hardware.broadcastradio@vts-utils-lib",
         "libgmock",
     ],
-    test_suites: ["general-tests"],
+    test_suites: [
+        "general-tests",
+        "vts-core",
+    ],
 }
diff --git a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
index e36f4d9..d170a6d 100644
--- a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
+++ b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
@@ -16,7 +16,6 @@
 
 #define EGMOCK_VERBOSE 1
 
-#include <VtsHalHidlTargetTestBase.h>
 #include <android-base/logging.h>
 #include <android-base/strings.h>
 #include <android/hardware/broadcastradio/2.0/IBroadcastRadio.h>
@@ -25,11 +24,13 @@
 #include <android/hardware/broadcastradio/2.0/types.h>
 #include <broadcastradio-utils-2x/Utils.h>
 #include <broadcastradio-vts-utils/call-barrier.h>
-#include <broadcastradio-vts-utils/environment-utils.h>
 #include <broadcastradio-vts-utils/mock-timeout.h>
 #include <broadcastradio-vts-utils/pointer-utils.h>
 #include <cutils/bitops.h>
 #include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include <chrono>
 #include <optional>
@@ -52,7 +53,6 @@
 using testing::Invoke;
 using testing::SaveArg;
 
-using broadcastradio::vts::BroadcastRadioHidlEnvironment;
 using broadcastradio::vts::CallBarrier;
 using broadcastradio::vts::clearAndWait;
 using utils::make_identifier;
@@ -100,10 +100,8 @@
     MOCK_METHOD1(onListUpdated, Return<void>(const hidl_vec<Announcement>&));
 };
 
-static BroadcastRadioHidlEnvironment<IBroadcastRadio>* gEnv = nullptr;
-
-class BroadcastRadioHalTest : public ::testing::VtsHalHidlTargetTestBase {
-   protected:
+class BroadcastRadioHalTest : public ::testing::TestWithParam<std::string> {
+  protected:
     virtual void SetUp() override;
     virtual void TearDown() override;
 
@@ -185,7 +183,7 @@
     EXPECT_EQ(nullptr, mModule.get()) << "Module is already open";
 
     // lookup HIDL service (radio module)
-    mModule = getService<IBroadcastRadio>(gEnv->getServiceName<IBroadcastRadio>());
+    mModule = IBroadcastRadio::getService(GetParam());
     ASSERT_NE(nullptr, mModule.get()) << "Couldn't find broadcast radio HAL implementation";
 
     // get module properties
@@ -243,10 +241,10 @@
     auto startResult = mSession->startProgramListUpdates({});
     if (startResult == Result::NOT_SUPPORTED) {
         printSkipped("Program list not supported");
-        return nullopt;
+        return std::nullopt;
     }
     EXPECT_EQ(Result::OK, startResult);
-    if (startResult != Result::OK) return nullopt;
+    if (startResult != Result::OK) return std::nullopt;
 
     EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onProgramListReady, timeout::programListScan);
 
@@ -264,7 +262,7 @@
  *  - the method succeeds when called for the second time without
  *    closing previous session.
  */
-TEST_F(BroadcastRadioHalTest, OpenSession) {
+TEST_P(BroadcastRadioHalTest, OpenSession) {
     // simply open session for the first time
     ASSERT_TRUE(openSession());
 
@@ -308,7 +306,7 @@
  *  - all channel grids (frequency ranges and spacings) are valid;
  *  - seek spacing is a multiple of the manual spacing value.
  */
-TEST_F(BroadcastRadioHalTest, GetAmFmRegionConfig) {
+TEST_P(BroadcastRadioHalTest, GetAmFmRegionConfig) {
     AmFmRegionConfig config;
     bool supported = getAmFmRegionConfig(false, &config);
     if (!supported) {
@@ -341,7 +339,7 @@
  *  - all channel grids (frequency ranges and spacings) are valid;
  *  - seek spacing is not set.
  */
-TEST_F(BroadcastRadioHalTest, GetAmFmRegionConfigCapabilities) {
+TEST_P(BroadcastRadioHalTest, GetAmFmRegionConfigCapabilities) {
     AmFmRegionConfig config;
     bool supported = getAmFmRegionConfig(true, &config);
     if (!supported) {
@@ -369,7 +367,7 @@
  *  - all channel labels match correct format;
  *  - all channel frequencies are in correct range.
  */
-TEST_F(BroadcastRadioHalTest, GetDabRegionConfig) {
+TEST_P(BroadcastRadioHalTest, GetDabRegionConfig) {
     Result halResult;
     hidl_vec<DabTableEntry> config;
     auto cb = [&](Result result, hidl_vec<DabTableEntry> configCb) {
@@ -411,7 +409,7 @@
  *    invoked carrying a proper selector;
  *  - program changes exactly to what was requested.
  */
-TEST_F(BroadcastRadioHalTest, FmTune) {
+TEST_P(BroadcastRadioHalTest, FmTune) {
     ASSERT_TRUE(openSession());
 
     uint64_t freq = 100100;  // 100.1 FM
@@ -458,7 +456,7 @@
  *  - if the selector is not supported, it's ignored;
  *  - if it is supported, an invalid value results with INVALID_ARGUMENTS;
  */
-TEST_F(BroadcastRadioHalTest, TuneFailsWithInvalid) {
+TEST_P(BroadcastRadioHalTest, TuneFailsWithInvalid) {
     ASSERT_TRUE(openSession());
 
     vector<ProgramIdentifier> invalid = {
@@ -489,7 +487,7 @@
  * Verifies that:
  *  - tune fails with NOT_SUPPORTED when program selector is not initialized.
  */
-TEST_F(BroadcastRadioHalTest, TuneFailsWithEmpty) {
+TEST_P(BroadcastRadioHalTest, TuneFailsWithEmpty) {
     ASSERT_TRUE(openSession());
 
     // Program type is 1-based, so 0 will always be invalid.
@@ -506,7 +504,7 @@
  *  - the program info is changed within timeout::tune;
  *  - works both directions and with or without skipping sub-channel.
  */
-TEST_F(BroadcastRadioHalTest, Seek) {
+TEST_P(BroadcastRadioHalTest, Seek) {
     ASSERT_TRUE(openSession());
 
     // TODO(b/69958777): see FmTune workaround
@@ -531,7 +529,7 @@
  *  - the program info is changed within timeout::tune if the method succeeded;
  *  - works both directions.
  */
-TEST_F(BroadcastRadioHalTest, Step) {
+TEST_P(BroadcastRadioHalTest, Step) {
     ASSERT_TRUE(openSession());
 
     // TODO(b/69958777): see FmTune workaround
@@ -558,7 +556,7 @@
  * Verifies that:
  *  - the method does not crash after being invoked multiple times.
  */
-TEST_F(BroadcastRadioHalTest, Cancel) {
+TEST_P(BroadcastRadioHalTest, Cancel) {
     ASSERT_TRUE(openSession());
 
     for (int i = 0; i < 10; i++) {
@@ -576,7 +574,7 @@
  * Verifies that:
  *  - callback is called for empty parameters set.
  */
-TEST_F(BroadcastRadioHalTest, NoParameters) {
+TEST_P(BroadcastRadioHalTest, NoParameters) {
     ASSERT_TRUE(openSession());
 
     hidl_vec<VendorKeyValue> halResults = {};
@@ -605,7 +603,7 @@
  *  - unknown parameters are ignored;
  *  - callback is called also for empty results set.
  */
-TEST_F(BroadcastRadioHalTest, UnknownParameters) {
+TEST_P(BroadcastRadioHalTest, UnknownParameters) {
     ASSERT_TRUE(openSession());
 
     hidl_vec<VendorKeyValue> halResults = {};
@@ -633,7 +631,7 @@
  * Verifies that:
  *  - the method does not crash after being invoked multiple times.
  */
-TEST_F(BroadcastRadioHalTest, Close) {
+TEST_P(BroadcastRadioHalTest, Close) {
     ASSERT_TRUE(openSession());
 
     for (int i = 0; i < 10; i++) {
@@ -648,7 +646,7 @@
  * Verifies that:
  * - getImage call handles argument 0 gracefully.
  */
-TEST_F(BroadcastRadioHalTest, GetNoImage) {
+TEST_P(BroadcastRadioHalTest, GetNoImage) {
     size_t len = 0;
     auto result = mModule->getImage(0, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
 
@@ -663,7 +661,7 @@
  * - isConfigFlagSet either succeeds or ends with NOT_SUPPORTED or INVALID_STATE;
  * - call success or failure is consistent with setConfigFlag.
  */
-TEST_F(BroadcastRadioHalTest, FetchConfigFlags) {
+TEST_P(BroadcastRadioHalTest, FetchConfigFlags) {
     ASSERT_TRUE(openSession());
 
     for (auto flag : gConfigFlagValues) {
@@ -691,7 +689,7 @@
  * - setConfigFlag either succeeds or ends with NOT_SUPPORTED or INVALID_STATE;
  * - isConfigFlagSet reflects the state requested immediately after the set call.
  */
-TEST_F(BroadcastRadioHalTest, SetConfigFlags) {
+TEST_P(BroadcastRadioHalTest, SetConfigFlags) {
     ASSERT_TRUE(openSession());
 
     auto get = [&](ConfigFlag flag) {
@@ -743,7 +741,7 @@
  * - the complete list is fetched within timeout::programListScan;
  * - stopProgramListUpdates does not crash.
  */
-TEST_F(BroadcastRadioHalTest, GetProgramList) {
+TEST_P(BroadcastRadioHalTest, GetProgramList) {
     ASSERT_TRUE(openSession());
 
     getProgramList();
@@ -757,7 +755,7 @@
  *  - the identifier matches the name;
  *  - there is only one identifier of that type.
  */
-TEST_F(BroadcastRadioHalTest, HdRadioStationNameId) {
+TEST_P(BroadcastRadioHalTest, HdRadioStationNameId) {
     ASSERT_TRUE(openSession());
 
     auto list = getProgramList();
@@ -785,7 +783,7 @@
  *  - if it succeeds, it returns a valid close handle (which is a nullptr otherwise);
  *  - closing handle does not crash.
  */
-TEST_F(BroadcastRadioHalTest, AnnouncementListenerRegistration) {
+TEST_P(BroadcastRadioHalTest, AnnouncementListenerRegistration) {
     sp<AnnouncementListenerMock> listener = new AnnouncementListenerMock();
 
     Result halResult = Result::UNKNOWN_ERROR;
@@ -811,6 +809,11 @@
     closeHandle->close();
 }
 
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, BroadcastRadioHalTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IBroadcastRadio::descriptor)),
+        android::hardware::PrintInstanceNameToString);
+
 }  // namespace vts
 }  // namespace V2_0
 }  // namespace broadcastradio
@@ -818,14 +821,8 @@
 }  // namespace android
 
 int main(int argc, char** argv) {
-    using android::hardware::broadcastradio::V2_0::vts::gEnv;
-    using android::hardware::broadcastradio::V2_0::IBroadcastRadio;
-    using android::hardware::broadcastradio::vts::BroadcastRadioHidlEnvironment;
     android::base::SetDefaultTag("BcRadio.vts");
     android::base::SetMinimumLogSeverity(android::base::VERBOSE);
-    gEnv = new BroadcastRadioHidlEnvironment<IBroadcastRadio>;
-    ::testing::AddGlobalTestEnvironment(gEnv);
     ::testing::InitGoogleTest(&argc, argv);
-    gEnv->init(&argc, argv);
     return RUN_ALL_TESTS();
 }
diff --git a/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/pointer-utils.h b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/pointer-utils.h
index 0b6f5eb..1d76008 100644
--- a/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/pointer-utils.h
+++ b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/pointer-utils.h
@@ -19,6 +19,8 @@
 #include <chrono>
 #include <thread>
 
+using namespace std::chrono_literals;
+
 namespace android {
 namespace hardware {
 namespace broadcastradio {
diff --git a/graphics/composer/2.4/IComposerClient.hal b/graphics/composer/2.4/IComposerClient.hal
index f23536c..06b4c5e 100644
--- a/graphics/composer/2.4/IComposerClient.hal
+++ b/graphics/composer/2.4/IComposerClient.hal
@@ -48,6 +48,12 @@
          * with protected buffers.
          */
         PROTECTED_CONTENTS = 4,
+
+        /**
+         * Indicates that both the composer HAL implementation and the given display
+         * support a low latency mode, such as HDMI 2.1 Auto Low Latency Mode.
+         */
+        AUTO_LOW_LATENCY_MODE = 5,
     };
 
     /**
@@ -64,6 +70,18 @@
         EXTERNAL = 1,
     };
 
+    enum ContentType : uint32_t {
+        NONE = 0,
+
+        /**
+         * These modes correspond to those found in the HDMI 1.4 specification.
+         */
+        GRAPHICS = 1,
+        PHOTO = 2,
+        CINEMA = 3,
+        GAME = 4,
+    };
+
     /**
      * Constraints for changing vsync period.
      */
@@ -172,4 +190,60 @@
     setActiveConfigWithConstraints(Display display, Config config,
         VsyncPeriodChangeConstraints vsyncPeriodChangeConstraints)
         generates (Error error, VsyncPeriodChangeTimeline timeline);
+
+    /**
+     * Requests the display to enable/disable its low latency mode.
+     *
+     * If the display is connected via HDMI 2.1, then Auto Low Latency Mode should be triggered. If
+     * the display is internally connected and a custom low latency mode is available, that should
+     * be triggered.
+     *
+     * This function should only be called if the display reports support for
+     * DisplayCapability::AUTO_LOW_LATENCY_MODE from getDisplayCapabilities_2_4.
+     *
+     * @return error is NONE upon success. Otherwise,
+     *     BAD_DISPLAY when an invalid display handle was passed in.
+     *     UNSUPPORTED when AUTO_LOW_LATENCY_MODE is not supported by the composer
+     *         implementation or the given display
+     */
+    setAutoLowLatencyMode(Display display, bool on)
+        generates (Error error);
+
+    /**
+     * Provides a list of all the content types supported by this display (any of
+     * ContentType::{GRAPHICS, PHOTO, CINEMA, GAME}). This list must not change after
+     * initialization.
+     *
+     * Content types are introduced in HDMI 1.4 and supporting them is optional. The
+     * ContentType::NONE is always supported and will not be returned by this method..
+     *
+     * @return error is NONE upon success. Otherwise,
+     *     BAD_DISPLAY when an invalid display handle was passed in.
+     * @return supportedContentTypes is a list of supported content types.
+     */
+    getSupportedContentTypes(Display display)
+        generates(Error error, vec<ContentType> supportedContentTypes);
+
+    /**
+     * Instructs the connected display that the content being shown is of the given type - one of
+     * GRAPHICS, PHOTO, CINEMA, GAME.
+     *
+     * Content types are introduced in HDMI 1.4 and supporting them is optional. If they are
+     * supported, this signal should switch the display to a mode that is optimal for the given
+     * type of content. See HDMI 1.4 specification for more information.
+     *
+     * If the display is internally connected (not through HDMI), and such modes are available,
+     * this method should trigger them.
+     *
+     * This function should only be called if the display reports support for the corresponding
+     * content type (ContentType::{GRAPHICS, PHOTO, CINEMA, GAME}) from getSupportedContentTypes.
+     * ContentType::NONE is supported by default and can always be set.
+     *
+     * @return error is NONE upon success. Otherwise,
+     *     BAD_DISPLAY when an invalid display handle was passed in.
+     *     UNSUPPORTED when the given content type is not supported by the composer
+     *         implementation or the given display
+     */
+    setContentType(Display display, ContentType type)
+        generates (Error error);
 };
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 4160ed9..dcd959d 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
@@ -139,6 +139,24 @@
         return Void();
     }
 
+    Return<Error> setAutoLowLatencyMode(Display display, bool on) override {
+        return mHal->setAutoLowLatencyMode(display, on);
+    }
+
+    Return<void> getSupportedContentTypes(
+            Display display, IComposerClient::getSupportedContentTypes_cb hidl_cb) override {
+        std::vector<IComposerClient::ContentType> supportedContentTypes;
+        Error error = mHal->getSupportedContentTypes(display, &supportedContentTypes);
+
+        hidl_cb(error, supportedContentTypes);
+        return Void();
+    }
+
+    Return<Error> setContentType(Display display,
+                                 IComposerClient::ContentType contentType) override {
+        return mHal->setContentType(display, contentType);
+    }
+
     static std::unique_ptr<ComposerClientImpl> create(Hal* hal) {
         auto client = std::make_unique<ComposerClientImpl>(hal);
         return client->init() ? std::move(client) : nullptr;
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 89dbe66..a1e56ae 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
@@ -67,6 +67,11 @@
             Display display, Config config,
             const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
             VsyncPeriodChangeTimeline* timeline) = 0;
+    virtual Error setAutoLowLatencyMode(Display display, bool on) = 0;
+    virtual Error getSupportedContentTypes(
+            Display display,
+            std::vector<IComposerClient::ContentType>* outSupportedContentTypes) = 0;
+    virtual Error setContentType(Display display, IComposerClient::ContentType contentType) = 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 d59d0d5..a27582a 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
@@ -167,6 +167,57 @@
         return Error::NONE;
     }
 
+    Error setAutoLowLatencyMode(Display display, bool on) override {
+        if (!mDispatch.setAutoLowLatencyMode) {
+            return Error::UNSUPPORTED;
+        }
+
+        int32_t error = mDispatch.setAutoLowLatencyMode(mDevice, display, on);
+        if (error != HWC2_ERROR_NONE) {
+            return static_cast<Error>(error);
+        }
+        return Error::NONE;
+    }
+
+    Error getSupportedContentTypes(
+            Display display,
+            std::vector<IComposerClient::ContentType>* outSupportedContentTypes) override {
+        if (!mDispatch.getSupportedContentTypes) {
+            return Error::UNSUPPORTED;
+        }
+
+        uint32_t count = 0;
+        int32_t error = mDispatch.getSupportedContentTypes(mDevice, display, &count, nullptr);
+        if (error != HWC2_ERROR_NONE) {
+            return static_cast<Error>(error);
+        }
+
+        outSupportedContentTypes->resize(count);
+
+        error = mDispatch.getSupportedContentTypes(
+                mDevice, display, &count,
+                reinterpret_cast<std::underlying_type<IComposerClient::ContentType>::type*>(
+                        outSupportedContentTypes->data()));
+        if (error != HWC2_ERROR_NONE) {
+            *outSupportedContentTypes = std::vector<IComposerClient::ContentType>();
+            return static_cast<Error>(error);
+        }
+        return Error::NONE;
+    }
+
+    Error setContentType(Display display, IComposerClient::ContentType contentType) override {
+        if (!mDispatch.setContentType) {
+            return Error::UNSUPPORTED;
+        }
+
+        int32_t error =
+                mDispatch.setContentType(mDevice, display, static_cast<int32_t>(contentType));
+        if (error != HWC2_ERROR_NONE) {
+            return static_cast<Error>(error);
+        }
+        return Error::NONE;
+    }
+
   protected:
     bool initDispatch() override {
         if (!BaseType2_3::initDispatch()) {
@@ -179,6 +230,11 @@
                                    &mDispatch.getDisplayVsyncPeriod);
         this->initOptionalDispatch(HWC2_FUNCTION_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS,
                                    &mDispatch.setActiveConfigWithConstraints);
+        this->initOptionalDispatch(HWC2_FUNCTION_SET_AUTO_LOW_LATENCY_MODE,
+                                   &mDispatch.setAutoLowLatencyMode);
+        this->initOptionalDispatch(HWC2_FUNCTION_GET_SUPPORTED_CONTENT_TYPES,
+                                   &mDispatch.getSupportedContentTypes);
+        this->initOptionalDispatch(HWC2_FUNCTION_SET_CONTENT_TYPE, &mDispatch.setContentType);
         return true;
     }
 
@@ -222,6 +278,9 @@
         HWC2_PFN_GET_DISPLAY_CONNECTION_TYPE getDisplayConnectionType;
         HWC2_PFN_GET_DISPLAY_VSYNC_PERIOD getDisplayVsyncPeriod;
         HWC2_PFN_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS setActiveConfigWithConstraints;
+        HWC2_PFN_SET_AUTO_LOW_LATENCY_MODE setAutoLowLatencyMode;
+        HWC2_PFN_GET_SUPPORTED_CONTENT_TYPES getSupportedContentTypes;
+        HWC2_PFN_SET_CONTENT_TYPE setContentType;
     } 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 35ac23f..5b06d6d 100644
--- a/graphics/composer/2.4/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.4/utils/vts/ComposerVts.cpp
@@ -106,6 +106,25 @@
     return error;
 }
 
+Error ComposerClient::setAutoLowLatencyMode(Display display, bool on) {
+    return mClient->setAutoLowLatencyMode(display, on);
+}
+
+Error ComposerClient::getSupportedContentTypes(
+        Display display, std::vector<IComposerClient::ContentType>* outSupportedContentTypes) {
+    Error error = Error::NONE;
+    mClient->getSupportedContentTypes(
+            display, [&](const auto& tmpError, const auto& tmpSupportedContentTypes) {
+                error = tmpError;
+                *outSupportedContentTypes = tmpSupportedContentTypes;
+            });
+    return error;
+}
+
+Error ComposerClient::setContentType(Display display, IComposerClient::ContentType contentType) {
+    return mClient->setContentType(display, contentType);
+}
+
 }  // namespace vts
 }  // namespace V2_4
 }  // namespace composer
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 83e74ed..b094bc8 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
@@ -84,6 +84,13 @@
             const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
             VsyncPeriodChangeTimeline* timeline);
 
+    Error setAutoLowLatencyMode(Display display, bool on);
+
+    Error getSupportedContentTypes(
+            Display display, std::vector<IComposerClient::ContentType>* outSupportedContentTypes);
+
+    Error setContentType(Display display, IComposerClient::ContentType contentType);
+
   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 f038f55..6b6f2a5 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -47,6 +47,9 @@
 using mapper::V2_0::IMapper;
 using mapper::V2_0::vts::Gralloc;
 
+using ContentType = IComposerClient::ContentType;
+using DisplayCapability = IComposerClient::DisplayCapability;
+
 class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> {
   protected:
     void SetUp() override {
@@ -117,6 +120,11 @@
     void Test_setActiveConfigWithConstraints(
             const IComposerClient::VsyncPeriodChangeConstraints& constraints);
 
+    void Test_setContentType(const ContentType& contentType, const char* contentTypeStr);
+    void Test_setContentTypeForDisplay(const Display& display,
+                                       const std::vector<ContentType>& capabilities,
+                                       const ContentType& contentType, const char* contentTypeStr);
+
     std::unique_ptr<Composer> mComposer;
     std::unique_ptr<ComposerClient> mComposerClient;
     sp<V2_1::vts::GraphicsComposerCallback> mComposerCallback;
@@ -377,6 +385,117 @@
     Test_setActiveConfigWithConstraints(constraints);
 }
 
+TEST_P(GraphicsComposerHidlTest, setAutoLowLatencyModeBadDisplay) {
+    EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->setAutoLowLatencyMode(mInvalidDisplayId, true));
+    EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->setAutoLowLatencyMode(mInvalidDisplayId, false));
+}
+
+TEST_P(GraphicsComposerHidlTest, setAutoLowLatencyMode) {
+    for (Display display : mComposerCallback->getDisplays()) {
+        std::vector<DisplayCapability> capabilities;
+        const auto error = mComposerClient->getDisplayCapabilities(display, &capabilities);
+        EXPECT_EQ(Error::NONE, error);
+
+        const bool allmSupport =
+                std::find(capabilities.begin(), capabilities.end(),
+                          DisplayCapability::AUTO_LOW_LATENCY_MODE) != capabilities.end();
+
+        if (!allmSupport) {
+            EXPECT_EQ(Error::UNSUPPORTED,
+                      mComposerClient->setAutoLowLatencyMode(mPrimaryDisplay, true));
+            EXPECT_EQ(Error::UNSUPPORTED,
+                      mComposerClient->setAutoLowLatencyMode(mPrimaryDisplay, false));
+            GTEST_SUCCEED() << "Auto Low Latency Mode is not supported on display "
+                            << to_string(display) << ", skipping test";
+            return;
+        }
+
+        EXPECT_EQ(Error::NONE, mComposerClient->setAutoLowLatencyMode(mPrimaryDisplay, true));
+        EXPECT_EQ(Error::NONE, mComposerClient->setAutoLowLatencyMode(mPrimaryDisplay, false));
+    }
+}
+
+TEST_P(GraphicsComposerHidlTest, getSupportedContentTypesBadDisplay) {
+    std::vector<ContentType> supportedContentTypes;
+    const auto error =
+            mComposerClient->getSupportedContentTypes(mInvalidDisplayId, &supportedContentTypes);
+    EXPECT_EQ(Error::BAD_DISPLAY, error);
+}
+
+TEST_P(GraphicsComposerHidlTest, getSupportedContentTypes) {
+    std::vector<ContentType> supportedContentTypes;
+    for (Display display : mComposerCallback->getDisplays()) {
+        supportedContentTypes.clear();
+        const auto error =
+                mComposerClient->getSupportedContentTypes(display, &supportedContentTypes);
+        const bool noneSupported =
+                std::find(supportedContentTypes.begin(), supportedContentTypes.end(),
+                          ContentType::NONE) != supportedContentTypes.end();
+        EXPECT_EQ(Error::NONE, error);
+        EXPECT_FALSE(noneSupported);
+    }
+}
+
+TEST_P(GraphicsComposerHidlTest, setContentTypeNoneAlwaysAccepted) {
+    for (Display display : mComposerCallback->getDisplays()) {
+        const auto error = mComposerClient->setContentType(display, ContentType::NONE);
+        EXPECT_NE(Error::UNSUPPORTED, error);
+    }
+}
+
+TEST_P(GraphicsComposerHidlTest, setContentTypeBadDisplay) {
+    const auto types = {ContentType::NONE, ContentType::GRAPHICS, ContentType::PHOTO,
+                        ContentType::CINEMA, ContentType::GAME};
+    for (auto type : types) {
+        EXPECT_EQ(Error::BAD_DISPLAY, mComposerClient->setContentType(mInvalidDisplayId, type));
+    }
+}
+
+void GraphicsComposerHidlTest::Test_setContentTypeForDisplay(
+        const Display& display, const std::vector<ContentType>& capabilities,
+        const ContentType& contentType, const char* contentTypeStr) {
+    const bool contentTypeSupport =
+            std::find(capabilities.begin(), capabilities.end(), contentType) != capabilities.end();
+
+    if (!contentTypeSupport) {
+        EXPECT_EQ(Error::UNSUPPORTED, mComposerClient->setContentType(display, contentType));
+        GTEST_SUCCEED() << contentTypeStr << " content type is not supported on display "
+                        << to_string(display) << ", skipping test";
+        return;
+    }
+
+    EXPECT_EQ(Error::NONE, mComposerClient->setContentType(display, contentType));
+    EXPECT_EQ(Error::NONE, mComposerClient->setContentType(display, ContentType::NONE));
+}
+
+void GraphicsComposerHidlTest::Test_setContentType(const ContentType& contentType,
+                                                   const char* contentTypeStr) {
+    for (Display display : mComposerCallback->getDisplays()) {
+        std::vector<ContentType> supportedContentTypes;
+        const auto error =
+                mComposerClient->getSupportedContentTypes(display, &supportedContentTypes);
+        EXPECT_EQ(Error::NONE, error);
+
+        Test_setContentTypeForDisplay(display, supportedContentTypes, contentType, contentTypeStr);
+    }
+}
+
+TEST_P(GraphicsComposerHidlTest, setGraphicsContentType) {
+    Test_setContentType(ContentType::GRAPHICS, "GRAPHICS");
+}
+
+TEST_P(GraphicsComposerHidlTest, setPhotoContentType) {
+    Test_setContentType(ContentType::PHOTO, "PHOTO");
+}
+
+TEST_P(GraphicsComposerHidlTest, setCinemaContentType) {
+    Test_setContentType(ContentType::CINEMA, "CINEMA");
+}
+
+TEST_P(GraphicsComposerHidlTest, setGameContentType) {
+    Test_setContentType(ContentType::GAME, "GAME");
+}
+
 INSTANTIATE_TEST_SUITE_P(
         PerInstance, GraphicsComposerHidlTest,
         testing::ValuesIn(android::hardware::getAllHalInstanceNames(IComposer::descriptor)),
diff --git a/wifi/1.4/Android.bp b/wifi/1.4/Android.bp
index b443230..3b94619 100644
--- a/wifi/1.4/Android.bp
+++ b/wifi/1.4/Android.bp
@@ -15,7 +15,6 @@
         "IWifiNanIface.hal",
         "IWifiRttController.hal",
         "IWifiRttControllerEventCallback.hal",
-        "IWifiStaIface.hal",
     ],
     interfaces: [
         "android.hardware.wifi@1.0",
diff --git a/wifi/1.4/IWifiStaIface.hal b/wifi/1.4/IWifiStaIface.hal
deleted file mode 100644
index 8bb0de8..0000000
--- a/wifi/1.4/IWifiStaIface.hal
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.wifi@1.4;
-
-import @1.0::WifiStatus;
-import @1.0::MacAddress;
-import @1.0::IWifiStaIface;
-import @1.3::IWifiStaIface;
-
-/**
- * Interface used to represent a single STA iface.
- *
- * IWifiChip.createStaIface() may return a @1.4::IWifiStaIface when supported.
- */
-interface IWifiStaIface extends @1.3::IWifiStaIface {
-    enum StaIfaceCapabilityMask : @1.0::IWifiStaIface.StaIfaceCapabilityMask {
-        STA_6G = 1 << 15,
-    };
-
-    /**
-     * Get the capabilities supported by this STA iface.
-     *
-     * @return status WifiStatus of the operation.
-     *         Possible status codes:
-     *         |WifiStatusCode.SUCCESS|,
-     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
-     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|,
-     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
-     *         |WifiStatusCode.ERROR_UNKNOWN|
-     * @return capabilities Bitset of |StaIfaceCapabilityMask| values.
-     */
-    getCapabilities_1_4()
-        generates (WifiStatus status, bitfield<StaIfaceCapabilityMask> capabilities);
-};
diff --git a/wifi/1.4/default/hidl_struct_util.cpp b/wifi/1.4/default/hidl_struct_util.cpp
index 45ffdde..4996e35 100644
--- a/wifi/1.4/default/hidl_struct_util.cpp
+++ b/wifi/1.4/default/hidl_struct_util.cpp
@@ -120,8 +120,6 @@
             return HidlStaIfaceCaps::ND_OFFLOAD;
         case WIFI_FEATURE_MKEEP_ALIVE:
             return HidlStaIfaceCaps::KEEP_ALIVE;
-        case WIFI_FEATURE_INFRA_6G:
-            return HidlStaIfaceCaps::STA_6G;
     };
     CHECK(false) << "Unknown legacy feature: " << feature;
     return {};
@@ -394,8 +392,7 @@
           WIFI_FEATURE_IE_WHITELIST, WIFI_FEATURE_SCAN_RAND,
           WIFI_FEATURE_INFRA_5G, WIFI_FEATURE_HOTSPOT, WIFI_FEATURE_PNO,
           WIFI_FEATURE_TDLS, WIFI_FEATURE_TDLS_OFFCHANNEL,
-          WIFI_FEATURE_CONFIG_NDO, WIFI_FEATURE_MKEEP_ALIVE,
-          WIFI_FEATURE_INFRA_6G}) {
+          WIFI_FEATURE_CONFIG_NDO, WIFI_FEATURE_MKEEP_ALIVE}) {
         if (feature & legacy_feature_set) {
             *hidl_caps |= convertLegacyFeatureToHidlStaIfaceCapability(feature);
         }
diff --git a/wifi/1.4/default/hidl_struct_util.h b/wifi/1.4/default/hidl_struct_util.h
index 160870a..d040c1f 100644
--- a/wifi/1.4/default/hidl_struct_util.h
+++ b/wifi/1.4/default/hidl_struct_util.h
@@ -25,7 +25,6 @@
 #include <android/hardware/wifi/1.3/IWifiChip.h>
 #include <android/hardware/wifi/1.3/types.h>
 #include <android/hardware/wifi/1.4/IWifiChipEventCallback.h>
-#include <android/hardware/wifi/1.4/IWifiStaIface.h>
 #include <android/hardware/wifi/1.4/types.h>
 
 #include "wifi_legacy_hal.h"
diff --git a/wifi/1.4/default/wifi_chip.cpp b/wifi/1.4/default/wifi_chip.cpp
index 2b015d3..a70457b 100644
--- a/wifi/1.4/default/wifi_chip.cpp
+++ b/wifi/1.4/default/wifi_chip.cpp
@@ -938,7 +938,8 @@
     return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 
-std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::createStaIfaceInternal() {
+std::pair<WifiStatus, sp<V1_3::IWifiStaIface>>
+WifiChip::createStaIfaceInternal() {
     if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::STA)) {
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
@@ -962,7 +963,7 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(sta_ifaces_)};
 }
 
-std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::getStaIfaceInternal(
+std::pair<WifiStatus, sp<V1_3::IWifiStaIface>> WifiChip::getStaIfaceInternal(
     const std::string& ifname) {
     const auto iface = findUsingName(sta_ifaces_, ifname);
     if (!iface.get()) {
diff --git a/wifi/1.4/default/wifi_chip.h b/wifi/1.4/default/wifi_chip.h
index c76eabf..3323ade 100644
--- a/wifi/1.4/default/wifi_chip.h
+++ b/wifi/1.4/default/wifi_chip.h
@@ -197,9 +197,9 @@
     std::pair<WifiStatus, sp<IWifiP2pIface>> getP2pIfaceInternal(
         const std::string& ifname);
     WifiStatus removeP2pIfaceInternal(const std::string& ifname);
-    std::pair<WifiStatus, sp<IWifiStaIface>> createStaIfaceInternal();
+    std::pair<WifiStatus, sp<V1_3::IWifiStaIface>> createStaIfaceInternal();
     std::pair<WifiStatus, std::vector<hidl_string>> getStaIfaceNamesInternal();
-    std::pair<WifiStatus, sp<IWifiStaIface>> getStaIfaceInternal(
+    std::pair<WifiStatus, sp<V1_3::IWifiStaIface>> getStaIfaceInternal(
         const std::string& ifname);
     WifiStatus removeStaIfaceInternal(const std::string& ifname);
     std::pair<WifiStatus, sp<V1_0::IWifiRttController>>
diff --git a/wifi/1.4/default/wifi_sta_iface.cpp b/wifi/1.4/default/wifi_sta_iface.cpp
index 68c989d..e2ea6e4 100644
--- a/wifi/1.4/default/wifi_sta_iface.cpp
+++ b/wifi/1.4/default/wifi_sta_iface.cpp
@@ -266,13 +266,6 @@
                            hidl_status_cb);
 }
 
-Return<void> WifiStaIface::getCapabilities_1_4(
-    getCapabilities_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                           &WifiStaIface::getCapabilitiesInternal_1_4,
-                           hidl_status_cb);
-}
-
 std::pair<WifiStatus, std::string> WifiStaIface::getNameInternal() {
     return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
 }
@@ -290,7 +283,26 @@
 }
 
 std::pair<WifiStatus, uint32_t> WifiStaIface::getCapabilitiesInternal() {
-    return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), 0};
+    legacy_hal::wifi_error legacy_status;
+    uint64_t legacy_feature_set;
+    std::tie(legacy_status, legacy_feature_set) =
+        legacy_hal_.lock()->getSupportedFeatureSet(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), 0};
+    }
+    uint32_t legacy_logger_feature_set;
+    std::tie(legacy_status, legacy_logger_feature_set) =
+        legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        // some devices don't support querying logger feature set
+        legacy_logger_feature_set = 0;
+    }
+    uint32_t hidl_caps;
+    if (!hidl_struct_util::convertLegacyFeaturesToHidlStaCapabilities(
+            legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
 }
 
 std::pair<WifiStatus, StaApfPacketFilterCapabilities>
@@ -628,29 +640,6 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), mac};
 }
 
-std::pair<WifiStatus, uint32_t> WifiStaIface::getCapabilitiesInternal_1_4() {
-    legacy_hal::wifi_error legacy_status;
-    uint64_t legacy_feature_set;
-    std::tie(legacy_status, legacy_feature_set) =
-        legacy_hal_.lock()->getSupportedFeatureSet(ifname_);
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        return {createWifiStatusFromLegacyError(legacy_status), 0};
-    }
-    uint32_t legacy_logger_feature_set;
-    std::tie(legacy_status, legacy_logger_feature_set) =
-        legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname_);
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        // some devices don't support querying logger feature set
-        legacy_logger_feature_set = 0;
-    }
-    uint32_t hidl_caps;
-    if (!hidl_struct_util::convertLegacyFeaturesToHidlStaCapabilities(
-            legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) {
-        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0};
-    }
-    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
-}
-
 }  // namespace implementation
 }  // namespace V1_4
 }  // namespace wifi
diff --git a/wifi/1.4/default/wifi_sta_iface.h b/wifi/1.4/default/wifi_sta_iface.h
index e85e39d..dee04f2 100644
--- a/wifi/1.4/default/wifi_sta_iface.h
+++ b/wifi/1.4/default/wifi_sta_iface.h
@@ -19,7 +19,7 @@
 
 #include <android-base/macros.h>
 #include <android/hardware/wifi/1.0/IWifiStaIfaceEventCallback.h>
-#include <android/hardware/wifi/1.4/IWifiStaIface.h>
+#include <android/hardware/wifi/1.3/IWifiStaIface.h>
 
 #include "hidl_callback_util.h"
 #include "wifi_iface_util.h"
@@ -35,7 +35,7 @@
 /**
  * HIDL interface object used to control a STA Iface instance.
  */
-class WifiStaIface : public V1_4::IWifiStaIface {
+class WifiStaIface : public V1_3::IWifiStaIface {
    public:
     WifiStaIface(const std::string& ifname,
                  const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
@@ -112,8 +112,6 @@
                                setMacAddress_cb hidl_status_cb) override;
     Return<void> getFactoryMacAddress(
         getFactoryMacAddress_cb hidl_status_cb) override;
-    Return<void> getCapabilities_1_4(
-        getCapabilities_1_4_cb hidl_status_cb) override;
 
    private:
     // Corresponding worker functions for the HIDL methods.
@@ -162,7 +160,6 @@
     WifiStatus setMacAddressInternal(const std::array<uint8_t, 6>& mac);
     std::pair<WifiStatus, std::array<uint8_t, 6>>
     getFactoryMacAddressInternal();
-    std::pair<WifiStatus, uint32_t> getCapabilitiesInternal_1_4();
 
     std::string ifname_;
     std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
diff --git a/wifi/1.4/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_sta_iface_hidl_test.cpp
deleted file mode 100644
index ec4b2c9..0000000
--- a/wifi/1.4/vts/functional/wifi_sta_iface_hidl_test.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Staache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-
-#include <android/hardware/wifi/1.4/IWifiStaIface.h>
-
-#include <VtsHalHidlTargetTestBase.h>
-
-#include "wifi_hidl_call_util.h"
-#include "wifi_hidl_test_utils.h"
-
-using ::android::sp;
-using ::android::hardware::hidl_array;
-using ::android::hardware::wifi::V1_0::WifiStatus;
-using ::android::hardware::wifi::V1_0::WifiStatusCode;
-using ::android::hardware::wifi::V1_4::IWifiStaIface;
-
-/**
- * Fixture to use for all STA Iface HIDL interface tests.
- */
-class WifiStaIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-   public:
-    virtual void SetUp() override {
-        wifi_sta_iface_ = IWifiStaIface::castFrom(getWifiStaIface());
-        ASSERT_NE(nullptr, wifi_sta_iface_.get());
-    }
-
-    virtual void TearDown() override { stopWifi(); }
-
-   protected:
-    sp<IWifiStaIface> wifi_sta_iface_;
-};
-
-/*
- * GetCapabilities_1_4
- */
-TEST_F(WifiStaIfaceHidlTest, GetCapabilities_1_4) {
-    configureChipForIfaceType(IfaceType::STA, true);
-
-    const auto& status_and_caps =
-        HIDL_INVOKE(wifi_sta_iface_, getCapabilities_1_4);
-    if (status_and_caps.first.code != WifiStatusCode::SUCCESS) {
-        EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED,
-                  status_and_caps.first.code);
-        return;
-    }
-    EXPECT_NE(0u, status_and_caps.second);
-}