Merge "vibrator: Document the source of always-on source IDs." into rvc-dev
diff --git a/automotive/evs/1.0/vts/functional/Android.bp b/automotive/evs/1.0/vts/functional/Android.bp
index 8988bfd..9f7cd3f 100644
--- a/automotive/evs/1.0/vts/functional/Android.bp
+++ b/automotive/evs/1.0/vts/functional/Android.bp
@@ -28,7 +28,7 @@
         "android.hardware.automotive.evs@1.0",
         "android.hardware.automotive.evs@common-default-lib",
     ],
-    test_suites: ["general-tests"],
+    test_suites: ["vts-core"],
     cflags: [
         "-O0",
         "-g",
diff --git a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
index f7580f0..54862a2 100644
--- a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
+++ b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
@@ -17,15 +17,6 @@
 #define LOG_TAG "VtsHalEvsTest"
 
 
-// Note:  We have't got a great way to indicate which target
-// should be tested, so we'll leave the interface served by the
-// default (mock) EVS driver here for easy reference.  All
-// actual EVS drivers should serve on the EvsEnumeratorHw name,
-// however, so the code is checked in that way.
-//const static char kEnumeratorName[]  = "EvsEnumeratorHw-Mock";
-const static char kEnumeratorName[]  = "EvsEnumeratorHw";
-
-
 // These values are called out in the EVS design doc (as of Mar 8, 2017)
 static const int kMaxStreamStartMilliseconds = 500;
 static const int kMinimumFramesPerSecond = 10;
@@ -53,8 +44,9 @@
 #include <android/hardware/automotive/evs/1.0/IEvsCameraStream.h>
 #include <android/hardware/automotive/evs/1.0/IEvsDisplay.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 using namespace ::android::hardware::automotive::evs::V1_0;
 using ::android::hardware::Return;
@@ -64,32 +56,19 @@
 using ::android::hardware::hidl_string;
 using ::android::sp;
 
-// Test environment for Evs HIDL HAL.
-class EvsHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static EvsHidlEnvironment* Instance() {
-        static EvsHidlEnvironment* instance = new EvsHidlEnvironment;
-        return instance;
-    }
-
-    virtual void registerTestServices() override { registerTestService<IEvsEnumerator>(); }
-
-   private:
-    EvsHidlEnvironment() {}
-};
-
 // The main test class for EVS
-class EvsHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class EvsHidlTest : public ::testing::TestWithParam<std::string> {
 public:
     virtual void SetUp() override {
         // Make sure we can connect to the enumerator
-        string service_name =
-            EvsHidlEnvironment::Instance()->getServiceName<IEvsEnumerator>(kEnumeratorName);
-        pEnumerator = getService<IEvsEnumerator>(service_name);
+        std::string service_name = GetParam();
+        pEnumerator = IEvsEnumerator::getService(service_name);
+
         ASSERT_NE(pEnumerator.get(), nullptr);
 
-        mIsHwModule = !service_name.compare(kEnumeratorName);
+        // "default" is reserved for EVS manager.
+        constexpr static char kEvsManagerName[] = "default";
+        mIsHwModule = service_name.compare(kEvsManagerName);
     }
 
     virtual void TearDown() override {}
@@ -130,7 +109,7 @@
  * Opens each camera reported by the enumerator and then explicitly closes it via a
  * call to closeCamera.  Then repeats the test to ensure all cameras can be reopened.
  */
-TEST_F(EvsHidlTest, CameraOpenClean) {
+TEST_P(EvsHidlTest, CameraOpenClean) {
     ALOGI("Starting CameraOpenClean test");
 
     // Get the camera list
@@ -162,7 +141,7 @@
  * call.  This ensures that the intended "aggressive open" behavior works.  This is necessary for
  * the system to be tolerant of shutdown/restart race conditions.
  */
-TEST_F(EvsHidlTest, CameraOpenAggressive) {
+TEST_P(EvsHidlTest, CameraOpenAggressive) {
     ALOGI("Starting CameraOpenAggressive test");
 
     // Get the camera list
@@ -216,7 +195,7 @@
  * DisplayOpen:
  * Test both clean shut down and "aggressive open" device stealing behavior.
  */
-TEST_F(EvsHidlTest, DisplayOpen) {
+TEST_P(EvsHidlTest, DisplayOpen) {
     ALOGI("Starting DisplayOpen test");
 
     // Request exclusive access to the EVS display, then let it go
@@ -264,7 +243,7 @@
  * Validate that display states transition as expected and can be queried from either the display
  * object itself or the owning enumerator.
  */
-TEST_F(EvsHidlTest, DisplayStates) {
+TEST_P(EvsHidlTest, DisplayStates) {
     ALOGI("Starting DisplayStates test");
 
     // Ensure the display starts in the expected state
@@ -324,7 +303,7 @@
  * CameraStreamPerformance:
  * Measure and qualify the stream start up time and streaming frame rate of each reported camera
  */
-TEST_F(EvsHidlTest, CameraStreamPerformance) {
+TEST_P(EvsHidlTest, CameraStreamPerformance) {
     ALOGI("Starting CameraStreamPerformance test");
 
     // Get the camera list
@@ -387,7 +366,7 @@
  * Ensure the camera implementation behaves properly when the client holds onto buffers for more
  * than one frame time.  The camera must cleanly skip frames until the client is ready again.
  */
-TEST_F(EvsHidlTest, CameraStreamBuffering) {
+TEST_P(EvsHidlTest, CameraStreamBuffering) {
     ALOGI("Starting CameraStreamBuffering test");
 
     // Arbitrary constant (should be > 1 and less than crazy)
@@ -456,7 +435,7 @@
  * imagery is simply copied to the display buffer and presented on screen.  This is the one test
  * which a human could observe to see the operation of the system on the physical display.
  */
-TEST_F(EvsHidlTest, CameraToDisplayRoundTrip) {
+TEST_P(EvsHidlTest, CameraToDisplayRoundTrip) {
     ALOGI("Starting CameraToDisplayRoundTrip test");
 
     // Get the camera list
@@ -517,7 +496,7 @@
  * Verify that each client can start and stop video streams on the same
  * underlying camera.
  */
-TEST_F(EvsHidlTest, MultiCameraStream) {
+TEST_P(EvsHidlTest, MultiCameraStream) {
     ALOGI("Starting MultiCameraStream test");
 
     if (mIsHwModule) {
@@ -601,11 +580,8 @@
 }
 
 
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(EvsHidlEnvironment::Instance());
-    ::testing::InitGoogleTest(&argc, argv);
-    EvsHidlEnvironment::Instance()->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    ALOGI("Test result = %d", status);
-    return status;
-}
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance,
+    EvsHidlTest,
+    testing::ValuesIn(android::hardware::getAllHalInstanceNames(IEvsEnumerator::descriptor)),
+    android::hardware::PrintInstanceNameToString);
diff --git a/boot/1.1/default/boot_control/Android.bp b/boot/1.1/default/boot_control/Android.bp
new file mode 100644
index 0000000..b2e68df
--- /dev/null
+++ b/boot/1.1/default/boot_control/Android.bp
@@ -0,0 +1,61 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_defaults {
+    name: "libboot_control_defaults",
+    vendor: true,
+    recovery_available: true,
+    relative_install_path: "hw",
+
+    cflags: [
+        "-D_FILE_OFFSET_BITS=64",
+        "-Werror",
+        "-Wall",
+        "-Wextra",
+    ],
+
+    shared_libs: [
+        "android.hardware.boot@1.1",
+        "libbase",
+        "liblog",
+    ],
+    static_libs: [
+        "libbootloader_message_vendor",
+        "libfstab",
+    ],
+}
+
+cc_library_static {
+    name: "libboot_control",
+    defaults: ["libboot_control_defaults"],
+    export_include_dirs: ["include"],
+
+    srcs: ["libboot_control.cpp"],
+}
+
+cc_library_shared {
+    name: "bootctrl.default",
+    defaults: ["libboot_control_defaults"],
+
+    srcs: ["legacy_boot_control.cpp"],
+
+    static_libs: [
+        "libboot_control",
+    ],
+    shared_libs: [
+        "libhardware",
+    ],
+}
diff --git a/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h b/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h
new file mode 100644
index 0000000..5468658
--- /dev/null
+++ b/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h
@@ -0,0 +1,89 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#pragma once
+
+#include <string>
+
+#include <android/hardware/boot/1.1/IBootControl.h>
+
+namespace android {
+namespace bootable {
+
+// Helper library to implement the IBootControl HAL using the misc partition.
+class BootControl {
+  using MergeStatus = ::android::hardware::boot::V1_1::MergeStatus;
+
+ public:
+  bool Init();
+  unsigned int GetNumberSlots();
+  unsigned int GetCurrentSlot();
+  bool MarkBootSuccessful();
+  bool SetActiveBootSlot(unsigned int slot);
+  bool SetSlotAsUnbootable(unsigned int slot);
+  bool SetSlotBootable(unsigned int slot);
+  bool IsSlotBootable(unsigned int slot);
+  const char* GetSuffix(unsigned int slot);
+  bool IsSlotMarkedSuccessful(unsigned int slot);
+  bool SetSnapshotMergeStatus(MergeStatus status);
+  MergeStatus GetSnapshotMergeStatus();
+
+  bool IsValidSlot(unsigned int slot);
+
+  const std::string& misc_device() const {
+    return misc_device_;
+  }
+
+ private:
+  // Whether this object was initialized with data from the bootloader message
+  // that doesn't change until next reboot.
+  bool initialized_ = false;
+
+  // The path to the misc_device as reported in the fstab.
+  std::string misc_device_;
+
+  // The number of slots present on the device.
+  unsigned int num_slots_ = 0;
+
+  // The slot where we are running from.
+  unsigned int current_slot_ = 0;
+};
+
+// Helper functions to write the Virtual A/B merge status message. These are
+// separate because BootControl uses bootloader_control_ab in vendor space,
+// whereas the Virtual A/B merge status is in system space. A HAL might not
+// use bootloader_control_ab, but may want to use the AOSP method of maintaining
+// the merge status.
+
+// If the Virtual A/B message has not yet been initialized, then initialize it.
+// This should be called when the BootControl HAL first loads.
+//
+// If the Virtual A/B message in misc was already initialized, true is returned.
+// If initialization was attempted, but failed, false is returned, and the HAL
+// should fail to load.
+bool InitMiscVirtualAbMessageIfNeeded();
+
+// Save the current merge status as well as the current slot.
+bool SetMiscVirtualAbMergeStatus(unsigned int current_slot,
+                                 android::hardware::boot::V1_1::MergeStatus status);
+
+// Return the current merge status. If the saved status is SNAPSHOTTED but the
+// slot hasn't changed, the status returned will be NONE.
+bool GetMiscVirtualAbMergeStatus(unsigned int current_slot,
+                                 android::hardware::boot::V1_1::MergeStatus* status);
+
+}  // namespace bootable
+}  // namespace android
diff --git a/boot/1.1/default/boot_control/include/private/boot_control_definition.h b/boot/1.1/default/boot_control/include/private/boot_control_definition.h
new file mode 100644
index 0000000..8f02111
--- /dev/null
+++ b/boot/1.1/default/boot_control/include/private/boot_control_definition.h
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+
+/**
+ * The A/B-specific bootloader message structure (4-KiB).
+ *
+ * We separate A/B boot control metadata from the regular bootloader
+ * message struct and keep it here. Everything that's A/B-specific
+ * stays after struct bootloader_message, which belongs to the vendor
+ * space of /misc partition. Also, the A/B-specific contents should be
+ * managed by the A/B-bootloader or boot control HAL.
+ *
+ * The slot_suffix field is used for A/B implementations where the
+ * bootloader does not set the androidboot.ro.boot.slot_suffix kernel
+ * commandline parameter. This is used by fs_mgr to mount /system and
+ * other partitions with the slotselect flag set in fstab. A/B
+ * implementations are free to use all 32 bytes and may store private
+ * data past the first NUL-byte in this field. It is encouraged, but
+ * not mandatory, to use 'struct bootloader_control' described below.
+ *
+ * The update_channel field is used to store the Omaha update channel
+ * if update_engine is compiled with Omaha support.
+ */
+struct bootloader_message_ab {
+    struct bootloader_message message;
+    char slot_suffix[32];
+    char update_channel[128];
+
+    // Round up the entire struct to 4096-byte.
+    char reserved[1888];
+};
+
+/**
+ * Be cautious about the struct size change, in case we put anything post
+ * bootloader_message_ab struct (b/29159185).
+ */
+#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus)
+static_assert(sizeof(struct bootloader_message_ab) == 4096,
+              "struct bootloader_message_ab size changes");
+#endif
+
+#define BOOT_CTRL_MAGIC   0x42414342 /* Bootloader Control AB */
+#define BOOT_CTRL_VERSION 1
+
+struct slot_metadata {
+    // Slot priority with 15 meaning highest priority, 1 lowest
+    // priority and 0 the slot is unbootable.
+    uint8_t priority : 4;
+    // Number of times left attempting to boot this slot.
+    uint8_t tries_remaining : 3;
+    // 1 if this slot has booted successfully, 0 otherwise.
+    uint8_t successful_boot : 1;
+    // 1 if this slot is corrupted from a dm-verity corruption, 0
+    // otherwise.
+    uint8_t verity_corrupted : 1;
+    // Reserved for further use.
+    uint8_t reserved : 7;
+} __attribute__((packed));
+
+/* Bootloader Control AB
+ *
+ * This struct can be used to manage A/B metadata. It is designed to
+ * be put in the 'slot_suffix' field of the 'bootloader_message'
+ * structure described above. It is encouraged to use the
+ * 'bootloader_control' structure to store the A/B metadata, but not
+ * mandatory.
+ */
+struct bootloader_control {
+    // NUL terminated active slot suffix.
+    char slot_suffix[4];
+    // Bootloader Control AB magic number (see BOOT_CTRL_MAGIC).
+    uint32_t magic;
+    // Version of struct being used (see BOOT_CTRL_VERSION).
+    uint8_t version;
+    // Number of slots being managed.
+    uint8_t nb_slot : 3;
+    // Number of times left attempting to boot recovery.
+    uint8_t recovery_tries_remaining : 3;
+    // Status of any pending snapshot merge of dynamic partitions.
+    uint8_t merge_status : 3;
+    // Ensure 4-bytes alignment for slot_info field.
+    uint8_t reserved0[1];
+    // Per-slot information.  Up to 4 slots.
+    struct slot_metadata slot_info[4];
+    // Reserved for further use.
+    uint8_t reserved1[8];
+    // CRC32 of all 28 bytes preceding this field (little endian
+    // format).
+    uint32_t crc32_le;
+} __attribute__((packed));
+
+#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus)
+static_assert(sizeof(struct bootloader_control) ==
+              sizeof(((struct bootloader_message_ab *)0)->slot_suffix),
+              "struct bootloader_control has wrong size");
+#endif
+
diff --git a/boot/1.1/default/boot_control/legacy_boot_control.cpp b/boot/1.1/default/boot_control/legacy_boot_control.cpp
new file mode 100644
index 0000000..73d3a58
--- /dev/null
+++ b/boot/1.1/default/boot_control/legacy_boot_control.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2015 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 <string>
+
+#include <hardware/boot_control.h>
+#include <hardware/hardware.h>
+
+#include <libboot_control/libboot_control.h>
+
+using android::bootable::BootControl;
+
+struct boot_control_private_t {
+  // The base struct needs to be first in the list.
+  boot_control_module_t base;
+
+  BootControl impl;
+};
+
+namespace {
+
+void BootControl_init(boot_control_module_t* module) {
+  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+  impl.Init();
+}
+
+unsigned int BootControl_getNumberSlots(boot_control_module_t* module) {
+  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+  return impl.GetNumberSlots();
+}
+
+unsigned int BootControl_getCurrentSlot(boot_control_module_t* module) {
+  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+  return impl.GetCurrentSlot();
+}
+
+int BootControl_markBootSuccessful(boot_control_module_t* module) {
+  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+  return impl.MarkBootSuccessful() ? 0 : -1;
+}
+
+int BootControl_setActiveBootSlot(boot_control_module_t* module, unsigned int slot) {
+  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+  return impl.SetActiveBootSlot(slot) ? 0 : -1;
+}
+
+int BootControl_setSlotAsUnbootable(struct boot_control_module* module, unsigned int slot) {
+  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+  return impl.SetSlotAsUnbootable(slot) ? 0 : -1;
+}
+
+int BootControl_isSlotBootable(struct boot_control_module* module, unsigned int slot) {
+  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+  return impl.IsSlotBootable(slot) ? 0 : -1;
+}
+
+int BootControl_isSlotMarkedSuccessful(struct boot_control_module* module, unsigned int slot) {
+  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+  return impl.IsSlotMarkedSuccessful(slot) ? 0 : -1;
+}
+
+const char* BootControl_getSuffix(boot_control_module_t* module, unsigned int slot) {
+  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+  return impl.GetSuffix(slot);
+}
+
+static int BootControl_open(const hw_module_t* module __unused, const char* id __unused,
+                            hw_device_t** device __unused) {
+  /* Nothing to do currently. */
+  return 0;
+}
+
+struct hw_module_methods_t BootControl_methods = {
+  .open = BootControl_open,
+};
+
+}  // namespace
+
+boot_control_private_t HAL_MODULE_INFO_SYM = {
+  .base =
+      {
+          .common =
+              {
+                  .tag = HARDWARE_MODULE_TAG,
+                  .module_api_version = BOOT_CONTROL_MODULE_API_VERSION_0_1,
+                  .hal_api_version = HARDWARE_HAL_API_VERSION,
+                  .id = BOOT_CONTROL_HARDWARE_MODULE_ID,
+                  .name = "AOSP reference bootctrl HAL",
+                  .author = "The Android Open Source Project",
+                  .methods = &BootControl_methods,
+              },
+          .init = BootControl_init,
+          .getNumberSlots = BootControl_getNumberSlots,
+          .getCurrentSlot = BootControl_getCurrentSlot,
+          .markBootSuccessful = BootControl_markBootSuccessful,
+          .setActiveBootSlot = BootControl_setActiveBootSlot,
+          .setSlotAsUnbootable = BootControl_setSlotAsUnbootable,
+          .isSlotBootable = BootControl_isSlotBootable,
+          .getSuffix = BootControl_getSuffix,
+          .isSlotMarkedSuccessful = BootControl_isSlotMarkedSuccessful,
+      },
+};
diff --git a/boot/1.1/default/boot_control/libboot_control.cpp b/boot/1.1/default/boot_control/libboot_control.cpp
new file mode 100644
index 0000000..2c6ccaf
--- /dev/null
+++ b/boot/1.1/default/boot_control/libboot_control.cpp
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2015 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 <libboot_control/libboot_control.h>
+
+#include <endian.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <string>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+#include <bootloader_message/bootloader_message.h>
+
+#include "private/boot_control_definition.h"
+
+namespace android {
+namespace bootable {
+
+using ::android::hardware::boot::V1_1::MergeStatus;
+
+// The number of boot attempts that should be made from a new slot before
+// rolling back to the previous slot.
+constexpr unsigned int kDefaultBootAttempts = 7;
+static_assert(kDefaultBootAttempts < 8, "tries_remaining field only has 3 bits");
+
+constexpr unsigned int kMaxNumSlots =
+    sizeof(bootloader_control::slot_info) / sizeof(bootloader_control::slot_info[0]);
+constexpr const char* kSlotSuffixes[kMaxNumSlots] = { "_a", "_b", "_c", "_d" };
+constexpr off_t kBootloaderControlOffset = offsetof(bootloader_message_ab, slot_suffix);
+
+static uint32_t CRC32(const uint8_t* buf, size_t size) {
+  static uint32_t crc_table[256];
+
+  // Compute the CRC-32 table only once.
+  if (!crc_table[1]) {
+    for (uint32_t i = 0; i < 256; ++i) {
+      uint32_t crc = i;
+      for (uint32_t j = 0; j < 8; ++j) {
+        uint32_t mask = -(crc & 1);
+        crc = (crc >> 1) ^ (0xEDB88320 & mask);
+      }
+      crc_table[i] = crc;
+    }
+  }
+
+  uint32_t ret = -1;
+  for (size_t i = 0; i < size; ++i) {
+    ret = (ret >> 8) ^ crc_table[(ret ^ buf[i]) & 0xFF];
+  }
+
+  return ~ret;
+}
+
+// Return the little-endian representation of the CRC-32 of the first fields
+// in |boot_ctrl| up to the crc32_le field.
+uint32_t BootloaderControlLECRC(const bootloader_control* boot_ctrl) {
+  return htole32(
+      CRC32(reinterpret_cast<const uint8_t*>(boot_ctrl), offsetof(bootloader_control, crc32_le)));
+}
+
+bool LoadBootloaderControl(const std::string& misc_device, bootloader_control* buffer) {
+  android::base::unique_fd fd(open(misc_device.c_str(), O_RDONLY));
+  if (fd.get() == -1) {
+    PLOG(ERROR) << "failed to open " << misc_device;
+    return false;
+  }
+  if (lseek(fd, kBootloaderControlOffset, SEEK_SET) != kBootloaderControlOffset) {
+    PLOG(ERROR) << "failed to lseek " << misc_device;
+    return false;
+  }
+  if (!android::base::ReadFully(fd.get(), buffer, sizeof(bootloader_control))) {
+    PLOG(ERROR) << "failed to read " << misc_device;
+    return false;
+  }
+  return true;
+}
+
+bool UpdateAndSaveBootloaderControl(const std::string& misc_device, bootloader_control* buffer) {
+  buffer->crc32_le = BootloaderControlLECRC(buffer);
+  android::base::unique_fd fd(open(misc_device.c_str(), O_WRONLY | O_SYNC));
+  if (fd.get() == -1) {
+    PLOG(ERROR) << "failed to open " << misc_device;
+    return false;
+  }
+  if (lseek(fd.get(), kBootloaderControlOffset, SEEK_SET) != kBootloaderControlOffset) {
+    PLOG(ERROR) << "failed to lseek " << misc_device;
+    return false;
+  }
+  if (!android::base::WriteFully(fd.get(), buffer, sizeof(bootloader_control))) {
+    PLOG(ERROR) << "failed to write " << misc_device;
+    return false;
+  }
+  return true;
+}
+
+void InitDefaultBootloaderControl(BootControl* control, bootloader_control* boot_ctrl) {
+  memset(boot_ctrl, 0, sizeof(*boot_ctrl));
+
+  unsigned int current_slot = control->GetCurrentSlot();
+  if (current_slot < kMaxNumSlots) {
+    strlcpy(boot_ctrl->slot_suffix, kSlotSuffixes[current_slot], sizeof(boot_ctrl->slot_suffix));
+  }
+  boot_ctrl->magic = BOOT_CTRL_MAGIC;
+  boot_ctrl->version = BOOT_CTRL_VERSION;
+
+  // Figure out the number of slots by checking if the partitions exist,
+  // otherwise assume the maximum supported by the header.
+  boot_ctrl->nb_slot = kMaxNumSlots;
+  std::string base_path = control->misc_device();
+  size_t last_path_sep = base_path.rfind('/');
+  if (last_path_sep != std::string::npos) {
+    // We test the existence of the "boot" partition on each possible slot,
+    // which is a partition required by Android Bootloader Requirements.
+    base_path = base_path.substr(0, last_path_sep + 1) + "boot";
+    int last_existing_slot = -1;
+    int first_missing_slot = -1;
+    for (unsigned int slot = 0; slot < kMaxNumSlots; ++slot) {
+      std::string partition_path = base_path + kSlotSuffixes[slot];
+      struct stat part_stat;
+      int err = stat(partition_path.c_str(), &part_stat);
+      if (!err) {
+        last_existing_slot = slot;
+        LOG(INFO) << "Found slot: " << kSlotSuffixes[slot];
+      } else if (err < 0 && errno == ENOENT && first_missing_slot == -1) {
+        first_missing_slot = slot;
+      }
+    }
+    // We only declare that we found the actual number of slots if we found all
+    // the boot partitions up to the number of slots, and no boot partition
+    // after that. Not finding any of the boot partitions implies a problem so
+    // we just leave the number of slots in the maximum value.
+    if ((last_existing_slot != -1 && last_existing_slot + 1 == first_missing_slot) ||
+        (first_missing_slot == -1 && last_existing_slot + 1 == kMaxNumSlots)) {
+      boot_ctrl->nb_slot = last_existing_slot + 1;
+      LOG(INFO) << "Found a system with " << last_existing_slot + 1 << " slots.";
+    }
+  }
+
+  for (unsigned int slot = 0; slot < kMaxNumSlots; ++slot) {
+    slot_metadata entry = {};
+
+    if (slot < boot_ctrl->nb_slot) {
+      entry.priority = 7;
+      entry.tries_remaining = kDefaultBootAttempts;
+      entry.successful_boot = 0;
+    } else {
+      entry.priority = 0;  // Unbootable
+    }
+
+    // When the boot_control stored on disk is invalid, we assume that the
+    // current slot is successful. The bootloader should repair this situation
+    // before booting and write a valid boot_control slot, so if we reach this
+    // stage it means that the misc partition was corrupted since boot.
+    if (current_slot == slot) {
+      entry.successful_boot = 1;
+    }
+
+    boot_ctrl->slot_info[slot] = entry;
+  }
+  boot_ctrl->recovery_tries_remaining = 0;
+
+  boot_ctrl->crc32_le = BootloaderControlLECRC(boot_ctrl);
+}
+
+// Return the index of the slot suffix passed or -1 if not a valid slot suffix.
+int SlotSuffixToIndex(const char* suffix) {
+  for (unsigned int slot = 0; slot < kMaxNumSlots; ++slot) {
+    if (!strcmp(kSlotSuffixes[slot], suffix)) return slot;
+  }
+  return -1;
+}
+
+// Initialize the boot_control_private struct with the information from
+// the bootloader_message buffer stored in |boot_ctrl|. Returns whether the
+// initialization succeeded.
+bool BootControl::Init() {
+  if (initialized_) return true;
+
+  // Initialize the current_slot from the read-only property. If the property
+  // was not set (from either the command line or the device tree), we can later
+  // initialize it from the bootloader_control struct.
+  std::string suffix_prop = android::base::GetProperty("ro.boot.slot_suffix", "");
+  if (suffix_prop.empty()) {
+    LOG(ERROR) << "Slot suffix property is not set";
+    return false;
+  }
+  current_slot_ = SlotSuffixToIndex(suffix_prop.c_str());
+
+  std::string err;
+  std::string device = get_bootloader_message_blk_device(&err);
+  if (device.empty()) {
+    LOG(ERROR) << "Could not find bootloader message block device: " << err;
+    return false;
+  }
+
+  bootloader_control boot_ctrl;
+  if (!LoadBootloaderControl(device.c_str(), &boot_ctrl)) {
+    LOG(ERROR) << "Failed to load bootloader control block";
+    return false;
+  }
+
+  // Note that since there isn't a module unload function this memory is leaked.
+  // We use `device` below sometimes, so it's not moved out of here.
+  misc_device_ = device;
+  initialized_ = true;
+
+  // Validate the loaded data, otherwise we will destroy it and re-initialize it
+  // with the current information.
+  uint32_t computed_crc32 = BootloaderControlLECRC(&boot_ctrl);
+  if (boot_ctrl.crc32_le != computed_crc32) {
+    LOG(WARNING) << "Invalid boot control found, expected CRC-32 0x" << std::hex << computed_crc32
+                 << " but found 0x" << std::hex << boot_ctrl.crc32_le << ". Re-initializing.";
+    InitDefaultBootloaderControl(this, &boot_ctrl);
+    UpdateAndSaveBootloaderControl(device.c_str(), &boot_ctrl);
+  }
+
+  if (!InitMiscVirtualAbMessageIfNeeded()) {
+    return false;
+  }
+
+  num_slots_ = boot_ctrl.nb_slot;
+  return true;
+}
+
+unsigned int BootControl::GetNumberSlots() {
+  return num_slots_;
+}
+
+unsigned int BootControl::GetCurrentSlot() {
+  return current_slot_;
+}
+
+bool BootControl::MarkBootSuccessful() {
+  bootloader_control bootctrl;
+  if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+  bootctrl.slot_info[current_slot_].successful_boot = 1;
+  // tries_remaining == 0 means that the slot is not bootable anymore, make
+  // sure we mark the current slot as bootable if it succeeds in the last
+  // attempt.
+  bootctrl.slot_info[current_slot_].tries_remaining = 1;
+  return UpdateAndSaveBootloaderControl(misc_device_, &bootctrl);
+}
+
+bool BootControl::SetActiveBootSlot(unsigned int slot) {
+  if (slot >= kMaxNumSlots || slot >= num_slots_) {
+    // Invalid slot number.
+    return false;
+  }
+
+  bootloader_control bootctrl;
+  if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+  // Set every other slot with a lower priority than the new "active" slot.
+  const unsigned int kActivePriority = 15;
+  const unsigned int kActiveTries = 6;
+  for (unsigned int i = 0; i < num_slots_; ++i) {
+    if (i != slot) {
+      if (bootctrl.slot_info[i].priority >= kActivePriority)
+        bootctrl.slot_info[i].priority = kActivePriority - 1;
+    }
+  }
+
+  // Note that setting a slot as active doesn't change the successful bit.
+  // The successful bit will only be changed by setSlotAsUnbootable().
+  bootctrl.slot_info[slot].priority = kActivePriority;
+  bootctrl.slot_info[slot].tries_remaining = kActiveTries;
+
+  // Setting the current slot as active is a way to revert the operation that
+  // set *another* slot as active at the end of an updater. This is commonly
+  // used to cancel the pending update. We should only reset the verity_corrpted
+  // bit when attempting a new slot, otherwise the verity bit on the current
+  // slot would be flip.
+  if (slot != current_slot_) bootctrl.slot_info[slot].verity_corrupted = 0;
+
+  return UpdateAndSaveBootloaderControl(misc_device_, &bootctrl);
+}
+
+bool BootControl::SetSlotAsUnbootable(unsigned int slot) {
+  if (slot >= kMaxNumSlots || slot >= num_slots_) {
+    // Invalid slot number.
+    return false;
+  }
+
+  bootloader_control bootctrl;
+  if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+  // The only way to mark a slot as unbootable, regardless of the priority is to
+  // set the tries_remaining to 0.
+  bootctrl.slot_info[slot].successful_boot = 0;
+  bootctrl.slot_info[slot].tries_remaining = 0;
+  return UpdateAndSaveBootloaderControl(misc_device_, &bootctrl);
+}
+
+bool BootControl::IsSlotBootable(unsigned int slot) {
+  if (slot >= kMaxNumSlots || slot >= num_slots_) {
+    // Invalid slot number.
+    return false;
+  }
+
+  bootloader_control bootctrl;
+  if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+  return bootctrl.slot_info[slot].tries_remaining != 0;
+}
+
+bool BootControl::IsSlotMarkedSuccessful(unsigned int slot) {
+  if (slot >= kMaxNumSlots || slot >= num_slots_) {
+    // Invalid slot number.
+    return false;
+  }
+
+  bootloader_control bootctrl;
+  if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+  return bootctrl.slot_info[slot].successful_boot && bootctrl.slot_info[slot].tries_remaining;
+}
+
+bool BootControl::IsValidSlot(unsigned int slot) {
+  return slot < kMaxNumSlots && slot < num_slots_;
+}
+
+bool BootControl::SetSnapshotMergeStatus(MergeStatus status) {
+  return SetMiscVirtualAbMergeStatus(current_slot_, status);
+}
+
+MergeStatus BootControl::GetSnapshotMergeStatus() {
+  MergeStatus status;
+  if (!GetMiscVirtualAbMergeStatus(current_slot_, &status)) {
+    return MergeStatus::UNKNOWN;
+  }
+  return status;
+}
+
+const char* BootControl::GetSuffix(unsigned int slot) {
+  if (slot >= kMaxNumSlots || slot >= num_slots_) {
+    return nullptr;
+  }
+  return kSlotSuffixes[slot];
+}
+
+bool InitMiscVirtualAbMessageIfNeeded() {
+  std::string err;
+  misc_virtual_ab_message message;
+  if (!ReadMiscVirtualAbMessage(&message, &err)) {
+    LOG(ERROR) << "Could not read merge status: " << err;
+    return false;
+  }
+
+  if (message.version == MISC_VIRTUAL_AB_MESSAGE_VERSION &&
+      message.magic == MISC_VIRTUAL_AB_MAGIC_HEADER) {
+    // Already initialized.
+    return true;
+  }
+
+  message = {};
+  message.version = MISC_VIRTUAL_AB_MESSAGE_VERSION;
+  message.magic = MISC_VIRTUAL_AB_MAGIC_HEADER;
+  if (!WriteMiscVirtualAbMessage(message, &err)) {
+    LOG(ERROR) << "Could not write merge status: " << err;
+    return false;
+  }
+  return true;
+}
+
+bool SetMiscVirtualAbMergeStatus(unsigned int current_slot,
+                                 android::hardware::boot::V1_1::MergeStatus status) {
+  std::string err;
+  misc_virtual_ab_message message;
+
+  if (!ReadMiscVirtualAbMessage(&message, &err)) {
+    LOG(ERROR) << "Could not read merge status: " << err;
+    return false;
+  }
+
+  message.merge_status = static_cast<uint8_t>(status);
+  message.source_slot = current_slot;
+  if (!WriteMiscVirtualAbMessage(message, &err)) {
+    LOG(ERROR) << "Could not write merge status: " << err;
+    return false;
+  }
+  return true;
+}
+
+bool GetMiscVirtualAbMergeStatus(unsigned int current_slot,
+                                 android::hardware::boot::V1_1::MergeStatus* status) {
+  std::string err;
+  misc_virtual_ab_message message;
+
+  if (!ReadMiscVirtualAbMessage(&message, &err)) {
+    LOG(ERROR) << "Could not read merge status: " << err;
+    return false;
+  }
+
+  // If the slot reverted after having created a snapshot, then the snapshot will
+  // be thrown away at boot. Thus we don't count this as being in a snapshotted
+  // state.
+  *status = static_cast<MergeStatus>(message.merge_status);
+  if (*status == MergeStatus::SNAPSHOTTED && current_slot == message.source_slot) {
+    *status = MergeStatus::NONE;
+  }
+  return true;
+}
+
+}  // namespace bootable
+}  // namespace android
diff --git a/camera/common/1.0/default/Exif.cpp b/camera/common/1.0/default/Exif.cpp
index 4de05c5..413b6bb 100644
--- a/camera/common/1.0/default/Exif.cpp
+++ b/camera/common/1.0/default/Exif.cpp
@@ -632,13 +632,13 @@
 }
 
 bool ExifUtilsImpl::setImageHeight(uint32_t length) {
-    SET_LONG(EXIF_IFD_0, EXIF_TAG_IMAGE_LENGTH, length);
+    SET_SHORT(EXIF_IFD_0, EXIF_TAG_IMAGE_LENGTH, length);
     SET_LONG(EXIF_IFD_EXIF, EXIF_TAG_PIXEL_Y_DIMENSION, length);
     return true;
 }
 
 bool ExifUtilsImpl::setImageWidth(uint32_t width) {
-    SET_LONG(EXIF_IFD_0, EXIF_TAG_IMAGE_WIDTH, width);
+    SET_SHORT(EXIF_IFD_0, EXIF_TAG_IMAGE_WIDTH, width);
     SET_LONG(EXIF_IFD_EXIF, EXIF_TAG_PIXEL_X_DIMENSION, width);
     return true;
 }
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 5c73aa2..c9d76da 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -69,65 +69,67 @@
 #include <android/hidl/memory/1.0/IMemory.h>
 
 using namespace ::android::hardware::camera::device;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
+using ::android::BufferItemConsumer;
+using ::android::BufferQueue;
+using ::android::GraphicBuffer;
+using ::android::IGraphicBufferConsumer;
+using ::android::IGraphicBufferProducer;
+using ::android::sp;
+using ::android::Surface;
+using ::android::wp;
 using ::android::hardware::hidl_bitfield;
 using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
-using ::android::sp;
-using ::android::wp;
-using ::android::GraphicBuffer;
-using ::android::IGraphicBufferProducer;
-using ::android::IGraphicBufferConsumer;
-using ::android::BufferQueue;
-using ::android::BufferItemConsumer;
-using ::android::Surface;
-using ::android::hardware::graphics::common::V1_0::BufferUsage;
-using ::android::hardware::graphics::common::V1_0::Dataspace;
-using ::android::hardware::graphics::common::V1_0::PixelFormat;
-using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
 using ::android::hardware::camera::common::V1_0::CameraDeviceStatus;
+using ::android::hardware::camera::common::V1_0::Status;
 using ::android::hardware::camera::common::V1_0::TorchMode;
 using ::android::hardware::camera::common::V1_0::TorchModeStatus;
 using ::android::hardware::camera::common::V1_0::helper::CameraParameters;
 using ::android::hardware::camera::common::V1_0::helper::Size;
-using ::android::hardware::camera::provider::V2_4::ICameraProvider;
-using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
-using ::android::hardware::camera::device::V3_2::ICameraDevice;
-using ::android::hardware::camera::device::V3_2::BufferCache;
-using ::android::hardware::camera::device::V3_2::CaptureRequest;
-using ::android::hardware::camera::device::V3_2::CaptureResult;
-using ::android::hardware::camera::device::V3_2::ICameraDeviceSession;
-using ::android::hardware::camera::device::V3_2::NotifyMsg;
-using ::android::hardware::camera::device::V3_2::RequestTemplate;
-using ::android::hardware::camera::device::V3_2::StreamType;
-using ::android::hardware::camera::device::V3_2::StreamRotation;
-using ::android::hardware::camera::device::V3_2::StreamConfiguration;
-using ::android::hardware::camera::device::V3_2::StreamConfigurationMode;
-using ::android::hardware::camera::device::V3_2::CameraMetadata;
-using ::android::hardware::camera::device::V3_2::HalStreamConfiguration;
-using ::android::hardware::camera::device::V3_2::BufferStatus;
-using ::android::hardware::camera::device::V3_2::StreamBuffer;
-using ::android::hardware::camera::device::V3_2::MsgType;
-using ::android::hardware::camera::device::V3_2::ErrorMsg;
-using ::android::hardware::camera::device::V3_2::ErrorCode;
 using ::android::hardware::camera::device::V1_0::CameraFacing;
-using ::android::hardware::camera::device::V1_0::NotifyCallbackMsg;
+using ::android::hardware::camera::device::V1_0::CameraFrameMetadata;
 using ::android::hardware::camera::device::V1_0::CommandType;
 using ::android::hardware::camera::device::V1_0::DataCallbackMsg;
-using ::android::hardware::camera::device::V1_0::CameraFrameMetadata;
-using ::android::hardware::camera::device::V1_0::ICameraDevicePreviewCallback;
 using ::android::hardware::camera::device::V1_0::FrameCallbackFlag;
 using ::android::hardware::camera::device::V1_0::HandleTimestampMessage;
-using ::android::hardware::camera::metadata::V3_4::CameraMetadataEnumAndroidSensorInfoColorFilterArrangement;
-using ::android::hardware::camera::metadata::V3_4::CameraMetadataTag;
+using ::android::hardware::camera::device::V1_0::ICameraDevicePreviewCallback;
+using ::android::hardware::camera::device::V1_0::NotifyCallbackMsg;
+using ::android::hardware::camera::device::V3_2::BufferCache;
+using ::android::hardware::camera::device::V3_2::BufferStatus;
+using ::android::hardware::camera::device::V3_2::CameraMetadata;
+using ::android::hardware::camera::device::V3_2::CaptureRequest;
+using ::android::hardware::camera::device::V3_2::CaptureResult;
+using ::android::hardware::camera::device::V3_2::ErrorCode;
+using ::android::hardware::camera::device::V3_2::ErrorMsg;
+using ::android::hardware::camera::device::V3_2::HalStreamConfiguration;
+using ::android::hardware::camera::device::V3_2::ICameraDevice;
+using ::android::hardware::camera::device::V3_2::ICameraDeviceSession;
+using ::android::hardware::camera::device::V3_2::MsgType;
+using ::android::hardware::camera::device::V3_2::NotifyMsg;
+using ::android::hardware::camera::device::V3_2::RequestTemplate;
+using ::android::hardware::camera::device::V3_2::StreamBuffer;
+using ::android::hardware::camera::device::V3_2::StreamConfiguration;
+using ::android::hardware::camera::device::V3_2::StreamConfigurationMode;
+using ::android::hardware::camera::device::V3_2::StreamRotation;
+using ::android::hardware::camera::device::V3_2::StreamType;
 using ::android::hardware::camera::device::V3_4::PhysicalCameraMetadata;
-using ::android::hardware::MessageQueue;
-using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::camera::metadata::V3_4::
+        CameraMetadataEnumAndroidSensorInfoColorFilterArrangement;
+using ::android::hardware::camera::metadata::V3_4::CameraMetadataTag;
+using ::android::hardware::camera::provider::V2_4::ICameraProvider;
+using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
+using ::android::hardware::camera::provider::V2_6::CameraIdAndStreamCombination;
+using ::android::hardware::graphics::common::V1_0::BufferUsage;
+using ::android::hardware::graphics::common::V1_0::Dataspace;
+using ::android::hardware::graphics::common::V1_0::PixelFormat;
 using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
 using ::android::hidl::memory::V1_0::IMapper;
+using ::android::hidl::memory::V1_0::IMemory;
 using ResultMetadataQueue = MessageQueue<uint8_t, kSynchronizedReadWrite>;
 using ::android::hidl::manager::V1_0::IServiceManager;
 
@@ -554,7 +556,12 @@
 
  hidl_vec<hidl_string> getCameraDeviceNames(sp<ICameraProvider> provider);
 
-    struct EmptyDeviceCb : public V3_5::ICameraDeviceCallback {
+ std::map<hidl_string, hidl_string> getCameraDeviceIdToNameMap(sp<ICameraProvider> provider);
+
+ hidl_vec<hidl_vec<hidl_string>> getConcurrentDeviceCombinations(
+         sp<::android::hardware::camera::provider::V2_6::ICameraProvider>&);
+
+ struct EmptyDeviceCb : public V3_5::ICameraDeviceCallback {
      virtual Return<void> processCaptureResult(
          const hidl_vec<CaptureResult>& /*results*/) override {
          ALOGI("processCaptureResult callback");
@@ -591,8 +598,7 @@
          ADD_FAILURE();  // Empty callback should not reach here
          return Void();
      }
-
-    };
+ };
 
     struct DeviceCb : public V3_5::ICameraDeviceCallback {
         DeviceCb(CameraHidlTest *parent, int deviceVersion, const camera_metadata_t *staticMeta) :
@@ -808,6 +814,13 @@
     static Status getAvailableOutputStreams(const camera_metadata_t *staticMeta,
             std::vector<AvailableStream> &outputStreams,
             const AvailableStream *threshold = nullptr);
+
+    static Status getMaxOutputSizeForFormat(const camera_metadata_t* staticMeta, PixelFormat format,
+                                            Size* size);
+
+    static Status getMandatoryConcurrentStreams(const camera_metadata_t* staticMeta,
+                                                std::vector<AvailableStream>* outputStreams);
+
     static Status getJpegBufferSize(camera_metadata_t *staticMeta,
             uint32_t* outBufSize);
     static Status isConstrainedModeAvailable(camera_metadata_t *staticMeta);
@@ -1535,6 +1548,20 @@
     return Void();
 }
 
+std::map<hidl_string, hidl_string> CameraHidlTest::getCameraDeviceIdToNameMap(
+        sp<ICameraProvider> provider) {
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(provider);
+    std::map<hidl_string, hidl_string> idToNameMap;
+    for (auto& name : cameraDeviceNames) {
+        std::string version, cameraId;
+        if (!matchDeviceName(name, mProviderType, &version, &cameraId)) {
+            ADD_FAILURE();
+        }
+        idToNameMap.insert(std::make_pair(hidl_string(cameraId), name));
+    }
+    return idToNameMap;
+}
+
 hidl_vec<hidl_string> CameraHidlTest::getCameraDeviceNames(sp<ICameraProvider> provider) {
     std::vector<std::string> cameraDeviceNames;
     Return<void> ret;
@@ -1591,6 +1618,21 @@
     return retList;
 }
 
+hidl_vec<hidl_vec<hidl_string>> CameraHidlTest::getConcurrentDeviceCombinations(
+        sp<::android::hardware::camera::provider::V2_6::ICameraProvider>& provider2_6) {
+    hidl_vec<hidl_vec<hidl_string>> combinations;
+    Return<void> ret = provider2_6->getConcurrentStreamingCameraIds(
+            [&combinations](Status concurrentIdStatus,
+                            const hidl_vec<hidl_vec<hidl_string>>& cameraDeviceIdCombinations) {
+                ASSERT_EQ(concurrentIdStatus, Status::OK);
+                combinations = cameraDeviceIdCombinations;
+            });
+    if (!ret.isOk()) {
+        ADD_FAILURE();
+    }
+    return combinations;
+}
+
 // Test devices with first_api_level >= P does not advertise device@1.0
 TEST_P(CameraHidlTest, noHal1AfterP) {
     constexpr int32_t HAL1_PHASE_OUT_API_LEVEL = 28;
@@ -3078,6 +3120,157 @@
     }
 }
 
+// Verify that mandatory concurrent streams and outputs are supported.
+TEST_P(CameraHidlTest, configureConcurrentStreamsAvailableOutputs) {
+    struct CameraTestInfo {
+        camera_metadata_t* staticMeta = nullptr;
+        sp<ICameraDeviceSession> session;
+        sp<device::V3_3::ICameraDeviceSession> session3_3;
+        sp<device::V3_4::ICameraDeviceSession> session3_4;
+        sp<device::V3_5::ICameraDeviceSession> session3_5;
+        sp<device::V3_6::ICameraDeviceSession> session3_6;
+        sp<device::V3_2::ICameraDevice> cameraDevice;
+        sp<device::V3_5::ICameraDevice> cameraDevice3_5;
+        ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5;
+        ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
+        ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
+    };
+    if (mProvider2_6 == nullptr) {
+        // This test is provider@2.6 specific
+        ALOGW("%s provider not 2_6, skipping", __func__);
+        return;
+    }
+
+    std::map<hidl_string, hidl_string> idToNameMap = getCameraDeviceIdToNameMap(mProvider2_6);
+    hidl_vec<hidl_vec<hidl_string>> concurrentDeviceCombinations =
+            getConcurrentDeviceCombinations(mProvider2_6);
+    std::vector<AvailableStream> outputStreams;
+    for (const auto& cameraDeviceIds : concurrentDeviceCombinations) {
+        std::vector<CameraIdAndStreamCombination> cameraIdsAndStreamCombinations;
+        std::vector<CameraTestInfo> cameraTestInfos;
+        size_t i = 0;
+        for (const auto& id : cameraDeviceIds) {
+            CameraTestInfo cti;
+            Return<void> ret;
+            auto it = idToNameMap.find(id);
+            ASSERT_TRUE(idToNameMap.end() != it);
+            hidl_string name = it->second;
+            int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+            if (deviceVersion == CAMERA_DEVICE_API_VERSION_1_0) {
+                continue;
+            } else if (deviceVersion <= 0) {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+                return;
+            }
+            openEmptyDeviceSession(name, mProvider2_6, &cti.session /*out*/,
+                                   &cti.staticMeta /*out*/, &cti.cameraDevice /*out*/);
+            castSession(cti.session, deviceVersion, &cti.session3_3, &cti.session3_4,
+                        &cti.session3_5, &cti.session3_6);
+            castDevice(cti.cameraDevice, deviceVersion, &cti.cameraDevice3_5);
+
+            outputStreams.clear();
+            ASSERT_EQ(Status::OK, getMandatoryConcurrentStreams(cti.staticMeta, &outputStreams));
+            ASSERT_NE(0u, outputStreams.size());
+
+            uint32_t jpegBufferSize = 0;
+            ASSERT_EQ(Status::OK, getJpegBufferSize(cti.staticMeta, &jpegBufferSize));
+            ASSERT_NE(0u, jpegBufferSize);
+
+            int32_t streamId = 0;
+            ::android::hardware::hidl_vec<V3_2::Stream> streams3_2(outputStreams.size());
+            size_t j = 0;
+            for (const auto& it : outputStreams) {
+                V3_2::Stream stream3_2;
+                V3_2::DataspaceFlags dataspaceFlag = 0;
+                switch (static_cast<PixelFormat>(it.format)) {
+                    case PixelFormat::BLOB:
+                        dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::V0_JFIF);
+                        break;
+                    case PixelFormat::Y16:
+                        dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::DEPTH);
+                        break;
+                    default:
+                        dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::UNKNOWN);
+                }
+                stream3_2 = {streamId++,
+                             StreamType::OUTPUT,
+                             static_cast<uint32_t>(it.width),
+                             static_cast<uint32_t>(it.height),
+                             static_cast<PixelFormat>(it.format),
+                             GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+                             dataspaceFlag,
+                             StreamRotation::ROTATION_0};
+                streams3_2[j] = stream3_2;
+                j++;
+            }
+
+            // Add the created stream configs to cameraIdsAndStreamCombinations
+            createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE,
+                                      &cti.config3_2, &cti.config3_4, &cti.config3_5,
+                                      jpegBufferSize);
+
+            cti.config3_5.streamConfigCounter = outputStreams.size();
+            CameraIdAndStreamCombination cameraIdAndStreamCombination;
+            cameraIdAndStreamCombination.cameraId = id;
+            cameraIdAndStreamCombination.streamConfiguration = cti.config3_4;
+            cameraIdsAndStreamCombinations.push_back(cameraIdAndStreamCombination);
+            i++;
+            cameraTestInfos.push_back(cti);
+        }
+        // Now verify that concurrent streams are supported
+        auto cb = [](Status s, bool supported) {
+            ASSERT_EQ(Status::OK, s);
+            ASSERT_EQ(supported, true);
+        };
+
+        auto ret = mProvider2_6->isConcurrentStreamCombinationSupported(
+                cameraIdsAndStreamCombinations, cb);
+
+        // Test the stream can actually be configured
+        for (const auto& cti : cameraTestInfos) {
+            if (cti.session3_5 != nullptr) {
+                bool expectStreamCombQuery = (isLogicalMultiCamera(cti.staticMeta) == Status::OK);
+                verifyStreamCombination(cti.cameraDevice3_5, cti.config3_4,
+                                        /*expectedStatus*/ true, expectStreamCombQuery);
+                ret = cti.session3_5->configureStreams_3_5(
+                        cti.config3_5,
+                        [&cti](Status s, device::V3_4::HalStreamConfiguration halConfig) {
+                            ASSERT_EQ(Status::OK, s);
+                            ASSERT_EQ(cti.config3_5.v3_4.streams.size(), halConfig.streams.size());
+                        });
+            } else if (cti.session3_4 != nullptr) {
+                ret = cti.session3_4->configureStreams_3_4(
+                        cti.config3_4,
+                        [&cti](Status s, device::V3_4::HalStreamConfiguration halConfig) {
+                            ASSERT_EQ(Status::OK, s);
+                            ASSERT_EQ(cti.config3_4.streams.size(), halConfig.streams.size());
+                        });
+            } else if (cti.session3_3 != nullptr) {
+                ret = cti.session3_3->configureStreams_3_3(
+                        cti.config3_2,
+                        [&cti](Status s, device::V3_3::HalStreamConfiguration halConfig) {
+                            ASSERT_EQ(Status::OK, s);
+                            ASSERT_EQ(cti.config3_2.streams.size(), halConfig.streams.size());
+                        });
+            } else {
+                ret = cti.session->configureStreams(
+                        cti.config3_2, [&cti](Status s, HalStreamConfiguration halConfig) {
+                            ASSERT_EQ(Status::OK, s);
+                            ASSERT_EQ(cti.config3_2.streams.size(), halConfig.streams.size());
+                        });
+            }
+            ASSERT_TRUE(ret.isOk());
+        }
+
+        for (const auto& cti : cameraTestInfos) {
+            free_camera_metadata(cti.staticMeta);
+            ret = cti.session->close();
+            ASSERT_TRUE(ret.isOk());
+        }
+    }
+}
+
 // Check for correct handling of invalid/incorrect configuration parameters.
 TEST_P(CameraHidlTest, configureStreamsInvalidOutputs) {
     hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
@@ -5158,6 +5351,65 @@
     return Status::OK;
 }
 
+static Size getMinSize(Size a, Size b) {
+    if (a.width * a.height < b.width * b.height) {
+        return a;
+    }
+    return b;
+}
+
+// TODO: Add more combinations
+Status CameraHidlTest::getMandatoryConcurrentStreams(const camera_metadata_t* staticMeta,
+                                                     std::vector<AvailableStream>* outputStreams) {
+    if (nullptr == staticMeta) {
+        return Status::ILLEGAL_ARGUMENT;
+    }
+    Size yuvMaxSize(1280, 720);
+    Size jpegMaxSize(1920, 1440);
+    Size maxAvailableYuvSize;
+    Size maxAvailableJpegSize;
+    getMaxOutputSizeForFormat(staticMeta, PixelFormat::YCBCR_420_888, &maxAvailableYuvSize);
+    getMaxOutputSizeForFormat(staticMeta, PixelFormat::BLOB, &maxAvailableJpegSize);
+    Size yuvChosenSize = getMinSize(yuvMaxSize, maxAvailableYuvSize);
+    Size jpegChosenSize = getMinSize(jpegMaxSize, maxAvailableJpegSize);
+
+    AvailableStream yuvStream = {.width = yuvChosenSize.width,
+                                 .height = yuvChosenSize.height,
+                                 .format = static_cast<int32_t>(PixelFormat::YCBCR_420_888)};
+
+    AvailableStream jpegStream = {.width = jpegChosenSize.width,
+                                  .height = jpegChosenSize.height,
+                                  .format = static_cast<int32_t>(PixelFormat::BLOB)};
+    outputStreams->push_back(yuvStream);
+    outputStreams->push_back(jpegStream);
+
+    return Status::OK;
+}
+
+Status CameraHidlTest::getMaxOutputSizeForFormat(const camera_metadata_t* staticMeta,
+                                                 PixelFormat format, Size* size) {
+    std::vector<AvailableStream> outputStreams;
+    if (size == nullptr || getAvailableOutputStreams(staticMeta, outputStreams) != Status::OK) {
+        return Status::ILLEGAL_ARGUMENT;
+    }
+    Size maxSize;
+    bool found = false;
+    for (auto& outputStream : outputStreams) {
+        if (static_cast<int32_t>(format) == outputStream.format &&
+            (outputStream.width * outputStream.height > maxSize.width * maxSize.height)) {
+            maxSize.width = outputStream.width;
+            maxSize.height = outputStream.height;
+            found = true;
+        }
+    }
+    if (!found) {
+        ALOGE("%s :chosen format %d not found", __FUNCTION__, static_cast<int32_t>(format));
+        return Status::ILLEGAL_ARGUMENT;
+    }
+    *size = maxSize;
+    return Status::OK;
+}
+
 void CameraHidlTest::fillOutputStreams(camera_metadata_ro_entry_t* entry,
         std::vector<AvailableStream>& outputStreams, const AvailableStream* threshold,
         const int32_t availableConfigOutputTag) {
diff --git a/confirmationui/1.0/vts/functional/Android.bp b/confirmationui/1.0/vts/functional/Android.bp
index fd088cd..c8b522c 100644
--- a/confirmationui/1.0/vts/functional/Android.bp
+++ b/confirmationui/1.0/vts/functional/Android.bp
@@ -27,5 +27,5 @@
         "libcn-cbor",
         "android.hardware.confirmationui-support-lib",
     ],
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp b/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp
index fb01ad0..d953ab0 100644
--- a/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp
+++ b/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp
@@ -26,8 +26,12 @@
 #include <android/hardware/confirmationui/1.0/types.h>
 #include <android/hardware/confirmationui/support/confirmationui_utils.h>
 
+#include <gtest/gtest.h>
+
 #include <VtsHalHidlTargetCallbackBase.h>
-#include <VtsHalHidlTargetTestBase.h>
+
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include <openssl/hmac.h>
 #include <openssl/sha.h>
@@ -199,43 +203,18 @@
     }
 };
 
-class ConfirmationUIHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static ConfirmationUIHidlEnvironment* Instance() {
-        static ConfirmationUIHidlEnvironment* instance = new ConfirmationUIHidlEnvironment;
-        return instance;
-    }
-
-    void registerTestServices() override { registerTestService<IConfirmationUI>(); }
-
-   private:
-    ConfirmationUIHidlEnvironment(){};
-
-    GTEST_DISALLOW_COPY_AND_ASSIGN_(ConfirmationUIHidlEnvironment);
-};
-
-class ConfirmationUIHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-   public:
-    void TearDown() override { confirmator().abort(); }
-
-    static void SetUpTestCase() {
-        string service_name =
-            ConfirmationUIHidlEnvironment::Instance()->getServiceName<IConfirmationUI>();
-        confirmator_ = IConfirmationUI::getService(service_name);
+class ConfirmationUIHidlTest : public ::testing::TestWithParam<std::string> {
+  public:
+    void TearDown() override { confirmator_->abort(); }
+    void SetUp() override {
+        confirmator_ = IConfirmationUI::getService(GetParam());
         ASSERT_NE(nullptr, confirmator_.get());
     }
 
-    static void TearDownTestCase() { confirmator_.clear(); }
-
-    static IConfirmationUI& confirmator() { return *confirmator_; }
-
-   private:
-    static sp<IConfirmationUI> confirmator_;
+  protected:
+    sp<IConfirmationUI> confirmator_;
 };
 
-sp<IConfirmationUI> ConfirmationUIHidlTest::confirmator_;
-
 #define ASSERT_HAL_CALL(expected, call)                               \
     {                                                                 \
         auto result = call;                                           \
@@ -250,17 +229,17 @@
 typedef std::unique_ptr<cn_cbor, CnCborDeleter> CnCborPtr;
 
 // Simulates the User taping Ok
-TEST_F(ConfirmationUIHidlTest, UserOkTest) {
+TEST_P(ConfirmationUIHidlTest, UserOkTest) {
     static constexpr char test_prompt[] = "Me first, gimme gimme!";
     static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
     sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
     ASSERT_HAL_CALL(ResponseCode::OK,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
 
-    ASSERT_HAL_CALL(ResponseCode::OK, confirmator().deliverSecureInputEvent(
-                                          makeTestToken(TestModeCommands::OK_EVENT)));
+    ASSERT_HAL_CALL(ResponseCode::OK, confirmator_->deliverSecureInputEvent(
+                                              makeTestToken(TestModeCommands::OK_EVENT)));
 
     auto result = conf_cb->WaitForCallback();
     ASSERT_EQ(ResponseCode::OK, result.args->error_);
@@ -294,40 +273,40 @@
 }
 
 // Initiates a confirmation prompt with a message that is too long
-TEST_F(ConfirmationUIHidlTest, MessageTooLongTest) {
+TEST_P(ConfirmationUIHidlTest, MessageTooLongTest) {
     static constexpr uint8_t test_extra[static_cast<uint32_t>(MessageSize::MAX)] = {};
     static constexpr char test_prompt[] = "D\'oh!";
     sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + sizeof(test_extra));
     ASSERT_HAL_CALL(ResponseCode::UIErrorMessageTooLong,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
 }
 
 // If the message gets very long some HAL implementations might fail even before the message
 // reaches the trusted app implementation. But the HAL must still diagnose the correct error.
-TEST_F(ConfirmationUIHidlTest, MessageWayTooLongTest) {
+TEST_P(ConfirmationUIHidlTest, MessageWayTooLongTest) {
     static constexpr uint8_t test_extra[static_cast<uint32_t>(MessageSize::MAX) * 10] = {};
     static constexpr char test_prompt[] = "D\'oh!";
     sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + sizeof(test_extra));
     ASSERT_HAL_CALL(ResponseCode::UIErrorMessageTooLong,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
 }
 
 // Simulates the User tapping the Cancel
-TEST_F(ConfirmationUIHidlTest, UserCancelTest) {
+TEST_P(ConfirmationUIHidlTest, UserCancelTest) {
     static constexpr char test_prompt[] = "Me first, gimme gimme!";
     static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
     sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
     ASSERT_HAL_CALL(ResponseCode::OK,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
 
-    ASSERT_HAL_CALL(ResponseCode::OK, confirmator().deliverSecureInputEvent(
-                                          makeTestToken(TestModeCommands::CANCEL_EVENT)));
+    ASSERT_HAL_CALL(ResponseCode::OK, confirmator_->deliverSecureInputEvent(
+                                              makeTestToken(TestModeCommands::CANCEL_EVENT)));
 
     auto result = conf_cb->WaitForCallback();
     ASSERT_EQ(ResponseCode::Canceled, result.args->error_);
@@ -337,16 +316,16 @@
 }
 
 // Simulates the framework cancelling an ongoing prompt
-TEST_F(ConfirmationUIHidlTest, AbortTest) {
+TEST_P(ConfirmationUIHidlTest, AbortTest) {
     static constexpr char test_prompt[] = "Me first, gimme gimme!";
     static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
     sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
     ASSERT_HAL_CALL(ResponseCode::OK,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
 
-    confirmator().abort();
+    confirmator_->abort();
 
     auto result = conf_cb->WaitForCallback();
     ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
@@ -356,7 +335,7 @@
 
 // Tests if the confirmation dialog can successfully render 100 'W' characters as required by
 // the design guidelines.
-TEST_F(ConfirmationUIHidlTest, PortableMessageTest1) {
+TEST_P(ConfirmationUIHidlTest, PortableMessageTest1) {
     static constexpr char test_prompt[] =
             "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
             "WWWWWWWWWWWWWW";
@@ -365,9 +344,9 @@
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
     ASSERT_HAL_CALL(ResponseCode::OK,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
 
-    confirmator().abort();
+    confirmator_->abort();
 
     auto result = conf_cb->WaitForCallback();
     ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
@@ -377,7 +356,7 @@
 
 // Tests if the confirmation dialog can successfully render 100 'W' characters as required by
 // the design guidelines in magnified mode.
-TEST_F(ConfirmationUIHidlTest, PortableMessageTest1Magnified) {
+TEST_P(ConfirmationUIHidlTest, PortableMessageTest1Magnified) {
     static constexpr char test_prompt[] =
             "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
             "WWWWWWWWWWWWWW";
@@ -386,10 +365,10 @@
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
     ASSERT_HAL_CALL(ResponseCode::OK,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en",
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en",
                                                          {UIOption::AccessibilityMagnified}));
 
-    confirmator().abort();
+    confirmator_->abort();
 
     auto result = conf_cb->WaitForCallback();
     ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
@@ -399,7 +378,7 @@
 
 // Tests if the confirmation dialog can successfully render 8 groups of 12 'W' characters as
 // required by the design guidelines.
-TEST_F(ConfirmationUIHidlTest, PortableMessageTest2) {
+TEST_P(ConfirmationUIHidlTest, PortableMessageTest2) {
     static constexpr char test_prompt[] =
             "WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW "
             "WWWWWWWWWWWW WWWWWWWWWWWW";
@@ -408,9 +387,9 @@
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
     ASSERT_HAL_CALL(ResponseCode::OK,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
 
-    confirmator().abort();
+    confirmator_->abort();
 
     auto result = conf_cb->WaitForCallback();
     ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
@@ -420,7 +399,7 @@
 
 // Tests if the confirmation dialog can successfully render 8 groups of 12 'W' characters as
 // required by the design guidelines in magnified mode.
-TEST_F(ConfirmationUIHidlTest, PortableMessageTest2Magnified) {
+TEST_P(ConfirmationUIHidlTest, PortableMessageTest2Magnified) {
     static constexpr char test_prompt[] =
             "WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW "
             "WWWWWWWWWWWW WWWWWWWWWWWW";
@@ -429,10 +408,10 @@
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
     ASSERT_HAL_CALL(ResponseCode::OK,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en",
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en",
                                                          {UIOption::AccessibilityMagnified}));
 
-    confirmator().abort();
+    confirmator_->abort();
 
     auto result = conf_cb->WaitForCallback();
     ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
@@ -442,19 +421,19 @@
 
 // Passing malformed UTF-8 to the confirmation UI
 // This test passes a string that ends in the middle of a multibyte character
-TEST_F(ConfirmationUIHidlTest, MalformedUTF8Test1) {
+TEST_P(ConfirmationUIHidlTest, MalformedUTF8Test1) {
     static constexpr char test_prompt[] = {char(0xc0), 0};
     static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
     sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
     ASSERT_HAL_CALL(ResponseCode::UIErrorMalformedUTF8Encoding,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
 }
 
 // Passing malformed UTF-8 to the confirmation UI
 // This test passes a string with a 5-byte character.
-TEST_F(ConfirmationUIHidlTest, MalformedUTF8Test2) {
+TEST_P(ConfirmationUIHidlTest, MalformedUTF8Test2) {
     static constexpr char test_prompt[] = {char(0xf8), char(0x82), char(0x82),
                                            char(0x82), char(0x82), 0};
     static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
@@ -462,19 +441,19 @@
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
     ASSERT_HAL_CALL(ResponseCode::UIErrorMalformedUTF8Encoding,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
 }
 
 // Passing malformed UTF-8 to the confirmation UI
 // This test passes a string with a 2-byte character followed by a stray non UTF-8 character.
-TEST_F(ConfirmationUIHidlTest, MalformedUTF8Test3) {
+TEST_P(ConfirmationUIHidlTest, MalformedUTF8Test3) {
     static constexpr char test_prompt[] = {char(0xc0), char(0x82), char(0x83), 0};
     static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
     sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
     ASSERT_HAL_CALL(ResponseCode::UIErrorMalformedUTF8Encoding,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
 }
 
 // Test the implementation of HMAC SHA 256 against a golden blob.
@@ -494,16 +473,13 @@
     ASSERT_EQ(expected, result.value());
 }
 
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, ConfirmationUIHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IConfirmationUI::descriptor)),
+        android::hardware::PrintInstanceNameToString);
+
 }  // namespace test
 }  // namespace V1_0
 }  // namespace confirmationui
 }  // namespace hardware
 }  // namespace android
-
-int main(int argc, char** argv) {
-    ::testing::InitGoogleTest(&argc, argv);
-    std::vector<std::string> positional_args;
-    int status = RUN_ALL_TESTS();
-    ALOGI("Test result = %d", status);
-    return status;
-}
diff --git a/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc b/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc
index b659be8..fc2893f 100644
--- a/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc
+++ b/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc
@@ -1,5 +1,5 @@
 service vendor.contexthub-hal-1-0 /vendor/bin/hw/android.hardware.contexthub@1.0-service
     interface android.hardware.contexthub@1.0::IContexthub default
     class hal
-    user system
-    group system
+    user context_hub
+    group context_hub
diff --git a/contexthub/1.1/default/android.hardware.contexthub@1.1-service.rc b/contexthub/1.1/default/android.hardware.contexthub@1.1-service.rc
index 9db00f9..b00b1bd 100644
--- a/contexthub/1.1/default/android.hardware.contexthub@1.1-service.rc
+++ b/contexthub/1.1/default/android.hardware.contexthub@1.1-service.rc
@@ -2,5 +2,5 @@
     interface android.hardware.contexthub@1.0::IContexthub default
     interface android.hardware.contexthub@1.1::IContexthub default
     class hal
-    user system
-    group system
+    user context_hub
+    group context_hub
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index 295ba36..6cc5e34 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -221,7 +221,7 @@
                     case PlaneLayoutComponentType::Y:
                         ASSERT_EQ(nullptr, outYCbCr->y);
                         ASSERT_EQ(8, planeLayoutComponent.sizeInBits);
-                        ASSERT_EQ(8, planeLayout.sampleIncrementInBits);
+                        ASSERT_EQ(32, planeLayout.sampleIncrementInBits);
                         outYCbCr->y = tmpData;
                         outYCbCr->ystride = planeLayout.strideInBytes;
                         break;
diff --git a/sensors/1.0/default/android.hardware.sensors@1.0-service.rc b/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
index b41730b..1af6d0b 100644
--- a/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
+++ b/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
@@ -2,6 +2,6 @@
     interface android.hardware.sensors@1.0::ISensors default
     class hal
     user system
-    group system wakelock uhid
+    group system wakelock uhid context_hub
     capabilities BLOCK_SUSPEND
     rlimit rtprio 10 10
diff --git a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
index 1e5e886..aca6961 100644
--- a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
+++ b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
@@ -25,6 +25,13 @@
 using ::android::hardware::sensors::V1_0::Result;
 using ::android::hardware::sensors::V1_0::SensorInfo;
 
+void SensorsHidlEnvironmentV1_0::HidlTearDown() {
+    mStopThread = true;
+    if (mPollThread.joinable()) {
+        mPollThread.detach();
+    }
+}
+
 bool SensorsHidlEnvironmentV1_0::resetHal() {
     // wait upto 100ms * 10 = 1s for hidl service.
     constexpr auto RETRY_DELAY = std::chrono::milliseconds(100);
@@ -103,18 +110,23 @@
     ALOGD("polling thread start");
 
     while (!stop) {
-        env->sensors->poll(
-            64, [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
-                if (result != Result::OK ||
-                    (events.size() == 0 && dynamicSensorsAdded.size() == 0) || stop) {
-                    stop = true;
-                    return;
-                }
+        if (!env->sensors
+                     ->poll(64,
+                            [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
+                                if (result != Result::OK ||
+                                    (events.size() == 0 && dynamicSensorsAdded.size() == 0) ||
+                                    stop) {
+                                    stop = true;
+                                    return;
+                                }
 
-                for (const auto& e : events) {
-                    env->addEvent(e);
-                }
-            });
+                                for (const auto& e : events) {
+                                    env->addEvent(e);
+                                }
+                            })
+                     .isOk()) {
+            break;
+        }
     }
     ALOGD("polling thread end");
 }
\ No newline at end of file
diff --git a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
index 485ed1e..168777d 100644
--- a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
+++ b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
@@ -32,6 +32,8 @@
 class SensorsHidlEnvironmentV1_0
     : public SensorsHidlEnvironmentBase<::android::hardware::sensors::V1_0::Event> {
   public:
+    void HidlTearDown() override;
+
     using Event = ::android::hardware::sensors::V1_0::Event;
     SensorsHidlEnvironmentV1_0(const std::string& service_name)
         : SensorsHidlEnvironmentBase(service_name) {}
diff --git a/sensors/2.0/multihal/Android.bp b/sensors/2.0/multihal/Android.bp
index 24c475c..b7fa15a 100644
--- a/sensors/2.0/multihal/Android.bp
+++ b/sensors/2.0/multihal/Android.bp
@@ -92,3 +92,18 @@
         "android.hardware.sensors@2.0-ScopedWakelock",
     ],
 }
+
+cc_test_library {
+    name: "android.hardware.sensors@2.0-ScopedWakelock.testlib",
+    defaults: [
+        "hidl_defaults",
+        "android.hardware.sensors@2.0-multihal-defaults",
+    ],
+    srcs: [
+        "ScopedWakelock.cpp",
+    ],
+    vendor_available: true,
+    export_header_lib_headers: [
+        "android.hardware.sensors@2.0-multihal.header",
+    ],
+}
diff --git a/sensors/2.0/multihal/tests/Android.bp b/sensors/2.0/multihal/tests/Android.bp
index a9feaf7..472f3f3 100644
--- a/sensors/2.0/multihal/tests/Android.bp
+++ b/sensors/2.0/multihal/tests/Android.bp
@@ -80,11 +80,11 @@
     static_libs: [
         "android.hardware.sensors@2.0-HalProxy",
         "android.hardware.sensors@2.0-fakesubhal-unittest",
+        "android.hardware.sensors@2.0-ScopedWakelock.testlib",
     ],
     shared_libs: [
         "android.hardware.sensors@1.0",
         "android.hardware.sensors@2.0",
-        "android.hardware.sensors@2.0-ScopedWakelock",
         "libbase",
         "libcutils",
         "libfmq",
diff --git a/sensors/2.0/multihal/tests/HalProxy_test.cpp b/sensors/2.0/multihal/tests/HalProxy_test.cpp
index 1fd35d1..4633a75 100644
--- a/sensors/2.0/multihal/tests/HalProxy_test.cpp
+++ b/sensors/2.0/multihal/tests/HalProxy_test.cpp
@@ -724,6 +724,45 @@
     EXPECT_EQ(eventOut.sensorHandle, (subhal2Index << 24) | sensorHandleToPost);
 }
 
+TEST(HalProxyTest, FillAndDrainPendingQueueTest) {
+    constexpr size_t kQueueSize = 5;
+    // TODO: Make this constant linked to same limit in HalProxy.h
+    constexpr size_t kMaxPendingQueueSize = 100000;
+    AllSensorsSubHal subhal;
+    std::vector<ISensorsSubHal*> subHals{&subhal};
+
+    std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+    std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
+    ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+    EventFlag* eventQueueFlag;
+    EventFlag::createEventFlag(eventQueue->getEventFlagWord(), &eventQueueFlag);
+    HalProxy proxy(subHals);
+    proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
+
+    // Fill pending queue
+    std::vector<Event> events = makeMultipleAccelerometerEvents(kQueueSize);
+    subhal.postEvents(events, false);
+    events = makeMultipleAccelerometerEvents(kMaxPendingQueueSize);
+    subhal.postEvents(events, false);
+
+    // Drain pending queue
+    for (int i = 0; i < kMaxPendingQueueSize + kQueueSize; i += kQueueSize) {
+        ASSERT_TRUE(readEventsOutOfQueue(kQueueSize, eventQueue, eventQueueFlag));
+    }
+
+    // Put one event on pending queue
+    events = makeMultipleAccelerometerEvents(kQueueSize);
+    subhal.postEvents(events, false);
+    events = {makeAccelerometerEvent()};
+    subhal.postEvents(events, false);
+
+    // Read out to make room for one event on pending queue to write to FMQ
+    ASSERT_TRUE(readEventsOutOfQueue(kQueueSize, eventQueue, eventQueueFlag));
+
+    // Should be able to read that last event off queue
+    EXPECT_TRUE(readEventsOutOfQueue(1, eventQueue, eventQueueFlag));
+}
+
 // Helper implementations follow
 void testSensorsListFromProxyAndSubHal(const std::vector<SensorInfo>& proxySensorsList,
                                        const std::vector<SensorInfo>& subHalSensorsList) {
diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
index 8895350..a0d436f 100644
--- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
+++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
@@ -16,6 +16,261 @@
 
 #include "VtsHalSensorsV2_XTargetTest.h"
 
+// Test if sensor hal can do UI speed accelerometer streaming properly
+TEST_P(SensorsHidlTest, AccelerometerStreamingOperationSlow) {
+    testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(200),
+                           std::chrono::seconds(5), mAccelNormChecker);
+}
+
+// Test if sensor hal can do normal speed accelerometer streaming properly
+TEST_P(SensorsHidlTest, AccelerometerStreamingOperationNormal) {
+    testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(20),
+                           std::chrono::seconds(5), mAccelNormChecker);
+}
+
+// Test if sensor hal can do game speed accelerometer streaming properly
+TEST_P(SensorsHidlTest, AccelerometerStreamingOperationFast) {
+    testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(5),
+                           std::chrono::seconds(5), mAccelNormChecker);
+}
+
+// Test if sensor hal can do UI speed gyroscope streaming properly
+TEST_P(SensorsHidlTest, GyroscopeStreamingOperationSlow) {
+    testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(200),
+                           std::chrono::seconds(5), mGyroNormChecker);
+}
+
+// Test if sensor hal can do normal speed gyroscope streaming properly
+TEST_P(SensorsHidlTest, GyroscopeStreamingOperationNormal) {
+    testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(20),
+                           std::chrono::seconds(5), mGyroNormChecker);
+}
+
+// Test if sensor hal can do game speed gyroscope streaming properly
+TEST_P(SensorsHidlTest, GyroscopeStreamingOperationFast) {
+    testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(5),
+                           std::chrono::seconds(5), mGyroNormChecker);
+}
+
+// Test if sensor hal can do UI speed magnetometer streaming properly
+TEST_P(SensorsHidlTest, MagnetometerStreamingOperationSlow) {
+    testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(200),
+                           std::chrono::seconds(5), NullChecker<EventType>());
+}
+
+// Test if sensor hal can do normal speed magnetometer streaming properly
+TEST_P(SensorsHidlTest, MagnetometerStreamingOperationNormal) {
+    testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(20),
+                           std::chrono::seconds(5), NullChecker<EventType>());
+}
+
+// Test if sensor hal can do game speed magnetometer streaming properly
+TEST_P(SensorsHidlTest, MagnetometerStreamingOperationFast) {
+    testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(5),
+                           std::chrono::seconds(5), NullChecker<EventType>());
+}
+
+// Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active
+TEST_P(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) {
+    testSamplingRateHotSwitchOperation(SensorTypeVersion::ACCELEROMETER);
+    testSamplingRateHotSwitchOperation(SensorTypeVersion::ACCELEROMETER, false /*fastToSlow*/);
+}
+
+// Test if sensor hal can do gyroscope sampling rate switch properly when sensor is active
+TEST_P(SensorsHidlTest, GyroscopeSamplingPeriodHotSwitchOperation) {
+    testSamplingRateHotSwitchOperation(SensorTypeVersion::GYROSCOPE);
+    testSamplingRateHotSwitchOperation(SensorTypeVersion::GYROSCOPE, false /*fastToSlow*/);
+}
+
+// Test if sensor hal can do magnetometer sampling rate switch properly when sensor is active
+TEST_P(SensorsHidlTest, MagnetometerSamplingPeriodHotSwitchOperation) {
+    testSamplingRateHotSwitchOperation(SensorTypeVersion::MAGNETIC_FIELD);
+    testSamplingRateHotSwitchOperation(SensorTypeVersion::MAGNETIC_FIELD, false /*fastToSlow*/);
+}
+
+// Test if sensor hal can do accelerometer batching properly
+TEST_P(SensorsHidlTest, AccelerometerBatchingOperation) {
+    testBatchingOperation(SensorTypeVersion::ACCELEROMETER);
+}
+
+// Test if sensor hal can do gyroscope batching properly
+TEST_P(SensorsHidlTest, GyroscopeBatchingOperation) {
+    testBatchingOperation(SensorTypeVersion::GYROSCOPE);
+}
+
+// Test if sensor hal can do magnetometer batching properly
+TEST_P(SensorsHidlTest, MagnetometerBatchingOperation) {
+    testBatchingOperation(SensorTypeVersion::MAGNETIC_FIELD);
+}
+
+// Test sensor event direct report with ashmem for accel sensor at normal rate
+TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) {
+    testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM,
+                              RateLevel::NORMAL, mAccelNormChecker);
+}
+
+// Test sensor event direct report with ashmem for accel sensor at fast rate
+TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationFast) {
+    testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM,
+                              RateLevel::FAST, mAccelNormChecker);
+}
+
+// Test sensor event direct report with ashmem for accel sensor at very fast rate
+TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM,
+                              RateLevel::VERY_FAST, mAccelNormChecker);
+}
+
+// Test sensor event direct report with ashmem for gyro sensor at normal rate
+TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationNormal) {
+    testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM,
+                              RateLevel::NORMAL, mGyroNormChecker);
+}
+
+// Test sensor event direct report with ashmem for gyro sensor at fast rate
+TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationFast) {
+    testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::FAST,
+                              mGyroNormChecker);
+}
+
+// Test sensor event direct report with ashmem for gyro sensor at very fast rate
+TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM,
+                              RateLevel::VERY_FAST, mGyroNormChecker);
+}
+
+// Test sensor event direct report with ashmem for mag sensor at normal rate
+TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationNormal) {
+    testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM,
+                              RateLevel::NORMAL, NullChecker<EventType>());
+}
+
+// Test sensor event direct report with ashmem for mag sensor at fast rate
+TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationFast) {
+    testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM,
+                              RateLevel::FAST, NullChecker<EventType>());
+}
+
+// Test sensor event direct report with ashmem for mag sensor at very fast rate
+TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM,
+                              RateLevel::VERY_FAST, NullChecker<EventType>());
+}
+
+// Test sensor event direct report with gralloc for accel sensor at normal rate
+TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) {
+    testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC,
+                              RateLevel::NORMAL, mAccelNormChecker);
+}
+
+// Test sensor event direct report with gralloc for accel sensor at fast rate
+TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationFast) {
+    testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC,
+                              RateLevel::FAST, mAccelNormChecker);
+}
+
+// Test sensor event direct report with gralloc for accel sensor at very fast rate
+TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC,
+                              RateLevel::VERY_FAST, mAccelNormChecker);
+}
+
+// Test sensor event direct report with gralloc for gyro sensor at normal rate
+TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) {
+    testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC,
+                              RateLevel::NORMAL, mGyroNormChecker);
+}
+
+// Test sensor event direct report with gralloc for gyro sensor at fast rate
+TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationFast) {
+    testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::FAST,
+                              mGyroNormChecker);
+}
+
+// Test sensor event direct report with gralloc for gyro sensor at very fast rate
+TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC,
+                              RateLevel::VERY_FAST, mGyroNormChecker);
+}
+
+// Test sensor event direct report with gralloc for mag sensor at normal rate
+TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationNormal) {
+    testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC,
+                              RateLevel::NORMAL, NullChecker<EventType>());
+}
+
+// Test sensor event direct report with gralloc for mag sensor at fast rate
+TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationFast) {
+    testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC,
+                              RateLevel::FAST, NullChecker<EventType>());
+}
+
+// Test sensor event direct report with gralloc for mag sensor at very fast rate
+TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC,
+                              RateLevel::VERY_FAST, NullChecker<EventType>());
+}
+
+TEST_P(SensorsHidlTest, ConfigureDirectChannelWithInvalidHandle) {
+    SensorInfoType sensor;
+    SharedMemType memType;
+    RateLevel rate;
+    if (!getDirectChannelSensor(&sensor, &memType, &rate)) {
+        return;
+    }
+
+    // Verify that an invalid channel handle produces a BAD_VALUE result
+    configDirectReport(sensor.sensorHandle, -1, rate, [](Result result, int32_t /* reportToken */) {
+        ASSERT_EQ(result, Result::BAD_VALUE);
+    });
+}
+
+TEST_P(SensorsHidlTest, CleanupDirectConnectionOnInitialize) {
+    constexpr size_t kNumEvents = 1;
+    constexpr size_t kMemSize = kNumEvents * kEventSize;
+
+    SensorInfoType sensor;
+    SharedMemType memType;
+    RateLevel rate;
+
+    if (!getDirectChannelSensor(&sensor, &memType, &rate)) {
+        return;
+    }
+
+    std::shared_ptr<SensorsTestSharedMemory<SensorTypeVersion, EventType>> mem(
+            SensorsTestSharedMemory<SensorTypeVersion, EventType>::create(memType, kMemSize));
+    ASSERT_NE(mem, nullptr);
+
+    int32_t directChannelHandle = 0;
+    registerDirectChannel(mem->getSharedMemInfo(), [&](Result result, int32_t channelHandle) {
+        ASSERT_EQ(result, Result::OK);
+        directChannelHandle = channelHandle;
+    });
+
+    // Configure the channel and expect success
+    configDirectReport(
+            sensor.sensorHandle, directChannelHandle, rate,
+            [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::OK); });
+
+    // Call initialize() via the environment setup to cause the HAL to re-initialize
+    // Clear the active direct connections so they are not stopped during TearDown
+    auto handles = mDirectChannelHandles;
+    mDirectChannelHandles.clear();
+    getEnvironment()->HidlTearDown();
+    getEnvironment()->HidlSetUp();
+    if (HasFatalFailure()) {
+        return;  // Exit early if resetting the environment failed
+    }
+
+    // Attempt to configure the direct channel and expect it to fail
+    configDirectReport(
+            sensor.sensorHandle, directChannelHandle, rate,
+            [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::BAD_VALUE); });
+
+    // Restore original handles, though they should already be deactivated
+    mDirectChannelHandles = handles;
+}
+
 TEST_P(SensorsHidlTest, SensorListDoesntContainInvalidType) {
     getSensors()->getSensorsList([&](const auto& list) {
         const size_t count = list.size();
@@ -26,6 +281,21 @@
     });
 }
 
+TEST_P(SensorsHidlTest, FlushNonexistentSensor) {
+    SensorInfoType sensor;
+    std::vector<SensorInfoType> sensors = getNonOneShotSensors();
+    if (sensors.size() == 0) {
+        sensors = getOneShotSensors();
+        if (sensors.size() == 0) {
+            return;
+        }
+    }
+    sensor = sensors.front();
+    sensor.sensorHandle = getInvalidSensorHandle();
+    runSingleFlushTest(std::vector<SensorInfoType>{sensor}, false /* activateSensor */,
+                       0 /* expectedFlushCount */, Result::BAD_VALUE);
+}
+
 INSTANTIATE_TEST_SUITE_P(PerInstance, SensorsHidlTest,
                          testing::ValuesIn(android::hardware::getAllHalInstanceNames(
                                  android::hardware::sensors::V2_0::ISensors::descriptor)),
diff --git a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
index 53ed259..745ab2d 100644
--- a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
+++ b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
@@ -469,201 +469,6 @@
     ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL));
 }
 
-// Test if sensor hal can do UI speed accelerometer streaming properly
-TEST_P(SensorsHidlTest, AccelerometerStreamingOperationSlow) {
-    testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(200),
-                           std::chrono::seconds(5), mAccelNormChecker);
-}
-
-// Test if sensor hal can do normal speed accelerometer streaming properly
-TEST_P(SensorsHidlTest, AccelerometerStreamingOperationNormal) {
-    testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(20),
-                           std::chrono::seconds(5), mAccelNormChecker);
-}
-
-// Test if sensor hal can do game speed accelerometer streaming properly
-TEST_P(SensorsHidlTest, AccelerometerStreamingOperationFast) {
-    testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(5),
-                           std::chrono::seconds(5), mAccelNormChecker);
-}
-
-// Test if sensor hal can do UI speed gyroscope streaming properly
-TEST_P(SensorsHidlTest, GyroscopeStreamingOperationSlow) {
-    testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(200),
-                           std::chrono::seconds(5), mGyroNormChecker);
-}
-
-// Test if sensor hal can do normal speed gyroscope streaming properly
-TEST_P(SensorsHidlTest, GyroscopeStreamingOperationNormal) {
-    testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(20),
-                           std::chrono::seconds(5), mGyroNormChecker);
-}
-
-// Test if sensor hal can do game speed gyroscope streaming properly
-TEST_P(SensorsHidlTest, GyroscopeStreamingOperationFast) {
-    testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(5),
-                           std::chrono::seconds(5), mGyroNormChecker);
-}
-
-// Test if sensor hal can do UI speed magnetometer streaming properly
-TEST_P(SensorsHidlTest, MagnetometerStreamingOperationSlow) {
-    testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(200),
-                           std::chrono::seconds(5), NullChecker<EventType>());
-}
-
-// Test if sensor hal can do normal speed magnetometer streaming properly
-TEST_P(SensorsHidlTest, MagnetometerStreamingOperationNormal) {
-    testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(20),
-                           std::chrono::seconds(5), NullChecker<EventType>());
-}
-
-// Test if sensor hal can do game speed magnetometer streaming properly
-TEST_P(SensorsHidlTest, MagnetometerStreamingOperationFast) {
-    testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(5),
-                           std::chrono::seconds(5), NullChecker<EventType>());
-}
-
-// Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active
-TEST_P(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) {
-    testSamplingRateHotSwitchOperation(SensorTypeVersion::ACCELEROMETER);
-    testSamplingRateHotSwitchOperation(SensorTypeVersion::ACCELEROMETER, false /*fastToSlow*/);
-}
-
-// Test if sensor hal can do gyroscope sampling rate switch properly when sensor is active
-TEST_P(SensorsHidlTest, GyroscopeSamplingPeriodHotSwitchOperation) {
-    testSamplingRateHotSwitchOperation(SensorTypeVersion::GYROSCOPE);
-    testSamplingRateHotSwitchOperation(SensorTypeVersion::GYROSCOPE, false /*fastToSlow*/);
-}
-
-// Test if sensor hal can do magnetometer sampling rate switch properly when sensor is active
-TEST_P(SensorsHidlTest, MagnetometerSamplingPeriodHotSwitchOperation) {
-    testSamplingRateHotSwitchOperation(SensorTypeVersion::MAGNETIC_FIELD);
-    testSamplingRateHotSwitchOperation(SensorTypeVersion::MAGNETIC_FIELD, false /*fastToSlow*/);
-}
-
-// Test if sensor hal can do accelerometer batching properly
-TEST_P(SensorsHidlTest, AccelerometerBatchingOperation) {
-    testBatchingOperation(SensorTypeVersion::ACCELEROMETER);
-}
-
-// Test if sensor hal can do gyroscope batching properly
-TEST_P(SensorsHidlTest, GyroscopeBatchingOperation) {
-    testBatchingOperation(SensorTypeVersion::GYROSCOPE);
-}
-
-// Test if sensor hal can do magnetometer batching properly
-TEST_P(SensorsHidlTest, MagnetometerBatchingOperation) {
-    testBatchingOperation(SensorTypeVersion::MAGNETIC_FIELD);
-}
-
-// Test sensor event direct report with ashmem for accel sensor at normal rate
-TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) {
-    testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM,
-                              RateLevel::NORMAL, mAccelNormChecker);
-}
-
-// Test sensor event direct report with ashmem for accel sensor at fast rate
-TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationFast) {
-    testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM,
-                              RateLevel::FAST, mAccelNormChecker);
-}
-
-// Test sensor event direct report with ashmem for accel sensor at very fast rate
-TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationVeryFast) {
-    testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM,
-                              RateLevel::VERY_FAST, mAccelNormChecker);
-}
-
-// Test sensor event direct report with ashmem for gyro sensor at normal rate
-TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationNormal) {
-    testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM,
-                              RateLevel::NORMAL, mGyroNormChecker);
-}
-
-// Test sensor event direct report with ashmem for gyro sensor at fast rate
-TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationFast) {
-    testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::FAST,
-                              mGyroNormChecker);
-}
-
-// Test sensor event direct report with ashmem for gyro sensor at very fast rate
-TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationVeryFast) {
-    testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM,
-                              RateLevel::VERY_FAST, mGyroNormChecker);
-}
-
-// Test sensor event direct report with ashmem for mag sensor at normal rate
-TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationNormal) {
-    testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM,
-                              RateLevel::NORMAL, NullChecker<EventType>());
-}
-
-// Test sensor event direct report with ashmem for mag sensor at fast rate
-TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationFast) {
-    testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM,
-                              RateLevel::FAST, NullChecker<EventType>());
-}
-
-// Test sensor event direct report with ashmem for mag sensor at very fast rate
-TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationVeryFast) {
-    testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM,
-                              RateLevel::VERY_FAST, NullChecker<EventType>());
-}
-
-// Test sensor event direct report with gralloc for accel sensor at normal rate
-TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) {
-    testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC,
-                              RateLevel::NORMAL, mAccelNormChecker);
-}
-
-// Test sensor event direct report with gralloc for accel sensor at fast rate
-TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationFast) {
-    testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC,
-                              RateLevel::FAST, mAccelNormChecker);
-}
-
-// Test sensor event direct report with gralloc for accel sensor at very fast rate
-TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationVeryFast) {
-    testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC,
-                              RateLevel::VERY_FAST, mAccelNormChecker);
-}
-
-// Test sensor event direct report with gralloc for gyro sensor at normal rate
-TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) {
-    testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC,
-                              RateLevel::NORMAL, mGyroNormChecker);
-}
-
-// Test sensor event direct report with gralloc for gyro sensor at fast rate
-TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationFast) {
-    testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::FAST,
-                              mGyroNormChecker);
-}
-
-// Test sensor event direct report with gralloc for gyro sensor at very fast rate
-TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationVeryFast) {
-    testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC,
-                              RateLevel::VERY_FAST, mGyroNormChecker);
-}
-
-// Test sensor event direct report with gralloc for mag sensor at normal rate
-TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationNormal) {
-    testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC,
-                              RateLevel::NORMAL, NullChecker<EventType>());
-}
-
-// Test sensor event direct report with gralloc for mag sensor at fast rate
-TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationFast) {
-    testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC,
-                              RateLevel::FAST, NullChecker<EventType>());
-}
-
-// Test sensor event direct report with gralloc for mag sensor at very fast rate
-TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) {
-    testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC,
-                              RateLevel::VERY_FAST, NullChecker<EventType>());
-}
-
 void SensorsHidlTest::activateAllSensors(bool enable) {
     for (const SensorInfoType& sensorInfo : getSensorsList()) {
         if (isValidType(sensorInfo.type)) {
@@ -829,21 +634,6 @@
                        Result::BAD_VALUE);
 }
 
-TEST_P(SensorsHidlTest, FlushNonexistentSensor) {
-    SensorInfoType sensor;
-    std::vector<SensorInfoType> sensors = getNonOneShotSensors();
-    if (sensors.size() == 0) {
-        sensors = getOneShotSensors();
-        if (sensors.size() == 0) {
-            return;
-        }
-    }
-    sensor = sensors.front();
-    sensor.sensorHandle = getInvalidSensorHandle();
-    runSingleFlushTest(std::vector<SensorInfoType>{sensor}, false /* activateSensor */,
-                       0 /* expectedFlushCount */, Result::BAD_VALUE);
-}
-
 TEST_P(SensorsHidlTest, Batch) {
     if (getSensorsList().size() == 0) {
         return;
@@ -1124,63 +914,3 @@
     }
     return found;
 }
-
-TEST_P(SensorsHidlTest, ConfigureDirectChannelWithInvalidHandle) {
-    SensorInfoType sensor;
-    SharedMemType memType;
-    RateLevel rate;
-    if (!getDirectChannelSensor(&sensor, &memType, &rate)) {
-        return;
-    }
-
-    // Verify that an invalid channel handle produces a BAD_VALUE result
-    configDirectReport(sensor.sensorHandle, -1, rate, [](Result result, int32_t /* reportToken */) {
-        ASSERT_EQ(result, Result::BAD_VALUE);
-    });
-}
-
-TEST_P(SensorsHidlTest, CleanupDirectConnectionOnInitialize) {
-    constexpr size_t kNumEvents = 1;
-    constexpr size_t kMemSize = kNumEvents * kEventSize;
-
-    SensorInfoType sensor;
-    SharedMemType memType;
-    RateLevel rate;
-
-    if (!getDirectChannelSensor(&sensor, &memType, &rate)) {
-        return;
-    }
-
-    std::shared_ptr<SensorsTestSharedMemory<SensorTypeVersion, EventType>> mem(
-            SensorsTestSharedMemory<SensorTypeVersion, EventType>::create(memType, kMemSize));
-    ASSERT_NE(mem, nullptr);
-
-    int32_t directChannelHandle = 0;
-    registerDirectChannel(mem->getSharedMemInfo(), [&](Result result, int32_t channelHandle) {
-        ASSERT_EQ(result, Result::OK);
-        directChannelHandle = channelHandle;
-    });
-
-    // Configure the channel and expect success
-    configDirectReport(
-            sensor.sensorHandle, directChannelHandle, rate,
-            [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::OK); });
-
-    // Call initialize() via the environment setup to cause the HAL to re-initialize
-    // Clear the active direct connections so they are not stopped during TearDown
-    auto handles = mDirectChannelHandles;
-    mDirectChannelHandles.clear();
-    getEnvironment()->HidlTearDown();
-    getEnvironment()->HidlSetUp();
-    if (HasFatalFailure()) {
-        return;  // Exit early if resetting the environment failed
-    }
-
-    // Attempt to configure the direct channel and expect it to fail
-    configDirectReport(
-            sensor.sensorHandle, directChannelHandle, rate,
-            [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::BAD_VALUE); });
-
-    // Restore original handles, though they should already be deactivated
-    mDirectChannelHandles = handles;
-}
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
index 781427d..19dfbe5 100644
--- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
@@ -46,12 +46,7 @@
         std::this_thread::sleep_for(std::chrono::seconds(3));
     }
 
-    virtual void HidlTearDown() {
-        mStopThread = true;
-        if (mPollThread.joinable()) {
-            mPollThread.join();
-        }
-    }
+    virtual void HidlTearDown() = 0;
 
     // Get and clear all events collected so far (like "cat" shell command).
     // If output is nullptr, it clears all collected events.
diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.cpp b/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.cpp
index 7ea5462..dbf2b91 100644
--- a/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.cpp
+++ b/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.cpp
@@ -21,6 +21,8 @@
 #include "supplicant_hidl_test_utils_1_3.h"
 
 using ::android::sp;
+using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
+using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
 using ::android::hardware::wifi::supplicant::V1_3::ISupplicant;
 using ::android::hardware::wifi::supplicant::V1_3::ISupplicantStaIface;
 using ::android::hardware::wifi::supplicant::V1_3::ISupplicantStaNetwork;
@@ -43,3 +45,15 @@
     return ISupplicant::castFrom(
         getSupplicant(supplicant_instance_name, isP2pOn));
 }
+
+bool isFilsSupported(sp<ISupplicantStaIface> sta_iface) {
+    uint32_t keyMgmtMask = 0;
+    sta_iface->getKeyMgmtCapabilities_1_3(
+        [&](const SupplicantStatus& status, uint32_t keyMgmtMaskInternal) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+            keyMgmtMask = keyMgmtMaskInternal;
+        });
+
+    return (keyMgmtMask & (ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA256 |
+                           ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA384));
+}
diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.h b/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.h
index f8dca13..69fc598 100644
--- a/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.h
+++ b/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.h
@@ -31,4 +31,7 @@
         supplicant);
 android::sp<android::hardware::wifi::supplicant::V1_3::ISupplicant>
 getSupplicant_1_3(const std::string& supplicant_instance_name, bool isP2pOn);
+bool isFilsSupported(
+    android::sp<android::hardware::wifi::supplicant::V1_3::ISupplicantStaIface>
+        sta_iface);
 #endif /* SUPPLICANT_HIDL_TEST_UTILS_1_3_H */
diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp
index f7019d2..3754520 100644
--- a/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -517,7 +517,10 @@
  * FilsHlpAddRequest
  */
 TEST_P(SupplicantStaIfaceHidlTest, FilsHlpAddRequest) {
-    uint32_t keyMgmtMask = 0;
+    if (!isFilsSupported(sta_iface_)) {
+        GTEST_SKIP()
+            << "Skipping test since driver/supplicant doesn't support FILS";
+    }
     uint8_t destMacAddr[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
     std::vector<uint8_t> pktBuffer = {
         0x08, 0x00, 0x45, 0x10, 0x01, 0x3a, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
@@ -548,22 +551,9 @@
         0x63, 0x70, 0x2d, 0x52, 0x37, 0x0a, 0x01, 0x03, 0x06, 0x0f, 0x1a, 0x1c,
         0x33, 0x3a, 0x3b, 0x2b, 0xff, 0x00};
 
-    sta_iface_->getKeyMgmtCapabilities_1_3(
-        [&](const SupplicantStatus& status, uint32_t keyMgmtMaskInternal) {
-            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
-            keyMgmtMask = keyMgmtMaskInternal;
-        });
-
-    SupplicantStatusCode expectedStatusCode =
-        (keyMgmtMask & (ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA256 |
-                        ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA384))
-            ? SupplicantStatusCode::SUCCESS
-            : SupplicantStatusCode::FAILURE_UNKNOWN;
-
     sta_iface_->filsHlpAddRequest(
-        destMacAddr, pktBuffer,
-        [expectedStatusCode](const SupplicantStatus& status) {
-            EXPECT_EQ(expectedStatusCode, status.code);
+        destMacAddr, pktBuffer, [](const SupplicantStatus& status) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
         });
 }
 
@@ -571,23 +561,14 @@
  * FilsHlpFlushRequest
  */
 TEST_P(SupplicantStaIfaceHidlTest, FilsHlpFlushRequest) {
-    uint32_t keyMgmtMask = 0;
-    sta_iface_->getKeyMgmtCapabilities_1_3(
-        [&](const SupplicantStatus& status, uint32_t keyMgmtMaskInternal) {
-            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
-            keyMgmtMask = keyMgmtMaskInternal;
-        });
+    if (!isFilsSupported(sta_iface_)) {
+        GTEST_SKIP()
+            << "Skipping test since driver/supplicant doesn't support FILS";
+    }
 
-    SupplicantStatusCode expectedStatusCode =
-        (keyMgmtMask & (ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA256 |
-                        ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA384))
-            ? SupplicantStatusCode::SUCCESS
-            : SupplicantStatusCode::FAILURE_UNKNOWN;
-
-    sta_iface_->filsHlpFlushRequest(
-        [expectedStatusCode](const SupplicantStatus& status) {
-            EXPECT_EQ(expectedStatusCode, status.code);
-        });
+    sta_iface_->filsHlpFlushRequest([](const SupplicantStatus& status) {
+        EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+    });
 }
 INSTANTIATE_TEST_CASE_P(
     PerInstance, SupplicantStaIfaceHidlTest,
diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp b/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
index 6be24bc..9c40de1 100644
--- a/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
+++ b/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
@@ -290,23 +290,14 @@
  * SetEapErp
  */
 TEST_P(SupplicantStaNetworkHidlTest, SetEapErp) {
-    uint32_t keyMgmtMask = 0;
-    sta_iface_->getKeyMgmtCapabilities_1_3(
-        [&](const SupplicantStatus &status, uint32_t keyMgmtMaskInternal) {
-            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
-            keyMgmtMask = keyMgmtMaskInternal;
-        });
+    if (!isFilsSupported(sta_iface_)) {
+        GTEST_SKIP()
+            << "Skipping test since driver/supplicant doesn't support FILS";
+    }
 
-    SupplicantStatusCode expectedStatusCode =
-        (keyMgmtMask & (ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA256 |
-                        ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA384))
-            ? SupplicantStatusCode::SUCCESS
-            : SupplicantStatusCode::FAILURE_UNKNOWN;
-
-    sta_network_->setEapErp(
-        true, [expectedStatusCode](const SupplicantStatus &status) {
-            EXPECT_EQ(expectedStatusCode, status.code);
-        });
+    sta_network_->setEapErp(true, [](const SupplicantStatus &status) {
+        EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+    });
 }
 INSTANTIATE_TEST_CASE_P(
     PerInstance, SupplicantStaNetworkHidlTest,