Merge "gralloc4-vts: fix Lock_YCBCR_420_888 test" into rvc-dev
diff --git a/audio/core/all-versions/default/StreamOut.cpp b/audio/core/all-versions/default/StreamOut.cpp
index 150d641..1519c48 100644
--- a/audio/core/all-versions/default/StreamOut.cpp
+++ b/audio/core/all-versions/default/StreamOut.cpp
@@ -455,20 +455,22 @@
     sp<IStreamOutCallback> callback = self->mCallback;
     if (callback.get() == nullptr) return 0;
     ALOGV("asyncCallback() event %d", event);
+    Return<void> result;
     switch (event) {
         case STREAM_CBK_EVENT_WRITE_READY:
-            callback->onWriteReady();
+            result = callback->onWriteReady();
             break;
         case STREAM_CBK_EVENT_DRAIN_READY:
-            callback->onDrainReady();
+            result = callback->onDrainReady();
             break;
         case STREAM_CBK_EVENT_ERROR:
-            callback->onError();
+            result = callback->onError();
             break;
         default:
             ALOGW("asyncCallback() unknown event %d", event);
             break;
     }
+    ALOGW_IF(!result.isOk(), "Client callback failed: %s", result.description().c_str());
     return 0;
 }
 
@@ -629,16 +631,18 @@
     sp<IStreamOutEventCallback> eventCallback = self->mEventCallback;
     if (eventCallback.get() == nullptr) return 0;
     ALOGV("%s event %d", __func__, event);
+    Return<void> result;
     switch (event) {
         case STREAM_EVENT_CBK_TYPE_CODEC_FORMAT_CHANGED: {
             hidl_vec<uint8_t> audioMetadata;
             audioMetadata.setToExternal((uint8_t*)param, strlen((char*)param));
-            eventCallback->onCodecFormatChanged(audioMetadata);
+            result = eventCallback->onCodecFormatChanged(audioMetadata);
         } break;
         default:
             ALOGW("%s unknown event %d", __func__, event);
             break;
     }
+    ALOGW_IF(!result.isOk(), "Client callback failed: %s", result.description().c_str());
     return 0;
 }
 #endif
diff --git a/audio/core/all-versions/vts/functional/ConfigHelper.h b/audio/core/all-versions/vts/functional/ConfigHelper.h
index a2f4116..8ef2b43 100644
--- a/audio/core/all-versions/vts/functional/ConfigHelper.h
+++ b/audio/core/all-versions/vts/functional/ConfigHelper.h
@@ -40,7 +40,7 @@
             return devs.getDevice(AUDIO_DEVICE_IN_BUILTIN_MIC, {}, AUDIO_FORMAT_DEFAULT);
         };
         auto primaryMic = getMic(policyConfig.getPrimaryModule()->getDeclaredDevices());
-        auto availableMic = getMic(policyConfig.getAvailableInputDevices());
+        auto availableMic = getMic(policyConfig.getInputDevices());
 
         return primaryMic != nullptr && primaryMic->equals(availableMic);
     }
diff --git a/audio/effect/all-versions/vts/functional/ValidateAudioEffectsConfiguration.cpp b/audio/effect/all-versions/vts/functional/ValidateAudioEffectsConfiguration.cpp
index f9e4aa3..9c0135b 100644
--- a/audio/effect/all-versions/vts/functional/ValidateAudioEffectsConfiguration.cpp
+++ b/audio/effect/all-versions/vts/functional/ValidateAudioEffectsConfiguration.cpp
@@ -18,6 +18,12 @@
 #include <iterator>
 
 #include <media/EffectsConfig.h>
+// clang-format off
+#include PATH(android/hardware/audio/effect/FILE_VERSION/IEffectsFactory.h)
+// clang-format on
+
+#include <gtest/gtest.h>
+#include <hidl/ServiceManagement.h>
 
 #include "utility/ValidateXml.h"
 
@@ -29,6 +35,11 @@
     RecordProperty("description",
                    "Verify that the effects configuration file is valid according to the schema");
     using namespace android::effectsConfig;
+    if (android::hardware::getAllHalInstanceNames(
+                ::android::hardware::audio::effect::CPP_VERSION::IEffectsFactory::descriptor)
+                .size() == 0) {
+        GTEST_SKIP() << "No Effects HAL version " STRINGIFY(CPP_VERSION) " on this device";
+    }
 
     std::vector<const char*> locations(std::begin(DEFAULT_LOCATIONS), std::end(DEFAULT_LOCATIONS));
     const char* xsd = "/data/local/tmp/audio_effects_conf_" STRINGIFY(CPP_VERSION) ".xsd";
diff --git a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
index 390d4ee..070242f 100644
--- a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
@@ -155,11 +155,20 @@
     0xfe3199be, 0xaed0, 0x413f, 0x87bb,
     std::array<uint8_t, 6>{{0x11, 0x26, 0x0e, 0xb6, 0x3c, 0xf1}}};
 
+enum { PARAM_FACTORY_NAME, PARAM_EFFECT_UUID };
+using EffectParameter = std::tuple<std::string, Uuid>;
+
+static inline std::string EffectParameterToString(
+        const ::testing::TestParamInfo<EffectParameter>& info) {
+    return ::android::hardware::PrintInstanceNameToString(::testing::TestParamInfo<std::string>{
+            std::get<PARAM_FACTORY_NAME>(info.param), info.index});
+}
+
 // The main test class for Audio Effect HIDL HAL.
-class AudioEffectHidlTest : public ::testing::TestWithParam<std::string> {
+class AudioEffectHidlTest : public ::testing::TestWithParam<EffectParameter> {
   public:
     void SetUp() override {
-        effectsFactory = IEffectsFactory::getService(GetParam());
+        effectsFactory = IEffectsFactory::getService(std::get<PARAM_FACTORY_NAME>(GetParam()));
         ASSERT_NE(nullptr, effectsFactory.get());
 
         findAndCreateEffect(getEffectType());
@@ -180,7 +189,7 @@
         RecordProperty("description", description);
     }
 
-    virtual Uuid getEffectType() { return EQUALIZER_EFFECT_TYPE; }
+    Uuid getEffectType() const { return std::get<PARAM_EFFECT_UUID>(GetParam()); }
 
     void findAndCreateEffect(const Uuid& type);
     void findEffectInstance(const Uuid& type, Uuid* uuid);
@@ -369,7 +378,9 @@
     description("Verify Disable -> Enable -> Disable sequence for an effect");
     Return<Result> ret = effect->disable();
     EXPECT_TRUE(ret.isOk());
-    EXPECT_EQ(Result::INVALID_ARGUMENTS, ret);
+    // Note: some legacy effects may return -EINVAL (INVALID_ARGUMENTS),
+    //       more canonical is to return -ENOSYS (NOT_SUPPORTED)
+    EXPECT_TRUE(ret == Result::NOT_SUPPORTED || ret == Result::INVALID_ARGUMENTS);
     ret = effect->enable();
     EXPECT_TRUE(ret.isOk());
     EXPECT_EQ(Result::OK, ret);
@@ -519,15 +530,19 @@
 
 // The main test class for Equalizer Audio Effect HIDL HAL.
 class EqualizerAudioEffectHidlTest : public AudioEffectHidlTest {
-   public:
+  public:
     void SetUp() override {
         AudioEffectHidlTest::SetUp();
         equalizer = IEqualizerEffect::castFrom(effect);
         ASSERT_NE(nullptr, equalizer.get());
     }
 
-   protected:
-    Uuid getEffectType() override { return EQUALIZER_EFFECT_TYPE; }
+    void TearDown() override {
+        equalizer.clear();
+        AudioEffectHidlTest::TearDown();
+    }
+
+  protected:
     void getNumBands(uint16_t* numBands);
     void getLevelRange(int16_t* minLevel, int16_t* maxLevel);
     void getBandFrequencyRange(uint16_t band, uint32_t* minFreq, uint32_t* centerFreq,
@@ -765,16 +780,19 @@
 
 // The main test class for Equalizer Audio Effect HIDL HAL.
 class LoudnessEnhancerAudioEffectHidlTest : public AudioEffectHidlTest {
-   public:
+  public:
     void SetUp() override {
         AudioEffectHidlTest::SetUp();
         enhancer = ILoudnessEnhancerEffect::castFrom(effect);
         ASSERT_NE(nullptr, enhancer.get());
     }
 
-   protected:
-    Uuid getEffectType() override { return LOUDNESS_ENHANCER_EFFECT_TYPE; }
+    void TearDown() override {
+        enhancer.clear();
+        AudioEffectHidlTest::TearDown();
+    }
 
+  protected:
     sp<ILoudnessEnhancerEffect> enhancer;
 };
 
@@ -799,19 +817,31 @@
     EXPECT_EQ(gain, actualGain);
 }
 
+INSTANTIATE_TEST_SUITE_P(EffectsFactory, AudioEffectsFactoryHidlTest,
+                         ::testing::ValuesIn(::android::hardware::getAllHalInstanceNames(
+                                 IEffectsFactory::descriptor)),
+                         ::android::hardware::PrintInstanceNameToString);
 INSTANTIATE_TEST_SUITE_P(
-        EffectsFactory, AudioEffectsFactoryHidlTest,
-        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IEffectsFactory::descriptor)),
-        android::hardware::PrintInstanceNameToString);
+        Equalizer_IEffect, AudioEffectHidlTest,
+        ::testing::Combine(::testing::ValuesIn(::android::hardware::getAllHalInstanceNames(
+                                   IEffectsFactory::descriptor)),
+                           ::testing::Values(EQUALIZER_EFFECT_TYPE)),
+        EffectParameterToString);
 INSTANTIATE_TEST_SUITE_P(
-        Equalizer, AudioEffectHidlTest,
-        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IEffectsFactory::descriptor)),
-        android::hardware::PrintInstanceNameToString);
+        LoudnessEnhancer_IEffect, AudioEffectHidlTest,
+        ::testing::Combine(::testing::ValuesIn(::android::hardware::getAllHalInstanceNames(
+                                   IEffectsFactory::descriptor)),
+                           ::testing::Values(LOUDNESS_ENHANCER_EFFECT_TYPE)),
+        EffectParameterToString);
 INSTANTIATE_TEST_SUITE_P(
         Equalizer, EqualizerAudioEffectHidlTest,
-        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IEffectsFactory::descriptor)),
-        android::hardware::PrintInstanceNameToString);
+        ::testing::Combine(::testing::ValuesIn(::android::hardware::getAllHalInstanceNames(
+                                   IEffectsFactory::descriptor)),
+                           ::testing::Values(EQUALIZER_EFFECT_TYPE)),
+        EffectParameterToString);
 INSTANTIATE_TEST_SUITE_P(
         LoudnessEnhancer, LoudnessEnhancerAudioEffectHidlTest,
-        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IEffectsFactory::descriptor)),
-        android::hardware::PrintInstanceNameToString);
+        ::testing::Combine(::testing::ValuesIn(::android::hardware::getAllHalInstanceNames(
+                                   IEffectsFactory::descriptor)),
+                           ::testing::Values(LOUDNESS_ENHANCER_EFFECT_TYPE)),
+        EffectParameterToString);
diff --git a/automotive/can/1.0/default/Android.bp b/automotive/can/1.0/default/Android.bp
index ee2e92b..f5cf425 100644
--- a/automotive/can/1.0/default/Android.bp
+++ b/automotive/can/1.0/default/Android.bp
@@ -51,5 +51,6 @@
     ],
     static_libs: [
         "android.hardware.automotive.can@libnetdevice",
+        "android.hardware.automotive@libc++fs",
     ],
 }
diff --git a/automotive/can/1.0/default/CanBus.cpp b/automotive/can/1.0/default/CanBus.cpp
index 9f704c1..8b98e5e 100644
--- a/automotive/can/1.0/default/CanBus.cpp
+++ b/automotive/can/1.0/default/CanBus.cpp
@@ -226,7 +226,6 @@
  * \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::SET) return flag;
     if (filterFlag == FilterFlag::NOT_SET) return !flag;
@@ -302,7 +301,6 @@
     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;
     }
diff --git a/automotive/can/1.0/default/CanBusSlcan.cpp b/automotive/can/1.0/default/CanBusSlcan.cpp
index d15905d..f08566c 100644
--- a/automotive/can/1.0/default/CanBusSlcan.cpp
+++ b/automotive/can/1.0/default/CanBusSlcan.cpp
@@ -56,7 +56,7 @@
      * that has already been configured and brought up.
      */
     if (ioctl(uartFd.get(), SIOCGIFNAME, ifrequest.ifr_name) < 0) {
-        LOG(ERROR) << "Failed to get the name of the created device: " << strerror(errno);
+        PLOG(ERROR) << "Failed to get the name of the created device";
         return ICanController::Result::UNKNOWN_ERROR;
     }
 
@@ -80,7 +80,7 @@
      * controlling terminal */
     mFd = base::unique_fd(open(mUartName.c_str(), O_RDWR | O_NONBLOCK | O_NOCTTY));
     if (!mFd.ok()) {
-        LOG(ERROR) << "SLCAN Failed to open " << mUartName << ": " << strerror(errno);
+        PLOG(ERROR) << "SLCAN Failed to open " << mUartName;
         return ICanController::Result::BAD_INTERFACE_ID;
     }
 
@@ -92,7 +92,7 @@
     // blank terminal settings and pull them from the device
     struct termios terminalSettings = {};
     if (tcgetattr(mFd.get(), &terminalSettings) < 0) {
-        LOG(ERROR) << "Failed to read attrs of" << mUartName << ": " << strerror(errno);
+        PLOG(ERROR) << "Failed to read attrs of" << mUartName;
         return ICanController::Result::UNKNOWN_ERROR;
     }
 
@@ -107,42 +107,40 @@
     struct serial_struct serialSettings;
     // get serial settings
     if (ioctl(mFd.get(), TIOCGSERIAL, &serialSettings) < 0) {
-        LOG(ERROR) << "Failed to read serial settings from " << mUartName << ": "
-                   << strerror(errno);
+        PLOG(ERROR) << "Failed to read serial settings from " << mUartName;
         return ICanController::Result::UNKNOWN_ERROR;
     }
     // set low latency mode
     serialSettings.flags |= ASYNC_LOW_LATENCY;
     // apply serial settings
     if (ioctl(mFd.get(), TIOCSSERIAL, &serialSettings) < 0) {
-        LOG(ERROR) << "Failed to set low latency mode on " << mUartName << ": " << strerror(errno);
+        PLOG(ERROR) << "Failed to set low latency mode on " << mUartName;
         return ICanController::Result::UNKNOWN_ERROR;
     }
 
     /* TCSADRAIN applies settings after we finish writing the rest of our
      * changes (as opposed to TCSANOW, which changes immediately) */
     if (tcsetattr(mFd.get(), TCSADRAIN, &terminalSettings) < 0) {
-        LOG(ERROR) << "Failed to apply terminal settings to " << mUartName << ": "
-                   << strerror(errno);
+        PLOG(ERROR) << "Failed to apply terminal settings to " << mUartName;
         return ICanController::Result::UNKNOWN_ERROR;
     }
 
     // apply speed setting for CAN
     if (write(mFd.get(), canBitrateCommand->c_str(), canBitrateCommand->length()) <= 0) {
-        LOG(ERROR) << "Failed to apply CAN bitrate: " << strerror(errno);
+        PLOG(ERROR) << "Failed to apply CAN bitrate";
         return ICanController::Result::UNKNOWN_ERROR;
     }
 
-    // set open flag TODO: also support listen only
+    // TODO(b/144775286): set open flag & support listen only
     if (write(mFd.get(), slcanprotocol::kOpenCommand.c_str(),
               slcanprotocol::kOpenCommand.length()) <= 0) {
-        LOG(ERROR) << "Failed to set open flag: " << strerror(errno);
+        PLOG(ERROR) << "Failed to set open flag";
         return ICanController::Result::UNKNOWN_ERROR;
     }
 
     // set line discipline to slcan
     if (ioctl(mFd.get(), TIOCSETD, &slcanprotocol::kSlcanDiscipline) < 0) {
-        LOG(ERROR) << "Failed to set line discipline to slcan: " << strerror(errno);
+        PLOG(ERROR) << "Failed to set line discipline to slcan";
         return ICanController::Result::UNKNOWN_ERROR;
     }
 
diff --git a/automotive/can/1.0/default/CanController.cpp b/automotive/can/1.0/default/CanController.cpp
index 0700c77..a2643af 100644
--- a/automotive/can/1.0/default/CanController.cpp
+++ b/automotive/can/1.0/default/CanController.cpp
@@ -23,6 +23,8 @@
 #include <android-base/logging.h>
 #include <android/hidl/manager/1.2/IServiceManager.h>
 
+#include <filesystem>
+#include <fstream>
 #include <regex>
 
 namespace android::hardware::automotive::can::V1_0::implementation {
@@ -30,6 +32,29 @@
 using IfId = ICanController::BusConfig::InterfaceId;
 using IfIdDisc = ICanController::BusConfig::InterfaceId::hidl_discriminator;
 
+namespace fsErrors {
+static const std::error_code ok;
+static const std::error_code eperm(EPERM, std::generic_category());
+static const std::error_code enoent(ENOENT, std::generic_category());
+static const std::error_code eacces(EACCES, std::generic_category());
+}  // namespace fsErrors
+
+/* In the /sys/devices tree, there are files called "serial", which contain the serial numbers
+ * for various devices. The exact location inside of this directory is dependent upon the
+ * hardware we are running on, so we have to start from /sys/devices and work our way down. */
+static const std::filesystem::path kDevPath("/sys/devices/");
+static const std::regex kTtyRe("^tty[A-Z]+[0-9]+$");
+static constexpr auto kOpts = ~(std::filesystem::directory_options::follow_directory_symlink |
+                                std::filesystem::directory_options::skip_permission_denied);
+
+/**
+ * A helper object to associate the interface name and type of a USB to CAN adapter.
+ */
+struct UsbCanIface {
+    ICanController::InterfaceType iftype;
+    std::string ifaceName;
+};
+
 Return<void> CanController::getSupportedInterfaceTypes(getSupportedInterfaceTypes_cb _hidl_cb) {
     _hidl_cb({ICanController::InterfaceType::VIRTUAL, ICanController::InterfaceType::SOCKETCAN,
               ICanController::InterfaceType::SLCAN});
@@ -41,6 +66,152 @@
     return std::regex_match(name, nameRE);
 }
 
+/**
+ * Given a UsbCanIface object, get the ifaceName given the serialPath.
+ *
+ * \param serialPath - Absolute path to a "serial" file for a given device in /sys.
+ * \return A populated UsbCanIface. On failure, nullopt is returned.
+ */
+static std::optional<UsbCanIface> getIfaceName(std::filesystem::path serialPath) {
+    std::error_code fsStatus;
+    // Since the path is to a file called "serial", we need to search its parent directory.
+    std::filesystem::recursive_directory_iterator fsItr(serialPath.parent_path(), kOpts, fsStatus);
+    if (fsStatus != fsErrors::ok) {
+        LOG(ERROR) << "Failed to open " << serialPath.parent_path();
+        return std::nullopt;
+    }
+
+    for (; fsStatus == fsErrors::ok && fsItr != std::filesystem::recursive_directory_iterator();
+         fsItr.increment(fsStatus)) {
+        /* We want either a directory called "net" or a directory that looks like tty<something>, so
+         * skip files. */
+        bool isDir = fsItr->is_directory(fsStatus);
+        if (fsStatus != fsErrors::ok || !isDir) continue;
+
+        /* path() returns an iterator that steps through directories from / to the leaf.
+         * end() returns one past the leaf of the path, but we want the leaf. Decrementing the
+         * path gives us a pointer to the leaf, which we then dereference.*/
+        std::string currentDir = *(--(fsItr->path().end()));
+        if (currentDir == "net") {
+            /* This device is a SocketCAN device. The iface name is the only directory under
+             * net/. Multiple directories under net/ is an error.*/
+            std::filesystem::directory_iterator netItr(fsItr->path(), kOpts, fsStatus);
+            if (fsStatus != fsErrors::ok) {
+                LOG(ERROR) << "Failed to open " << fsItr->path() << " to get net name!";
+                return std::nullopt;
+            }
+
+            // Get the leaf of the path. This is the interface name, assuming it's the only leaf.
+            std::string netName = *(--(netItr->path().end()));
+
+            // Check if there is more than one item in net/
+            netItr.increment(fsStatus);
+            if (fsStatus != fsErrors::ok) {
+                // It's possible we have a valid net name, but this is most likely an error.
+                LOG(ERROR) << "Failed to verify " << fsItr->path() << " has valid net name!";
+                return std::nullopt;
+            }
+            if (netItr != std::filesystem::directory_iterator()) {
+                // There should never be more than one name under net/
+                LOG(ERROR) << "Found more than one net name in " << fsItr->path() << "!";
+                return std::nullopt;
+            }
+            return {{ICanController::InterfaceType::SOCKETCAN, netName}};
+        } else if (std::regex_match(currentDir, kTtyRe)) {
+            // This device is a USB serial device, and currentDir is the tty name.
+            return {{ICanController::InterfaceType::SLCAN, "/dev/" + currentDir}};
+        }
+    }
+
+    // check if the loop above exited due to a c++fs error.
+    if (fsStatus != fsErrors::ok) {
+        LOG(ERROR) << "Failed search filesystem: " << fsStatus;
+    }
+    return std::nullopt;
+}
+
+/**
+ * A helper function to read the serial number from a "serial" file in /sys/devices/
+ *
+ * \param serialnoPath - path to the file to read.
+ * \return the serial number, or nullopt on failure.
+ */
+static std::optional<std::string> readSerialNo(const std::string& serialnoPath) {
+    std::ifstream serialnoStream(serialnoPath);
+    std::string serialno;
+    if (!serialnoStream.good()) {
+        LOG(ERROR) << "Failed to read serial number from " << serialnoPath;
+        return std::nullopt;
+    }
+    std::getline(serialnoStream, serialno);
+    return serialno;
+}
+
+/**
+ * Searches for USB devices found in /sys/devices/, and attempts to find a device matching the
+ * provided list of serial numbers.
+ *
+ * \param configSerialnos - a list of serial number (suffixes) from the HAL config.
+ * \param iftype - the type of the interface to be located.
+ * \return a matching USB device. On failure, std::nullopt is returned.
+ */
+static std::optional<UsbCanIface> findUsbDevice(const hidl_vec<hidl_string>& configSerialnos) {
+    std::error_code fsStatus;
+    std::filesystem::recursive_directory_iterator fsItr(kDevPath, kOpts, fsStatus);
+    if (fsStatus != fsErrors::ok) {
+        LOG(ERROR) << "Failed to open " << kDevPath;
+        return std::nullopt;
+    }
+
+    for (; fsStatus == fsErrors::ok && fsItr != std::filesystem::recursive_directory_iterator();
+         fsItr.increment(fsStatus)) {
+        // We want to find a file called "serial", which is in a directory somewhere. Skip files.
+        bool isDir = fsItr->is_directory(fsStatus);
+        if (fsStatus != fsErrors::ok) {
+            LOG(ERROR) << "Failed check if " << fsStatus;
+            return std::nullopt;
+        }
+        if (!isDir) continue;
+
+        auto serialnoPath = fsItr->path() / "serial";
+        bool isReg = std::filesystem::is_regular_file(serialnoPath, fsStatus);
+
+        /* Make sure we have permissions to this directory, ignore enoent, since the file
+         * "serial" may not exist, which is ok. */
+        if (fsStatus == fsErrors::eperm || fsStatus == fsErrors::eacces) {
+            /* This means we  don't have access to this directory. If we recurse into it, this
+             * will cause the iterator to loose its state and we'll crash. */
+            fsItr.disable_recursion_pending();
+            continue;
+        }
+        if (fsStatus == fsErrors::enoent) continue;
+        if (fsStatus != fsErrors::ok) {
+            LOG(WARNING) << "An unexpected error occurred while checking for serialno: "
+                         << fsStatus;
+            continue;
+        }
+        if (!isReg) continue;
+
+        // we found a serial number
+        auto serialno = readSerialNo(serialnoPath);
+        if (!serialno.has_value()) continue;
+
+        // see if the serial number exists in the config
+        for (auto&& cfgSn : configSerialnos) {
+            if (serialno->ends_with(std::string(cfgSn))) {
+                auto ifaceInfo = getIfaceName(serialnoPath);
+                if (!ifaceInfo.has_value()) break;
+                return ifaceInfo;
+            }
+        }
+    }
+    if (fsStatus != fsErrors::ok) {
+        LOG(ERROR) << "Error searching filesystem: " << fsStatus;
+        return std::nullopt;
+    }
+    return std::nullopt;
+}
+
 Return<ICanController::Result> CanController::upInterface(const ICanController::BusConfig& config) {
     LOG(VERBOSE) << "Attempting to bring interface up: " << toString(config);
 
@@ -58,24 +229,46 @@
 
     sp<CanBus> busService;
 
+    // SocketCAN native type interface.
     if (config.interfaceId.getDiscriminator() == IfIdDisc::socketcan) {
-        // TODO(b/142654031): support serialno
         auto& socketcan = config.interfaceId.socketcan();
-        if (socketcan.getDiscriminator() == IfId::Socketcan::hidl_discriminator::ifname) {
-            busService = new CanBusNative(socketcan.ifname(), config.bitrate);
+        std::string ifaceName;
+        if (socketcan.getDiscriminator() == IfId::Socketcan::hidl_discriminator::serialno) {
+            // Configure by serial number.
+            auto selectedDevice = findUsbDevice(socketcan.serialno());
+            // verify the returned device is the correct one
+            if (!selectedDevice.has_value() ||
+                selectedDevice->iftype != ICanController::InterfaceType::SOCKETCAN) {
+                return ICanController::Result::BAD_INTERFACE_ID;
+            }
+            ifaceName = selectedDevice->ifaceName;
         } else {
-            return ICanController::Result::BAD_INTERFACE_ID;
+            // configure by iface name.
+            ifaceName = socketcan.ifname();
         }
-    } else if (config.interfaceId.getDiscriminator() == IfIdDisc::virtualif) {
+        busService = new CanBusNative(ifaceName, config.bitrate);
+    }
+    // Virtual interface.
+    else if (config.interfaceId.getDiscriminator() == IfIdDisc::virtualif) {
         busService = new CanBusVirtual(config.interfaceId.virtualif().ifname);
-    } else if (config.interfaceId.getDiscriminator() == IfIdDisc::slcan) {
-        // TODO(b/142654031): support serialno
+    }
+    // SLCAN interface.
+    else if (config.interfaceId.getDiscriminator() == IfIdDisc::slcan) {
         auto& slcan = config.interfaceId.slcan();
-        if (slcan.getDiscriminator() == IfId::Slcan::hidl_discriminator::ttyname) {
-            busService = new CanBusSlcan(slcan.ttyname(), config.bitrate);
+        std::string ttyName;
+        if (slcan.getDiscriminator() == IfId::Slcan::hidl_discriminator::serialno) {
+            // Configure by serial number.
+            auto selectedDevice = findUsbDevice(slcan.serialno());
+            if (!selectedDevice.has_value() ||
+                selectedDevice->iftype != ICanController::InterfaceType::SLCAN) {
+                return ICanController::Result::BAD_INTERFACE_ID;
+            }
+            ttyName = selectedDevice->ifaceName;
         } else {
-            return ICanController::Result::BAD_INTERFACE_ID;
+            // Configure by tty name.
+            ttyName = slcan.ttyname();
         }
+        busService = new CanBusSlcan(ttyName, config.bitrate);
     } else {
         return ICanController::Result::NOT_SUPPORTED;
     }
diff --git a/automotive/can/1.0/default/CanSocket.cpp b/automotive/can/1.0/default/CanSocket.cpp
index 86ccc0e..f379d5a 100644
--- a/automotive/can/1.0/default/CanSocket.cpp
+++ b/automotive/can/1.0/default/CanSocket.cpp
@@ -67,7 +67,7 @@
 bool CanSocket::send(const struct canfd_frame& frame) {
     const auto res = write(mSocket.get(), &frame, CAN_MTU);
     if (res < 0) {
-        LOG(DEBUG) << "CanSocket send failed: " << errno;
+        PLOG(DEBUG) << "CanSocket send failed";
         return false;
     }
     if (res != CAN_MTU) {
@@ -102,7 +102,7 @@
         const auto sel = selectRead(mSocket, kReadPooling);
         if (sel == 0) continue;  // timeout
         if (sel == -1) {
-            LOG(ERROR) << "Select failed: " << errno;
+            PLOG(ERROR) << "Select failed";
             break;
         }
 
@@ -130,7 +130,7 @@
             if (errno == EAGAIN) continue;
 
             errnoCopy = errno;
-            LOG(ERROR) << "Failed to read CAN packet: " << strerror(errno) << " (" << errno << ")";
+            PLOG(ERROR) << "Failed to read CAN packet";
             break;
         }
 
diff --git a/automotive/can/1.0/default/libc++fs/Android.bp b/automotive/can/1.0/default/libc++fs/Android.bp
new file mode 100644
index 0000000..1fe324e
--- /dev/null
+++ b/automotive/can/1.0/default/libc++fs/Android.bp
@@ -0,0 +1,83 @@
+//
+// Copyright (C) 2020 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.
+//
+
+// TODO(152067309): Stop building this yourself once it's ABI stable and has
+// been made vendor available. Just use libc++fs instead of this.
+
+cc_defaults {
+    name: "android.hardware.automotive@libc++fsdefaults",
+    host_supported: true,
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-unused-parameter",
+    ],
+    cppflags: [
+        "-std=c++14",
+        "-fexceptions",
+        "-DLIBCXX_BUILDING_LIBCXXABI",
+        "-D_LIBCPP_BUILDING_LIBRARY",
+    ],
+    rtti: true,
+    stl: "none",
+    target: {
+        linux_bionic: {
+            enabled: true,
+        },
+        windows: {
+            enabled: true,
+            cflags: [
+                "-D_LIBCPP_HAS_THREAD_API_WIN32",
+                "-D_LIBCXXABI_BUILDING_LIBRARY",
+                "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+                "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+                "-UWIN32_LEAN_AND_MEAN",
+            ],
+        },
+        windows_x86: {
+            cflags: [
+                "-fsjlj-exceptions",
+            ],
+        },
+    },
+}
+
+cc_library_static {
+    name: "android.hardware.automotive@libc++fs",
+    recovery_available: true,
+    vendor: true,
+    defaults: ["android.hardware.automotive@libc++fsdefaults"],
+    srcs: [
+        "src/filesystem/directory_iterator.cpp",
+        "src/filesystem/operations.cpp",
+    ],
+    multilib: {
+        lib32: {
+            // off_t usage is constrained to within the libc++ source (not the
+            // headers), so we can build the filesystem library with a 64-bit
+            // off_t on LP32 to get large file support without needing all users
+            // of the library to match.
+            cflags: ["-D_FILE_OFFSET_BITS=64"],
+        },
+    },
+    target: {
+        windows: {
+            enabled: false,
+        },
+    },
+}
diff --git a/automotive/can/1.0/default/libc++fs/include b/automotive/can/1.0/default/libc++fs/include
new file mode 120000
index 0000000..346e659
--- /dev/null
+++ b/automotive/can/1.0/default/libc++fs/include
@@ -0,0 +1 @@
+../../../../../../../external/libcxx/include/
\ No newline at end of file
diff --git a/automotive/can/1.0/default/libc++fs/src b/automotive/can/1.0/default/libc++fs/src
new file mode 120000
index 0000000..7abb4ba
--- /dev/null
+++ b/automotive/can/1.0/default/libc++fs/src
@@ -0,0 +1 @@
+../../../../../../../external/libcxx/src/
\ No newline at end of file
diff --git a/automotive/can/1.0/default/libnetdevice/NetlinkSocket.cpp b/automotive/can/1.0/default/libnetdevice/NetlinkSocket.cpp
index 6a7f506..7817169 100644
--- a/automotive/can/1.0/default/libnetdevice/NetlinkSocket.cpp
+++ b/automotive/can/1.0/default/libnetdevice/NetlinkSocket.cpp
@@ -23,7 +23,7 @@
 NetlinkSocket::NetlinkSocket(int protocol) {
     mFd.reset(socket(AF_NETLINK, SOCK_RAW, protocol));
     if (!mFd.ok()) {
-        LOG(ERROR) << "Can't open Netlink socket: " << errno;
+        PLOG(ERROR) << "Can't open Netlink socket";
         mFailed = true;
         return;
     }
@@ -32,7 +32,7 @@
     sa.nl_family = AF_NETLINK;
 
     if (bind(mFd.get(), reinterpret_cast<struct sockaddr*>(&sa), sizeof(sa)) < 0) {
-        LOG(ERROR) << "Can't bind Netlink socket: " << errno;
+        PLOG(ERROR) << "Can't bind Netlink socket";
         mFd.reset();
         mFailed = true;
     }
@@ -57,7 +57,7 @@
     msg.msg_iovlen = 1;
 
     if (sendmsg(mFd.get(), &msg, 0) < 0) {
-        LOG(ERROR) << "Can't send Netlink message: " << errno;
+        PLOG(ERROR) << "Can't send Netlink message";
         return false;
     }
     return true;
@@ -79,7 +79,7 @@
 
     const ssize_t status = recvmsg(mFd.get(), &msg, 0);
     if (status < 0) {
-        LOG(ERROR) << "Failed to receive Netlink message: " << errno;
+        PLOG(ERROR) << "Failed to receive Netlink message";
         return false;
     }
     size_t remainingLen = status;
diff --git a/automotive/can/1.0/default/libnetdevice/can.cpp b/automotive/can/1.0/default/libnetdevice/can.cpp
index 06d45d3..a2a85dc 100644
--- a/automotive/can/1.0/default/libnetdevice/can.cpp
+++ b/automotive/can/1.0/default/libnetdevice/can.cpp
@@ -48,7 +48,7 @@
     }
 
     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);
+        PLOG(ERROR) << "Can't receive error frames, CAN setsockpt failed";
         return {};
     }
 
diff --git a/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp b/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
index aee8205..b051442 100644
--- a/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
+++ b/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
@@ -41,7 +41,7 @@
     }
 
     if (ioctl(sock.get(), request, &ifr) < 0) {
-        LOG(ERROR) << "ioctl(" << std::hex << request << std::dec << ") failed: " << errno;
+        PLOG(ERROR) << "ioctl(" << std::hex << request << std::dec << ") failed";
         return false;
     }
 
diff --git a/automotive/can/1.0/tools/Android.bp b/automotive/can/1.0/tools/Android.bp
index 21f364b..a6c40d9 100644
--- a/automotive/can/1.0/tools/Android.bp
+++ b/automotive/can/1.0/tools/Android.bp
@@ -27,6 +27,9 @@
     header_libs: [
         "android.hardware.automotive.can@hidl-utils-lib",
     ],
+    static_libs: [
+        "android.hardware.automotive.can@libcanhaltools",
+    ],
 }
 
 cc_binary {
@@ -42,6 +45,9 @@
     header_libs: [
         "android.hardware.automotive.can@hidl-utils-lib",
     ],
+    static_libs: [
+        "android.hardware.automotive.can@libcanhaltools",
+    ],
 }
 
 cc_binary {
@@ -54,4 +60,7 @@
         "android.hardware.automotive.can@1.0",
         "libhidlbase",
     ],
+    static_libs: [
+        "android.hardware.automotive.can@libcanhaltools",
+    ],
 }
diff --git a/automotive/can/1.0/tools/canhalctrl.cpp b/automotive/can/1.0/tools/canhalctrl.cpp
index 33755bf..bf1c3b1 100644
--- a/automotive/can/1.0/tools/canhalctrl.cpp
+++ b/automotive/can/1.0/tools/canhalctrl.cpp
@@ -15,9 +15,11 @@
  */
 
 #include <android-base/logging.h>
+#include <android-base/parseint.h>
 #include <android/hardware/automotive/can/1.0/ICanController.h>
 #include <android/hidl/manager/1.2/IServiceManager.h>
 #include <hidl-utils/hidl-utils.h>
+#include <libcanhaltools/libcanhaltools.h>
 
 #include <iostream>
 #include <string>
@@ -41,34 +43,17 @@
     std::cerr << " bus name - name under which ICanBus will be published" << std::endl;
 }
 
-static hidl_vec<hidl_string> getControlServices() {
-    auto manager = hidl::manager::V1_2::IServiceManager::getService();
-    hidl_vec<hidl_string> services;
-    manager->listManifestByInterface(ICanController::descriptor, hidl_utils::fill(&services));
-    if (services.size() == 0) {
-        std::cerr << "No ICanController services registered (missing privileges?)" << std::endl;
-        exit(-1);
-    }
-    return services;
-}
-
-static bool isSupported(sp<ICanController> ctrl, ICanController::InterfaceType iftype) {
-    hidl_vec<ICanController::InterfaceType> supported;
-    if (!ctrl->getSupportedInterfaceTypes(hidl_utils::fill(&supported)).isOk()) return false;
-    return supported.contains(iftype);
-}
-
 static int up(const std::string& busName, ICanController::InterfaceType type,
               const std::string& interface, uint32_t bitrate) {
     bool anySupported = false;
-    for (auto&& service : getControlServices()) {
+    for (auto&& service : libcanhaltools::getControlServices()) {
         auto ctrl = ICanController::getService(service);
         if (ctrl == nullptr) {
             std::cerr << "Couldn't open ICanController/" << service;
             continue;
         }
 
-        if (!isSupported(ctrl, type)) continue;
+        if (!libcanhaltools::isSupported(ctrl, type)) continue;
         anySupported = true;
 
         ICanController::BusConfig config = {};
@@ -88,8 +73,8 @@
             slcan.ttyname(interface);
             config.interfaceId.slcan(slcan);
         } else if (type == ICanController::InterfaceType::INDEXED) {
-            auto idx = std::stol(interface);
-            if (idx < 0 || idx > UINT8_MAX) {
+            unsigned idx;
+            if (!android::base::ParseUint(interface, &idx, unsigned(UINT8_MAX))) {
                 std::cerr << "Interface index out of range: " << idx;
                 return -1;
             }
@@ -111,7 +96,7 @@
 }
 
 static int down(const std::string& busName) {
-    for (auto&& service : getControlServices()) {
+    for (auto&& service : libcanhaltools::getControlServices()) {
         auto ctrl = ICanController::getService(service);
         if (ctrl == nullptr) continue;
 
@@ -162,9 +147,11 @@
             return -1;
         }
 
-        long long bitrate = 0;
-        if (argc == 4) {
-            bitrate = std::stoll(argv[3]);
+        uint32_t bitrate = 0;
+        if (argc == 4 && !android::base::ParseUint(argv[3], &bitrate)) {
+            std::cerr << "Invalid bitrate!" << std::endl;
+            usage();
+            return -1;
         }
 
         return up(busName, *type, interface, bitrate);
diff --git a/automotive/can/1.0/tools/canhalsend.cpp b/automotive/can/1.0/tools/canhalsend.cpp
index 7e6833a..f0f9d10 100644
--- a/automotive/can/1.0/tools/canhalsend.cpp
+++ b/automotive/can/1.0/tools/canhalsend.cpp
@@ -15,6 +15,8 @@
  */
 
 #include <android-base/logging.h>
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
 #include <android/hardware/automotive/can/1.0/ICanBus.h>
 #include <android/hidl/manager/1.2/IServiceManager.h>
 
@@ -27,13 +29,13 @@
 using Result = V1_0::Result;
 
 static void usage() {
-    std::cerr << "cansend - simple command line tool to send raw CAN frames" << std::endl;
+    std::cerr << "canhalsend - simple command line tool to send raw CAN frames" << std::endl;
     std::cerr << std::endl << "usage:" << std::endl << std::endl;
     std::cerr << "canhalsend <bus name> <can id>#<data>" << std::endl;
     std::cerr << "where:" << std::endl;
-    std::cerr << " bus name - name under which ICanBus is be published" << std::endl;
-    std::cerr << " can id - such as 1a5" << std::endl;
-    std::cerr << " data - such as deadbeef or 010203" << std::endl;
+    std::cerr << " bus name - name under which ICanBus is published" << std::endl;
+    std::cerr << " can id - such as 1a5 or 1fab5982" << std::endl;
+    std::cerr << " data - such as deadbeef, 010203, or R for a remote frame" << std::endl;
 }
 
 // TODO(b/135918744): extract to a new library
@@ -53,18 +55,13 @@
     return ICanBus::castFrom(ret);
 }
 
-static int cansend(const std::string& busname, V1_0::CanMessageId msgid,
-                   std::vector<uint8_t> payload) {
+static int cansend(const std::string& busname, const V1_0::CanMessage& msg) {
     auto bus = tryOpen(busname);
     if (bus == nullptr) {
         std::cerr << "Bus " << busname << " is not available" << std::endl;
         return -1;
     }
 
-    V1_0::CanMessage msg = {};
-    msg.id = msgid;
-    msg.payload = payload;
-
     const auto result = bus->send(msg);
     if (result != Result::OK) {
         std::cerr << "Send call failed: " << toString(result) << std::endl;
@@ -73,27 +70,54 @@
     return 0;
 }
 
-static std::optional<std::tuple<V1_0::CanMessageId, std::vector<uint8_t>>> parseCanMessage(
-        const std::string& msg) {
+static std::optional<V1_0::CanMessage> parseCanMessage(const std::string& msg) {
     const auto hashpos = msg.find("#");
     if (hashpos == std::string::npos) return std::nullopt;
 
     const std::string msgidStr = msg.substr(0, hashpos);
     const std::string payloadStr = msg.substr(hashpos + 1);
 
-    size_t idx = 0;
-    V1_0::CanMessageId msgid = std::stoi(msgidStr, &idx, 16);
-    if (msgidStr[idx] != '\0') return std::nullopt;
+    V1_0::CanMessageId msgid;
+    // "0x" must be prepended to msgidStr, since ParseUint doesn't accept a base argument.
+    if (!android::base::ParseUint("0x" + msgidStr, &msgid)) return std::nullopt;
+
+    V1_0::CanMessage canmsg = {};
+    canmsg.id = msgid;
+    if (msgid > 0x7FF) {
+        canmsg.isExtendedId = true;
+    }
+
+    if (android::base::StartsWith(payloadStr, "R")) {
+        canmsg.remoteTransmissionRequest = true;
+
+        /* The CAN bus HAL doesn't define a data length code (DLC) field, since it is inferrred
+         * from the payload size. RTR messages indicate to the receiver how many bytes they are
+         * expecting to receive back via the DLC sent with the RTR frame. */
+        if (payloadStr.size() <= 1) return canmsg;
+
+        unsigned int dlc = 0;
+
+        /* The maximum DLC for CAN-FD is 64 bytes and CAN 2.0 is 8 bytes. Limit the size of the DLC
+         * to something memory safe and let the HAL determine if the DLC is valid. */
+        if (!android::base::ParseUint(payloadStr.substr(1), &dlc, 10000u)) {
+            std::cerr << "Invalid DLC for RTR frame!" << std::endl;
+            return std::nullopt;
+        }
+        canmsg.payload.resize(dlc);
+        return canmsg;
+    }
 
     std::vector<uint8_t> payload;
     if (payloadStr.size() % 2 != 0) return std::nullopt;
     for (size_t i = 0; i < payloadStr.size(); i += 2) {
         std::string byteStr(payloadStr, i, 2);
-        payload.emplace_back(std::stoi(byteStr, &idx, 16));
-        if (byteStr[idx] != '\0') return std::nullopt;
+        uint8_t byteBuf;
+        if (!android::base::ParseUint("0x" + byteStr, &byteBuf)) return std::nullopt;
+        payload.emplace_back(byteBuf);
     }
+    canmsg.payload = payload;
 
-    return {{msgid, payload}};
+    return canmsg;
 }
 
 static int main(int argc, char* argv[]) {
@@ -117,9 +141,8 @@
         std::cerr << "Failed to parse CAN message argument" << std::endl;
         return -1;
     }
-    const auto [msgid, payload] = *canmsg;
 
-    return cansend(busname, msgid, payload);
+    return cansend(busname, *canmsg);
 }
 
 }  // namespace android::hardware::automotive::can
diff --git a/automotive/can/1.0/tools/configurator/Android.bp b/automotive/can/1.0/tools/configurator/Android.bp
new file mode 100644
index 0000000..2c4bc1d
--- /dev/null
+++ b/automotive/can/1.0/tools/configurator/Android.bp
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2020 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: "canhalconfigurator",
+    init_rc: ["canhalconfigurator.rc"],
+    defaults: ["android.hardware.automotive.can@defaults"],
+    srcs: [
+        "canhalconfigurator.cpp",
+        "canprototools.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.automotive.can@1.0",
+        "libhidlbase",
+        "libprotobuf-cpp-full",
+    ],
+    static_libs: [
+        "android.hardware.automotive.can@1.x-config-format",
+        "android.hardware.automotive.can@libcanhaltools",
+    ],
+}
diff --git a/automotive/can/1.0/tools/configurator/canhalconfigurator.cpp b/automotive/can/1.0/tools/configurator/canhalconfigurator.cpp
new file mode 100644
index 0000000..a100f06
--- /dev/null
+++ b/automotive/can/1.0/tools/configurator/canhalconfigurator.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2020 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 "canbus_config.pb.h"
+#include "canprototools.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/automotive/can/1.0/ICanController.h>
+#include <libcanhaltools/libcanhaltools.h>
+
+#include <chrono>
+#include <thread>
+
+namespace android::hardware::automotive::can {
+
+using ICanController = V1_0::ICanController;
+
+/**
+ * Takes output from parsed protobuf config and uses it to configure the CAN HAL.
+ *
+ * \param pb_cfg is an instance of the autogenerated protobuf object for our configuration.
+ * \return boolean status, true on success, false on failure.
+ */
+static bool processPbCfg(const config::CanBusConfig& pb_cfg) {
+    for (auto const& bus : pb_cfg.buses()) {
+        if (bus.name().empty()) {
+            LOG(ERROR) << "Invalid config: Bus config must have a valid name field";
+            return false;
+        }
+
+        LOG(INFO) << "Configure " << bus.name();
+        auto bus_cfg = config::fromPbBus(bus);
+        if (!bus_cfg.has_value()) {
+            return false;
+        }
+
+        // TODO(149405589): remove this sleep and associated includes.
+        std::this_thread::sleep_for(std::chrono::seconds(1));
+        if (libcanhaltools::configureIface(*bus_cfg) != ICanController::Result::OK) {
+            LOG(ERROR) << "No controller supports " << bus.name() << std::endl;
+            // TODO(149405589): add retry logic in case a bus fails to come up.
+            continue;
+        }
+        LOG(INFO) << bus.name() << " has been successfully configured!";
+    }
+    return true;
+}
+
+/**
+ * This kicks off the CAN HAL configuration process. This starts the following:
+ *     1. Reading the config file
+ *     2. Setting up CAN buses
+ *     3. Handling services
+ * \param filepath is a string specifying the absolute path of the config file
+ * \return boolean status, true on success, false on failure
+ */
+static bool configuratorStart(const std::string& filepath) {
+    base::SetDefaultTag("CanConfigurator");
+
+    auto pb_cfg = config::parseConfigFile(filepath);
+    if (!pb_cfg.has_value()) {
+        return false;
+    }
+
+    // process the rest of the config file data and configure the CAN buses.
+    if (!processPbCfg(*pb_cfg)) {
+        return false;
+    }
+    LOG(INFO) << "CAN HAL has been configured!";
+    return true;
+}
+
+}  // namespace android::hardware::automotive::can
+
+int main(int argc, char* argv[]) {
+    std::string config_filepath = "/etc/canbus_config.pb";
+
+    // allow for CLI specification of a config file.
+    if (argc == 2) {
+        config_filepath = argv[1];
+    } else if (argc > 2) {
+        std::cerr << "usage: " << argv[0] << " [optional config filepath]";
+        return 1;
+    }
+
+    if (!::android::hardware::automotive::can::configuratorStart(config_filepath)) {
+        return 1;
+    }
+    return 0;
+}
diff --git a/automotive/can/1.0/tools/configurator/canhalconfigurator.rc b/automotive/can/1.0/tools/configurator/canhalconfigurator.rc
new file mode 100644
index 0000000..12c2465
--- /dev/null
+++ b/automotive/can/1.0/tools/configurator/canhalconfigurator.rc
@@ -0,0 +1,3 @@
+service canhalconfigurator /system/bin/canhalconfigurator
+  class core
+  oneshot
diff --git a/automotive/can/1.0/tools/configurator/canprototools.cpp b/automotive/can/1.0/tools/configurator/canprototools.cpp
new file mode 100644
index 0000000..0a12bd6
--- /dev/null
+++ b/automotive/can/1.0/tools/configurator/canprototools.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2020 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 "canprototools.h"
+
+#include <android-base/logging.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/text_format.h>
+#include <hidl/HidlTransportSupport.h>
+#include <libcanhaltools/libcanhaltools.h>
+
+#include <fstream>
+
+namespace android::hardware::automotive::can::config {
+
+using ICanController = V1_0::ICanController;
+
+/**
+ * Helper function for parseConfigFile. readString is used to get the fist n characters (n) from an
+ * istream object (s) and return it as a string object.
+ *
+ * \param s istream of the file you intend to read.
+ * \param n streamsize object of the number of characters you'd like.
+ * \return optional string containing up to n characters from the stream(s) you provided.
+ */
+static std::optional<std::string> readString(std::istream& s, std::streamsize n) {
+    char buff[n];
+    auto got = s.read(buff, n).gcount();
+    if (!s.good() && !s.eof()) return std::nullopt;
+    return std::string(buff, 0, std::min(n, got));
+}
+
+std::optional<CanBusConfig> parseConfigFile(const std::string& filepath) {
+    std::ifstream cfg_stream(filepath);
+
+    // text headers that would be present in a plaintext proto config file.
+    static const std::array<std::string, 3> text_headers = {"buses", "#", "controller"};
+    auto cfg_file_snippet = readString(cfg_stream, 10);
+
+    if (!cfg_file_snippet.has_value()) {
+        LOG(ERROR) << "Can't open " << filepath << " for reading";
+        return std::nullopt;
+    }
+    cfg_stream.seekg(0);
+
+    // check if any of the textHeaders are at the start of the config file.
+    bool text_format = false;
+    for (auto const& header : text_headers) {
+        if (cfg_file_snippet->compare(0, header.length(), header) == 0) {
+            text_format = true;
+            break;
+        }
+    }
+
+    CanBusConfig config;
+    if (text_format) {
+        google::protobuf::io::IstreamInputStream pb_stream(&cfg_stream);
+        if (!google::protobuf::TextFormat::Parse(&pb_stream, &config)) {
+            LOG(ERROR) << "Failed to parse (text format) " << filepath;
+            return std::nullopt;
+        }
+    } else if (!config.ParseFromIstream(&cfg_stream)) {
+        LOG(ERROR) << "Failed to parse (binary format) " << filepath;
+        return std::nullopt;
+    }
+    return config;
+}
+
+std::optional<ICanController::BusConfig> fromPbBus(const Bus& pb_bus) {
+    ICanController::BusConfig bus_cfg = {};
+    bus_cfg.name = pb_bus.name();
+
+    switch (pb_bus.iface_type_case()) {
+        case Bus::kNative: {
+            const auto ifname = pb_bus.native().ifname();
+            const auto serialno = pb_bus.native().serialno();
+            if (ifname.empty() == serialno.empty()) {
+                LOG(ERROR) << "Invalid config: native type bus must have an iface name xor a "
+                           << "serial number";
+                return std::nullopt;
+            }
+            bus_cfg.bitrate = pb_bus.bitrate();
+            ICanController::BusConfig::InterfaceId::Socketcan socketcan = {};
+            if (!ifname.empty()) socketcan.ifname(ifname);
+            if (!serialno.empty()) socketcan.serialno({serialno.begin(), serialno.end()});
+            bus_cfg.interfaceId.socketcan(socketcan);
+            break;
+        }
+        case Bus::kSlcan: {
+            const auto ttyname = pb_bus.slcan().ttyname();
+            const auto serialno = pb_bus.slcan().serialno();
+            if (ttyname.empty() == serialno.empty()) {
+                LOG(ERROR) << "Invalid config: slcan type bus must have a tty name";
+                return std::nullopt;
+            }
+            bus_cfg.bitrate = pb_bus.bitrate();
+            ICanController::BusConfig::InterfaceId::Slcan slcan = {};
+            if (!ttyname.empty()) slcan.ttyname(ttyname);
+            if (!serialno.empty()) slcan.serialno({serialno.begin(), serialno.end()});
+            bus_cfg.interfaceId.slcan(slcan);
+            break;
+        }
+        case Bus::kVirtual: {
+            // Theoretically, we could just create the next available vcan iface.
+            const auto ifname = pb_bus.virtual_().ifname();
+            if (ifname.empty()) {
+                LOG(ERROR) << "Invalid config: native type bus must have an iface name";
+                return std::nullopt;
+            }
+            bus_cfg.interfaceId.virtualif({ifname});
+            break;
+        }
+        case Bus::kIndexed: {
+            const auto index = pb_bus.indexed().index();
+            if (index > UINT8_MAX) {
+                LOG(ERROR) << "Interface index out of range: " << index;
+                return std::nullopt;
+            }
+            bus_cfg.interfaceId.indexed({uint8_t(index)});
+            break;
+        }
+        default:
+            LOG(ERROR) << "Invalid config: bad interface type for " << bus_cfg.name;
+            return std::nullopt;
+    }
+    return bus_cfg;
+}
+
+std::optional<ICanController::InterfaceType> getHalIftype(const Bus& pb_bus) {
+    switch (pb_bus.iface_type_case()) {
+        case Bus::kNative:
+            return ICanController::InterfaceType::SOCKETCAN;
+        case Bus::kSlcan:
+            return ICanController::InterfaceType::SLCAN;
+        case Bus::kVirtual:
+            return ICanController::InterfaceType::VIRTUAL;
+        case Bus::kIndexed:
+            return ICanController::InterfaceType::INDEXED;
+        default:
+            return std::nullopt;
+    }
+}
+
+}  // namespace android::hardware::automotive::can::config
diff --git a/automotive/can/1.0/tools/configurator/canprototools.h b/automotive/can/1.0/tools/configurator/canprototools.h
new file mode 100644
index 0000000..b7f2b6f
--- /dev/null
+++ b/automotive/can/1.0/tools/configurator/canprototools.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2020 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 "canbus_config.pb.h"
+
+#include <android/hardware/automotive/can/1.0/ICanController.h>
+
+namespace android::hardware::automotive::can::config {
+
+/**
+ * This reads the protobuf config file into a protobuf object. Both text based protobuf files as
+ * well as binary format protobuf files are supported.
+ *
+ * \param filepath string containing the name of the config file to read.
+ * \return a CanBusConfig protobuf object constructed from the config file.
+ */
+std::optional<CanBusConfig> parseConfigFile(const std::string& filepath);
+
+/**
+ * Converts protobuf format single-bus config object to a HAL bus config object.
+ *
+ * \param pb_bus is the protobuf object representing a the configuration of one CAN bus.
+ * \return a converted HAL bus config object.
+ */
+std::optional<V1_0::ICanController::BusConfig> fromPbBus(const Bus& pb_bus);
+
+/**
+ * Get the CAN HAL interface type specified by a given protobuf config object.
+ *
+ * \param pb_bus is the protobuf object representing a the configuration of one CAN bus.
+ * \return the CAN HAL interface type.
+ */
+std::optional<V1_0::ICanController::InterfaceType> getHalIftype(const Bus& pb_bus);
+
+}  // namespace android::hardware::automotive::can::config
diff --git a/automotive/can/1.0/tools/configurator/proto/Android.bp b/automotive/can/1.0/tools/configurator/proto/Android.bp
new file mode 100644
index 0000000..05e1205
--- /dev/null
+++ b/automotive/can/1.0/tools/configurator/proto/Android.bp
@@ -0,0 +1,28 @@
+//
+// Copyright (C) 2020 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_static {
+    name: "android.hardware.automotive.can@1.x-config-format",
+    defaults: ["android.hardware.automotive.can@defaults"],
+    proto: {
+        export_proto_headers: true,
+        type: "full",
+    },
+    strip: {
+        keep_symbols: true,
+    },
+    srcs: ["canbus_config.proto"],
+}
diff --git a/automotive/can/1.0/tools/configurator/proto/canbus_config.proto b/automotive/can/1.0/tools/configurator/proto/canbus_config.proto
new file mode 100644
index 0000000..9aa33ac
--- /dev/null
+++ b/automotive/can/1.0/tools/configurator/proto/canbus_config.proto
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 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 = "proto3";
+
+package android.hardware.automotive.can.config;
+
+message IfaceNative {
+    string ifname = 1;
+    repeated string serialno = 2;
+};
+
+message IfaceSlcan {
+    string ttyname = 1;
+    repeated string serialno = 2;
+};
+
+message IfaceVirtual {
+    string ifname = 1;
+};
+
+message IfaceIndexed {
+    uint32 index = 1;
+};
+
+message Bus {
+    string name = 1;  // this is the name presented in the HAL
+    oneof iface_type {
+        IfaceNative native = 2;
+        IfaceSlcan slcan = 3;
+        IfaceVirtual virtual = 4;
+        IfaceIndexed indexed = 5;
+    }
+    uint32 bitrate = 6;
+};
+
+message CanBusConfig {
+    repeated Bus buses = 1;
+};
diff --git a/automotive/can/1.0/tools/libcanhaltools/Android.bp b/automotive/can/1.0/tools/libcanhaltools/Android.bp
new file mode 100644
index 0000000..cee9eef
--- /dev/null
+++ b/automotive/can/1.0/tools/libcanhaltools/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2020 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_static {
+    name: "android.hardware.automotive.can@libcanhaltools",
+    defaults: ["android.hardware.automotive.can@defaults"],
+    vendor_available: true,
+    srcs: [
+        "libcanhaltools.cpp",
+    ],
+    export_include_dirs: ["include"],
+    shared_libs: [
+        "android.hardware.automotive.can@1.0",
+        "libhidlbase",
+    ],
+    header_libs: [
+        "android.hardware.automotive.can@hidl-utils-lib",
+    ],
+}
diff --git a/automotive/can/1.0/tools/libcanhaltools/include/libcanhaltools/libcanhaltools.h b/automotive/can/1.0/tools/libcanhaltools/include/libcanhaltools/libcanhaltools.h
new file mode 100644
index 0000000..bbd1fe5
--- /dev/null
+++ b/automotive/can/1.0/tools/libcanhaltools/include/libcanhaltools/libcanhaltools.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2020 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/automotive/can/1.0/ICanBus.h>
+#include <android/hardware/automotive/can/1.0/ICanController.h>
+
+namespace android::hardware::automotive::can::libcanhaltools {
+
+/**
+ * Fetch the list of registered can controller services.
+ *
+ * \return list of service names identifying the registered can controllers.
+ */
+hidl_vec<hidl_string> getControlServices();
+
+/**
+ * Determine if an can controller supports a specific interface type.
+ *
+ * \param ctrl a pointer to a can controller instance to check for interface support.
+ * \param iftype the interface type we wish to check if ctrl supports.
+ * \return true if iftype is supported by ctrl, false if not supported.
+ */
+bool isSupported(sp<V1_0::ICanController> ctrl, V1_0::ICanController::InterfaceType iftype);
+
+/**
+ * Configures a CAN interface through the CAN HAL and brings it up.
+ *
+ * \param can_config this holds the parameters for configuring a CAN bus.
+ * \return status passed back from the CAN HAL, should be OK on success.
+ */
+V1_0::ICanController::Result configureIface(V1_0::ICanController::BusConfig can_config);
+
+}  // namespace android::hardware::automotive::can::libcanhaltools
diff --git a/automotive/can/1.0/tools/libcanhaltools/libcanhaltools.cpp b/automotive/can/1.0/tools/libcanhaltools/libcanhaltools.cpp
new file mode 100644
index 0000000..9192e2f
--- /dev/null
+++ b/automotive/can/1.0/tools/libcanhaltools/libcanhaltools.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2020 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 "libcanhaltools/libcanhaltools.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/automotive/can/1.0/ICanController.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+#include <hidl-utils/hidl-utils.h>
+
+#include <iostream>
+#include <string>
+
+namespace android::hardware::automotive::can::libcanhaltools {
+
+using ICanBus = V1_0::ICanBus;
+using ICanController = V1_0::ICanController;
+using IfIdDisc = ICanController::BusConfig::InterfaceId::hidl_discriminator;
+
+hidl_vec<hidl_string> getControlServices() {
+    auto manager = hidl::manager::V1_2::IServiceManager::getService();
+    hidl_vec<hidl_string> services;
+    manager->listManifestByInterface(ICanController::descriptor, hidl_utils::fill(&services));
+    CHECK(services.size() > 0) << "No ICanController services registered (missing privileges?)"
+                               << std::endl;
+    return services;
+}
+
+bool isSupported(sp<ICanController> ctrl, ICanController::InterfaceType iftype) {
+    hidl_vec<ICanController::InterfaceType> supported;
+    if (!ctrl->getSupportedInterfaceTypes(hidl_utils::fill(&supported)).isOk()) return false;
+    return supported.contains(iftype);
+}
+
+ICanController::InterfaceType getIftype(ICanController::BusConfig can_config) {
+    switch (can_config.interfaceId.getDiscriminator()) {
+        case IfIdDisc::socketcan:
+            return ICanController::InterfaceType::SOCKETCAN;
+        case IfIdDisc::slcan:
+            return ICanController::InterfaceType::SLCAN;
+        case IfIdDisc::virtualif:
+            return ICanController::InterfaceType::VIRTUAL;
+        case IfIdDisc::indexed:
+            return ICanController::InterfaceType::INDEXED;
+        default:
+            CHECK(false) << "HAL returned unexpected interface type!";
+    }
+}
+
+ICanController::Result configureIface(ICanController::BusConfig can_config) {
+    auto iftype = getIftype(can_config);
+    auto can_controller_list = getControlServices();
+    for (auto const& service : can_controller_list) {
+        auto ctrl = ICanController::getService(service);
+        if (ctrl == nullptr) {
+            LOG(ERROR) << "Couldn't open ICanController/" << service;
+            continue;
+        }
+
+        if (!libcanhaltools::isSupported(ctrl, iftype)) continue;
+
+        const auto up_result = ctrl->upInterface(can_config);
+        if (up_result != ICanController::Result::OK) {
+            LOG(ERROR) << "Failed to bring " << can_config.name << " up: " << toString(up_result)
+                       << std::endl;
+        }
+        return up_result;
+    }
+    return ICanController::Result::NOT_SUPPORTED;
+}
+
+}  // namespace android::hardware::automotive::can::libcanhaltools
diff --git a/automotive/evs/1.0/default/Android.bp b/automotive/evs/1.0/default/Android.bp
index 69bb721..6e28ab1 100644
--- a/automotive/evs/1.0/default/Android.bp
+++ b/automotive/evs/1.0/default/Android.bp
@@ -27,4 +27,8 @@
         "-O0",
         "-g",
     ],
+
+    vintf_fragments: [
+        "manifest_android.hardware.automotive.evs@1.0-service.xml",
+    ],
 }
diff --git a/automotive/evs/1.0/default/ServiceNames.h b/automotive/evs/1.0/default/ServiceNames.h
index 1178da5..84b1697 100644
--- a/automotive/evs/1.0/default/ServiceNames.h
+++ b/automotive/evs/1.0/default/ServiceNames.h
@@ -14,4 +14,4 @@
  * limitations under the License.
  */
 
-const static char kEnumeratorServiceName[] = "EvsEnumeratorHw";
+const static char kEnumeratorServiceName[] = "hw/0";
diff --git a/automotive/evs/1.0/default/manifest_android.hardware.automotive.evs@1.0-service.xml b/automotive/evs/1.0/default/manifest_android.hardware.automotive.evs@1.0-service.xml
new file mode 100644
index 0000000..39aec43
--- /dev/null
+++ b/automotive/evs/1.0/default/manifest_android.hardware.automotive.evs@1.0-service.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2020 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.automotive.evs</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IEvsEnumerator</name>
+            <instance>hw/0</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/automotive/evs/1.1/default/Android.bp b/automotive/evs/1.1/default/Android.bp
index d843167..6e5695d 100644
--- a/automotive/evs/1.1/default/Android.bp
+++ b/automotive/evs/1.1/default/Android.bp
@@ -45,6 +45,10 @@
     required: [
         "evs_default_configuration.xml",
     ],
+
+    vintf_fragments: [
+        "manifest_android.hardware.automotive.evs@1.1-service.xml",
+    ],
 }
 
 prebuilt_etc {
diff --git a/automotive/evs/1.1/default/manifest_android.hardware.automotive.evs@1.1-service.xml b/automotive/evs/1.1/default/manifest_android.hardware.automotive.evs@1.1-service.xml
new file mode 100644
index 0000000..d4d9b17
--- /dev/null
+++ b/automotive/evs/1.1/default/manifest_android.hardware.automotive.evs@1.1-service.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2020 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.automotive.evs</name>
+        <transport>hwbinder</transport>
+        <version>1.1</version>
+        <interface>
+            <name>IEvsEnumerator</name>
+            <instance>hw/0</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/ConfidenceLevel.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/ConfidenceLevel.aidl
new file mode 100644
index 0000000..6e40d79
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/ConfidenceLevel.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@Backing(type="byte") @VintfStability
+enum ConfidenceLevel {
+  NONE = 0,
+  LOW = 1,
+  HIGH = 2,
+  MAX = 3,
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/DriverMonitoringDetection.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/DriverMonitoringDetection.aidl
new file mode 100644
index 0000000..51d2149
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/DriverMonitoringDetection.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@VintfStability
+parcelable DriverMonitoringDetection {
+  android.hardware.automotive.occupant_awareness.ConfidenceLevel confidenceScore;
+  boolean isLookingOnRoad;
+  long gazeDurationMillis;
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/GazeDetection.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/GazeDetection.aidl
new file mode 100644
index 0000000..5ce14df
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/GazeDetection.aidl
@@ -0,0 +1,28 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@VintfStability
+parcelable GazeDetection {
+  android.hardware.automotive.occupant_awareness.ConfidenceLevel gazeConfidence;
+  double[] headPosition;
+  double[] headAngleUnitVector;
+  double[] gazeAngleUnitVector;
+  android.hardware.automotive.occupant_awareness.VehicleRegion gazeTarget;
+  String customGazeTarget;
+  long timeOnTargetMillis;
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/IOccupantAwareness.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/IOccupantAwareness.aidl
new file mode 100644
index 0000000..7faff00
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/IOccupantAwareness.aidl
@@ -0,0 +1,31 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@VintfStability
+interface IOccupantAwareness {
+  android.hardware.automotive.occupant_awareness.OccupantAwarenessStatus startDetection();
+  android.hardware.automotive.occupant_awareness.OccupantAwarenessStatus stopDetection();
+  int getCapabilityForRole(in android.hardware.automotive.occupant_awareness.Role occupantRole);
+  android.hardware.automotive.occupant_awareness.OccupantAwarenessStatus getState(in android.hardware.automotive.occupant_awareness.Role occupantRole, in int detectionCapability);
+  void setCallback(in android.hardware.automotive.occupant_awareness.IOccupantAwarenessClientCallback callback);
+  void getLatestDetection(out android.hardware.automotive.occupant_awareness.OccupantDetections detections);
+  const int CAP_NONE = 0;
+  const int CAP_PRESENCE_DETECTION = 1;
+  const int CAP_GAZE_DETECTION = 2;
+  const int CAP_DRIVER_MONITORING_DETECTION = 4;
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/IOccupantAwarenessClientCallback.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/IOccupantAwarenessClientCallback.aidl
new file mode 100644
index 0000000..31b8220
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/IOccupantAwarenessClientCallback.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@VintfStability
+interface IOccupantAwarenessClientCallback {
+  oneway void onSystemStatusChanged(in int detectionFlags, in android.hardware.automotive.occupant_awareness.OccupantAwarenessStatus status);
+  oneway void onDetectionEvent(in android.hardware.automotive.occupant_awareness.OccupantDetections detections);
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/OccupantAwarenessStatus.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/OccupantAwarenessStatus.aidl
new file mode 100644
index 0000000..26371c9
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/OccupantAwarenessStatus.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@Backing(type="byte") @VintfStability
+enum OccupantAwarenessStatus {
+  READY = 0,
+  NOT_SUPPORTED = 1,
+  NOT_INITIALIZED = 2,
+  FAILURE = 3,
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/OccupantDetection.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/OccupantDetection.aidl
new file mode 100644
index 0000000..42b1095
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/OccupantDetection.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@VintfStability
+parcelable OccupantDetection {
+  android.hardware.automotive.occupant_awareness.Role role;
+  android.hardware.automotive.occupant_awareness.PresenceDetection[] presenceData;
+  android.hardware.automotive.occupant_awareness.GazeDetection[] gazeData;
+  android.hardware.automotive.occupant_awareness.DriverMonitoringDetection[] attentionData;
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/OccupantDetections.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/OccupantDetections.aidl
new file mode 100644
index 0000000..9bcad6b
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/OccupantDetections.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@VintfStability
+parcelable OccupantDetections {
+  long timeStampMillis;
+  android.hardware.automotive.occupant_awareness.OccupantDetection[] detections;
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/PresenceDetection.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/PresenceDetection.aidl
new file mode 100644
index 0000000..dd6c5c8
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/PresenceDetection.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@VintfStability
+parcelable PresenceDetection {
+  boolean isOccupantDetected;
+  long detectionDurationMillis;
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/Role.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/Role.aidl
new file mode 100644
index 0000000..7b2b907
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/Role.aidl
@@ -0,0 +1,35 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@Backing(type="int") @VintfStability
+enum Role {
+  INVALID = 0,
+  UNKNOWN = 1,
+  FRONT_PASSENGER = 2,
+  DRIVER = 4,
+  ROW_2_PASSENGER_LEFT = 8,
+  ROW_2_PASSENGER_CENTER = 16,
+  ROW_2_PASSENGER_RIGHT = 32,
+  ROW_3_PASSENGER_LEFT = 64,
+  ROW_3_PASSENGER_CENTER = 128,
+  ROW_3_PASSENGER_RIGHT = 256,
+  FRONT_OCCUPANTS = 6,
+  ROW_2_OCCUPANTS = 56,
+  ROW_3_OCCUPANTS = 448,
+  ALL_OCCUPANTS = 511,
+}
diff --git a/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/VehicleRegion.aidl b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/VehicleRegion.aidl
new file mode 100644
index 0000000..f96d950
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/aidl_api/android.hardware.automotive.occupant_awareness/current/android/hardware/automotive/occupant_awareness/VehicleRegion.aidl
@@ -0,0 +1,31 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.occupant_awareness;
+@Backing(type="int") @VintfStability
+enum VehicleRegion {
+  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,
+  CUSTOM_TARGET = 200,
+}
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
index e3cbf2e..f2d3c13 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
@@ -206,7 +206,7 @@
         InternalPool(VehiclePropertyType type, size_t vectorSize)
             : mPropType(type), mVectorSize(vectorSize) {}
 
-        RecyclableType obtain() {
+        RecyclableType obtain() override {
             return ObjectPool<VehiclePropValue>::obtain();
         }
     protected:
diff --git a/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp b/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
index 24b777c..6087bfa 100644
--- a/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
@@ -58,6 +58,8 @@
         return false;
     }
     // update the propertyValue.
+    // The timestamp in propertyStore should only be updated by the server side. It indicates
+    // the time when the event is generated by the server.
     valueToUpdate->timestamp = propValue.timestamp;
     valueToUpdate->value = propValue.value;
     if (updateStatus) {
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 53c9ffb..ea75986 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
@@ -80,6 +80,7 @@
 constexpr int WHEEL_REAR_LEFT = (int)VehicleAreaWheel::LEFT_REAR;
 constexpr int WHEEL_REAR_RIGHT = (int)VehicleAreaWheel::RIGHT_REAR;
 constexpr int INITIAL_USER_INFO = (int)VehicleProperty::INITIAL_USER_INFO;
+constexpr int SWITCH_USER = (int)VehicleProperty::SWITCH_USER;
 
 /**
  * This property is used for test purpose to generate fake events. Here is the test package that
@@ -1019,6 +1020,14 @@
                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                         },
         },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::SWITCH_USER),
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
 };
 
 }  // 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
index 9c3c95f..ce7dc65 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
@@ -73,10 +73,16 @@
 
 void EmulatedPassthroughConnector::dumpUserHal(int fd, std::string indent) {
     if (mInitialUserResponseFromCmd != nullptr) {
-        dprintf(fd, "%sInitial User Info: %s\n", indent.c_str(),
+        dprintf(fd, "%sInitialUserInfo response: %s\n", indent.c_str(),
                 toString(*mInitialUserResponseFromCmd).c_str());
     } else {
-        dprintf(fd, "%sNo Initial User Info\n", indent.c_str());
+        dprintf(fd, "%sNo InitialUserInfo response\n", indent.c_str());
+    }
+    if (mSwitchUserResponseFromCmd != nullptr) {
+        dprintf(fd, "%sSwitchUser response: %s\n", indent.c_str(),
+                toString(*mSwitchUserResponseFromCmd).c_str());
+    } else {
+        dprintf(fd, "%sNo SwitchUser response\n", indent.c_str());
     }
 }
 
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 6d5f23f..84354c1 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
@@ -15,8 +15,9 @@
  */
 #define LOG_TAG "DefaultVehicleHal_v2_0"
 
-#include <android/log.h>
 #include <android-base/macros.h>
+#include <android/log.h>
+#include <sys/system_properties.h>
 
 #include "EmulatedVehicleHal.h"
 #include "JsonFakeValueGenerator.h"
@@ -126,7 +127,9 @@
             *outStatus = v != nullptr ? StatusCode::OK : StatusCode::INVALID_ARG;
             break;
     }
-
+    if (v.get()) {
+        v->timestamp = elapsedRealtimeNano();
+    }
     return v;
 }
 
@@ -186,6 +189,14 @@
         return StatusCode::NOT_AVAILABLE;
     }
 
+    if (mInEmulator && propValue.prop == toInt(VehicleProperty::DISPLAY_BRIGHTNESS)) {
+        // Emulator does not support remote brightness control, b/139959479
+        // do not send it down so that it does not bring unnecessary property change event
+        // return other error code, such NOT_AVAILABLE, causes Emulator to be freezing
+        // TODO: return StatusCode::NOT_AVAILABLE once the above issue is fixed
+        return StatusCode::OK;
+    }
+
     /**
      * After checking all conditions, such as the property is available, a real vhal will
      * sent the events to Car ECU to take actions.
@@ -211,6 +222,17 @@
     return false;
 }
 
+// determine if it's running inside Android Emulator
+static bool isInEmulator() {
+    char propValue[PROP_VALUE_MAX];
+    bool isEmulator = (__system_property_get("ro.kernel.qemu", propValue) != 0);
+    if (!isEmulator) {
+        isEmulator = (__system_property_get("ro.hardware", propValue) != 0) &&
+                     (!strcmp(propValue, "ranchu") || !strcmp(propValue, "goldfish"));
+    }
+    return isEmulator;
+}
+
 // Parse supported properties list and generate vector of property values to hold current values.
 void EmulatedVehicleHal::onCreate() {
     static constexpr bool shouldUpdateStatus = true;
@@ -261,6 +283,8 @@
     }
     initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
     initObd2FreezeFrame(*mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));
+    mInEmulator = isInEmulator();
+    ALOGD("mInEmulator=%s", mInEmulator ? "true" : "false");
 }
 
 std::vector<VehiclePropConfig> EmulatedVehicleHal::listProperties()  {
@@ -283,6 +307,7 @@
         }
 
         if (v.get()) {
+            v->timestamp = elapsedRealtimeNano();
             doHalEvent(std::move(v));
         }
     }
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 ebf1995..dc05145 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
@@ -86,6 +86,7 @@
     std::unordered_set<int32_t> mHvacPowerProps;
     RecurrentTimer mRecurrentTimer;
     VehicleHalClient* mVehicleClient;
+    bool mInEmulator;
 };
 
 }  // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
index a91ca8e..70e39eb 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "VehicleHalServer"
+
 #include "VehicleHalServer.h"
 
 #include <fstream>
@@ -244,7 +246,9 @@
             }
             break;
         case INITIAL_USER_INFO:
-            return onSetInitialUserInfo(value, updateStatus);
+            return onSetInitialUserInfoResponse(value, updateStatus);
+        case SWITCH_USER:
+            return onSetSwitchUserResponse(value, updateStatus);
         default:
             break;
     }
@@ -282,8 +286,8 @@
  * - if it's 3, then don't send a property change (so Android can emulate a timeout)
  *
  */
-StatusCode VehicleHalServer::onSetInitialUserInfo(const VehiclePropValue& value,
-                                                  bool updateStatus) {
+StatusCode VehicleHalServer::onSetInitialUserInfoResponse(const VehiclePropValue& value,
+                                                          bool updateStatus) {
     // TODO: LOG calls below might be more suited to be DEBUG, but those are not being logged
     // (even when explicitly calling setprop log.tag. As this class should be using ALOG instead of
     // LOG, it's not worth investigating why...
@@ -320,7 +324,7 @@
     // mInitialUserResponseFromCmd is used for just one request
     std::unique_ptr<VehiclePropValue> response = std::move(mInitialUserResponseFromCmd);
 
-    // TODO(b/138709788): rather than populate the raw values directly, it should use the
+    // TODO(b/150409377): rather than populate the raw values directly, it should use the
     // libraries that convert a InitialUserInfoResponse into a VehiclePropValue)
 
     switch (response->areaId) {
@@ -350,4 +354,73 @@
     return StatusCode::OK;
 }
 
+/**
+ * Used to emulate SWITCH_USER - see onSetInitialUserInfoResponse() for usage.
+ */
+StatusCode VehicleHalServer::onSetSwitchUserResponse(const VehiclePropValue& value,
+                                                     bool updateStatus) {
+    if (value.value.int32Values.size() == 0) {
+        LOG(ERROR) << "set(SWITCH_USER): no int32values, ignoring it: " << toString(value);
+        return StatusCode::INVALID_ARG;
+    }
+
+    if (value.areaId != 0) {
+        LOG(INFO) << "set(SWITCH_USER) called from lshal; storing it: " << toString(value);
+        mSwitchUserResponseFromCmd.reset(new VehiclePropValue(value));
+        return StatusCode::OK;
+    }
+    LOG(INFO) << "set(SWITCH_USER) called from Android: " << toString(value);
+
+    int32_t requestId = value.value.int32Values[0];
+
+    // Create the update property and set common values
+    auto updatedValue = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
+    updatedValue->prop = SWITCH_USER;
+    updatedValue->timestamp = elapsedRealtimeNano();
+
+    if (mSwitchUserResponseFromCmd == nullptr) {
+        updatedValue->value.int32Values.resize(3);
+        updatedValue->value.int32Values[0] = requestId;
+        updatedValue->value.int32Values[1] = (int32_t)SwitchUserMessageType::VEHICLE_RESPONSE;
+        updatedValue->value.int32Values[2] = (int32_t)SwitchUserStatus::SUCCESS;
+        LOG(INFO) << "no lshal response; returning VEHICLE_RESPONSE / SUCCESS: "
+                  << toString(*updatedValue);
+        onPropertyValueFromCar(*updatedValue, updateStatus);
+        return StatusCode::OK;
+    }
+
+    // mSwitchUserResponseFromCmd is used for just one request
+    std::unique_ptr<VehiclePropValue> response = std::move(mSwitchUserResponseFromCmd);
+
+    // TODO(b/150409377): move code below to a local function like sendUserHalResponse(),
+    // as it's the same for all (like onSetInitialUserInfoResponse)
+
+    switch (response->areaId) {
+        case 1:
+            LOG(INFO) << "returning response with right request id";
+            *updatedValue = *response;
+            updatedValue->areaId = 0;
+            updatedValue->value.int32Values[0] = requestId;
+            break;
+        case 2:
+            LOG(INFO) << "returning response with wrong request id";
+            *updatedValue = *response;
+            updatedValue->areaId = 0;
+            updatedValue->value.int32Values[0] = -requestId;
+            break;
+        case 3:
+            LOG(INFO) << "not generating a property change event because of lshal prop: "
+                      << toString(*response);
+            return StatusCode::OK;
+        default:
+            LOG(ERROR) << "invalid action on lshal response: " << toString(*response);
+            return StatusCode::INTERNAL_ERROR;
+    }
+
+    LOG(INFO) << "updating property to: " << toString(*updatedValue);
+    onPropertyValueFromCar(*updatedValue, updateStatus);
+
+    return StatusCode::OK;
+}
+
 }  // namespace android::hardware::automotive::vehicle::V2_0::impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
index b1ae106..20e094a 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
@@ -53,13 +53,15 @@
     VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode,
                                              int32_t targetDisplay);
 
-    StatusCode onSetInitialUserInfo(const VehiclePropValue& value, bool updateStatus);
+    StatusCode onSetInitialUserInfoResponse(const VehiclePropValue& value, bool updateStatus);
+    StatusCode onSetSwitchUserResponse(const VehiclePropValue& value, bool updateStatus);
 
-  // data members
+    // data members
 
   protected:
     // TODO(b/146207078): it might be clearer to move members below to an EmulatedUserHal class
     std::unique_ptr<VehiclePropValue> mInitialUserResponseFromCmd;
+    std::unique_ptr<VehiclePropValue> mSwitchUserResponseFromCmd;
 
   private:
     GeneratorHub mGeneratorHub{
diff --git a/biometrics/face/1.1/default/Android.bp b/biometrics/face/1.0/default/Android.bp
similarity index 84%
rename from biometrics/face/1.1/default/Android.bp
rename to biometrics/face/1.0/default/Android.bp
index 360071f..d6ff087 100644
--- a/biometrics/face/1.1/default/Android.bp
+++ b/biometrics/face/1.0/default/Android.bp
@@ -15,10 +15,10 @@
  */
 
 cc_binary {
-    name: "android.hardware.biometrics.face@1.1-service.example",
+    name: "android.hardware.biometrics.face@1.0-service.example",
     defaults: ["hidl_defaults"],
     vendor: true,
-    init_rc: ["android.hardware.biometrics.face@1.1-service.rc"],
+    init_rc: ["android.hardware.biometrics.face@1.0-service.rc"],
     vintf_fragments: ["manifest_face_default.xml"],
     relative_install_path: "hw",
     proprietary: true,
@@ -31,6 +31,5 @@
         "libutils",
         "liblog",
         "android.hardware.biometrics.face@1.0",
-        "android.hardware.biometrics.face@1.1",
     ],
 }
diff --git a/biometrics/face/1.1/default/BiometricsFace.cpp b/biometrics/face/1.0/default/BiometricsFace.cpp
similarity index 81%
rename from biometrics/face/1.1/default/BiometricsFace.cpp
rename to biometrics/face/1.0/default/BiometricsFace.cpp
index 2143880..2dd6476 100644
--- a/biometrics/face/1.1/default/BiometricsFace.cpp
+++ b/biometrics/face/1.0/default/BiometricsFace.cpp
@@ -110,20 +110,4 @@
     return Status::OK;
 }
 
-// Methods from ::android::hardware::biometrics::face::V1_1::IBiometricsFace follow.
-Return<Status> BiometricsFace::enroll_1_1(const hidl_vec<uint8_t>& /* hat */,
-                                          uint32_t /* timeoutSec */,
-                                          const hidl_vec<Feature>& /* disabledFeatures */,
-                                          const hidl_handle& /* windowId */) {
-    mClientCallback->onError(kDeviceId, mUserId, FaceError::UNABLE_TO_PROCESS, 0 /* vendorCode */);
-    return Status::OK;
-}
-
-Return<Status> BiometricsFace::enrollRemotely(const hidl_vec<uint8_t>& /* hat */,
-                                              uint32_t /* timeoutSec */,
-                                              const hidl_vec<Feature>& /* disabledFeatures */) {
-    mClientCallback->onError(kDeviceId, mUserId, FaceError::UNABLE_TO_PROCESS, 0 /* vendorCode */);
-    return Status::OK;
-}
-
 }  // namespace android::hardware::biometrics::face::implementation
diff --git a/biometrics/face/1.1/default/BiometricsFace.h b/biometrics/face/1.0/default/BiometricsFace.h
similarity index 81%
rename from biometrics/face/1.1/default/BiometricsFace.h
rename to biometrics/face/1.0/default/BiometricsFace.h
index 5ce5771..1d99ed2 100644
--- a/biometrics/face/1.1/default/BiometricsFace.h
+++ b/biometrics/face/1.0/default/BiometricsFace.h
@@ -16,7 +16,7 @@
 
 #pragma once
 
-#include <android/hardware/biometrics/face/1.1/IBiometricsFace.h>
+#include <android/hardware/biometrics/face/1.0/IBiometricsFace.h>
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
 #include <random>
@@ -34,7 +34,7 @@
 using ::android::hardware::biometrics::face::V1_0::IBiometricsFaceClientCallback;
 using ::android::hardware::biometrics::face::V1_0::Status;
 
-class BiometricsFace : public V1_1::IBiometricsFace {
+class BiometricsFace : public V1_0::IBiometricsFace {
   public:
     BiometricsFace();
 
@@ -71,14 +71,6 @@
 
     Return<Status> resetLockout(const hidl_vec<uint8_t>& hat) override;
 
-    // Methods from ::android::hardware::biometrics::face::V1_1::IBiometricsFace follow.
-    Return<Status> enroll_1_1(const hidl_vec<uint8_t>& hat, uint32_t timeoutSec,
-                              const hidl_vec<Feature>& disabledFeatures,
-                              const hidl_handle& windowId) override;
-
-    Return<Status> enrollRemotely(const hidl_vec<uint8_t>& hat, uint32_t timeoutSec,
-                                  const hidl_vec<Feature>& disabledFeatures) override;
-
   private:
     std::mt19937 mRandom;
     int32_t mUserId;
diff --git a/biometrics/face/1.1/default/android.hardware.biometrics.face@1.1-service.rc b/biometrics/face/1.0/default/android.hardware.biometrics.face@1.0-service.rc
similarity index 75%
rename from biometrics/face/1.1/default/android.hardware.biometrics.face@1.1-service.rc
rename to biometrics/face/1.0/default/android.hardware.biometrics.face@1.0-service.rc
index 687e2d8..6c7362f 100644
--- a/biometrics/face/1.1/default/android.hardware.biometrics.face@1.1-service.rc
+++ b/biometrics/face/1.0/default/android.hardware.biometrics.face@1.0-service.rc
@@ -1,4 +1,4 @@
-service vendor.face-hal-1-1-default /vendor/bin/hw/android.hardware.biometrics.face@1.1-service.example
+service vendor.face-hal-1-0-default /vendor/bin/hw/android.hardware.biometrics.face@1.0-service.example
     # "class hal" causes a race condition on some devices due to files created
     # in /data. As a workaround, postpone startup until later in boot once
     # /data is mounted.
diff --git a/biometrics/face/1.1/default/manifest_face_default.xml b/biometrics/face/1.0/default/manifest_face_default.xml
similarity index 90%
rename from biometrics/face/1.1/default/manifest_face_default.xml
rename to biometrics/face/1.0/default/manifest_face_default.xml
index ec71d9c..380ae49 100644
--- a/biometrics/face/1.1/default/manifest_face_default.xml
+++ b/biometrics/face/1.0/default/manifest_face_default.xml
@@ -2,7 +2,7 @@
     <hal format="hidl">
         <name>android.hardware.biometrics.face</name>
         <transport>hwbinder</transport>
-        <version>1.1</version>
+        <version>1.0</version>
         <interface>
             <name>IBiometricsFace</name>
             <instance>default</instance>
diff --git a/biometrics/face/1.1/default/service.cpp b/biometrics/face/1.0/default/service.cpp
similarity index 88%
rename from biometrics/face/1.1/default/service.cpp
rename to biometrics/face/1.0/default/service.cpp
index 344bdb9..9818c95 100644
--- a/biometrics/face/1.1/default/service.cpp
+++ b/biometrics/face/1.0/default/service.cpp
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "android.hardware.biometrics.face@1.1-service"
+#define LOG_TAG "android.hardware.biometrics.face@1.0-service"
 
 #include <android/hardware/biometrics/face/1.0/types.h>
-#include <android/hardware/biometrics/face/1.1/IBiometricsFace.h>
+#include <android/hardware/biometrics/face/1.0/IBiometricsFace.h>
 #include <android/log.h>
 #include <hidl/HidlSupport.h>
 #include <hidl/HidlTransportSupport.h>
@@ -27,7 +27,7 @@
 using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
 using android::hardware::biometrics::face::implementation::BiometricsFace;
-using android::hardware::biometrics::face::V1_1::IBiometricsFace;
+using android::hardware::biometrics::face::V1_0::IBiometricsFace;
 
 int main() {
     ALOGI("BiometricsFace HAL is being started.");
diff --git a/biometrics/face/1.1/Android.bp b/biometrics/face/1.1/Android.bp
deleted file mode 100644
index 2206597..0000000
--- a/biometrics/face/1.1/Android.bp
+++ /dev/null
@@ -1,17 +0,0 @@
-// This file is autogenerated by hidl-gen -Landroidbp.
-
-hidl_interface {
-    name: "android.hardware.biometrics.face@1.1",
-    root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
-    srcs: [
-        "IBiometricsFace.hal",
-    ],
-    interfaces: [
-        "android.hardware.biometrics.face@1.0",
-        "android.hidl.base@1.0",
-    ],
-    gen_java: true,
-}
diff --git a/biometrics/face/1.1/IBiometricsFace.hal b/biometrics/face/1.1/IBiometricsFace.hal
deleted file mode 100644
index 84e7443..0000000
--- a/biometrics/face/1.1/IBiometricsFace.hal
+++ /dev/null
@@ -1,117 +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.biometrics.face@1.1;
-
-import @1.0::IBiometricsFace;
-import @1.0::Status;
-import @1.0::Feature;
-
-/**
- * The HAL interface for biometric face authentication.
- */
-interface IBiometricsFace extends @1.0::IBiometricsFace {
-    /**
-     * Enrolls a user's face for a remote client, for example Android Auto.
-     *
-     * The HAL implementation is responsible for creating a secure communication
-     * channel and receiving the enrollment images from a mobile device with
-     * face authentication hardware.
-     *
-     * Note that the Hardware Authentication Token must be valid for the
-     * duration of enrollment and thus should be explicitly invalidated by a
-     * call to revokeChallenge() when enrollment is complete, to reduce the
-     * window of opportunity to re-use the challenge and HAT. For example,
-     * Settings calls generateChallenge() once to allow the user to enroll one
-     * or more faces or toggle secure settings without having to re-enter the
-     * PIN/pattern/password. Once the user completes the operation, Settings
-     * invokes revokeChallenge() to close the transaction. If the HAT is expired,
-     * the implementation must invoke onError with UNABLE_TO_PROCESS.
-     *
-     * Requirements for using this API:
-     * - Mobile devices MUST NOT delegate enrollment to another device by calling
-     * this API. This feature is intended only to allow enrollment on devices
-     * where it is impossible to enroll locally on the device.
-     * - The path MUST be protected by a secret key with rollback protection.
-     * - Synchronizing between devices MUST be accomplished by having both
-     * devices agree on a secret PIN entered by the user (similar to BT
-     * pairing procedure) and use a salted version of that PIN plus other secret
-     * to encrypt traffic.
-     * - All communication to/from the remote device MUST be encrypted and signed
-     * to prevent image injection and other man-in-the-middle type attacks.
-     * - generateChallenge() and revokeChallenge() MUST be implemented on both
-     * remote and local host (e.g. hash the result of the remote host with a
-     * local secret before responding to the API call) and any transmission of
-     * the challenge between hosts MUST be signed to prevent man-in-the-middle
-     * attacks.
-     * - In the event of a lost connection, the result of the last
-     * generateChallenge() MUST be invalidated and the process started over.
-     * - Both the remote and local host MUST honor the timeout and invalidate the
-     * challenge.
-     *
-     * This method triggers the IBiometricsFaceClientCallback#onEnrollResult()
-     * method.
-     *
-     * @param hat A valid Hardware Authentication Token, generated as a result
-     *     of a generateChallenge() challenge being wrapped by the gatekeeper
-     *     after a successful strong authentication request.
-     * @param timeoutSec A timeout in seconds, after which this enroll
-     *     attempt is cancelled. Note that the framework can continue
-     *     enrollment by calling this again with a valid HAT. This timeout is
-     *     expected to be used to limit power usage if the device becomes idle
-     *     during enrollment. The implementation is expected to send
-     *     ERROR_TIMEOUT if this happens.
-     * @param disabledFeatures A list of features to be disabled during
-     *     enrollment. Note that all features are enabled by default.
-     * @return status The status of this method call.
-     */
-    enrollRemotely(vec<uint8_t> hat, uint32_t timeoutSec, vec<Feature> disabledFeatures)
-        generates (Status status);
-
-    /**
-     * Enrolls a user's face.
-     *
-     * Note that the Hardware Authentication Token must be valid for the
-     * duration of enrollment and thus should be explicitly invalidated by a
-     * call to revokeChallenge() when enrollment is complete, to reduce the
-     * window of opportunity to re-use the challenge and HAT. For example,
-     * Settings calls generateChallenge() once to allow the user to enroll one
-     * or more faces or toggle secure settings without having to re-enter the
-     * PIN/pattern/password. Once the user completes the operation, Settings
-     * invokes revokeChallenge() to close the transaction. If the HAT is expired,
-     * the implementation must invoke onError with UNABLE_TO_PROCESS.
-     *
-     * This method triggers the IBiometricsFaceClientCallback#onEnrollResult()
-     * method.
-     *
-     * @param hat A valid Hardware Authentication Token, generated as a result
-     *     of a generateChallenge() challenge being wrapped by the gatekeeper
-     *     after a successful strong authentication request.
-     * @param timeoutSec A timeout in seconds, after which this enroll
-     *     attempt is cancelled. Note that the framework can continue
-     *     enrollment by calling this again with a valid HAT. This timeout is
-     *     expected to be used to limit power usage if the device becomes idle
-     *     during enrollment. The implementation is expected to send
-     *     ERROR_TIMEOUT if this happens.
-     * @param disabledFeatures A list of features to be disabled during
-     *     enrollment. Note that all features are enabled by default.
-     * @param windowId optional ID of a camera preview window for a
-     *     single-camera device. Must be null if not used.
-     * @return status The status of this method call.
-     */
-    enroll_1_1(vec<uint8_t> hat, uint32_t timeoutSec, vec<Feature> disabledFeatures,
-        handle windowId) generates (Status status);
-};
diff --git a/biometrics/face/1.1/vts/functional/Android.bp b/biometrics/face/1.1/vts/functional/Android.bp
deleted file mode 100644
index ccbb399..0000000
--- a/biometrics/face/1.1/vts/functional/Android.bp
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2020 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: "VtsHalBiometricsFaceV1_1TargetTest",
-    defaults: ["VtsHalTargetTestDefaults"],
-    srcs: ["VtsHalBiometricsFaceV1_1TargetTest.cpp"],
-    static_libs: [
-        "android.hardware.biometrics.face@1.0",
-        "android.hardware.biometrics.face@1.1",
-    ],
-    test_suites: [
-        "general-tests",
-        "vts-core",
-    ],
-}
diff --git a/biometrics/face/1.1/vts/functional/VtsHalBiometricsFaceV1_1TargetTest.cpp b/biometrics/face/1.1/vts/functional/VtsHalBiometricsFaceV1_1TargetTest.cpp
deleted file mode 100644
index 6ada442..0000000
--- a/biometrics/face/1.1/vts/functional/VtsHalBiometricsFaceV1_1TargetTest.cpp
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright 2020 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 "biometrics_face_hidl_hal_test"
-
-#include <android/hardware/biometrics/face/1.0/IBiometricsFaceClientCallback.h>
-#include <android/hardware/biometrics/face/1.1/IBiometricsFace.h>
-
-#include <VtsHalHidlTargetCallbackBase.h>
-#include <android-base/logging.h>
-#include <gtest/gtest.h>
-#include <hidl/GtestPrinter.h>
-#include <hidl/ServiceManagement.h>
-
-#include <chrono>
-#include <cstdint>
-#include <random>
-
-using android::sp;
-using android::hardware::hidl_handle;
-using android::hardware::hidl_vec;
-using android::hardware::Return;
-using android::hardware::Void;
-using android::hardware::biometrics::face::V1_0::FaceAcquiredInfo;
-using android::hardware::biometrics::face::V1_0::FaceError;
-using android::hardware::biometrics::face::V1_0::IBiometricsFaceClientCallback;
-using android::hardware::biometrics::face::V1_0::OptionalUint64;
-using android::hardware::biometrics::face::V1_0::Status;
-using android::hardware::biometrics::face::V1_1::IBiometricsFace;
-
-namespace {
-
-// Arbitrary, nonexistent userId
-constexpr uint32_t kUserId = 9;
-constexpr uint32_t kTimeoutSec = 3;
-constexpr auto kTimeout = std::chrono::seconds(kTimeoutSec);
-constexpr char kFacedataDir[] = "/data/vendor_de/0/facedata";
-constexpr char kCallbackNameOnError[] = "onError";
-
-// Callback arguments that need to be captured for the tests.
-struct FaceCallbackArgs {
-    // The error passed to the last onError() callback.
-    FaceError error;
-
-    // The userId passed to the last callback.
-    int32_t userId;
-};
-
-// Test callback class for the BiometricsFace HAL.
-// The HAL will call these callback methods to notify about completed operations
-// or encountered errors.
-class FaceCallback : public ::testing::VtsHalHidlTargetCallbackBase<FaceCallbackArgs>,
-                     public IBiometricsFaceClientCallback {
-  public:
-    Return<void> onEnrollResult(uint64_t, uint32_t, int32_t, uint32_t) override { return Void(); }
-
-    Return<void> onAuthenticated(uint64_t, uint32_t, int32_t, const hidl_vec<uint8_t>&) override {
-        return Void();
-    }
-
-    Return<void> onAcquired(uint64_t, int32_t, FaceAcquiredInfo, int32_t) override {
-        return Void();
-    }
-
-    Return<void> onError(uint64_t, int32_t userId, FaceError error, int32_t) override {
-        FaceCallbackArgs args = {};
-        args.error = error;
-        args.userId = userId;
-        NotifyFromCallback(kCallbackNameOnError, args);
-        return Void();
-    }
-
-    Return<void> onRemoved(uint64_t, const hidl_vec<uint32_t>&, int32_t) override { return Void(); }
-
-    Return<void> onEnumerate(uint64_t, const hidl_vec<uint32_t>&, int32_t) override {
-        return Void();
-    }
-
-    Return<void> onLockoutChanged(uint64_t) override { return Void(); }
-};
-
-// Test class for the BiometricsFace HAL.
-class FaceHidlTest : public ::testing::TestWithParam<std::string> {
-  public:
-    void SetUp() override {
-        mService = IBiometricsFace::getService(GetParam());
-        ASSERT_NE(mService, nullptr);
-        mCallback = new FaceCallback();
-        mCallback->SetWaitTimeoutDefault(kTimeout);
-        Return<void> ret1 = mService->setCallback(mCallback, [](const OptionalUint64& res) {
-            ASSERT_EQ(Status::OK, res.status);
-            // Makes sure the "deviceId" represented by "res.value" is not 0.
-            // 0 would mean the HIDL is not available.
-            ASSERT_NE(0UL, res.value);
-        });
-        ASSERT_TRUE(ret1.isOk());
-        Return<Status> ret2 = mService->setActiveUser(kUserId, kFacedataDir);
-        ASSERT_EQ(Status::OK, static_cast<Status>(ret2));
-    }
-
-    void TearDown() override {}
-
-    sp<IBiometricsFace> mService;
-    sp<FaceCallback> mCallback;
-};
-
-// enroll with an invalid (all zeroes) HAT should fail.
-TEST_P(FaceHidlTest, Enroll2_2ZeroHatTest) {
-    // Filling HAT with zeros
-    hidl_vec<uint8_t> token(69);
-    for (size_t i = 0; i < 69; i++) {
-        token[i] = 0;
-    }
-
-    hidl_handle windowId = nullptr;
-    Return<Status> ret = mService->enroll_1_1(token, kTimeoutSec, {}, windowId);
-    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
-
-    // onError should be called with a meaningful (nonzero) error.
-    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
-    EXPECT_TRUE(res.no_timeout);
-    EXPECT_EQ(kUserId, res.args->userId);
-    EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error);
-}
-
-// enroll with an invalid HAT should fail.
-TEST_P(FaceHidlTest, Enroll2_2GarbageHatTest) {
-    // Filling HAT with pseudorandom invalid data.
-    // Using default seed to make the test reproducible.
-    std::mt19937 gen(std::mt19937::default_seed);
-    std::uniform_int_distribution<uint8_t> dist;
-    hidl_vec<uint8_t> token(69);
-    for (size_t i = 0; i < 69; ++i) {
-        token[i] = dist(gen);
-    }
-
-    hidl_handle windowId = nullptr;
-    Return<Status> ret = mService->enroll_1_1(token, kTimeoutSec, {}, windowId);
-    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
-
-    // onError should be called with a meaningful (nonzero) error.
-    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
-    EXPECT_TRUE(res.no_timeout);
-    EXPECT_EQ(kUserId, res.args->userId);
-    EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error);
-}
-
-// enroll with an invalid (all zeroes) HAT should fail.
-TEST_P(FaceHidlTest, EnrollRemotelyZeroHatTest) {
-    // Filling HAT with zeros
-    hidl_vec<uint8_t> token(69);
-    for (size_t i = 0; i < 69; i++) {
-        token[i] = 0;
-    }
-
-    Return<Status> ret = mService->enrollRemotely(token, kTimeoutSec, {});
-    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
-
-    // onError should be called with a meaningful (nonzero) error.
-    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
-    EXPECT_TRUE(res.no_timeout);
-    EXPECT_EQ(kUserId, res.args->userId);
-    EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error);
-}
-
-// enroll with an invalid HAT should fail.
-TEST_P(FaceHidlTest, EnrollRemotelyGarbageHatTest) {
-    // Filling HAT with pseudorandom invalid data.
-    // Using default seed to make the test reproducible.
-    std::mt19937 gen(std::mt19937::default_seed);
-    std::uniform_int_distribution<uint8_t> dist;
-    hidl_vec<uint8_t> token(69);
-    for (size_t i = 0; i < 69; ++i) {
-        token[i] = dist(gen);
-    }
-
-    Return<Status> ret = mService->enrollRemotely(token, kTimeoutSec, {});
-    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
-
-    // onError should be called with a meaningful (nonzero) error.
-    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
-    EXPECT_TRUE(res.no_timeout);
-    EXPECT_EQ(kUserId, res.args->userId);
-    EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error);
-}
-
-}  // anonymous namespace
-
-INSTANTIATE_TEST_SUITE_P(
-        PerInstance, FaceHidlTest,
-        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IBiometricsFace::descriptor)),
-        android::hardware::PrintInstanceNameToString);
diff --git a/biometrics/fingerprint/2.2/IBiometricsFingerprint.hal b/biometrics/fingerprint/2.2/IBiometricsFingerprint.hal
index 0651034..249830a 100644
--- a/biometrics/fingerprint/2.2/IBiometricsFingerprint.hal
+++ b/biometrics/fingerprint/2.2/IBiometricsFingerprint.hal
@@ -17,42 +17,12 @@
 package android.hardware.biometrics.fingerprint@2.2;
 
 import @2.1::IBiometricsFingerprint;
-import @2.1::RequestStatus;
 
+/**
+ * The HAL interface for biometric fingerprint authentication.
+ *
+ * This interface is required because all top-level interfaces need to be
+ * updated in a minor uprev.
+ */
 interface IBiometricsFingerprint extends @2.1::IBiometricsFingerprint {
-    /**
-     * Fingerprint enroll request:
-     * Switches the HAL state machine to collect and store a new fingerprint
-     * template. Switches back as soon as enroll is complete, signalled by
-     * (fingerprintMsg.type == FINGERPRINT_TEMPLATE_ENROLLING &&
-     *  fingerprintMsg.data.enroll.samplesRemaining == 0)
-     * or after timeoutSec seconds.
-     * The fingerprint template must be assigned to the group gid.
-     *
-     * @param hat a valid Hardware Authentication Token (HAT), generated
-     * as a result of a preEnroll() call.
-     * @param gid a framework defined fingerprint set (group) id.
-     * @param timeoutSec a timeout in seconds.
-     * @param windowId optional ID of an illumination window for optical under
-     * display fingerprint sensors. Must contain a null pointer if not used.
-     *
-     * @return debugErrno is a value the framework logs in case it is not 0.
-     *
-     * A notify() function may be called with a more detailed error structure.
-     */
-    enroll_2_2(vec<uint8_t> hat, uint32_t gid, uint32_t timeoutSec, handle windowId)
-        generates (RequestStatus debugErrno);
-
-    /**
-     * Authenticates an operation identified by operationId
-     *
-     * @param operationId operation id.
-     * @param gid fingerprint group id.
-     * @param windowId optional ID of an illumination window for optical under
-     * display fingerprint sensors. Must contain a null pointer if not used.
-     *
-     * @return debugErrno is a value the framework logs in case it is not 0.
-     */
-    authenticate_2_2(uint64_t operationId, uint32_t gid, handle windowId)
-        generates (RequestStatus debugErrno);
 };
diff --git a/biometrics/fingerprint/2.2/vts/functional/VtsHalBiometricsFingerprintV2_2TargetTest.cpp b/biometrics/fingerprint/2.2/vts/functional/VtsHalBiometricsFingerprintV2_2TargetTest.cpp
index 50bd4ab..df29fd4 100644
--- a/biometrics/fingerprint/2.2/vts/functional/VtsHalBiometricsFingerprintV2_2TargetTest.cpp
+++ b/biometrics/fingerprint/2.2/vts/functional/VtsHalBiometricsFingerprintV2_2TargetTest.cpp
@@ -18,65 +18,66 @@
 
 #include <VtsHalHidlTargetCallbackBase.h>
 #include <android-base/properties.h>
-#include <android/hardware/biometrics/fingerprint/2.1/IBiometricsFingerprintClientCallback.h>
-#include <android/hardware/biometrics/fingerprint/2.2/IBiometricsFingerprint.h>
+#include <android/hardware/biometrics/fingerprint/2.1/IBiometricsFingerprint.h>
+#include <android/hardware/biometrics/fingerprint/2.2/IBiometricsFingerprintClientCallback.h>
 #include <gtest/gtest.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/HidlSupport.h>
 #include <hidl/ServiceManagement.h>
 
 #include <cinttypes>
-#include <random>
+
+namespace {
+
+namespace hidl_interface = android::hardware::biometrics::fingerprint::V2_1;
+namespace hidl_interface_2_2 = android::hardware::biometrics::fingerprint::V2_2;
+
+using hidl_interface::FingerprintError;
+using hidl_interface::IBiometricsFingerprint;
+using hidl_interface::RequestStatus;
 
 using android::sp;
 using android::base::GetUintProperty;
-using android::hardware::hidl_handle;
 using android::hardware::hidl_vec;
 using android::hardware::Return;
 using android::hardware::Void;
-using android::hardware::biometrics::fingerprint::V2_1::FingerprintAcquiredInfo;
-using android::hardware::biometrics::fingerprint::V2_1::FingerprintError;
-using android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprintClientCallback;
-using android::hardware::biometrics::fingerprint::V2_1::RequestStatus;
-using android::hardware::biometrics::fingerprint::V2_2::IBiometricsFingerprint;
-
-namespace {
 
 constexpr uint32_t kTimeoutSec = 3;
 constexpr auto kTimeout = std::chrono::seconds(kTimeoutSec);
 constexpr uint32_t kGroupId = 99;
-constexpr char kCallbackNameOnError[] = "onError";
+constexpr char kCallbackNameOnAcquired[] = "onAcquired";
 
 // Callback arguments that need to be captured for the tests.
 struct FingerprintCallbackArgs {
-    // The error passed to the last onError() callback.
-    FingerprintError error;
-
-    // The deviceId passed to the last callback.
-    uint64_t deviceId;
+    // The info passed to the last onAcquired() callback.
+    hidl_interface_2_2::FingerprintAcquiredInfo info;
 };
 
 // Test callback class for the BiometricsFingerprint HAL.
 // The HAL will call these callback methods to notify about completed operations
 // or encountered errors.
 class FingerprintCallback : public ::testing::VtsHalHidlTargetCallbackBase<FingerprintCallbackArgs>,
-                            public IBiometricsFingerprintClientCallback {
+                            public hidl_interface_2_2::IBiometricsFingerprintClientCallback {
   public:
     Return<void> onEnrollResult(uint64_t, uint32_t, uint32_t, uint32_t) override { return Void(); }
 
-    Return<void> onAcquired(uint64_t, FingerprintAcquiredInfo, int32_t) override { return Void(); }
+    Return<void> onAcquired(uint64_t, hidl_interface::FingerprintAcquiredInfo, int32_t) override {
+        return Void();
+    }
+
+    Return<void> onAcquired_2_2(uint64_t, hidl_interface_2_2::FingerprintAcquiredInfo info,
+                                int32_t) override {
+        FingerprintCallbackArgs args = {};
+        args.info = info;
+        NotifyFromCallback(kCallbackNameOnAcquired, args);
+        return Void();
+    }
 
     Return<void> onAuthenticated(uint64_t, uint32_t, uint32_t, const hidl_vec<uint8_t>&) override {
         return Void();
     }
 
-    Return<void> onError(uint64_t deviceId, FingerprintError error, int32_t) override {
-        FingerprintCallbackArgs args = {};
-        args.error = error;
-        args.deviceId = deviceId;
-        NotifyFromCallback(kCallbackNameOnError, args);
-        return Void();
-    }
+    Return<void> onError(uint64_t, FingerprintError, int32_t) override { return Void(); }
 
     Return<void> onRemoved(uint64_t, uint32_t, uint32_t, uint32_t) override { return Void(); }
 
@@ -121,41 +122,16 @@
     sp<FingerprintCallback> mCallback;
 };
 
-// Enroll with an invalid (all zeroes) HAT should fail.
-TEST_P(FingerprintHidlTest, EnrollZeroHatTest) {
-    // Filling HAT with zeros
-    hidl_vec<uint8_t> token(69);
-    for (size_t i = 0; i < 69; i++) {
-        token[i] = 0;
-    }
-
-    hidl_handle windowId = nullptr;
-    Return<RequestStatus> ret = mService->enroll_2_2(token, kGroupId, kTimeoutSec, windowId);
-    ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(ret));
-
-    // At least one call to onError should occur
-    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
-    ASSERT_NE(FingerprintError::ERROR_NO_ERROR, res.args->error);
-}
-
-// Enroll with an invalid (null) HAT should fail.
-TEST_P(FingerprintHidlTest, EnrollGarbageHatTest) {
-    // Filling HAT with pseudorandom invalid data.
-    // Using default seed to make the test reproducible.
-    std::mt19937 gen(std::mt19937::default_seed);
-    std::uniform_int_distribution<uint8_t> dist;
-    hidl_vec<uint8_t> token(69);
-    for (size_t i = 0; i < 69; ++i) {
-        token[i] = dist(gen);
-    }
-
-    hidl_handle windowId = nullptr;
-    Return<RequestStatus> ret = mService->enroll_2_2(token, kGroupId, kTimeoutSec, windowId);
-    ASSERT_EQ(RequestStatus::SYS_OK, static_cast<RequestStatus>(ret));
-
-    // At least one call to onError should occur
-    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
-    ASSERT_NE(FingerprintError::ERROR_NO_ERROR, res.args->error);
+// The START message and onAcquired_2_2 method should exist and work together correctly.
+// Note, this test doesn't use the HAL. It just makes sure that the newly added constant and
+// callback compile. Unfortunately, there is no way to test the usage of the constant within the
+// actual HAL.
+TEST_P(FingerprintHidlTest, acquiredInfoStartTest) {
+    mCallback->SetWaitTimeoutDefault(kTimeout);
+    mCallback->onAcquired_2_2(0 /* deviceId */, hidl_interface_2_2::FingerprintAcquiredInfo::START,
+                              0 /* vendorCode */);
+    auto res = mCallback->WaitForCallback(kCallbackNameOnAcquired);
+    ASSERT_EQ(hidl_interface_2_2::FingerprintAcquiredInfo::START, res.args->info);
 }
 
 }  // anonymous namespace
diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp
index f518a15..677b496 100644
--- a/camera/device/3.4/default/ExternalCameraDevice.cpp
+++ b/camera/device/3.4/default/ExternalCameraDevice.cpp
@@ -20,6 +20,7 @@
 
 #include <algorithm>
 #include <array>
+#include <regex>
 #include <linux/videodev2.h>
 #include "android-base/macros.h"
 #include "CameraMetadata.h"
@@ -46,10 +47,20 @@
 
 } // anonymous namespace
 
+const std::regex kDevicePathRE("/dev/video([0-9]+)");
+
 ExternalCameraDevice::ExternalCameraDevice(
-        const std::string& cameraId, const ExternalCameraConfig& cfg) :
-        mCameraId(cameraId),
-        mCfg(cfg) {}
+        const std::string& devicePath, const ExternalCameraConfig& cfg) :
+        mCameraId("-1"),
+        mDevicePath(devicePath),
+        mCfg(cfg) {
+    std::smatch sm;
+    if (std::regex_match(mDevicePath, sm, kDevicePathRE)) {
+        mCameraId = std::to_string(mCfg.cameraIdOffset + std::stoi(sm[1]));
+    } else {
+        ALOGE("%s: device path match failed for %s", __FUNCTION__, mDevicePath.c_str());
+    }
+}
 
 ExternalCameraDevice::~ExternalCameraDevice() {}
 
@@ -129,20 +140,20 @@
         return Void();
     }
 
-    unique_fd fd(::open(mCameraId.c_str(), O_RDWR));
+    unique_fd fd(::open(mDevicePath.c_str(), O_RDWR));
     if (fd.get() < 0) {
         int numAttempt = 0;
         do {
             ALOGW("%s: v4l2 device %s open failed, wait 33ms and try again",
-                    __FUNCTION__, mCameraId.c_str());
+                    __FUNCTION__, mDevicePath.c_str());
             usleep(OPEN_RETRY_SLEEP_US); // sleep and try again
-            fd.reset(::open(mCameraId.c_str(), O_RDWR));
+            fd.reset(::open(mDevicePath.c_str(), O_RDWR));
             numAttempt++;
         } while (fd.get() < 0 && numAttempt <= MAX_RETRY);
 
         if (fd.get() < 0) {
             ALOGE("%s: v4l2 device open %s failed: %s",
-                    __FUNCTION__, mCameraId.c_str(), strerror(errno));
+                    __FUNCTION__, mDevicePath.c_str(), strerror(errno));
             mLock.unlock();
             _hidl_cb(Status::INTERNAL_ERROR, nullptr);
             return Void();
@@ -203,9 +214,9 @@
 status_t ExternalCameraDevice::initCameraCharacteristics() {
     if (mCameraCharacteristics.isEmpty()) {
         // init camera characteristics
-        unique_fd fd(::open(mCameraId.c_str(), O_RDWR));
+        unique_fd fd(::open(mDevicePath.c_str(), O_RDWR));
         if (fd.get() < 0) {
-            ALOGE("%s: v4l2 device open %s failed", __FUNCTION__, mCameraId.c_str());
+            ALOGE("%s: v4l2 device open %s failed", __FUNCTION__, mDevicePath.c_str());
             return DEAD_OBJECT;
         }
 
diff --git a/camera/device/3.4/default/ExternalCameraUtils.cpp b/camera/device/3.4/default/ExternalCameraUtils.cpp
index 62a4c87..8f4626c 100644
--- a/camera/device/3.4/default/ExternalCameraUtils.cpp
+++ b/camera/device/3.4/default/ExternalCameraUtils.cpp
@@ -703,6 +703,7 @@
 namespace common {
 
 namespace {
+    const int kDefaultCameraIdOffset = 100;
     const int kDefaultJpegBufSize = 5 << 20; // 5MB
     const int kDefaultNumVideoBuffer = 4;
     const int kDefaultNumStillBuffer = 2;
@@ -738,6 +739,11 @@
         return ret;
     }
 
+    XMLElement *cameraIdOffset = providerCfg->FirstChildElement("CameraIdOffset");
+    if (cameraIdOffset != nullptr) {
+        ret.cameraIdOffset = std::atoi(cameraIdOffset->GetText());
+    }
+
     XMLElement *ignore = providerCfg->FirstChildElement("ignore");
     if (ignore == nullptr) {
         ALOGI("%s: no internal ignored device specified", __FUNCTION__);
@@ -874,6 +880,7 @@
 }
 
 ExternalCameraConfig::ExternalCameraConfig() :
+        cameraIdOffset(kDefaultCameraIdOffset),
         maxJpegBufSize(kDefaultJpegBufSize),
         numVideoBuffers(kDefaultNumVideoBuffer),
         numStillBuffers(kDefaultNumStillBuffer),
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
index 1958fcb..88726f4 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
@@ -149,6 +149,7 @@
     bool mInitialized = false;
     bool mInitFailed = false;
     std::string mCameraId;
+    std::string mDevicePath;
     const ExternalCameraConfig& mCfg;
     std::vector<SupportedV4L2Format> mSupportedFormats;
     CroppingType mCroppingType;
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
index 74f75eb..b354406 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
@@ -68,6 +68,9 @@
     static const char* kDefaultCfgPath;
     static ExternalCameraConfig loadFromCfg(const char* cfgPath = kDefaultCfgPath);
 
+    // CameraId base offset for numerical representation
+    uint32_t cameraIdOffset;
+
     // List of internal V4L2 video nodes external camera HAL must ignore.
     std::unordered_set<std::string> mInternalDevices;
 
diff --git a/camera/device/3.6/default/ExternalCameraDeviceSession.cpp b/camera/device/3.6/default/ExternalCameraDeviceSession.cpp
index 60a1a10..8fd8e58 100644
--- a/camera/device/3.6/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/3.6/default/ExternalCameraDeviceSession.cpp
@@ -272,16 +272,17 @@
 
     // convert hal requests to offline request
     std::deque<std::shared_ptr<HalRequest>> offlineReqs(halReqs.size());
+    size_t i = 0;
     for (auto& v4lReq : halReqs) {
-        std::shared_ptr<HalRequest> halReq = std::make_shared<HalRequest>();
-        halReq->frameNumber = v4lReq->frameNumber;
-        halReq->setting = v4lReq->setting;
-        halReq->shutterTs = v4lReq->shutterTs;
-        halReq->buffers = v4lReq->buffers;
+        offlineReqs[i] = std::make_shared<HalRequest>();
+        offlineReqs[i]->frameNumber = v4lReq->frameNumber;
+        offlineReqs[i]->setting = v4lReq->setting;
+        offlineReqs[i]->shutterTs = v4lReq->shutterTs;
+        offlineReqs[i]->buffers = v4lReq->buffers;
         sp<V3_4::implementation::V4L2Frame> v4l2Frame =
                 static_cast<V3_4::implementation::V4L2Frame*>(v4lReq->frameIn.get());
-        halReq->frameIn = new AllocatedV4L2Frame(v4l2Frame);
-        offlineReqs.push_back(halReq);
+        offlineReqs[i]->frameIn = new AllocatedV4L2Frame(v4l2Frame);
+        i++;
         // enqueue V4L2 frame
         enqueueV4l2Frame(v4l2Frame);
     }
diff --git a/camera/metadata/3.5/types.hal b/camera/metadata/3.5/types.hal
index 4e2252c..99d6115 100644
--- a/camera/metadata/3.5/types.hal
+++ b/camera/metadata/3.5/types.hal
@@ -35,28 +35,29 @@
  * '/system/media/camera/docs/docs.html' in the corresponding Android source tree.</p>
  */
 enum CameraMetadataTag : @3.4::CameraMetadataTag {
-    /** android.control.availableBokehMaxSizes [static, int32[], ndk_public]
+    /** android.control.availableExtendedSceneModeMaxSizes [static, int32[], ndk_public]
      *
-     * <p>The list of bokeh modes for ANDROID_CONTROL_BOKEH_MODE that are supported by this camera
-     * device, and each bokeh mode's maximum streaming (non-stall) size with bokeh effect.</p>
+     * <p>The list of extended scene modes for ANDROID_CONTROL_EXTENDED_SCENE_MODE that are supported
+     * by this camera device, and each extended scene mode's maximum streaming (non-stall) size
+     * with  effect.</p>
      *
-     * @see ANDROID_CONTROL_BOKEH_MODE
+     * @see ANDROID_CONTROL_EXTENDED_SCENE_MODE
      */
-    ANDROID_CONTROL_AVAILABLE_BOKEH_MAX_SIZES = android.hardware.camera.metadata@3.3::CameraMetadataTag:ANDROID_CONTROL_END_3_3,
+    ANDROID_CONTROL_AVAILABLE_EXTENDED_SCENE_MODE_MAX_SIZES = android.hardware.camera.metadata@3.3::CameraMetadataTag:ANDROID_CONTROL_END_3_3,
 
-    /** android.control.availableBokehZoomRatioRanges [static, float[], ndk_public]
+    /** android.control.availableExtendedSceneModeZoomRatioRanges [static, float[], ndk_public]
      *
-     * <p>The ranges of supported zoom ratio for non-OFF ANDROID_CONTROL_BOKEH_MODE.</p>
+     * <p>The ranges of supported zoom ratio for non-DISABLED ANDROID_CONTROL_EXTENDED_SCENE_MODE.</p>
      *
-     * @see ANDROID_CONTROL_BOKEH_MODE
+     * @see ANDROID_CONTROL_EXTENDED_SCENE_MODE
      */
-    ANDROID_CONTROL_AVAILABLE_BOKEH_ZOOM_RATIO_RANGES,
+    ANDROID_CONTROL_AVAILABLE_EXTENDED_SCENE_MODE_ZOOM_RATIO_RANGES,
 
-    /** android.control.bokehMode [dynamic, enum, public]
+    /** android.control.extendedSceneMode [dynamic, enum, public]
      *
-     * <p>Whether bokeh mode is enabled for a particular capture request.</p>
+     * <p>Whether extended scene mode is enabled for a particular capture request.</p>
      */
-    ANDROID_CONTROL_BOKEH_MODE,
+    ANDROID_CONTROL_EXTENDED_SCENE_MODE,
 
     /** android.control.zoomRatioRange [static, float[], public]
      *
@@ -72,7 +73,7 @@
 
     ANDROID_CONTROL_END_3_5,
 
-    /** android.scaler.availableRotateAndCropModes [static, byte[], public]
+    /** android.scaler.availableRotateAndCropModes [static, byte[], hidden]
      *
      * <p>List of rotate-and-crop modes for ANDROID_SCALER_ROTATE_AND_CROP that are supported by this camera device.</p>
      *
@@ -80,7 +81,7 @@
      */
     ANDROID_SCALER_AVAILABLE_ROTATE_AND_CROP_MODES = android.hardware.camera.metadata@3.4::CameraMetadataTag:ANDROID_SCALER_END_3_4,
 
-    /** android.scaler.rotateAndCrop [dynamic, enum, public]
+    /** android.scaler.rotateAndCrop [dynamic, enum, hidden]
      *
      * <p>Whether a rotation-and-crop operation is applied to processed
      * outputs from the camera.</p>
@@ -95,13 +96,22 @@
  * Enumeration definitions for the various entries that need them
  */
 
-/** android.control.bokehMode enumeration values
- * @see ANDROID_CONTROL_BOKEH_MODE
+/** android.control.mode enumeration values added since v3.2
+ * @see ANDROID_CONTROL_MODE
  */
-enum CameraMetadataEnumAndroidControlBokehMode : uint32_t {
-    ANDROID_CONTROL_BOKEH_MODE_OFF,
-    ANDROID_CONTROL_BOKEH_MODE_STILL_CAPTURE,
-    ANDROID_CONTROL_BOKEH_MODE_CONTINUOUS,
+enum CameraMetadataEnumAndroidControlMode :
+        @3.2::CameraMetadataEnumAndroidControlMode {
+    ANDROID_CONTROL_MODE_USE_EXTENDED_SCENE_MODE,
+};
+
+/** android.control.extendedSceneMode enumeration values
+ * @see ANDROID_CONTROL_EXTENDED_SCENE_MODE
+ */
+enum CameraMetadataEnumAndroidControlExtendedSceneMode : uint32_t {
+    ANDROID_CONTROL_EXTENDED_SCENE_MODE_DISABLED                = 0,
+    ANDROID_CONTROL_EXTENDED_SCENE_MODE_BOKEH_STILL_CAPTURE,
+    ANDROID_CONTROL_EXTENDED_SCENE_MODE_BOKEH_CONTINUOUS,
+    ANDROID_CONTROL_EXTENDED_SCENE_MODE_VENDOR_START            = 0x40,
 };
 
 /** android.lens.poseReference enumeration values added since v3.3
diff --git a/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp b/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp
index 2bfced2..64a51f6 100644
--- a/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp
+++ b/camera/provider/2.4/default/ExternalCameraProviderImpl_2_4.cpp
@@ -44,17 +44,19 @@
 const char* kDevicePath = "/dev/";
 constexpr char kPrefix[] = "video";
 constexpr int kPrefixLen = sizeof(kPrefix) - 1;
+constexpr int kDevicePrefixLen = sizeof(kDevicePath) + kPrefixLen + 1;
 
-bool matchDeviceName(const hidl_string& deviceName, std::string* deviceVersion,
-                     std::string* cameraId) {
+bool matchDeviceName(int cameraIdOffset,
+                     const hidl_string& deviceName, std::string* deviceVersion,
+                     std::string* cameraDevicePath) {
     std::string deviceNameStd(deviceName.c_str());
     std::smatch sm;
     if (std::regex_match(deviceNameStd, sm, kDeviceNameRE)) {
         if (deviceVersion != nullptr) {
             *deviceVersion = sm[1];
         }
-        if (cameraId != nullptr) {
-            *cameraId = sm[2];
+        if (cameraDevicePath != nullptr) {
+            *cameraDevicePath = "/dev/video" + std::to_string(std::stoi(sm[2]) - cameraIdOffset);
         }
         return true;
     }
@@ -146,8 +148,9 @@
         const hidl_string& cameraDeviceName,
         ICameraProvider::getCameraDeviceInterface_V3_x_cb _hidl_cb) {
 
-    std::string cameraId, deviceVersion;
-    bool match = matchDeviceName(cameraDeviceName, &deviceVersion, &cameraId);
+    std::string cameraDevicePath, deviceVersion;
+    bool match = matchDeviceName(mCfg.cameraIdOffset, cameraDeviceName,
+                                 &deviceVersion, &cameraDevicePath);
     if (!match) {
         _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
         return Void();
@@ -164,19 +167,19 @@
         case 4: {
             ALOGV("Constructing v3.4 external camera device");
             deviceImpl = new device::V3_4::implementation::ExternalCameraDevice(
-                    cameraId, mCfg);
+                    cameraDevicePath, mCfg);
             break;
         }
         case 5: {
             ALOGV("Constructing v3.5 external camera device");
             deviceImpl = new device::V3_5::implementation::ExternalCameraDevice(
-                    cameraId, mCfg);
+                    cameraDevicePath, mCfg);
             break;
         }
         case 6: {
             ALOGV("Constructing v3.6 external camera device");
             deviceImpl = new device::V3_6::implementation::ExternalCameraDevice(
-                    cameraId, mCfg);
+                    cameraDevicePath, mCfg);
             break;
         }
         default:
@@ -186,7 +189,7 @@
     }
 
     if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
-        ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
+        ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraDevicePath.c_str());
         _hidl_cb(Status::INTERNAL_ERROR, nullptr);
         return Void();
     }
@@ -210,12 +213,14 @@
     ALOGI("ExtCam: adding %s to External Camera HAL!", devName);
     Mutex::Autolock _l(mLock);
     std::string deviceName;
+    std::string cameraId = std::to_string(mCfg.cameraIdOffset +
+                                          std::atoi(devName + kDevicePrefixLen));
     if (mPreferredHal3MinorVersion == 6) {
-        deviceName = std::string("device@3.6/external/") + devName;
+        deviceName = std::string("device@3.6/external/") + cameraId;
     } else if (mPreferredHal3MinorVersion == 5) {
-        deviceName = std::string("device@3.5/external/") + devName;
+        deviceName = std::string("device@3.5/external/") + cameraId;
     } else {
-        deviceName = std::string("device@3.4/external/") + devName;
+        deviceName = std::string("device@3.4/external/") + cameraId;
     }
     mCameraStatusMap[deviceName] = CameraDeviceStatus::PRESENT;
     if (mCallbacks != nullptr) {
@@ -259,12 +264,14 @@
 void ExternalCameraProviderImpl_2_4::deviceRemoved(const char* devName) {
     Mutex::Autolock _l(mLock);
     std::string deviceName;
+    std::string cameraId = std::to_string(mCfg.cameraIdOffset +
+                                          std::atoi(devName + kDevicePrefixLen));
     if (mPreferredHal3MinorVersion == 6) {
-        deviceName = std::string("device@3.6/external/") + devName;
+        deviceName = std::string("device@3.6/external/") + cameraId;
     } else if (mPreferredHal3MinorVersion == 5) {
-        deviceName = std::string("device@3.5/external/") + devName;
+        deviceName = std::string("device@3.5/external/") + cameraId;
     } else {
-        deviceName = std::string("device@3.4/external/") + devName;
+        deviceName = std::string("device@3.4/external/") + cameraId;
     }
     if (mCameraStatusMap.find(deviceName) != mCameraStatusMap.end()) {
         mCameraStatusMap.erase(deviceName);
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index c9d76da..05b8b47 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -784,7 +784,7 @@
             const CameraMetadata& chars, int deviceVersion,
             const hidl_vec<hidl_string>& deviceNames);
     void verifyCameraCharacteristics(Status status, const CameraMetadata& chars);
-    void verifyBokehCharacteristics(const camera_metadata_t* metadata);
+    void verifyExtendedSceneModeCharacteristics(const camera_metadata_t* metadata);
     void verifyZoomCharacteristics(const camera_metadata_t* metadata);
     void verifyRecommendedConfigs(const CameraMetadata& metadata);
     void verifyMonochromeCharacteristics(const CameraMetadata& chars, int deviceVersion);
@@ -6588,77 +6588,98 @@
                 poseReference >= ANDROID_LENS_POSE_REFERENCE_PRIMARY_CAMERA);
     }
 
-    verifyBokehCharacteristics(metadata);
+    verifyExtendedSceneModeCharacteristics(metadata);
     verifyZoomCharacteristics(metadata);
 }
 
-void CameraHidlTest::verifyBokehCharacteristics(const camera_metadata_t* metadata) {
+void CameraHidlTest::verifyExtendedSceneModeCharacteristics(const camera_metadata_t* metadata) {
     camera_metadata_ro_entry entry;
     int retcode = 0;
 
+    retcode = find_camera_metadata_ro_entry(metadata, ANDROID_CONTROL_AVAILABLE_MODES, &entry);
+    if ((0 == retcode) && (entry.count > 0)) {
+        for (auto i = 0; i < entry.count; i++) {
+            ASSERT_TRUE(entry.data.u8[i] >= ANDROID_CONTROL_MODE_OFF &&
+                        entry.data.u8[i] <= ANDROID_CONTROL_MODE_USE_EXTENDED_SCENE_MODE);
+        }
+    } else {
+        ADD_FAILURE() << "Get camera controlAvailableModes failed!";
+    }
+
     // Check key availability in capabilities, request and result.
 
     retcode = find_camera_metadata_ro_entry(metadata,
             ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, &entry);
-    bool hasBokehRequestKey = false;
+    bool hasExtendedSceneModeRequestKey = false;
     if ((0 == retcode) && (entry.count > 0)) {
-        hasBokehRequestKey = std::find(entry.data.i32, entry.data.i32+entry.count,
-                ANDROID_CONTROL_BOKEH_MODE) != entry.data.i32+entry.count;
+        hasExtendedSceneModeRequestKey =
+                std::find(entry.data.i32, entry.data.i32 + entry.count,
+                          ANDROID_CONTROL_EXTENDED_SCENE_MODE) != entry.data.i32 + entry.count;
     } else {
         ADD_FAILURE() << "Get camera availableRequestKeys failed!";
     }
 
     retcode = find_camera_metadata_ro_entry(metadata,
             ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, &entry);
-    bool hasBokehResultKey = false;
+    bool hasExtendedSceneModeResultKey = false;
     if ((0 == retcode) && (entry.count > 0)) {
-        hasBokehResultKey = std::find(entry.data.i32, entry.data.i32+entry.count,
-                ANDROID_CONTROL_BOKEH_MODE) != entry.data.i32+entry.count;
+        hasExtendedSceneModeResultKey =
+                std::find(entry.data.i32, entry.data.i32 + entry.count,
+                          ANDROID_CONTROL_EXTENDED_SCENE_MODE) != entry.data.i32 + entry.count;
     } else {
         ADD_FAILURE() << "Get camera availableResultKeys failed!";
     }
 
     retcode = find_camera_metadata_ro_entry(metadata,
             ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, &entry);
-    bool hasBokehMaxSizesKey = false;
-    bool hasBokehZoomRatioRangesKey = false;
+    bool hasExtendedSceneModeMaxSizesKey = false;
+    bool hasExtendedSceneModeZoomRatioRangesKey = false;
     if ((0 == retcode) && (entry.count > 0)) {
-        hasBokehMaxSizesKey = std::find(entry.data.i32, entry.data.i32+entry.count,
-                ANDROID_CONTROL_AVAILABLE_BOKEH_MAX_SIZES) != entry.data.i32+entry.count;
-        hasBokehZoomRatioRangesKey = std::find(entry.data.i32, entry.data.i32+entry.count,
-                ANDROID_CONTROL_AVAILABLE_BOKEH_ZOOM_RATIO_RANGES) != entry.data.i32+entry.count;
+        hasExtendedSceneModeMaxSizesKey =
+                std::find(entry.data.i32, entry.data.i32 + entry.count,
+                          ANDROID_CONTROL_AVAILABLE_EXTENDED_SCENE_MODE_MAX_SIZES) !=
+                entry.data.i32 + entry.count;
+        hasExtendedSceneModeZoomRatioRangesKey =
+                std::find(entry.data.i32, entry.data.i32 + entry.count,
+                          ANDROID_CONTROL_AVAILABLE_EXTENDED_SCENE_MODE_ZOOM_RATIO_RANGES) !=
+                entry.data.i32 + entry.count;
     } else {
         ADD_FAILURE() << "Get camera availableCharacteristicsKeys failed!";
     }
 
     camera_metadata_ro_entry maxSizesEntry;
-    retcode = find_camera_metadata_ro_entry(metadata,
-            ANDROID_CONTROL_AVAILABLE_BOKEH_MAX_SIZES, &maxSizesEntry);
-    bool hasBokehMaxSizes = (0 == retcode && maxSizesEntry.count > 0);
+    retcode = find_camera_metadata_ro_entry(
+            metadata, ANDROID_CONTROL_AVAILABLE_EXTENDED_SCENE_MODE_MAX_SIZES, &maxSizesEntry);
+    bool hasExtendedSceneModeMaxSizes = (0 == retcode && maxSizesEntry.count > 0);
 
     camera_metadata_ro_entry zoomRatioRangesEntry;
-    retcode = find_camera_metadata_ro_entry(metadata,
-            ANDROID_CONTROL_AVAILABLE_BOKEH_ZOOM_RATIO_RANGES, &zoomRatioRangesEntry);
-    bool hasBokehZoomRatioRanges = (0 == retcode && zoomRatioRangesEntry.count > 0);
+    retcode = find_camera_metadata_ro_entry(
+            metadata, ANDROID_CONTROL_AVAILABLE_EXTENDED_SCENE_MODE_ZOOM_RATIO_RANGES,
+            &zoomRatioRangesEntry);
+    bool hasExtendedSceneModeZoomRatioRanges = (0 == retcode && zoomRatioRangesEntry.count > 0);
 
-    // Bokeh keys must all be available, or all be unavailable.
-    bool noBokeh = !hasBokehRequestKey && !hasBokehResultKey && !hasBokehMaxSizesKey &&
-            !hasBokehZoomRatioRangesKey && !hasBokehMaxSizes && !hasBokehZoomRatioRanges;
-    if (noBokeh) {
+    // Extended scene mode keys must all be available, or all be unavailable.
+    bool noExtendedSceneMode =
+            !hasExtendedSceneModeRequestKey && !hasExtendedSceneModeResultKey &&
+            !hasExtendedSceneModeMaxSizesKey && !hasExtendedSceneModeZoomRatioRangesKey &&
+            !hasExtendedSceneModeMaxSizes && !hasExtendedSceneModeZoomRatioRanges;
+    if (noExtendedSceneMode) {
         return;
     }
-    bool hasBokeh = hasBokehRequestKey && hasBokehResultKey && hasBokehMaxSizesKey &&
-            hasBokehZoomRatioRangesKey && hasBokehMaxSizes && hasBokehZoomRatioRanges;
-    ASSERT_TRUE(hasBokeh);
+    bool hasExtendedSceneMode = hasExtendedSceneModeRequestKey && hasExtendedSceneModeResultKey &&
+                                hasExtendedSceneModeMaxSizesKey &&
+                                hasExtendedSceneModeZoomRatioRangesKey &&
+                                hasExtendedSceneModeMaxSizes && hasExtendedSceneModeZoomRatioRanges;
+    ASSERT_TRUE(hasExtendedSceneMode);
 
-    // Must have OFF, and must have one of STILL_CAPTURE and CONTINUOUS.
-    // Only valid combinations: {OFF, CONTINUOUS}, {OFF, STILL_CAPTURE}, and
-    // {OFF, CONTINUOUS, STILL_CAPTURE}.
+    // Must have DISABLED, and must have one of BOKEH_STILL_CAPTURE, BOKEH_CONTINUOUS, or a VENDOR
+    // mode.
     ASSERT_TRUE((maxSizesEntry.count == 6 && zoomRatioRangesEntry.count == 2) ||
             (maxSizesEntry.count == 9 && zoomRatioRangesEntry.count == 4));
-    bool hasOffMode = false;
-    bool hasStillCaptureMode = false;
-    bool hasContinuousMode = false;
+    bool hasDisabledMode = false;
+    bool hasBokehStillCaptureMode = false;
+    bool hasBokehContinuousMode = false;
+    bool hasVendorMode = false;
     std::vector<AvailableStream> outputStreams;
     ASSERT_EQ(Status::OK, getAvailableOutputStreams(metadata, outputStreams));
     for (int i = 0, j = 0; i < maxSizesEntry.count && j < zoomRatioRangesEntry.count; i += 3) {
@@ -6666,24 +6687,29 @@
         int32_t maxWidth = maxSizesEntry.data.i32[i+1];
         int32_t maxHeight = maxSizesEntry.data.i32[i+2];
         switch (mode) {
-            case ANDROID_CONTROL_BOKEH_MODE_OFF:
-                hasOffMode = true;
+            case ANDROID_CONTROL_EXTENDED_SCENE_MODE_DISABLED:
+                hasDisabledMode = true;
                 ASSERT_TRUE(maxWidth == 0 && maxHeight == 0);
                 break;
-            case ANDROID_CONTROL_BOKEH_MODE_STILL_CAPTURE:
-                hasStillCaptureMode = true;
+            case ANDROID_CONTROL_EXTENDED_SCENE_MODE_BOKEH_STILL_CAPTURE:
+                hasBokehStillCaptureMode = true;
                 j += 2;
                 break;
-            case ANDROID_CONTROL_BOKEH_MODE_CONTINUOUS:
-                hasContinuousMode = true;
+            case ANDROID_CONTROL_EXTENDED_SCENE_MODE_BOKEH_CONTINUOUS:
+                hasBokehContinuousMode = true;
                 j += 2;
                 break;
             default:
-                ADD_FAILURE() << "Invalid bokehMode advertised: " << mode;
+                if (mode < ANDROID_CONTROL_EXTENDED_SCENE_MODE_VENDOR_START) {
+                    ADD_FAILURE() << "Invalid extended scene mode advertised: " << mode;
+                } else {
+                    hasVendorMode = true;
+                    j += 2;
+                }
                 break;
         }
 
-        if (mode != ANDROID_CONTROL_BOKEH_MODE_OFF) {
+        if (mode != ANDROID_CONTROL_EXTENDED_SCENE_MODE_DISABLED) {
             // Make sure size is supported.
             bool sizeSupported = false;
             for (const auto& stream : outputStreams) {
@@ -6703,8 +6729,8 @@
             ASSERT_LE(minZoomRatio, maxZoomRatio);
         }
     }
-    ASSERT_TRUE(hasOffMode);
-    ASSERT_TRUE(hasStillCaptureMode || hasContinuousMode);
+    ASSERT_TRUE(hasDisabledMode);
+    ASSERT_TRUE(hasBokehStillCaptureMode || hasBokehContinuousMode || hasVendorMode);
 }
 
 void CameraHidlTest::verifyZoomCharacteristics(const camera_metadata_t* metadata) {
diff --git a/camera/provider/2.6/ICameraProvider.hal b/camera/provider/2.6/ICameraProvider.hal
index 5651550..ed1d31d 100644
--- a/camera/provider/2.6/ICameraProvider.hal
+++ b/camera/provider/2.6/ICameraProvider.hal
@@ -76,6 +76,13 @@
      * configuration settings exposed through camera metadata), should the sum
      * of resource costs for the combination be <= 100.
      *
+     * The lists of camera id combinations returned by this method may contain
+     * hidden physical camera ids. If a combination does contain hidden physical
+     * camera ids, the camera framework must be able to open any logical cameras
+     * that contain these hidden physical camera ids in their
+     * ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS list, in addition to the other
+     * camera ids advertised in the combination, for concurrent operation.
+     *
      * @return status Status code for the operation
      * @return cameraIds a list of camera id combinations that support
      *         concurrent stream configurations with the minimum guarantees
diff --git a/cas/1.2/vts/functional/Android.bp b/cas/1.2/vts/functional/Android.bp
index 9bc372c..2d6517f 100644
--- a/cas/1.2/vts/functional/Android.bp
+++ b/cas/1.2/vts/functional/Android.bp
@@ -31,6 +31,8 @@
     shared_libs: [
         "libbinder",
     ],
-    test_suites: ["general-tests"],
+    test_suites: [
+        "general-tests",
+        "vts-core",
+    ],
 }
-
diff --git a/cas/1.2/vts/functional/VtsHalCasV1_2TargetTest.cpp b/cas/1.2/vts/functional/VtsHalCasV1_2TargetTest.cpp
index 8439ceb..58e0f2e 100644
--- a/cas/1.2/vts/functional/VtsHalCasV1_2TargetTest.cpp
+++ b/cas/1.2/vts/functional/VtsHalCasV1_2TargetTest.cpp
@@ -16,8 +16,6 @@
 
 #define LOG_TAG "mediacas_hidl_hal_test"
 
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
 #include <android-base/logging.h>
 #include <android/hardware/cas/1.0/IDescramblerBase.h>
 #include <android/hardware/cas/1.0/types.h>
@@ -28,8 +26,11 @@
 #include <android/hardware/cas/native/1.0/IDescrambler.h>
 #include <android/hardware/cas/native/1.0/types.h>
 #include <binder/MemoryDealer.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
 #include <hidl/HidlSupport.h>
 #include <hidl/HidlTransportSupport.h>
+#include <hidl/ServiceManagement.h>
 #include <hidl/Status.h>
 #include <hidlmemory/FrameworkUtils.h>
 #include <utils/Condition.h>
@@ -293,27 +294,14 @@
     EXPECT_EQ(mEventArg, static_cast<int32_t>(mode));
 }
 
-// Test environment for Cas HIDL HAL.
-class CasHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-  public:
-    // get the test environment singleton
-    static CasHidlEnvironment* Instance() {
-        static CasHidlEnvironment* instance = new CasHidlEnvironment;
-        return instance;
-    }
-
-    virtual void registerTestServices() override { registerTestService<IMediaCasService>(); }
-};
-
-class MediaCasHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class MediaCasHidlTest : public testing::TestWithParam<std::string> {
   public:
     virtual void SetUp() override {
-        mService = ::testing::VtsHalHidlTargetTestBase::getService<IMediaCasService>(
-                CasHidlEnvironment::Instance()->getServiceName<IMediaCasService>());
+        mService = IMediaCasService::getService(GetParam());
         ASSERT_NE(mService, nullptr);
     }
 
-    sp<IMediaCasService> mService;
+    sp<IMediaCasService> mService = nullptr;
 
   protected:
     static void description(const std::string& description) {
@@ -497,7 +485,7 @@
     return ::testing::AssertionResult(returnVoid.isOk());
 }
 
-TEST_F(MediaCasHidlTest, TestClearKeyApisWithSession) {
+TEST_P(MediaCasHidlTest, TestClearKeyApisWithSession) {
     description("Test that valid call sequences with SessionEvent send and receive");
 
     ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
@@ -609,11 +597,7 @@
 
 }  // anonymous namespace
 
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(CasHidlEnvironment::Instance());
-    ::testing::InitGoogleTest(&argc, argv);
-    CasHidlEnvironment::Instance()->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    LOG(INFO) << "Test result = " << status;
-    return status;
-}
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, MediaCasHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IMediaCasService::descriptor)),
+        android::hardware::PrintInstanceNameToString);
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/NativeHandle.aidl b/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/NativeHandle.aidl
new file mode 100644
index 0000000..f37b7d5
--- /dev/null
+++ b/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/NativeHandle.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.common;
+@VintfStability
+parcelable NativeHandle {
+  ParcelFileDescriptor[] fds;
+  int[] ints;
+}
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index 7883dd9..ba56832 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -23,8 +23,9 @@
         "kernel_config_o_3.18",
         "kernel_config_o_4.4",
         "kernel_config_o_4.9",
-    ]
+    ],
 }
+
 vintf_compatibility_matrix {
     name: "framework_compatibility_matrix.1.xml",
     stem: "compatibility_matrix.1.xml",
@@ -35,8 +36,9 @@
         "kernel_config_o_3.18",
         "kernel_config_o_4.4",
         "kernel_config_o_4.9",
-    ]
+    ],
 }
+
 vintf_compatibility_matrix {
     name: "framework_compatibility_matrix.2.xml",
     stem: "compatibility_matrix.2.xml",
@@ -47,7 +49,7 @@
         "kernel_config_o_mr1_3.18",
         "kernel_config_o_mr1_4.4",
         "kernel_config_o_mr1_4.9",
-    ]
+    ],
 }
 
 vintf_compatibility_matrix {
@@ -60,7 +62,7 @@
         "kernel_config_p_4.4",
         "kernel_config_p_4.9",
         "kernel_config_p_4.14",
-    ]
+    ],
 }
 
 vintf_compatibility_matrix {
@@ -73,18 +75,18 @@
         "kernel_config_q_4.9",
         "kernel_config_q_4.14",
         "kernel_config_q_4.19",
-    ]
+    ],
 }
 
 vintf_compatibility_matrix {
-    name: "framework_compatibility_matrix.current.xml",
-    stem: "compatibility_matrix.current.xml",
+    name: "framework_compatibility_matrix.5.xml",
+    stem: "compatibility_matrix.5.xml",
     srcs: [
-        "compatibility_matrix.current.xml",
+        "compatibility_matrix.5.xml",
     ],
     kernel_configs: [
-        "kernel_config_current_4.14",
-        "kernel_config_current_4.19",
-        "kernel_config_current_5.4",
-    ]
+        "kernel_config_r_4.14",
+        "kernel_config_r_4.19",
+        "kernel_config_r_5.4",
+    ],
 }
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index 6d204cb..e69fc8d 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -97,7 +97,7 @@
     framework_compatibility_matrix.2.xml \
     framework_compatibility_matrix.3.xml \
     framework_compatibility_matrix.4.xml \
-    framework_compatibility_matrix.current.xml \
+    framework_compatibility_matrix.5.xml \
     framework_compatibility_matrix.device.xml \
 
 my_framework_matrix_deps += \
diff --git a/compatibility_matrices/compatibility_matrix.4.xml b/compatibility_matrices/compatibility_matrix.4.xml
index 01ec172..e5e012c 100644
--- a/compatibility_matrices/compatibility_matrix.4.xml
+++ b/compatibility_matrices/compatibility_matrix.4.xml
@@ -181,12 +181,6 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.gnss</name>
-        <!--
-         - Both versions are listed here as a workaround for libvintf since 2.0 extends 1.1.
-         - Devices launched with Q must support gnss@2.0, see VtsTrebleVendorVintfTest
-         - test DeviceManifestTest#GnssHalVersionCompatibility.
-        -->
-        <version>1.1</version>
         <version>2.0</version>
         <interface>
             <name>IGnss</name>
@@ -429,7 +423,6 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.thermal</name>
-        <version>1.0-1</version>
         <version>2.0</version>
         <interface>
             <name>IThermal</name>
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.5.xml
similarity index 93%
rename from compatibility_matrices/compatibility_matrix.current.xml
rename to compatibility_matrices/compatibility_matrix.5.xml
index de1ee84..38f589d 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.5.xml
@@ -34,15 +34,28 @@
     <hal format="hidl" optional="true">
         <name>android.hardware.automotive.audiocontrol</name>
         <version>1.0</version>
+        <version>2.0</version>
         <interface>
             <name>IAudioControl</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.automotive.evs</name>
+        <name>android.hardware.automotive.can</name>
         <version>1.0</version>
         <interface>
+            <name>ICanBus</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+        <interface>
+            <name>ICanController</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.evs</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IEvsEnumerator</name>
             <instance>default</instance>
             <regex-instance>[a-z]+/[0-9]+</regex-instance>
@@ -197,12 +210,6 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.gnss</name>
-        <!--
-         - Both versions are listed here as a workaround for libvintf since 2.0 extends 1.1.
-         - Devices launched with Q must support gnss@2.0, see VtsTrebleVendorVintfTest
-         - test DeviceManifestTest#GnssHalVersionCompatibility.
-        -->
-        <version>1.1</version>
         <version>2.0-1</version>
         <interface>
             <name>IGnss</name>
@@ -211,7 +218,7 @@
     </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.graphics.allocator</name>
-        <!-- TODO(b/136016160): deprecating 2.0. New devices should not use this -->
+        <!-- New, non-Go devices should use 4.0, tested in vts_treble_vintf_vendor_test -->
         <version>2.0</version>
         <version>3.0</version>
         <version>4.0</version>
@@ -230,7 +237,7 @@
     </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.graphics.mapper</name>
-        <!-- TODO(b/136016160): deprecating 2.1. New devices should not use this -->
+        <!-- New, non-Go devices should use 4.0, tested in vts_treble_vintf_vendor_test -->
         <version>2.1</version>
         <version>3.0</version>
         <version>4.0</version>
@@ -255,6 +262,13 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.identity</name>
+        <interface>
+            <name>IIdentityCredentialStore</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.ir</name>
         <version>1.0</version>
@@ -451,7 +465,6 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.thermal</name>
-        <version>1.0</version>
         <version>2.0</version>
         <interface>
             <name>IThermal</name>
@@ -475,6 +488,14 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.tv.tuner</name>
+        <version>1.0</version>
+        <interface>
+            <name>ITuner</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.usb</name>
         <version>1.0-2</version>
         <interface>
diff --git a/configstore/1.1/default/Android.mk b/configstore/1.1/default/Android.mk
index e7edc34..6b7bb00 100644
--- a/configstore/1.1/default/Android.mk
+++ b/configstore/1.1/default/Android.mk
@@ -35,3 +35,14 @@
 LOCAL_SRC_FILES := seccomp_policy/configstore@1.1-$(TARGET_ARCH).policy
 include $(BUILD_PREBUILT)
 endif
+
+# disable configstore
+include $(CLEAR_VARS)
+LOCAL_MODULE := disable_configstore
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_SRC_FILES:= disable_configstore.cpp
+LOCAL_OVERRIDES_MODULES := android.hardware.configstore@1.1-service
+LOCAL_VENDOR_MODULE := true
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_EXECUTABLE)
diff --git a/configstore/1.1/default/disable_configstore.cpp b/configstore/1.1/default/disable_configstore.cpp
new file mode 100644
index 0000000..b727ddb
--- /dev/null
+++ b/configstore/1.1/default/disable_configstore.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+int main() {
+    return 1;
+}
diff --git a/current.txt b/current.txt
index 873e2f6..183d006 100644
--- a/current.txt
+++ b/current.txt
@@ -451,9 +451,9 @@
 443659bb9e27221e5da0d16c7a0ecb2dc3a9a03acc8a0b2196b47c50735e2d2e android.hardware.audio.effect@5.0::IVirtualizerEffect
 78fed26a781cdca1b3bcb37520bff705d7764ee81db9cfd37014953c7ad2596e android.hardware.audio.effect@5.0::IVisualizerEffect
 6385b6accab8a544e2ee54ba7bf5aa55dff6153bcedd80fdaae16fe9e0be7050 android.hardware.audio.effect@5.0::types
-95aa2f59e29e2f84d8e84320ace9b6682b426a16e897b4bd241375cbee0e07f3 android.hardware.biometrics.face@1.0::types
 e18ff318f3fc43db37f554696dc4e551abb9b119bde53950f73e28ce33a97a40 android.hardware.biometrics.face@1.0::IBiometricsFace
 b6e55d7795bbafd011fb95a3b6d3954bf66c349e14cf107f3b72032ce3ceb448 android.hardware.biometrics.face@1.0::IBiometricsFaceClientCallback
+95aa2f59e29e2f84d8e84320ace9b6682b426a16e897b4bd241375cbee0e07f3 android.hardware.biometrics.face@1.0::types
 ecedc58dbcdb13503c19c0ab160ac1dd0530bb1471164149282dd1463c684185 android.hardware.bluetooth.audio@2.0::IBluetoothAudioPort
 fb9c40e4deab40be5476477078fe3d8a4a4495fd9deef4321878d169d675c633 android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvider
 f7431f3e3e4e3387fc6f27a6cf423eddcd824a395dc4349d302c995ab44a9895 android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvidersFactory
@@ -594,11 +594,11 @@
 2ce820dc4f3c6d85721b65150ed2157c6e2e2055f866fb6c6ba4790f14408d66 android.hardware.camera.provider@2.4::ICameraProviderCallback
 b69a7615c508acf5c5201efd1bfa3262167874fc3594e2db5a3ff93addd8ac75 android.hardware.keymaster@4.0::IKeymasterDevice
 eb2fa0c883c2185d514be0b84c179b283753ef0c1b77b45b4f359bd23bba8b75 android.hardware.neuralnetworks@1.0::IPreparedModel
-8eac60e1f724d141c71c69f06d4544acb720a55dfbbcd97fa01bb3d25ee4e2f5 android.hardware.neuralnetworks@1.0::types
+92e101b30e47bdf526a01c52cecfbe730def5997b8260ab497eb949eb2a6dcdf android.hardware.neuralnetworks@1.0::types
 5f6d3097ba84cb63c430787123f4de1b31c11f90b531b98eae9a8623a5ae962a android.hardware.neuralnetworks@1.1::types
 fb382e986c10b8fbb797a8546e8f9ea6d1107bfe6f3fb7e57f6bbbf1f807a906 android.hardware.neuralnetworks@1.2::IDevice
 40e71cd693de5b832325c5d8f081f2ff20a7ba2b89d401cee5b4b3eb0e241681 android.hardware.neuralnetworks@1.2::IPreparedModel
-00649d29680f2c47edf60000c3ae7ae906ba638f0616947147e3676a83cf36fa android.hardware.neuralnetworks@1.2::types
+ee1a0dee5be00a6fe2d4d3270068c78016dcb194d768fe07ed894ea20904037f 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
@@ -606,7 +606,6 @@
 5751f230e86a36111e7c5b995577cbf89d8df76c8e6c7641199198f3db3a93f7 android.hardware.wifi@1.3::IWifiStaIface
 
 # HALs released in Android R
-822369cf4dc16a6f6b9622bcf86cbdc0b692dc82193fc15e967767175cbfdd8f android.hardware.audio@6.0::types
 7241bd4596a927cd46d4b82f5e29e2cbe57f194aa1b25555f1d1d352e8b15c61 android.hardware.audio@6.0::IDevice
 2402876cbc23c0de3690a665eca84fd3857d1808dba5cad25ce272f81ecef8c9 android.hardware.audio@6.0::IDevicesFactory
 bca5379d5065e2e08b6ad7308ffc8a71a972fc0698bec678ea32eea786d01cb5 android.hardware.audio@6.0::IPrimaryDevice
@@ -615,8 +614,8 @@
 164826a380f4c1700183003f62d7532e367b67381c30ea44f946c0cf00008f85 android.hardware.audio@6.0::IStreamOut
 997fdaad7a9d17ee7e01feb7031a753e2365e72ad30b11d950e9183fabdf3844 android.hardware.audio@6.0::IStreamOutCallback
 e7ca0db9a1098210f327a9b152fa6afe6bf019c41e5264c64829d04d50c0a526 android.hardware.audio@6.0::IStreamOutEventCallback
+822369cf4dc16a6f6b9622bcf86cbdc0b692dc82193fc15e967767175cbfdd8f android.hardware.audio@6.0::types
 bee662c62d997d8065e2bcb5c1e7a9578931f22ce28fd02c219fdb4d0630abf7 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
@@ -631,18 +630,49 @@
 5237c42d3913ef569f07bec802568084b615155d05a7951e75085da54856508c android.hardware.audio.effect@6.0::IPresetReverbEffect
 282193799d60bff27a84c65a36218c1e7d8f582f5828e2e059383d1b90aa56bd android.hardware.audio.effect@6.0::IVirtualizerEffect
 0868e00f7c5ee16723bda1a8f57099763d04100ae7126a1c2d3a9a87c844a7e8 android.hardware.audio.effect@6.0::IVisualizerEffect
-7e8e1c3d0173c5d503dd01cecff8e3864478557ca6b9e8cc2291598b1a4aea62 android.hardware.biometrics.face@1.1::IBiometricsFace
-ae6315fd42196478ac08441cb489d854118001bca5b9b9fd58af5110952be30e android.hardware.biometrics.fingerprint@2.2::types
-6828bbf18dc5d0f00c73341a10c8e4d574346c1abb1c2ed682ba5e9f8a3240d9 android.hardware.biometrics.fingerprint@2.2::IBiometricsFingerprint
+817930d58412d662cb45e641c50cb62c727e4a3e3ffe7029a53cad9677b97d58 android.hardware.audio.effect@6.0::types
+ca515ff4b63c80cf5ad7b3395c997c57d6c56157361f6c367d1c96f23cc4860a android.hardware.automotive.audiocontrol@1.0::types
+4bc4e8087f5c389f013370ed68bc8a1a29cb2f203237937697f35e005a5ad0b4 android.hardware.automotive.audiocontrol@2.0::IAudioControl
+37ef585d6687cb31e35c67ab456140d70edba9c4333ce5a6ddd70e636e985773 android.hardware.automotive.audiocontrol@2.0::ICloseHandle
+3cf3e5e48ba2642052bbccc1aa4e8bb142933ac960ff40eeedd16e4fe452e7a5 android.hardware.automotive.audiocontrol@2.0::IFocusListener
+d06fc14b325beeef06bd39de8f178f490d9e9095255626866071aab42be1fc40 android.hardware.automotive.audiocontrol@2.0::types
+949a2582c9efa3f6f631f56120eae3f02313f251dbf9246c327e419cdf0652a2 android.hardware.automotive.can@1.0::ICanBus
+43cddb1907a30343bced68946884416ea25ab14ae2df4709357528b2bedba84c android.hardware.automotive.can@1.0::ICanController
+272e826492b27b0dbdeda408e84a41ae43e98f29e57995b6452ded270aae4eee android.hardware.automotive.can@1.0::ICanErrorListener
+07e387bd8bc0e4df5f372515ed960a0b1ae74ea7231d4490a0bb09b07046e4f1 android.hardware.automotive.can@1.0::ICanMessageListener
+2166132d6c247630a193217b4338074f634d6691b1ed6796cb26b3812e90b46e android.hardware.automotive.can@1.0::ICloseHandle
+83355471a3b6d7f777d3f129714585ffb77d9b6f8a3d0365741969631efb81b2 android.hardware.automotive.can@1.0::types
+8afd93d525cf17818e3d46e72f30debeaacc6fb166a59a8e25272f2baeb0ef7a android.hardware.automotive.evs@1.1::IEvsCamera
+89ff5ab18b3069f21a57f559b290caa50670f0ae1b74178f630183aef39b496b android.hardware.automotive.evs@1.1::IEvsCameraStream
+4c67f768067a0aceac74381f6f62e778ab3b6a18f47db3c9b98c58190ef5619d android.hardware.automotive.evs@1.1::IEvsDisplay
+87958d728d7c0ee9b9391ab4a072b097914921a7b38f7dc3df427f933a5b528e android.hardware.automotive.evs@1.1::IEvsEnumerator
+f53b4e8de6209c6d0fa9036005671b34a2f98328b51423d3a5137a43bf42c84d android.hardware.automotive.evs@1.1::IEvsUltrasonicsArray
+0460bacbde906a846a3d71b2b7b33d6927cac3ff072e523ffac7853577464406 android.hardware.automotive.evs@1.1::IEvsUltrasonicsArrayStream
+8a156203892de3cfa47baaccabef3c45b3315cae93b332357598d60896b1ac7f android.hardware.automotive.evs@1.1::types
+4e4904c4067dadae974ddf90351f362331dcd04bba1d890d313cc8ba91f68c15 android.hardware.automotive.sv@1.0::ISurroundView2dSession
+63336e9d03f545020ff2982ff76d9d8c44fa76ad476293b5ef6732cbbd71e61b android.hardware.automotive.sv@1.0::ISurroundView3dSession
+b7015428cd52ce8192d13bfcbf2c4455cda3727d57f2aac80d65a1747104f5ac android.hardware.automotive.sv@1.0::ISurroundViewService
+7d2e77ad86766bbc213fa7377eab739f44cc0866e567e6d33c0e27e7f99e27a8 android.hardware.automotive.sv@1.0::ISurroundViewSession
+d34769e55df919739bb46f25ae2e125e9c807733afa94daeca20feadd74de79c android.hardware.automotive.sv@1.0::ISurroundViewStream
+affd9c591f48a69773fcf43dc4a716d292cd4bc5ba2be8649276af0aedea435d android.hardware.automotive.sv@1.0::types
+b3caf524c46a47d67e6453a34419e1881942d059e146cda740502670e9a752c3 android.hardware.automotive.vehicle@2.0::IVehicle
+7ce8728b27600e840cacf0a832f6942819fe535f9d3797ae052d5eef5065921c android.hardware.automotive.vehicle@2.0::IVehicleCallback
+6b2564fce1d364baf9ba15a5cb00a8f08f86a5be5387c0ede795328ca536a2c7 android.hardware.automotive.vehicle@2.0::types
+140f8f62100ccf9cd282ae3685a0f4ef0a9f971d77dfbc7350ccb4e04cf295ec android.hardware.biometrics.fingerprint@2.2::IBiometricsFingerprint
 82cad99f5feb2ea9bcd4579055edf4af8feb9fc602a6e4827ddd727d254d4991 android.hardware.biometrics.fingerprint@2.2::IBiometricsFingerprintClientCallback
+ae6315fd42196478ac08441cb489d854118001bca5b9b9fd58af5110952be30e android.hardware.biometrics.fingerprint@2.2::types
 362fd1c21641c2224f3b80c30d9797b988fa3f344243d531ba73c553779a5763 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
 b8c63679e1a3874b356f3e691aecce1191d38f59063cf2ed2dce8a9d4cabf00e android.hardware.camera.device@3.6::ICameraDevice
-99aae72ae75a8ddf63ccffbc585f3a55f4d0847b4adff3d7a0f8bd9e2305bec1 android.hardware.camera.provider@2.6::ICameraProvider
-8f8d9463508ff9cae88eb35c429fd0e2dbca0ca8f5de7fdf836cc0c4370becb6 android.hardware.camera.provider@2.6::ICameraProviderCallback
+eb90c4d366f05a025d1d1a3672f8b4c3e33e420fa387f73f21b264645bfdf845 android.hardware.camera.device@3.6::ICameraDeviceSession
+a718c8a3acaa938de5a57923e8c4625ed7ca051e05a1d930ba6998557d7b57c8 android.hardware.camera.device@3.6::ICameraOfflineSession
 a35d5151b48505f06a775b38c0e2e265f80a845d92802324c643565807f81c53 android.hardware.camera.device@3.6::types
+02bdf82dba7dce273a554b4474468a8fb1fb4f61ab65da95eb16e080df63fff6 android.hardware.camera.metadata@3.5::types
+21086e1c7a2acc0ebe0ff8561b11f3c2009be687a92d79b608a5f00b16c5f598 android.hardware.camera.provider@2.6::ICameraProvider
+8f8d9463508ff9cae88eb35c429fd0e2dbca0ca8f5de7fdf836cc0c4370becb6 android.hardware.camera.provider@2.6::ICameraProviderCallback
+1edf7aef68ef3bd577a1175b1462fb82e3e39f01c6915dda61fba121028df283 android.hardware.camera.provider@2.6::types
 c1aa508d00b66ed5feefea398fd5edf28fa651ac89773adad7dfda4e0a73a952 android.hardware.cas@1.2::ICas
 9811f867def49b420d8c707f7e38d3bdd64f835244e1d2a5e9762ab9835672dc android.hardware.cas@1.2::ICasListener
 f18695dd36ee205640b8326a17453858a7b4596653aaa6ef0016b0aef1bd4dac android.hardware.cas@1.2::IMediaCasService
@@ -651,27 +681,29 @@
 3581d0ba61663cdd45807494dcd697d01c074f27587df9140655f94346969cfe android.hardware.contexthub@1.1::types
 66931c2506fbb5af61f20138cb05e0a09e7bf67d6964c231d27c648933bb33ec android.hardware.drm@1.3::ICryptoFactory
 994d08ab27d613022c258a9ec48cece7adf2a305e92df5d76ef923e2c6665f64 android.hardware.drm@1.3::IDrmFactory
-d9df99be0f59d8f33a9699fe316c67bfd11818aa69440bb1123ba43e717cea85 android.hardware.dumpstate@1.1::types
 186bc152ae189ab48f3a761a44ddf5edd0d483073c5b6ca1f802f8b50488b754 android.hardware.dumpstate@1.1::IDumpstateDevice
-769d346927a94fd40ee80a5a976d8d15cf022ef99c5900738f4a82f26c0ed229 android.hardware.gnss@2.1::types
+d9df99be0f59d8f33a9699fe316c67bfd11818aa69440bb1123ba43e717cea85 android.hardware.dumpstate@1.1::types
 c319e68b03829958404402c2d9c682019678087d60495807c0a7444e0a6af981 android.hardware.gnss@2.1::IGnss
 ba5ac712b2a656dc07c83ab4a7a2c2f3bee1bbcb752e8b8ffa9b672f3b5b0728 android.hardware.gnss@2.1::IGnssAntennaInfo
 0bc3ed97cbc3f6abc89c68f4e9f4d124f9f723431997dc88c2186cf4d2ad47ee android.hardware.gnss@2.1::IGnssAntennaInfoCallback
 3541d83adfeac16ee3e45d183a58dffe06012ccb5aa5bcd2e4f6eeae269f69cd android.hardware.gnss@2.1::IGnssCallback
 737d750017738f0753d13ba01a3310e0161f294b8ae80b3fd63eaa227e9d9c66 android.hardware.gnss@2.1::IGnssConfiguration
 7913a11206a577b12ade86a7cf3f95c2639cb514d086673f279bf99238c9917e android.hardware.gnss@2.1::IGnssMeasurement
-0a16e5913e94d995cfcf959a1c6f10b0b8e9dfdb5f45ac6e7244711ddd740272 android.hardware.gnss@2.1::IGnssMeasurementCallback
+df52e2c39ed701a355b5e0fdbf83fe5fa7d04bfecd715116b39373d46dc3c682 android.hardware.gnss@2.1::IGnssMeasurementCallback
+769d346927a94fd40ee80a5a976d8d15cf022ef99c5900738f4a82f26c0ed229 android.hardware.gnss@2.1::types
 6670e7780803a8c696c6391fda5589a334b1b37dc7be9393792ed35035413633 android.hardware.gnss.measurement_corrections@1.1::IMeasurementCorrections
 956c1576ca0d6f11b42980ef59052062836b6763fe973af6cb709da50787f710 android.hardware.gnss.measurement_corrections@1.1::types
+a2dcf188b02102d3cf80ca0a280dce05d45a8df809751b3c52347426ed58ebbe android.hardware.graphics.allocator@4.0::IAllocator
+0a90c665605df3d7d7b0fcafcc4178c3345a6e4ba7e3148fefe4973629827463 android.hardware.graphics.composer@2.4::IComposer
+809b815bac3d9a5ead591b5fed20f08dbd2bcf7b5c6858201fdd0d8347db9177 android.hardware.graphics.composer@2.4::IComposerCallback
+8006ee6e02453443f7e79cfcd9f85d9863bed53c4cfc55519de98b64ca72edc2 android.hardware.graphics.composer@2.4::IComposerClient
+fda61f0a5a56cf4e0e8697fb4899a26a4dc450ff837f3425b53932fe34583d11 android.hardware.graphics.composer@2.4::types
+4d674afdc4447f614c8cc466ed45c5955a0192fa3d3c70884b11dd3c88f0b468 android.hardware.graphics.mapper@4.0::IMapper
+b58a5e83a8ab04ff6e500f6afc17a1129a1f3de044b296b4b6bd34a085220f87 android.hardware.graphics.mapper@4.0::types
 ce8dbe76eb9ee94b46ef98f725be992e760a5751073d4f4912484026541371f3 android.hardware.health@2.1::IHealth
 26f04510a0b57aba5167c5c0a7c2f077c2acbb98b81902a072517829fd9fd67f android.hardware.health@2.1::IHealthInfoCallback
 e2f8bc1868fd4a3fd587c172773ea5a8c2f5a3deaf7958394102ca455252b255 android.hardware.health@2.1::types
-0589e410f519e36514e7ece18f283f022df0f70efd2c12821d822f67f74aba98 android.hardware.identity@1.0::types
-bbeee9604128ede83ee755b67e73b5ad29e6e1dbac9ec41fea6ffe2745b0c50a android.hardware.identity@1.0::IIdentityCredential
-96ce8aad80f4c476f25261f790d357c117e79e18474c7dadd850dac704bbe65e android.hardware.identity@1.0::IIdentityCredentialStore
-8da9c938e58f7d636ddd2f92c646f99d9a9e79612e6441b6380ab12744251873 android.hardware.identity@1.0::IWritableIdentityCredential
-27ae3724053940462114228872b3ffaf0b8e6177d5ba97f5a76339d12b8a99dd android.hardware.keymaster@4.1::IKeymasterDevice
-adb0efdf1462e9b2e742c0dcadd598666aac551f178be06e755bfcdf5797abd0 android.hardware.keymaster@4.1::IOperation
+c5da8636c14cd30f1ae9f10c2219e35b4e29a64443103a5842352dd070afe514 android.hardware.keymaster@4.1::IKeymasterDevice
 ddcf89cd8ee2df0d32aee55050826446fb64f7aafde0a7cd946c64f61b1a364c android.hardware.keymaster@4.1::types
 df9c79c4fdde2821550c6d5c3d07f5ec0adfb1b702561ce543c906ddef698703 android.hardware.media.c2@1.1::IComponent
 a3eddd9bbdc87e8c22764070037dd1154f1cf006e6fba93364c4f85d4c134a19 android.hardware.media.c2@1.1::IComponentStore
@@ -681,8 +713,20 @@
 6e904be0ddca5ae1de8eba020e6c38ed935ea7d80cd08f47787f137a0ca58555 android.hardware.neuralnetworks@1.3::IFencedExecutionCallback
 2b0b10d2ea7a18a4048cd0eb83d35c19a817aeee95f65807fc31f4ef21381397 android.hardware.neuralnetworks@1.3::IPreparedModel
 eee3430cc86c97c7b407495863d8fb61da6f1a64b7721e77b9b4909b11b174e9 android.hardware.neuralnetworks@1.3::IPreparedModelCallback
-c9320b04ec302624985180a02d591bea5e435601fc411a6cabb58878e4e1ad68 android.hardware.neuralnetworks@1.3::types
-b335c3c732c799b299fa61c6de6260ab4d20cbd0ec21acd6db14d8156c745d0b android.hardware.tv.tuner@1.0::types
+acf84925f8ee0a651f2ec547ac334034de266479b93af5434f6c1f25e66aba96 android.hardware.neuralnetworks@1.3::types
+b454df853441c12f6e425e8a60dd29fda20f5e6e39b93d1103e4b37495db38aa android.hardware.radio@1.5::IRadio
+fcbb0742a88215ee7a6d7ce0825d253eb2b50391fc6c8c48667f9fd7f6d4549e android.hardware.radio@1.5::IRadioIndication
+b809193970a91ca637a4b0184767315601d32e3ef3d5992ffbc7a8d14a14f015 android.hardware.radio@1.5::IRadioResponse
+a5bcd595a5108312fe2eb402e716d0b7dab8eb689a2a5f54fdef3ff71f3babd5 android.hardware.radio@1.5::types
+c2cc192edcc222a12b524fb0e0e7f17ef2b48d6b1c0be7b60bc114601793d7a9 android.hardware.secure_element@1.2::ISecureElement
+3ca6616381080bdd6c08141ad12775a94ae868c58b02b1274ae3326f7de724ab android.hardware.sensors@2.1::ISensors
+3d4141c6373cd9ca02fe221a7d12343840de2255d032c38248fe8e35816b58b2 android.hardware.sensors@2.1::ISensorsCallback
+8051cc50fc90ed447f058a8b15d81f35a65f1bd9004b1de4f127edeb89b47978 android.hardware.sensors@2.1::types
+b37f78e3fdc79af8b32a545b2b426f1fd1355b359d9e7835f3bf1ed0aa4518d8 android.hardware.soundtrigger@2.3::ISoundTriggerHw
+4a6517ea4ad807855428b0101d8e1a486497bd88ab4300ba3b2be43d46d32580 android.hardware.soundtrigger@2.3::types
+b878fcad575742925690303f717e2186058a378670be6e2f85e7e503841954aa android.hardware.tv.cec@2.0::IHdmiCec
+009b9a02619b14da27027cb5d424fa01f098f6b6f6fa0829049497fc3612d67d android.hardware.tv.cec@2.0::IHdmiCecCallback
+af1443272c4db47dea5adc5b6c4293dd09c20466a58684c68a5d88c0e7e46261 android.hardware.tv.cec@2.0::types
 adab52e647d1a1ccfbdabdfc9c73352f8e834b61322e505bc6e3d3a0d3acc259 android.hardware.tv.tuner@1.0::IDemux
 548e1a16fc4f779346e14968a63cd6f160e1e2c8b8c99256b2bac24a24b52a9a android.hardware.tv.tuner@1.0::IDescrambler
 b84597d59f0f1d03c9997d60eb15280f3950c287d46016240d89859789db4d47 android.hardware.tv.tuner@1.0::IDvr
@@ -695,7 +739,16 @@
 b2310785bdb55f97bbbb2176e2ee73ed8d2a7ce5895bd20c997b90c5f2868ad8 android.hardware.tv.tuner@1.0::ILnbCallback
 4788787e662293d526ff7789fc24e82533e7f6ff99a967ebc3e3ec6b17628796 android.hardware.tv.tuner@1.0::ITimeFilter
 c350c7783843e0c7cf30f90c918770b0d3c09fc0fe5e532e2f2e7210fcfe71c9 android.hardware.tv.tuner@1.0::ITuner
+b335c3c732c799b299fa61c6de6260ab4d20cbd0ec21acd6db14d8156c745d0b android.hardware.tv.tuner@1.0::types
+7746fda1fbf9c7c132bae701cc5a161309e4f5e7f3e8065811045975ee86196d android.hardware.usb.gadget@1.1::IUsbGadget
 3e01d4446cd69fd1c48f8572efd97487bc179564b32bd795800b97bbe10be37b android.hardware.wifi@1.4::IWifi
+84757251ff195b447dc511c0d3f055a684d4fed7847eb4d65a2455eb914059d2 android.hardware.wifi@1.4::IWifiApIface
+2e07983a70a1b963bee8aece050e5ea503a3dde31e21a9f8352cf17e9113d347 android.hardware.wifi@1.4::IWifiChip
+08c1912be480c08aa77f6d56bb083d66cd13eca11e01c2d3e727bcb3a1e4f79b android.hardware.wifi@1.4::IWifiChipEventCallback
+ff66371a467d1f3caacea15d93f39b7b767b0d6b8cd41d040337cdabf2514b87 android.hardware.wifi@1.4::IWifiNanIface
+10bd6f19198c281ee2052641048e970ad66b732e4f6ffe79a0f697ea15761e0f android.hardware.wifi@1.4::IWifiRttController
+fcd92a4c898360185dd659f0a1e3001c25eb40b59c3457fd235acf3a8c407525 android.hardware.wifi@1.4::IWifiRttControllerEventCallback
+d878c406d9c1cc67f9d9a3a66b16dcbd7d944e0ed520745fc9ad21d95031e839 android.hardware.wifi@1.4::types
 c67aaf26a7a40d14ea61e70e20afacbd0bb906df1704d585ac8599fbb69dd44b android.hardware.wifi.hostapd@1.2::IHostapd
 2b5a7ea572b736030c64a3b4043af244425477c4672301780fe15aba5ed393d9 android.hardware.wifi.hostapd@1.2::types
 a64467bae843569f0d465c5be7f0c7a5b987985b55a3ef4794dd5afc68538650 android.hardware.wifi.supplicant@1.3::ISupplicant
@@ -703,13 +756,3 @@
 2ce1f7fb52e49f80b13a9b153d491bce530552f02357ea729acae922a8659f93 android.hardware.wifi.supplicant@1.3::ISupplicantStaIfaceCallback
 77531c8d048f8f8ae532babd0ca86332a865ec9aace1b051226ef2b21123e645 android.hardware.wifi.supplicant@1.3::ISupplicantStaNetwork
 98592d193a717066facf91428426e5abe211e3bd718bc372e29fb944ddbe6e7c android.hardware.wifi.supplicant@1.3::types
-e7669bddacbdaee2cd9a87762a13fb7648639eead54bf4d767dc06eaaeb35736 android.hardware.radio@1.5::types
-b454df853441c12f6e425e8a60dd29fda20f5e6e39b93d1103e4b37495db38aa android.hardware.radio@1.5::IRadio
-fcbb0742a88215ee7a6d7ce0825d253eb2b50391fc6c8c48667f9fd7f6d4549e android.hardware.radio@1.5::IRadioIndication
-b809193970a91ca637a4b0184767315601d32e3ef3d5992ffbc7a8d14a14f015 android.hardware.radio@1.5::IRadioResponse
-3ca6616381080bdd6c08141ad12775a94ae868c58b02b1274ae3326f7de724ab android.hardware.sensors@2.1::ISensors
-3d4141c6373cd9ca02fe221a7d12343840de2255d032c38248fe8e35816b58b2 android.hardware.sensors@2.1::ISensorsCallback
-8051cc50fc90ed447f058a8b15d81f35a65f1bd9004b1de4f127edeb89b47978 android.hardware.sensors@2.1::types
-4a6517ea4ad807855428b0101d8e1a486497bd88ab4300ba3b2be43d46d32580 android.hardware.soundtrigger@2.3::types
-b37f78e3fdc79af8b32a545b2b426f1fd1355b359d9e7835f3bf1ed0aa4518d8 android.hardware.soundtrigger@2.3::ISoundTriggerHw
-7746fda1fbf9c7c132bae701cc5a161309e4f5e7f3e8065811045975ee86196d android.hardware.usb.gadget@1.1::IUsbGadget
diff --git a/dumpstate/1.0/default/DumpstateDevice.cpp b/dumpstate/1.0/default/DumpstateDevice.cpp
index c57bf43..e3c2e0b 100644
--- a/dumpstate/1.0/default/DumpstateDevice.cpp
+++ b/dumpstate/1.0/default/DumpstateDevice.cpp
@@ -51,9 +51,8 @@
     ALOGI("Dumpstate HIDL not provided by device\n");
     dprintf(fd, "Dumpstate HIDL not provided by device; providing bogus data.\n");
 
-    // Shows some examples on how to use the libdumpstateutil API.
-    RunCommandToFd(fd, "DATE", {"/vendor/bin/date"});
-    DumpFileToFd(fd, "HOSTS", "/system/etc/hosts");
+    // Shows an example on how to use the libdumpstateutil API.
+    DumpFileToFd(fd, "cmdline", "/proc/self/cmdline");
 
     return Void();
 }
diff --git a/dumpstate/1.1/default/Android.bp b/dumpstate/1.1/default/Android.bp
new file mode 100644
index 0000000..bd92075
--- /dev/null
+++ b/dumpstate/1.1/default/Android.bp
@@ -0,0 +1,26 @@
+cc_binary {
+    name: "android.hardware.dumpstate@1.1-service.example",
+    vendor: true,
+    relative_install_path: "hw",
+    defaults: ["hidl_defaults"],
+    init_rc: [
+        "android.hardware.dumpstate@1.1-service.example.rc",
+    ],
+    vintf_fragments: [
+        "android.hardware.dumpstate@1.1-service.example.xml",
+    ],
+    srcs: ["main.cpp"],
+    shared_libs: [
+        "android.hardware.dumpstate@1.0",
+        "android.hardware.dumpstate@1.1",
+        "libbase",
+        "libcutils",
+        "libdumpstateutil",
+        "libhidlbase",
+        "liblog",
+        "libutils",
+    ],
+    cflags: [
+        "-DLOG_TAG=\"android.hardware.dumpstate@1.1-service.example\"",
+    ],
+}
diff --git a/dumpstate/1.1/default/android.hardware.dumpstate@1.1-service.example.rc b/dumpstate/1.1/default/android.hardware.dumpstate@1.1-service.example.rc
new file mode 100644
index 0000000..3a1e06a
--- /dev/null
+++ b/dumpstate/1.1/default/android.hardware.dumpstate@1.1-service.example.rc
@@ -0,0 +1,8 @@
+service dumpstate-1-1 /vendor/bin/hw/android.hardware.dumpstate@1.1-service.example
+    class hal
+    user nobody
+    group nobody
+    interface android.hardware.dumpstate@1.0::IDumpstateDevice default
+    interface android.hardware.dumpstate@1.1::IDumpstateDevice default
+    oneshot
+    disabled
diff --git a/dumpstate/1.1/default/android.hardware.dumpstate@1.1-service.example.xml b/dumpstate/1.1/default/android.hardware.dumpstate@1.1-service.example.xml
new file mode 100644
index 0000000..775e8c8
--- /dev/null
+++ b/dumpstate/1.1/default/android.hardware.dumpstate@1.1-service.example.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.dumpstate</name>
+        <transport>hwbinder</transport>
+        <version>1.1</version>
+        <interface>
+            <name>IDumpstateDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/dumpstate/1.1/default/main.cpp b/dumpstate/1.1/default/main.cpp
new file mode 100644
index 0000000..3c17e18
--- /dev/null
+++ b/dumpstate/1.1/default/main.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2020 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/properties.h>
+#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
+#include <android/hardware/dumpstate/1.1/types.h>
+#include <hidl/HidlLazyUtils.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <log/log.h>
+
+#include "DumpstateUtil.h"
+
+namespace {
+using ::android::hardware::hidl_handle;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+using ::android::hardware::dumpstate::V1_1::DumpstateMode;
+using ::android::hardware::dumpstate::V1_1::DumpstateStatus;
+using ::android::hardware::dumpstate::V1_1::IDumpstateDevice;
+
+using ::android::os::dumpstate::DumpFileToFd;
+
+const char kVerboseLoggingProperty[] = "persist.dumpstate.verbose_logging.enabled";
+
+struct DumpstateDevice : public IDumpstateDevice {
+    // 1.1
+    Return<DumpstateStatus> dumpstateBoard_1_1(const hidl_handle& handle, const DumpstateMode mode,
+                                               uint64_t /*timeoutMillis*/) override {
+        if (handle == nullptr || handle->numFds < 1) {
+            ALOGE("no FDs\n");
+            return DumpstateStatus::ILLEGAL_ARGUMENT;
+        }
+
+        int fd = handle->data[0];
+        if (fd < 0) {
+            ALOGE("invalid FD: %d\n", fd);
+            return DumpstateStatus::ILLEGAL_ARGUMENT;
+        }
+
+        switch (mode) {
+            case DumpstateMode::FULL:
+                return dumpstateBoardImpl(fd, true);
+
+            case DumpstateMode::DEFAULT:
+                return dumpstateBoardImpl(fd, false);
+
+            case DumpstateMode::INTERACTIVE:
+            case DumpstateMode::REMOTE:
+            case DumpstateMode::WEAR:
+            case DumpstateMode::CONNECTIVITY:
+            case DumpstateMode::WIFI:
+            case DumpstateMode::PROTO:
+                ALOGE("The requested mode is not supported: %s\n", toString(mode).c_str());
+                return DumpstateStatus::UNSUPPORTED_MODE;
+
+            default:
+                ALOGE("The requested mode is invalid: %s\n", toString(mode).c_str());
+                return DumpstateStatus::ILLEGAL_ARGUMENT;
+        }
+    }
+
+    Return<void> setVerboseLoggingEnabled(bool enable) override {
+        ::android::base::SetProperty(kVerboseLoggingProperty, enable ? "true" : "false");
+        return Void();
+    }
+
+    Return<bool> getVerboseLoggingEnabled() override { return getVerboseLoggingEnabledImpl(); }
+
+    // 1.0
+    Return<void> dumpstateBoard(const hidl_handle& h) override {
+        dumpstateBoard_1_1(h, DumpstateMode::DEFAULT, 0);
+        return Void();
+    }
+
+    DumpstateStatus dumpstateBoardImpl(const int fd, const bool full) {
+        ALOGD("DumpstateDevice::dumpstateBoard() FD: %d\n", fd);
+        ALOGI("Dumpstate HIDL not provided by device\n");
+
+        dprintf(fd, "verbose logging: %s\n",
+                getVerboseLoggingEnabledImpl() ? "enabled" : "disabled");
+
+        dprintf(fd, "[%s] %s\n", (full ? "full" : "default"), "Hello, world!");
+
+        // Shows an example on how to use the libdumpstateutil API.
+        DumpFileToFd(fd, "cmdline", "/proc/self/cmdline");
+
+        return DumpstateStatus::OK;
+    }
+
+    static bool getVerboseLoggingEnabledImpl() {
+        return ::android::base::GetBoolProperty(kVerboseLoggingProperty, false);
+    }
+};
+}  // namespace
+
+int main(int, char**) {
+    using ::android::sp;
+    using ::android::hardware::configureRpcThreadpool;
+    using ::android::hardware::joinRpcThreadpool;
+    using ::android::hardware::LazyServiceRegistrar;
+
+    configureRpcThreadpool(1, true);
+
+    sp<DumpstateDevice> dumpstate(new DumpstateDevice);
+    auto serviceRegistrar = LazyServiceRegistrar::getInstance();
+
+    if (serviceRegistrar.registerService(dumpstate) != ::android::OK) {
+        ALOGE("Could not register service.");
+        return 1;
+    }
+
+    joinRpcThreadpool();
+    return 0;
+}
diff --git a/gnss/1.1/vts/functional/gnss_hal_test.cpp b/gnss/1.1/vts/functional/gnss_hal_test.cpp
index 88fbff8..52aaa69 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test.cpp
@@ -99,7 +99,7 @@
     EXPECT_TRUE(result);
 }
 
-bool GnssHalTest::StartAndCheckFirstLocation() {
+bool GnssHalTest::StartAndCheckFirstLocation(bool strict) {
     auto result = gnss_hal_->start();
 
     EXPECT_TRUE(result.isOk());
@@ -110,11 +110,14 @@
      * so allow time to demodulate ephemeris over the air.
      */
     const int kFirstGnssLocationTimeoutSeconds = 75;
+    int locationCalledCount = 0;
 
-    EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_,
-                                                 kFirstGnssLocationTimeoutSeconds));
-    int locationCalledCount = gnss_cb_->location_cbq_.calledCount();
-    EXPECT_EQ(locationCalledCount, 1);
+    if (strict) {
+        EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_,
+                                                     kFirstGnssLocationTimeoutSeconds));
+        locationCalledCount = gnss_cb_->location_cbq_.calledCount();
+        EXPECT_EQ(locationCalledCount, 1);
+    }
 
     if (locationCalledCount > 0) {
         // don't require speed on first fix
@@ -138,7 +141,7 @@
 
     SetPositionMode(kMinIntervalMsec, kLowPowerMode);
 
-    EXPECT_TRUE(StartAndCheckFirstLocation());
+    EXPECT_TRUE(StartAndCheckFirstLocation(/* strict= */ true));
 
     for (int i = 1; i < count; i++) {
         EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_,
diff --git a/gnss/1.1/vts/functional/gnss_hal_test.h b/gnss/1.1/vts/functional/gnss_hal_test.h
index 88b7723..75c4216 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test.h
+++ b/gnss/1.1/vts/functional/gnss_hal_test.h
@@ -102,9 +102,11 @@
      *   <p> Note this leaves the Location request active, to enable Stop call vs. other call
      *   reordering tests.
      *
+     *   <p> if 'strict' is true, the test will fail if no location is generated.
+     *
      * returns  true if a location was successfully generated
      */
-    bool StartAndCheckFirstLocation();
+    bool StartAndCheckFirstLocation(bool strict);
 
     /*
      * CheckLocation:
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 8530ffb..e6a51eb 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
@@ -93,7 +93,7 @@
     SetPositionMode(kMinIntervalMsec, kLowPowerMode);
 
     // Don't expect true - as without AGPS access
-    if (!StartAndCheckFirstLocation()) {
+    if (!StartAndCheckFirstLocation(/* strict= */ false)) {
         ALOGW("GetLocationLowPower test - no first low power location received.");
     }
 
diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp
index b3a3203..59e18f3 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp
@@ -97,7 +97,7 @@
     EXPECT_TRUE(result);
 }
 
-bool GnssHalTest::StartAndCheckFirstLocation() {
+bool GnssHalTest::StartAndCheckFirstLocation(bool strict) {
     const auto result = gnss_hal_->start();
 
     EXPECT_TRUE(result.isOk());
@@ -107,12 +107,14 @@
      * so allow time to demodulate ephemeris over the air.
      */
     const int kFirstGnssLocationTimeoutSeconds = 75;
+    int locationCalledCount = 0;
 
-    EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_,
-                                                 kFirstGnssLocationTimeoutSeconds));
-    int locationCalledCount = gnss_cb_->location_cbq_.calledCount();
-    EXPECT_EQ(locationCalledCount, 1);
-
+    if (strict) {
+        EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_,
+                                                     kFirstGnssLocationTimeoutSeconds));
+        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);
@@ -135,7 +137,7 @@
 
     SetPositionMode(kMinIntervalMsec, kLowPowerMode);
 
-    EXPECT_TRUE(StartAndCheckFirstLocation());
+    EXPECT_TRUE(StartAndCheckFirstLocation(/* strict= */ true));
 
     for (int i = 1; i < count; i++) {
         EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_,
diff --git a/gnss/2.0/vts/functional/gnss_hal_test.h b/gnss/2.0/vts/functional/gnss_hal_test.h
index 55dc1bc..a02a9ff 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test.h
+++ b/gnss/2.0/vts/functional/gnss_hal_test.h
@@ -152,9 +152,11 @@
      *   <p> Note this leaves the Location request active, to enable Stop call vs. other call
      *   reordering tests.
      *
+     *   <p> if 'strict' is true, the test will fail if no location is generated.
+     *
      * returns  true if a location was successfully generated
      */
-    bool StartAndCheckFirstLocation();
+    bool StartAndCheckFirstLocation(bool strict);
 
     /*
      * CheckLocation:
diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
index 53f5b9e..c93e89b 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
@@ -395,7 +395,7 @@
 }
 
 TEST_P(GnssHalTest, TestGnssLocationElapsedRealtime) {
-    StartAndCheckFirstLocation();
+    StartAndCheckFirstLocation(/* strict= */ true);
 
     ASSERT_TRUE((int)gnss_cb_->last_location_.elapsedRealtime.flags <=
                 (int)(ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
@@ -411,7 +411,7 @@
 
 // This test only verify that injectBestLocation_2_0 does not crash.
 TEST_P(GnssHalTest, TestInjectBestLocation_2_0) {
-    StartAndCheckFirstLocation();
+    StartAndCheckFirstLocation(/* strict= */ true);
     gnss_hal_->injectBestLocation_2_0(gnss_cb_->last_location_);
     StopAndClearLocations();
 }
@@ -455,7 +455,7 @@
     SetPositionMode(kMinIntervalMsec, kLowPowerMode);
 
     // Don't expect true - as without AGPS access
-    if (!StartAndCheckFirstLocation()) {
+    if (!StartAndCheckFirstLocation(/* strict= */ false)) {
         ALOGW("GetLocationLowPower test - no first low power location received.");
     }
 
@@ -854,4 +854,4 @@
     result = gnss_configuration_hal->setBlacklist(sources);
     ASSERT_TRUE(result.isOk());
     EXPECT_TRUE(result);
-}
\ No newline at end of file
+}
diff --git a/gnss/2.1/IGnssMeasurementCallback.hal b/gnss/2.1/IGnssMeasurementCallback.hal
index 0e6abbd..60a5423 100644
--- a/gnss/2.1/IGnssMeasurementCallback.hal
+++ b/gnss/2.1/IGnssMeasurementCallback.hal
@@ -30,13 +30,13 @@
      */
     enum GnssMeasurementFlags : @1.0::IGnssMeasurementCallback.GnssMeasurementFlags {
         /**
-         * A valid receiver inter-signal bias is stored in the data structure.
+         * A valid full inter-signal bias is stored in the data structure.
          */
-        HAS_RECEIVER_ISB = 1 << 16,
+        HAS_FULL_ISB = 1 << 16,
         /**
-         * A valid receiver inter-signal bias uncertainty is stored in the data structure.
+         * A valid full inter-signal bias uncertainty is stored in the data structure.
          */
-        HAS_RECEIVER_ISB_UNCERTAINTY = 1 << 17,
+        HAS_FULL_ISB_UNCERTAINTY = 1 << 17,
         /**
          * A valid satellite inter-signal bias is stored in the data structure.
          */
@@ -77,42 +77,58 @@
         bitfield<GnssMeasurementFlags> flags;
 
         /**
-         * The receiver inter-signal bias (ISB) in nanoseconds.
+         * The full inter-signal bias (ISB) in nanoseconds.
          *
-         * This value is the estimated receiver-side inter-system (different from the constellation
-         * in GnssClock.referenceSignalTypeForIsb) bias and inter-frequency (different from the
-         * carrier frequency in GnssClock.referenceSignalTypeForIsb) bias. The reported receiver ISB
-         * must include signal delays caused by
+         * This value is the sum of the estimated receiver-side and the space-segment-side
+         * inter-system bias, inter-frequency bias and inter-code bias, including
          *
-         * - Receiver inter-constellation bias
-         * - Receiver inter-frequency bias
-         * - Receiver inter-code bias
+         * - Receiver inter-constellation bias (with respect to the constellation in
+         *   GnssClock.referenceSignalTypeForIsb)
+         * - Receiver inter-frequency bias (with respect to the carrier frequency in
+         *   GnssClock.referenceSignalTypeForIsb)
+         * - Receiver inter-code bias (with respect to the code type in
+         *   GnssClock.referenceSignalTypeForIsb)
+         * - Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPS-UTC Time Offset
+         *   (TauGps), BDS-GLO Time Offset (BGTO)) (with respect to the constellation in
+         *   GnssClock.referenceSignalTypeForIsb)
+         * - Group delay (e.g., Total Group Delay (TGD))
+         * - Satellite inter-frequency bias (GLO only) (with respect to the carrier frequency in
+         *   GnssClock.referenceSignalTypeForIsb)
+         * - Satellite inter-code bias (e.g., Differential Code Bias (DCB)) (with respect to the
+         *   code type in GnssClock.referenceSignalTypeForIsb)
+         *
+         * If a component of the above is already compensated in the provided
+         * GnssMeasurement.receivedSvTimeInNs, then it must not be included in the reported full
+         * ISB.
          *
          * The value does not include the inter-frequency Ionospheric bias.
          *
-         * The receiver ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 nanoseconds.
+         * The full ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 nanoseconds.
          */
-        double receiverInterSignalBiasNs;
+        double fullInterSignalBiasNs;
 
         /**
-         * 1-sigma uncertainty associated with the receiver inter-signal bias in nanoseconds.
+         * 1-sigma uncertainty associated with the full inter-signal bias in nanoseconds.
          */
-        double receiverInterSignalBiasUncertaintyNs;
+        double fullInterSignalBiasUncertaintyNs;
 
         /**
          * The satellite inter-signal bias in nanoseconds.
          *
-         * This value is the satellite-and-control-segment-side inter-system (different from the
-         * constellation in GnssClock.referenceSignalTypeForIsb) bias and inter-frequency (different
-         * from the carrier frequency in GnssClock.referenceSignalTypeForIsb) bias, including:
+         * This value is the sum of the space-segment-side inter-system bias, inter-frequency bias
+         * and inter-code bias, including
          *
-         * - Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPT-UTC Time Offset (TauGps),
-         *   BDS-GLO Time Offset (BGTO))
+         * - Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPS-UTC Time Offset
+         *   (TauGps), BDS-GLO Time Offset (BGTO)) (with respect to the constellation in
+         *   GnssClock.referenceSignalTypeForIsb)
          * - Group delay (e.g., Total Group Delay (TGD))
-         * - Satellite inter-signal bias, which includes satellite inter-frequency bias (GLO only),
-         *   and satellite inter-code bias (e.g., Differential Code Bias (DCB)).
+         * - Satellite inter-frequency bias (GLO only) (with respect to the carrier frequency in
+         *   GnssClock.referenceSignalTypeForIsb)
+         * - Satellite inter-code bias (e.g., Differential Code Bias (DCB)) (with respect to the
+         *   code type in GnssClock.referenceSignalTypeForIsb)
          *
-         * The receiver ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0 nanoseconds.
+         * The satellite ISB of GnssClock.referenceSignalTypeForIsb is defined to be 0.0
+         * nanoseconds.
          */
         double satelliteInterSignalBiasNs;
 
diff --git a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
index 7b054c0..33feb5e 100644
--- a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
@@ -98,7 +98,7 @@
  * TestGnssMeasurementFields:
  * Sets a GnssMeasurementCallback, waits for a measurement, and verifies
  * 1. basebandCN0DbHz is valid
- * 2. ISB fields are valid if HAS_INTER_SIGNAL_BIAS is true.
+ * 2. ISB fields are valid
  */
 TEST_P(GnssHalTest, TestGnssMeasurementFields) {
     const int kFirstGnssMeasurementTimeoutSeconds = 10;
@@ -126,9 +126,8 @@
         // Verify basebandCn0DbHz is valid.
         ASSERT_TRUE(measurement.basebandCN0DbHz > 0.0 && measurement.basebandCN0DbHz <= 65.0);
 
-        if (((uint32_t)(measurement.flags & GnssMeasurementFlags::HAS_RECEIVER_ISB) > 0) &&
-            ((uint32_t)(measurement.flags & GnssMeasurementFlags::HAS_RECEIVER_ISB_UNCERTAINTY) >
-             0) &&
+        if (((uint32_t)(measurement.flags & GnssMeasurementFlags::HAS_FULL_ISB) > 0) &&
+            ((uint32_t)(measurement.flags & GnssMeasurementFlags::HAS_FULL_ISB_UNCERTAINTY) > 0) &&
             ((uint32_t)(measurement.flags & GnssMeasurementFlags::HAS_SATELLITE_ISB) > 0) &&
             ((uint32_t)(measurement.flags & GnssMeasurementFlags::HAS_SATELLITE_ISB_UNCERTAINTY) >
              0)) {
@@ -143,8 +142,8 @@
             ASSERT_TRUE(carrierFrequencyHz > 0);
             ASSERT_TRUE(codeType != "");
 
-            ASSERT_TRUE(std::abs(measurement.receiverInterSignalBiasNs) < 1.0e6);
-            ASSERT_TRUE(measurement.receiverInterSignalBiasUncertaintyNs >= 0);
+            ASSERT_TRUE(std::abs(measurement.fullInterSignalBiasNs) < 1.0e6);
+            ASSERT_TRUE(measurement.fullInterSignalBiasUncertaintyNs >= 0);
             ASSERT_TRUE(std::abs(measurement.satelliteInterSignalBiasNs) < 1.0e6);
             ASSERT_TRUE(measurement.satelliteInterSignalBiasUncertaintyNs >= 0);
         }
diff --git a/gnss/common/utils/default/Utils.cpp b/gnss/common/utils/default/Utils.cpp
index 2e5b873..386090e 100644
--- a/gnss/common/utils/default/Utils.cpp
+++ b/gnss/common/utils/default/Utils.cpp
@@ -39,12 +39,12 @@
             .v2_0 = gnssDataV2_0.measurements[0],
             .flags = (uint32_t)(GnssMeasurementFlagsV2_1::HAS_CARRIER_FREQUENCY |
                                 GnssMeasurementFlagsV2_1::HAS_CARRIER_PHASE |
-                                GnssMeasurementFlagsV2_1::HAS_RECEIVER_ISB |
-                                GnssMeasurementFlagsV2_1::HAS_RECEIVER_ISB_UNCERTAINTY |
+                                GnssMeasurementFlagsV2_1::HAS_FULL_ISB |
+                                GnssMeasurementFlagsV2_1::HAS_FULL_ISB_UNCERTAINTY |
                                 GnssMeasurementFlagsV2_1::HAS_SATELLITE_ISB |
                                 GnssMeasurementFlagsV2_1::HAS_SATELLITE_ISB_UNCERTAINTY),
-            .receiverInterSignalBiasNs = 10.0,
-            .receiverInterSignalBiasUncertaintyNs = 100.0,
+            .fullInterSignalBiasNs = 30.0,
+            .fullInterSignalBiasUncertaintyNs = 250.0,
             .satelliteInterSignalBiasNs = 20.0,
             .satelliteInterSignalBiasUncertaintyNs = 150.0,
             .basebandCN0DbHz = 25.0,
diff --git a/graphics/allocator/2.0/default/OWNERS b/graphics/allocator/2.0/default/OWNERS
index 273cb4c..2a56b38 100644
--- a/graphics/allocator/2.0/default/OWNERS
+++ b/graphics/allocator/2.0/default/OWNERS
@@ -1,4 +1,4 @@
 # Graphics team
-jessehall@google.com
-marissaw@google.com
+chrisforbes@google.com
 stoza@google.com
+vhau@google.com
diff --git a/graphics/allocator/2.0/utils/OWNERS b/graphics/allocator/2.0/utils/OWNERS
index 273cb4c..2a56b38 100644
--- a/graphics/allocator/2.0/utils/OWNERS
+++ b/graphics/allocator/2.0/utils/OWNERS
@@ -1,4 +1,4 @@
 # Graphics team
-jessehall@google.com
-marissaw@google.com
+chrisforbes@google.com
 stoza@google.com
+vhau@google.com
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/BlendMode.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/BlendMode.aidl
new file mode 100644
index 0000000..deafdfa
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/BlendMode.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="int") @VintfStability
+enum BlendMode {
+  INVALID = 0,
+  NONE = 1,
+  PREMULTIPLIED = 2,
+  COVERAGE = 3,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/BufferUsage.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/BufferUsage.aidl
new file mode 100644
index 0000000..58eefc4
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/BufferUsage.aidl
@@ -0,0 +1,47 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="long") @VintfStability
+enum BufferUsage {
+  CPU_READ_MASK = 15,
+  CPU_READ_NEVER = 0,
+  CPU_READ_RARELY = 2,
+  CPU_READ_OFTEN = 3,
+  CPU_WRITE_MASK = 240,
+  CPU_WRITE_NEVER = 0,
+  CPU_WRITE_RARELY = 32,
+  CPU_WRITE_OFTEN = 48,
+  GPU_TEXTURE = 256,
+  GPU_RENDER_TARGET = 512,
+  COMPOSER_OVERLAY = 2048,
+  COMPOSER_CLIENT_TARGET = 4096,
+  PROTECTED = 16384,
+  COMPOSER_CURSOR = 32768,
+  VIDEO_ENCODER = 65536,
+  CAMERA_OUTPUT = 131072,
+  CAMERA_INPUT = 262144,
+  RENDERSCRIPT = 1048576,
+  VIDEO_DECODER = 4194304,
+  SENSOR_DIRECT_DATA = 8388608,
+  GPU_CUBE_MAP = 33554432,
+  GPU_MIPMAP_COMPLETE = 67108864,
+  HW_IMAGE_ENCODER = 134217728,
+  GPU_DATA_BUFFER = 16777216,
+  VENDOR_MASK = -268435456,
+  VENDOR_MASK_HI = -281474976710656,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ChromaSiting.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ChromaSiting.aidl
new file mode 100644
index 0000000..7ca4dfa
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ChromaSiting.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="long") @VintfStability
+enum ChromaSiting {
+  NONE = 0,
+  UNKNOWN = 1,
+  SITED_INTERSTITIAL = 2,
+  COSITED_HORIZONTAL = 3,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Compression.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Compression.aidl
new file mode 100644
index 0000000..06e40a0
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Compression.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="long") @VintfStability
+enum Compression {
+  NONE = 0,
+  DISPLAY_STREAM_COMPRESSION = 1,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Cta861_3.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Cta861_3.aidl
new file mode 100644
index 0000000..d4af501
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Cta861_3.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable Cta861_3 {
+  float maxContentLightLevel;
+  float maxFrameAverageLightLevel;
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Dataspace.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Dataspace.aidl
new file mode 100644
index 0000000..43d7f84
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Dataspace.aidl
@@ -0,0 +1,81 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="int") @VintfStability
+enum Dataspace {
+  UNKNOWN = 0,
+  ARBITRARY = 1,
+  STANDARD_SHIFT = 16,
+  STANDARD_MASK = 4128768,
+  STANDARD_UNSPECIFIED = 0,
+  STANDARD_BT709 = 65536,
+  STANDARD_BT601_625 = 131072,
+  STANDARD_BT601_625_UNADJUSTED = 196608,
+  STANDARD_BT601_525 = 262144,
+  STANDARD_BT601_525_UNADJUSTED = 327680,
+  STANDARD_BT2020 = 393216,
+  STANDARD_BT2020_CONSTANT_LUMINANCE = 458752,
+  STANDARD_BT470M = 524288,
+  STANDARD_FILM = 589824,
+  STANDARD_DCI_P3 = 655360,
+  STANDARD_ADOBE_RGB = 720896,
+  TRANSFER_SHIFT = 22,
+  TRANSFER_MASK = 130023424,
+  TRANSFER_UNSPECIFIED = 0,
+  TRANSFER_LINEAR = 4194304,
+  TRANSFER_SRGB = 8388608,
+  TRANSFER_SMPTE_170M = 12582912,
+  TRANSFER_GAMMA2_2 = 16777216,
+  TRANSFER_GAMMA2_6 = 20971520,
+  TRANSFER_GAMMA2_8 = 25165824,
+  TRANSFER_ST2084 = 29360128,
+  TRANSFER_HLG = 33554432,
+  RANGE_SHIFT = 27,
+  RANGE_MASK = 939524096,
+  RANGE_UNSPECIFIED = 0,
+  RANGE_FULL = 134217728,
+  RANGE_LIMITED = 268435456,
+  RANGE_EXTENDED = 402653184,
+  SRGB_LINEAR = 138477568,
+  SCRGB_LINEAR = 406913024,
+  SRGB = 142671872,
+  SCRGB = 411107328,
+  JFIF = 146931712,
+  BT601_625 = 281149440,
+  BT601_525 = 281280512,
+  BT709 = 281083904,
+  DCI_P3_LINEAR = 139067392,
+  DCI_P3 = 155844608,
+  DISPLAY_P3_LINEAR = 139067392,
+  DISPLAY_P3 = 143261696,
+  ADOBE_RGB = 151715840,
+  BT2020_LINEAR = 138805248,
+  BT2020 = 147193856,
+  BT2020_PQ = 163971072,
+  DEPTH = 4096,
+  SENSOR = 4097,
+  BT2020_ITU = 281411584,
+  BT2020_ITU_PQ = 298188800,
+  BT2020_ITU_HLG = 302383104,
+  BT2020_HLG = 168165376,
+  DISPLAY_BT2020 = 142999552,
+  DYNAMIC_DEPTH = 4098,
+  JPEG_APP_SEGMENTS = 4099,
+  HEIF = 4100,
+  BT709_FULL_RANGE = 146866176,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ExtendableType.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ExtendableType.aidl
new file mode 100644
index 0000000..6fcb794
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/ExtendableType.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable ExtendableType {
+  @utf8InCpp String name;
+  long value = 0;
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/HardwareBuffer.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/HardwareBuffer.aidl
new file mode 100644
index 0000000..72222e1
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/HardwareBuffer.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable HardwareBuffer {
+  android.hardware.graphics.common.HardwareBufferDescription description;
+  android.hardware.common.NativeHandle handle;
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/HardwareBufferDescription.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/HardwareBufferDescription.aidl
new file mode 100644
index 0000000..8b12169
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/HardwareBufferDescription.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable HardwareBufferDescription {
+  int width;
+  int height;
+  int layers;
+  android.hardware.graphics.common.PixelFormat format;
+  android.hardware.graphics.common.BufferUsage usage;
+  int stride;
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Interlaced.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Interlaced.aidl
new file mode 100644
index 0000000..26674c9
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Interlaced.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="long") @VintfStability
+enum Interlaced {
+  NONE = 0,
+  TOP_BOTTOM = 1,
+  RIGHT_LEFT = 2,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PixelFormat.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PixelFormat.aidl
new file mode 100644
index 0000000..e5f0470
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PixelFormat.aidl
@@ -0,0 +1,50 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="int") @VintfStability
+enum PixelFormat {
+  UNSPECIFIED = 0,
+  RGBA_8888 = 1,
+  RGBX_8888 = 2,
+  RGB_888 = 3,
+  RGB_565 = 4,
+  BGRA_8888 = 5,
+  YCBCR_422_SP = 16,
+  YCRCB_420_SP = 17,
+  YCBCR_422_I = 20,
+  RGBA_FP16 = 22,
+  RAW16 = 32,
+  BLOB = 33,
+  IMPLEMENTATION_DEFINED = 34,
+  YCBCR_420_888 = 35,
+  RAW_OPAQUE = 36,
+  RAW10 = 37,
+  RAW12 = 38,
+  RGBA_1010102 = 43,
+  Y8 = 538982489,
+  Y16 = 540422489,
+  YV12 = 842094169,
+  DEPTH_16 = 48,
+  DEPTH_24 = 49,
+  DEPTH_24_STENCIL_8 = 50,
+  DEPTH_32F = 51,
+  DEPTH_32F_STENCIL_8 = 52,
+  STENCIL_8 = 53,
+  YCBCR_P010 = 54,
+  HSV_888 = 55,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayout.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayout.aidl
new file mode 100644
index 0000000..8bca42f
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayout.aidl
@@ -0,0 +1,30 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable PlaneLayout {
+  android.hardware.graphics.common.PlaneLayoutComponent[] components;
+  long offsetInBytes;
+  long sampleIncrementInBits;
+  long strideInBytes;
+  long widthInSamples;
+  long heightInSamples;
+  long totalSizeInBytes;
+  long horizontalSubsampling;
+  long verticalSubsampling;
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayoutComponent.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayoutComponent.aidl
new file mode 100644
index 0000000..f5a649c
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayoutComponent.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable PlaneLayoutComponent {
+  android.hardware.graphics.common.ExtendableType type;
+  long offsetInBits;
+  long sizeInBits;
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayoutComponentType.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayoutComponentType.aidl
new file mode 100644
index 0000000..7ff8d76
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PlaneLayoutComponentType.aidl
@@ -0,0 +1,29 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="long") @VintfStability
+enum PlaneLayoutComponentType {
+  Y = 1,
+  CB = 2,
+  CR = 4,
+  R = 1024,
+  G = 2048,
+  B = 4096,
+  RAW = 1048576,
+  A = 1073741824,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Rect.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Rect.aidl
new file mode 100644
index 0000000..e0ba69b
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Rect.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable Rect {
+  int left;
+  int top;
+  int right;
+  int bottom;
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Smpte2086.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Smpte2086.aidl
new file mode 100644
index 0000000..5da36f6
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Smpte2086.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable Smpte2086 {
+  android.hardware.graphics.common.XyColor primaryRed;
+  android.hardware.graphics.common.XyColor primaryGreen;
+  android.hardware.graphics.common.XyColor primaryBlue;
+  android.hardware.graphics.common.XyColor whitePoint;
+  float maxLuminance;
+  float minLuminance;
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/StandardMetadataType.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/StandardMetadataType.aidl
new file mode 100644
index 0000000..34b53a2
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/StandardMetadataType.aidl
@@ -0,0 +1,43 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@Backing(type="long") @VintfStability
+enum StandardMetadataType {
+  INVALID = 0,
+  BUFFER_ID = 1,
+  NAME = 2,
+  WIDTH = 3,
+  HEIGHT = 4,
+  LAYER_COUNT = 5,
+  PIXEL_FORMAT_REQUESTED = 6,
+  PIXEL_FORMAT_FOURCC = 7,
+  PIXEL_FORMAT_MODIFIER = 8,
+  USAGE = 9,
+  ALLOCATION_SIZE = 10,
+  PROTECTED_CONTENT = 11,
+  COMPRESSION = 12,
+  INTERLACED = 13,
+  CHROMA_SITING = 14,
+  PLANE_LAYOUTS = 15,
+  CROP = 16,
+  DATASPACE = 17,
+  BLEND_MODE = 18,
+  SMPTE2086 = 19,
+  CTA861_3 = 20,
+  SMPTE2094_40 = 21,
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/XyColor.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/XyColor.aidl
new file mode 100644
index 0000000..d96d0ac
--- /dev/null
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/XyColor.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.common;
+@VintfStability
+parcelable XyColor {
+  float x;
+  float y;
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/BufferUsage.aidl b/graphics/common/aidl/android/hardware/graphics/common/BufferUsage.aidl
index 5f9888a..d978f46 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/BufferUsage.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/BufferUsage.aidl
@@ -110,5 +110,5 @@
 
     /** bits 32-47 must be zero and are reserved for future versions */
     /** bits 48-63 are reserved for vendor extensions */
-    VENDOR_MASK_HI                     = 0xffff << 48,
+    VENDOR_MASK_HI                     = (1L * 0xffff) << 48,
 }
diff --git a/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl b/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
index 4942462..4e0c5ef 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
@@ -403,10 +403,6 @@
      *   cr_offset = y_size
      *   cb_offset = y_size + c_size
      *
-     * This range is reserved for vendor extensions. Formats in this range
-     * must support BufferUsage::GPU_TEXTURE. Clients must assume they do not
-     * have an alpha component.
-     *
      * This format must be accepted by the allocator when used with the
      * following usage flags:
      *
diff --git a/graphics/mapper/2.0/default/OWNERS b/graphics/mapper/2.0/default/OWNERS
index 273cb4c..2a56b38 100644
--- a/graphics/mapper/2.0/default/OWNERS
+++ b/graphics/mapper/2.0/default/OWNERS
@@ -1,4 +1,4 @@
 # Graphics team
-jessehall@google.com
-marissaw@google.com
+chrisforbes@google.com
 stoza@google.com
+vhau@google.com
diff --git a/graphics/mapper/2.0/utils/OWNERS b/graphics/mapper/2.0/utils/OWNERS
index 273cb4c..2a56b38 100644
--- a/graphics/mapper/2.0/utils/OWNERS
+++ b/graphics/mapper/2.0/utils/OWNERS
@@ -1,4 +1,4 @@
 # Graphics team
-jessehall@google.com
-marissaw@google.com
+chrisforbes@google.com
 stoza@google.com
+vhau@google.com
diff --git a/graphics/mapper/2.0/vts/OWNERS b/graphics/mapper/2.0/vts/OWNERS
index 8e86f64..11b7d21 100644
--- a/graphics/mapper/2.0/vts/OWNERS
+++ b/graphics/mapper/2.0/vts/OWNERS
@@ -1,5 +1,7 @@
 # Graphics team
-marissaw@google.com
+chrisforbes@google.com
+stoza@google.com
+vhau@google.com
 
 # VTS team
 yim@google.com
diff --git a/graphics/mapper/2.1/default/OWNERS b/graphics/mapper/2.1/default/OWNERS
index 273cb4c..2a56b38 100644
--- a/graphics/mapper/2.1/default/OWNERS
+++ b/graphics/mapper/2.1/default/OWNERS
@@ -1,4 +1,4 @@
 # Graphics team
-jessehall@google.com
-marissaw@google.com
+chrisforbes@google.com
 stoza@google.com
+vhau@google.com
diff --git a/graphics/mapper/2.1/utils/OWNERS b/graphics/mapper/2.1/utils/OWNERS
index 273cb4c..2a56b38 100644
--- a/graphics/mapper/2.1/utils/OWNERS
+++ b/graphics/mapper/2.1/utils/OWNERS
@@ -1,4 +1,4 @@
 # Graphics team
-jessehall@google.com
-marissaw@google.com
+chrisforbes@google.com
 stoza@google.com
+vhau@google.com
diff --git a/graphics/mapper/2.1/vts/OWNERS b/graphics/mapper/2.1/vts/OWNERS
index 8e86f64..11b7d21 100644
--- a/graphics/mapper/2.1/vts/OWNERS
+++ b/graphics/mapper/2.1/vts/OWNERS
@@ -1,5 +1,7 @@
 # Graphics team
-marissaw@google.com
+chrisforbes@google.com
+stoza@google.com
+vhau@google.com
 
 # VTS team
 yim@google.com
diff --git a/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
index 1185945..3d792f9 100644
--- a/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
+++ b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
@@ -94,7 +94,7 @@
                                                     mDummyDescriptorInfo.width);
     ASSERT_EQ(Error::BAD_BUFFER, ret)
         << "validateBufferSize with raw buffer handle did not fail with BAD_BUFFER";
-    native_handle_delete(rawBufferHandle);
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(rawBufferHandle));
 }
 
 /**
@@ -179,11 +179,11 @@
     ASSERT_NO_FATAL_FAILURE(rawBufferHandle = const_cast<native_handle_t*>(
                                 mGralloc->allocate(mDummyDescriptorInfo, false)));
     mGralloc->getMapper()->getTransportSize(
-        invalidHandle, [&](const auto& tmpError, const auto&, const auto&) {
-            ASSERT_EQ(Error::BAD_BUFFER, tmpError)
-                << "getTransportSize with raw buffer handle did not fail with BAD_BUFFER";
-        });
-    native_handle_delete(rawBufferHandle);
+            rawBufferHandle, [&](const auto& tmpError, const auto&, const auto&) {
+                ASSERT_EQ(Error::BAD_BUFFER, tmpError)
+                        << "getTransportSize with raw buffer handle did not fail with BAD_BUFFER";
+            });
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(rawBufferHandle));
 }
 
 /**
diff --git a/graphics/mapper/3.0/utils/OWNERS b/graphics/mapper/3.0/utils/OWNERS
index 96f6d51..2a56b38 100644
--- a/graphics/mapper/3.0/utils/OWNERS
+++ b/graphics/mapper/3.0/utils/OWNERS
@@ -1,3 +1,4 @@
 # Graphics team
-marissaw@google.com
+chrisforbes@google.com
 stoza@google.com
+vhau@google.com
diff --git a/graphics/mapper/3.0/vts/OWNERS b/graphics/mapper/3.0/vts/OWNERS
index 96f6d51..2a56b38 100644
--- a/graphics/mapper/3.0/vts/OWNERS
+++ b/graphics/mapper/3.0/vts/OWNERS
@@ -1,3 +1,4 @@
 # Graphics team
-marissaw@google.com
+chrisforbes@google.com
 stoza@google.com
+vhau@google.com
diff --git a/graphics/mapper/4.0/utils/OWNERS b/graphics/mapper/4.0/utils/OWNERS
index 96f6d51..2a56b38 100644
--- a/graphics/mapper/4.0/utils/OWNERS
+++ b/graphics/mapper/4.0/utils/OWNERS
@@ -1,3 +1,4 @@
 # Graphics team
-marissaw@google.com
+chrisforbes@google.com
 stoza@google.com
+vhau@google.com
diff --git a/graphics/mapper/4.0/vts/OWNERS b/graphics/mapper/4.0/vts/OWNERS
index 96f6d51..2a56b38 100644
--- a/graphics/mapper/4.0/vts/OWNERS
+++ b/graphics/mapper/4.0/vts/OWNERS
@@ -1,3 +1,4 @@
 # Graphics team
-marissaw@google.com
+chrisforbes@google.com
 stoza@google.com
+vhau@google.com
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index 82dbeb9..5c8d0d8 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -2134,8 +2134,14 @@
 
         Error err;
         mGralloc->getAllocator()->allocate(
-                descriptor, 1,
-                [&](const auto& tmpError, const auto&, const auto&) { err = tmpError; });
+                descriptor, 1, [&](const auto& tmpError, const auto&, const auto& tmpBuffers) {
+                    err = tmpError;
+                    if (err == Error::NONE) {
+                        ASSERT_EQ(1, tmpBuffers.size());
+                        ASSERT_NO_FATAL_FAILURE(bufferHandle =
+                                                        mGralloc->importBuffer(tmpBuffers[0]));
+                    }
+                });
         if (err == Error::UNSUPPORTED) {
             continue;
         }
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/Certificate.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/Certificate.aidl
new file mode 100644
index 0000000..7e3002d
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/Certificate.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+parcelable Certificate {
+  byte[] encodedCertificate;
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/CipherSuite.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/CipherSuite.aidl
new file mode 100644
index 0000000..447203f
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/CipherSuite.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@Backing(type="int") @VintfStability
+enum CipherSuite {
+  CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 = 1,
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/HardwareInformation.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/HardwareInformation.aidl
new file mode 100644
index 0000000..e1296e0
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/HardwareInformation.aidl
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+parcelable HardwareInformation {
+  @utf8InCpp String credentialStoreName;
+  @utf8InCpp String credentialStoreAuthorName;
+  int dataChunkSize;
+  boolean isDirectAccess;
+  @utf8InCpp String[] supportedDocTypes;
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl
new file mode 100644
index 0000000..58b90b5
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl
@@ -0,0 +1,30 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+interface IIdentityCredential {
+  byte[] deleteCredential();
+  byte[] createEphemeralKeyPair();
+  void setReaderEphemeralPublicKey(in byte[] publicKey);
+  long createAuthChallenge();
+  void startRetrieval(in android.hardware.identity.SecureAccessControlProfile[] accessControlProfiles, in android.hardware.keymaster.HardwareAuthToken authToken, in byte[] itemsRequest, in byte[] signingKeyBlob, in byte[] sessionTranscript, in byte[] readerSignature, in int[] requestCounts);
+  void startRetrieveEntryValue(in @utf8InCpp String nameSpace, in @utf8InCpp String name, in int entrySize, in int[] accessControlProfileIds);
+  byte[] retrieveEntryValue(in byte[] encryptedContent);
+  void finishRetrieval(out byte[] mac, out byte[] deviceNameSpaces);
+  android.hardware.identity.Certificate generateSigningKeyPair(out byte[] signingKeyBlob);
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredentialStore.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredentialStore.aidl
new file mode 100644
index 0000000..5dafb76
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredentialStore.aidl
@@ -0,0 +1,37 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+interface IIdentityCredentialStore {
+  android.hardware.identity.HardwareInformation getHardwareInformation();
+  android.hardware.identity.IWritableIdentityCredential createCredential(in @utf8InCpp String docType, in boolean testCredential);
+  android.hardware.identity.IIdentityCredential getCredential(in android.hardware.identity.CipherSuite cipherSuite, in byte[] credentialData);
+  const int STATUS_OK = 0;
+  const int STATUS_FAILED = 1;
+  const int STATUS_CIPHER_SUITE_NOT_SUPPORTED = 2;
+  const int STATUS_INVALID_DATA = 3;
+  const int STATUS_INVALID_AUTH_TOKEN = 4;
+  const int STATUS_INVALID_ITEMS_REQUEST_MESSAGE = 5;
+  const int STATUS_READER_SIGNATURE_CHECK_FAILED = 6;
+  const int STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND = 7;
+  const int STATUS_USER_AUTHENTICATION_FAILED = 8;
+  const int STATUS_READER_AUTHENTICATION_FAILED = 9;
+  const int STATUS_NO_ACCESS_CONTROL_PROFILES = 10;
+  const int STATUS_NOT_IN_REQUEST_MESSAGE = 11;
+  const int STATUS_SESSION_TRANSCRIPT_MISMATCH = 12;
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IWritableIdentityCredential.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IWritableIdentityCredential.aidl
new file mode 100644
index 0000000..32f283c
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IWritableIdentityCredential.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+interface IWritableIdentityCredential {
+  android.hardware.identity.Certificate[] getAttestationCertificate(in byte[] attestationApplicationId, in byte[] attestationChallenge);
+  void startPersonalization(in int accessControlProfileCount, in int[] entryCounts);
+  android.hardware.identity.SecureAccessControlProfile addAccessControlProfile(in int id, in android.hardware.identity.Certificate readerCertificate, in boolean userAuthenticationRequired, in long timeoutMillis, in long secureUserId);
+  void beginAddEntry(in int[] accessControlProfileIds, in @utf8InCpp String nameSpace, in @utf8InCpp String name, in int entrySize);
+  byte[] addEntryValue(in byte[] content);
+  void finishAddingEntries(out byte[] credentialData, out byte[] proofOfProvisioningSignature);
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/SecureAccessControlProfile.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/SecureAccessControlProfile.aidl
new file mode 100644
index 0000000..dfc1ad0
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/SecureAccessControlProfile.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+parcelable SecureAccessControlProfile {
+  int id;
+  android.hardware.identity.Certificate readerCertificate;
+  boolean userAuthenticationRequired;
+  long timeoutMillis;
+  long secureUserId;
+  byte[] mac;
+}
diff --git a/keymaster/4.1/Android.bp b/keymaster/4.1/Android.bp
index 3b505d8..f6ac6f8 100644
--- a/keymaster/4.1/Android.bp
+++ b/keymaster/4.1/Android.bp
@@ -9,7 +9,6 @@
     srcs: [
         "types.hal",
         "IKeymasterDevice.hal",
-        "IOperation.hal",
     ],
     interfaces: [
         "android.hardware.keymaster@3.0",
diff --git a/keymaster/4.1/IKeymasterDevice.hal b/keymaster/4.1/IKeymasterDevice.hal
index 1456abe..bbeccaa 100644
--- a/keymaster/4.1/IKeymasterDevice.hal
+++ b/keymaster/4.1/IKeymasterDevice.hal
@@ -24,8 +24,6 @@
 import @4.0::OperationHandle;
 import @4.0::VerificationToken;
 
-import IOperation;
-
 /**
  * @4.1::IKeymasterDevice is a minor extension to @4.0::IKeymasterDevice.  It adds support for
  *
@@ -78,18 +76,4 @@
      * 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
deleted file mode 100644
index 7103e9e..0000000
--- a/keymaster/4.1/IOperation.hal
+++ /dev/null
@@ -1,31 +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.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
index 27297b9..3442b18 100644
--- a/keymaster/4.1/default/Android.bp
+++ b/keymaster/4.1/default/Android.bp
@@ -20,6 +20,7 @@
     relative_install_path: "hw",
     vendor: true,
     init_rc: ["android.hardware.keymaster@4.1-service.rc"],
+    vintf_fragments: ["android.hardware.keymaster@4.1-service.xml"],
     srcs: ["service.cpp"],
 
     shared_libs: [
diff --git a/keymaster/4.1/default/android.hardware.keymaster@4.1-service.xml b/keymaster/4.1/default/android.hardware.keymaster@4.1-service.xml
new file mode 100644
index 0000000..9ba05c5
--- /dev/null
+++ b/keymaster/4.1/default/android.hardware.keymaster@4.1-service.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.keymaster</name>
+        <transport>hwbinder</transport>
+        <version>4.1</version>
+        <interface>
+            <name>IKeymasterDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/keymaster/4.1/support/include/keymasterV4_1/Keymaster3.h b/keymaster/4.1/support/include/keymasterV4_1/Keymaster3.h
index c201e8c..a27f78f 100644
--- a/keymaster/4.1/support/include/keymasterV4_1/Keymaster3.h
+++ b/keymaster/4.1/support/include/keymasterV4_1/Keymaster3.h
@@ -19,7 +19,6 @@
 #include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
 
 #include "Keymaster.h"
-#include "Operation.h"
 
 namespace android::hardware::keymaster::V4_1::support {
 
@@ -122,17 +121,6 @@
 
     Return<ErrorCode> earlyBootEnded() override { return ErrorCode::UNIMPLEMENTED; }
 
-    Return<void> beginOp(KeyPurpose purpose, const hidl_vec<uint8_t>& keyBlob,
-                         const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
-                         beginOp_cb _hidl_cb) override {
-        return begin(purpose, keyBlob, inParams, authToken,
-                     [&_hidl_cb](V4_0::ErrorCode errorCode, const hidl_vec<KeyParameter>& outParams,
-                                 OperationHandle operationHandle) {
-                         _hidl_cb(static_cast<ErrorCode>(errorCode), outParams,
-                                  new Operation(operationHandle));
-                     });
-    }
-
   private:
     void getVersionIfNeeded();
 
diff --git a/keymaster/4.1/support/include/keymasterV4_1/Keymaster4.h b/keymaster/4.1/support/include/keymasterV4_1/Keymaster4.h
index 6d74d98..75d9139 100644
--- a/keymaster/4.1/support/include/keymasterV4_1/Keymaster4.h
+++ b/keymaster/4.1/support/include/keymasterV4_1/Keymaster4.h
@@ -17,7 +17,6 @@
 #pragma once
 
 #include "Keymaster.h"
-#include "Operation.h"
 
 namespace android::hardware::keymaster::V4_1::support {
 
@@ -171,20 +170,6 @@
         return ErrorCode::UNIMPLEMENTED;
     }
 
-    Return<void> beginOp(KeyPurpose purpose, const hidl_vec<uint8_t>& keyBlob,
-                         const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
-                         beginOp_cb _hidl_cb) override {
-        if (km4_1_dev_) return km4_1_dev_->beginOp(purpose, keyBlob, inParams, authToken, _hidl_cb);
-
-        return km4_0_dev_->begin(
-                purpose, keyBlob, inParams, authToken,
-                [&_hidl_cb](V4_0::ErrorCode errorCode, const hidl_vec<KeyParameter>& outParams,
-                            OperationHandle operationHandle) {
-                    _hidl_cb(static_cast<ErrorCode>(errorCode), outParams,
-                             new Operation(operationHandle));
-                });
-    }
-
   private:
     void getVersionIfNeeded();
 
diff --git a/keymaster/4.1/support/include/keymasterV4_1/Operation.h b/keymaster/4.1/support/include/keymasterV4_1/Operation.h
deleted file mode 100644
index 902d49a..0000000
--- a/keymaster/4.1/support/include/keymasterV4_1/Operation.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- ** Copyright 2020, 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/keymaster/4.1/IOperation.h>
-
-#include <keymasterV4_1/keymaster_tags.h>
-
-namespace android::hardware::keymaster::V4_1::support {
-
-class Operation : public IOperation {
-  public:
-    Operation(OperationHandle handle) : handle_(handle) {}
-
-    Return<void> getOperationChallenge(getOperationChallenge_cb _hidl_cb) override {
-        _hidl_cb(V4_1::ErrorCode::OK, handle_);
-        return Void();
-    }
-
-  private:
-    OperationHandle handle_;
-};
-
-}  // namespace android::hardware::keymaster::V4_1::support
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/HardwareAuthToken.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/HardwareAuthToken.aidl
new file mode 100644
index 0000000..db1df2b
--- /dev/null
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/HardwareAuthToken.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.keymaster;
+@VintfStability
+parcelable HardwareAuthToken {
+  long challenge;
+  long userId;
+  long authenticatorId;
+  android.hardware.keymaster.HardwareAuthenticatorType authenticatorType;
+  android.hardware.keymaster.Timestamp timestamp;
+  byte[] mac;
+}
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/HardwareAuthenticatorType.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/HardwareAuthenticatorType.aidl
new file mode 100644
index 0000000..924567f
--- /dev/null
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/HardwareAuthenticatorType.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.keymaster;
+@Backing(type="int") @VintfStability
+enum HardwareAuthenticatorType {
+  NONE = 0,
+  PASSWORD = 1,
+  FINGERPRINT = 2,
+  ANY = -1,
+}
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/Timestamp.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/Timestamp.aidl
new file mode 100644
index 0000000..45fa1ae
--- /dev/null
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/Timestamp.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.keymaster;
+@VintfStability
+parcelable Timestamp {
+  long milliSeconds;
+}
diff --git a/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/BrightnessMode.aidl b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/BrightnessMode.aidl
new file mode 100644
index 0000000..c4c6d64
--- /dev/null
+++ b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/BrightnessMode.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.light;
+@VintfStability
+enum BrightnessMode {
+  USER = 0,
+  SENSOR = 1,
+  LOW_PERSISTENCE = 2,
+}
diff --git a/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/FlashMode.aidl b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/FlashMode.aidl
new file mode 100644
index 0000000..349f9f3
--- /dev/null
+++ b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/FlashMode.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.light;
+@VintfStability
+enum FlashMode {
+  NONE = 0,
+  TIMED = 1,
+  HARDWARE = 2,
+}
diff --git a/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLight.aidl b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLight.aidl
new file mode 100644
index 0000000..c397f91
--- /dev/null
+++ b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLight.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.light;
+@VintfStability
+parcelable HwLight {
+  int id;
+  int ordinal;
+  android.hardware.light.LightType type;
+}
diff --git a/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLightState.aidl b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLightState.aidl
new file mode 100644
index 0000000..44a0882
--- /dev/null
+++ b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/HwLightState.aidl
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.light;
+@VintfStability
+parcelable HwLightState {
+  int color;
+  android.hardware.light.FlashMode flashMode;
+  int flashOnMs;
+  int flashOffMs;
+  android.hardware.light.BrightnessMode brightnessMode;
+}
diff --git a/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/ILights.aidl b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/ILights.aidl
new file mode 100644
index 0000000..fc6c626
--- /dev/null
+++ b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/ILights.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.light;
+@VintfStability
+interface ILights {
+  void setLightState(in int id, in android.hardware.light.HwLightState state);
+  android.hardware.light.HwLight[] getLights();
+}
diff --git a/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/LightType.aidl b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/LightType.aidl
new file mode 100644
index 0000000..77ab98c
--- /dev/null
+++ b/light/aidl/aidl_api/android.hardware.light/current/android/hardware/light/LightType.aidl
@@ -0,0 +1,30 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.light;
+@VintfStability
+enum LightType {
+  BACKLIGHT = 0,
+  KEYBOARD = 1,
+  BUTTONS = 2,
+  BATTERY = 3,
+  NOTIFICATIONS = 4,
+  ATTENTION = 5,
+  BLUETOOTH = 6,
+  WIFI = 7,
+  MICROPHONE = 8,
+}
diff --git a/neuralnetworks/1.0/types.hal b/neuralnetworks/1.0/types.hal
index 1175a30..620eefb 100644
--- a/neuralnetworks/1.0/types.hal
+++ b/neuralnetworks/1.0/types.hal
@@ -261,7 +261,7 @@
      *      filter.
      * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
      *      tensor of type {@link OperandType::TENSOR_FLOAT32}
-     *      the bias must be of the same type.
+     *       the bias must be of the same type.
      *      For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
      *      of 0 and bias_scale == input_scale * filter_scale.
@@ -289,7 +289,7 @@
      *      filter.
      * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
      *      tensor of type {@link OperandType::TENSOR_FLOAT32}
-     *      the bias must be of the same
+     *       the bias must be of the same
      *      type.
      *      For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
@@ -356,7 +356,7 @@
      *      specifying the filter.
      * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
      *      tensor of type {@link OperandType::TENSOR_FLOAT32}
-     *      the bias must be of the same type.
+     *       the bias must be of the same type.
      *      For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
      *      of 0 and bias_scale == input_scale * filter_scale.
@@ -385,7 +385,7 @@
      *      specifying the filter.
      * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
      *      tensor of type {@link OperandType::TENSOR_FLOAT32}
-     *      the bias must be of the same type.
+     *       the bias must be of the same type.
      *      For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
      *      of 0 and bias_scale == input_scale * filter_scale.
@@ -628,7 +628,7 @@
     HASHTABLE_LOOKUP = 10,
 
     /**
-     * Applies L2 normalization along the depth dimension.
+     * Applies L2 normalization along the axis dimension.
      *
      * The values in the output tensor are computed as:
      *
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
index e28605d..ae1e3a2 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -125,7 +125,9 @@
 // Test driver for those generated from ml/nn/runtime/test/spec
 void Execute(const sp<IDevice>& device, const TestModel& testModel) {
     const Model model = createModel(testModel);
-    const Request request = createRequest(testModel);
+
+    ExecutionContext context;
+    const Request request = context.createRequest(testModel);
 
     // Create IPreparedModel.
     sp<IPreparedModel> preparedModel;
@@ -143,7 +145,7 @@
     ASSERT_EQ(ErrorStatus::NONE, executionCallback->getStatus());
 
     // Retrieve execution results.
-    const std::vector<TestBuffer> outputs = getOutputBuffers(request);
+    const std::vector<TestBuffer> outputs = context.getOutputBuffers(request);
 
     // We want "close-enough" results.
     checkResults(testModel, outputs);
@@ -158,6 +160,10 @@
     return TestModelManager::get().getTestModels(filter);
 }
 
+std::vector<NamedModel> getNamedModels(const FilterNameFn& filter) {
+    return TestModelManager::get().getTestModels(filter);
+}
+
 std::string printGeneratedTest(const testing::TestParamInfo<GeneratedTestParam>& info) {
     const auto& [namedDevice, namedModel] = info.param;
     return gtestCompliantName(getName(namedDevice) + "_" + getName(namedModel));
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h
index f230a02..1a55c2f 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h
@@ -37,6 +37,9 @@
 using FilterFn = std::function<bool(const test_helper::TestModel&)>;
 std::vector<NamedModel> getNamedModels(const FilterFn& filter);
 
+using FilterNameFn = std::function<bool(const std::string&)>;
+std::vector<NamedModel> getNamedModels(const FilterNameFn& filter);
+
 std::string printGeneratedTest(const testing::TestParamInfo<GeneratedTestParam>& info);
 
 #define INSTANTIATE_GENERATED_TEST(TestSuite, filter)                                     \
diff --git a/neuralnetworks/1.0/vts/functional/Utils.cpp b/neuralnetworks/1.0/vts/functional/Utils.cpp
index 0dba85a..3613e69 100644
--- a/neuralnetworks/1.0/vts/functional/Utils.cpp
+++ b/neuralnetworks/1.0/vts/functional/Utils.cpp
@@ -21,10 +21,13 @@
 
 #include <android-base/logging.h>
 #include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware_buffer.h>
 #include <android/hidl/allocator/1.0/IAllocator.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
+#include <vndk/hardware_buffer.h>
 
+#include <gtest/gtest.h>
 #include <algorithm>
 #include <iostream>
 #include <vector>
@@ -37,10 +40,64 @@
 using V1_0::Request;
 using V1_0::RequestArgument;
 
-constexpr uint32_t kInputPoolIndex = 0;
-constexpr uint32_t kOutputPoolIndex = 1;
+std::unique_ptr<TestAshmem> TestAshmem::create(uint32_t size) {
+    auto ashmem = std::make_unique<TestAshmem>(size);
+    return ashmem->mIsValid ? std::move(ashmem) : nullptr;
+}
 
-Request createRequest(const TestModel& testModel) {
+void TestAshmem::initialize(uint32_t size) {
+    mIsValid = false;
+    ASSERT_GT(size, 0);
+    mHidlMemory = nn::allocateSharedMemory(size);
+    ASSERT_TRUE(mHidlMemory.valid());
+    mMappedMemory = mapMemory(mHidlMemory);
+    ASSERT_NE(mMappedMemory, nullptr);
+    mPtr = static_cast<uint8_t*>(static_cast<void*>(mMappedMemory->getPointer()));
+    ASSERT_NE(mPtr, nullptr);
+    mIsValid = true;
+}
+
+std::unique_ptr<TestBlobAHWB> TestBlobAHWB::create(uint32_t size) {
+    auto ahwb = std::make_unique<TestBlobAHWB>(size);
+    return ahwb->mIsValid ? std::move(ahwb) : nullptr;
+}
+
+void TestBlobAHWB::initialize(uint32_t size) {
+    mIsValid = false;
+    ASSERT_GT(size, 0);
+    const auto usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
+    const AHardwareBuffer_Desc desc = {
+            .width = size,
+            .height = 1,
+            .layers = 1,
+            .format = AHARDWAREBUFFER_FORMAT_BLOB,
+            .usage = usage,
+            .stride = size,
+    };
+    ASSERT_EQ(AHardwareBuffer_allocate(&desc, &mAhwb), 0);
+    ASSERT_NE(mAhwb, nullptr);
+
+    void* buffer = nullptr;
+    ASSERT_EQ(AHardwareBuffer_lock(mAhwb, usage, -1, nullptr, &buffer), 0);
+    ASSERT_NE(buffer, nullptr);
+    mPtr = static_cast<uint8_t*>(buffer);
+
+    const native_handle_t* handle = AHardwareBuffer_getNativeHandle(mAhwb);
+    ASSERT_NE(handle, nullptr);
+    mHidlMemory = hidl_memory("hardware_buffer_blob", handle, desc.width);
+    mIsValid = true;
+}
+
+TestBlobAHWB::~TestBlobAHWB() {
+    if (mAhwb) {
+        AHardwareBuffer_unlock(mAhwb, nullptr);
+        AHardwareBuffer_release(mAhwb);
+    }
+}
+
+Request ExecutionContext::createRequest(const TestModel& testModel, MemoryType memoryType) {
+    CHECK(memoryType == MemoryType::ASHMEM || memoryType == MemoryType::BLOB_AHWB);
+
     // Model inputs.
     hidl_vec<RequestArgument> inputs(testModel.main.inputIndexes.size());
     size_t inputSize = 0;
@@ -80,16 +137,19 @@
     }
 
     // Allocate memory pools.
-    hidl_vec<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
-                                   nn::allocateSharedMemory(outputSize)};
-    CHECK_NE(pools[kInputPoolIndex].size(), 0u);
-    CHECK_NE(pools[kOutputPoolIndex].size(), 0u);
-    sp<IMemory> inputMemory = mapMemory(pools[kInputPoolIndex]);
-    CHECK(inputMemory.get() != nullptr);
-    uint8_t* inputPtr = static_cast<uint8_t*>(static_cast<void*>(inputMemory->getPointer()));
-    CHECK(inputPtr != nullptr);
+    if (memoryType == MemoryType::ASHMEM) {
+        mInputMemory = TestAshmem::create(inputSize);
+        mOutputMemory = TestAshmem::create(outputSize);
+    } else {
+        mInputMemory = TestBlobAHWB::create(inputSize);
+        mOutputMemory = TestBlobAHWB::create(outputSize);
+    }
+    EXPECT_NE(mInputMemory, nullptr);
+    EXPECT_NE(mOutputMemory, nullptr);
+    hidl_vec<hidl_memory> pools = {mInputMemory->getHidlMemory(), mOutputMemory->getHidlMemory()};
 
     // Copy input data to the memory pool.
+    uint8_t* inputPtr = mInputMemory->getPointer();
     for (uint32_t i = 0; i < testModel.main.inputIndexes.size(); i++) {
         const auto& op = testModel.main.operands[testModel.main.inputIndexes[i]];
         if (op.data.size() > 0) {
@@ -102,18 +162,13 @@
     return {.inputs = std::move(inputs), .outputs = std::move(outputs), .pools = std::move(pools)};
 }
 
-std::vector<TestBuffer> getOutputBuffers(const Request& request) {
-    sp<IMemory> outputMemory = mapMemory(request.pools[kOutputPoolIndex]);
-    CHECK(outputMemory.get() != nullptr);
-    uint8_t* outputPtr = static_cast<uint8_t*>(static_cast<void*>(outputMemory->getPointer()));
-    CHECK(outputPtr != nullptr);
-
+std::vector<TestBuffer> ExecutionContext::getOutputBuffers(const Request& request) const {
     // Copy out output results.
+    uint8_t* outputPtr = mOutputMemory->getPointer();
     std::vector<TestBuffer> outputBuffers;
     for (const auto& output : request.outputs) {
         outputBuffers.emplace_back(output.location.length, outputPtr + output.location.offset);
     }
-
     return outputBuffers;
 }
 
diff --git a/neuralnetworks/1.0/vts/functional/ValidateModel.cpp b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
index cc15263..79d8594 100644
--- a/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
@@ -24,6 +24,8 @@
 
 using implementation::PreparedModelCallback;
 
+using PrepareModelMutation = std::function<void(Model*)>;
+
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
 static void validateGetSupportedOperations(const sp<IDevice>& device, const std::string& message,
@@ -54,12 +56,13 @@
 }
 
 // Primary validation function. This function will take a valid model, apply a
-// mutation to it to invalidate the model, then pass it to interface calls that
-// use the model. Note that the model here is passed by value, and any mutation
-// to the model does not leave this function.
-static void validate(const sp<IDevice>& device, const std::string& message, Model model,
-                     const std::function<void(Model*)>& mutation) {
-    mutation(&model);
+// mutation to invalidate the model, then pass these to supportedOperations and
+// prepareModel.
+static void validate(const sp<IDevice>& device, const std::string& message,
+                     const Model& originalModel, const PrepareModelMutation& mutate) {
+    Model model = originalModel;
+    mutate(&model);
+
     validateGetSupportedOperations(device, message, model);
     validatePrepareModel(device, message, model);
 }
diff --git a/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
index 05eefd1..0baa85b 100644
--- a/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
@@ -24,15 +24,17 @@
 
 using implementation::ExecutionCallback;
 
+using ExecutionMutation = std::function<void(Request*)>;
+
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
 // Primary validation function. This function will take a valid request, apply a
 // mutation to it to invalidate the request, then pass it to interface calls
-// that use the request. Note that the request here is passed by value, and any
-// mutation to the request does not leave this function.
+// that use the request.
 static void validate(const sp<IPreparedModel>& preparedModel, const std::string& message,
-                     Request request, const std::function<void(Request*)>& mutation) {
-    mutation(&request);
+                     const Request& originalRequest, const ExecutionMutation& mutate) {
+    Request request = originalRequest;
+    mutate(&request);
     SCOPED_TRACE(message + " [execute]");
 
     sp<ExecutionCallback> executionCallback = new ExecutionCallback();
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp
index cb22250..2c17796 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp
@@ -129,11 +129,17 @@
 
 TEST_P(ValidationTest, Test) {
     const Model model = createModel(kTestModel);
-    const Request request = createRequest(kTestModel);
+    ExecutionContext context;
+    const Request request = context.createRequest(kTestModel);
     ASSERT_FALSE(kTestModel.expectFailure);
     validateEverything(kDevice, model, request);
 }
 
-INSTANTIATE_GENERATED_TEST(ValidationTest, [](const test_helper::TestModel&) { return true; });
+INSTANTIATE_GENERATED_TEST(ValidationTest, [](const std::string& testName) {
+    // Skip validation for the "inputs_as_internal" and "all_tensors_as_inputs"
+    // generated tests.
+    return testName.find("inputs_as_internal") == std::string::npos &&
+           testName.find("all_tensors_as_inputs") == std::string::npos;
+});
 
 }  // namespace android::hardware::neuralnetworks::V1_0::vts::functional
diff --git a/neuralnetworks/1.0/vts/functional/include/1.0/Utils.h b/neuralnetworks/1.0/vts/functional/include/1.0/Utils.h
index 6d4534c..3292f79 100644
--- a/neuralnetworks/1.0/vts/functional/include/1.0/Utils.h
+++ b/neuralnetworks/1.0/vts/functional/include/1.0/Utils.h
@@ -19,6 +19,8 @@
 
 #include <android-base/logging.h>
 #include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware_buffer.h>
+#include <android/hidl/memory/1.0/IMemory.h>
 #include <algorithm>
 #include <iosfwd>
 #include <string>
@@ -28,11 +30,73 @@
 
 namespace android::hardware::neuralnetworks {
 
-// Create HIDL Request from the TestModel struct.
-V1_0::Request createRequest(const test_helper::TestModel& testModel);
+// Convenience class to manage the lifetime of memory resources.
+class TestMemoryBase {
+    DISALLOW_COPY_AND_ASSIGN(TestMemoryBase);
 
-// After execution, copy out output results from the output memory pool.
-std::vector<::test_helper::TestBuffer> getOutputBuffers(const V1_0::Request& request);
+  public:
+    TestMemoryBase() = default;
+    virtual ~TestMemoryBase() = default;
+    uint8_t* getPointer() const { return mPtr; }
+    hidl_memory getHidlMemory() const { return mHidlMemory; }
+
+  protected:
+    uint8_t* mPtr = nullptr;
+    hidl_memory mHidlMemory;
+    bool mIsValid = false;
+};
+
+class TestAshmem : public TestMemoryBase {
+  public:
+    static std::unique_ptr<TestAshmem> create(uint32_t size);
+
+    // Prefer TestAshmem::create.
+    // The constructor calls initialize, which constructs the memory resources. This is a workaround
+    // that gtest macros cannot be used directly in a constructor.
+    TestAshmem(uint32_t size) { initialize(size); }
+
+  private:
+    void initialize(uint32_t size);
+    sp<hidl::memory::V1_0::IMemory> mMappedMemory;
+};
+
+class TestBlobAHWB : public TestMemoryBase {
+  public:
+    static std::unique_ptr<TestBlobAHWB> create(uint32_t size);
+
+    // Prefer TestBlobAHWB::create.
+    // The constructor calls initialize, which constructs the memory resources. This is a
+    // workaround that gtest macros cannot be used directly in a constructor.
+    TestBlobAHWB(uint32_t size) { initialize(size); }
+    ~TestBlobAHWB();
+
+  private:
+    void initialize(uint32_t size);
+    AHardwareBuffer* mAhwb = nullptr;
+};
+
+enum class MemoryType { ASHMEM, BLOB_AHWB, DEVICE };
+
+// Manages the lifetime of memory resources used in an execution.
+class ExecutionContext {
+    DISALLOW_COPY_AND_ASSIGN(ExecutionContext);
+
+  public:
+    static constexpr uint32_t kInputPoolIndex = 0;
+    static constexpr uint32_t kOutputPoolIndex = 1;
+
+    ExecutionContext() = default;
+
+    // Create HIDL Request from the TestModel struct.
+    V1_0::Request createRequest(const test_helper::TestModel& testModel,
+                                MemoryType memoryType = MemoryType::ASHMEM);
+
+    // After execution, copy out output results from the output memory pool.
+    std::vector<test_helper::TestBuffer> getOutputBuffers(const V1_0::Request& request) const;
+
+  private:
+    std::unique_ptr<TestMemoryBase> mInputMemory, mOutputMemory;
+};
 
 // Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
 // so this is efficiently accomplished by moving the element to the end and
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.cpp
index cee15a3..a233835 100644
--- a/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.cpp
@@ -133,7 +133,9 @@
 // Test driver for those generated from ml/nn/runtime/test/spec
 void Execute(const sp<IDevice>& device, const TestModel& testModel) {
     const Model model = createModel(testModel);
-    const Request request = createRequest(testModel);
+
+    ExecutionContext context;
+    const Request request = context.createRequest(testModel);
 
     // Create IPreparedModel.
     sp<IPreparedModel> preparedModel;
@@ -151,7 +153,7 @@
     ASSERT_EQ(ErrorStatus::NONE, executionCallback->getStatus());
 
     // Retrieve execution results.
-    const std::vector<TestBuffer> outputs = getOutputBuffers(request);
+    const std::vector<TestBuffer> outputs = context.getOutputBuffers(request);
 
     // We want "close-enough" results.
     checkResults(testModel, outputs);
@@ -166,6 +168,10 @@
     return TestModelManager::get().getTestModels(filter);
 }
 
+std::vector<NamedModel> getNamedModels(const FilterNameFn& filter) {
+    return TestModelManager::get().getTestModels(filter);
+}
+
 std::string printGeneratedTest(const testing::TestParamInfo<GeneratedTestParam>& info) {
     const auto& [namedDevice, namedModel] = info.param;
     return gtestCompliantName(getName(namedDevice) + "_" + getName(namedModel));
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.h
index cf449ea..4b1a96e 100644
--- a/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.h
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.h
@@ -37,6 +37,9 @@
 using FilterFn = std::function<bool(const test_helper::TestModel&)>;
 std::vector<NamedModel> getNamedModels(const FilterFn& filter);
 
+using FilterNameFn = std::function<bool(const std::string&)>;
+std::vector<NamedModel> getNamedModels(const FilterNameFn& filter);
+
 std::string printGeneratedTest(const testing::TestParamInfo<GeneratedTestParam>& info);
 
 #define INSTANTIATE_GENERATED_TEST(TestSuite, filter)                                     \
diff --git a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
index 0629a1e..3b6f0f8 100644
--- a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
@@ -30,6 +30,8 @@
 using V1_0::OperandType;
 using V1_0::implementation::PreparedModelCallback;
 
+using PrepareModelMutation = std::function<void(Model*, ExecutionPreference*)>;
+
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
 static void validateGetSupportedOperations(const sp<IDevice>& device, const std::string& message,
@@ -67,16 +69,19 @@
 }
 
 // Primary validation function. This function will take a valid model, apply a
-// mutation to it to invalidate the model, then pass it to interface calls that
-// use the model. Note that the model here is passed by value, and any mutation
-// to the model does not leave this function.
-static void validate(const sp<IDevice>& device, const std::string& message, Model model,
-                     const std::function<void(Model*)>& mutation,
-                     ExecutionPreference preference = ExecutionPreference::FAST_SINGLE_ANSWER) {
-    mutation(&model);
+// mutation to invalidate either the model or the execution preference, then
+// pass these to supportedOperations and/or prepareModel if that method is
+// called with an invalid argument.
+static void validate(const sp<IDevice>& device, const std::string& message,
+                     const Model& originalModel, const PrepareModelMutation& mutate) {
+    Model model = originalModel;
+    ExecutionPreference preference = ExecutionPreference::FAST_SINGLE_ANSWER;
+    mutate(&model, &preference);
+
     if (validExecutionPreference(preference)) {
         validateGetSupportedOperations(device, message, model);
     }
+
     validatePrepareModel(device, message, model, preference);
 }
 
@@ -115,9 +120,11 @@
             const std::string message = "mutateOperandTypeTest: operand " +
                                         std::to_string(operand) + " set to value " +
                                         std::to_string(invalidOperandType);
-            validate(device, message, model, [operand, invalidOperandType](Model* model) {
-                model->operands[operand].type = static_cast<OperandType>(invalidOperandType);
-            });
+            validate(device, message, model,
+                     [operand, invalidOperandType](Model* model, ExecutionPreference*) {
+                         model->operands[operand].type =
+                                 static_cast<OperandType>(invalidOperandType);
+                     });
         }
     }
 }
@@ -144,9 +151,10 @@
         const uint32_t invalidRank = getInvalidRank(model.operands[operand].type);
         const std::string message = "mutateOperandRankTest: operand " + std::to_string(operand) +
                                     " has rank of " + std::to_string(invalidRank);
-        validate(device, message, model, [operand, invalidRank](Model* model) {
-            model->operands[operand].dimensions = std::vector<uint32_t>(invalidRank, 0);
-        });
+        validate(device, message, model,
+                 [operand, invalidRank](Model* model, ExecutionPreference*) {
+                     model->operands[operand].dimensions = std::vector<uint32_t>(invalidRank, 0);
+                 });
     }
 }
 
@@ -173,9 +181,10 @@
         const float invalidScale = getInvalidScale(model.operands[operand].type);
         const std::string message = "mutateOperandScaleTest: operand " + std::to_string(operand) +
                                     " has scale of " + std::to_string(invalidScale);
-        validate(device, message, model, [operand, invalidScale](Model* model) {
-            model->operands[operand].scale = invalidScale;
-        });
+        validate(device, message, model,
+                 [operand, invalidScale](Model* model, ExecutionPreference*) {
+                     model->operands[operand].scale = invalidScale;
+                 });
     }
 }
 
@@ -204,9 +213,10 @@
             const std::string message = "mutateOperandZeroPointTest: operand " +
                                         std::to_string(operand) + " has zero point of " +
                                         std::to_string(invalidZeroPoint);
-            validate(device, message, model, [operand, invalidZeroPoint](Model* model) {
-                model->operands[operand].zeroPoint = invalidZeroPoint;
-            });
+            validate(device, message, model,
+                     [operand, invalidZeroPoint](Model* model, ExecutionPreference*) {
+                         model->operands[operand].zeroPoint = invalidZeroPoint;
+                     });
         }
     }
 }
@@ -282,9 +292,10 @@
             const std::string message = "mutateOperationOperandTypeTest: operand " +
                                         std::to_string(operand) + " set to type " +
                                         toString(invalidOperandType);
-            validate(device, message, model, [operand, invalidOperandType](Model* model) {
-                mutateOperand(&model->operands[operand], invalidOperandType);
-            });
+            validate(device, message, model,
+                     [operand, invalidOperandType](Model* model, ExecutionPreference*) {
+                         mutateOperand(&model->operands[operand], invalidOperandType);
+                     });
         }
     }
 }
@@ -304,10 +315,11 @@
             const std::string message = "mutateOperationTypeTest: operation " +
                                         std::to_string(operation) + " set to value " +
                                         std::to_string(invalidOperationType);
-            validate(device, message, model, [operation, invalidOperationType](Model* model) {
-                model->operations[operation].type =
-                        static_cast<OperationType>(invalidOperationType);
-            });
+            validate(device, message, model,
+                     [operation, invalidOperationType](Model* model, ExecutionPreference*) {
+                         model->operations[operation].type =
+                                 static_cast<OperationType>(invalidOperationType);
+                     });
         }
     }
 }
@@ -321,9 +333,10 @@
             const std::string message = "mutateOperationInputOperandIndexTest: operation " +
                                         std::to_string(operation) + " input " +
                                         std::to_string(input);
-            validate(device, message, model, [operation, input, invalidOperand](Model* model) {
-                model->operations[operation].inputs[input] = invalidOperand;
-            });
+            validate(device, message, model,
+                     [operation, input, invalidOperand](Model* model, ExecutionPreference*) {
+                         model->operations[operation].inputs[input] = invalidOperand;
+                     });
         }
     }
 }
@@ -337,9 +350,10 @@
             const std::string message = "mutateOperationOutputOperandIndexTest: operation " +
                                         std::to_string(operation) + " output " +
                                         std::to_string(output);
-            validate(device, message, model, [operation, output, invalidOperand](Model* model) {
-                model->operations[operation].outputs[output] = invalidOperand;
-            });
+            validate(device, message, model,
+                     [operation, output, invalidOperand](Model* model, ExecutionPreference*) {
+                         model->operations[operation].outputs[output] = invalidOperand;
+                     });
         }
     }
 }
@@ -372,7 +386,7 @@
     for (size_t operand = 0; operand < model.operands.size(); ++operand) {
         const std::string message = "removeOperandTest: operand " + std::to_string(operand);
         validate(device, message, model,
-                 [operand](Model* model) { removeOperand(model, operand); });
+                 [operand](Model* model, ExecutionPreference*) { removeOperand(model, operand); });
     }
 }
 
@@ -388,8 +402,9 @@
 static void removeOperationTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         const std::string message = "removeOperationTest: operation " + std::to_string(operation);
-        validate(device, message, model,
-                 [operation](Model* model) { removeOperation(model, operation); });
+        validate(device, message, model, [operation](Model* model, ExecutionPreference*) {
+            removeOperation(model, operation);
+        });
     }
 }
 
@@ -409,11 +424,12 @@
             const std::string message = "removeOperationInputTest: operation " +
                                         std::to_string(operation) + ", input " +
                                         std::to_string(input);
-            validate(device, message, model, [operation, input](Model* model) {
-                uint32_t operand = model->operations[operation].inputs[input];
-                model->operands[operand].numberOfConsumers--;
-                hidl_vec_removeAt(&model->operations[operation].inputs, input);
-            });
+            validate(device, message, model,
+                     [operation, input](Model* model, ExecutionPreference*) {
+                         uint32_t operand = model->operations[operation].inputs[input];
+                         model->operands[operand].numberOfConsumers--;
+                         hidl_vec_removeAt(&model->operations[operation].inputs, input);
+                     });
         }
     }
 }
@@ -426,9 +442,10 @@
             const std::string message = "removeOperationOutputTest: operation " +
                                         std::to_string(operation) + ", output " +
                                         std::to_string(output);
-            validate(device, message, model, [operation, output](Model* model) {
-                hidl_vec_removeAt(&model->operations[operation].outputs, output);
-            });
+            validate(device, message, model,
+                     [operation, output](Model* model, ExecutionPreference*) {
+                         hidl_vec_removeAt(&model->operations[operation].outputs, output);
+                     });
         }
     }
 }
@@ -444,7 +461,7 @@
 static void addOperationInputTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         const std::string message = "addOperationInputTest: operation " + std::to_string(operation);
-        validate(device, message, model, [operation](Model* model) {
+        validate(device, message, model, [operation](Model* model, ExecutionPreference*) {
             uint32_t index = addOperand(model, OperandLifeTime::MODEL_INPUT);
             hidl_vec_push_back(&model->operations[operation].inputs, index);
             hidl_vec_push_back(&model->inputIndexes, index);
@@ -458,7 +475,7 @@
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         const std::string message =
                 "addOperationOutputTest: operation " + std::to_string(operation);
-        validate(device, message, model, [operation](Model* model) {
+        validate(device, message, model, [operation](Model* model, ExecutionPreference*) {
             uint32_t index = addOperand(model, OperandLifeTime::MODEL_OUTPUT);
             hidl_vec_push_back(&model->operations[operation].outputs, index);
             hidl_vec_push_back(&model->outputIndexes, index);
@@ -474,12 +491,13 @@
 };
 
 static void mutateExecutionPreferenceTest(const sp<IDevice>& device, const Model& model) {
-    for (int32_t preference : invalidExecutionPreferences) {
+    for (int32_t invalidPreference : invalidExecutionPreferences) {
         const std::string message =
-                "mutateExecutionPreferenceTest: preference " + std::to_string(preference);
-        validate(
-                device, message, model, [](Model*) {},
-                static_cast<ExecutionPreference>(preference));
+                "mutateExecutionPreferenceTest: preference " + std::to_string(invalidPreference);
+        validate(device, message, model,
+                 [invalidPreference](Model*, ExecutionPreference* preference) {
+                     *preference = static_cast<ExecutionPreference>(invalidPreference);
+                 });
     }
 }
 
diff --git a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
index 9684eb2..2914335 100644
--- a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
@@ -28,15 +28,17 @@
 using V1_0::Request;
 using V1_0::implementation::ExecutionCallback;
 
+using ExecutionMutation = std::function<void(Request*)>;
+
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
 // Primary validation function. This function will take a valid request, apply a
 // mutation to it to invalidate the request, then pass it to interface calls
-// that use the request. Note that the request here is passed by value, and any
-// mutation to the request does not leave this function.
+// that use the request.
 static void validate(const sp<IPreparedModel>& preparedModel, const std::string& message,
-                     Request request, const std::function<void(Request*)>& mutation) {
-    mutation(&request);
+                     const Request& originalRequest, const ExecutionMutation& mutate) {
+    Request request = originalRequest;
+    mutate(&request);
     SCOPED_TRACE(message + " [execute]");
 
     sp<ExecutionCallback> executionCallback = new ExecutionCallback();
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp
index d56d40b..54e8802 100644
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp
@@ -132,11 +132,17 @@
 
 TEST_P(ValidationTest, Test) {
     const Model model = createModel(kTestModel);
-    const Request request = createRequest(kTestModel);
+    ExecutionContext context;
+    const Request request = context.createRequest(kTestModel);
     ASSERT_FALSE(kTestModel.expectFailure);
     validateEverything(kDevice, model, request);
 }
 
-INSTANTIATE_GENERATED_TEST(ValidationTest, [](const test_helper::TestModel&) { return true; });
+INSTANTIATE_GENERATED_TEST(ValidationTest, [](const std::string& testName) {
+    // Skip validation for the "inputs_as_internal" and "all_tensors_as_inputs"
+    // generated tests.
+    return testName.find("inputs_as_internal") == std::string::npos &&
+           testName.find("all_tensors_as_inputs") == std::string::npos;
+});
 
 }  // namespace android::hardware::neuralnetworks::V1_1::vts::functional
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index f0fd769..2c3c599 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -846,7 +846,7 @@
     HASHTABLE_LOOKUP = @1.1::OperationType:HASHTABLE_LOOKUP,
 
     /**
-     * Applies L2 normalization along the depth dimension.
+     * Applies L2 normalization along the axis dimension.
      *
      * The values in the output tensor are computed as:
      *
@@ -854,8 +854,7 @@
      *         input[batch, row, col, channel] /
      *         sqrt(sum_{c} pow(input[batch, row, col, c], 2))
      *
-     * For input tensor with rank less than 4, independently normalizes each
-     * 1-D slice along dimension dim.
+     * By default the axis dimension is the last dimension of the input tensor.
      *
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
@@ -3843,7 +3842,8 @@
      * * 1: A scalar {@link OperandType::INT32}, specifying the number of
      *      independent samples to draw for each row slice.
      * * 2: A 1-D {@link OperandType::TENSOR_INT32} tensor with shape [2],
-     *      specifying seeds used to initialize the random distribution.
+     *      specifying seeds used to initialize the random distribution. If both
+     *      provided seeds are 0, both will be randomly generated.
      * Outputs:
      * * 0: A 2-D {@link OperandType::TENSOR_INT32} tensor with shape
      *      [batches, samples], containing the drawn samples.
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index 31a1a81..7c1faee 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -28,7 +28,7 @@
     ],
     header_libs: [
         "libbase_headers",
-    ]
+    ],
 }
 
 cc_test {
@@ -39,9 +39,9 @@
         "CompilationCachingTests.cpp",
         "GeneratedTestHarness.cpp",
         "TestAssertions.cpp",
+        "ValidateBurst.cpp",
         "ValidateModel.cpp",
         "ValidateRequest.cpp",
-        "ValidateBurst.cpp",
         "VtsHalNeuralnetworks.cpp",
     ],
     local_include_dirs: ["include"],
@@ -50,18 +50,17 @@
         "libnativewindow",
     ],
     static_libs: [
+        "VtsHalNeuralNetworksV1_0_utils",
+        "VtsHalNeuralNetworksV1_2Callbacks",
         "android.hardware.neuralnetworks@1.0",
         "android.hardware.neuralnetworks@1.1",
         "android.hardware.neuralnetworks@1.2",
-        "android.hardware.neuralnetworks@1.3",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
         "libgmock",
         "libhidlmemory",
         "libneuralnetworks_generated_test_harness",
         "libneuralnetworks_utils",
-        "VtsHalNeuralNetworksV1_0_utils",
-        "VtsHalNeuralNetworksV1_2Callbacks",
     ],
     whole_static_libs: [
         "neuralnetworks_generated_V1_0_example",
@@ -71,5 +70,8 @@
     header_libs: [
         "libneuralnetworks_headers",
     ],
-    test_suites: ["general-tests", "vts-core"],
+    test_suites: [
+        "general-tests",
+        "vts-core",
+    ],
 }
diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
index 10dec79..449b8f3 100644
--- a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
@@ -32,7 +32,6 @@
 #include "GeneratedTestHarness.h"
 #include "MemoryUtils.h"
 #include "TestHarness.h"
-#include "Utils.h"
 #include "VtsHalNeuralnetworks.h"
 
 // Forward declaration of the mobilenet generated test models in
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
index 4c8fede..35275b4 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
@@ -43,7 +43,6 @@
 #include "ExecutionBurstController.h"
 #include "MemoryUtils.h"
 #include "TestHarness.h"
-#include "Utils.h"
 #include "VtsHalNeuralnetworks.h"
 
 namespace android::hardware::neuralnetworks::V1_2::vts::functional {
@@ -69,6 +68,7 @@
     Executor executor;
     MeasureTiming measureTiming;
     OutputType outputType;
+    MemoryType memoryType;
 };
 
 }  // namespace
@@ -217,7 +217,8 @@
         return;
     }
 
-    Request request = createRequest(testModel);
+    ExecutionContext context;
+    Request request = context.createRequest(testModel, testConfig.memoryType);
     if (testConfig.outputType == OutputType::INSUFFICIENT) {
         makeOutputInsufficientSize(/*outputIndex=*/0, &request);
     }
@@ -273,7 +274,7 @@
             int n;
             std::tie(n, outputShapes, timing, std::ignore) =
                     controller->compute(request, testConfig.measureTiming, keys);
-            executionStatus = nn::convertToV1_0(nn::convertResultCodeToErrorStatus(n));
+            executionStatus = nn::legacyConvertResultCodeToErrorStatus(n);
 
             break;
         }
@@ -327,7 +328,7 @@
     }
 
     // Retrieve execution results.
-    const std::vector<TestBuffer> outputs = getOutputBuffers(request);
+    const std::vector<TestBuffer> outputs = context.getOutputBuffers(request);
 
     // We want "close-enough" results.
     checkResults(testModel, outputs);
@@ -338,24 +339,30 @@
     std::vector<OutputType> outputTypesList;
     std::vector<MeasureTiming> measureTimingList;
     std::vector<Executor> executorList;
+    std::vector<MemoryType> memoryTypeList;
 
     if (testDynamicOutputShape) {
         outputTypesList = {OutputType::UNSPECIFIED, OutputType::INSUFFICIENT};
         measureTimingList = {MeasureTiming::NO, MeasureTiming::YES};
         executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST};
+        memoryTypeList = {MemoryType::ASHMEM};
     } else {
         outputTypesList = {OutputType::FULLY_SPECIFIED};
         measureTimingList = {MeasureTiming::NO, MeasureTiming::YES};
         executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST};
+        memoryTypeList = {MemoryType::ASHMEM, MemoryType::BLOB_AHWB};
     }
 
     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);
+                for (const MemoryType memoryType : memoryTypeList) {
+                    const TestConfig testConfig = {.executor = executor,
+                                                   .measureTiming = measureTiming,
+                                                   .outputType = outputType,
+                                                   .memoryType = memoryType};
+                    EvaluatePreparedModel(preparedModel, testModel, testConfig);
+                }
             }
         }
     }
@@ -383,6 +390,10 @@
     return TestModelManager::get().getTestModels(filter);
 }
 
+std::vector<NamedModel> getNamedModels(const FilterNameFn& filter) {
+    return TestModelManager::get().getTestModels(filter);
+}
+
 std::string printGeneratedTest(const testing::TestParamInfo<GeneratedTestParam>& info) {
     const auto& [namedDevice, namedModel] = info.param;
     return gtestCompliantName(getName(namedDevice) + "_" + getName(namedModel));
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.h
index dfc980c..98295ff 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.h
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.h
@@ -41,6 +41,9 @@
 using FilterFn = std::function<bool(const test_helper::TestModel&)>;
 std::vector<NamedModel> getNamedModels(const FilterFn& filter);
 
+using FilterNameFn = std::function<bool(const std::string&)>;
+std::vector<NamedModel> getNamedModels(const FilterNameFn& filter);
+
 std::string printGeneratedTest(const testing::TestParamInfo<GeneratedTestParam>& info);
 
 #define INSTANTIATE_GENERATED_TEST(TestSuite, filter)                                     \
diff --git a/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp b/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp
index ec9629b..4476266 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp
@@ -23,7 +23,6 @@
 #include "ExecutionBurstServer.h"
 #include "GeneratedTestHarness.h"
 #include "TestHarness.h"
-#include "Utils.h"
 
 #include <android-base/logging.h>
 #include <chrono>
@@ -38,6 +37,8 @@
 using V1_0::Request;
 using ExecutionBurstCallback = ExecutionBurstController::ExecutionBurstCallback;
 
+using BurstExecutionMutation = std::function<void(std::vector<FmqRequestDatum>*)>;
+
 // This constant value represents the length of an FMQ that is large enough to
 // return a result from a burst execution for all of the generated test cases.
 constexpr size_t kExecutionBurstChannelLength = 1024;
@@ -116,13 +117,13 @@
 
 // Primary validation function. This function will take a valid serialized
 // request, apply a mutation to it to invalidate the serialized request, then
-// pass it to interface calls that use the serialized request. Note that the
-// serialized request here is passed by value, and any mutation to the
-// serialized request does not leave this function.
+// pass it to interface calls that use the serialized request.
 static void validate(RequestChannelSender* sender, ResultChannelReceiver* receiver,
-                     const std::string& message, std::vector<FmqRequestDatum> serialized,
-                     const std::function<void(std::vector<FmqRequestDatum>*)>& mutation) {
-    mutation(&serialized);
+                     const std::string& message,
+                     const std::vector<FmqRequestDatum>& originalSerialized,
+                     const BurstExecutionMutation& mutate) {
+    std::vector<FmqRequestDatum> serialized = originalSerialized;
+    mutate(&serialized);
 
     // skip if packet is too large to send
     if (serialized.size() > kExecutionBurstChannelLength) {
@@ -296,8 +297,7 @@
     // collect serialized result by running regular burst
     const auto [nRegular, outputShapesRegular, timingRegular, fallbackRegular] =
             controllerRegular->compute(request, MeasureTiming::NO, keys);
-    const ErrorStatus statusRegular =
-            nn::convertToV1_0(nn::convertResultCodeToErrorStatus(nRegular));
+    const ErrorStatus statusRegular = nn::legacyConvertResultCodeToErrorStatus(nRegular);
     EXPECT_FALSE(fallbackRegular);
 
     // skip test if regular burst output isn't useful for testing a failure
@@ -313,7 +313,7 @@
     // large enough to return the serialized result
     const auto [nSmall, outputShapesSmall, timingSmall, fallbackSmall] =
             controllerSmall->compute(request, MeasureTiming::NO, keys);
-    const ErrorStatus statusSmall = nn::convertToV1_0(nn::convertResultCodeToErrorStatus(nSmall));
+    const ErrorStatus statusSmall = nn::legacyConvertResultCodeToErrorStatus(nSmall);
     EXPECT_NE(ErrorStatus::NONE, statusSmall);
     EXPECT_EQ(0u, outputShapesSmall.size());
     EXPECT_TRUE(badTiming(timingSmall));
diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
index 30530be..7451f09 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
@@ -29,6 +29,8 @@
 using V1_1::ExecutionPreference;
 using HidlToken = hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
 
+using PrepareModelMutation = std::function<void(Model*, ExecutionPreference*)>;
+
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
 static void validateGetSupportedOperations(const sp<IDevice>& device, const std::string& message,
@@ -67,16 +69,19 @@
 }
 
 // Primary validation function. This function will take a valid model, apply a
-// mutation to it to invalidate the model, then pass it to interface calls that
-// use the model. Note that the model here is passed by value, and any mutation
-// to the model does not leave this function.
-static void validate(const sp<IDevice>& device, const std::string& message, Model model,
-                     const std::function<void(Model*)>& mutation,
-                     ExecutionPreference preference = ExecutionPreference::FAST_SINGLE_ANSWER) {
-    mutation(&model);
+// mutation to invalidate either the model or the execution preference, then
+// pass these to supportedOperations and/or prepareModel if that method is
+// called with an invalid argument.
+static void validate(const sp<IDevice>& device, const std::string& message,
+                     const Model& originalModel, const PrepareModelMutation& mutate) {
+    Model model = originalModel;
+    ExecutionPreference preference = ExecutionPreference::FAST_SINGLE_ANSWER;
+    mutate(&model, &preference);
+
     if (validExecutionPreference(preference)) {
         validateGetSupportedOperations(device, message, model);
     }
+
     validatePrepareModel(device, message, model, preference);
 }
 
@@ -115,9 +120,11 @@
             const std::string message = "mutateOperandTypeTest: operand " +
                                         std::to_string(operand) + " set to value " +
                                         std::to_string(invalidOperandType);
-            validate(device, message, model, [operand, invalidOperandType](Model* model) {
-                model->operands[operand].type = static_cast<OperandType>(invalidOperandType);
-            });
+            validate(device, message, model,
+                     [operand, invalidOperandType](Model* model, ExecutionPreference*) {
+                         model->operands[operand].type =
+                                 static_cast<OperandType>(invalidOperandType);
+                     });
         }
     }
 }
@@ -155,9 +162,10 @@
         }
         const std::string message = "mutateOperandRankTest: operand " + std::to_string(operand) +
                                     " has rank of " + std::to_string(invalidRank);
-        validate(device, message, model, [operand, invalidRank](Model* model) {
-            model->operands[operand].dimensions = std::vector<uint32_t>(invalidRank, 0);
-        });
+        validate(device, message, model,
+                 [operand, invalidRank](Model* model, ExecutionPreference*) {
+                     model->operands[operand].dimensions = std::vector<uint32_t>(invalidRank, 0);
+                 });
     }
 }
 
@@ -192,9 +200,10 @@
         const float invalidScale = getInvalidScale(model.operands[operand].type);
         const std::string message = "mutateOperandScaleTest: operand " + std::to_string(operand) +
                                     " has scale of " + std::to_string(invalidScale);
-        validate(device, message, model, [operand, invalidScale](Model* model) {
-            model->operands[operand].scale = invalidScale;
-        });
+        validate(device, message, model,
+                 [operand, invalidScale](Model* model, ExecutionPreference*) {
+                     model->operands[operand].scale = invalidScale;
+                 });
     }
 }
 
@@ -234,9 +243,10 @@
             const std::string message = "mutateOperandZeroPointTest: operand " +
                                         std::to_string(operand) + " has zero point of " +
                                         std::to_string(invalidZeroPoint);
-            validate(device, message, model, [operand, invalidZeroPoint](Model* model) {
-                model->operands[operand].zeroPoint = invalidZeroPoint;
-            });
+            validate(device, message, model,
+                     [operand, invalidZeroPoint](Model* model, ExecutionPreference*) {
+                         model->operands[operand].zeroPoint = invalidZeroPoint;
+                     });
         }
     }
 }
@@ -386,9 +396,10 @@
             const std::string message = "mutateOperationOperandTypeTest: operand " +
                                         std::to_string(operand) + " set to type " +
                                         toString(invalidOperandType);
-            validate(device, message, model, [operand, invalidOperandType](Model* model) {
-                mutateOperand(&model->operands[operand], invalidOperandType);
-            });
+            validate(device, message, model,
+                     [operand, invalidOperandType](Model* model, ExecutionPreference*) {
+                         mutateOperand(&model->operands[operand], invalidOperandType);
+                     });
         }
     }
 }
@@ -407,10 +418,11 @@
             const std::string message = "mutateOperationTypeTest: operation " +
                                         std::to_string(operation) + " set to value " +
                                         std::to_string(invalidOperationType);
-            validate(device, message, model, [operation, invalidOperationType](Model* model) {
-                model->operations[operation].type =
-                        static_cast<OperationType>(invalidOperationType);
-            });
+            validate(device, message, model,
+                     [operation, invalidOperationType](Model* model, ExecutionPreference*) {
+                         model->operations[operation].type =
+                                 static_cast<OperationType>(invalidOperationType);
+                     });
         }
     }
 }
@@ -424,9 +436,10 @@
             const std::string message = "mutateOperationInputOperandIndexTest: operation " +
                                         std::to_string(operation) + " input " +
                                         std::to_string(input);
-            validate(device, message, model, [operation, input, invalidOperand](Model* model) {
-                model->operations[operation].inputs[input] = invalidOperand;
-            });
+            validate(device, message, model,
+                     [operation, input, invalidOperand](Model* model, ExecutionPreference*) {
+                         model->operations[operation].inputs[input] = invalidOperand;
+                     });
         }
     }
 }
@@ -440,9 +453,10 @@
             const std::string message = "mutateOperationOutputOperandIndexTest: operation " +
                                         std::to_string(operation) + " output " +
                                         std::to_string(output);
-            validate(device, message, model, [operation, output, invalidOperand](Model* model) {
-                model->operations[operation].outputs[output] = invalidOperand;
-            });
+            validate(device, message, model,
+                     [operation, output, invalidOperand](Model* model, ExecutionPreference*) {
+                         model->operations[operation].outputs[output] = invalidOperand;
+                     });
         }
     }
 }
@@ -503,7 +517,7 @@
         }
         const std::string message = "removeOperandTest: operand " + std::to_string(operand);
         validate(device, message, model,
-                 [operand](Model* model) { removeOperand(model, operand); });
+                 [operand](Model* model, ExecutionPreference*) { removeOperand(model, operand); });
     }
 }
 
@@ -519,8 +533,9 @@
 static void removeOperationTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         const std::string message = "removeOperationTest: operation " + std::to_string(operation);
-        validate(device, message, model,
-                 [operation](Model* model) { removeOperation(model, operation); });
+        validate(device, message, model, [operation](Model* model, ExecutionPreference*) {
+            removeOperation(model, operation);
+        });
     }
 }
 
@@ -601,11 +616,12 @@
             const std::string message = "removeOperationInputTest: operation " +
                                         std::to_string(operation) + ", input " +
                                         std::to_string(input);
-            validate(device, message, model, [operation, input](Model* model) {
-                uint32_t operand = model->operations[operation].inputs[input];
-                model->operands[operand].numberOfConsumers--;
-                hidl_vec_removeAt(&model->operations[operation].inputs, input);
-            });
+            validate(device, message, model,
+                     [operation, input](Model* model, ExecutionPreference*) {
+                         uint32_t operand = model->operations[operation].inputs[input];
+                         model->operands[operand].numberOfConsumers--;
+                         hidl_vec_removeAt(&model->operations[operation].inputs, input);
+                     });
         }
     }
 }
@@ -618,9 +634,10 @@
             const std::string message = "removeOperationOutputTest: operation " +
                                         std::to_string(operation) + ", output " +
                                         std::to_string(output);
-            validate(device, message, model, [operation, output](Model* model) {
-                hidl_vec_removeAt(&model->operations[operation].outputs, output);
-            });
+            validate(device, message, model,
+                     [operation, output](Model* model, ExecutionPreference*) {
+                         hidl_vec_removeAt(&model->operations[operation].outputs, output);
+                     });
         }
     }
 }
@@ -651,7 +668,7 @@
             continue;
         }
         const std::string message = "addOperationInputTest: operation " + std::to_string(operation);
-        validate(device, message, model, [operation](Model* model) {
+        validate(device, message, model, [operation](Model* model, ExecutionPreference*) {
             uint32_t index = addOperand(model, OperandLifeTime::MODEL_INPUT);
             hidl_vec_push_back(&model->operations[operation].inputs, index);
             hidl_vec_push_back(&model->inputIndexes, index);
@@ -665,7 +682,7 @@
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         const std::string message =
                 "addOperationOutputTest: operation " + std::to_string(operation);
-        validate(device, message, model, [operation](Model* model) {
+        validate(device, message, model, [operation](Model* model, ExecutionPreference*) {
             uint32_t index = addOperand(model, OperandLifeTime::MODEL_OUTPUT);
             hidl_vec_push_back(&model->operations[operation].outputs, index);
             hidl_vec_push_back(&model->outputIndexes, index);
@@ -681,12 +698,13 @@
 };
 
 static void mutateExecutionPreferenceTest(const sp<IDevice>& device, const Model& model) {
-    for (int32_t preference : invalidExecutionPreferences) {
+    for (int32_t invalidPreference : invalidExecutionPreferences) {
         const std::string message =
-                "mutateExecutionPreferenceTest: preference " + std::to_string(preference);
-        validate(
-                device, message, model, [](Model*) {},
-                static_cast<ExecutionPreference>(preference));
+                "mutateExecutionPreferenceTest: preference " + std::to_string(invalidPreference);
+        validate(device, message, model,
+                 [invalidPreference](Model*, ExecutionPreference* preference) {
+                     *preference = static_cast<ExecutionPreference>(invalidPreference);
+                 });
     }
 }
 
diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
index 7b5ff9b..934d893 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
@@ -22,7 +22,6 @@
 #include "ExecutionBurstController.h"
 #include "GeneratedTestHarness.h"
 #include "TestHarness.h"
-#include "Utils.h"
 #include "VtsHalNeuralnetworks.h"
 
 namespace android::hardware::neuralnetworks::V1_2::vts::functional {
@@ -31,6 +30,8 @@
 using V1_0::ErrorStatus;
 using V1_0::Request;
 
+using ExecutionMutation = std::function<void(Request*)>;
+
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
 static bool badTiming(Timing timing) {
@@ -39,11 +40,11 @@
 
 // Primary validation function. This function will take a valid request, apply a
 // mutation to it to invalidate the request, then pass it to interface calls
-// that use the request. Note that the request here is passed by value, and any
-// mutation to the request does not leave this function.
+// that use the request.
 static void validate(const sp<IPreparedModel>& preparedModel, const std::string& message,
-                     Request request, const std::function<void(Request*)>& mutation) {
-    mutation(&request);
+                     const Request& originalRequest, const ExecutionMutation& mutate) {
+    Request request = originalRequest;
+    mutate(&request);
 
     // We'd like to test both with timing requested and without timing
     // requested. Rather than running each test both ways, we'll decide whether
@@ -107,7 +108,7 @@
 
         // execute and verify
         const auto [n, outputShapes, timing, fallback] = burst->compute(request, measure, keys);
-        const ErrorStatus status = nn::convertToV1_0(nn::convertResultCodeToErrorStatus(n));
+        const ErrorStatus status = nn::legacyConvertResultCodeToErrorStatus(n);
         EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
         EXPECT_EQ(outputShapes.size(), 0);
         EXPECT_TRUE(badTiming(timing));
diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp
index 4fbd0e2..a60ec4d 100644
--- a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp
@@ -153,7 +153,8 @@
 
 TEST_P(ValidationTest, Test) {
     const Model model = createModel(kTestModel);
-    const Request request = createRequest(kTestModel);
+    ExecutionContext context;
+    const Request request = context.createRequest(kTestModel);
     if (kTestModel.expectFailure) {
         validateFailure(kDevice, model, request);
     } else {
@@ -161,7 +162,12 @@
     }
 }
 
-INSTANTIATE_GENERATED_TEST(ValidationTest, [](const test_helper::TestModel&) { return true; });
+INSTANTIATE_GENERATED_TEST(ValidationTest, [](const std::string& testName) {
+    // Skip validation for the "inputs_as_internal" and "all_tensors_as_inputs"
+    // generated tests.
+    return testName.find("inputs_as_internal") == std::string::npos &&
+           testName.find("all_tensors_as_inputs") == std::string::npos;
+});
 
 sp<IPreparedModel> getPreparedModel_1_2(const sp<implementation::PreparedModelCallback>& callback) {
     sp<V1_0::IPreparedModel> preparedModelV1_0 = callback->getPreparedModel();
diff --git a/neuralnetworks/1.3/types.hal b/neuralnetworks/1.3/types.hal
index daaf22e..56930c2 100644
--- a/neuralnetworks/1.3/types.hal
+++ b/neuralnetworks/1.3/types.hal
@@ -833,7 +833,7 @@
     HASHTABLE_LOOKUP = @1.2::OperationType:HASHTABLE_LOOKUP,
 
     /**
-     * Applies L2 normalization along the depth dimension.
+     * Applies L2 normalization along the axis dimension.
      *
      * The values in the output tensor are computed as:
      *
@@ -841,8 +841,7 @@
      *         input[batch, row, col, channel] /
      *         sqrt(sum_{c} pow(input[batch, row, col, c], 2))
      *
-     * For input tensor with rank less than 4, independently normalizes each
-     * 1-D slice along dimension dim.
+     * By default the axis dimension is the last dimension of the input tensor.
      *
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
@@ -867,6 +866,10 @@
      *      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.
+     *
+     *      NOTE: Before HAL version 1.3, if the elements along an axis are all zeros,
+     *      the result is undefined. Since HAL version 1.3, if the elements along an axis
+     *      are all zeros, the result is logical zero.
      */
     L2_NORMALIZATION = @1.2::OperationType:L2_NORMALIZATION,
 
@@ -4063,7 +4066,8 @@
      * * 1: A scalar {@link OperandType::INT32}, specifying the number of
      *      independent samples to draw for each row slice.
      * * 2: A 1-D {@link OperandType::TENSOR_INT32} tensor with shape [2],
-     *      specifying seeds used to initialize the random distribution.
+     *      specifying seeds used to initialize the random distribution. If both
+     *      provided seeds are 0, both will be randomly generated.
      * Outputs:
      * * 0: A 2-D {@link OperandType::TENSOR_INT32} tensor with shape
      *      [batches, samples], containing the drawn samples.
@@ -5168,6 +5172,8 @@
      * * {@link OperandType::TENSOR_FLOAT16}
      * * {@link OperandType::TENSOR_FLOAT32}
      *
+     * Supported tensor rank: from 1.
+     *
      * Inputs:
      * * 0: A tensor, specifying the input. May be zero-sized.
      * * 1: A scalar, specifying the alpha parameter.
@@ -5197,6 +5203,8 @@
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED}
      *
+     * Supported tensor rank: from 1.
+     *
      * Inputs:
      * * 0: A tensor, specifying the input. May be zero-sized.
      *
@@ -5215,6 +5223,8 @@
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_INT32}
      *
+     * Supported tensor rank: from 1.
+     *
      * Inputs:
      * * 0: A 1-D tensor, specifying the desired output tensor shape.
      * * 1: A scalar, specifying the value to fill the output tensors with.
@@ -5248,6 +5258,8 @@
      * * {@link OperandType::TENSOR_QUANT8_SYMM}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED}
      *
+     * Supported tensor rank: from 1.
+     *
      * Inputs:
      * * 0: The input tensor.
      *
diff --git a/neuralnetworks/1.3/vts/functional/Android.bp b/neuralnetworks/1.3/vts/functional/Android.bp
index f936267..545a5be 100644
--- a/neuralnetworks/1.3/vts/functional/Android.bp
+++ b/neuralnetworks/1.3/vts/functional/Android.bp
@@ -40,6 +40,7 @@
         "BasicTests.cpp",
         "CompilationCachingTests.cpp",
         "GeneratedTestHarness.cpp",
+        "MemoryDomainTests.cpp",
         "QualityOfServiceTests.cpp",
         "TestAssertions.cpp",
         "ValidateBurst.cpp",
diff --git a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
index 83a8d94..4dbac16 100644
--- a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
@@ -72,21 +72,10 @@
 
 namespace {
 
-enum class Executor { ASYNC, SYNC, BURST, FENCED };
-
 enum class OutputType { FULLY_SPECIFIED, UNSPECIFIED, INSUFFICIENT, MISSED_DEADLINE };
 
-enum class MemoryType { SHARED, DEVICE };
-
 enum class IOType { INPUT, OUTPUT };
 
-static void waitForSyncFence(int syncFd) {
-    constexpr int kInfiniteTimeout = -1;
-    ASSERT_GT(syncFd, 0);
-    int r = sync_wait(syncFd, kInfiniteTimeout);
-    ASSERT_GE(r, 0);
-}
-
 struct TestConfig {
     Executor executor;
     MeasureTiming measureTiming;
@@ -277,6 +266,13 @@
 
 }  // namespace
 
+void waitForSyncFence(int syncFd) {
+    constexpr int kInfiniteTimeout = -1;
+    ASSERT_GT(syncFd, 0);
+    int r = sync_wait(syncFd, kInfiniteTimeout);
+    ASSERT_GE(r, 0);
+}
+
 Model createModel(const TestModel& testModel) {
     uint32_t constCopySize = 0;
     uint32_t constRefSize = 0;
@@ -338,21 +334,39 @@
     }
 }
 
-constexpr uint32_t kInputPoolIndex = 0;
-constexpr uint32_t kOutputPoolIndex = 1;
-constexpr uint32_t kDeviceMemoryBeginIndex = 2;
+class ExecutionContextV1_3 {
+  public:
+    ExecutionContextV1_3(sp<IDevice> device, sp<IPreparedModel> preparedModel)
+        : kDevice(std::move(device)), kPreparedModel(std::move(preparedModel)) {}
 
-static std::pair<Request, std::vector<sp<IBuffer>>> createRequest(
-        const sp<IDevice>& device, const sp<IPreparedModel>& preparedModel,
-        const TestModel& testModel, bool preferDeviceMemory) {
+    std::optional<Request> createRequest(const TestModel& testModel, MemoryType memoryType);
+    std::vector<TestBuffer> getOutputBuffers(const TestModel& testModel,
+                                             const Request& request) const;
+
+  private:
+    // Get a TestBuffer with data copied from an IBuffer object.
+    void getBuffer(const sp<IBuffer>& buffer, size_t size, TestBuffer* testBuffer) const;
+
+    static constexpr uint32_t kInputPoolIndex = 0;
+    static constexpr uint32_t kOutputPoolIndex = 1;
+    static constexpr uint32_t kDeviceMemoryBeginIndex = 2;
+
+    const sp<IDevice> kDevice;
+    const sp<IPreparedModel> kPreparedModel;
+    std::unique_ptr<TestMemoryBase> mInputMemory, mOutputMemory;
+    std::vector<sp<IBuffer>> mBuffers;
+};
+
+std::optional<Request> ExecutionContextV1_3::createRequest(const TestModel& testModel,
+                                                           MemoryType memoryType) {
     // Memory pools are organized as:
     // - 0: Input shared memory pool
     // - 1: Output shared memory pool
     // - [2, 2+i): Input device memories
     // - [2+i, 2+i+o): Output device memories
-    DeviceMemoryAllocator allocator(device, preparedModel, testModel);
-    std::vector<sp<IBuffer>> buffers;
+    DeviceMemoryAllocator allocator(kDevice, kPreparedModel, testModel);
     std::vector<uint32_t> tokens;
+    mBuffers.clear();
 
     // Model inputs.
     hidl_vec<RequestArgument> inputs(testModel.main.inputIndexes.size());
@@ -363,13 +377,13 @@
             // Omitted input.
             inputs[i] = {.hasNoValue = true};
             continue;
-        } else if (preferDeviceMemory) {
+        } else if (memoryType == MemoryType::DEVICE) {
             SCOPED_TRACE("Input index = " + std::to_string(i));
             auto [buffer, token] = allocator.allocate<IOType::INPUT>(i);
             if (buffer != nullptr) {
-                DataLocation loc = {.poolIndex = static_cast<uint32_t>(buffers.size() +
+                DataLocation loc = {.poolIndex = static_cast<uint32_t>(mBuffers.size() +
                                                                        kDeviceMemoryBeginIndex)};
-                buffers.push_back(std::move(buffer));
+                mBuffers.push_back(std::move(buffer));
                 tokens.push_back(token);
                 inputs[i] = {.hasNoValue = false, .location = loc, .dimensions = {}};
                 continue;
@@ -389,13 +403,13 @@
     size_t outputSize = 0;
     for (uint32_t i = 0; i < testModel.main.outputIndexes.size(); i++) {
         const auto& op = testModel.main.operands[testModel.main.outputIndexes[i]];
-        if (preferDeviceMemory) {
+        if (memoryType == MemoryType::DEVICE) {
             SCOPED_TRACE("Output index = " + std::to_string(i));
             auto [buffer, token] = allocator.allocate<IOType::OUTPUT>(i);
             if (buffer != nullptr) {
-                DataLocation loc = {.poolIndex = static_cast<uint32_t>(buffers.size() +
+                DataLocation loc = {.poolIndex = static_cast<uint32_t>(mBuffers.size() +
                                                                        kDeviceMemoryBeginIndex)};
-                buffers.push_back(std::move(buffer));
+                mBuffers.push_back(std::move(buffer));
                 tokens.push_back(token);
                 outputs[i] = {.hasNoValue = false, .location = loc, .dimensions = {}};
                 continue;
@@ -418,21 +432,29 @@
         outputs[i] = {.hasNoValue = false, .location = loc, .dimensions = {}};
     }
 
+    if (memoryType == MemoryType::DEVICE && mBuffers.empty()) {
+        return std::nullopt;
+    }
+
     // Memory pools.
-    hidl_vec<Request::MemoryPool> pools(kDeviceMemoryBeginIndex + buffers.size());
-    pools[kInputPoolIndex].hidlMemory(nn::allocateSharedMemory(std::max<size_t>(inputSize, 1)));
-    pools[kOutputPoolIndex].hidlMemory(nn::allocateSharedMemory(std::max<size_t>(outputSize, 1)));
-    CHECK_NE(pools[kInputPoolIndex].hidlMemory().size(), 0u);
-    CHECK_NE(pools[kOutputPoolIndex].hidlMemory().size(), 0u);
-    for (uint32_t i = 0; i < buffers.size(); i++) {
+    hidl_vec<Request::MemoryPool> pools(kDeviceMemoryBeginIndex + mBuffers.size());
+    if (memoryType == MemoryType::BLOB_AHWB) {
+        mInputMemory = TestBlobAHWB::create(std::max<size_t>(inputSize, 1));
+        mOutputMemory = TestBlobAHWB::create(std::max<size_t>(outputSize, 1));
+    } else {
+        mInputMemory = TestAshmem::create(std::max<size_t>(inputSize, 1));
+        mOutputMemory = TestAshmem::create(std::max<size_t>(outputSize, 1));
+    }
+    EXPECT_NE(mInputMemory, nullptr);
+    EXPECT_NE(mOutputMemory, nullptr);
+    pools[kInputPoolIndex].hidlMemory(mInputMemory->getHidlMemory());
+    pools[kOutputPoolIndex].hidlMemory(mOutputMemory->getHidlMemory());
+    for (uint32_t i = 0; i < mBuffers.size(); i++) {
         pools[kDeviceMemoryBeginIndex + i].token(tokens[i]);
     }
 
     // Copy input data to the input shared memory pool.
-    sp<IMemory> inputMemory = mapMemory(pools[kInputPoolIndex].hidlMemory());
-    CHECK(inputMemory.get() != nullptr);
-    uint8_t* inputPtr = static_cast<uint8_t*>(static_cast<void*>(inputMemory->getPointer()));
-    CHECK(inputPtr != nullptr);
+    uint8_t* inputPtr = mInputMemory->getPointer();
     for (uint32_t i = 0; i < testModel.main.inputIndexes.size(); i++) {
         if (!inputs[i].hasNoValue && inputs[i].location.poolIndex == kInputPoolIndex) {
             const auto& op = testModel.main.operands[testModel.main.inputIndexes[i]];
@@ -441,14 +463,38 @@
             std::copy(begin, end, inputPtr + inputs[i].location.offset);
         }
     }
-
-    Request request = {
+    return Request{
             .inputs = std::move(inputs), .outputs = std::move(outputs), .pools = std::move(pools)};
-    return {std::move(request), std::move(buffers)};
+}
+
+std::vector<TestBuffer> ExecutionContextV1_3::getOutputBuffers(const TestModel& testModel,
+                                                               const Request& request) const {
+    // Copy out output results.
+    uint8_t* outputPtr = mOutputMemory->getPointer();
+    std::vector<TestBuffer> outputBuffers;
+    for (uint32_t i = 0; i < request.outputs.size(); i++) {
+        const auto& outputLoc = request.outputs[i].location;
+        if (outputLoc.poolIndex == kOutputPoolIndex) {
+            outputBuffers.emplace_back(outputLoc.length, outputPtr + outputLoc.offset);
+        } else {
+            const auto& op = testModel.main.operands[testModel.main.outputIndexes[i]];
+            if (op.data.size() == 0) {
+                outputBuffers.emplace_back(0, nullptr);
+            } else {
+                SCOPED_TRACE("Output index = " + std::to_string(i));
+                const uint32_t bufferIndex = outputLoc.poolIndex - kDeviceMemoryBeginIndex;
+                TestBuffer buffer;
+                getBuffer(mBuffers[bufferIndex], op.data.size(), &buffer);
+                outputBuffers.push_back(std::move(buffer));
+            }
+        }
+    }
+    return outputBuffers;
 }
 
 // Get a TestBuffer with data copied from an IBuffer object.
-static void getBuffer(const sp<IBuffer>& buffer, size_t size, TestBuffer* testBuffer) {
+void ExecutionContextV1_3::getBuffer(const sp<IBuffer>& buffer, size_t size,
+                                     TestBuffer* testBuffer) const {
     // IBuffer -> Shared memory.
     hidl_memory tmp = nn::allocateSharedMemory(size);
     const auto ret = buffer->copyTo(tmp);
@@ -464,33 +510,11 @@
     *testBuffer = TestBuffer(size, outputPtr);
 }
 
-static std::vector<TestBuffer> getOutputBuffers(const TestModel& testModel, const Request& request,
-                                                const std::vector<sp<IBuffer>>& buffers) {
-    sp<IMemory> outputMemory = mapMemory(request.pools[kOutputPoolIndex].hidlMemory());
-    CHECK(outputMemory.get() != nullptr);
-    uint8_t* outputPtr = static_cast<uint8_t*>(static_cast<void*>(outputMemory->getPointer()));
-    CHECK(outputPtr != nullptr);
-
-    // Copy out output results.
-    std::vector<TestBuffer> outputBuffers;
-    for (uint32_t i = 0; i < request.outputs.size(); i++) {
-        const auto& outputLoc = request.outputs[i].location;
-        if (outputLoc.poolIndex == kOutputPoolIndex) {
-            outputBuffers.emplace_back(outputLoc.length, outputPtr + outputLoc.offset);
-        } else {
-            const auto& op = testModel.main.operands[testModel.main.outputIndexes[i]];
-            if (op.data.size() == 0) {
-                outputBuffers.emplace_back();
-            } else {
-                SCOPED_TRACE("Output index = " + std::to_string(i));
-                const uint32_t bufferIndex = outputLoc.poolIndex - kDeviceMemoryBeginIndex;
-                TestBuffer buffer;
-                getBuffer(buffers[bufferIndex], op.data.size(), &buffer);
-                outputBuffers.push_back(std::move(buffer));
-            }
-        }
-    }
-    return outputBuffers;
+static bool hasZeroSizedOutput(const TestModel& testModel) {
+    return std::any_of(testModel.main.outputIndexes.begin(), testModel.main.outputIndexes.end(),
+                       [&testModel](uint32_t index) {
+                           return testModel.main.operands[index].data.size() == 0;
+                       });
 }
 
 static Return<ErrorStatus> ExecutePreparedModel(const sp<IPreparedModel>& preparedModel,
@@ -536,13 +560,14 @@
         return;
     }
 
-    auto [request, buffers] =
-            createRequest(device, preparedModel, testModel,
-                          /*preferDeviceMemory=*/testConfig.memoryType == MemoryType::DEVICE);
+    ExecutionContextV1_3 context(device, preparedModel);
+    auto maybeRequest = context.createRequest(testModel, testConfig.memoryType);
     // Skip if testing memory domain but no device memory has been allocated.
-    if (testConfig.memoryType == MemoryType::DEVICE && buffers.empty()) {
+    if (!maybeRequest.has_value()) {
         return;
     }
+
+    Request request = std::move(maybeRequest.value());
     if (testConfig.outputType == OutputType::INSUFFICIENT) {
         makeOutputInsufficientSize(/*outputIndex=*/0, &request);
     }
@@ -641,6 +666,7 @@
                 ASSERT_EQ(syncFenceHandle.getNativeHandle(), nullptr);
                 ASSERT_EQ(fencedCallback, nullptr);
                 executionStatus = result;
+                timing = {UINT64_MAX, UINT64_MAX};
             } else if (syncFenceHandle.getNativeHandle()) {
                 // If a sync fence is returned, try start another run waiting for the sync fence.
                 ret = preparedModel->executeFenced(request, {syncFenceHandle},
@@ -689,6 +715,11 @@
 
     switch (testConfig.outputType) {
         case OutputType::FULLY_SPECIFIED:
+            if (testConfig.executor == Executor::FENCED && hasZeroSizedOutput(testModel)) {
+                // Executor::FENCED does not support zero-sized output.
+                ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionStatus);
+                return;
+            }
             // 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.
             ASSERT_EQ(ErrorStatus::NONE, executionStatus);
@@ -732,7 +763,7 @@
     }
 
     // Retrieve execution results.
-    const std::vector<TestBuffer> outputs = getOutputBuffers(testModel, request, buffers);
+    const std::vector<TestBuffer> outputs = context.getOutputBuffers(testModel, request);
 
     // We want "close-enough" results.
     checkResults(testModel, outputs);
@@ -743,29 +774,32 @@
     std::vector<OutputType> outputTypesList;
     std::vector<MeasureTiming> measureTimingList;
     std::vector<Executor> executorList;
-    MemoryType memoryType = MemoryType::SHARED;
+    std::vector<MemoryType> memoryTypeList;
 
     switch (testKind) {
         case TestKind::GENERAL: {
             outputTypesList = {OutputType::FULLY_SPECIFIED};
             measureTimingList = {MeasureTiming::NO, MeasureTiming::YES};
             executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST};
+            memoryTypeList = {MemoryType::ASHMEM};
         } break;
         case TestKind::DYNAMIC_SHAPE: {
             outputTypesList = {OutputType::UNSPECIFIED, OutputType::INSUFFICIENT};
             measureTimingList = {MeasureTiming::NO, MeasureTiming::YES};
             executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST, Executor::FENCED};
+            memoryTypeList = {MemoryType::ASHMEM};
         } break;
         case TestKind::MEMORY_DOMAIN: {
             outputTypesList = {OutputType::FULLY_SPECIFIED};
             measureTimingList = {MeasureTiming::NO};
             executorList = {Executor::ASYNC, Executor::SYNC, Executor::FENCED};
-            memoryType = MemoryType::DEVICE;
+            memoryTypeList = {MemoryType::BLOB_AHWB, MemoryType::DEVICE};
         } break;
         case TestKind::FENCED_COMPUTE: {
             outputTypesList = {OutputType::FULLY_SPECIFIED};
             measureTimingList = {MeasureTiming::NO, MeasureTiming::YES};
             executorList = {Executor::FENCED};
+            memoryTypeList = {MemoryType::ASHMEM};
         } break;
         case TestKind::QUANTIZATION_COUPLING: {
             LOG(FATAL) << "Wrong TestKind for EvaluatePreparedModel";
@@ -776,14 +810,17 @@
             measureTimingList = {MeasureTiming::NO, MeasureTiming::YES};
             // Burst does not support V1_3 loop timeout.
             executorList = {Executor::ASYNC, Executor::SYNC, Executor::FENCED};
+            memoryTypeList = {MemoryType::ASHMEM};
         } break;
     }
 
     for (const OutputType outputType : outputTypesList) {
         for (const MeasureTiming measureTiming : measureTimingList) {
             for (const Executor executor : executorList) {
-                const TestConfig testConfig(executor, measureTiming, outputType, memoryType);
-                EvaluatePreparedModel(device, preparedModel, testModel, testConfig);
+                for (const MemoryType memoryType : memoryTypeList) {
+                    const TestConfig testConfig(executor, measureTiming, outputType, memoryType);
+                    EvaluatePreparedModel(device, preparedModel, testModel, testConfig);
+                }
             }
         }
     }
@@ -802,7 +839,7 @@
     for (const OutputType outputType : outputTypesList) {
         for (const MeasureTiming measureTiming : measureTimingList) {
             for (const Executor executor : executorList) {
-                const TestConfig testConfig(executor, measureTiming, outputType, MemoryType::SHARED,
+                const TestConfig testConfig(executor, measureTiming, outputType, MemoryType::ASHMEM,
                                             /*reportSkipping=*/false);
                 bool baseSkipped = false;
                 EvaluatePreparedModel(device, preparedModel, testModel, testConfig, &baseSkipped);
@@ -879,6 +916,10 @@
     return TestModelManager::get().getTestModels(filter);
 }
 
+std::vector<NamedModel> getNamedModels(const FilterNameFn& filter) {
+    return TestModelManager::get().getTestModels(filter);
+}
+
 std::string printGeneratedTest(const testing::TestParamInfo<GeneratedTestParam>& info) {
     const auto& [namedDevice, namedModel] = info.param;
     return gtestCompliantName(getName(namedDevice) + "_" + getName(namedModel));
@@ -936,16 +977,12 @@
 INSTANTIATE_GENERATED_TEST(MemoryDomainTest,
                            [](const TestModel& testModel) { return !testModel.expectFailure; });
 
-INSTANTIATE_GENERATED_TEST(FencedComputeTest, [](const TestModel& testModel) {
-    return !testModel.expectFailure &&
-           std::all_of(testModel.main.outputIndexes.begin(), testModel.main.outputIndexes.end(),
-                       [&testModel](uint32_t index) {
-                           return testModel.main.operands[index].data.size() > 0;
-                       });
-});
+INSTANTIATE_GENERATED_TEST(FencedComputeTest,
+                           [](const TestModel& testModel) { return !testModel.expectFailure; });
 
 INSTANTIATE_GENERATED_TEST(QuantizationCouplingTest, [](const TestModel& testModel) {
-    return testModel.hasQuant8CoupledOperands() && testModel.main.operations.size() == 1;
+    return !testModel.expectFailure && testModel.hasQuant8CoupledOperands() &&
+           testModel.main.operations.size() == 1;
 });
 
 INSTANTIATE_GENERATED_TEST(InfiniteLoopTimeoutTest, [](const TestModel& testModel) {
diff --git a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h
index 834d335..4f05c48 100644
--- a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h
+++ b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h
@@ -41,6 +41,9 @@
 using FilterFn = std::function<bool(const test_helper::TestModel&)>;
 std::vector<NamedModel> getNamedModels(const FilterFn& filter);
 
+using FilterNameFn = std::function<bool(const std::string&)>;
+std::vector<NamedModel> getNamedModels(const FilterNameFn& filter);
+
 std::string printGeneratedTest(const testing::TestParamInfo<GeneratedTestParam>& info);
 
 #define INSTANTIATE_GENERATED_TEST(TestSuite, filter)                                     \
@@ -77,6 +80,8 @@
 void EvaluatePreparedModel(const sp<IDevice>& device, const sp<IPreparedModel>& preparedModel,
                            const test_helper::TestModel& testModel, TestKind testKind);
 
+void waitForSyncFence(int syncFd);
+
 }  // namespace android::hardware::neuralnetworks::V1_3::vts::functional
 
 #endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_3_GENERATED_TEST_HARNESS_H
diff --git a/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp b/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp
new file mode 100644
index 0000000..3c0c885
--- /dev/null
+++ b/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp
@@ -0,0 +1,1203 @@
+/*
+ * Copyright (C) 2020 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 "neuralnetworks_hidl_hal_test"
+
+#include <android-base/logging.h>
+#include <gtest/gtest.h>
+
+#include "1.3/Callbacks.h"
+#include "1.3/Utils.h"
+#include "GeneratedTestHarness.h"
+#include "MemoryUtils.h"
+#include "TestHarness.h"
+#include "Utils.h"
+#include "VtsHalNeuralnetworks.h"
+
+namespace android::hardware::neuralnetworks::V1_3::vts::functional {
+
+using namespace test_helper;
+using implementation::ExecutionCallback;
+using implementation::PreparedModelCallback;
+using V1_0::RequestArgument;
+using V1_1::ExecutionPreference;
+using V1_2::Constant;
+using V1_2::MeasureTiming;
+using V1_2::OutputShape;
+using V1_2::Timing;
+
+namespace {
+
+const auto kNamedDeviceChoices = testing::ValuesIn(getNamedDevices());
+
+// A 1.3 driver is likely to support at least one of the following operand types.
+const std::vector<TestOperandType> kTestOperandTypeChoicesVector = {
+        TestOperandType::TENSOR_FLOAT32,
+        TestOperandType::TENSOR_FLOAT16,
+        TestOperandType::TENSOR_QUANT8_ASYMM,
+        TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED,
+};
+const auto kTestOperandTypeChoices = testing::ValuesIn(kTestOperandTypeChoicesVector);
+
+bool isInChoices(TestOperandType type) {
+    return std::count(kTestOperandTypeChoicesVector.begin(), kTestOperandTypeChoicesVector.end(),
+                      type) > 0;
+}
+
+bool isFloat(TestOperandType type) {
+    CHECK(isInChoices(type));
+    return type == TestOperandType::TENSOR_FLOAT32 || type == TestOperandType::TENSOR_FLOAT16;
+}
+
+// Create dummy buffers for model constants as well as inputs and outputs.
+// We only care about the size here because we will not check accuracy in validation tests.
+void createDummyData(TestModel* testModel) {
+    for (auto& operand : testModel->main.operands) {
+        if (operand.data != nullptr) continue;
+        switch (operand.lifetime) {
+            case TestOperandLifeTime::SUBGRAPH_INPUT:
+            case TestOperandLifeTime::SUBGRAPH_OUTPUT:
+            case TestOperandLifeTime::CONSTANT_COPY:
+            case TestOperandLifeTime::CONSTANT_REFERENCE: {
+                const uint32_t size = nn::nonExtensionOperandSizeOfData(
+                        static_cast<OperandType>(operand.type), operand.dimensions);
+                operand.data = TestBuffer(size);
+            } break;
+            default:
+                break;
+        }
+    }
+}
+
+TestOperand createInt32Scalar(int32_t value) {
+    return {
+            .type = TestOperandType::INT32,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = TestOperandLifeTime::CONSTANT_COPY,
+            .data = TestBuffer::createFromVector<int32_t>({value}),
+    };
+}
+
+// Construct a test model with multiple CONV_2D operations with the given operand as inputs.
+// The dimensions of the filters are chosen to ensure outputs has the same dimensions as inputs.
+// We choose CONV_2D operation because it is commonly supported by most drivers.
+TestModel createConvModel(const TestOperand& operand, uint32_t numOperations) {
+    CHECK(isInChoices(operand.type));
+
+    TestOperand weight = {.type = operand.type,
+                          .dimensions = {operand.dimensions[3], 3, 3, operand.dimensions[3]},
+                          .numberOfConsumers = 1,
+                          .scale = isFloat(operand.type) ? 0.0f : 1.0f,
+                          .zeroPoint = 0,
+                          .lifetime = TestOperandLifeTime::CONSTANT_COPY};
+
+    TestOperand bias = {
+            .type = isFloat(operand.type) ? operand.type : TestOperandType::TENSOR_INT32,
+            .dimensions = {operand.dimensions[3]},
+            .numberOfConsumers = 1,
+            .scale = operand.scale * weight.scale,
+            .zeroPoint = 0,
+            .lifetime = TestOperandLifeTime::CONSTANT_COPY};
+
+    TestOperand output = operand;
+    output.numberOfConsumers = 0;
+    output.lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT;
+
+    const std::vector<TestOperand> operands = {
+            operand,
+            std::move(weight),
+            std::move(bias),
+            createInt32Scalar(1),  // same padding
+            createInt32Scalar(1),  // width stride
+            createInt32Scalar(1),  // height stride
+            createInt32Scalar(0),  // activation = NONE
+            std::move(output),
+    };
+
+    TestModel model;
+    for (uint32_t i = 0; i < numOperations; i++) {
+        model.main.operands.insert(model.main.operands.end(), operands.begin(), operands.end());
+        const uint32_t inputIndex = operands.size() * i;
+        const uint32_t outputIndex = inputIndex + operands.size() - 1;
+        std::vector<uint32_t> inputs(operands.size() - 1);
+        std::iota(inputs.begin(), inputs.end(), inputIndex);
+        model.main.operations.push_back({.type = TestOperationType::CONV_2D,
+                                         .inputs = std::move(inputs),
+                                         .outputs = {outputIndex}});
+        model.main.inputIndexes.push_back(inputIndex);
+        model.main.outputIndexes.push_back(outputIndex);
+    }
+    createDummyData(&model);
+    return model;
+}
+
+// Construct a test model with a single ADD operation with the given operand as input0 and input1.
+// This is to cover additional cases that the CONV_2D model does not support, e.g. arbitrary input
+// operand rank, scalar input operand. We choose ADD operation because it is commonly supported by
+// most drivers.
+TestModel createSingleAddModel(const TestOperand& operand) {
+    CHECK(isInChoices(operand.type));
+
+    TestOperand act = {
+            .type = TestOperandType::INT32,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT,
+    };
+
+    TestOperand output = operand;
+    output.numberOfConsumers = 0;
+    output.lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT;
+
+    TestModel model = {
+            .main =
+                    {
+                            .operands =
+                                    {
+                                            operand,
+                                            operand,
+                                            std::move(act),
+                                            output,
+                                    },
+                            .operations = {{.type = TestOperationType::ADD,
+                                            .inputs = {0, 1, 2},
+                                            .outputs = {3}}},
+                            .inputIndexes = {0, 1, 2},
+                            .outputIndexes = {3},
+                    },
+    };
+    createDummyData(&model);
+    return model;
+}
+
+// A dummy invalid IPreparedModel class for MemoryDomainAllocateTest.InvalidPreparedModel
+class InvalidPreparedModel : public IPreparedModel {
+  public:
+    Return<V1_0::ErrorStatus> execute(const V1_0::Request&,
+                                      const sp<V1_0::IExecutionCallback>&) override {
+        return V1_0::ErrorStatus::GENERAL_FAILURE;
+    }
+    Return<V1_0::ErrorStatus> execute_1_2(const V1_0::Request&, V1_2::MeasureTiming,
+                                          const sp<V1_2::IExecutionCallback>&) override {
+        return V1_0::ErrorStatus::GENERAL_FAILURE;
+    }
+    Return<V1_3::ErrorStatus> execute_1_3(const V1_3::Request&, V1_2::MeasureTiming,
+                                          const V1_3::OptionalTimePoint&,
+                                          const V1_3::OptionalTimeoutDuration&,
+                                          const sp<V1_3::IExecutionCallback>&) override {
+        return V1_3::ErrorStatus::GENERAL_FAILURE;
+    }
+    Return<void> executeSynchronously(const V1_0::Request&, V1_2::MeasureTiming,
+                                      executeSynchronously_cb) override {
+        return Void();
+    }
+    Return<void> executeSynchronously_1_3(const V1_3::Request&, V1_2::MeasureTiming,
+                                          const V1_3::OptionalTimePoint&,
+                                          const V1_3::OptionalTimeoutDuration&,
+                                          executeSynchronously_1_3_cb) override {
+        return Void();
+    }
+    Return<void> configureExecutionBurst(const sp<V1_2::IBurstCallback>&,
+                                         const MQDescriptorSync<V1_2::FmqRequestDatum>&,
+                                         const MQDescriptorSync<V1_2::FmqResultDatum>&,
+                                         configureExecutionBurst_cb) override {
+        return Void();
+    }
+    Return<void> executeFenced(const V1_3::Request&, const hidl_vec<hidl_handle>&,
+                               V1_2::MeasureTiming, const V1_3::OptionalTimePoint&,
+                               const V1_3::OptionalTimeoutDuration&,
+                               const V1_3::OptionalTimeoutDuration&, executeFenced_cb) override {
+        return Void();
+    }
+};
+
+}  // namespace
+
+class MemoryDomainTestBase : public testing::Test {
+  protected:
+    MemoryDomainTestBase(sp<IDevice> device, TestOperandType type)
+        : kDevice(std::move(device)),
+          kTestOperandType(type),
+          kTestOperand(kTestOperandMap.at(type)),
+          kTestOperandDataSize(nn::nonExtensionOperandSizeOfData(static_cast<OperandType>(type),
+                                                                 kTestOperand.dimensions)) {}
+
+    void SetUp() override {
+        testing::Test::SetUp();
+        ASSERT_NE(kDevice, nullptr);
+    }
+
+    sp<IPreparedModel> createConvPreparedModel(const TestOperand& testOperand,
+                                               uint32_t numOperations = 1) {
+        const TestModel testModel = createConvModel(testOperand, numOperations);
+        const Model model = createModel(testModel);
+        sp<IPreparedModel> preparedModel;
+        createPreparedModel(kDevice, model, &preparedModel, /*reportSkipping=*/false);
+        return preparedModel;
+    }
+
+    sp<IPreparedModel> createAddPreparedModel(const TestOperand& testOperand) {
+        const TestModel testModel = createSingleAddModel(testOperand);
+        const Model model = createModel(testModel);
+        sp<IPreparedModel> preparedModel;
+        createPreparedModel(kDevice, model, &preparedModel, /*reportSkipping=*/false);
+        return preparedModel;
+    }
+
+    static const std::map<TestOperandType, TestOperand> kTestOperandMap;
+
+    const sp<IDevice> kDevice;
+    const TestOperandType kTestOperandType;
+    const TestOperand& kTestOperand;
+    const uint32_t kTestOperandDataSize;
+};
+
+const std::map<TestOperandType, TestOperand> MemoryDomainTestBase::kTestOperandMap = {
+        {TestOperandType::TENSOR_FLOAT32,
+         {
+                 .type = TestOperandType::TENSOR_FLOAT32,
+                 .dimensions = {1, 32, 32, 8},
+                 .numberOfConsumers = 1,
+                 .scale = 0.0f,
+                 .zeroPoint = 0,
+                 .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT,
+         }},
+        {TestOperandType::TENSOR_FLOAT16,
+         {
+                 .type = TestOperandType::TENSOR_FLOAT16,
+                 .dimensions = {1, 32, 32, 8},
+                 .numberOfConsumers = 1,
+                 .scale = 0.0f,
+                 .zeroPoint = 0,
+                 .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT,
+         }},
+        {TestOperandType::TENSOR_QUANT8_ASYMM,
+         {
+                 .type = TestOperandType::TENSOR_QUANT8_ASYMM,
+                 .dimensions = {1, 32, 32, 8},
+                 .numberOfConsumers = 1,
+                 .scale = 0.5f,
+                 .zeroPoint = 0,
+                 .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT,
+         }},
+        {TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED,
+         {
+                 .type = TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED,
+                 .dimensions = {1, 32, 32, 8},
+                 .numberOfConsumers = 1,
+                 .scale = 0.5f,
+                 .zeroPoint = 0,
+                 .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT,
+         }},
+};
+
+using MemoryDomainAllocateTestParam = std::tuple<NamedDevice, TestOperandType>;
+class MemoryDomainAllocateTest : public MemoryDomainTestBase,
+                                 public testing::WithParamInterface<MemoryDomainAllocateTestParam> {
+  protected:
+    MemoryDomainAllocateTest()
+        : MemoryDomainTestBase(getData(std::get<NamedDevice>(GetParam())),
+                               std::get<TestOperandType>(GetParam())) {}
+
+    struct AllocateTestArgs {
+        hidl_vec<uint32_t> dimensions;
+        hidl_vec<sp<IPreparedModel>> preparedModels;
+        hidl_vec<BufferRole> inputRoles;
+        hidl_vec<BufferRole> outputRoles;
+    };
+
+    // Validation test for IDevice::allocate. The driver is expected to fail with INVALID_ARGUMENT,
+    // or GENERAL_FAILURE if memory domain is not supported.
+    void validateAllocate(AllocateTestArgs args) {
+        const auto ret = kDevice->allocate(
+                {.dimensions = std::move(args.dimensions)}, std::move(args.preparedModels),
+                std::move(args.inputRoles), std::move(args.outputRoles),
+                [](ErrorStatus status, const sp<IBuffer>& buffer, uint32_t token) {
+                    EXPECT_TRUE(status == ErrorStatus::INVALID_ARGUMENT ||
+                                status == ErrorStatus::GENERAL_FAILURE);
+                    EXPECT_EQ(buffer, nullptr);
+                    EXPECT_EQ(token, 0);
+                });
+        ASSERT_TRUE(ret.isOk());
+    }
+
+    void testConflictOperands(const sp<IPreparedModel>& model1, const sp<IPreparedModel>& model2) {
+        validateAllocate({
+                .preparedModels = {model1, model2},
+                .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f},
+                               {.modelIndex = 1, .ioIndex = 0, .frequency = 1.0f}},
+        });
+        validateAllocate({
+                .preparedModels = {model1, model2},
+                .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+                .outputRoles = {{.modelIndex = 1, .ioIndex = 0, .frequency = 1.0f}},
+        });
+        validateAllocate({
+                .preparedModels = {model1, model2},
+                .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f},
+                                {.modelIndex = 1, .ioIndex = 0, .frequency = 1.0f}},
+        });
+    }
+};
+
+TEST_P(MemoryDomainAllocateTest, EmptyRole) {
+    // Test with empty prepared models and roles.
+    validateAllocate({});
+
+    auto preparedModel = createConvPreparedModel(kTestOperand);
+    if (preparedModel == nullptr) return;
+
+    // Test again with non-empty prepared models but empty roles.
+    validateAllocate({
+            .preparedModels = {preparedModel},
+    });
+}
+
+TEST_P(MemoryDomainAllocateTest, NullptrPreparedModel) {
+    // Test with nullptr prepared model as input role.
+    validateAllocate({
+            .preparedModels = {nullptr},
+            .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+    });
+
+    // Test with nullptr prepared model as output role.
+    validateAllocate({
+            .preparedModels = {nullptr},
+            .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+    });
+}
+
+TEST_P(MemoryDomainAllocateTest, InvalidPreparedModel) {
+    sp<InvalidPreparedModel> invalidPreparedModel = new InvalidPreparedModel();
+
+    // Test with invalid prepared model as input role.
+    validateAllocate({
+            .preparedModels = {invalidPreparedModel},
+            .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+    });
+
+    // Test with invalid prepared model as output role.
+    validateAllocate({
+            .preparedModels = {invalidPreparedModel},
+            .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+    });
+}
+
+TEST_P(MemoryDomainAllocateTest, InvalidModelIndex) {
+    auto preparedModel = createConvPreparedModel(kTestOperand);
+    if (preparedModel == nullptr) return;
+
+    // This should fail, because the model index is out of bound.
+    validateAllocate({
+            .preparedModels = {preparedModel},
+            .inputRoles = {{.modelIndex = 1, .ioIndex = 0, .frequency = 1.0f}},
+    });
+
+    // This should fail, because the model index is out of bound.
+    validateAllocate({
+            .preparedModels = {preparedModel},
+            .outputRoles = {{.modelIndex = 1, .ioIndex = 0, .frequency = 1.0f}},
+    });
+}
+
+TEST_P(MemoryDomainAllocateTest, InvalidIOIndex) {
+    auto preparedModel = createConvPreparedModel(kTestOperand);
+    if (preparedModel == nullptr) return;
+
+    // This should fail, because the model only has one input.
+    validateAllocate({
+            .preparedModels = {preparedModel},
+            .inputRoles = {{.modelIndex = 0, .ioIndex = 1, .frequency = 1.0f}},
+    });
+
+    // This should fail, because the model only has one output.
+    validateAllocate({
+            .preparedModels = {preparedModel},
+            .outputRoles = {{.modelIndex = 0, .ioIndex = 1, .frequency = 1.0f}},
+    });
+}
+
+TEST_P(MemoryDomainAllocateTest, InvalidFrequency) {
+    auto preparedModel = createConvPreparedModel(kTestOperand);
+    if (preparedModel == nullptr) return;
+
+    for (float invalidFreq : {10.0f, 0.0f, -0.5f}) {
+        // Test with invalid frequency for input roles.
+        validateAllocate({
+                .preparedModels = {preparedModel},
+                .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = invalidFreq}},
+        });
+        // Test with invalid frequency for output roles.
+        validateAllocate({
+                .preparedModels = {preparedModel},
+                .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = invalidFreq}},
+        });
+    }
+}
+
+TEST_P(MemoryDomainAllocateTest, SameRoleSpecifiedTwice) {
+    auto preparedModel = createConvPreparedModel(kTestOperand);
+    if (preparedModel == nullptr) return;
+
+    // Same role with same model index.
+    validateAllocate({
+            .preparedModels = {preparedModel},
+            .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f},
+                           {.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+    });
+    validateAllocate({
+            .preparedModels = {preparedModel},
+            .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f},
+                            {.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+    });
+
+    // Different model indexes, but logically referring to the same role.
+    validateAllocate({
+            .preparedModels = {preparedModel, preparedModel},
+            .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f},
+                           {.modelIndex = 1, .ioIndex = 0, .frequency = 1.0f}},
+    });
+    validateAllocate({
+            .preparedModels = {preparedModel, preparedModel},
+            .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f},
+                            {.modelIndex = 1, .ioIndex = 0, .frequency = 1.0f}},
+    });
+}
+
+TEST_P(MemoryDomainAllocateTest, ConflictOperandType) {
+    const std::map<TestOperandType, TestOperandType> conflictTypeMap = {
+            {TestOperandType::TENSOR_FLOAT32, TestOperandType::TENSOR_FLOAT16},
+            {TestOperandType::TENSOR_FLOAT16, TestOperandType::TENSOR_FLOAT32},
+            {TestOperandType::TENSOR_QUANT8_ASYMM, TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED},
+            {TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED, TestOperandType::TENSOR_QUANT8_ASYMM},
+    };
+
+    TestOperand conflictTestOperand = kTestOperand;
+    const auto it = conflictTypeMap.find(kTestOperandType);
+    ASSERT_FALSE(it == conflictTypeMap.end());
+    conflictTestOperand.type = it->second;
+
+    auto preparedModel = createConvPreparedModel(kTestOperand);
+    auto conflictPreparedModel = createConvPreparedModel(conflictTestOperand);
+    if (preparedModel == nullptr || conflictPreparedModel == nullptr) return;
+    testConflictOperands(preparedModel, conflictPreparedModel);
+}
+
+TEST_P(MemoryDomainAllocateTest, ConflictScale) {
+    if (isFloat(kTestOperandType)) return;
+
+    TestOperand conflictTestOperand = kTestOperand;
+    ASSERT_NE(conflictTestOperand.scale, 1.0f);
+    conflictTestOperand.scale = 1.0f;
+
+    auto preparedModel = createConvPreparedModel(kTestOperand);
+    auto conflictPreparedModel = createConvPreparedModel(conflictTestOperand);
+    if (preparedModel == nullptr || conflictPreparedModel == nullptr) return;
+    testConflictOperands(preparedModel, conflictPreparedModel);
+}
+
+TEST_P(MemoryDomainAllocateTest, ConflictZeroPoint) {
+    if (isFloat(kTestOperandType)) return;
+
+    TestOperand conflictTestOperand = kTestOperand;
+    ASSERT_NE(conflictTestOperand.zeroPoint, 10);
+    conflictTestOperand.zeroPoint = 10;
+
+    auto preparedModel = createConvPreparedModel(kTestOperand);
+    auto conflictPreparedModel = createConvPreparedModel(conflictTestOperand);
+    if (preparedModel == nullptr || conflictPreparedModel == nullptr) return;
+    testConflictOperands(preparedModel, conflictPreparedModel);
+}
+
+TEST_P(MemoryDomainAllocateTest, ConflictRankBetweenRoles) {
+    TestOperand conflictTestOperand = kTestOperand;
+    conflictTestOperand.dimensions.pop_back();
+
+    auto preparedModel = createAddPreparedModel(kTestOperand);
+    auto conflictPreparedModel = createAddPreparedModel(conflictTestOperand);
+    if (preparedModel == nullptr || conflictPreparedModel == nullptr) return;
+    testConflictOperands(preparedModel, conflictPreparedModel);
+}
+
+TEST_P(MemoryDomainAllocateTest, ConflictDimensionsBetweenRoles) {
+    TestOperand conflictTestOperand = kTestOperand;
+    conflictTestOperand.dimensions[0] = 4;
+
+    auto preparedModel = createConvPreparedModel(kTestOperand);
+    auto conflictPreparedModel = createConvPreparedModel(conflictTestOperand);
+    if (preparedModel == nullptr || conflictPreparedModel == nullptr) return;
+    testConflictOperands(preparedModel, conflictPreparedModel);
+}
+
+TEST_P(MemoryDomainAllocateTest, ConflictRankBetweenRoleAndDesc) {
+    auto preparedModel = createConvPreparedModel(kTestOperand);
+    if (preparedModel == nullptr) return;
+
+    auto badDimensions = kTestOperand.dimensions;
+    badDimensions.pop_back();
+
+    validateAllocate({
+            .dimensions = badDimensions,
+            .preparedModels = {preparedModel},
+            .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+    });
+    validateAllocate({
+            .dimensions = badDimensions,
+            .preparedModels = {preparedModel},
+            .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+    });
+}
+
+TEST_P(MemoryDomainAllocateTest, ConflictDimensionsBetweenRoleAndDesc) {
+    auto preparedModel = createConvPreparedModel(kTestOperand);
+    if (preparedModel == nullptr) return;
+
+    auto badDimensions = kTestOperand.dimensions;
+    badDimensions[0] = 4;
+
+    validateAllocate({
+            .dimensions = badDimensions,
+            .preparedModels = {preparedModel},
+            .inputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+    });
+    validateAllocate({
+            .dimensions = badDimensions,
+            .preparedModels = {preparedModel},
+            .outputRoles = {{.modelIndex = 0, .ioIndex = 0, .frequency = 1.0f}},
+    });
+}
+
+TEST_P(MemoryDomainAllocateTest, ConflictRankWithScalarRole) {
+    auto preparedModel = createAddPreparedModel(kTestOperand);
+    if (preparedModel == nullptr) return;
+
+    // This should fail, because the target operand is a scalar but a non-empty dimension is
+    // specified.
+    validateAllocate({
+            .dimensions = {1},
+            .preparedModels = {preparedModel},
+            .inputRoles = {{.modelIndex = 0, .ioIndex = 2, .frequency = 1.0f}},
+    });
+}
+
+std::string printMemoryDomainAllocateTest(
+        const testing::TestParamInfo<MemoryDomainAllocateTestParam>& info) {
+    const auto& [namedDevice, operandType] = info.param;
+    const std::string type = toString(static_cast<OperandType>(operandType));
+    return gtestCompliantName(getName(namedDevice) + "_" + type);
+}
+
+INSTANTIATE_TEST_CASE_P(TestMemoryDomain, MemoryDomainAllocateTest,
+                        testing::Combine(kNamedDeviceChoices, kTestOperandTypeChoices),
+                        printMemoryDomainAllocateTest);
+
+class MemoryDomainCopyTestBase : public MemoryDomainTestBase {
+  protected:
+    MemoryDomainCopyTestBase(sp<IDevice> device, TestOperandType type)
+        : MemoryDomainTestBase(std::move(device), type) {}
+
+    // Allocates device memory for roles of a single prepared model.
+    // Returns {IBuffer, token} if success; returns {nullptr, 0} if not supported.
+    std::pair<sp<IBuffer>, uint32_t> allocateBuffer(const sp<IPreparedModel>& preparedModel,
+                                                    const std::vector<uint32_t>& inputIndexes,
+                                                    const std::vector<uint32_t>& outputIndexes,
+                                                    const std::vector<uint32_t>& dimensions) {
+        if (preparedModel == nullptr) {
+            return {nullptr, 0};
+        }
+
+        hidl_vec<BufferRole> inputRoles(inputIndexes.size()), outputRoles(outputIndexes.size());
+        auto trans = [](uint32_t ind) -> BufferRole {
+            return {.modelIndex = 0, .ioIndex = ind, .frequency = 1.0f};
+        };
+        std::transform(inputIndexes.begin(), inputIndexes.end(), inputRoles.begin(), trans);
+        std::transform(outputIndexes.begin(), outputIndexes.end(), outputRoles.begin(), trans);
+
+        sp<IBuffer> buffer;
+        uint32_t token = 0;
+        const auto ret = kDevice->allocate(
+                {.dimensions = dimensions}, {preparedModel}, std::move(inputRoles),
+                std::move(outputRoles),
+                [&buffer, &token](ErrorStatus err, const sp<IBuffer>& buf, uint32_t tok) {
+                    if (err == ErrorStatus::NONE) {
+                        EXPECT_NE(buf, nullptr);
+                        EXPECT_GT(tok, 0);
+                        buffer = buf;
+                        token = tok;
+                    } else {
+                        EXPECT_EQ(err, ErrorStatus::GENERAL_FAILURE);
+                        EXPECT_EQ(buf, nullptr);
+                        EXPECT_EQ(tok, 0);
+                    }
+                });
+        EXPECT_TRUE(ret.isOk());
+        return {std::move(buffer), token};
+    }
+
+    std::pair<sp<IBuffer>, uint32_t> allocateBuffer(const sp<IPreparedModel>& preparedModel,
+                                                    const std::vector<uint32_t>& inputIndexes,
+                                                    const std::vector<uint32_t>& outputIndexes) {
+        return allocateBuffer(preparedModel, inputIndexes, outputIndexes, {});
+    }
+
+    hidl_memory allocateSharedMemory(uint32_t size) {
+        hidl_memory memory = nn::allocateSharedMemory(size);
+        EXPECT_EQ(memory.size(), size);
+        return memory;
+    }
+
+    void testCopyFrom(const sp<IBuffer>& buffer, const hidl_memory& memory,
+                      const std::vector<uint32_t>& dimensions, ErrorStatus expectedStatus) {
+        const auto ret = buffer->copyFrom(memory, dimensions);
+        ASSERT_TRUE(ret.isOk());
+        ASSERT_EQ(static_cast<ErrorStatus>(ret), expectedStatus);
+    }
+
+    void testCopyTo(const sp<IBuffer>& buffer, const hidl_memory& memory,
+                    ErrorStatus expectedStatus) {
+        const auto ret = buffer->copyTo(memory);
+        ASSERT_TRUE(ret.isOk());
+        ASSERT_EQ(static_cast<ErrorStatus>(ret), expectedStatus);
+    }
+
+    void initializeDeviceMemory(const sp<IBuffer>& buffer) {
+        hidl_memory memory = nn::allocateSharedMemory(kTestOperandDataSize);
+        ASSERT_EQ(memory.size(), kTestOperandDataSize);
+        testCopyFrom(buffer, memory, kTestOperand.dimensions, ErrorStatus::NONE);
+    }
+};
+
+using MemoryDomainCopyTestParam = std::tuple<NamedDevice, TestOperandType>;
+class MemoryDomainCopyTest : public MemoryDomainCopyTestBase,
+                             public testing::WithParamInterface<MemoryDomainCopyTestParam> {
+  protected:
+    MemoryDomainCopyTest()
+        : MemoryDomainCopyTestBase(getData(std::get<NamedDevice>(GetParam())),
+                                   std::get<TestOperandType>(GetParam())) {}
+};
+
+TEST_P(MemoryDomainCopyTest, CopyFrom_InvalidMemorySize) {
+    auto preparedModel = createConvPreparedModel(kTestOperand);
+    auto [buffer, token] = allocateBuffer(preparedModel, {0}, {0});
+    if (buffer == nullptr) return;
+
+    uint32_t badMemorySize1 = kTestOperandDataSize / 2, badMemorySize2 = kTestOperandDataSize * 2;
+    hidl_memory badMemory1 = allocateSharedMemory(badMemorySize1);
+    hidl_memory badMemory2 = allocateSharedMemory(badMemorySize2);
+    testCopyFrom(buffer, badMemory1, {}, ErrorStatus::INVALID_ARGUMENT);
+    testCopyFrom(buffer, badMemory2, {}, ErrorStatus::INVALID_ARGUMENT);
+}
+
+TEST_P(MemoryDomainCopyTest, CopyFrom_InvalidMemorySize_DynamicShape) {
+    TestOperand testOperand = kTestOperand;
+    testOperand.dimensions[0] = 0;
+    auto preparedModel = createConvPreparedModel(testOperand);
+    auto [buffer, token] = allocateBuffer(preparedModel, {0}, {0});
+    if (buffer == nullptr) return;
+
+    uint32_t badMemorySize1 = kTestOperandDataSize / 2, badMemorySize2 = kTestOperandDataSize * 2;
+    hidl_memory badMemory1 = allocateSharedMemory(badMemorySize1);
+    hidl_memory badMemory2 = allocateSharedMemory(badMemorySize2);
+    hidl_memory goodMemory = allocateSharedMemory(kTestOperandDataSize);
+
+    auto badDimensions = kTestOperand.dimensions;
+    badDimensions[0] = 2;
+
+    testCopyFrom(buffer, badMemory1, kTestOperand.dimensions, ErrorStatus::INVALID_ARGUMENT);
+    testCopyFrom(buffer, badMemory2, kTestOperand.dimensions, ErrorStatus::INVALID_ARGUMENT);
+    testCopyFrom(buffer, goodMemory, kTestOperand.dimensions, ErrorStatus::NONE);
+    testCopyFrom(buffer, goodMemory, badDimensions, ErrorStatus::INVALID_ARGUMENT);
+}
+
+TEST_P(MemoryDomainCopyTest, CopyFrom_InvalidDimensions) {
+    auto preparedModel = createConvPreparedModel(kTestOperand);
+    auto [buffer, token] = allocateBuffer(preparedModel, {0}, {0});
+    if (buffer == nullptr) return;
+
+    hidl_memory memory = allocateSharedMemory(kTestOperandDataSize);
+
+    std::vector<uint32_t> badDimensions;
+    badDimensions = kTestOperand.dimensions;
+    badDimensions.pop_back();
+    testCopyFrom(buffer, memory, badDimensions, ErrorStatus::INVALID_ARGUMENT);
+
+    badDimensions = kTestOperand.dimensions;
+    badDimensions[0] = 2;
+    testCopyFrom(buffer, memory, badDimensions, ErrorStatus::INVALID_ARGUMENT);
+
+    badDimensions = kTestOperand.dimensions;
+    badDimensions[0] = 0;
+    testCopyFrom(buffer, memory, badDimensions, ErrorStatus::INVALID_ARGUMENT);
+
+    testCopyFrom(buffer, memory, {}, ErrorStatus::NONE);
+    testCopyFrom(buffer, memory, kTestOperand.dimensions, ErrorStatus::NONE);
+}
+
+TEST_P(MemoryDomainCopyTest, CopyFrom_InvalidDimensions_DynamicShape) {
+    TestOperand testOperand = kTestOperand;
+    testOperand.dimensions[0] = 0;
+    auto preparedModel = createConvPreparedModel(testOperand);
+    auto [buffer, token] = allocateBuffer(preparedModel, {0}, {0});
+    if (buffer == nullptr) return;
+
+    hidl_memory memory = allocateSharedMemory(kTestOperandDataSize);
+
+    std::vector<uint32_t> badDimensions;
+    badDimensions = kTestOperand.dimensions;
+    badDimensions.pop_back();
+    testCopyFrom(buffer, memory, badDimensions, ErrorStatus::INVALID_ARGUMENT);
+
+    badDimensions = kTestOperand.dimensions;
+    badDimensions[0] = 2;
+    badDimensions[3] = 4;
+    testCopyFrom(buffer, memory, badDimensions, ErrorStatus::INVALID_ARGUMENT);
+
+    badDimensions = kTestOperand.dimensions;
+    badDimensions[0] = 1;
+    badDimensions[3] = 0;
+    testCopyFrom(buffer, memory, badDimensions, ErrorStatus::INVALID_ARGUMENT);
+
+    testCopyFrom(buffer, memory, {}, ErrorStatus::INVALID_ARGUMENT);
+    testCopyFrom(buffer, memory, kTestOperand.dimensions, ErrorStatus::NONE);
+}
+
+TEST_P(MemoryDomainCopyTest, CopyTo_UninitializedMemory) {
+    auto preparedModel = createConvPreparedModel(kTestOperand);
+    auto [buffer, token] = allocateBuffer(preparedModel, {0}, {0});
+    if (buffer == nullptr) return;
+
+    hidl_memory memory = allocateSharedMemory(kTestOperandDataSize);
+    testCopyTo(buffer, memory, ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(MemoryDomainCopyTest, CopyTo_InvalidMemorySize) {
+    auto preparedModel = createConvPreparedModel(kTestOperand);
+    auto [buffer, token] = allocateBuffer(preparedModel, {0}, {0});
+    if (buffer == nullptr) return;
+
+    uint32_t badMemorySize1 = kTestOperandDataSize / 2, badMemorySize2 = kTestOperandDataSize * 2;
+    hidl_memory badMemory1 = allocateSharedMemory(badMemorySize1);
+    hidl_memory badMemory2 = allocateSharedMemory(badMemorySize2);
+    hidl_memory goodMemory = allocateSharedMemory(kTestOperandDataSize);
+
+    initializeDeviceMemory(buffer);
+    testCopyTo(buffer, badMemory1, ErrorStatus::INVALID_ARGUMENT);
+    testCopyTo(buffer, badMemory2, ErrorStatus::INVALID_ARGUMENT);
+    testCopyTo(buffer, goodMemory, ErrorStatus::NONE);
+}
+
+TEST_P(MemoryDomainCopyTest, CopyTo_InvalidMemorySize_DynamicShape) {
+    TestOperand testOperand = kTestOperand;
+    testOperand.dimensions[0] = 0;
+    auto preparedModel = createConvPreparedModel(testOperand);
+    auto [buffer, token] = allocateBuffer(preparedModel, {0}, {0});
+    if (buffer == nullptr) return;
+
+    uint32_t badMemorySize1 = kTestOperandDataSize / 2, badMemorySize2 = kTestOperandDataSize * 2;
+    hidl_memory badMemory1 = allocateSharedMemory(badMemorySize1);
+    hidl_memory badMemory2 = allocateSharedMemory(badMemorySize2);
+    hidl_memory goodMemory = allocateSharedMemory(kTestOperandDataSize);
+
+    initializeDeviceMemory(buffer);
+    testCopyTo(buffer, badMemory1, ErrorStatus::INVALID_ARGUMENT);
+    testCopyTo(buffer, badMemory2, ErrorStatus::INVALID_ARGUMENT);
+    testCopyTo(buffer, goodMemory, ErrorStatus::NONE);
+}
+
+std::string printMemoryDomainCopyTest(
+        const testing::TestParamInfo<MemoryDomainCopyTestParam>& info) {
+    const auto& [namedDevice, operandType] = info.param;
+    const std::string type = toString(static_cast<OperandType>(operandType));
+    return gtestCompliantName(getName(namedDevice) + "_" + type);
+}
+
+INSTANTIATE_TEST_CASE_P(TestMemoryDomain, MemoryDomainCopyTest,
+                        testing::Combine(kNamedDeviceChoices, kTestOperandTypeChoices),
+                        printMemoryDomainCopyTest);
+
+using MemoryDomainExecutionTestParam = std::tuple<NamedDevice, TestOperandType, Executor>;
+class MemoryDomainExecutionTest
+    : public MemoryDomainCopyTestBase,
+      public testing::WithParamInterface<MemoryDomainExecutionTestParam> {
+  protected:
+    MemoryDomainExecutionTest()
+        : MemoryDomainCopyTestBase(getData(std::get<NamedDevice>(GetParam())),
+                                   std::get<TestOperandType>(GetParam())) {}
+
+    Request::MemoryPool createSharedMemoryPool(uint32_t size) {
+        hidl_memory memory = allocateSharedMemory(size);
+        Request::MemoryPool pool;
+        pool.hidlMemory(memory);
+        return pool;
+    }
+
+    Request::MemoryPool createDeviceMemoryPool(uint32_t token) {
+        Request::MemoryPool pool;
+        pool.token(token);
+        return pool;
+    }
+
+    void testExecution(const sp<IPreparedModel>& preparedModel, const Request& request,
+                       ErrorStatus expectedStatus) {
+        switch (kExecutor) {
+            case Executor::ASYNC:
+                EXPECT_EQ(executeAsync(preparedModel, request), expectedStatus);
+                break;
+            case Executor::SYNC:
+                EXPECT_EQ(executeSync(preparedModel, request), expectedStatus);
+                break;
+            case Executor::FENCED:
+                EXPECT_EQ(executeFenced(preparedModel, request), expectedStatus);
+                break;
+            default:
+                ASSERT_TRUE(false);
+        }
+    }
+
+    ErrorStatus executeAsync(const sp<IPreparedModel>& preparedModel, const Request& request) {
+        ErrorStatus executionStatus;
+
+        // launch execution
+        sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+        const auto ret =
+                preparedModel->execute_1_3(request, MeasureTiming::NO, {}, {}, executionCallback);
+        EXPECT_TRUE(ret.isOk());
+        executionStatus = static_cast<ErrorStatus>(ret);
+
+        // retrieve execution status
+        executionCallback->wait();
+        if (executionStatus == ErrorStatus::NONE) {
+            executionStatus = executionCallback->getStatus();
+        } else {
+            EXPECT_EQ(executionStatus, executionCallback->getStatus());
+        }
+        const auto timing = executionCallback->getTiming();
+        EXPECT_EQ(UINT64_MAX, timing.timeOnDevice);
+        EXPECT_EQ(UINT64_MAX, timing.timeInDriver);
+        if (executionStatus != ErrorStatus::NONE) {
+            EXPECT_EQ(executionCallback->getOutputShapes().size(), 0);
+        }
+        return executionStatus;
+    }
+
+    ErrorStatus executeSync(const sp<IPreparedModel>& preparedModel, const Request& request) {
+        ErrorStatus executionStatus;
+        const auto ret = preparedModel->executeSynchronously_1_3(
+                request, MeasureTiming::NO, {}, {},
+                [&executionStatus](ErrorStatus error, const hidl_vec<OutputShape>& shapes,
+                                   const Timing& time) {
+                    executionStatus = error;
+                    EXPECT_EQ(UINT64_MAX, time.timeOnDevice);
+                    EXPECT_EQ(UINT64_MAX, time.timeInDriver);
+                    if (executionStatus != ErrorStatus::NONE) {
+                        EXPECT_EQ(shapes.size(), 0);
+                    }
+                });
+        EXPECT_TRUE(ret.isOk());
+        return executionStatus;
+    }
+
+    ErrorStatus executeFenced(const sp<IPreparedModel>& preparedModel, const Request& request) {
+        ErrorStatus executionStatus;
+        hidl_handle syncFenceHandle;
+        sp<IFencedExecutionCallback> fencedCallback;
+        const auto callbackFunc = [&executionStatus, &syncFenceHandle, &fencedCallback](
+                                          ErrorStatus error, const hidl_handle& handle,
+                                          const sp<IFencedExecutionCallback>& callback) {
+            executionStatus = error;
+            syncFenceHandle = handle;
+            fencedCallback = callback;
+        };
+        Return<void> ret = preparedModel->executeFenced(request, {}, MeasureTiming::NO, {}, {}, {},
+                                                        callbackFunc);
+        EXPECT_TRUE(ret.isOk());
+        if (executionStatus != ErrorStatus::NONE) {
+            EXPECT_EQ(syncFenceHandle.getNativeHandle(), nullptr);
+            EXPECT_EQ(fencedCallback, nullptr);
+            return executionStatus;
+        }
+        if (syncFenceHandle.getNativeHandle()) {
+            waitForSyncFence(syncFenceHandle.getNativeHandle()->data[0]);
+        }
+        EXPECT_NE(fencedCallback, nullptr);
+        ret = fencedCallback->getExecutionInfo(
+                [&executionStatus](ErrorStatus error, Timing t, Timing) {
+                    executionStatus = error;
+                    EXPECT_EQ(UINT64_MAX, t.timeOnDevice);
+                    EXPECT_EQ(UINT64_MAX, t.timeInDriver);
+                });
+        EXPECT_TRUE(ret.isOk());
+        return executionStatus;
+    }
+
+    const Executor kExecutor = std::get<Executor>(GetParam());
+};
+
+TEST_P(MemoryDomainExecutionTest, InvalidToken) {
+    auto preparedModel = createConvPreparedModel(kTestOperand);
+    if (preparedModel == nullptr) return;
+
+    Request::MemoryPool sharedMemory = createSharedMemoryPool(kTestOperandDataSize);
+    Request::MemoryPool badDeviceMemory1 = createDeviceMemoryPool(0);    // Invalid token.
+    Request::MemoryPool badDeviceMemory2 = createDeviceMemoryPool(100);  // Unknown token.
+    RequestArgument sharedMemoryArg = {
+            .location = {.poolIndex = 0, .offset = 0, .length = kTestOperandDataSize}};
+    RequestArgument deviceMemoryArg = {.location = {.poolIndex = 1}};
+
+    testExecution(preparedModel,
+                  {.inputs = {deviceMemoryArg},
+                   .outputs = {sharedMemoryArg},
+                   .pools = {sharedMemory, badDeviceMemory1}},
+                  ErrorStatus::INVALID_ARGUMENT);
+    testExecution(preparedModel,
+                  {.inputs = {deviceMemoryArg},
+                   .outputs = {sharedMemoryArg},
+                   .pools = {sharedMemory, badDeviceMemory2}},
+                  ErrorStatus::INVALID_ARGUMENT);
+    testExecution(preparedModel,
+                  {.inputs = {sharedMemoryArg},
+                   .outputs = {deviceMemoryArg},
+                   .pools = {sharedMemory, badDeviceMemory1}},
+                  ErrorStatus::INVALID_ARGUMENT);
+    testExecution(preparedModel,
+                  {.inputs = {sharedMemoryArg},
+                   .outputs = {deviceMemoryArg},
+                   .pools = {sharedMemory, badDeviceMemory2}},
+                  ErrorStatus::INVALID_ARGUMENT);
+}
+
+TEST_P(MemoryDomainExecutionTest, InvalidPreparedModel) {
+    auto preparedModel = createConvPreparedModel(kTestOperand);
+    auto [buffer, token] = allocateBuffer(preparedModel, {0}, {0});
+    if (buffer == nullptr) return;
+    auto badPreparedModel = createConvPreparedModel(kTestOperand);
+    if (badPreparedModel == nullptr) return;
+
+    Request::MemoryPool sharedMemory = createSharedMemoryPool(kTestOperandDataSize);
+    Request::MemoryPool deviceMemory = createDeviceMemoryPool(token);
+    RequestArgument sharedMemoryArg = {
+            .location = {.poolIndex = 0, .offset = 0, .length = kTestOperandDataSize}};
+    RequestArgument deviceMemoryArg = {.location = {.poolIndex = 1}};
+
+    // This should fail, because the buffer is not allocated for badPreparedModel.
+    initializeDeviceMemory(buffer);
+    testExecution(badPreparedModel,
+                  {.inputs = {deviceMemoryArg},
+                   .outputs = {sharedMemoryArg},
+                   .pools = {sharedMemory, deviceMemory}},
+                  ErrorStatus::INVALID_ARGUMENT);
+    testExecution(badPreparedModel,
+                  {.inputs = {sharedMemoryArg},
+                   .outputs = {deviceMemoryArg},
+                   .pools = {sharedMemory, deviceMemory}},
+                  ErrorStatus::INVALID_ARGUMENT);
+}
+
+TEST_P(MemoryDomainExecutionTest, InvalidIOIndex) {
+    auto preparedModel = createConvPreparedModel(kTestOperand, 2);
+    auto [buffer, token] = allocateBuffer(preparedModel, {0}, {});
+    if (buffer == nullptr) return;
+
+    Request::MemoryPool sharedMemory1 = createSharedMemoryPool(kTestOperandDataSize);
+    Request::MemoryPool sharedMemory2 = createSharedMemoryPool(kTestOperandDataSize);
+    Request::MemoryPool sharedMemory3 = createSharedMemoryPool(kTestOperandDataSize);
+    Request::MemoryPool deviceMemory = createDeviceMemoryPool(token);
+    RequestArgument sharedMemoryArg1 = {
+            .location = {.poolIndex = 0, .offset = 0, .length = kTestOperandDataSize}};
+    RequestArgument sharedMemoryArg2 = {
+            .location = {.poolIndex = 1, .offset = 0, .length = kTestOperandDataSize}};
+    RequestArgument sharedMemoryArg3 = {
+            .location = {.poolIndex = 2, .offset = 0, .length = kTestOperandDataSize}};
+    RequestArgument deviceMemoryArg = {.location = {.poolIndex = 3}};
+
+    // This should fail, because the device memory is not allocated for input 1.
+    initializeDeviceMemory(buffer);
+    testExecution(preparedModel,
+                  {.inputs = {sharedMemoryArg1, deviceMemoryArg},
+                   .outputs = {sharedMemoryArg2, sharedMemoryArg3},
+                   .pools = {sharedMemory1, sharedMemory2, sharedMemory3, deviceMemory}},
+                  ErrorStatus::INVALID_ARGUMENT);
+
+    // This should fail, because the device memory is not allocated for output 1.
+    testExecution(preparedModel,
+                  {.inputs = {sharedMemoryArg1, sharedMemoryArg2},
+                   .outputs = {sharedMemoryArg3, deviceMemoryArg},
+                   .pools = {sharedMemory1, sharedMemory2, sharedMemory3, deviceMemory}},
+                  ErrorStatus::INVALID_ARGUMENT);
+}
+
+TEST_P(MemoryDomainExecutionTest, InvalidIOType) {
+    auto preparedModel = createConvPreparedModel(kTestOperand);
+    auto [inputBuffer, inputToken] = allocateBuffer(preparedModel, {0}, {});
+    auto [outputBuffer, outputToken] = allocateBuffer(preparedModel, {}, {0});
+    if (inputBuffer == nullptr || outputBuffer == nullptr) return;
+
+    Request::MemoryPool sharedMemory = createSharedMemoryPool(kTestOperandDataSize);
+    Request::MemoryPool deviceMemory = createDeviceMemoryPool(inputToken);
+    RequestArgument sharedMemoryArg = {
+            .location = {.poolIndex = 0, .offset = 0, .length = kTestOperandDataSize}};
+    RequestArgument deviceMemoryArg = {.location = {.poolIndex = 1}};
+
+    // This should fail, because the device memory is allocated for input but used as output.
+    testExecution(preparedModel,
+                  {.inputs = {sharedMemoryArg},
+                   .outputs = {deviceMemoryArg},
+                   .pools = {sharedMemory, deviceMemory}},
+                  ErrorStatus::INVALID_ARGUMENT);
+
+    // This should fail, because the device memory is allocated for output but used as input.
+    deviceMemory.token(outputToken);
+    initializeDeviceMemory(outputBuffer);
+    testExecution(preparedModel,
+                  {.inputs = {deviceMemoryArg},
+                   .outputs = {sharedMemoryArg},
+                   .pools = {sharedMemory, deviceMemory}},
+                  ErrorStatus::INVALID_ARGUMENT);
+}
+
+TEST_P(MemoryDomainExecutionTest, UninitializedMemory) {
+    auto preparedModel = createConvPreparedModel(kTestOperand);
+    auto [buffer, token] = allocateBuffer(preparedModel, {0}, {0});
+    if (buffer == nullptr) return;
+
+    Request::MemoryPool sharedMemory = createSharedMemoryPool(kTestOperandDataSize);
+    Request::MemoryPool deviceMemory = createDeviceMemoryPool(token);
+    RequestArgument sharedMemoryArg = {
+            .location = {.poolIndex = 0, .offset = 0, .length = kTestOperandDataSize}};
+    RequestArgument deviceMemoryArg = {.location = {.poolIndex = 1}};
+
+    // This should fail, because the device memory is not initialized.
+    testExecution(preparedModel,
+                  {.inputs = {deviceMemoryArg},
+                   .outputs = {sharedMemoryArg},
+                   .pools = {sharedMemory, deviceMemory}},
+                  ErrorStatus::GENERAL_FAILURE);
+
+    // This should initialize the device memory.
+    testExecution(preparedModel,
+                  {.inputs = {sharedMemoryArg},
+                   .outputs = {deviceMemoryArg},
+                   .pools = {sharedMemory, deviceMemory}},
+                  ErrorStatus::NONE);
+
+    // Test again with initialized device memory.
+    testExecution(preparedModel,
+                  {.inputs = {deviceMemoryArg},
+                   .outputs = {sharedMemoryArg},
+                   .pools = {sharedMemory, deviceMemory}},
+                  ErrorStatus::NONE);
+}
+
+TEST_P(MemoryDomainExecutionTest, SameRequestMultipleRoles) {
+    auto preparedModel = createConvPreparedModel(kTestOperand, 2);
+    auto [buffer, token] = allocateBuffer(preparedModel, {0, 1}, {0, 1});
+    if (buffer == nullptr) return;
+
+    Request::MemoryPool sharedMemory1 = createSharedMemoryPool(kTestOperandDataSize);
+    Request::MemoryPool sharedMemory2 = createSharedMemoryPool(kTestOperandDataSize);
+    Request::MemoryPool deviceMemory = createDeviceMemoryPool(token);
+    RequestArgument sharedMemoryArg1 = {
+            .location = {.poolIndex = 0, .offset = 0, .length = kTestOperandDataSize}};
+    RequestArgument sharedMemoryArg2 = {
+            .location = {.poolIndex = 1, .offset = 0, .length = kTestOperandDataSize}};
+    RequestArgument deviceMemoryArg = {.location = {.poolIndex = 2}};
+
+    // This should fail, because the same device memory cannot be used for both input and output.
+    initializeDeviceMemory(buffer);
+    testExecution(preparedModel,
+                  {.inputs = {deviceMemoryArg, sharedMemoryArg1},
+                   .outputs = {deviceMemoryArg, sharedMemoryArg2},
+                   .pools = {sharedMemory1, sharedMemory2, deviceMemory}},
+                  ErrorStatus::INVALID_ARGUMENT);
+
+    // This should fail, because the same device memory cannot be used for multiple outputs.
+    testExecution(preparedModel,
+                  {.inputs = {sharedMemoryArg1, sharedMemoryArg2},
+                   .outputs = {deviceMemoryArg, deviceMemoryArg},
+                   .pools = {sharedMemory1, sharedMemory2, deviceMemory}},
+                  ErrorStatus::INVALID_ARGUMENT);
+
+    // The same device memory can be used for multiple inputs.
+    initializeDeviceMemory(buffer);
+    testExecution(preparedModel,
+                  {.inputs = {deviceMemoryArg, deviceMemoryArg},
+                   .outputs = {sharedMemoryArg1, sharedMemoryArg2},
+                   .pools = {sharedMemory1, sharedMemory2, deviceMemory}},
+                  ErrorStatus::NONE);
+}
+
+TEST_P(MemoryDomainExecutionTest, InvalidDimensions) {
+    // FENCED execution does not support dynamic shape.
+    if (kExecutor == Executor::FENCED) return;
+
+    TestOperand testOperand = kTestOperand;
+    testOperand.dimensions[0] = 0;
+    auto preparedModel = createConvPreparedModel(testOperand);
+    auto [buffer, token] = allocateBuffer(preparedModel, {0}, {0}, kTestOperand.dimensions);
+    if (buffer == nullptr) return;
+
+    Request::MemoryPool sharedMemory = createSharedMemoryPool(kTestOperandDataSize);
+    Request::MemoryPool deviceMemory = createDeviceMemoryPool(token);
+    auto badDimensions = kTestOperand.dimensions;
+    badDimensions[0] = 2;
+    RequestArgument sharedMemoryArg = {
+            .location = {.poolIndex = 0, .offset = 0, .length = kTestOperandDataSize},
+            .dimensions = badDimensions};
+    RequestArgument deviceMemoryArg = {.location = {.poolIndex = 1}};
+    RequestArgument deviceMemoryArgWithBadDimensions = {.location = {.poolIndex = 1},
+                                                        .dimensions = badDimensions};
+
+    initializeDeviceMemory(buffer);
+    testExecution(preparedModel,
+                  {.inputs = {deviceMemoryArgWithBadDimensions},
+                   .outputs = {sharedMemoryArg},
+                   .pools = {sharedMemory, deviceMemory}},
+                  ErrorStatus::INVALID_ARGUMENT);
+
+    testExecution(preparedModel,
+                  {.inputs = {sharedMemoryArg},
+                   .outputs = {deviceMemoryArgWithBadDimensions},
+                   .pools = {sharedMemory, deviceMemory}},
+                  ErrorStatus::INVALID_ARGUMENT);
+
+    testExecution(preparedModel,
+                  {.inputs = {sharedMemoryArg},
+                   .outputs = {deviceMemoryArg},
+                   .pools = {sharedMemory, deviceMemory}},
+                  ErrorStatus::GENERAL_FAILURE);
+}
+
+const auto kExecutorChoices = testing::Values(Executor::ASYNC, Executor::SYNC, Executor::FENCED);
+
+std::string printMemoryDomainExecutionTest(
+        const testing::TestParamInfo<MemoryDomainExecutionTestParam>& info) {
+    const auto& [namedDevice, operandType, executor] = info.param;
+    const std::string type = toString(static_cast<OperandType>(operandType));
+    const std::string executorStr = toString(executor);
+    return gtestCompliantName(getName(namedDevice) + "_" + type + "_" + executorStr);
+}
+
+INSTANTIATE_TEST_CASE_P(TestMemoryDomain, MemoryDomainExecutionTest,
+                        testing::Combine(kNamedDeviceChoices, kTestOperandTypeChoices,
+                                         kExecutorChoices),
+                        printMemoryDomainExecutionTest);
+
+}  // namespace android::hardware::neuralnetworks::V1_3::vts::functional
diff --git a/neuralnetworks/1.3/vts/functional/QualityOfServiceTests.cpp b/neuralnetworks/1.3/vts/functional/QualityOfServiceTests.cpp
index 879989e..2ef1e8f 100644
--- a/neuralnetworks/1.3/vts/functional/QualityOfServiceTests.cpp
+++ b/neuralnetworks/1.3/vts/functional/QualityOfServiceTests.cpp
@@ -214,7 +214,8 @@
 }
 
 void runExecutionTest(const sp<IPreparedModel>& preparedModel, const TestModel& testModel,
-                      const Request& request, bool synchronous, DeadlineBoundType deadlineBound) {
+                      const Request& request, const ExecutionContext& context, bool synchronous,
+                      DeadlineBoundType deadlineBound) {
     const ExecutionFunction execute = synchronous ? executeSynchronously : executeAsynchronously;
     const auto deadline = makeDeadline(deadlineBound);
 
@@ -261,7 +262,7 @@
     // Retrieve execution results.
     ASSERT_TRUE(nn::compliantWithV1_0(request));
     const V1_0::Request request10 = nn::convertToV1_0(request);
-    const std::vector<TestBuffer> outputs = getOutputBuffers(request10);
+    const std::vector<TestBuffer> outputs = context.getOutputBuffers(request10);
 
     // We want "close-enough" results.
     if (status == ErrorStatus::NONE) {
@@ -270,10 +271,11 @@
 }
 
 void runExecutionTests(const sp<IPreparedModel>& preparedModel, const TestModel& testModel,
-                       const Request& request) {
+                       const Request& request, const ExecutionContext& context) {
     for (bool synchronous : {false, true}) {
         for (auto deadlineBound : deadlineBounds) {
-            runExecutionTest(preparedModel, testModel, request, synchronous, deadlineBound);
+            runExecutionTest(preparedModel, testModel, request, context, synchronous,
+                             deadlineBound);
         }
     }
 }
@@ -291,8 +293,9 @@
     if (preparedModel == nullptr) return;
 
     // run execution tests
-    const Request request = nn::convertToV1_3(createRequest(testModel));
-    runExecutionTests(preparedModel, testModel, request);
+    ExecutionContext context;
+    const Request request = nn::convertToV1_3(context.createRequest(testModel));
+    runExecutionTests(preparedModel, testModel, request, context);
 }
 
 class DeadlineTest : public GeneratedTestBase {};
diff --git a/neuralnetworks/1.3/vts/functional/ValidateBurst.cpp b/neuralnetworks/1.3/vts/functional/ValidateBurst.cpp
index 6ff9dfd..c78439c 100644
--- a/neuralnetworks/1.3/vts/functional/ValidateBurst.cpp
+++ b/neuralnetworks/1.3/vts/functional/ValidateBurst.cpp
@@ -23,7 +23,6 @@
 #include "ExecutionBurstServer.h"
 #include "GeneratedTestHarness.h"
 #include "TestHarness.h"
-#include "Utils.h"
 
 #include <android-base/logging.h>
 #include <chrono>
@@ -43,6 +42,8 @@
 using V1_2::Timing;
 using ExecutionBurstCallback = ExecutionBurstController::ExecutionBurstCallback;
 
+using BurstExecutionMutation = std::function<void(std::vector<FmqRequestDatum>*)>;
+
 // This constant value represents the length of an FMQ that is large enough to
 // return a result from a burst execution for all of the generated test cases.
 constexpr size_t kExecutionBurstChannelLength = 1024;
@@ -122,13 +123,13 @@
 
 // Primary validation function. This function will take a valid serialized
 // request, apply a mutation to it to invalidate the serialized request, then
-// pass it to interface calls that use the serialized request. Note that the
-// serialized request here is passed by value, and any mutation to the
-// serialized request does not leave this function.
+// pass it to interface calls that use the serialized request.
 static void validate(RequestChannelSender* sender, ResultChannelReceiver* receiver,
-                     const std::string& message, std::vector<FmqRequestDatum> serialized,
-                     const std::function<void(std::vector<FmqRequestDatum>*)>& mutation) {
-    mutation(&serialized);
+                     const std::string& message,
+                     const std::vector<FmqRequestDatum>& originalSerialized,
+                     const BurstExecutionMutation& mutate) {
+    std::vector<FmqRequestDatum> serialized = originalSerialized;
+    mutate(&serialized);
 
     // skip if packet is too large to send
     if (serialized.size() > kExecutionBurstChannelLength) {
@@ -302,8 +303,7 @@
     // collect serialized result by running regular burst
     const auto [nRegular, outputShapesRegular, timingRegular, fallbackRegular] =
             controllerRegular->compute(request, MeasureTiming::NO, keys);
-    const V1_0::ErrorStatus statusRegular =
-            nn::convertToV1_0(nn::convertResultCodeToErrorStatus(nRegular));
+    const V1_0::ErrorStatus statusRegular = nn::legacyConvertResultCodeToErrorStatus(nRegular);
     EXPECT_FALSE(fallbackRegular);
 
     // skip test if regular burst output isn't useful for testing a failure
@@ -319,8 +319,7 @@
     // large enough to return the serialized result
     const auto [nSmall, outputShapesSmall, timingSmall, fallbackSmall] =
             controllerSmall->compute(request, MeasureTiming::NO, keys);
-    const V1_0::ErrorStatus statusSmall =
-            nn::convertToV1_0(nn::convertResultCodeToErrorStatus(nSmall));
+    const V1_0::ErrorStatus statusSmall = nn::legacyConvertResultCodeToErrorStatus(nSmall);
     EXPECT_NE(V1_0::ErrorStatus::NONE, statusSmall);
     EXPECT_EQ(0u, outputShapesSmall.size());
     EXPECT_TRUE(badTiming(timingSmall));
diff --git a/neuralnetworks/1.3/vts/functional/ValidateModel.cpp b/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
index 7da2da9..4c0100e 100644
--- a/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
@@ -30,6 +30,8 @@
 using HidlToken =
         hidl_array<uint8_t, static_cast<uint32_t>(V1_2::Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
 
+using PrepareModelMutation = std::function<void(Model*, ExecutionPreference*, Priority*)>;
+
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
 static void validateGetSupportedOperations(const sp<IDevice>& device, const std::string& message,
@@ -44,13 +46,14 @@
 }
 
 static void validatePrepareModel(const sp<IDevice>& device, const std::string& message,
-                                 const Model& model, ExecutionPreference preference) {
+                                 const Model& model, ExecutionPreference preference,
+                                 Priority priority) {
     SCOPED_TRACE(message + " [prepareModel_1_3]");
 
     sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel_1_3(
-            model, preference, kDefaultPriority, {}, hidl_vec<hidl_handle>(),
-            hidl_vec<hidl_handle>(), HidlToken(), preparedModelCallback);
+    Return<ErrorStatus> prepareLaunchStatus =
+            device->prepareModel_1_3(model, preference, priority, {}, hidl_vec<hidl_handle>(),
+                                     hidl_vec<hidl_handle>(), HidlToken(), preparedModelCallback);
     ASSERT_TRUE(prepareLaunchStatus.isOk());
     ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
 
@@ -67,18 +70,26 @@
            preference == ExecutionPreference::SUSTAINED_SPEED;
 }
 
+static bool validExecutionPriority(Priority priority) {
+    return priority == Priority::LOW || priority == Priority::MEDIUM || priority == Priority::HIGH;
+}
+
 // Primary validation function. This function will take a valid model, apply a
-// mutation to it to invalidate the model, then pass it to interface calls that
-// use the model. Note that the model here is passed by value, and any mutation
-// to the model does not leave this function.
-static void validate(const sp<IDevice>& device, const std::string& message, Model model,
-                     const std::function<void(Model*)>& mutation,
-                     ExecutionPreference preference = ExecutionPreference::FAST_SINGLE_ANSWER) {
-    mutation(&model);
-    if (validExecutionPreference(preference)) {
+// mutation to invalidate the model, the execution preference, or the priority,
+// then pass these to supportedOperations and/or prepareModel if that method is
+// called with an invalid argument.
+static void validate(const sp<IDevice>& device, const std::string& message,
+                     const Model& originalModel, const PrepareModelMutation& mutate) {
+    Model model = originalModel;
+    ExecutionPreference preference = ExecutionPreference::FAST_SINGLE_ANSWER;
+    Priority priority = kDefaultPriority;
+    mutate(&model, &preference, &priority);
+
+    if (validExecutionPreference(preference) && validExecutionPriority(priority)) {
         validateGetSupportedOperations(device, message, model);
     }
-    validatePrepareModel(device, message, model, preference);
+
+    validatePrepareModel(device, message, model, preference, priority);
 }
 
 static uint32_t addOperand(Model* model) {
@@ -116,9 +127,11 @@
             const std::string message = "mutateOperandTypeTest: operand " +
                                         std::to_string(operand) + " set to value " +
                                         std::to_string(invalidOperandType);
-            validate(device, message, model, [operand, invalidOperandType](Model* model) {
-                model->main.operands[operand].type = static_cast<OperandType>(invalidOperandType);
-            });
+            validate(device, message, model,
+                     [operand, invalidOperandType](Model* model, ExecutionPreference*, Priority*) {
+                         model->main.operands[operand].type =
+                                 static_cast<OperandType>(invalidOperandType);
+                     });
         }
     }
 }
@@ -156,9 +169,11 @@
         }
         const std::string message = "mutateOperandRankTest: operand " + std::to_string(operand) +
                                     " has rank of " + std::to_string(invalidRank);
-        validate(device, message, model, [operand, invalidRank](Model* model) {
-            model->main.operands[operand].dimensions = std::vector<uint32_t>(invalidRank, 0);
-        });
+        validate(device, message, model,
+                 [operand, invalidRank](Model* model, ExecutionPreference*, Priority*) {
+                     model->main.operands[operand].dimensions =
+                             std::vector<uint32_t>(invalidRank, 0);
+                 });
     }
 }
 
@@ -194,9 +209,10 @@
         const float invalidScale = getInvalidScale(model.main.operands[operand].type);
         const std::string message = "mutateOperandScaleTest: operand " + std::to_string(operand) +
                                     " has scale of " + std::to_string(invalidScale);
-        validate(device, message, model, [operand, invalidScale](Model* model) {
-            model->main.operands[operand].scale = invalidScale;
-        });
+        validate(device, message, model,
+                 [operand, invalidScale](Model* model, ExecutionPreference*, Priority*) {
+                     model->main.operands[operand].scale = invalidScale;
+                 });
     }
 }
 
@@ -237,9 +253,10 @@
             const std::string message = "mutateOperandZeroPointTest: operand " +
                                         std::to_string(operand) + " has zero point of " +
                                         std::to_string(invalidZeroPoint);
-            validate(device, message, model, [operand, invalidZeroPoint](Model* model) {
-                model->main.operands[operand].zeroPoint = invalidZeroPoint;
-            });
+            validate(device, message, model,
+                     [operand, invalidZeroPoint](Model* model, ExecutionPreference*, Priority*) {
+                         model->main.operands[operand].zeroPoint = invalidZeroPoint;
+                     });
         }
     }
 }
@@ -425,9 +442,10 @@
             const std::string message = "mutateOperationOperandTypeTest: operand " +
                                         std::to_string(operand) + " set to type " +
                                         toString(invalidOperandType);
-            validate(device, message, model, [operand, invalidOperandType](Model* model) {
-                mutateOperand(&model->main.operands[operand], invalidOperandType);
-            });
+            validate(device, message, model,
+                     [operand, invalidOperandType](Model* model, ExecutionPreference*, Priority*) {
+                         mutateOperand(&model->main.operands[operand], invalidOperandType);
+                     });
         }
     }
 }
@@ -446,10 +464,12 @@
             const std::string message = "mutateOperationTypeTest: operation " +
                                         std::to_string(operation) + " set to value " +
                                         std::to_string(invalidOperationType);
-            validate(device, message, model, [operation, invalidOperationType](Model* model) {
-                model->main.operations[operation].type =
-                        static_cast<OperationType>(invalidOperationType);
-            });
+            validate(device, message, model,
+                     [operation, invalidOperationType](Model* model, ExecutionPreference*,
+                                                       Priority*) {
+                         model->main.operations[operation].type =
+                                 static_cast<OperationType>(invalidOperationType);
+                     });
         }
     }
 }
@@ -463,9 +483,11 @@
             const std::string message = "mutateOperationInputOperandIndexTest: operation " +
                                         std::to_string(operation) + " input " +
                                         std::to_string(input);
-            validate(device, message, model, [operation, input, invalidOperand](Model* model) {
-                model->main.operations[operation].inputs[input] = invalidOperand;
-            });
+            validate(device, message, model,
+                     [operation, input, invalidOperand](Model* model, ExecutionPreference*,
+                                                        Priority*) {
+                         model->main.operations[operation].inputs[input] = invalidOperand;
+                     });
         }
     }
 }
@@ -480,9 +502,11 @@
             const std::string message = "mutateOperationOutputOperandIndexTest: operation " +
                                         std::to_string(operation) + " output " +
                                         std::to_string(output);
-            validate(device, message, model, [operation, output, invalidOperand](Model* model) {
-                model->main.operations[operation].outputs[output] = invalidOperand;
-            });
+            validate(device, message, model,
+                     [operation, output, invalidOperand](Model* model, ExecutionPreference*,
+                                                         Priority*) {
+                         model->main.operations[operation].outputs[output] = invalidOperand;
+                     });
         }
     }
 }
@@ -548,8 +572,9 @@
             continue;
         }
         const std::string message = "removeOperandTest: operand " + std::to_string(operand);
-        validate(device, message, model,
-                 [operand](Model* model) { removeOperand(model, operand); });
+        validate(device, message, model, [operand](Model* model, ExecutionPreference*, Priority*) {
+            removeOperand(model, operand);
+        });
     }
 }
 
@@ -566,7 +591,9 @@
     for (size_t operation = 0; operation < model.main.operations.size(); ++operation) {
         const std::string message = "removeOperationTest: operation " + std::to_string(operation);
         validate(device, message, model,
-                 [operation](Model* model) { removeOperation(model, operation); });
+                 [operation](Model* model, ExecutionPreference*, Priority*) {
+                     removeOperation(model, operation);
+                 });
     }
 }
 
@@ -654,11 +681,12 @@
             const std::string message = "removeOperationInputTest: operation " +
                                         std::to_string(operation) + ", input " +
                                         std::to_string(input);
-            validate(device, message, model, [operation, input](Model* model) {
-                uint32_t operand = model->main.operations[operation].inputs[input];
-                model->main.operands[operand].numberOfConsumers--;
-                hidl_vec_removeAt(&model->main.operations[operation].inputs, input);
-            });
+            validate(device, message, model,
+                     [operation, input](Model* model, ExecutionPreference*, Priority*) {
+                         uint32_t operand = model->main.operations[operation].inputs[input];
+                         model->main.operands[operand].numberOfConsumers--;
+                         hidl_vec_removeAt(&model->main.operations[operation].inputs, input);
+                     });
         }
     }
 }
@@ -672,9 +700,10 @@
             const std::string message = "removeOperationOutputTest: operation " +
                                         std::to_string(operation) + ", output " +
                                         std::to_string(output);
-            validate(device, message, model, [operation, output](Model* model) {
-                hidl_vec_removeAt(&model->main.operations[operation].outputs, output);
-            });
+            validate(device, message, model,
+                     [operation, output](Model* model, ExecutionPreference*, Priority*) {
+                         hidl_vec_removeAt(&model->main.operations[operation].outputs, output);
+                     });
         }
     }
 }
@@ -707,11 +736,12 @@
             continue;
         }
         const std::string message = "addOperationInputTest: operation " + std::to_string(operation);
-        validate(device, message, model, [operation](Model* model) {
-            uint32_t index = addOperand(model, OperandLifeTime::SUBGRAPH_INPUT);
-            hidl_vec_push_back(&model->main.operations[operation].inputs, index);
-            hidl_vec_push_back(&model->main.inputIndexes, index);
-        });
+        validate(device, message, model,
+                 [operation](Model* model, ExecutionPreference*, Priority*) {
+                     uint32_t index = addOperand(model, OperandLifeTime::SUBGRAPH_INPUT);
+                     hidl_vec_push_back(&model->main.operations[operation].inputs, index);
+                     hidl_vec_push_back(&model->main.inputIndexes, index);
+                 });
     }
 }
 
@@ -721,11 +751,12 @@
     for (size_t operation = 0; operation < model.main.operations.size(); ++operation) {
         const std::string message =
                 "addOperationOutputTest: operation " + std::to_string(operation);
-        validate(device, message, model, [operation](Model* model) {
-            uint32_t index = addOperand(model, OperandLifeTime::SUBGRAPH_OUTPUT);
-            hidl_vec_push_back(&model->main.operations[operation].outputs, index);
-            hidl_vec_push_back(&model->main.outputIndexes, index);
-        });
+        validate(device, message, model,
+                 [operation](Model* model, ExecutionPreference*, Priority*) {
+                     uint32_t index = addOperand(model, OperandLifeTime::SUBGRAPH_OUTPUT);
+                     hidl_vec_push_back(&model->main.operations[operation].outputs, index);
+                     hidl_vec_push_back(&model->main.outputIndexes, index);
+                 });
     }
 }
 
@@ -737,12 +768,31 @@
 };
 
 static void mutateExecutionPreferenceTest(const sp<IDevice>& device, const Model& model) {
-    for (int32_t preference : invalidExecutionPreferences) {
+    for (int32_t invalidPreference : invalidExecutionPreferences) {
         const std::string message =
-                "mutateExecutionPreferenceTest: preference " + std::to_string(preference);
-        validate(
-                device, message, model, [](Model*) {},
-                static_cast<ExecutionPreference>(preference));
+                "mutateExecutionPreferenceTest: preference " + std::to_string(invalidPreference);
+        validate(device, message, model,
+                 [invalidPreference](Model*, ExecutionPreference* preference, Priority*) {
+                     *preference = static_cast<ExecutionPreference>(invalidPreference);
+                 });
+    }
+}
+
+///////////////////////// VALIDATE PRIORITY /////////////////////////
+
+static const int32_t invalidPriorities[] = {
+        static_cast<int32_t>(Priority::LOW) - 1,   // lower bound
+        static_cast<int32_t>(Priority::HIGH) + 1,  // upper bound
+};
+
+static void mutateExecutionPriorityTest(const sp<IDevice>& device, const Model& model) {
+    for (int32_t invalidPriority : invalidPriorities) {
+        const std::string message =
+                "mutatePriorityTest: priority " + std::to_string(invalidPriority);
+        validate(device, message, model,
+                 [invalidPriority](Model*, ExecutionPreference*, Priority* priority) {
+                     *priority = static_cast<Priority>(invalidPriority);
+                 });
     }
 }
 
@@ -764,6 +814,7 @@
     addOperationInputTest(device, model);
     addOperationOutputTest(device, model);
     mutateExecutionPreferenceTest(device, model);
+    mutateExecutionPriorityTest(device, model);
 }
 
 }  // namespace android::hardware::neuralnetworks::V1_3::vts::functional
diff --git a/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
index 5e806e5..1ae8b3f 100644
--- a/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
@@ -34,6 +34,8 @@
 using V1_2::OutputShape;
 using V1_2::Timing;
 
+using ExecutionMutation = std::function<void(Request*)>;
+
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
 static bool badTiming(Timing timing) {
@@ -42,11 +44,11 @@
 
 // Primary validation function. This function will take a valid request, apply a
 // mutation to it to invalidate the request, then pass it to interface calls
-// that use the request. Note that the request here is passed by value, and any
-// mutation to the request does not leave this function.
+// that use the request.
 static void validate(const sp<IPreparedModel>& preparedModel, const std::string& message,
-                     Request request, const std::function<void(Request*)>& mutation) {
-    mutation(&request);
+                     const Request& originalRequest, const ExecutionMutation& mutate) {
+    Request request = originalRequest;
+    mutate(&request);
 
     // We'd like to test both with timing requested and without timing
     // requested. Rather than running each test both ways, we'll decide whether
diff --git a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp
index 5b07034..df1e453 100644
--- a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp
@@ -177,7 +177,8 @@
 
 TEST_P(ValidationTest, Test) {
     const Model model = createModel(kTestModel);
-    const Request request = nn::convertToV1_3(createRequest(kTestModel));
+    ExecutionContext context;
+    const Request request = nn::convertToV1_3(context.createRequest(kTestModel));
     if (kTestModel.expectFailure) {
         validateFailure(kDevice, model, request);
     } else {
@@ -185,11 +186,31 @@
     }
 }
 
-INSTANTIATE_GENERATED_TEST(ValidationTest, [](const test_helper::TestModel&) { return true; });
+INSTANTIATE_GENERATED_TEST(ValidationTest, [](const std::string& testName) {
+    // Skip validation for the "inputs_as_internal" and "all_tensors_as_inputs"
+    // generated tests.
+    return testName.find("inputs_as_internal") == std::string::npos &&
+           testName.find("all_tensors_as_inputs") == std::string::npos;
+});
 
 sp<IPreparedModel> getPreparedModel_1_3(const sp<PreparedModelCallback>& callback) {
     sp<V1_0::IPreparedModel> preparedModelV1_0 = callback->getPreparedModel();
     return IPreparedModel::castFrom(preparedModelV1_0).withDefault(nullptr);
 }
 
+std::string toString(Executor executor) {
+    switch (executor) {
+        case Executor::ASYNC:
+            return "ASYNC";
+        case Executor::SYNC:
+            return "SYNC";
+        case Executor::BURST:
+            return "BURST";
+        case Executor::FENCED:
+            return "FENCED";
+        default:
+            CHECK(false);
+    }
+}
+
 }  // namespace android::hardware::neuralnetworks::V1_3::vts::functional
diff --git a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h
index 4e51052..de082c3 100644
--- a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h
@@ -52,6 +52,10 @@
 // Utility function to get PreparedModel from callback and downcast to V1_2.
 sp<IPreparedModel> getPreparedModel_1_3(const sp<implementation::PreparedModelCallback>& callback);
 
+enum class Executor { ASYNC, SYNC, BURST, FENCED };
+
+std::string toString(Executor executor);
+
 }  // namespace android::hardware::neuralnetworks::V1_3::vts::functional
 
 #endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_3_VTS_HAL_NEURALNETWORKS_H
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl
new file mode 100644
index 0000000..aced215
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@Backing(type="int") @VintfStability
+enum Boost {
+  INTERACTION = 0,
+  DISPLAY_UPDATE_IMMINENT = 1,
+  ML_ACC = 2,
+  AUDIO_LAUNCH = 3,
+  CAMERA_LAUNCH = 4,
+  CAMERA_SHOT = 5,
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl
new file mode 100644
index 0000000..8a06623
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@VintfStability
+interface IPower {
+  oneway void setMode(in android.hardware.power.Mode type, in boolean enabled);
+  boolean isModeSupported(in android.hardware.power.Mode type);
+  oneway void setBoost(in android.hardware.power.Boost type, in int durationMs);
+  boolean isBoostSupported(in android.hardware.power.Boost type);
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl
new file mode 100644
index 0000000..f7c2552
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl
@@ -0,0 +1,36 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@Backing(type="int") @VintfStability
+enum Mode {
+  DOUBLE_TAP_TO_WAKE = 0,
+  LOW_POWER = 1,
+  SUSTAINED_PERFORMANCE = 2,
+  FIXED_PERFORMANCE = 3,
+  VR = 4,
+  LAUNCH = 5,
+  EXPENSIVE_RENDERING = 6,
+  INTERACTIVE = 7,
+  DEVICE_IDLE = 8,
+  DISPLAY_INACTIVE = 9,
+  AUDIO_STREAMING_LOW_LATENCY = 10,
+  CAMERA_STREAMING_SECURE = 11,
+  CAMERA_STREAMING_LOW = 12,
+  CAMERA_STREAMING_MID = 13,
+  CAMERA_STREAMING_HIGH = 14,
+}
diff --git a/radio/1.5/types.hal b/radio/1.5/types.hal
index 45f3b90..b061bd5 100644
--- a/radio/1.5/types.hal
+++ b/radio/1.5/types.hal
@@ -203,6 +203,9 @@
     vec<int32_t> channels;
 };
 
+/**
+ * IRadio 1.5 supports NGRAN bands up to V16.2.0
+ */
 enum NgranBands : int32_t {
     /** 3GPP TS 38.101-1, Table 5.2-1: FR1 bands */
     BAND_1 = 1,
@@ -243,7 +246,13 @@
     BAND_83 = 83,
     BAND_84 = 84,
     BAND_86 = 86,
+    BAND_89 = 89,
     BAND_90 = 90,
+    BAND_91 = 91,
+    BAND_92 = 92,
+    BAND_93 = 93,
+    BAND_94 = 94,
+    BAND_95 = 95,
     /** 3GPP TS 38.101-2, Table 5.2-1: FR2 bands */
     BAND_257 = 257,
     BAND_258 = 258,
@@ -251,6 +260,10 @@
     BAND_261 = 261,
 };
 
+/**
+ * Extended from @1.1 UtranBands to add TD-SCDMA bands
+ * IRadio 1.5 supports UTRAN bands up to V15.0.0
+ */
 enum UtranBands : @1.1::UtranBands {
     /** TD-SCDMA bands. 3GPP TS 25.102, Table 5.2: Frequency bands */
     BAND_A = 101,
@@ -262,6 +275,25 @@
 };
 
 /**
+ * Extended from @1.1 EutranBands to add more bands from 3GPP TS 36.101, Table 5.5: Operating bands
+ * IRadio 1.5 supports EUTRAN bands up to V16.4.0
+ */
+enum EutranBands : @1.1::EutranBands {
+    BAND_49 = 49,
+    BAND_50 = 50,
+    BAND_51 = 51,
+    BAND_52 = 52,
+    BAND_53 = 53,
+    BAND_71 = 71,
+    BAND_72 = 72,
+    BAND_73 = 73,
+    BAND_74 = 74,
+    BAND_85 = 85,
+    BAND_87 = 87,
+    BAND_88 = 88,
+};
+
+/**
  * Overwritten from @1.2::NetworkScanRequest to update RadioAccessSpecifier to 1.5 version.
  */
 struct NetworkScanRequest {
@@ -1023,16 +1055,37 @@
  * 3GPP2 C.S0068-0.
  */
 enum PersoSubstate : @1.0::PersoSubstate {
+    /**
+     * The device is personalized using the content of the Service Provider Name (SPN) in the SIM
+     * card.
+     */
     SIM_SPN,
     SIM_SPN_PUK,
-    /** Equivalent Home PLMN */
+    /**
+     * Service Provider and Equivalent Home PLMN
+     * The device is personalized using both the content of the GID1 (equivalent to service provider
+     * personalization) and the content of the Equivalent Home PLMN (EHPLMN) in the SIM card.
+     * If the GID1 in the SIM is absent, then just the content of the Equivalent Home PLMN
+     * is matched.
+     */
     SIM_SP_EHPLMN,
     SIM_SP_EHPLMN_PUK,
+    /**
+     * Device is personalized using the first digits of the ICCID of the SIM card.
+     */
     SIM_ICCID,
     SIM_ICCID_PUK,
+    /**
+     * Device is personalized using the content of the IMPI in the ISIM.
+     */
     SIM_IMPI,
     SIM_IMPI_PUK,
-    /** Network subset service provider */
+    /**
+     * Network Subset and Service Provider
+     * Device is personalized using both the content of GID1 (equivalent to service provider
+     * personalization) and the first digits of the IMSI (equivalent to network subset
+     * personalization).
+     */
     SIM_NS_SP,
     SIM_NS_SP_PUK,
 };
diff --git a/rebootescrow/aidl/aidl_api/android.hardware.rebootescrow/current/android/hardware/rebootescrow/IRebootEscrow.aidl b/rebootescrow/aidl/aidl_api/android.hardware.rebootescrow/current/android/hardware/rebootescrow/IRebootEscrow.aidl
new file mode 100644
index 0000000..ea669a3
--- /dev/null
+++ b/rebootescrow/aidl/aidl_api/android.hardware.rebootescrow/current/android/hardware/rebootescrow/IRebootEscrow.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.rebootescrow;
+@VintfStability
+interface IRebootEscrow {
+  void storeKey(in byte[] kek);
+  byte[] retrieveKey();
+}
diff --git a/rebootescrow/aidl/default/HadamardUtils.cpp b/rebootescrow/aidl/default/HadamardUtils.cpp
index d2422b9..adb2010 100644
--- a/rebootescrow/aidl/default/HadamardUtils.cpp
+++ b/rebootescrow/aidl/default/HadamardUtils.cpp
@@ -16,8 +16,6 @@
 
 #include <HadamardUtils.h>
 
-#include <limits>
-
 #include <android-base/logging.h>
 
 namespace aidl {
@@ -92,6 +90,31 @@
     return result;
 }
 
+// Constant-time conditional copy, to fix b/146520538
+// ctl must be 0 or 1; we do the copy if it's 1.
+static void CondCopy(uint32_t ctl, void* dest, const void* src, size_t len) {
+    const auto cdest = reinterpret_cast<uint8_t*>(dest);
+    const auto csrc = reinterpret_cast<const uint8_t*>(src);
+    for (size_t i = 0; i < len; i++) {
+        const uint32_t d = cdest[i];
+        const uint32_t s = csrc[i];
+        cdest[i] = d ^ (-ctl & (s ^ d));
+    }
+}
+
+struct CodewordWinner {
+    uint16_t codeword;
+    int32_t score;
+};
+
+// Replace dest with src if it has a higher score
+static void CopyWinner(CodewordWinner* dest, const CodewordWinner& src) {
+    // Scores are between - 2^15 and 2^15, so taking the difference won't
+    // overflow; we use the sign bit of the difference here.
+    CondCopy(static_cast<uint32_t>(dest->score - src.score) >> 31, dest, &src,
+             sizeof(CodewordWinner));
+}
+
 // Decode a single codeword. Because of the way codewords are striped together
 // this takes the entire input, plus an offset telling it which word to decode.
 static uint16_t DecodeWord(size_t word, const std::vector<uint8_t>& encoded) {
@@ -118,20 +141,15 @@
             }
         }
     }
-    auto hiscore = std::numeric_limits<int32_t>::min();
-    uint16_t winner;
-    // TODO(b/146520538): this needs to be constant time
+    // -ENCODE_LENGTH is least possible score, so start one less than that
+    auto best = CodewordWinner{0, -static_cast<int32_t>(ENCODE_LENGTH + 1)};
+    // For every possible codeword value, look at its score, and replace best if it's higher,
+    // in constant time.
     for (size_t i = 0; i < ENCODE_LENGTH; i++) {
-        if (scores[i] > hiscore) {
-            winner = i;
-            hiscore = scores[i];
-
-        } else if (-scores[i] > hiscore) {
-            winner = i | (1 << CODE_K);
-            hiscore = -scores[i];
-        }
+        CopyWinner(&best, CodewordWinner{static_cast<uint16_t>(i), scores[i]});
+        CopyWinner(&best, CodewordWinner{static_cast<uint16_t>(i | (1 << CODE_K)), -scores[i]});
     }
-    return winner;
+    return best.codeword;
 }
 
 std::vector<uint8_t> DecodeKey(const std::vector<uint8_t>& shuffled) {
diff --git a/sensors/2.0/multihal/Android.bp b/sensors/2.0/multihal/Android.bp
index 7213b44..3ce3390 100644
--- a/sensors/2.0/multihal/Android.bp
+++ b/sensors/2.0/multihal/Android.bp
@@ -28,6 +28,7 @@
     shared_libs: [
         "android.hardware.sensors@2.0",
         "android.hardware.sensors@2.0-ScopedWakelock",
+        "android.hardware.sensors@2.1",
         "libbase",
         "libcutils",
         "libfmq",
diff --git a/sensors/common/default/2.X/multihal/Android.bp b/sensors/common/default/2.X/multihal/Android.bp
index 2b4b3bf..6122323 100644
--- a/sensors/common/default/2.X/multihal/Android.bp
+++ b/sensors/common/default/2.X/multihal/Android.bp
@@ -16,11 +16,12 @@
 cc_defaults {
     name: "android.hardware.sensors@2.X-multihal-defaults",
     header_libs: [
-        "android.hardware.sensors@2.0-multihal.header",
+        "android.hardware.sensors@2.X-multihal.header",
     ],
     shared_libs: [
         "android.hardware.sensors@1.0",
         "android.hardware.sensors@2.0",
+        "android.hardware.sensors@2.1",
         "libbase",
         "libcutils",
         "libfmq",
@@ -32,9 +33,24 @@
     cflags: ["-DLOG_TAG=\"SensorsMultiHal\""],
 }
 
+// Header target for sub-HALs that implement the Multi-HAL 2.0 interface
 cc_library_headers {
     name: "android.hardware.sensors@2.0-multihal.header",
     vendor_available: true,
+    export_include_dirs: ["include/V2_0"],
+}
+
+// Header target for sub-HALs that implement the Multi-HAL 2.1 interface
+cc_library_headers {
+    name: "android.hardware.sensors@2.1-multihal.header",
+    vendor_available: true,
+    export_include_dirs: ["include/V2_1"],
+}
+
+// Header target for Multi-HAL so it can reference both 2.0/2.1 headers
+cc_library_headers {
+    name: "android.hardware.sensors@2.X-multihal.header",
+    vendor_available: true,
     export_include_dirs: ["include"],
 }
 
@@ -49,7 +65,7 @@
     ],
     vendor_available: true,
     export_header_lib_headers: [
-        "android.hardware.sensors@2.0-multihal.header",
+        "android.hardware.sensors@2.X-multihal.header",
     ],
 }
 
@@ -62,6 +78,9 @@
     srcs: [
         "ScopedWakelock.cpp",
     ],
+    header_libs: [
+        "android.hardware.sensors@2.0-multihal.header",
+    ],
     vendor_available: true,
     export_header_lib_headers: [
         "android.hardware.sensors@2.0-multihal.header",
@@ -78,6 +97,9 @@
         "ScopedWakelock.cpp",
     ],
     vendor_available: true,
+    header_libs: [
+        "android.hardware.sensors@2.0-multihal.header",
+    ],
     export_header_lib_headers: [
         "android.hardware.sensors@2.0-multihal.header",
     ],
diff --git a/sensors/common/default/2.X/multihal/HalProxy.cpp b/sensors/common/default/2.X/multihal/HalProxy.cpp
index ac6f17a..518e138 100644
--- a/sensors/common/default/2.X/multihal/HalProxy.cpp
+++ b/sensors/common/default/2.X/multihal/HalProxy.cpp
@@ -16,8 +16,6 @@
 
 #include "HalProxy.h"
 
-#include "SubHal.h"
-
 #include <android/hardware/sensors/2.0/types.h>
 
 #include <android-base/file.h>
diff --git a/sensors/common/default/2.X/multihal/ScopedWakelock.cpp b/sensors/common/default/2.X/multihal/ScopedWakelock.cpp
index d85d4a7..bf2ad35 100644
--- a/sensors/common/default/2.X/multihal/ScopedWakelock.cpp
+++ b/sensors/common/default/2.X/multihal/ScopedWakelock.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "ScopedWakelock.h"
+#include "V2_0/ScopedWakelock.h"
 
 namespace android {
 namespace hardware {
diff --git a/sensors/common/default/2.X/multihal/include/HalProxy.h b/sensors/common/default/2.X/multihal/include/HalProxy.h
index 978f7cf..d7e8795 100644
--- a/sensors/common/default/2.X/multihal/include/HalProxy.h
+++ b/sensors/common/default/2.X/multihal/include/HalProxy.h
@@ -16,8 +16,9 @@
 
 #pragma once
 
-#include "ScopedWakelock.h"
-#include "SubHal.h"
+#include "V2_0/ScopedWakelock.h"
+#include "V2_0/SubHal.h"
+#include "V2_1/SubHal.h"
 
 #include <android/hardware/sensors/2.0/ISensors.h>
 #include <android/hardware/sensors/2.0/types.h>
diff --git a/sensors/common/default/2.X/multihal/include/ScopedWakelock.h b/sensors/common/default/2.X/multihal/include/V2_0/ScopedWakelock.h
similarity index 100%
rename from sensors/common/default/2.X/multihal/include/ScopedWakelock.h
rename to sensors/common/default/2.X/multihal/include/V2_0/ScopedWakelock.h
diff --git a/sensors/common/default/2.X/multihal/include/SubHal.h b/sensors/common/default/2.X/multihal/include/V2_0/SubHal.h
similarity index 99%
rename from sensors/common/default/2.X/multihal/include/SubHal.h
rename to sensors/common/default/2.X/multihal/include/V2_0/SubHal.h
index 92ae3a6..2a80e6b 100644
--- a/sensors/common/default/2.X/multihal/include/SubHal.h
+++ b/sensors/common/default/2.X/multihal/include/V2_0/SubHal.h
@@ -159,7 +159,7 @@
  * library. This function will only be invoked once at initialization time.
  *
  * NOTE: The supported sensors HAL version must match SUB_HAL_2_0_VERSION exactly or the HalProxy
- * will fail to initialize.
+ *     will fail to initialize.
  *
  * @param uint32_t when this function returns, this parameter must contain the HAL version that
  *     this sub-HAL supports. To support this version of multi-HAL, this must be set to
diff --git a/sensors/common/default/2.X/multihal/include/SubHal.h b/sensors/common/default/2.X/multihal/include/V2_1/SubHal.h
similarity index 78%
copy from sensors/common/default/2.X/multihal/include/SubHal.h
copy to sensors/common/default/2.X/multihal/include/V2_1/SubHal.h
index 92ae3a6..cd49422 100644
--- a/sensors/common/default/2.X/multihal/include/SubHal.h
+++ b/sensors/common/default/2.X/multihal/include/V2_1/SubHal.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -16,27 +16,23 @@
 
 #pragma once
 
-#include "ScopedWakelock.h"
+#include "V2_0/ScopedWakelock.h"
 
-#include <android/hardware/sensors/1.0/types.h>
-#include <android/hardware/sensors/2.0/ISensors.h>
+#include <android/hardware/sensors/2.1/ISensors.h>
+#include <android/hardware/sensors/2.1/types.h>
 
 #include <vector>
 
 // Indicates the current version of the multiHAL interface formatted as (HAL major version) << 24 |
 // (HAL minor version) << 16 | (multiHAL version)
-#define SUB_HAL_2_0_VERSION 0x02000000
+#define SUB_HAL_2_1_VERSION 0x02010000
 
 namespace android {
 namespace hardware {
 namespace sensors {
-namespace V2_0 {
+namespace V2_1 {
 namespace implementation {
 
-using ::android::hardware::sensors::V1_0::Event;
-using ::android::hardware::sensors::V1_0::Result;
-using ::android::hardware::sensors::V1_0::SensorInfo;
-
 /**
  * Interface that contains several callbacks into the HalProxy class to communicate dynamic sensor
  * changes and sensor events to the framework and acquire wake locks. The HalProxy will ensure
@@ -45,6 +41,8 @@
  */
 class IHalProxyCallback : public ISensorsCallback {
   public:
+    using ScopedWakelock = V2_0::implementation::ScopedWakelock;
+
     /**
      * Thread-safe callback used to post events to the HalProxy. Sub-HALs should invoke this
      * whenever new sensor events need to be delivered to the sensors framework. Once invoked, the
@@ -55,7 +53,7 @@
      *
      * The provided ScopedWakelock must be locked if the events are from wakeup sensors. If it's
      * not locked accordingly, the HalProxy will crash as this indicates the sub-HAL isn't compliant
-     * with the sensors HAL 2.0 specification. Additionally, since ScopedWakelock isn't copyable,
+     * with the sensors HAL specification. Additionally, since ScopedWakelock isn't copyable,
      * the HalProxy will take ownership of the wake lock given when this method is invoked. Once the
      * method returns, the HalProxy will handle holding the wake lock, if necessary, until the
      * framework has successfully processed any wakeup events.
@@ -71,7 +69,7 @@
      * @param wakelock ScopedWakelock that should be locked to send events from wake sensors and
      *     unlocked otherwise.
      */
-    virtual void postEvents(const std::vector<Event>& events, ScopedWakelock wakelock) = 0;
+    virtual void postEvents(const std::vector<V2_1::Event>& events, ScopedWakelock wakelock) = 0;
 
     /**
      * Initializes a ScopedWakelock on the stack that, when locked, will increment the reference
@@ -86,9 +84,9 @@
 
 /**
  * ISensorsSubHal is an interface that sub-HALs must implement in order to be compliant with
- * multihal 2.0 and in order for the HalProxy to successfully load and communicate with the sub-HAL.
+ * multihal and in order for the HalProxy to successfully load and communicate with the sub-HAL.
  *
- * Any vendor wishing to implement this interface and support multihal 2.0 will need to create a
+ * Any vendor wishing to implement this interface and support multihal will need to create a
  * dynamic library that exposes sensorsHalGetSubHal (defined below). This library will be loaded by
  * the HalProxy when the sensors HAL is initialized and then the HalProxy will retrieve the vendor's
  * implementation of sensorsHalGetSubHal.
@@ -103,11 +101,25 @@
   public:
     // The ISensors version of initialize isn't used for multihal. Instead, sub-HALs must implement
     // the version below to allow communciation logic to centralized in the HalProxy
-    Return<Result> initialize(
-            const ::android::hardware::MQDescriptorSync<Event>& /* eventQueueDescriptor */,
+    Return<V1_0::Result> initialize_2_1(
+            const ::android::hardware::MQDescriptorSync<V2_1::Event>& /* eventQueueDescriptor */,
             const ::android::hardware::MQDescriptorSync<uint32_t>& /* wakeLockDescriptor */,
             const sp<ISensorsCallback>& /* sensorsCallback */) final {
-        return Result::INVALID_OPERATION;
+        return V1_0::Result::INVALID_OPERATION;
+    }
+
+    Return<V1_0::Result> initialize(
+            const ::android::hardware::MQDescriptorSync<V1_0::Event>& /* eventQueueDescriptor */,
+            const ::android::hardware::MQDescriptorSync<uint32_t>& /* wakeLockDescriptor */,
+            const sp<V2_0::ISensorsCallback>& /* sensorsCallback */) final {
+        return V1_0::Result::INVALID_OPERATION;
+    }
+
+    // Several HAL 2.0 methods won't be invoked on HAL 2.1 so they are stubbed out below.
+    Return<void> getSensorsList(getSensorsList_cb /* _hidl_cb */) final { return Void(); }
+
+    Return<V1_0::Result> injectSensorData(const V1_0::Event& /* event */) final {
+        return V1_0::Result::INVALID_OPERATION;
     }
 
     /**
@@ -143,28 +155,26 @@
      *     should be created.
      * @return result OK on success
      */
-    virtual Return<Result> initialize(const sp<IHalProxyCallback>& halProxyCallback) = 0;
+    virtual Return<V1_0::Result> initialize(const sp<IHalProxyCallback>& halProxyCallback) = 0;
 };
 
 }  // namespace implementation
-}  // namespace V2_0
+}  // namespace V2_1
 }  // namespace sensors
 }  // namespace hardware
 }  // namespace android
 
-using ::android::hardware::sensors::V2_0::implementation::ISensorsSubHal;
-
 /**
  * Function that must be exported so the HalProxy class can invoke it on the sub-HAL dynamic
  * library. This function will only be invoked once at initialization time.
  *
- * NOTE: The supported sensors HAL version must match SUB_HAL_2_0_VERSION exactly or the HalProxy
- * will fail to initialize.
+ * NOTE: The supported sensors HAL version must match SUB_HAL_2_1_VERSION or the HalProxy
+ *     will fail to initialize.
  *
  * @param uint32_t when this function returns, this parameter must contain the HAL version that
- *     this sub-HAL supports. To support this version of multi-HAL, this must be set to
- *     SUB_HAL_2_0_VERSION.
+ *     this sub-HAL supports. This must be set to SUB_HAL_2_1_VERSION.
  * @return A statically allocated, valid ISensorsSubHal implementation.
  */
-__attribute__((visibility("default"))) extern "C" ISensorsSubHal* sensorsHalGetSubHal(
-        uint32_t* version);
+__attribute__((visibility(
+        "default"))) extern "C" ::android::hardware::sensors::V2_1::implementation::ISensorsSubHal*
+sensorsHalGetSubHal_2_1(uint32_t* version);
diff --git a/sensors/common/default/2.X/multihal/tests/Android.bp b/sensors/common/default/2.X/multihal/tests/Android.bp
index afb63cc..7692b51 100644
--- a/sensors/common/default/2.X/multihal/tests/Android.bp
+++ b/sensors/common/default/2.X/multihal/tests/Android.bp
@@ -26,6 +26,7 @@
         "android.hardware.sensors@1.0",
         "android.hardware.sensors@2.0",
         "android.hardware.sensors@2.0-ScopedWakelock",
+        "android.hardware.sensors@2.1",
         "libcutils",
         "libfmq",
         "libhardware",
@@ -85,6 +86,8 @@
     shared_libs: [
         "android.hardware.sensors@1.0",
         "android.hardware.sensors@2.0",
+        "android.hardware.sensors@2.0-ScopedWakelock",
+        "android.hardware.sensors@2.1",
         "libbase",
         "libcutils",
         "libfmq",
diff --git a/sensors/common/default/2.X/multihal/tests/HalProxy_test.cpp b/sensors/common/default/2.X/multihal/tests/HalProxy_test.cpp
index 4633a75..867c4a1 100644
--- a/sensors/common/default/2.X/multihal/tests/HalProxy_test.cpp
+++ b/sensors/common/default/2.X/multihal/tests/HalProxy_test.cpp
@@ -19,8 +19,8 @@
 #include <fmq/MessageQueue.h>
 
 #include "HalProxy.h"
-#include "ScopedWakelock.h"
 #include "SensorsSubHal.h"
+#include "V2_0/ScopedWakelock.h"
 
 #include <chrono>
 #include <set>
diff --git a/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.h b/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.h
index c1e3647..6da4404 100644
--- a/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.h
+++ b/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.h
@@ -16,7 +16,7 @@
 
 #pragma once
 
-#include "SubHal.h"
+#include "V2_0/SubHal.h"
 
 #include "Sensor.h"
 
diff --git a/tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/Directionality.aidl b/tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/Directionality.aidl
new file mode 100644
index 0000000..26eb1b48
--- /dev/null
+++ b/tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/Directionality.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tests.extension.vibrator;
+@Backing(type="int") @VintfStability
+enum Directionality {
+  NONE = 0,
+  TRANSVERSE = 1,
+  LONGITUDINAL = 2,
+}
diff --git a/tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/ICustomVibrator.aidl b/tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/ICustomVibrator.aidl
new file mode 100644
index 0000000..ed9a3c6
--- /dev/null
+++ b/tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/ICustomVibrator.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tests.extension.vibrator;
+@VintfStability
+interface ICustomVibrator {
+  int getVendorCapabilities();
+  void setDirectionality(android.hardware.tests.extension.vibrator.Directionality directionality);
+  int perform(android.hardware.tests.extension.vibrator.VendorEffect effect, android.hardware.vibrator.IVibratorCallback callback);
+  const int CAP_VENDOR_DIRECTIONALITY = 1;
+}
diff --git a/tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/VendorEffect.aidl b/tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/VendorEffect.aidl
new file mode 100644
index 0000000..4d03a0a
--- /dev/null
+++ b/tests/extension/vibrator/aidl/aidl_api/test-android.hardware.vibrator-ext/current/android/hardware/tests/extension/vibrator/VendorEffect.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.tests.extension.vibrator;
+@Backing(type="int") @VintfStability
+enum VendorEffect {
+  CRACKLE = 0,
+  WIGGLE = 1,
+}
diff --git a/tv/tuner/1.0/default/Android.bp b/tv/tuner/1.0/default/Android.bp
index 989e25c..5711889 100644
--- a/tv/tuner/1.0/default/Android.bp
+++ b/tv/tuner/1.0/default/Android.bp
@@ -24,6 +24,7 @@
         "libfmq",
         "libhidlbase",
         "libhidlmemory",
+        "libion",
         "liblog",
         "libstagefright_foundation",
         "libutils",
diff --git a/tv/tuner/1.0/default/Filter.cpp b/tv/tuner/1.0/default/Filter.cpp
index 54d0952..f610c60 100644
--- a/tv/tuner/1.0/default/Filter.cpp
+++ b/tv/tuner/1.0/default/Filter.cpp
@@ -60,6 +60,8 @@
 Return<void> Filter::getQueueDesc(getQueueDesc_cb _hidl_cb) {
     ALOGV("%s", __FUNCTION__);
 
+    mIsUsingFMQ = true;
+
     _hidl_cb(Result::SUCCESS, *mFilterMQ->getDesc());
     return Void();
 }
@@ -120,9 +122,13 @@
     return Result::SUCCESS;
 }
 
-Return<Result> Filter::releaseAvHandle(const hidl_handle& /*avMemory*/, uint64_t /*avDataId*/) {
+Return<Result> Filter::releaseAvHandle(const hidl_handle& /*avMemory*/, uint64_t avDataId) {
     ALOGV("%s", __FUNCTION__);
+    if (mDataId2Avfd.find(avDataId) == mDataId2Avfd.end()) {
+        return Result::INVALID_ARGUMENT;
+    }
 
+    ::close(mDataId2Avfd[avDataId]);
     return Result::SUCCESS;
 }
 
@@ -174,14 +180,21 @@
     // Event Callback without waiting for the DATA_CONSUMED to init the process.
     while (mFilterThreadRunning) {
         if (mFilterEvent.events.size() == 0) {
-            ALOGD("[Filter] wait for filter data output.");
+            if (DEBUG_FILTER) {
+                ALOGD("[Filter] wait for filter data output.");
+            }
             usleep(1000 * 1000);
             continue;
         }
         // After successfully write, send a callback and wait for the read to be done
         mCallback->onFilterEvent(mFilterEvent);
+        freeAvHandle();
         mFilterEvent.events.resize(0);
         mFilterStatus = DemuxFilterStatus::DATA_READY;
+        if (mCallback == nullptr) {
+            ALOGD("[Filter] filter %d does not hava callback. Ending thread", mFilterId);
+            break;
+        }
         mCallback->onFilterStatus(mFilterStatus);
         break;
     }
@@ -191,7 +204,7 @@
         // We do not wait for the last round of written data to be read to finish the thread
         // because the VTS can verify the reading itself.
         for (int i = 0; i < SECTION_WRITE_COUNT; i++) {
-            while (mFilterThreadRunning) {
+            while (mFilterThreadRunning && mIsUsingFMQ) {
                 status_t status = mFilterEventFlag->wait(
                         static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED), &efState,
                         WAIT_TIMEOUT, true /* retry on spurious wake */);
@@ -202,11 +215,6 @@
                 break;
             }
 
-            if (mCallback == nullptr) {
-                ALOGD("[Filter] filter %d does not hava callback. Ending thread", mFilterId);
-                break;
-            }
-
             maySendFilterStatusCallback();
 
             while (mFilterThreadRunning) {
@@ -232,7 +240,22 @@
     ALOGD("[Filter] filter thread ended.");
 }
 
+void Filter::freeAvHandle() {
+    if (mType.mainType != DemuxFilterMainType::TS ||
+        (mType.subType.tsFilterType() == DemuxTsFilterType::AUDIO &&
+         mType.subType.tsFilterType() == DemuxTsFilterType::VIDEO)) {
+        return;
+    }
+    for (int i = 0; i < mFilterEvent.events.size(); i++) {
+        ::close(mFilterEvent.events[i].media().avMemory.getNativeHandle()->data[0]);
+        native_handle_close(mFilterEvent.events[i].media().avMemory.getNativeHandle());
+    }
+}
+
 void Filter::maySendFilterStatusCallback() {
+    if (!mIsUsingFMQ) {
+        return;
+    }
     std::lock_guard<std::mutex> lock(mFilterStatusLock);
     int availableToRead = mFilterMQ->availableToRead();
     int availableToWrite = mFilterMQ->availableToWrite();
@@ -409,19 +432,88 @@
 }
 
 Result Filter::startMediaFilterHandler() {
-    DemuxFilterMediaEvent mediaEvent;
-    mediaEvent = {
-            // temp dump meta data
-            .pts = 0,
-            .dataLength = 530,
-            .avMemory = nullptr,
-            .isSecureMemory = false,
-    };
-    mFilterEvent.events.resize(1);
-    mFilterEvent.events[0].media(mediaEvent);
+    std::lock_guard<std::mutex> lock(mFilterEventLock);
+    if (mFilterOutput.empty()) {
+        return Result::SUCCESS;
+    }
+
+    for (int i = 0; i < mFilterOutput.size(); i += 188) {
+        if (mPesSizeLeft == 0) {
+            uint32_t prefix = (mFilterOutput[i + 4] << 16) | (mFilterOutput[i + 5] << 8) |
+                              mFilterOutput[i + 6];
+            if (DEBUG_FILTER) {
+                ALOGD("[Filter] prefix %d", prefix);
+            }
+            if (prefix == 0x000001) {
+                // TODO handle mulptiple Pes filters
+                mPesSizeLeft = (mFilterOutput[i + 8] << 8) | mFilterOutput[i + 9];
+                mPesSizeLeft += 6;
+                if (DEBUG_FILTER) {
+                    ALOGD("[Filter] pes data length %d", mPesSizeLeft);
+                }
+            } else {
+                continue;
+            }
+        }
+
+        int endPoint = min(184, mPesSizeLeft);
+        // append data and check size
+        vector<uint8_t>::const_iterator first = mFilterOutput.begin() + i + 4;
+        vector<uint8_t>::const_iterator last = mFilterOutput.begin() + i + 4 + endPoint;
+        mPesOutput.insert(mPesOutput.end(), first, last);
+        // size does not match then continue
+        mPesSizeLeft -= endPoint;
+        if (DEBUG_FILTER) {
+            ALOGD("[Filter] pes data left %d", mPesSizeLeft);
+        }
+        if (mPesSizeLeft > 0 || mAvBufferCopyCount++ < 10) {
+            continue;
+        }
+
+        int av_fd = createAvIonFd(mPesOutput.size());
+        if (av_fd == -1) {
+            return Result::UNKNOWN_ERROR;
+        }
+        // copy the filtered data to the buffer
+        uint8_t* avBuffer = getIonBuffer(av_fd, mPesOutput.size());
+        if (avBuffer == NULL) {
+            return Result::UNKNOWN_ERROR;
+        }
+        memcpy(avBuffer, mPesOutput.data(), mPesOutput.size() * sizeof(uint8_t));
+
+        native_handle_t* nativeHandle = createNativeHandle(av_fd);
+        if (nativeHandle == NULL) {
+            return Result::UNKNOWN_ERROR;
+        }
+        hidl_handle handle;
+        handle.setTo(nativeHandle, /*shouldOwn=*/true);
+
+        // Create a dataId and add a <dataId, av_fd> pair into the dataId2Avfd map
+        uint64_t dataId = mLastUsedDataId++ /*createdUID*/;
+        mDataId2Avfd[dataId] = dup(av_fd);
+
+        // Create mediaEvent and send callback
+        DemuxFilterMediaEvent mediaEvent;
+        mediaEvent = {
+                .avMemory = std::move(handle),
+                .dataLength = static_cast<uint32_t>(mPesOutput.size()),
+                .avDataId = dataId,
+        };
+        int size = mFilterEvent.events.size();
+        mFilterEvent.events.resize(size + 1);
+        mFilterEvent.events[size].media(mediaEvent);
+
+        // Clear and log
+        mPesOutput.clear();
+        mAvBufferCopyCount = 0;
+        ::close(av_fd);
+        if (DEBUG_FILTER) {
+            ALOGD("[Filter] assembled av data length %d", mediaEvent.dataLength);
+        }
+    }
 
     mFilterOutput.clear();
-    // TODO handle write FQM for media stream
+
     return Result::SUCCESS;
 }
 
@@ -493,6 +585,42 @@
     mDvr = nullptr;
 }
 
+int Filter::createAvIonFd(int size) {
+    // Create an ion fd and allocate an av fd mapped to a buffer to it.
+    int ion_fd = ion_open();
+    if (ion_fd == -1) {
+        ALOGE("[Filter] Failed to open ion fd %d", errno);
+        return -1;
+    }
+    int av_fd = -1;
+    ion_alloc_fd(dup(ion_fd), size, 0 /*align*/, ION_HEAP_SYSTEM_MASK, 0 /*flags*/, &av_fd);
+    if (av_fd == -1) {
+        ALOGE("[Filter] Failed to create av fd %d", errno);
+        return -1;
+    }
+    return av_fd;
+}
+
+uint8_t* Filter::getIonBuffer(int fd, int size) {
+    uint8_t* avBuf = static_cast<uint8_t*>(
+            mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 /*offset*/));
+    if (avBuf == MAP_FAILED) {
+        ALOGE("[Filter] fail to allocate buffer %d", errno);
+        return NULL;
+    }
+    return avBuf;
+}
+
+native_handle_t* Filter::createNativeHandle(int fd) {
+    // Create a native handle to pass the av fd via the callback event.
+    native_handle_t* nativeHandle = native_handle_create(/*numFd*/ 1, 0);
+    if (nativeHandle == NULL) {
+        ALOGE("[Filter] Failed to create native_handle %d", errno);
+        return NULL;
+    }
+    nativeHandle->data[0] = dup(fd);
+    return nativeHandle;
+}
 }  // namespace implementation
 }  // namespace V1_0
 }  // namespace tuner
diff --git a/tv/tuner/1.0/default/Filter.h b/tv/tuner/1.0/default/Filter.h
index 0dc992a..afed98e 100644
--- a/tv/tuner/1.0/default/Filter.h
+++ b/tv/tuner/1.0/default/Filter.h
@@ -19,6 +19,7 @@
 
 #include <android/hardware/tv/tuner/1.0/IFilter.h>
 #include <fmq/MessageQueue.h>
+#include <ion/ion.h>
 #include <math.h>
 #include <set>
 #include "Demux.h"
@@ -87,6 +88,7 @@
     Result startRecordFilterHandler();
     void attachFilterToRecord(const sp<Dvr> dvr);
     void detachFilterFromRecord();
+    void freeAvHandle();
 
   private:
     // Tuner service
@@ -109,6 +111,7 @@
     vector<uint8_t> mFilterOutput;
     vector<uint8_t> mRecordFilterOutput;
     unique_ptr<FilterMQ> mFilterMQ;
+    bool mIsUsingFMQ = false;
     EventFlag* mFilterEventFlag;
     DemuxFilterEvent mFilterEvent;
 
@@ -160,6 +163,10 @@
     static void* __threadLoopFilter(void* user);
     void filterThreadLoop();
 
+    int createAvIonFd(int size);
+    uint8_t* getIonBuffer(int fd, int size);
+    native_handle_t* createNativeHandle(int fd);
+
     /**
      * Lock to protect writes to the FMQs
      */
@@ -181,6 +188,11 @@
     // TODO handle mulptiple Pes filters
     int mPesSizeLeft = 0;
     vector<uint8_t> mPesOutput;
+
+    // A map from data id to ion handle
+    std::map<uint64_t, int> mDataId2Avfd;
+    uint64_t mLastUsedDataId = 1;
+    int mAvBufferCopyCount = 0;
 };
 
 }  // namespace implementation
diff --git a/tv/tuner/1.0/default/Frontend.cpp b/tv/tuner/1.0/default/Frontend.cpp
index 7e206a7..bb0d8dc 100644
--- a/tv/tuner/1.0/default/Frontend.cpp
+++ b/tv/tuner/1.0/default/Frontend.cpp
@@ -63,9 +63,6 @@
         return Result::INVALID_STATE;
     }
 
-    // TODO dynamically allocate file to the source file
-    mSourceStreamFile = FRONTEND_STREAM_FILE;
-
     mCallback->onEvent(FrontendEventType::LOCKED);
     return Result::SUCCESS;
 }
@@ -180,7 +177,7 @@
 }
 
 string Frontend::getSourceFile() {
-    return mSourceStreamFile;
+    return FRONTEND_STREAM_FILE;
 }
 
 }  // namespace implementation
diff --git a/tv/tuner/1.0/default/Frontend.h b/tv/tuner/1.0/default/Frontend.h
index eab43a3..b954639 100644
--- a/tv/tuner/1.0/default/Frontend.h
+++ b/tv/tuner/1.0/default/Frontend.h
@@ -76,7 +76,6 @@
     FrontendId mId = 0;
 
     const string FRONTEND_STREAM_FILE = "/vendor/etc/dumpTs3.ts";
-    string mSourceStreamFile;
     std::ifstream mFrontendData;
 };
 
diff --git a/tv/tuner/1.0/default/Tuner.cpp b/tv/tuner/1.0/default/Tuner.cpp
index 4fd3355..8fb5061 100644
--- a/tv/tuner/1.0/default/Tuner.cpp
+++ b/tv/tuner/1.0/default/Tuner.cpp
@@ -106,7 +106,7 @@
     return Void();
 }
 
-Return<void> Tuner::getFrontendInfo(FrontendId /* frontendId */, getFrontendInfo_cb _hidl_cb) {
+Return<void> Tuner::getFrontendInfo(FrontendId /*frontendId*/, getFrontendInfo_cb _hidl_cb) {
     ALOGV("%s", __FUNCTION__);
 
     vector<FrontendStatusType> statusCaps = {
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index f693e7c..8b0413c 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -47,7 +47,6 @@
 #include "VtsHalTvTunerV1_0TestConfigurations.h"
 
 #define WAIT_TIMEOUT 3000000000
-#define WAIT_TIMEOUT_data_ready 3000000000 * 4
 
 using android::Condition;
 using android::IMemory;
@@ -57,6 +56,7 @@
 using android::sp;
 using android::hardware::EventFlag;
 using android::hardware::fromHeap;
+using android::hardware::hidl_handle;
 using android::hardware::hidl_string;
 using android::hardware::hidl_vec;
 using android::hardware::HidlMemory;
@@ -68,6 +68,7 @@
 using android::hardware::tv::tuner::V1_0::DataFormat;
 using android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
 using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using android::hardware::tv::tuner::V1_0::DemuxFilterMediaEvent;
 using android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings;
 using android::hardware::tv::tuner::V1_0::DemuxFilterPesEvent;
 using android::hardware::tv::tuner::V1_0::DemuxFilterRecordSettings;
@@ -156,7 +157,6 @@
 // const uint16_t FMQ_SIZE_4K = 0x1000;
 const uint32_t FMQ_SIZE_1M = 0x100000;
 const uint32_t FMQ_SIZE_16M = 0x1000000;
-const uint8_t FRONTEND_EVENT_CALLBACK_WAIT_COUNT = 4;
 
 enum FilterEventType : uint8_t {
     UNDEFINED,
@@ -179,52 +179,65 @@
   public:
     virtual Return<void> onEvent(FrontendEventType frontendEventType) override {
         android::Mutex::Autolock autoLock(mMsgLock);
+        ALOGD("[vts] frontend event received. Type: %d", frontendEventType);
         mEventReceived = true;
-        mEventType = frontendEventType;
         mMsgCondition.signal();
-        return Void();
+        switch (frontendEventType) {
+            case FrontendEventType::LOCKED:
+                mLockMsgReceived = true;
+                mLockMsgCondition.signal();
+                return Void();
+            default:
+                // do nothing
+                return Void();
+        }
     }
 
     virtual Return<void> onScanMessage(FrontendScanMessageType type,
                                        const FrontendScanMessage& message) override {
         android::Mutex::Autolock autoLock(mMsgLock);
-        ALOGD("[vts] scan message. Type: %d", mScanMessageType);
+        while (!mScanMsgProcessed) {
+            mMsgCondition.wait(mMsgLock);
+        }
+        ALOGD("[vts] frontend scan message. Type: %d", type);
         mScanMessageReceived = true;
+        mScanMsgProcessed = false;
         mScanMessageType = type;
-        mScanLockMessageReceived =
-                mScanLockMessageReceived | (type == FrontendScanMessageType::LOCKED);
         mScanMessage = message;
         mMsgCondition.signal();
         return Void();
-    };
+    }
 
     void tuneTestOnEventReceive(sp<IFrontend>& frontend, FrontendSettings settings);
     void tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings);
-    void scanTestOnMessageLock(sp<IFrontend>& frontend, FrontendSettings settings,
-                               FrontendScanType type);
+    void scanTest(sp<IFrontend>& frontend, FrontendConfig config, FrontendScanType type);
+
+    // Helper methods
+    uint32_t getTargetFrequency(FrontendSettings settings, FrontendType type);
+    void resetBlindScanStartingFrequency(FrontendConfig config, uint32_t resetingFreq);
 
   private:
     bool mEventReceived = false;
     bool mScanMessageReceived = false;
-    bool mScanLockMessageReceived = false;
-    FrontendEventType mEventType;
+    bool mLockMsgReceived = false;
+    bool mScanMsgProcessed = true;
     FrontendScanMessageType mScanMessageType;
     FrontendScanMessage mScanMessage;
     hidl_vec<uint8_t> mEventMessage;
     android::Mutex mMsgLock;
     android::Condition mMsgCondition;
-    uint8_t mOnEvenRetry = 0;
+    android::Condition mLockMsgCondition;
 };
 
 void FrontendCallback::tuneTestOnEventReceive(sp<IFrontend>& frontend, FrontendSettings settings) {
     Result result = frontend->tune(settings);
-
     EXPECT_TRUE(result == Result::SUCCESS);
 
     android::Mutex::Autolock autoLock(mMsgLock);
     while (!mEventReceived) {
         if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
-            EXPECT_TRUE(false) << "event not received within timeout";
+            EXPECT_TRUE(false) << "Event not received within timeout";
+            mLockMsgReceived = false;
             return;
         }
     }
@@ -233,61 +246,134 @@
 
 void FrontendCallback::tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings) {
     Result result = frontend->tune(settings);
-
     EXPECT_TRUE(result == Result::SUCCESS);
 
     android::Mutex::Autolock autoLock(mMsgLock);
-wait:
-    while (!mEventReceived) {
-        if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
-            EXPECT_TRUE(false) << "event not received within timeout";
+    while (!mLockMsgReceived) {
+        if (-ETIMEDOUT == mLockMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+            EXPECT_TRUE(false) << "Event LOCKED not received within timeout";
+            mLockMsgReceived = false;
             return;
         }
     }
-    if (mEventType != FrontendEventType::LOCKED) {
-        ALOGD("[vts] frontend callback event received. Type: %d", mEventType);
-        mEventReceived = false;
-        if (mOnEvenRetry++ < FRONTEND_EVENT_CALLBACK_WAIT_COUNT) {
-            goto wait;
-        }
-    }
-    EXPECT_TRUE(mEventType == FrontendEventType::LOCKED) << "LOCK event not received";
-    mEventReceived = false;
-    mOnEvenRetry = 0;
+    mLockMsgReceived = false;
 }
 
-void FrontendCallback::scanTestOnMessageLock(sp<IFrontend>& frontend, FrontendSettings settings,
-                                             FrontendScanType type) {
-    Result result = frontend->scan(settings, type);
-    EXPECT_TRUE(result == Result::SUCCESS);
-    android::Mutex::Autolock autoLock(mMsgLock);
-    int messagesCount = 0;
+void FrontendCallback::scanTest(sp<IFrontend>& frontend, FrontendConfig config,
+                                FrontendScanType type) {
+    uint32_t targetFrequency = getTargetFrequency(config.settings, config.type);
+    if (type == FrontendScanType::SCAN_BLIND) {
+        // reset the frequency in the scan configuration to test blind scan. The settings param of
+        // passed in means the real input config on the transponder connected to the DUT.
+        // We want the blind the test to start from lower frequency than this to check the blind
+        // scan implementation.
+        resetBlindScanStartingFrequency(config, targetFrequency - 100);
+    }
 
+    Result result = frontend->scan(config.settings, type);
+    EXPECT_TRUE(result == Result::SUCCESS);
+
+    bool scanMsgLockedReceived = false;
+    bool targetFrequencyReceived = false;
+
+    android::Mutex::Autolock autoLock(mMsgLock);
 wait:
-    int count = 0;
     while (!mScanMessageReceived) {
         if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
-            ALOGD("[vts] waiting for scan message callback...");
-            if (count++ > 10) {
-                EXPECT_TRUE(false) << "WAITING TOO LONG!!";
-                return;
-            }
+            EXPECT_TRUE(false) << "Scan message not received within timeout";
+            mScanMessageReceived = false;
+            mScanMsgProcessed = true;
+            return;
         }
     }
 
     if (mScanMessageType != FrontendScanMessageType::END) {
-        ALOGD("[vts] frontend scan message received. Type: %d", mScanMessageType);
-        mScanMessageReceived = false;
-        if (messagesCount++ > 3) {
-            EXPECT_TRUE(false) << "WAITING ON TOO MANY MSGS!!";
-            return;
+        if (mScanMessageType == FrontendScanMessageType::LOCKED) {
+            scanMsgLockedReceived = true;
+            Result result = frontend->scan(config.settings, type);
+            EXPECT_TRUE(result == Result::SUCCESS);
         }
+
+        if (mScanMessageType == FrontendScanMessageType::FREQUENCY) {
+            targetFrequencyReceived = mScanMessage.frequencies().size() > 0 &&
+                                      mScanMessage.frequencies()[0] == targetFrequency;
+        }
+
+        if (mScanMessageType == FrontendScanMessageType::PROGRESS_PERCENT) {
+            ALOGD("[vts] Scan in progress...[%d%%]", mScanMessage.progressPercent());
+        }
+
+        mScanMessageReceived = false;
+        mScanMsgProcessed = true;
+        mMsgCondition.signal();
         goto wait;
     }
 
-    EXPECT_TRUE(mScanLockMessageReceived) << "scan lock message not received before scan ended";
+    EXPECT_TRUE(scanMsgLockedReceived) << "Scan message LOCKED not received before END";
+    EXPECT_TRUE(targetFrequencyReceived) << "frequency not received before LOCKED on blindScan";
     mScanMessageReceived = false;
-    mScanLockMessageReceived = false;
+    mScanMsgProcessed = true;
+}
+
+uint32_t FrontendCallback::getTargetFrequency(FrontendSettings settings, FrontendType type) {
+    switch (type) {
+        case FrontendType::ANALOG:
+            return settings.analog().frequency;
+        case FrontendType::ATSC:
+            return settings.atsc().frequency;
+        case FrontendType::ATSC3:
+            return settings.atsc3().frequency;
+        case FrontendType::DVBC:
+            return settings.dvbc().frequency;
+        case FrontendType::DVBS:
+            return settings.dvbs().frequency;
+        case FrontendType::DVBT:
+            return settings.dvbt().frequency;
+        case FrontendType::ISDBS:
+            return settings.isdbs().frequency;
+        case FrontendType::ISDBS3:
+            return settings.isdbs3().frequency;
+        case FrontendType::ISDBT:
+            return settings.isdbt().frequency;
+        default:
+            return 0;
+    }
+}
+
+void FrontendCallback::resetBlindScanStartingFrequency(FrontendConfig config,
+                                                       uint32_t resetingFreq) {
+    switch (config.type) {
+        case FrontendType::ANALOG:
+            config.settings.analog().frequency = resetingFreq;
+            break;
+        case FrontendType::ATSC:
+            config.settings.atsc().frequency = resetingFreq;
+            break;
+        case FrontendType::ATSC3:
+            config.settings.atsc3().frequency = resetingFreq;
+            break;
+        case FrontendType::DVBC:
+            config.settings.dvbc().frequency = resetingFreq;
+            break;
+        case FrontendType::DVBS:
+            config.settings.dvbs().frequency = resetingFreq;
+            break;
+        case FrontendType::DVBT:
+            config.settings.dvbt().frequency = resetingFreq;
+            break;
+        case FrontendType::ISDBS:
+            config.settings.isdbs().frequency = resetingFreq;
+            break;
+        case FrontendType::ISDBS3:
+            config.settings.isdbs3().frequency = resetingFreq;
+            break;
+        case FrontendType::ISDBT:
+            config.settings.isdbt().frequency = resetingFreq;
+            break;
+        default:
+            // do nothing
+            return;
+    }
 }
 /******************************** End FrontendCallback **********************************/
 
@@ -313,6 +399,7 @@
     }
 
     void setFilterId(uint32_t filterId) { mFilterId = filterId; }
+    void setFilterInterface(sp<IFilter> filter) { mFilter = filter; }
     void setFilterEventType(FilterEventType type) { mFilterEventType = type; }
 
     void testFilterDataOutput();
@@ -324,6 +411,7 @@
     void updateFilterMQ(MQDesc& filterMQDescriptor);
     void updateGoldenOutputMap(string goldenOutputFile);
     bool readFilterEventData();
+    bool dumpAvData(DemuxFilterMediaEvent event);
 
   private:
     struct FilterThreadArgs {
@@ -336,6 +424,7 @@
     string mFilterIdToGoldenOutput;
 
     uint32_t mFilterId;
+    sp<IFilter> mFilter;
     FilterEventType mFilterEventType;
     std::unique_ptr<FilterMQ> mFilterMQ;
     EventFlag* mFilterMQEventFlag;
@@ -407,7 +496,7 @@
 bool FilterCallback::readFilterEventData() {
     bool result = false;
     DemuxFilterEvent filterEvent = mFilterEvent;
-    ALOGW("[vts] reading from filter FMQ %d", mFilterId);
+    ALOGW("[vts] reading from filter FMQ or buffer %d", mFilterId);
     // todo separate filter handlers
     for (int i = 0; i < filterEvent.events.size(); i++) {
         switch (mFilterEventType) {
@@ -418,8 +507,7 @@
                 mDataLength = filterEvent.events[i].pes().dataLength;
                 break;
             case FilterEventType::MEDIA:
-                mDataLength = filterEvent.events[i].media().dataLength;
-                break;
+                return dumpAvData(filterEvent.events[i].media());
             case FilterEventType::RECORD:
                 break;
             case FilterEventType::MMTPRECORD:
@@ -443,6 +531,26 @@
     mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
     return result;
 }
+
+bool FilterCallback::dumpAvData(DemuxFilterMediaEvent event) {
+    uint32_t length = event.dataLength;
+    uint64_t dataId = event.avDataId;
+    // read data from buffer pointed by a handle
+    hidl_handle handle = event.avMemory;
+
+    int av_fd = handle.getNativeHandle()->data[0];
+    uint8_t* buffer = static_cast<uint8_t*>(
+            mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, av_fd, 0 /*offset*/));
+    if (buffer == MAP_FAILED) {
+        ALOGE("[vts] fail to allocate av buffer, errno=%d", errno);
+        return false;
+    }
+    uint8_t output[length + 1];
+    memcpy(output, buffer, length);
+    // print buffer and check with golden output.
+    EXPECT_TRUE(mFilter->releaseAvHandle(handle, dataId) == Result::SUCCESS);
+    return true;
+}
 /******************************** End FilterCallback **********************************/
 
 /******************************** Start DvrCallback **********************************/
@@ -731,6 +839,7 @@
     sp<IFilter> mFilter;
     std::map<uint32_t, sp<IFilter>> mFilters;
     std::map<uint32_t, sp<FilterCallback>> mFilterCallbacks;
+
     sp<FilterCallback> mFilterCallback;
     sp<DvrCallback> mDvrCallback;
     MQDesc mFilterMQDescriptor;
@@ -826,7 +935,7 @@
     EXPECT_TRUE(mFrontendInfo.type == config.type)
             << "FrontendConfig does not match the frontend info of the given id.";
 
-    mFrontendCallback->scanTestOnMessageLock(mFrontend, config.settings, type);
+    mFrontendCallback->scanTest(mFrontend, config, type);
     return AssertionResult(true);
 }
 
@@ -926,13 +1035,14 @@
 
     if (status == Result::SUCCESS) {
         mFilterCallback->setFilterId(mFilterId);
+        mFilterCallback->setFilterInterface(mFilter);
         mUsedFilterIds.insert(mUsedFilterIds.end(), mFilterId);
         mFilters[mFilterId] = mFilter;
         mFilterCallbacks[mFilterId] = mFilterCallback;
         filterId = mFilterId;
     }
 
-    return AssertionResult(status == Result::SUCCESS || status == Result::UNAVAILABLE);
+    return AssertionResult(status == Result::SUCCESS);
 }
 
 AssertionResult TunerHidlTest::configFilter(DemuxFilterSettings setting, uint32_t filterId) {
@@ -1300,7 +1410,6 @@
         }
         ASSERT_TRUE(openFrontend(mFeIds[i]));
         ASSERT_TRUE(setFrontendCallback());
-        ASSERT_TRUE(stopTuneFrontend());
         ASSERT_TRUE(tuneFrontend(frontendArray[0]));
         ASSERT_TRUE(stopTuneFrontend());
         ASSERT_TRUE(closeFrontend());
@@ -1320,13 +1429,31 @@
         }
         ASSERT_TRUE(openFrontend(mFeIds[i]));
         ASSERT_TRUE(setFrontendCallback());
-        ASSERT_TRUE(stopScanFrontend());
         ASSERT_TRUE(scanFrontend(frontendScanArray[0], FrontendScanType::SCAN_AUTO));
         ASSERT_TRUE(stopScanFrontend());
         ASSERT_TRUE(closeFrontend());
         break;
     }
 }
+
+TEST_P(TunerHidlTest, BlindScanFrontend) {
+    description("Run an blind frontend scan with specific setting and check lock scanMessage");
+    ASSERT_TRUE(getFrontendIds());
+    ASSERT_TRUE(mFeIds.size() > 0);
+
+    for (size_t i = 0; i < mFeIds.size(); i++) {
+        ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
+        if (mFrontendInfo.type != frontendArray[0].type) {
+            continue;
+        }
+        ASSERT_TRUE(openFrontend(mFeIds[i]));
+        ASSERT_TRUE(setFrontendCallback());
+        ASSERT_TRUE(scanFrontend(frontendScanArray[0], FrontendScanType::SCAN_BLIND));
+        ASSERT_TRUE(stopScanFrontend());
+        ASSERT_TRUE(closeFrontend());
+        break;
+    }
+}
 /*=============================== End Frontend Tests ===============================*/
 
 /*============================ Start Demux/Filter Tests ============================*/
@@ -1535,6 +1662,39 @@
 
     ASSERT_TRUE(recordDataFlowTest(filterConf, recordSetting, goldenOutputFiles));
 }*/
+
+TEST_P(TunerHidlTest, AvBufferTest) {
+    description("Test the av filter data bufferring.");
+
+    ASSERT_TRUE(getFrontendIds());
+    ASSERT_TRUE(mFeIds.size() > 0);
+
+    for (size_t i = 0; i < mFeIds.size(); i++) {
+        ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
+        if (mFrontendInfo.type != frontendArray[1].type) {
+            continue;
+        }
+        ASSERT_TRUE(openFrontend(mFeIds[i]));
+        ASSERT_TRUE(setFrontendCallback());
+        ASSERT_TRUE(openDemux());
+        ASSERT_TRUE(openFilterInDemux(filterArray[0].type));
+        uint32_t filterId;
+        ASSERT_TRUE(getNewlyOpenedFilterId(filterId));
+        ASSERT_TRUE(configFilter(filterArray[0].setting, filterId));
+        ASSERT_TRUE(startFilter(filterId));
+        ASSERT_TRUE(setDemuxFrontendDataSource(mFeIds[i]));
+        // tune test
+        ASSERT_TRUE(tuneFrontend(frontendArray[1]));
+        // broadcast data flow test
+        ASSERT_TRUE(broadcastDataFlowTest(goldenOutputFiles));
+        ASSERT_TRUE(stopTuneFrontend());
+        ASSERT_TRUE(stopFilter(filterId));
+        ASSERT_TRUE(closeFilter(filterId));
+        ASSERT_TRUE(closeDemux());
+        ASSERT_TRUE(closeFrontend());
+        break;
+    }
+}
 /*============================== End Data Flow Tests ==============================*/
 /******************************** End Test Entry **********************************/
 }  // namespace
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
index 55ca857..31e3b51 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
@@ -64,7 +64,7 @@
 
 namespace {
 
-#define frontend_transponders_count 1
+#define frontend_transponders_count 2
 #define channels_count 1
 #define frontend_scan_count 1
 #define filter_count 2
@@ -108,13 +108,24 @@
             .standard = FrontendDvbtStandard::T,
     };
     frontendArray[0].type = FrontendType::DVBT, frontendArray[0].settings.dvbt(dvbtSettings);
+    frontendArray[1].type = FrontendType::DVBS;
 };
 
 /** Configuration array for the frontend scan test */
 inline void initFrontendScanConfig() {
-    frontendScanArray[0].type = FrontendType::DVBT, frontendScanArray[0].settings.dvbt({
-                                                            .frequency = 577000,
-                                                    });
+    frontendScanArray[0].type = FrontendType::DVBT;
+    frontendScanArray[0].settings.dvbt({
+            .frequency = 578000,
+            .transmissionMode = FrontendDvbtTransmissionMode::MODE_8K,
+            .bandwidth = FrontendDvbtBandwidth::BANDWIDTH_8MHZ,
+            .constellation = FrontendDvbtConstellation::AUTO,
+            .hierarchy = FrontendDvbtHierarchy::AUTO,
+            .hpCoderate = FrontendDvbtCoderate::AUTO,
+            .lpCoderate = FrontendDvbtCoderate::AUTO,
+            .guardInterval = FrontendDvbtGuardInterval::AUTO,
+            .isHighPriority = true,
+            .standard = FrontendDvbtStandard::T,
+    });
 };
 
 /** Configuration array for the filter test */
@@ -122,7 +133,7 @@
     // TS Video filter setting
     filterArray[0].type.mainType = DemuxFilterMainType::TS;
     filterArray[0].type.subType.tsFilterType(DemuxTsFilterType::VIDEO);
-    filterArray[0].setting.ts().tpid = 49;
+    filterArray[0].setting.ts().tpid = 119;
     filterArray[0].setting.ts().filterSettings.av({.isPassthrough = false});
     // TS PES filter setting
     filterArray[1].type.mainType = DemuxFilterMainType::TS;
@@ -134,4 +145,4 @@
     });
 };
 
-}  // namespace
\ No newline at end of file
+}  // namespace
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositeEffect.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositeEffect.aidl
new file mode 100644
index 0000000..8cb259f
--- /dev/null
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositeEffect.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.vibrator;
+@VintfStability
+parcelable CompositeEffect {
+  int delayMs;
+  android.hardware.vibrator.CompositePrimitive primitive;
+  float scale;
+}
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl
new file mode 100644
index 0000000..6ab7ac5
--- /dev/null
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl
@@ -0,0 +1,29 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.vibrator;
+@Backing(type="int") @VintfStability
+enum CompositePrimitive {
+  NOOP = 0,
+  CLICK = 1,
+  THUD = 2,
+  SPIN = 3,
+  QUICK_RISE = 4,
+  SLOW_RISE = 5,
+  QUICK_FALL = 6,
+  LIGHT_TICK = 7,
+}
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Effect.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Effect.aidl
new file mode 100644
index 0000000..5ed4dc5
--- /dev/null
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Effect.aidl
@@ -0,0 +1,43 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.vibrator;
+@Backing(type="int") @VintfStability
+enum Effect {
+  CLICK = 0,
+  DOUBLE_CLICK = 1,
+  TICK = 2,
+  THUD = 3,
+  POP = 4,
+  HEAVY_CLICK = 5,
+  RINGTONE_1 = 6,
+  RINGTONE_2 = 7,
+  RINGTONE_3 = 8,
+  RINGTONE_4 = 9,
+  RINGTONE_5 = 10,
+  RINGTONE_6 = 11,
+  RINGTONE_7 = 12,
+  RINGTONE_8 = 13,
+  RINGTONE_9 = 14,
+  RINGTONE_10 = 15,
+  RINGTONE_11 = 16,
+  RINGTONE_12 = 17,
+  RINGTONE_13 = 18,
+  RINGTONE_14 = 19,
+  RINGTONE_15 = 20,
+  TEXTURE_TICK = 21,
+}
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/EffectStrength.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/EffectStrength.aidl
new file mode 100644
index 0000000..802d236
--- /dev/null
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/EffectStrength.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.vibrator;
+@Backing(type="byte") @VintfStability
+enum EffectStrength {
+  LIGHT = 0,
+  MEDIUM = 1,
+  STRONG = 2,
+}
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl
new file mode 100644
index 0000000..2de1d7b
--- /dev/null
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl
@@ -0,0 +1,43 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.vibrator;
+@VintfStability
+interface IVibrator {
+  int getCapabilities();
+  void off();
+  void on(in int timeoutMs, in android.hardware.vibrator.IVibratorCallback callback);
+  int perform(in android.hardware.vibrator.Effect effect, in android.hardware.vibrator.EffectStrength strength, in android.hardware.vibrator.IVibratorCallback callback);
+  android.hardware.vibrator.Effect[] getSupportedEffects();
+  void setAmplitude(in float amplitude);
+  void setExternalControl(in boolean enabled);
+  int getCompositionDelayMax();
+  int getCompositionSizeMax();
+  android.hardware.vibrator.CompositePrimitive[] getSupportedPrimitives();
+  int getPrimitiveDuration(android.hardware.vibrator.CompositePrimitive primitive);
+  void compose(in android.hardware.vibrator.CompositeEffect[] composite, in android.hardware.vibrator.IVibratorCallback callback);
+  android.hardware.vibrator.Effect[] getSupportedAlwaysOnEffects();
+  void alwaysOnEnable(in int id, in android.hardware.vibrator.Effect effect, in android.hardware.vibrator.EffectStrength strength);
+  void alwaysOnDisable(in int id);
+  const int CAP_ON_CALLBACK = 1;
+  const int CAP_PERFORM_CALLBACK = 2;
+  const int CAP_AMPLITUDE_CONTROL = 4;
+  const int CAP_EXTERNAL_CONTROL = 8;
+  const int CAP_EXTERNAL_AMPLITUDE_CONTROL = 16;
+  const int CAP_COMPOSE_EFFECTS = 32;
+  const int CAP_ALWAYS_ON_CONTROL = 64;
+}
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorCallback.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorCallback.aidl
new file mode 100644
index 0000000..3a1e7d8
--- /dev/null
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorCallback.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.vibrator;
+@VintfStability
+interface IVibratorCallback {
+  oneway void onComplete();
+}
diff --git a/vibrator/aidl/android/hardware/vibrator/CompositeEffect.aidl b/vibrator/aidl/android/hardware/vibrator/CompositeEffect.aidl
index 84556b5..406a899 100644
--- a/vibrator/aidl/android/hardware/vibrator/CompositeEffect.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/CompositeEffect.aidl
@@ -23,6 +23,9 @@
     /* Period of silence preceding primitive. */
     int delayMs;
     CompositePrimitive primitive;
-    /* 0.0 (exclusive) - 1.0 (inclusive) */
+    /*
+     * 0.0 (inclusive) - 1.0 (inclusive),
+     * where 0.0 is minimum "feelable" amplitude.
+     */
     float scale;
 }
diff --git a/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl b/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
index 0fdfa5d..8e82db0 100644
--- a/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/CompositePrimitive.aidl
@@ -21,37 +21,53 @@
 enum CompositePrimitive {
     /**
      * No haptic effect. Used to generate extended delays between primitives.
+     *
+     * Support is required.
      */
     NOOP,
     /**
      * This effect should produce a sharp, crisp click sensation.
+     *
+     * Support is required.
      */
     CLICK,
     /**
      * A haptic effect that simulates downwards movement with gravity. Often
      * followed by extra energy of hitting and reverberation to augment
      * physicality.
+     *
+     * Support is optional.
      */
     THUD,
     /**
      * A haptic effect that simulates spinning momentum.
+     *
+     * Support is optional.
      */
     SPIN,
     /**
      * A haptic effect that simulates quick upward movement against gravity.
+     *
+     * Support is required.
      */
     QUICK_RISE,
     /**
      * A haptic effect that simulates slow upward movement against gravity.
+     *
+     * Support is required.
      */
     SLOW_RISE,
     /**
      * A haptic effect that simulates quick downwards movement with gravity.
+     *
+     * Support is required.
      */
     QUICK_FALL,
     /**
      * This very short effect should produce a light crisp sensation intended
      * to be used repetitively for dynamic feedback.
+     *
+     * Support is required.
      */
     LIGHT_TICK,
 }
diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
index 6489c1d..0b21248 100644
--- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
@@ -161,8 +161,8 @@
      * List of supported effect primitive.
      *
      * Return the effect primitives which are supported by the compose API.
-     * Implementations are expected to support all primitives of the interface
-     * version that they implement.
+     * Implementations are expected to support all required primitives of the
+     * interface version that they implement (see primitive definitions).
      */
     CompositePrimitive[] getSupportedPrimitives();
 
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index 9236b95..b359100 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -146,7 +146,7 @@
         if (e.delayMs > kComposeDelayMaxMs) {
             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
         }
-        if (e.scale <= 0.0f || e.scale > 1.0f) {
+        if (e.scale < 0.0f || e.scale > 1.0f) {
             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
         }
         if (std::find(supported.begin(), supported.end(), e.primitive) == supported.end()) {
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index 411fe7a..8340517 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -21,6 +21,7 @@
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
 
+#include <cmath>
 #include <future>
 
 using android::ProcessState;
@@ -53,6 +54,11 @@
         android::enum_range<CompositePrimitive>().begin(),
         android::enum_range<CompositePrimitive>().end()};
 
+const std::vector<CompositePrimitive> kOptionalPrimitives = {
+        CompositePrimitive::THUD,
+        CompositePrimitive::SPIN,
+};
+
 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),
@@ -128,7 +134,6 @@
             } else {
                 EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
                         << toString(effect) << " " << toString(strength);
-                EXPECT_EQ(lengthMs, 0);
             }
         }
     }
@@ -157,7 +162,6 @@
                 EXPECT_GT(lengthMs, 0);
             } else {
                 EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
-                EXPECT_EQ(lengthMs, 0);
             }
 
             if (!status.isOk()) continue;
@@ -177,7 +181,6 @@
             int lengthMs;
             Status status = vibrator->perform(effect, strength, callback, &lengthMs);
             EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode());
-            EXPECT_EQ(lengthMs, 0);
         }
     }
 }
@@ -267,38 +270,56 @@
 
         EXPECT_EQ(Status::EX_NONE, vibrator->getSupportedPrimitives(&supported).exceptionCode());
 
-        std::sort(supported.begin(), supported.end());
+        for (auto primitive : kCompositePrimitives) {
+            bool isPrimitiveSupported =
+                    std::find(supported.begin(), supported.end(), primitive) != supported.end();
+            bool isPrimitiveOptional =
+                    std::find(kOptionalPrimitives.begin(), kOptionalPrimitives.end(), primitive) !=
+                    kOptionalPrimitives.end();
 
-        EXPECT_EQ(kCompositePrimitives, supported);
+            EXPECT_TRUE(isPrimitiveSupported || isPrimitiveOptional) << toString(primitive);
+        }
     }
 }
 
 TEST_P(VibratorAidl, GetPrimitiveDuration) {
     if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
-        int32_t duration;
+        std::vector<CompositePrimitive> supported;
+        ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
 
         for (auto primitive : kCompositePrimitives) {
-            EXPECT_EQ(Status::EX_NONE,
-                      vibrator->getPrimitiveDuration(primitive, &duration).exceptionCode());
+            bool isPrimitiveSupported =
+                    std::find(supported.begin(), supported.end(), primitive) != supported.end();
+            int32_t duration;
+
+            Status status = vibrator->getPrimitiveDuration(primitive, &duration);
+
+            if (isPrimitiveSupported) {
+                EXPECT_EQ(Status::EX_NONE, status.exceptionCode());
+            } else {
+                EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode());
+            }
         }
     }
 }
 
 TEST_P(VibratorAidl, ComposeValidPrimitives) {
     if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
+        std::vector<CompositePrimitive> supported;
         int32_t maxDelay, maxSize;
 
+        ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
         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) {
+        for (auto primitive : supported) {
             CompositeEffect effect;
 
             effect.delayMs = std::rand() % (maxDelay + 1);
             effect.primitive = primitive;
-            effect.scale = static_cast<float>(std::rand()) / RAND_MAX ?: 1.0f;
+            effect.scale = static_cast<float>(std::rand()) / RAND_MAX;
             composite.emplace_back(effect);
 
             if (composite.size() == maxSize) {
@@ -317,7 +338,21 @@
 
 TEST_P(VibratorAidl, ComposeUnsupportedPrimitives) {
     if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
-        for (auto primitive : kInvalidPrimitives) {
+        auto unsupported = kInvalidPrimitives;
+        std::vector<CompositePrimitive> supported;
+
+        ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
+
+        for (auto primitive : kCompositePrimitives) {
+            bool isPrimitiveSupported =
+                    std::find(supported.begin(), supported.end(), primitive) != supported.end();
+
+            if (!isPrimitiveSupported) {
+                unsupported.push_back(primitive);
+            }
+        }
+
+        for (auto primitive : unsupported) {
             std::vector<CompositeEffect> composite(1);
 
             for (auto& effect : composite) {
@@ -332,7 +367,33 @@
     }
 }
 
-TEST_P(VibratorAidl, CompseDelayBoundary) {
+TEST_P(VibratorAidl, ComposeScaleBoundary) {
+    if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
+        std::vector<CompositeEffect> composite(1);
+        CompositeEffect& effect = composite[0];
+
+        effect.delayMs = 0;
+        effect.primitive = CompositePrimitive::CLICK;
+
+        effect.scale = std::nextafter(0.0f, -1.0f);
+        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+                  vibrator->compose(composite, nullptr).exceptionCode());
+
+        effect.scale = 0.0f;
+        EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
+
+        effect.scale = 1.0f;
+        EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, nullptr).exceptionCode());
+
+        effect.scale = std::nextafter(1.0f, 2.0f);
+        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+                  vibrator->compose(composite, nullptr).exceptionCode());
+
+        vibrator->off();
+    }
+}
+
+TEST_P(VibratorAidl, ComposeDelayBoundary) {
     if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
         int32_t maxDelay;
 
@@ -357,7 +418,7 @@
     }
 }
 
-TEST_P(VibratorAidl, CompseSizeBoundary) {
+TEST_P(VibratorAidl, ComposeSizeBoundary) {
     if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
         int32_t maxSize;
 
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 f332001..2ea8841 100644
--- a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
@@ -377,7 +377,7 @@
 
     sp<IWifiP2pIface> iface;
     EXPECT_EQ(WifiStatusCode::SUCCESS, createP2pIface(&iface));
-    EXPECT_NE(nullptr, iface.get());
+    ASSERT_NE(nullptr, iface.get());
 
     std::string iface_name = getIfaceName(iface);
     const auto& status_and_iface_names2 =
@@ -404,7 +404,7 @@
 
     sp<IWifiP2pIface> p2p_iface;
     EXPECT_EQ(WifiStatusCode::SUCCESS, createP2pIface(&p2p_iface));
-    EXPECT_NE(nullptr, p2p_iface.get());
+    ASSERT_NE(nullptr, p2p_iface.get());
 
     std::string iface_name = getIfaceName(p2p_iface);
     const auto& status_and_iface1 =
@@ -430,7 +430,7 @@
 
     sp<IWifiP2pIface> p2p_iface;
     EXPECT_EQ(WifiStatusCode::SUCCESS, createP2pIface(&p2p_iface));
-    EXPECT_NE(nullptr, p2p_iface.get());
+    ASSERT_NE(nullptr, p2p_iface.get());
 
     std::string iface_name = getIfaceName(p2p_iface);
     std::string invalid_name = iface_name + "0";
@@ -470,7 +470,7 @@
 
     sp<IWifiStaIface> iface;
     EXPECT_EQ(WifiStatusCode::SUCCESS, createStaIface(&iface));
-    EXPECT_NE(nullptr, iface.get());
+    ASSERT_NE(nullptr, iface.get());
 
     std::string iface_name = getIfaceName(iface);
     const auto& status_and_iface_names2 =
@@ -497,7 +497,7 @@
 
     sp<IWifiStaIface> sta_iface;
     EXPECT_EQ(WifiStatusCode::SUCCESS, createStaIface(&sta_iface));
-    EXPECT_NE(nullptr, sta_iface.get());
+    ASSERT_NE(nullptr, sta_iface.get());
 
     std::string iface_name = getIfaceName(sta_iface);
     const auto& status_and_iface1 =
@@ -523,7 +523,7 @@
 
     sp<IWifiStaIface> sta_iface;
     EXPECT_EQ(WifiStatusCode::SUCCESS, createStaIface(&sta_iface));
-    EXPECT_NE(nullptr, sta_iface.get());
+    ASSERT_NE(nullptr, sta_iface.get());
 
     std::string iface_name = getIfaceName(sta_iface);
     std::string invalid_name = iface_name + "0";
@@ -542,7 +542,7 @@
 
     sp<IWifiStaIface> iface;
     EXPECT_EQ(WifiStatusCode::SUCCESS, createStaIface(&iface));
-    EXPECT_NE(nullptr, iface.get());
+    ASSERT_NE(nullptr, iface.get());
 
     const auto& status_and_rtt_controller =
         HIDL_INVOKE(wifi_chip_, createRttController, iface);
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 1eb9c99..1014c1d 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
@@ -59,10 +59,10 @@
     const std::string& instance_name = GetInstanceName();
 
     sp<IWifiChip> wifi_chip = getWifiChip(instance_name);
-    EXPECT_NE(nullptr, wifi_chip.get());
+    ASSERT_NE(nullptr, wifi_chip.get());
 
     sp<IWifiStaIface> wifi_sta_iface = getWifiStaIface(instance_name);
-    EXPECT_NE(nullptr, wifi_sta_iface.get());
+    ASSERT_NE(nullptr, wifi_sta_iface.get());
 
     const auto& status_and_controller =
         HIDL_INVOKE(wifi_chip, createRttController, wifi_sta_iface);