Merge "Validate Render Engine output in composer VTS 2.2"
diff --git a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
index 40961f7..d3d7387 100644
--- a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
+++ b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
@@ -14,29 +14,24 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "face_hidl_test"
+#define LOG_TAG "biometrics_face_hidl_hal_test"
 
+#include <android/hardware/biometrics/face/1.0/IBiometricsFace.h>
+#include <android/hardware/biometrics/face/1.0/IBiometricsFaceClientCallback.h>
+
+#include <VtsHalHidlTargetCallbackBase.h>
 #include <VtsHalHidlTargetTestBase.h>
 #include <VtsHalHidlTargetTestEnvBase.h>
 #include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android/hardware/biometrics/face/1.0/IBiometricsFace.h>
-#include <android/hardware/biometrics/face/1.0/IBiometricsFaceClientCallback.h>
-#include <hidl/HidlSupport.h>
-#include <hidl/HidlTransportSupport.h>
-#include <utils/Condition.h>
 
-#include <cinttypes>
+#include <chrono>
 #include <cstdint>
-#include <future>
-#include <utility>
+#include <random>
 
-using android::Condition;
-using android::Mutex;
 using android::sp;
-using android::base::GetUintProperty;
 using android::hardware::hidl_vec;
 using android::hardware::Return;
+using android::hardware::Void;
 using android::hardware::biometrics::face::V1_0::FaceAcquiredInfo;
 using android::hardware::biometrics::face::V1_0::FaceError;
 using android::hardware::biometrics::face::V1_0::Feature;
@@ -48,263 +43,203 @@
 
 namespace {
 
-const uint32_t kTimeout = 3;
-const std::chrono::seconds kTimeoutInSeconds = std::chrono::seconds(kTimeout);
-const uint32_t kUserId = 99;
-const uint32_t kFaceId = 5;
-const char kTmpDir[] = "/data/system/users/0/facedata";
-const int kIterations = 1000;
+// Arbitrary, nonexistent userId
+constexpr uint32_t kUserId = 9;
+// Arbitrary, nonexistent faceId
+constexpr uint32_t kFaceId = 5;
+constexpr uint32_t kTimeoutSec = 3;
+constexpr auto kTimeout = std::chrono::seconds(kTimeoutSec);
+constexpr int kGenerateChallengeIterations = 10;
+constexpr char kFacedataDir[] = "/data/vendor_de/0/facedata";
+constexpr char kCallbackNameOnEnrollResult[] = "onEnrollResult";
+constexpr char kCallbackNameOnAuthenticated[] = "onAuthenticated";
+constexpr char kCallbackNameOnAcquired[] = "onAcquired";
+constexpr char kCallbackNameOnError[] = "onError";
+constexpr char kCallbackNameOnRemoved[] = "onRemoved";
+constexpr char kCallbackNameOnEnumerate[] = "onEnumerate";
+constexpr char kCallbackNameOnLockoutChanged[] = "onLockoutChanged";
 
-const auto kAssertCallbackIsSet = [](const OptionalUint64& res) {
-    ASSERT_EQ(Status::OK, res.status);
-    // Makes sure the "deviceId" represented by "res.value" is not 0.
-    // 0 would mean the HIDL is not available.
-    ASSERT_NE(0UL, res.value);
+// Callback arguments that need to be captured for the tests.
+struct FaceCallbackArgs {
+    // The error passed to the last onError() callback.
+    FaceError error;
+
+    // The userId passed to the last onRemoved() callback.
+    int32_t userId;
 };
 
-// Wait for a callback to occur (signaled by the given future) up to the
-// provided timeout. If the future is invalid or the callback does not come
-// within the given time, returns false.
-template <class ReturnType>
-bool waitForCallback(std::future<ReturnType> future,
-                     std::chrono::milliseconds timeout = kTimeoutInSeconds) {
-    auto expiration = std::chrono::system_clock::now() + timeout;
-    EXPECT_TRUE(future.valid());
-    if (future.valid()) {
-        std::future_status status = future.wait_until(expiration);
-        EXPECT_NE(std::future_status::timeout, status) << "Timed out waiting for callback";
-        if (status == std::future_status::ready) {
-            return true;
-        }
-    }
-    return false;
-}
-
-// Base callback implementation that just logs all callbacks by default
-class FaceCallbackBase : public IBiometricsFaceClientCallback {
+// Test callback class for the BiometricsFace HAL.
+// The HAL will call these callback methods to notify about completed operations
+// or encountered errors.
+class FaceCallback : public ::testing::VtsHalHidlTargetCallbackBase<FaceCallbackArgs>,
+                     public IBiometricsFaceClientCallback {
   public:
     Return<void> onEnrollResult(uint64_t, uint32_t, int32_t, uint32_t) override {
-        ALOGD("Enroll callback called.");
-        return Return<void>();
+        NotifyFromCallback(kCallbackNameOnEnrollResult);
+        return Void();
     }
 
     Return<void> onAuthenticated(uint64_t, uint32_t, int32_t, const hidl_vec<uint8_t>&) override {
-        ALOGD("Authenticated callback called.");
-        return Return<void>();
+        NotifyFromCallback(kCallbackNameOnAuthenticated);
+        return Void();
     }
 
     Return<void> onAcquired(uint64_t, int32_t, FaceAcquiredInfo, int32_t) override {
-        ALOGD("Acquired callback called.");
-        return Return<void>();
+        NotifyFromCallback(kCallbackNameOnAcquired);
+        return Void();
     }
 
-    Return<void> onError(uint64_t, int32_t, FaceError, int32_t) override {
-        ALOGD("Error callback called.");
-        EXPECT_TRUE(false);  // fail any test that triggers an error
-        return Return<void>();
+    Return<void> onError(uint64_t, int32_t, FaceError error, int32_t) override {
+        FaceCallbackArgs args = {};
+        args.error = error;
+        NotifyFromCallback(kCallbackNameOnError, args);
+        return Void();
     }
 
-    Return<void> onRemoved(uint64_t, const hidl_vec<uint32_t>&, int32_t) override {
-        ALOGD("Removed callback called.");
-        return Return<void>();
+    Return<void> onRemoved(uint64_t, const hidl_vec<uint32_t>&, int32_t userId) override {
+        FaceCallbackArgs args = {};
+        args.userId = userId;
+        NotifyFromCallback(kCallbackNameOnRemoved, args);
+        return Void();
     }
 
-    Return<void> onEnumerate(uint64_t, const hidl_vec<uint32_t>&, int32_t /* userId */) override {
-        ALOGD("Enumerate callback called.");
-        return Return<void>();
+    Return<void> onEnumerate(uint64_t, const hidl_vec<uint32_t>&, int32_t) override {
+        NotifyFromCallback(kCallbackNameOnEnumerate);
+        return Void();
     }
 
     Return<void> onLockoutChanged(uint64_t) override {
-        ALOGD("LockoutChanged callback called.");
-        return Return<void>();
+        NotifyFromCallback(kCallbackNameOnLockoutChanged);
+        return Void();
     }
 };
 
-class EnumerateCallback : public FaceCallbackBase {
-  public:
-    Return<void> onEnumerate(uint64_t, const hidl_vec<uint32_t>&, int32_t) override {
-        promise.set_value();
-        return Return<void>();
-    }
-
-    std::promise<void> promise;
-};
-
-class ErrorCallback : public FaceCallbackBase {
-  public:
-    ErrorCallback(bool filterErrors = false, FaceError errorType = FaceError::HW_UNAVAILABLE)
-        : filterErrors(filterErrors), errorType(errorType), hasError(false) {}
-
-    Return<void> onError(uint64_t, int32_t, FaceError error, int32_t) override {
-        if ((filterErrors && errorType == error) || !filterErrors) {
-            hasError = true;
-            this->error = error;
-            promise.set_value();
-        }
-        return Return<void>();
-    }
-
-    bool filterErrors;
-    FaceError errorType;
-    bool hasError;
-    FaceError error;
-    std::promise<void> promise;
-};
-
-class RemoveCallback : public FaceCallbackBase {
-  public:
-    explicit RemoveCallback(int32_t userId) : removeUserId(userId) {}
-
-    Return<void> onRemoved(uint64_t, const hidl_vec<uint32_t>&, int32_t userId) override {
-        EXPECT_EQ(removeUserId, userId);
-        promise.set_value();
-        return Return<void>();
-    }
-
-    int32_t removeUserId;
-    std::promise<void> promise;
-};
-
-class LockoutChangedCallback : public FaceCallbackBase {
-  public:
-    Return<void> onLockoutChanged(uint64_t duration) override {
-        this->hasDuration = true;
-        this->duration = duration;
-        promise.set_value();
-        return Return<void>();
-    }
-    bool hasDuration;
-    uint64_t duration;
-    std::promise<void> promise;
-};
-
-// Test environment for Face HIDL HAL.
+// Test environment for the BiometricsFace HAL.
 class FaceHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
   public:
-    // get the test environment singleton
+    // Get the test environment singleton.
     static FaceHidlEnvironment* Instance() {
         static FaceHidlEnvironment* instance = new FaceHidlEnvironment;
         return instance;
     }
 
     void registerTestServices() override { registerTestService<IBiometricsFace>(); }
+
+  private:
+    FaceHidlEnvironment() = default;
 };
 
+// Test class for the BiometricsFace HAL.
 class FaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
   public:
     void SetUp() override {
         mService = ::testing::VtsHalHidlTargetTestBase::getService<IBiometricsFace>(
                 FaceHidlEnvironment::Instance()->getServiceName<IBiometricsFace>());
-        ASSERT_FALSE(mService == nullptr);
-        Return<Status> res = mService->setActiveUser(kUserId, kTmpDir);
-        ASSERT_EQ(Status::OK, static_cast<Status>(res));
+        ASSERT_NE(mService, nullptr);
+        mCallback = new FaceCallback();
+        mCallback->SetWaitTimeoutDefault(kTimeout);
+        Return<void> ret1 = mService->setCallback(mCallback, [](const OptionalUint64& res) {
+            ASSERT_EQ(Status::OK, res.status);
+            // Makes sure the "deviceId" represented by "res.value" is not 0.
+            // 0 would mean the HIDL is not available.
+            ASSERT_NE(0UL, res.value);
+        });
+        ASSERT_TRUE(ret1.isOk());
+        Return<Status> ret2 = mService->setActiveUser(kUserId, kFacedataDir);
+        ASSERT_EQ(Status::OK, static_cast<Status>(ret2));
     }
 
     void TearDown() override {}
 
     sp<IBiometricsFace> mService;
+    sp<FaceCallback> mCallback;
 };
 
-// The service should be reachable.
-TEST_F(FaceHidlTest, ConnectTest) {
-    sp<FaceCallbackBase> cb = new FaceCallbackBase();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-}
-
-// Starting the service with null callback should succeed.
-TEST_F(FaceHidlTest, ConnectNullTest) {
-    mService->setCallback(nullptr, kAssertCallbackIsSet);
-}
-
 // generateChallenge should always return a unique, cryptographically secure,
 // non-zero number.
 TEST_F(FaceHidlTest, GenerateChallengeTest) {
     std::map<uint64_t, int> m;
-    for (int i = 0; i < kIterations; ++i) {
-        mService->generateChallenge(kTimeout, [&m](const OptionalUint64& res) {
-            ASSERT_EQ(Status::OK, res.status);
-            EXPECT_NE(0UL, res.value);
-            m[res.value]++;
-            EXPECT_EQ(1UL, m[res.value]);
-        });
+    for (int i = 0; i < kGenerateChallengeIterations; ++i) {
+        Return<void> ret =
+                mService->generateChallenge(kTimeoutSec, [&m](const OptionalUint64& res) {
+                    ASSERT_EQ(Status::OK, res.status);
+                    EXPECT_NE(0UL, res.value);
+                    m[res.value]++;
+                    EXPECT_EQ(1UL, m[res.value]);
+                });
+        ASSERT_TRUE(ret.isOk());
     }
 }
 
 // enroll with an invalid (all zeroes) HAT should fail.
 TEST_F(FaceHidlTest, EnrollZeroHatTest) {
-    sp<ErrorCallback> cb = new ErrorCallback();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-
+    // Filling HAT with zeros
     hidl_vec<uint8_t> token(69);
     for (size_t i = 0; i < 69; i++) {
         token[i] = 0;
     }
 
-    Return<Status> res = mService->enroll(token, kTimeout, {});
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
+    Return<Status> ret = mService->enroll(token, kTimeoutSec, {});
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 
-    // At least one call to onError should occur
-    ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
-    ASSERT_TRUE(cb->hasError);
+    // onError should be called with a meaningful (nonzero) error.
+    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
+    EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error);
 }
 
 // enroll with an invalid HAT should fail.
 TEST_F(FaceHidlTest, EnrollGarbageHatTest) {
-    sp<ErrorCallback> cb = new ErrorCallback();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-
-    // Filling HAT with invalid data
+    // Filling HAT with pseudorandom invalid data.
+    // Using default seed to make the test reproducible.
+    std::mt19937 gen(std::mt19937::default_seed);
+    std::uniform_int_distribution<uint8_t> dist;
     hidl_vec<uint8_t> token(69);
     for (size_t i = 0; i < 69; ++i) {
-        token[i] = i;
+        token[i] = dist(gen);
     }
 
-    Return<Status> res = mService->enroll(token, kTimeout, {});
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
+    Return<Status> ret = mService->enroll(token, kTimeoutSec, {});
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 
-    // At least one call to onError should occur
-    ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
-    ASSERT_TRUE(cb->hasError);
+    // onError should be called with a meaningful (nonzero) error.
+    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
+    EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error);
 }
 
 // setFeature with an invalid (all zeros) HAT should fail.
 TEST_F(FaceHidlTest, SetFeatureZeroHatTest) {
-    sp<ErrorCallback> cb = new ErrorCallback();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-
     hidl_vec<uint8_t> token(69);
     for (size_t i = 0; i < 69; i++) {
         token[i] = 0;
     }
 
-    Return<Status> res = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token, 0);
-    ASSERT_EQ(Status::ILLEGAL_ARGUMENT, static_cast<Status>(res));
+    Return<Status> ret = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token, 0);
+    ASSERT_EQ(Status::ILLEGAL_ARGUMENT, static_cast<Status>(ret));
 }
 
 // setFeature with an invalid HAT should fail.
 TEST_F(FaceHidlTest, SetFeatureGarbageHatTest) {
-    sp<ErrorCallback> cb = new ErrorCallback();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-
-    // Filling HAT with invalid data
+    // Filling HAT with pseudorandom invalid data.
+    // Using default seed to make the test reproducible.
+    std::mt19937 gen(std::mt19937::default_seed);
+    std::uniform_int_distribution<uint8_t> dist;
     hidl_vec<uint8_t> token(69);
     for (size_t i = 0; i < 69; ++i) {
-        token[i] = i;
+        token[i] = dist(gen);
     }
 
-    Return<Status> res = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token, 0);
-    ASSERT_EQ(Status::ILLEGAL_ARGUMENT, static_cast<Status>(res));
+    Return<Status> ret = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token, 0);
+    ASSERT_EQ(Status::ILLEGAL_ARGUMENT, static_cast<Status>(ret));
 }
 
-void assertGetFeatureFails(sp<IBiometricsFace> service, int faceId, Feature feature) {
-    std::promise<void> promise;
-
+void assertGetFeatureFails(const sp<IBiometricsFace>& service, uint32_t faceId, Feature feature) {
     // Features cannot be retrieved for invalid faces.
-    Return<void> res = service->getFeature(feature, faceId, [&promise](const OptionalBool& result) {
+    Return<void> res = service->getFeature(feature, faceId, [](const OptionalBool& result) {
         ASSERT_EQ(Status::ILLEGAL_ARGUMENT, result.status);
-        promise.set_value();
     });
-    ASSERT_TRUE(waitForCallback(promise.get_future()));
+    ASSERT_TRUE(res.isOk());
 }
 
 TEST_F(FaceHidlTest, GetFeatureRequireAttentionTest) {
@@ -317,111 +252,95 @@
 
 // revokeChallenge should always return within the timeout
 TEST_F(FaceHidlTest, RevokeChallengeTest) {
-    sp<FaceCallbackBase> cb = new FaceCallbackBase();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-
     auto start = std::chrono::system_clock::now();
-    mService->revokeChallenge();
+    Return<Status> ret = mService->revokeChallenge();
     auto elapsed = std::chrono::system_clock::now() - start;
-    ASSERT_GE(kTimeoutInSeconds, elapsed);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
+    ASSERT_GE(kTimeout, elapsed);
 }
 
 // The call to getAuthenticatorId should succeed.
 TEST_F(FaceHidlTest, GetAuthenticatorIdTest) {
-    mService->getAuthenticatorId(
+    Return<void> ret = mService->getAuthenticatorId(
             [](const OptionalUint64& res) { ASSERT_EQ(Status::OK, res.status); });
+    ASSERT_TRUE(ret.isOk());
 }
 
 // The call to enumerate should succeed.
 TEST_F(FaceHidlTest, EnumerateTest) {
-    sp<EnumerateCallback> cb = new EnumerateCallback();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-    Return<Status> res = mService->enumerate();
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
-    ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
+    Return<Status> ret = mService->enumerate();
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
+    auto res = mCallback->WaitForCallback(kCallbackNameOnEnumerate);
+    EXPECT_TRUE(res.no_timeout);
 }
 
 // The call to remove should succeed for any faceId
 TEST_F(FaceHidlTest, RemoveFaceTest) {
-    sp<ErrorCallback> cb = new ErrorCallback();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-
     // Remove a face
-    Return<Status> res = mService->remove(kFaceId);
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
+    Return<Status> ret = mService->remove(kFaceId);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 }
 
 // Remove should accept 0 to delete all faces
 TEST_F(FaceHidlTest, RemoveAllFacesTest) {
-    sp<ErrorCallback> cb = new ErrorCallback();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-
     // Remove all faces
-    Return<Status> res = mService->remove(0);
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
+    Return<Status> ret = mService->remove(0);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 }
 
 // Active user should successfully set to a writable location.
 TEST_F(FaceHidlTest, SetActiveUserTest) {
     // Create an active user
-    Return<Status> res = mService->setActiveUser(2, kTmpDir);
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
+    Return<Status> ret = mService->setActiveUser(2, kFacedataDir);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 
     // Reset active user
-    res = mService->setActiveUser(kUserId, kTmpDir);
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
+    ret = mService->setActiveUser(kUserId, kFacedataDir);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 }
 
 // Active user should fail to set to an unwritable location.
 TEST_F(FaceHidlTest, SetActiveUserUnwritableTest) {
     // Create an active user to an unwritable location (device root dir)
-    Return<Status> res = mService->setActiveUser(3, "/");
-    ASSERT_NE(Status::OK, static_cast<Status>(res));
+    Return<Status> ret = mService->setActiveUser(3, "/");
+    ASSERT_NE(Status::OK, static_cast<Status>(ret));
 
     // Reset active user
-    res = mService->setActiveUser(kUserId, kTmpDir);
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
+    ret = mService->setActiveUser(kUserId, kFacedataDir);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 }
 
 // Active user should fail to set to a null location.
 TEST_F(FaceHidlTest, SetActiveUserNullTest) {
     // Create an active user to a null location.
-    Return<Status> res = mService->setActiveUser(4, nullptr);
-    ASSERT_NE(Status::OK, static_cast<Status>(res));
+    Return<Status> ret = mService->setActiveUser(4, nullptr);
+    ASSERT_NE(Status::OK, static_cast<Status>(ret));
 
     // Reset active user
-    res = mService->setActiveUser(kUserId, kTmpDir);
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
+    ret = mService->setActiveUser(kUserId, kFacedataDir);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 }
 
 // Cancel should always return CANCELED from any starting state including
 // the IDLE state.
 TEST_F(FaceHidlTest, CancelTest) {
-    sp<ErrorCallback> cb = new ErrorCallback(true, FaceError::CANCELED);
-    mService->setCallback(cb, kAssertCallbackIsSet);
-
-    Return<Status> res = mService->cancel();
+    Return<Status> ret = mService->cancel();
     // check that we were able to make an IPC request successfully
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
-
-    // make sure callback was invoked within kTimeoutInSeconds
-    ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
-    // check error should be CANCELED
-    ASSERT_EQ(FaceError::CANCELED, cb->error);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
+    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
+    // make sure callback was invoked within kRevokeChallengeTimeout
+    EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(FaceError::CANCELED, res.args->error);
 }
 
 TEST_F(FaceHidlTest, OnLockoutChangedTest) {
-    sp<LockoutChangedCallback> cb = new LockoutChangedCallback();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-
-    // Update active user and ensure lockout duration 0 is received
-    mService->setActiveUser(5, kTmpDir);
+    // Update active user and ensure onLockoutChanged was called.
+    Return<Status> ret = mService->setActiveUser(kUserId + 1, kFacedataDir);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 
     // Make sure callback was invoked
-    ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
-
-    // Check that duration 0 was received
-    ASSERT_EQ(0, cb->duration);
+    auto res = mCallback->WaitForCallback(kCallbackNameOnLockoutChanged);
+    EXPECT_TRUE(res.no_timeout);
 }
 
 }  // anonymous namespace
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 86c2c1e..3cbcc7b 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -607,7 +607,9 @@
 
     struct DeviceCb : public V3_5::ICameraDeviceCallback {
         DeviceCb(CameraHidlTest *parent, int deviceVersion, const camera_metadata_t *staticMeta) :
-                mParent(parent), mDeviceVersion(deviceVersion), mStaticMetadata(staticMeta) {}
+                mParent(parent), mDeviceVersion(deviceVersion) {
+            mStaticMetadata = staticMeta;
+        }
 
         Return<void> processCaptureResult_3_4(
                 const hidl_vec<V3_4::CaptureResult>& results) override;
@@ -631,7 +633,7 @@
 
         CameraHidlTest *mParent; // Parent object
         int mDeviceVersion;
-        const camera_metadata_t *mStaticMetadata;
+        android::hardware::camera::common::V1_0::helper::CameraMetadata mStaticMetadata;
         bool hasOutstandingBuffersLocked();
 
         /* members for requestStreamBuffers() and returnStreamBuffers()*/
@@ -1194,18 +1196,20 @@
         // Verify final result metadata
         bool isAtLeast_3_5 = mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_5;
         if (isAtLeast_3_5) {
+            auto staticMetadataBuffer = mStaticMetadata.getAndLock();
             bool isMonochrome = Status::OK ==
-                    CameraHidlTest::isMonochromeCamera(mStaticMetadata);
+                    CameraHidlTest::isMonochromeCamera(staticMetadataBuffer);
             if (isMonochrome) {
                 mParent->verifyMonochromeCameraResult(request->collectedResult);
             }
 
             // Verify logical camera result metadata
             bool isLogicalCamera =
-                    Status::OK == CameraHidlTest::isLogicalMultiCamera(mStaticMetadata);
+                    Status::OK == CameraHidlTest::isLogicalMultiCamera(staticMetadataBuffer);
             if (isLogicalCamera) {
-                mParent->verifyLogicalCameraResult(mStaticMetadata, request->collectedResult);
+                mParent->verifyLogicalCameraResult(staticMetadataBuffer, request->collectedResult);
             }
+            mStaticMetadata.unlock(staticMetadataBuffer);
         }
     }
 
@@ -5402,7 +5406,7 @@
         ASSERT_EQ(Status::OK, s);
         staticMeta = clone_camera_metadata(
                 reinterpret_cast<const camera_metadata_t*>(metadata.data()));
-         ASSERT_NE(nullptr, staticMeta);
+        ASSERT_NE(nullptr, staticMeta);
     });
     ASSERT_TRUE(ret.isOk());
 
diff --git a/compatibility_matrices/compatibility_matrix.4.xml b/compatibility_matrices/compatibility_matrix.4.xml
index 21a0847..01ec172 100644
--- a/compatibility_matrices/compatibility_matrix.4.xml
+++ b/compatibility_matrices/compatibility_matrix.4.xml
@@ -365,7 +365,13 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.radio.config</name>
-        <version>1.2</version>
+        <!--
+        Note: Devices launching with target-level 4, if implementing the
+        radio config HAL, must provide an implementation of 1.1 IRadioConfig
+        that can handle version 1.2 of IRadioConfigResponse and
+        IRadioConfigIndication.
+        -->
+        <version>1.1</version>
         <interface>
             <name>IRadioConfig</name>
             <instance>default</instance>
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 2284723..6e1bc8f 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -365,7 +365,10 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.radio.config</name>
-        <version>1.2</version>
+        <!--
+        See compatibility_matrix.4.xml on versioning of radio config HAL.
+        -->
+        <version>1.1</version>
         <interface>
             <name>IRadioConfig</name>
             <instance>default</instance>
diff --git a/gnss/1.1/vts/functional/gnss_hal_test.cpp b/gnss/1.1/vts/functional/gnss_hal_test.cpp
index 381ac1d..f3b376e 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test.cpp
@@ -16,10 +16,16 @@
 
 #define LOG_TAG "GnssHalTest"
 
+#include <android/hidl/manager/1.2/IServiceManager.h>
+#include <hidl/ServiceManagement.h>
+
 #include <gnss_hal_test.h>
 #include <chrono>
 #include "Utils.h"
 
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+
 using ::android::hardware::gnss::common::Utils;
 
 // Implementations for the main test class for GNSS HAL
@@ -149,6 +155,28 @@
     }
 }
 
+bool GnssHalTest::IsGnssHalVersion_1_1() const {
+    using ::android::hidl::manager::V1_2::IServiceManager;
+    sp<IServiceManager> manager = ::android::hardware::defaultServiceManager1_2();
+
+    bool hasGnssHalVersion_1_1 = false;
+    manager->listManifestByInterface(
+            "android.hardware.gnss@1.1::IGnss",
+            [&hasGnssHalVersion_1_1](const hidl_vec<hidl_string>& registered) {
+                ASSERT_EQ(1, registered.size());
+                hasGnssHalVersion_1_1 = true;
+            });
+
+    bool hasGnssHalVersion_2_0 = false;
+    manager->listManifestByInterface(
+            "android.hardware.gnss@2.0::IGnss",
+            [&hasGnssHalVersion_2_0](const hidl_vec<hidl_string>& registered) {
+                hasGnssHalVersion_2_0 = registered.size() != 0;
+            });
+
+    return hasGnssHalVersion_1_1 && !hasGnssHalVersion_2_0;
+}
+
 void GnssHalTest::notify() {
     std::unique_lock<std::mutex> lock(mtx_);
     notify_count_++;
diff --git a/gnss/1.1/vts/functional/gnss_hal_test.h b/gnss/1.1/vts/functional/gnss_hal_test.h
index 64478b5..84a9f84 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test.h
+++ b/gnss/1.1/vts/functional/gnss_hal_test.h
@@ -145,6 +145,12 @@
      */
     void SetPositionMode(const int min_interval_msec, const bool low_power_mode);
 
+    /*
+     * IsGnssHalVersion_1_1:
+     * returns  true if the GNSS HAL version is exactly 1.1.
+     */
+    bool IsGnssHalVersion_1_1() const;
+
     sp<IGnss> gnss_hal_;         // GNSS HAL to call into
     sp<IGnssCallback> gnss_cb_;  // Primary callback interface
 
diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
index 2d901f3..4288d0d 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
@@ -202,6 +202,11 @@
  * formerly strongest satellite
  */
 TEST_F(GnssHalTest, BlacklistIndividualSatellites) {
+    if (!IsGnssHalVersion_1_1()) {
+        ALOGI("Test BlacklistIndividualSatellites skipped. GNSS HAL version is greater than 1.1.");
+        return;
+    }
+
     const int kLocationsToAwait = 3;
     const int kRetriesToUnBlacklist = 10;
 
@@ -323,6 +328,11 @@
  * 4a & b) Clean up by turning off location, and send in empty blacklist.
  */
 TEST_F(GnssHalTest, BlacklistConstellation) {
+    if (!IsGnssHalVersion_1_1()) {
+        ALOGI("Test BlacklistConstellation skipped. GNSS HAL version is greater than 1.1.");
+        return;
+    }
+
     const int kLocationsToAwait = 3;
 
     StartAndCheckLocations(kLocationsToAwait);
diff --git a/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp b/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp
index a8e40ba..ae36c50 100644
--- a/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp
+++ b/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp
@@ -23,7 +23,6 @@
     ::testing::AddGlobalTestEnvironment(GnssHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
     GnssHidlEnvironment::Instance()->init(&argc, argv);
-    // TODO (b/122463165): Expand coverage to include 1.1 and 1.0 VTS tests.
     int status = RUN_ALL_TESTS();
     ALOGI("Test result = %d", status);
     return status;
diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp
index a9f858c..14ae43c 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp
@@ -152,7 +152,7 @@
       name_cbq_("name"),
       capabilities_cbq_("capabilities"),
       location_cbq_("location"),
-      sv_info_cbq_("sv_info") {}
+      sv_info_list_cbq_("sv_info") {}
 
 Return<void> GnssHalTest::GnssCallback::gnssSetSystemInfoCb(
         const IGnssCallback_1_0::GnssSystemInfo& info) {
@@ -204,7 +204,7 @@
 Return<void> GnssHalTest::GnssCallback::gnssSvStatusCb_2_0(
         const hidl_vec<IGnssCallback_2_0::GnssSvInfo>& svInfoList) {
     ALOGI("gnssSvStatusCb_2_0. Size = %d", (int)svInfoList.size());
-    sv_info_cbq_.store(svInfoList);
+    sv_info_list_cbq_.store(svInfoList);
     return Void();
 }
 
diff --git a/gnss/2.0/vts/functional/gnss_hal_test.h b/gnss/2.0/vts/functional/gnss_hal_test.h
index 05e37d3..90a7866 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test.h
+++ b/gnss/2.0/vts/functional/gnss_hal_test.h
@@ -23,6 +23,7 @@
 
 #include <condition_variable>
 #include <deque>
+#include <list>
 #include <mutex>
 
 using android::hardware::hidl_vec;
@@ -85,6 +86,14 @@
          */
         bool retrieve(T& event, int timeout_seconds);
 
+        /*
+         * Removes parameter count number of callack events at the front of the queue, stores
+         * them in event_list parameter and returns the number of events retrieved. Waits up to
+         * timeout_seconds to retrieve each event. If timeout occurs, it returns the number of
+         * items retrieved which will be less than count.
+         */
+        int retrieve(list<T>& event_list, int count, int timeout_seconds);
+
         /* Returns the number of events pending to be retrieved from the callback event queue. */
         int size() const;
 
@@ -117,7 +126,7 @@
         CallbackQueue<android::hardware::hidl_string> name_cbq_;
         CallbackQueue<uint32_t> capabilities_cbq_;
         CallbackQueue<GnssLocation_2_0> location_cbq_;
-        CallbackQueue<hidl_vec<IGnssCallback_2_0::GnssSvInfo>> sv_info_cbq_;
+        CallbackQueue<hidl_vec<IGnssCallback_2_0::GnssSvInfo>> sv_info_list_cbq_;
 
         GnssCallback();
         virtual ~GnssCallback() = default;
@@ -265,6 +274,19 @@
 }
 
 template <class T>
+int GnssHalTest::CallbackQueue<T>::retrieve(list<T>& event_list, int count, int timeout_seconds) {
+    for (int i = 0; i < count; ++i) {
+        T event;
+        if (!retrieve(event, timeout_seconds)) {
+            return i;
+        }
+        event_list.push_back(event);
+    }
+
+    return count;
+}
+
+template <class T>
 int GnssHalTest::CallbackQueue<T>::size() const {
     std::unique_lock<std::recursive_mutex> lock(mtx_);
     return events_.size();
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 155afd6..6e0887f 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
@@ -23,7 +23,10 @@
 using android::hardware::hidl_string;
 using android::hardware::hidl_vec;
 
+using GnssConstellationType_2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
+using GnssConstellationType_1_0 = android::hardware::gnss::V1_0::GnssConstellationType;
 using IGnssConfiguration_2_0 = android::hardware::gnss::V2_0::IGnssConfiguration;
+using IGnssConfiguration_1_1 = android::hardware::gnss::V1_1::IGnssConfiguration;
 using IAGnssRil_2_0 = android::hardware::gnss::V2_0::IAGnssRil;
 using IGnssMeasurement_2_0 = android::hardware::gnss::V2_0::IGnssMeasurement;
 using IGnssMeasurement_1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
@@ -33,15 +36,12 @@
 using IAGnss_2_0 = android::hardware::gnss::V2_0::IAGnss;
 using IAGnss_1_0 = android::hardware::gnss::V1_0::IAGnss;
 using IAGnssCallback_2_0 = android::hardware::gnss::V2_0::IAGnssCallback;
-using IGnssBatching_V1_0 = android::hardware::gnss::V1_0::IGnssBatching;
-using IGnssBatching_V2_0 = android::hardware::gnss::V2_0::IGnssBatching;
 
 using android::hardware::gnss::common::Utils;
 using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
 using android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections;
 using android::hardware::gnss::V1_0::IGnssNi;
 using android::hardware::gnss::V2_0::ElapsedRealtimeFlags;
-using android::hardware::gnss::V2_0::GnssConstellationType;
 using android::hardware::gnss::V2_0::IGnssCallback;
 using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl;
 
@@ -209,9 +209,9 @@
 
         // Verify ConstellationType is valid.
         ASSERT_TRUE(static_cast<uint8_t>(measurement.constellation) >=
-                            static_cast<uint8_t>(GnssConstellationType::UNKNOWN) &&
+                            static_cast<uint8_t>(GnssConstellationType_2_0::UNKNOWN) &&
                     static_cast<uint8_t>(measurement.constellation) <=
-                            static_cast<uint8_t>(GnssConstellationType::IRNSS));
+                            static_cast<uint8_t>(GnssConstellationType_2_0::IRNSS));
 
         // Verify State is valid.
         ASSERT_TRUE(
@@ -414,3 +414,356 @@
     auto gnssBatching_2_0 = gnss_hal_->getExtensionGnssBatching_2_0();
     ASSERT_TRUE(gnssBatching_2_0.isOk());
 }
+
+/*
+ * MapConstellationType:
+ * Given a GnssConstellationType_2_0 type constellation, maps to its equivalent
+ * GnssConstellationType_1_0 type constellation. For constellations that do not have
+ * an equivalent value, maps to GnssConstellationType_1_0::UNKNOWN
+ */
+GnssConstellationType_1_0 MapConstellationType(GnssConstellationType_2_0 constellation) {
+    switch (constellation) {
+        case GnssConstellationType_2_0::GPS:
+            return GnssConstellationType_1_0::GPS;
+        case GnssConstellationType_2_0::SBAS:
+            return GnssConstellationType_1_0::SBAS;
+        case GnssConstellationType_2_0::GLONASS:
+            return GnssConstellationType_1_0::GLONASS;
+        case GnssConstellationType_2_0::QZSS:
+            return GnssConstellationType_1_0::QZSS;
+        case GnssConstellationType_2_0::BEIDOU:
+            return GnssConstellationType_1_0::BEIDOU;
+        case GnssConstellationType_2_0::GALILEO:
+            return GnssConstellationType_1_0::GALILEO;
+        default:
+            return GnssConstellationType_1_0::UNKNOWN;
+    }
+}
+
+/*
+ * FindStrongFrequentNonGpsSource:
+ *
+ * Search through a GnssSvStatus list for the strongest non-GPS satellite observed enough times
+ *
+ * returns the strongest source,
+ *         or a source with constellation == UNKNOWN if none are found sufficient times
+ */
+IGnssConfiguration_1_1::BlacklistedSource FindStrongFrequentNonGpsSource(
+        const list<hidl_vec<IGnssCallback_2_0::GnssSvInfo>>& sv_info_lists,
+        const int min_observations) {
+    struct ComparableBlacklistedSource {
+        IGnssConfiguration_1_1::BlacklistedSource id;
+
+        ComparableBlacklistedSource() {
+            id.constellation = GnssConstellationType_1_0::UNKNOWN;
+            id.svid = 0;
+        }
+
+        bool operator<(const ComparableBlacklistedSource& compare) const {
+            return ((id.svid < compare.id.svid) || ((id.svid == compare.id.svid) &&
+                                                    (id.constellation < compare.id.constellation)));
+        }
+    };
+
+    struct SignalCounts {
+        int observations;
+        float max_cn0_dbhz;
+    };
+
+    std::map<ComparableBlacklistedSource, SignalCounts> mapSignals;
+
+    for (const auto& sv_info_list : sv_info_lists) {
+        for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
+            if ((sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
+                (sv_info.constellation != GnssConstellationType_2_0::IRNSS) &&
+                (sv_info.constellation != GnssConstellationType_2_0::GPS)) {
+                ComparableBlacklistedSource source;
+                source.id.svid = sv_info.v1_0.svid;
+                source.id.constellation = MapConstellationType(sv_info.constellation);
+
+                const auto& itSignal = mapSignals.find(source);
+                if (itSignal == mapSignals.end()) {
+                    SignalCounts counts;
+                    counts.observations = 1;
+                    counts.max_cn0_dbhz = sv_info.v1_0.cN0Dbhz;
+                    mapSignals.insert(
+                            std::pair<ComparableBlacklistedSource, SignalCounts>(source, counts));
+                } else {
+                    itSignal->second.observations++;
+                    if (itSignal->second.max_cn0_dbhz < sv_info.v1_0.cN0Dbhz) {
+                        itSignal->second.max_cn0_dbhz = sv_info.v1_0.cN0Dbhz;
+                    }
+                }
+            }
+        }
+    }
+
+    float max_cn0_dbhz_with_sufficient_count = 0.;
+    int total_observation_count = 0;
+    int blacklisted_source_count_observation = 0;
+
+    ComparableBlacklistedSource source_to_blacklist;  // initializes to zero = UNKNOWN constellation
+    for (auto const& pairSignal : mapSignals) {
+        total_observation_count += pairSignal.second.observations;
+        if ((pairSignal.second.observations >= min_observations) &&
+            (pairSignal.second.max_cn0_dbhz > max_cn0_dbhz_with_sufficient_count)) {
+            source_to_blacklist = pairSignal.first;
+            blacklisted_source_count_observation = pairSignal.second.observations;
+            max_cn0_dbhz_with_sufficient_count = pairSignal.second.max_cn0_dbhz;
+        }
+    }
+    ALOGD("Among %d observations, chose svid %d, constellation %d, "
+          "with %d observations at %.1f max CNo",
+          total_observation_count, source_to_blacklist.id.svid,
+          (int)source_to_blacklist.id.constellation, blacklisted_source_count_observation,
+          max_cn0_dbhz_with_sufficient_count);
+
+    return source_to_blacklist.id;
+}
+
+/*
+ * BlacklistIndividualSatellites:
+ *
+ * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
+ * GnssStatus for common satellites (strongest and one other.)
+ * 2a & b) Turns off location, and blacklists common satellites.
+ * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
+ * GnssStatus does not use those satellites.
+ * 4a & b) Turns off location, and send in empty blacklist.
+ * 5a) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
+ * GnssStatus does re-use at least the previously strongest satellite
+ * 5b) Retry a few times, in case GNSS search strategy takes a while to reacquire even the
+ * formerly strongest satellite
+ */
+TEST_F(GnssHalTest, BlacklistIndividualSatellites) {
+    if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) {
+        return;
+    }
+
+    const int kLocationsToAwait = 3;
+    const int kRetriesToUnBlacklist = 10;
+
+    gnss_cb_->location_cbq_.reset();
+    StartAndCheckLocations(kLocationsToAwait);
+    int location_called_count = gnss_cb_->location_cbq_.calledCount();
+
+    // Tolerate 1 less sv status to handle edge cases in reporting.
+    int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+    EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
+    ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)",
+          sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
+
+    /*
+     * Identify strongest SV seen at least kLocationsToAwait -1 times
+     * Why -1?  To avoid test flakiness in case of (plausible) slight flakiness in strongest signal
+     * observability (one epoch RF null)
+     */
+
+    const int kGnssSvStatusTimeout = 2;
+    list<hidl_vec<IGnssCallback_2_0::GnssSvInfo>> sv_info_lists;
+    int count = gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_lists, sv_info_list_cbq_size,
+                                                     kGnssSvStatusTimeout);
+    ASSERT_EQ(count, sv_info_list_cbq_size);
+
+    IGnssConfiguration_1_1::BlacklistedSource source_to_blacklist =
+            FindStrongFrequentNonGpsSource(sv_info_lists, kLocationsToAwait - 1);
+
+    if (source_to_blacklist.constellation == GnssConstellationType_1_0::UNKNOWN) {
+        // Cannot find a non-GPS satellite. Let the test pass.
+        return;
+    }
+
+    // Stop locations, blacklist the common SV
+    StopAndClearLocations();
+
+    auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_1_1();
+    ASSERT_TRUE(gnss_configuration_hal_return.isOk());
+    sp<IGnssConfiguration_1_1> gnss_configuration_hal = gnss_configuration_hal_return;
+    ASSERT_NE(gnss_configuration_hal, nullptr);
+
+    hidl_vec<IGnssConfiguration_1_1::BlacklistedSource> sources;
+    sources.resize(1);
+    sources[0] = source_to_blacklist;
+
+    auto result = gnss_configuration_hal->setBlacklist(sources);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+
+    // retry and ensure satellite not used
+    gnss_cb_->sv_info_list_cbq_.reset();
+
+    gnss_cb_->location_cbq_.reset();
+    StartAndCheckLocations(kLocationsToAwait);
+
+    // early exit if test is being run with insufficient signal
+    location_called_count = gnss_cb_->location_cbq_.calledCount();
+    if (location_called_count == 0) {
+        ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
+    }
+    ASSERT_TRUE(location_called_count > 0);
+
+    // Tolerate 1 less sv status to handle edge cases in reporting.
+    sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+    EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
+    ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)",
+          sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
+    for (int i = 0; i < sv_info_list_cbq_size; ++i) {
+        hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
+        gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
+        for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
+            auto constellation = MapConstellationType(sv_info.constellation);
+            EXPECT_FALSE((sv_info.v1_0.svid == source_to_blacklist.svid) &&
+                         (constellation == source_to_blacklist.constellation) &&
+                         (sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX));
+        }
+    }
+
+    // clear blacklist and restart - this time updating the blacklist while location is still on
+    sources.resize(0);
+
+    result = gnss_configuration_hal->setBlacklist(sources);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+
+    bool strongest_sv_is_reobserved = false;
+    // do several loops awaiting a few locations, allowing non-immediate reacquisition strategies
+    int unblacklist_loops_remaining = kRetriesToUnBlacklist;
+    while (!strongest_sv_is_reobserved && (unblacklist_loops_remaining-- > 0)) {
+        StopAndClearLocations();
+        gnss_cb_->sv_info_list_cbq_.reset();
+
+        gnss_cb_->location_cbq_.reset();
+        StartAndCheckLocations(kLocationsToAwait);
+
+        // early exit loop if test is being run with insufficient signal
+        location_called_count = gnss_cb_->location_cbq_.calledCount();
+        if (location_called_count == 0) {
+            ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
+        }
+        ASSERT_TRUE(location_called_count > 0);
+
+        // Tolerate 1 less sv status to handle edge cases in reporting.
+        sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+        EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
+        ALOGD("Clear blacklist, observed %d GnssSvStatus, while awaiting %d Locations"
+              ", tries remaining %d",
+              sv_info_list_cbq_size, kLocationsToAwait, unblacklist_loops_remaining);
+
+        for (int i = 0; i < sv_info_list_cbq_size; ++i) {
+            hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
+            gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
+            for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
+                auto constellation = MapConstellationType(sv_info.constellation);
+                if ((sv_info.v1_0.svid == source_to_blacklist.svid) &&
+                    (constellation == source_to_blacklist.constellation) &&
+                    (sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX)) {
+                    strongest_sv_is_reobserved = true;
+                    break;
+                }
+            }
+            if (strongest_sv_is_reobserved) break;
+        }
+    }
+    EXPECT_TRUE(strongest_sv_is_reobserved);
+    StopAndClearLocations();
+}
+
+/*
+ * BlacklistConstellation:
+ *
+ * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
+ * GnssStatus for any non-GPS constellations.
+ * 2a & b) Turns off location, and blacklist first non-GPS constellations.
+ * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
+ * GnssStatus does not use any constellation but GPS.
+ * 4a & b) Clean up by turning off location, and send in empty blacklist.
+ */
+TEST_F(GnssHalTest, BlacklistConstellation) {
+    if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) {
+        return;
+    }
+
+    const int kLocationsToAwait = 3;
+
+    gnss_cb_->location_cbq_.reset();
+    StartAndCheckLocations(kLocationsToAwait);
+    const int location_called_count = gnss_cb_->location_cbq_.calledCount();
+
+    // Tolerate 1 less sv status to handle edge cases in reporting.
+    int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+    EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
+    ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)",
+          sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
+
+    // Find first non-GPS constellation to blacklist. Exclude IRNSS in GnssConstellationType_2_0
+    // as blacklisting of this constellation is not supported in gnss@2.0.
+    const int kGnssSvStatusTimeout = 2;
+    GnssConstellationType_1_0 constellation_to_blacklist = GnssConstellationType_1_0::UNKNOWN;
+    for (int i = 0; i < sv_info_list_cbq_size; ++i) {
+        hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
+        gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
+        for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
+            if ((sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
+                (sv_info.constellation != GnssConstellationType_2_0::UNKNOWN) &&
+                (sv_info.constellation != GnssConstellationType_2_0::IRNSS) &&
+                (sv_info.constellation != GnssConstellationType_2_0::GPS)) {
+                // found a non-GPS V1_0 constellation
+                constellation_to_blacklist = MapConstellationType(sv_info.constellation);
+                break;
+            }
+        }
+        if (constellation_to_blacklist != GnssConstellationType_1_0::UNKNOWN) {
+            break;
+        }
+    }
+
+    if (constellation_to_blacklist == GnssConstellationType_1_0::UNKNOWN) {
+        ALOGI("No non-GPS constellations found, constellation blacklist test less effective.");
+        // Proceed functionally to blacklist something.
+        constellation_to_blacklist = GnssConstellationType_1_0::GLONASS;
+    }
+    IGnssConfiguration_1_1::BlacklistedSource source_to_blacklist;
+    source_to_blacklist.constellation = constellation_to_blacklist;
+    source_to_blacklist.svid = 0;  // documented wildcard for all satellites in this constellation
+
+    auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_1_1();
+    ASSERT_TRUE(gnss_configuration_hal_return.isOk());
+    sp<IGnssConfiguration_1_1> gnss_configuration_hal = gnss_configuration_hal_return;
+    ASSERT_NE(gnss_configuration_hal, nullptr);
+
+    hidl_vec<IGnssConfiguration_1_1::BlacklistedSource> sources;
+    sources.resize(1);
+    sources[0] = source_to_blacklist;
+
+    auto result = gnss_configuration_hal->setBlacklist(sources);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+
+    // retry and ensure constellation not used
+    gnss_cb_->sv_info_list_cbq_.reset();
+
+    gnss_cb_->location_cbq_.reset();
+    StartAndCheckLocations(kLocationsToAwait);
+
+    // Tolerate 1 less sv status to handle edge cases in reporting.
+    sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+    EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
+    ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations", sv_info_list_cbq_size,
+          kLocationsToAwait);
+    for (int i = 0; i < sv_info_list_cbq_size; ++i) {
+        hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
+        gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
+        for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
+            auto constellation = MapConstellationType(sv_info.constellation);
+            EXPECT_FALSE((constellation == source_to_blacklist.constellation) &&
+                         (sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX));
+        }
+    }
+
+    // clean up
+    StopAndClearLocations();
+    sources.resize(0);
+    result = gnss_configuration_hal->setBlacklist(sources);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+}
\ No newline at end of file
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index c66f574..293c50c 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -309,6 +309,11 @@
     return make_string(a, N);
 }
 
+bool avb_verification_enabled() {
+    char value[PROPERTY_VALUE_MAX];
+    return property_get("ro.boot.vbmeta.device_state", value, "") != 0;
+}
+
 }  // namespace
 
 bool verify_attestation_record(const string& challenge, const string& app_id,
@@ -359,26 +364,32 @@
     EXPECT_EQ(0, memcmp(challenge.data(), att_challenge.data(), challenge.length()));
 
     char property_value[PROPERTY_VALUE_MAX] = {};
-    for (int i = 0; i < att_hw_enforced.size(); i++) {
-        if (att_hw_enforced[i].tag == TAG_BOOT_PATCHLEVEL ||
-            att_hw_enforced[i].tag == TAG_VENDOR_PATCHLEVEL) {
-            std::string date = std::to_string(att_hw_enforced[i].f.integer);
-            // strptime seems to require delimiters, but the tag value will be YYYYMMDD
-            date.insert(6, "-");
-            date.insert(4, "-");
-            EXPECT_EQ(date.size(), 10);
-            struct tm time;
-            strptime(date.c_str(), "%Y-%m-%d", &time);
+    // TODO(b/136282179): When running under VTS-on-GSI the TEE-backed
+    // keymaster implementation will report YYYYMM dates instead of YYYYMMDD
+    // for the BOOT_PATCH_LEVEL.
+    if (avb_verification_enabled()) {
+        for (int i = 0; i < att_hw_enforced.size(); i++) {
+            if (att_hw_enforced[i].tag == TAG_BOOT_PATCHLEVEL ||
+                att_hw_enforced[i].tag == TAG_VENDOR_PATCHLEVEL) {
+                std::string date = std::to_string(att_hw_enforced[i].f.integer);
+                // strptime seems to require delimiters, but the tag value will
+                // be YYYYMMDD
+                date.insert(6, "-");
+                date.insert(4, "-");
+                EXPECT_EQ(date.size(), 10);
+                struct tm time;
+                strptime(date.c_str(), "%Y-%m-%d", &time);
 
-            // Day of the month (0-31)
-            EXPECT_GE(time.tm_mday, 0);
-            EXPECT_LT(time.tm_mday, 32);
-            // Months since Jan (0-11)
-            EXPECT_GE(time.tm_mon, 0);
-            EXPECT_LT(time.tm_mon, 12);
-            // Years since 1900
-            EXPECT_GT(time.tm_year, 110);
-            EXPECT_LT(time.tm_year, 200);
+                // Day of the month (0-31)
+                EXPECT_GE(time.tm_mday, 0);
+                EXPECT_LT(time.tm_mday, 32);
+                // Months since Jan (0-11)
+                EXPECT_GE(time.tm_mon, 0);
+                EXPECT_LT(time.tm_mon, 12);
+                // Years since 1900
+                EXPECT_GT(time.tm_year, 110);
+                EXPECT_LT(time.tm_year, 200);
+            }
         }
     }
 
@@ -410,18 +421,20 @@
                                 &verified_boot_state, &device_locked, &verified_boot_hash);
     EXPECT_EQ(ErrorCode::OK, error);
 
-    property_get("ro.boot.vbmeta.digest", property_value, "nogood");
-    EXPECT_NE(strcmp(property_value, "nogood"), 0);
-    string prop_string(property_value);
-    EXPECT_EQ(prop_string.size(), 64);
-    EXPECT_EQ(prop_string, bin2hex(verified_boot_hash));
+    if (avb_verification_enabled()) {
+        property_get("ro.boot.vbmeta.digest", property_value, "nogood");
+        EXPECT_NE(strcmp(property_value, "nogood"), 0);
+        string prop_string(property_value);
+        EXPECT_EQ(prop_string.size(), 64);
+        EXPECT_EQ(prop_string, bin2hex(verified_boot_hash));
 
-    property_get("ro.boot.vbmeta.device_state", property_value, "nogood");
-    EXPECT_NE(property_value, "nogood");
-    if (!strcmp(property_value, "unlocked")) {
-        EXPECT_FALSE(device_locked);
-    } else {
-        EXPECT_TRUE(device_locked);
+        property_get("ro.boot.vbmeta.device_state", property_value, "nogood");
+        EXPECT_NE(strcmp(property_value, "nogood"), 0);
+        if (!strcmp(property_value, "unlocked")) {
+            EXPECT_FALSE(device_locked);
+        } else {
+            EXPECT_TRUE(device_locked);
+        }
     }
 
     // Verified boot key should be all 0's if the boot state is not verified or self signed
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
index 696c746..26f2c90 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
@@ -41,6 +41,12 @@
 
     ALOGI("emergencyDial, rspInfo.error = %s\n", toString(radioRsp_v1_4->rspInfo.error).c_str());
     EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error);
+
+    // Give some time for modem to establish the emergency call channel.
+    sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME);
+
+    // Disconnect all the potential established calls to prevent them affecting other tests.
+    clearPotentialEstablishedCalls();
 }
 
 /*
@@ -67,6 +73,12 @@
     ALOGI("emergencyDial_withServices, rspInfo.error = %s\n",
           toString(radioRsp_v1_4->rspInfo.error).c_str());
     EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error);
+
+    // Give some time for modem to establish the emergency call channel.
+    sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME);
+
+    // Disconnect all the potential established calls to prevent them affecting other tests.
+    clearPotentialEstablishedCalls();
 }
 
 /*
@@ -93,6 +105,12 @@
     ALOGI("emergencyDial_withEmergencyRouting, rspInfo.error = %s\n",
           toString(radioRsp_v1_4->rspInfo.error).c_str());
     EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error);
+
+    // Give some time for modem to establish the emergency call channel.
+    sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME);
+
+    // Disconnect all the potential established calls to prevent them affecting other tests.
+    clearPotentialEstablishedCalls();
 }
 
 /*
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
index d2d21ce..63e5f6e 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
@@ -87,6 +87,23 @@
     return status;
 }
 
+void RadioHidlTest_v1_4::clearPotentialEstablishedCalls() {
+    // Get the current call Id to hangup the established emergency call.
+    serial = GetRandomSerialNumber();
+    radio_v1_4->getCurrentCalls(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+
+    // Hang up to disconnect the established call channels.
+    for (const ::android::hardware::radio::V1_2::Call& call : radioRsp_v1_4->currentCalls) {
+        serial = GetRandomSerialNumber();
+        radio_v1_4->hangup(serial, call.base.index);
+        ALOGI("Hang up to disconnect the established call channel: %d", call.base.index);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        // Give some time for modem to disconnect the established call channel.
+        sleep(MODEM_EMERGENCY_CALL_DISCONNECT_TIME);
+    }
+}
+
 void RadioHidlTest_v1_4::updateSimCardStatus() {
     serial = GetRandomSerialNumber();
     radio_v1_4->getIccCardStatus(serial);
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
index f662472..b07f9c3 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
+++ b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
@@ -44,6 +44,9 @@
 using ::android::hardware::Void;
 
 #define TIMEOUT_PERIOD 75
+#define MODEM_EMERGENCY_CALL_ESTABLISH_TIME 3
+#define MODEM_EMERGENCY_CALL_DISCONNECT_TIME 3
+
 #define RADIO_SERVICE_NAME "slot1"
 
 class RadioHidlTest_v1_4;
@@ -59,6 +62,9 @@
 
     RadioResponseInfo rspInfo;
 
+    // Call
+    hidl_vec<::android::hardware::radio::V1_2::Call> currentCalls;
+
     // Modem
     bool isModemEnabled;
     bool enableModemResponseToggle;
@@ -725,6 +731,9 @@
     /* Serial number for radio request */
     int serial;
 
+    /* Clear Potential Established Calls */
+    void clearPotentialEstablishedCalls();
+
     /* Update Sim Card Status */
     void updateSimCardStatus();
 
diff --git a/radio/1.4/vts/functional/radio_response.cpp b/radio/1.4/vts/functional/radio_response.cpp
index eac0c68..a849926 100644
--- a/radio/1.4/vts/functional/radio_response.cpp
+++ b/radio/1.4/vts/functional/radio_response.cpp
@@ -77,7 +77,9 @@
     return Void();
 }
 
-Return<void> RadioResponse_v1_4::hangupConnectionResponse(const RadioResponseInfo& /*info*/) {
+Return<void> RadioResponse_v1_4::hangupConnectionResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_4.notify(info.serial);
     return Void();
 }
 
@@ -729,9 +731,10 @@
 
 Return<void> RadioResponse_v1_4::getCurrentCallsResponse_1_2(
         const RadioResponseInfo& info,
-        const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::Call>& /*calls*/) {
+        const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::Call>& calls) {
     rspInfo = info;
     parent_v1_4.notify(info.serial);
+    currentCalls = calls;
     return Void();
 }
 
diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
index 03fcc17..dc54f27 100644
--- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
+++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
@@ -130,8 +130,8 @@
 
 void SensorsHidlEnvironmentV2_0::startPollingThread() {
     mStopThread = false;
-    mPollThread = std::thread(pollingThread, this);
     mEvents.reserve(MAX_RECEIVE_BUFFER_EVENT_COUNT);
+    mPollThread = std::thread(pollingThread, this);
 }
 
 void SensorsHidlEnvironmentV2_0::readEvents() {
diff --git a/tests/libhwbinder/aidl/Android.bp b/tests/libhwbinder/aidl/Android.bp
index 6d49704..c9e09f7 100644
--- a/tests/libhwbinder/aidl/Android.bp
+++ b/tests/libhwbinder/aidl/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "android.hardware.tests.libbinder",
     defaults: ["hidl_defaults"],