Merge changes from topic "ic-hal-v2-rvc" into rvc-dev

* changes:
  Identity Credential: Add method to accept verification token.
  Identity Credential: Pass additional information to HAL.
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 2e6fa25..341aae7 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -2527,14 +2527,21 @@
      * int32[5]: 0   // user #0  (usersInfo.existingUsers[0].userId)
      * int32[6]: 1   // flags of user #0  (usersInfo.existingUsers[0].flags)
      *
-     * And if the HAL want to respond with the creation of an admin user called "Admin", the
+     * And if the HAL want to respond with the creation of an admin user called "Owner", the
      * response would be:
      *
-     * int32[0]: 42    // must match the request id from the request
-     * int32[1]:  2    // action = InitialUserInfoResponseAction::CREATE
-     * int32[2]: -1    // userToSwitchOrCreate.userId (not used as user will be created)
-     * int32[3]:  8    // userToSwitchOrCreate.flags = ADMIN
-     * string: "Admin" // userNameToCreate
+     * int32[0]: 42      // must match the request id from the request
+     * int32[1]:  2      // action = InitialUserInfoResponseAction::CREATE
+     * int32[2]: -1      // userToSwitchOrCreate.userId (not used as user will be created)
+     * int32[3]:  8      // userToSwitchOrCreate.flags = ADMIN
+     * string: "||Owner"  // userLocales + separator + userNameToCreate
+     *
+     * Notice the string value represents multiple values, separated by ||. The first value is the
+     * (optional) system locales for the user to be created (in this case, it's empty, meaning it
+     * will use Android's default value), while the second value is the (also optional) name of the
+     * to user to be created (when the type of response is InitialUserInfoResponseAction:CREATE).
+     * For example, to create the same "Owner" user with "en-US" and "pt-BR" locales, the string
+     * value of the response would be "en-US,pt-BR||Owner".
      *
      * NOTE: if the HAL doesn't support user management, then it should not define this property,
      * which in turn would disable the other user-related properties (for example, the Android
@@ -4367,6 +4374,12 @@
      * Name of the user that should be created.
      */
     string userNameToCreate;
+
+    /**
+     * System locales of the initial user (value will be passed as-is to
+     * android.provider.Settings.System.SYSTEM_LOCALES)
+     */
+    string userLocales;
 };
 
 /**
diff --git a/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp b/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp
index fbddf6d..613c528 100644
--- a/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp
+++ b/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp
@@ -82,6 +82,10 @@
 
 // Sanity check Boot::setActiveBootSlot() on good and bad inputs.
 TEST_P(BootHidlTest, SetActiveBootSlot) {
+    Slot curSlot = boot->getCurrentSlot();
+    Slot otherSlot = curSlot ? 0 : 1;
+    auto otherBootable = boot->isSlotBootable(otherSlot);
+
     for (Slot s = 0; s < 2; s++) {
         CommandResult cr;
         Return<void> result = boot->setActiveBootSlot(s, generate_callback(&cr));
@@ -90,7 +94,17 @@
     {
         // Restore original flags to avoid problems on reboot
         CommandResult cr;
-        Return<void> result = boot->markBootSuccessful(generate_callback(&cr));
+        auto result = boot->setActiveBootSlot(curSlot, generate_callback(&cr));
+        EXPECT_TRUE(result.isOk());
+        EXPECT_TRUE(cr.success);
+
+        if (otherBootable == BoolResult::FALSE) {
+            result = boot->setSlotAsUnbootable(otherSlot, generate_callback(&cr));
+            EXPECT_TRUE(result.isOk());
+            EXPECT_TRUE(cr.success);
+        }
+
+        result = boot->markBootSuccessful(generate_callback(&cr));
         EXPECT_TRUE(result.isOk());
         EXPECT_TRUE(cr.success);
     }
@@ -105,19 +119,22 @@
 
 // Sanity check Boot::setSlotAsUnbootable() on good and bad inputs.
 TEST_P(BootHidlTest, SetSlotAsUnbootable) {
+    Slot curSlot = boot->getCurrentSlot();
+    Slot otherSlot = curSlot ? 0 : 1;
+    auto otherBootable = boot->isSlotBootable(otherSlot);
     {
         CommandResult cr;
-        Slot curSlot = boot->getCurrentSlot();
-        Slot otherSlot = curSlot ? 0 : 1;
         Return<void> result = boot->setSlotAsUnbootable(otherSlot, generate_callback(&cr));
         EXPECT_TRUE(result.isOk());
         if (cr.success) {
             EXPECT_EQ(BoolResult::FALSE, boot->isSlotBootable(otherSlot));
 
             // Restore original flags to avoid problems on reboot
-            result = boot->setActiveBootSlot(otherSlot, generate_callback(&cr));
-            EXPECT_TRUE(result.isOk());
-            EXPECT_TRUE(cr.success);
+            if (otherBootable == BoolResult::TRUE) {
+                result = boot->setActiveBootSlot(otherSlot, generate_callback(&cr));
+                EXPECT_TRUE(result.isOk());
+                EXPECT_TRUE(cr.success);
+            }
             result = boot->setActiveBootSlot(curSlot, generate_callback(&cr));
             EXPECT_TRUE(result.isOk());
             EXPECT_TRUE(cr.success);
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index bf5fbfe..550a2e0 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -6942,8 +6942,11 @@
 
     float minZoomRatio = entry.data.f[0];
     float maxZoomRatio = entry.data.f[1];
-    if (maxDigitalZoom != maxZoomRatio) {
-        ADD_FAILURE() << "Maximum zoom ratio is different than maximum digital zoom!";
+    constexpr float FLOATING_POINT_THRESHOLD = 0.00001f;
+    if (maxDigitalZoom > maxZoomRatio + FLOATING_POINT_THRESHOLD) {
+        ADD_FAILURE() << "Maximum digital zoom " << maxDigitalZoom
+                      << " is larger than maximum zoom ratio " << maxZoomRatio << " + threshold "
+                      << FLOATING_POINT_THRESHOLD << "!";
     }
     if (minZoomRatio > maxZoomRatio) {
         ADD_FAILURE() << "Maximum zoom ratio is less than minimum zoom ratio!";
diff --git a/common/aidl/Android.bp b/common/aidl/Android.bp
index 0731230..9ea4cdf 100644
--- a/common/aidl/Android.bp
+++ b/common/aidl/Android.bp
@@ -17,6 +17,13 @@
         cpp: {
             enabled: false,
         },
+        ndk: {
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.media.swcodec",
+            ],
+            min_sdk_version: "29",
+        },
     },
     versions: ["1"],
 }
diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
index c93e89b..094c7c1 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
@@ -223,9 +223,10 @@
                 static_cast<uint32_t>(measurement.state) >=
                         static_cast<uint32_t>(IGnssMeasurementCallback_2_0::GnssMeasurementState::
                                                       STATE_UNKNOWN) &&
-                static_cast<uint32_t>(measurement.state) <=
-                        static_cast<uint32_t>(IGnssMeasurementCallback_2_0::GnssMeasurementState::
-                                                      STATE_2ND_CODE_LOCK));
+                static_cast<uint32_t>(measurement.state) <
+                        (static_cast<uint32_t>(IGnssMeasurementCallback_2_0::GnssMeasurementState::
+                                                       STATE_2ND_CODE_LOCK)
+                         << 1));
     }
 
     iGnssMeasurement->close();
diff --git a/graphics/common/aidl/Android.bp b/graphics/common/aidl/Android.bp
index c089a76..e594233 100644
--- a/graphics/common/aidl/Android.bp
+++ b/graphics/common/aidl/Android.bp
@@ -20,6 +20,13 @@
         cpp: {
             enabled: false,
         },
+        ndk: {
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.media.swcodec",
+            ],
+            min_sdk_version: "29",
+        },
     },
     versions: ["1"],
 }
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index 9e56534..529fb18 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -1927,8 +1927,13 @@
     info.usage = BufferUsage::PROTECTED | BufferUsage::COMPOSER_OVERLAY;
 
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
-                                   info, gralloc4::MetadataType_ProtectedContent, &vec));
+    auto err = mGralloc->getFromBufferDescriptorInfo(info, gralloc4::MetadataType_ProtectedContent,
+                                                     &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
 
     uint64_t protectedContent = 0;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeProtectedContent(vec, &protectedContent));
@@ -1943,8 +1948,13 @@
     info.usage = static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
 
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
-                                   info, gralloc4::MetadataType_Compression, &vec));
+    auto err =
+            mGralloc->getFromBufferDescriptorInfo(info, gralloc4::MetadataType_Compression, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
 
     ExtendableType compression = gralloc4::Compression_DisplayStreamCompression;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeCompression(vec, &compression));
@@ -1958,8 +1968,13 @@
  */
 TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoInterlaced) {
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
-                                   mDummyDescriptorInfo, gralloc4::MetadataType_Interlaced, &vec));
+    auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                     gralloc4::MetadataType_Interlaced, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
 
     ExtendableType interlaced = gralloc4::Interlaced_TopBottom;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeInterlaced(vec, &interlaced));
@@ -1973,9 +1988,13 @@
  */
 TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoChromaSiting) {
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE,
-              mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
-                                                    gralloc4::MetadataType_ChromaSiting, &vec));
+    auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                     gralloc4::MetadataType_ChromaSiting, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
 
     ExtendableType chromaSiting = gralloc4::ChromaSiting_CositedHorizontal;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeChromaSiting(vec, &chromaSiting));
@@ -2009,8 +2028,12 @@
     info.usage = static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
 
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE,
-              mGralloc->getFromBufferDescriptorInfo(info, gralloc4::MetadataType_Crop, &vec));
+    auto err = mGralloc->getFromBufferDescriptorInfo(info, gralloc4::MetadataType_Crop, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
 
     std::vector<aidl::android::hardware::graphics::common::Rect> crops;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeCrop(vec, &crops));
@@ -2022,8 +2045,13 @@
  */
 TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoDataspace) {
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
-                                   mDummyDescriptorInfo, gralloc4::MetadataType_Dataspace, &vec));
+    auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                     gralloc4::MetadataType_Dataspace, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
 
     Dataspace dataspace = Dataspace::DISPLAY_P3;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeDataspace(vec, &dataspace));
@@ -2035,8 +2063,13 @@
  */
 TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoBlendMode) {
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
-                                   mDummyDescriptorInfo, gralloc4::MetadataType_BlendMode, &vec));
+    auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                     gralloc4::MetadataType_BlendMode, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
 
     BlendMode blendMode = BlendMode::COVERAGE;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeBlendMode(vec, &blendMode));
@@ -2048,8 +2081,13 @@
  */
 TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoSmpte2086) {
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
-                                   mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2086, &vec));
+    auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                     gralloc4::MetadataType_Smpte2086, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
 
     std::optional<Smpte2086> smpte2086;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2086(vec, &smpte2086));
@@ -2061,8 +2099,13 @@
  */
 TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoCta861_3) {
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
-                                   mDummyDescriptorInfo, gralloc4::MetadataType_Cta861_3, &vec));
+    auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                     gralloc4::MetadataType_Cta861_3, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
 
     std::optional<Cta861_3> cta861_3;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeCta861_3(vec, &cta861_3));
@@ -2074,9 +2117,14 @@
  */
 TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoSmpte2094_40) {
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE,
-              mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
-                                                    gralloc4::MetadataType_Smpte2094_40, &vec));
+    auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                     gralloc4::MetadataType_Smpte2094_40, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
+
     std::optional<std::vector<uint8_t>> smpte2094_40;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_40(vec, &smpte2094_40));
     EXPECT_FALSE(smpte2094_40.has_value());
diff --git a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
index 4dbac16..914a01a 100644
--- a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
@@ -568,8 +568,10 @@
     }
 
     Request request = std::move(maybeRequest.value());
+
+    constexpr uint32_t kInsufficientOutputIndex = 0;
     if (testConfig.outputType == OutputType::INSUFFICIENT) {
-        makeOutputInsufficientSize(/*outputIndex=*/0, &request);
+        makeOutputInsufficientSize(kInsufficientOutputIndex, &request);
     }
 
     OptionalTimeoutDuration loopTimeoutDuration;
@@ -745,7 +747,21 @@
             }
             ASSERT_EQ(ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, executionStatus);
             ASSERT_EQ(outputShapes.size(), testModel.main.outputIndexes.size());
-            ASSERT_FALSE(outputShapes[0].isSufficient);
+            // Check that all returned output dimensions are at least as fully specified as the
+            // union of the information about the corresponding operand in the model and in the
+            // request. In this test, all model outputs have known rank with all dimensions
+            // unspecified, and no dimensional information is provided in the request.
+            for (uint32_t i = 0; i < outputShapes.size(); i++) {
+                ASSERT_EQ(outputShapes[i].isSufficient, i != kInsufficientOutputIndex);
+                const auto& actual = outputShapes[i].dimensions;
+                const auto& golden =
+                        testModel.main.operands[testModel.main.outputIndexes[i]].dimensions;
+                ASSERT_EQ(actual.size(), golden.size());
+                for (uint32_t j = 0; j < actual.size(); j++) {
+                    if (actual[j] == 0) continue;
+                    EXPECT_EQ(actual[j], golden[j]) << "index: " << j;
+                }
+            }
             return;
         case OutputType::MISSED_DEADLINE:
             ASSERT_TRUE(executionStatus == ErrorStatus::MISSED_DEADLINE_TRANSIENT ||
diff --git a/tv/tuner/1.0/default/Demux.cpp b/tv/tuner/1.0/default/Demux.cpp
index 4e5ae4b..da56041 100644
--- a/tv/tuner/1.0/default/Demux.cpp
+++ b/tv/tuner/1.0/default/Demux.cpp
@@ -60,13 +60,7 @@
     ALOGV("%s", __FUNCTION__);
 
     uint32_t filterId;
-    if (!mUnusedFilterIds.empty()) {
-        filterId = *mUnusedFilterIds.begin();
-
-        mUnusedFilterIds.erase(filterId);
-    } else {
-        filterId = ++mLastUsedFilterId;
-    }
+    filterId = ++mLastUsedFilterId;
 
     mUsedFilterIds.insert(filterId);
 
@@ -84,6 +78,9 @@
     }
 
     mFilters[filterId] = filter;
+    if (filter->isPcrFilter()) {
+        mPcrFilterIds.insert(filterId);
+    }
     bool result = true;
     if (mDvr != nullptr && mDvr->getType() == DvrType::PLAYBACK) {
         result = mDvr->addPlaybackFilter(filter);
@@ -102,19 +99,53 @@
     return Void();
 }
 
-Return<void> Demux::getAvSyncHwId(const sp<IFilter>& /* filter */, getAvSyncHwId_cb _hidl_cb) {
+Return<void> Demux::getAvSyncHwId(const sp<IFilter>& filter, getAvSyncHwId_cb _hidl_cb) {
     ALOGV("%s", __FUNCTION__);
 
-    AvSyncHwId avSyncHwId = 0;
+    uint32_t avSyncHwId = -1;
+    int id;
+    Result status;
 
-    _hidl_cb(Result::SUCCESS, avSyncHwId);
+    filter->getId([&](Result result, uint32_t filterId) {
+        id = filterId;
+        status = result;
+    });
+
+    if (status != Result::SUCCESS) {
+        ALOGE("[Demux] Can't get filter Id.");
+        _hidl_cb(Result::INVALID_STATE, avSyncHwId);
+        return Void();
+    }
+
+    if (!mFilters[id]->isMediaFilter()) {
+        ALOGE("[Demux] Given filter is not a media filter.");
+        _hidl_cb(Result::INVALID_ARGUMENT, avSyncHwId);
+        return Void();
+    }
+
+    if (!mPcrFilterIds.empty()) {
+        ALOGE("[Demux] No PCR filter opened.");
+        // Return the lowest pcr filter id in the default implementation as the av sync id
+        _hidl_cb(Result::SUCCESS, *mPcrFilterIds.begin());
+        return Void();
+    }
+
+    _hidl_cb(Result::INVALID_STATE, avSyncHwId);
     return Void();
 }
 
-Return<void> Demux::getAvSyncTime(AvSyncHwId /* avSyncHwId */, getAvSyncTime_cb _hidl_cb) {
+Return<void> Demux::getAvSyncTime(AvSyncHwId avSyncHwId, getAvSyncTime_cb _hidl_cb) {
     ALOGV("%s", __FUNCTION__);
 
-    uint64_t avSyncTime = 0;
+    uint64_t avSyncTime = -1;
+    if (mPcrFilterIds.empty()) {
+        _hidl_cb(Result::INVALID_STATE, avSyncTime);
+        return Void();
+    }
+    if (avSyncHwId != *mPcrFilterIds.begin()) {
+        _hidl_cb(Result::INVALID_ARGUMENT, avSyncTime);
+        return Void();
+    }
 
     _hidl_cb(Result::SUCCESS, avSyncTime);
     return Void();
@@ -123,7 +154,6 @@
 Return<Result> Demux::close() {
     ALOGV("%s", __FUNCTION__);
 
-    mUnusedFilterIds.clear();
     mUsedFilterIds.clear();
     mLastUsedFilterId = -1;
 
@@ -171,7 +201,6 @@
     // resetFilterRecords(filterId);
     mUsedFilterIds.erase(filterId);
     mRecordFilterIds.erase(filterId);
-    mUnusedFilterIds.insert(filterId);
     mFilters.erase(filterId);
 
     return Result::SUCCESS;
diff --git a/tv/tuner/1.0/default/Demux.h b/tv/tuner/1.0/default/Demux.h
index 3c91daf..6c46b0d 100644
--- a/tv/tuner/1.0/default/Demux.h
+++ b/tv/tuner/1.0/default/Demux.h
@@ -130,6 +130,7 @@
 
     uint32_t mDemuxId;
     uint32_t mCiCamId;
+    set<uint32_t> mPcrFilterIds;
     /**
      * Record the last used filter id. Initial value is -1.
      * Filter Id starts with 0.
@@ -141,13 +142,6 @@
      */
     set<uint32_t> mUsedFilterIds;
     /**
-     * Record all the unused filter Ids within mLastUsedFilterId.
-     * Removed filter Id should be added into this set.
-     * When this set is not empty, ids here should be allocated first
-     * and added into usedFilterIds.
-     */
-    set<uint32_t> mUnusedFilterIds;
-    /**
      * Record all the attached record filter Ids.
      * Any removed filter id should be removed from this set.
      */
diff --git a/tv/tuner/1.0/default/Filter.cpp b/tv/tuner/1.0/default/Filter.cpp
index fef7a35..8bca70c 100644
--- a/tv/tuner/1.0/default/Filter.cpp
+++ b/tv/tuner/1.0/default/Filter.cpp
@@ -37,6 +37,32 @@
     mBufferSize = bufferSize;
     mCallback = cb;
     mDemux = demux;
+
+    switch (mType.mainType) {
+        case DemuxFilterMainType::TS:
+            if (mType.subType.tsFilterType() == DemuxTsFilterType::AUDIO ||
+                mType.subType.tsFilterType() == DemuxTsFilterType::VIDEO) {
+                mIsMediaFilter = true;
+            }
+            if (mType.subType.tsFilterType() == DemuxTsFilterType::PCR) {
+                mIsPcrFilter = true;
+            }
+            break;
+        case DemuxFilterMainType::MMTP:
+            if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO ||
+                mType.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) {
+                mIsMediaFilter = true;
+            }
+            break;
+        case DemuxFilterMainType::IP:
+            break;
+        case DemuxFilterMainType::TLV:
+            break;
+        case DemuxFilterMainType::ALP:
+            break;
+        default:
+            break;
+    }
 }
 
 Filter::~Filter() {}
@@ -73,16 +99,8 @@
     switch (mType.mainType) {
         case DemuxFilterMainType::TS:
             mTpid = settings.ts().tpid;
-            if (mType.subType.tsFilterType() == DemuxTsFilterType::AUDIO ||
-                mType.subType.tsFilterType() == DemuxTsFilterType::VIDEO) {
-                mIsMediaFilter = true;
-            }
             break;
         case DemuxFilterMainType::MMTP:
-            if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO ||
-                mType.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) {
-                mIsMediaFilter = true;
-            }
             break;
         case DemuxFilterMainType::IP:
             break;
diff --git a/tv/tuner/1.0/default/Filter.h b/tv/tuner/1.0/default/Filter.h
index 9b49ad8..09e9604 100644
--- a/tv/tuner/1.0/default/Filter.h
+++ b/tv/tuner/1.0/default/Filter.h
@@ -89,6 +89,8 @@
     void attachFilterToRecord(const sp<Dvr> dvr);
     void detachFilterFromRecord();
     void freeAvHandle();
+    bool isMediaFilter() { return mIsMediaFilter; };
+    bool isPcrFilter() { return mIsPcrFilter; };
 
   private:
     // Tuner service
@@ -104,6 +106,7 @@
     uint32_t mBufferSize;
     DemuxFilterType mType;
     bool mIsMediaFilter = false;
+    bool mIsPcrFilter = false;
     DemuxFilterSettings mFilterSettings;
 
     uint16_t mTpid;
diff --git a/tv/tuner/1.0/vts/functional/DemuxTests.cpp b/tv/tuner/1.0/vts/functional/DemuxTests.cpp
index b1d8a0a..6c32534 100644
--- a/tv/tuner/1.0/vts/functional/DemuxTests.cpp
+++ b/tv/tuner/1.0/vts/functional/DemuxTests.cpp
@@ -38,4 +38,25 @@
     auto status = mDemux->close();
     mDemux = nullptr;
     return AssertionResult(status.isOk());
+}
+
+void DemuxTests::getAvSyncId(sp<IFilter> filter, uint32_t& avSyncHwId) {
+    ASSERT_TRUE(mDemux) << "Demux is not opened yet.";
+    Result status;
+    mDemux->getAvSyncHwId(filter, [&](Result result, uint32_t id) {
+        status = result;
+        avSyncHwId = id;
+    });
+    ASSERT_TRUE(status == Result::SUCCESS) << "Fail to get avSyncHwId.";
+}
+
+void DemuxTests::getAvSyncTime(uint32_t avSyncId) {
+    ASSERT_TRUE(mDemux) << "Demux is not opened yet.";
+    Result status;
+    uint64_t syncTime;
+    mDemux->getAvSyncTime(avSyncId, [&](Result result, uint64_t time) {
+        status = result;
+        syncTime = time;
+    });
+    ASSERT_TRUE(status == Result::SUCCESS) << "Fail to get avSyncTime.";
 }
\ No newline at end of file
diff --git a/tv/tuner/1.0/vts/functional/DemuxTests.h b/tv/tuner/1.0/vts/functional/DemuxTests.h
index 6e1e395..0443c67 100644
--- a/tv/tuner/1.0/vts/functional/DemuxTests.h
+++ b/tv/tuner/1.0/vts/functional/DemuxTests.h
@@ -31,6 +31,7 @@
 using android::hardware::Return;
 using android::hardware::Void;
 using android::hardware::tv::tuner::V1_0::IDemux;
+using android::hardware::tv::tuner::V1_0::IFilter;
 using android::hardware::tv::tuner::V1_0::ITuner;
 using android::hardware::tv::tuner::V1_0::Result;
 
@@ -42,6 +43,8 @@
 
     AssertionResult openDemux(sp<IDemux>& demux, uint32_t& demuxId);
     AssertionResult setDemuxFrontendDataSource(uint32_t frontendId);
+    void getAvSyncId(sp<IFilter> filter, uint32_t& avSyncHwId);
+    void getAvSyncTime(uint32_t avSyncId);
     AssertionResult closeDemux();
 
   protected:
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.cpp b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
index fc5071c..d54a959 100644
--- a/tv/tuner/1.0/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
@@ -246,6 +246,120 @@
     return AssertionResult(status == Result::SUCCESS);
 }
 
+void FrontendTests::verifyFrontendStatus(vector<FrontendStatusType> statusTypes,
+                                         vector<FrontendStatus> expectStatuses) {
+    ASSERT_TRUE(mFrontend) << "Frontend is not opened yet.";
+    Result status;
+    vector<FrontendStatus> realStatuses;
+
+    mFrontend->getStatus(statusTypes, [&](Result result, const hidl_vec<FrontendStatus>& statuses) {
+        status = result;
+        realStatuses = statuses;
+    });
+
+    ASSERT_TRUE(realStatuses.size() == statusTypes.size());
+    for (int i = 0; i < statusTypes.size(); i++) {
+        FrontendStatusType type = statusTypes[i];
+        switch (type) {
+            case FrontendStatusType::DEMOD_LOCK: {
+                ASSERT_TRUE(realStatuses[i].isDemodLocked() == expectStatuses[i].isDemodLocked());
+                break;
+            }
+            case FrontendStatusType::SNR: {
+                ASSERT_TRUE(realStatuses[i].snr() == expectStatuses[i].snr());
+                break;
+            }
+            case FrontendStatusType::BER: {
+                ASSERT_TRUE(realStatuses[i].ber() == expectStatuses[i].ber());
+                break;
+            }
+            case FrontendStatusType::PER: {
+                ASSERT_TRUE(realStatuses[i].per() == expectStatuses[i].per());
+                break;
+            }
+            case FrontendStatusType::PRE_BER: {
+                ASSERT_TRUE(realStatuses[i].preBer() == expectStatuses[i].preBer());
+                break;
+            }
+            case FrontendStatusType::SIGNAL_QUALITY: {
+                ASSERT_TRUE(realStatuses[i].signalQuality() == expectStatuses[i].signalQuality());
+                break;
+            }
+            case FrontendStatusType::SIGNAL_STRENGTH: {
+                ASSERT_TRUE(realStatuses[i].signalStrength() == expectStatuses[i].signalStrength());
+                break;
+            }
+            case FrontendStatusType::SYMBOL_RATE: {
+                ASSERT_TRUE(realStatuses[i].symbolRate() == expectStatuses[i].symbolRate());
+                break;
+            }
+            case FrontendStatusType::FEC: {
+                ASSERT_TRUE(realStatuses[i].innerFec() == expectStatuses[i].innerFec());
+                break;
+            }
+            case FrontendStatusType::MODULATION: {
+                // TODO: check modulation status
+                break;
+            }
+            case FrontendStatusType::SPECTRAL: {
+                ASSERT_TRUE(realStatuses[i].inversion() == expectStatuses[i].inversion());
+                break;
+            }
+            case FrontendStatusType::LNB_VOLTAGE: {
+                ASSERT_TRUE(realStatuses[i].lnbVoltage() == expectStatuses[i].lnbVoltage());
+                break;
+            }
+            case FrontendStatusType::PLP_ID: {
+                ASSERT_TRUE(realStatuses[i].plpId() == expectStatuses[i].plpId());
+                break;
+            }
+            case FrontendStatusType::EWBS: {
+                ASSERT_TRUE(realStatuses[i].isEWBS() == expectStatuses[i].isEWBS());
+                break;
+            }
+            case FrontendStatusType::AGC: {
+                ASSERT_TRUE(realStatuses[i].agc() == expectStatuses[i].agc());
+                break;
+            }
+            case FrontendStatusType::LNA: {
+                ASSERT_TRUE(realStatuses[i].isLnaOn() == expectStatuses[i].isLnaOn());
+                break;
+            }
+            case FrontendStatusType::LAYER_ERROR: {
+                vector<bool> realLayberError = realStatuses[i].isLayerError();
+                vector<bool> expectLayerError = expectStatuses[i].isLayerError();
+                ASSERT_TRUE(realLayberError.size() == expectLayerError.size());
+                for (int i = 0; i < realLayberError.size(); i++) {
+                    ASSERT_TRUE(realLayberError[i] == expectLayerError[i]);
+                }
+                break;
+            }
+            case FrontendStatusType::MER: {
+                ASSERT_TRUE(realStatuses[i].mer() == expectStatuses[i].mer());
+                break;
+            }
+            case FrontendStatusType::FREQ_OFFSET: {
+                ASSERT_TRUE(realStatuses[i].freqOffset() == expectStatuses[i].freqOffset());
+                break;
+            }
+            case FrontendStatusType::HIERARCHY: {
+                ASSERT_TRUE(realStatuses[i].hierarchy() == expectStatuses[i].hierarchy());
+                break;
+            }
+            case FrontendStatusType::RF_LOCK: {
+                ASSERT_TRUE(realStatuses[i].isRfLocked() == expectStatuses[i].isRfLocked());
+                break;
+            }
+            case FrontendStatusType::ATSC3_PLP_INFO:
+                // TODO: verify plpinfo
+                break;
+            default:
+                continue;
+        }
+    }
+    ASSERT_TRUE(status == Result::SUCCESS);
+}
+
 AssertionResult FrontendTests::tuneFrontend(FrontendConfig config) {
     EXPECT_TRUE(mFrontendCallback)
             << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
@@ -294,6 +408,7 @@
     ASSERT_TRUE(openFrontendById(feId));
     ASSERT_TRUE(setFrontendCallback());
     ASSERT_TRUE(tuneFrontend(frontendConf));
+    verifyFrontendStatus(frontendConf.tuneStatusTypes, frontendConf.expectTuneStatuses);
     ASSERT_TRUE(stopTuneFrontend());
     ASSERT_TRUE(closeFrontend());
 }
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.h b/tv/tuner/1.0/vts/functional/FrontendTests.h
index 1a9bec9..2bdc8fd 100644
--- a/tv/tuner/1.0/vts/functional/FrontendTests.h
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.h
@@ -109,6 +109,8 @@
     AssertionResult scanFrontend(FrontendConfig config, FrontendScanType type);
     AssertionResult stopScanFrontend();
     AssertionResult tuneFrontend(FrontendConfig config);
+    void verifyFrontendStatus(vector<FrontendStatusType> statusTypes,
+                              vector<FrontendStatus> expectStatuses);
     AssertionResult stopTuneFrontend();
     AssertionResult closeFrontend();
 
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index c44f77d..9ac42da 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -263,6 +263,41 @@
     ASSERT_TRUE(mFrontendTests.closeFrontend());
 }
 
+TEST_P(TunerDemuxHidlTest, getAvSyncTime) {
+    description("Get the A/V sync time from a PCR filter.");
+    uint32_t feId;
+    uint32_t demuxId;
+    sp<IDemux> demux;
+    uint32_t mediaFilterId;
+    uint32_t pcrFilterId;
+    uint32_t avSyncHwId;
+    sp<IFilter> mediaFilter;
+
+    mFrontendTests.getFrontendIdByType(frontendArray[DVBT].type, feId);
+    ASSERT_TRUE(feId != INVALID_ID);
+    ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+    ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+    mFilterTests.setDemux(demux);
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterArray[TS_VIDEO1].type,
+                                               filterArray[TS_VIDEO1].bufferSize));
+    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(mediaFilterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_VIDEO1].settings, mediaFilterId));
+    mediaFilter = mFilterTests.getFilterById(mediaFilterId);
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterArray[TS_PCR0].type,
+                                               filterArray[TS_PCR0].bufferSize));
+    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(pcrFilterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_PCR0].settings, pcrFilterId));
+    mDemuxTests.getAvSyncId(mediaFilter, avSyncHwId);
+    ASSERT_TRUE(pcrFilterId == avSyncHwId);
+    mDemuxTests.getAvSyncTime(pcrFilterId);
+    ASSERT_TRUE(mFilterTests.closeFilter(pcrFilterId));
+    ASSERT_TRUE(mFilterTests.closeFilter(mediaFilterId));
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+    ASSERT_TRUE(mFrontendTests.closeFrontend());
+}
+
 TEST_P(TunerFilterHidlTest, StartFilterInDemux) {
     description("Open and start a filter in Demux.");
     // TODO use paramterized tests
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
index 21a9855..6dddc38 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
@@ -68,6 +68,7 @@
 
         mFrontendTests.setService(mService);
         mDemuxTests.setService(mService);
+        mFilterTests.setService(mService);
     }
 
   protected:
@@ -78,6 +79,7 @@
     sp<ITuner> mService;
     FrontendTests mFrontendTests;
     DemuxTests mDemuxTests;
+    FilterTests mFilterTests;
 };
 
 class TunerFilterHidlTest : public testing::TestWithParam<std::string> {
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
index b84013b..287f673 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
@@ -40,6 +40,8 @@
 using android::hardware::tv::tuner::V1_0::FrontendDvbtStandard;
 using android::hardware::tv::tuner::V1_0::FrontendDvbtTransmissionMode;
 using android::hardware::tv::tuner::V1_0::FrontendSettings;
+using android::hardware::tv::tuner::V1_0::FrontendStatus;
+using android::hardware::tv::tuner::V1_0::FrontendStatusType;
 using android::hardware::tv::tuner::V1_0::FrontendType;
 using android::hardware::tv::tuner::V1_0::PlaybackSettings;
 using android::hardware::tv::tuner::V1_0::RecordSettings;
@@ -88,6 +90,8 @@
 struct FrontendConfig {
     FrontendType type;
     FrontendSettings settings;
+    vector<FrontendStatusType> tuneStatusTypes;
+    vector<FrontendStatus> expectTuneStatuses;
 };
 
 struct ChannelConfig {
@@ -127,6 +131,14 @@
             .standard = FrontendDvbtStandard::T,
     };
     frontendArray[DVBT].type = FrontendType::DVBT, frontendArray[DVBT].settings.dvbt(dvbtSettings);
+    vector<FrontendStatusType> types;
+    types.push_back(FrontendStatusType::DEMOD_LOCK);
+    FrontendStatus status;
+    status.isDemodLocked(true);
+    vector<FrontendStatus> statuses;
+    statuses.push_back(status);
+    frontendArray[DVBT].tuneStatusTypes = types;
+    frontendArray[DVBT].expectTuneStatuses = statuses;
     frontendArray[DVBS].type = FrontendType::DVBS;
 };
 
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
index 793dd8c..14a8509 100644
--- a/wifi/1.0/vts/functional/Android.bp
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -23,14 +23,14 @@
         "wifi_hidl_test_utils.cpp",
     ],
     export_include_dirs: [
-        "."
+        ".",
     ],
     shared_libs: [
         "libnativehelper",
     ],
     static_libs: [
         "android.hardware.wifi@1.0",
-        "libwifi-system-iface"
+        "libwifi-system-iface",
     ],
 }
 
@@ -49,9 +49,12 @@
         "android.hardware.wifi@1.1",
         "android.hardware.wifi@1.2",
         "android.hardware.wifi@1.3",
-        "libwifi-system-iface"
+        "libwifi-system-iface",
     ],
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
 }
 
 // These tests are split out so that they can be conditioned on presence of the
@@ -66,9 +69,12 @@
     static_libs: [
         "VtsHalWifiV1_0TargetTestUtil",
         "android.hardware.wifi@1.0",
-        "libwifi-system-iface"
+        "libwifi-system-iface",
     ],
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
 }
 
 // These tests are split out so that they can be conditioned on presence of
@@ -83,7 +89,10 @@
     static_libs: [
         "VtsHalWifiV1_0TargetTestUtil",
         "android.hardware.wifi@1.0",
-        "libwifi-system-iface"
+        "libwifi-system-iface",
     ],
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
 }
diff --git a/wifi/1.0/vts/functional/wifi_rtt_controller_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_rtt_controller_hidl_test.cpp
index 1014c1d..3c9ed9e 100644
--- a/wifi/1.0/vts/functional/wifi_rtt_controller_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_rtt_controller_hidl_test.cpp
@@ -16,6 +16,7 @@
 
 #include <android-base/logging.h>
 
+#include <VtsCoreUtil.h>
 #include <android/hardware/wifi/1.0/IWifi.h>
 #include <android/hardware/wifi/1.0/IWifiRttController.h>
 #include <gtest/gtest.h>
@@ -38,6 +39,8 @@
 class WifiRttControllerHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
+        if (!::testing::deviceSupportsFeature("android.hardware.wifi.rtt"))
+            GTEST_SKIP() << "Skipping this test since RTT is not supported.";
         // Make sure test starts with a clean state
         stopWifi(GetInstanceName());
     }
diff --git a/wifi/1.1/vts/functional/Android.bp b/wifi/1.1/vts/functional/Android.bp
index eb68bc0..7dc78e4 100644
--- a/wifi/1.1/vts/functional/Android.bp
+++ b/wifi/1.1/vts/functional/Android.bp
@@ -18,14 +18,18 @@
     name: "VtsHalWifiV1_1TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
-        "wifi_chip_hidl_test.cpp"],
+        "wifi_chip_hidl_test.cpp",
+    ],
     static_libs: [
         "VtsHalWifiV1_0TargetTestUtil",
         "android.hardware.wifi@1.0",
         "android.hardware.wifi@1.1",
         "android.hardware.wifi@1.2",
         "android.hardware.wifi@1.3",
-        "libwifi-system-iface"
+        "libwifi-system-iface",
     ],
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
 }
diff --git a/wifi/1.2/vts/functional/Android.bp b/wifi/1.2/vts/functional/Android.bp
index 90bcac1..159ba94 100644
--- a/wifi/1.2/vts/functional/Android.bp
+++ b/wifi/1.2/vts/functional/Android.bp
@@ -27,10 +27,13 @@
         "android.hardware.wifi@1.1",
         "android.hardware.wifi@1.2",
         "android.hardware.wifi@1.3",
-        "libwifi-system-iface"
+        "libwifi-system-iface",
     ],
     disable_framework: true,
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
 }
 
 cc_test {
@@ -44,8 +47,10 @@
         "android.hardware.wifi@1.0",
         "android.hardware.wifi@1.1",
         "android.hardware.wifi@1.2",
-        "libwifi-system-iface"
+        "libwifi-system-iface",
     ],
-    disable_framework: true,
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
 }
diff --git a/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp
index 96656f3..bc392a9 100644
--- a/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp
+++ b/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp
@@ -16,6 +16,7 @@
 
 #include <android-base/logging.h>
 
+#include <VtsCoreUtil.h>
 #include <android/hardware/wifi/1.2/IWifi.h>
 #include <android/hardware/wifi/1.2/IWifiNanIface.h>
 #include <android/hardware/wifi/1.2/IWifiNanIfaceEventCallback.h>
@@ -50,6 +51,8 @@
 class WifiNanIfaceHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
+        if (!::testing::deviceSupportsFeature("android.hardware.wifi.aware"))
+            GTEST_SKIP() << "Skipping this test since NAN is not supported.";
         // Make sure to start with a clean state
         stopWifi(GetInstanceName());
 
diff --git a/wifi/1.4/default/tests/mock_wifi_iface_util.h b/wifi/1.4/default/tests/mock_wifi_iface_util.h
index 3b36f13..8d77a7d 100644
--- a/wifi/1.4/default/tests/mock_wifi_iface_util.h
+++ b/wifi/1.4/default/tests/mock_wifi_iface_util.h
@@ -41,6 +41,7 @@
                  void(const std::string&, IfaceEventHandlers));
     MOCK_METHOD1(unregisterIfaceEventHandlers, void(const std::string&));
     MOCK_METHOD2(setUpState, bool(const std::string&, bool));
+    MOCK_METHOD1(ifNameToIndex, unsigned(const std::string&));
 };
 }  // namespace iface_util
 }  // namespace implementation
diff --git a/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp
index d5b1a50..323d2ff 100644
--- a/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp
@@ -787,6 +787,8 @@
     property_set("wifi.aware.interface", "aware0");
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+    EXPECT_CALL(*iface_util_, ifNameToIndex("aware0"))
+        .WillOnce(testing::Return(4));
     EXPECT_CALL(*iface_util_, setUpState("aware0", true))
         .WillOnce(testing::Return(true));
     ASSERT_EQ(createIface(IfaceType::NAN), "aware0");
diff --git a/wifi/1.4/default/wifi_chip.cpp b/wifi/1.4/default/wifi_chip.cpp
index 61912a5..8747e61 100644
--- a/wifi/1.4/default/wifi_chip.cpp
+++ b/wifi/1.4/default/wifi_chip.cpp
@@ -885,7 +885,7 @@
     }
     bool is_dedicated_iface = true;
     std::string ifname = getNanIfaceName();
-    if (ifname.empty()) {
+    if (ifname.empty() || !iface_util_.lock()->ifNameToIndex(ifname)) {
         // Use the first shared STA iface (wlan0) if a dedicated aware iface is
         // not defined.
         ifname = getFirstActiveWlanIfaceName();
diff --git a/wifi/1.4/default/wifi_iface_util.cpp b/wifi/1.4/default/wifi_iface_util.cpp
index 13ba022..49b7674 100644
--- a/wifi/1.4/default/wifi_iface_util.cpp
+++ b/wifi/1.4/default/wifi_iface_util.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <net/if.h>
 #include <cstddef>
 #include <iostream>
 #include <limits>
@@ -122,6 +123,10 @@
     }
     return true;
 }
+
+unsigned WifiIfaceUtil::ifNameToIndex(const std::string& iface_name) {
+    return if_nametoindex(iface_name.c_str());
+}
 }  // namespace iface_util
 }  // namespace implementation
 }  // namespace V1_4
diff --git a/wifi/1.4/default/wifi_iface_util.h b/wifi/1.4/default/wifi_iface_util.h
index f83d717..126b6ca 100644
--- a/wifi/1.4/default/wifi_iface_util.h
+++ b/wifi/1.4/default/wifi_iface_util.h
@@ -57,6 +57,7 @@
                                             IfaceEventHandlers handlers);
     virtual void unregisterIfaceEventHandlers(const std::string& iface_name);
     virtual bool setUpState(const std::string& iface_name, bool request_up);
+    virtual unsigned ifNameToIndex(const std::string& iface_name);
 
    private:
     std::array<uint8_t, 6> createRandomMacAddress();
diff --git a/wifi/1.4/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_nan_iface_hidl_test.cpp
index 24daee6..f6a1147 100644
--- a/wifi/1.4/vts/functional/wifi_nan_iface_hidl_test.cpp
+++ b/wifi/1.4/vts/functional/wifi_nan_iface_hidl_test.cpp
@@ -16,6 +16,7 @@
 
 #include <android-base/logging.h>
 
+#include <VtsCoreUtil.h>
 #include <android/hardware/wifi/1.2/IWifiNanIfaceEventCallback.h>
 #include <android/hardware/wifi/1.4/IWifi.h>
 #include <android/hardware/wifi/1.4/IWifiNanIface.h>
@@ -51,6 +52,8 @@
 class WifiNanIfaceHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
+        if (!::testing::deviceSupportsFeature("android.hardware.wifi.aware"))
+            GTEST_SKIP() << "Skipping this test since NAN is not supported.";
         // Make sure to start with a clean state
         stopWifi(GetInstanceName());
 
diff --git a/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp
index 4035fb8..9d84223 100644
--- a/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp
+++ b/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp
@@ -19,6 +19,7 @@
 
 #undef NAN  // NAN is defined in bionic/libc/include/math.h:38
 
+#include <VtsCoreUtil.h>
 #include <android/hardware/wifi/1.3/IWifiStaIface.h>
 #include <android/hardware/wifi/1.4/IWifi.h>
 #include <android/hardware/wifi/1.4/IWifiChip.h>
@@ -59,6 +60,8 @@
 class WifiRttControllerHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
+        if (!::testing::deviceSupportsFeature("android.hardware.wifi.rtt"))
+            GTEST_SKIP() << "Skipping this test since RTT is not supported.";
         // Make sure to start with a clean state
         stopWifi(GetInstanceName());
 
diff --git a/wifi/supplicant/1.3/vts/functional/Android.bp b/wifi/supplicant/1.3/vts/functional/Android.bp
index 8eebed0..68c2929 100644
--- a/wifi/supplicant/1.3/vts/functional/Android.bp
+++ b/wifi/supplicant/1.3/vts/functional/Android.bp
@@ -64,4 +64,5 @@
         "general-tests",
         "vts",
     ],
+    disable_framework: true,
 }