Merge "Verify there are no more current calls" into qt-dev am: 1f12b5323a
am: 45fa5dacd9

Change-Id: Icedd28ef8734308638cd0d01e21d80fba765aeb9
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 4016a5a..ee236ba 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
@@ -66,6 +66,11 @@
  * each received location.
  */
 TEST_F(GnssHalTest, GetLocationLowPower) {
+    if (!IsGnssHalVersion_1_1()) {
+        ALOGI("Test GetLocationLowPower skipped. GNSS HAL version is greater than 1.1.");
+        return;
+    }
+
     const int kMinIntervalMsec = 5000;
     const int kLocationTimeoutSubsequentSec = (kMinIntervalMsec / 1000) * 2;
     const int kNoLocationPeriodSec = (kMinIntervalMsec / 1000) / 2;
@@ -209,6 +214,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;
 
@@ -330,6 +340,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..39736cc 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,423 @@
     auto gnssBatching_2_0 = gnss_hal_->getExtensionGnssBatching_2_0();
     ASSERT_TRUE(gnssBatching_2_0.isOk());
 }
+
+/*
+ * GetLocationLowPower:
+ * Turns on location, waits for at least 5 locations allowing max of LOCATION_TIMEOUT_SUBSEQUENT_SEC
+ * between one location and the next. Also ensure that MIN_INTERVAL_MSEC is respected by waiting
+ * NO_LOCATION_PERIOD_SEC and verfiy that no location is received. Also perform validity checks on
+ * each received location.
+ */
+TEST_F(GnssHalTest, GetLocationLowPower) {
+    if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::LOW_POWER_MODE)) {
+        ALOGI("Test GetLocationLowPower skipped. LOW_POWER_MODE capability not supported.");
+        return;
+    }
+
+    const int kMinIntervalMsec = 5000;
+    const int kLocationTimeoutSubsequentSec = (kMinIntervalMsec / 1000) * 2;
+    const int kNoLocationPeriodSec = (kMinIntervalMsec / 1000) / 2;
+    const int kLocationsToCheck = 5;
+    const bool kLowPowerMode = true;
+
+    // Warmup period - VTS doesn't have AGPS access via GnssLocationProvider
+    gnss_cb_->location_cbq_.reset();
+    StartAndCheckLocations(kLocationsToCheck);
+    StopAndClearLocations();
+    gnss_cb_->location_cbq_.reset();
+
+    // Start of Low Power Mode test
+    SetPositionMode(kMinIntervalMsec, kLowPowerMode);
+
+    // Don't expect true - as without AGPS access
+    if (!StartAndCheckFirstLocation()) {
+        ALOGW("GetLocationLowPower test - no first low power location received.");
+    }
+
+    for (int i = 1; i < kLocationsToCheck; i++) {
+        // Verify that kMinIntervalMsec is respected by waiting kNoLocationPeriodSec and
+        // ensure that no location is received yet
+
+        gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, kNoLocationPeriodSec);
+        const int locationCalledCount = gnss_cb_->location_cbq_.calledCount();
+
+        // Tolerate (ignore) one extra location right after the first one
+        // to handle startup edge case scheduling limitations in some implementations
+        if ((i == 1) && (locationCalledCount == 2)) {
+            CheckLocation(gnss_cb_->last_location_, true);
+            continue;  // restart the quiet wait period after this too-fast location
+        }
+        EXPECT_LE(locationCalledCount, i);
+        if (locationCalledCount != i) {
+            ALOGW("GetLocationLowPower test - not enough locations received. %d vs. %d expected ",
+                  locationCalledCount, i);
+        }
+
+        if (!gnss_cb_->location_cbq_.retrieve(
+                    gnss_cb_->last_location_,
+                    kLocationTimeoutSubsequentSec - kNoLocationPeriodSec)) {
+            ALOGW("GetLocationLowPower test - timeout awaiting location %d", i);
+        } else {
+            CheckLocation(gnss_cb_->last_location_, true);
+        }
+    }
+
+    StopAndClearLocations();
+}
+
+/*
+ * 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)) {
+        ALOGI("Test BlacklistIndividualSatellites skipped. SATELLITE_BLACKLIST capability"
+              " not supported.");
+        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)) {
+        ALOGI("Test BlacklistConstellation skipped. SATELLITE_BLACKLIST capability not supported.");
+        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/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
index d4c5f32..444797d 100644
--- a/sensors/1.0/vts/functional/Android.bp
+++ b/sensors/1.0/vts/functional/Android.bp
@@ -16,6 +16,7 @@
 
 cc_test {
     name: "VtsHalSensorsV1_0TargetTest",
+    cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""],
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         "SensorsHidlEnvironmentV1_0.cpp",
diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
index 47308e1..5453ef6 100644
--- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
+++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "sensors_hidl_hal_test"
-
 #include "SensorsHidlEnvironmentV1_0.h"
 #include "sensors-vts-utils/SensorsHidlTestBase.h"
 
diff --git a/sensors/2.0/vts/functional/Android.bp b/sensors/2.0/vts/functional/Android.bp
index 8e8413c..98f0eac 100644
--- a/sensors/2.0/vts/functional/Android.bp
+++ b/sensors/2.0/vts/functional/Android.bp
@@ -16,6 +16,7 @@
 
 cc_test {
     name: "VtsHalSensorsV2_0TargetTest",
+    cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""],
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         "SensorsHidlEnvironmentV2_0.cpp",
diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
index 0525bdc..03fcc17 100644
--- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
+++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
@@ -38,6 +38,13 @@
 
 constexpr size_t SensorsHidlEnvironmentV2_0::MAX_RECEIVE_BUFFER_EVENT_COUNT;
 
+void SensorsHalDeathRecipient::serviceDied(
+        uint64_t /* cookie */,
+        const ::android::wp<::android::hidl::base::V1_0::IBase>& /* service */) {
+    ALOGE("Sensors HAL died (likely crashed) during test");
+    FAIL() << "Sensors HAL died during test";
+}
+
 struct SensorsCallback : ISensorsCallback {
     Return<void> onDynamicSensorsConnected(const hidl_vec<SensorInfo>& /* sensorInfos */) {
         return Return<void>();
@@ -56,6 +63,7 @@
         if (mSensors == nullptr) {
             break;
         }
+        mSensors->linkToDeath(mDeathRecipient, 0 /* cookie */);
 
         // Initialize FMQs
         mEventQueue = std::make_unique<EventMessageQueue>(MAX_RECEIVE_BUFFER_EVENT_COUNT,
diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h
index 5e54530..b0dbd90 100644
--- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h
+++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h
@@ -32,6 +32,13 @@
 using ::android::hardware::MessageQueue;
 
 class SensorsHidlTest;
+
+class SensorsHalDeathRecipient : public ::android::hardware::hidl_death_recipient {
+    virtual void serviceDied(
+            uint64_t cookie,
+            const ::android::wp<::android::hidl::base::V1_0::IBase>& service) override;
+};
+
 class SensorsHidlEnvironmentV2_0 : public SensorsHidlEnvironmentBase {
    public:
     using Event = ::android::hardware::sensors::V1_0::Event;
@@ -84,6 +91,11 @@
     sp<android::hardware::sensors::V2_0::ISensors> mSensors;
 
     /**
+     * Monitors the HAL for crashes, triggering test failure if seen
+     */
+    sp<SensorsHalDeathRecipient> mDeathRecipient = new SensorsHalDeathRecipient();
+
+    /**
      * Type used to simplify the creation of the Event FMQ
      */
     typedef MessageQueue<Event, ::android::hardware::kSynchronizedReadWrite> EventMessageQueue;
diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
index 62c5334..6ff393d 100644
--- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
+++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "sensors_hidl_hal_test"
-
 #include "SensorsHidlEnvironmentV2_0.h"
 #include "sensors-vts-utils/SensorsHidlTestBase.h"
 #include "sensors-vts-utils/SensorsTestSharedMemory.h"
@@ -40,6 +38,10 @@
 using ::android::hardware::sensors::V1_0::SensorStatus;
 using ::android::hardware::sensors::V1_0::SharedMemType;
 using ::android::hardware::sensors::V1_0::Vec3;
+using std::chrono::duration_cast;
+using std::chrono::microseconds;
+using std::chrono::milliseconds;
+using std::chrono::nanoseconds;
 
 constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
 
@@ -69,9 +71,9 @@
     }
 
     void waitForFlushEvents(const std::vector<SensorInfo>& sensorsToWaitFor,
-                            int32_t numCallsToFlush, int64_t timeoutMs) {
+                            int32_t numCallsToFlush, milliseconds timeout) {
         std::unique_lock<std::recursive_mutex> lock(mFlushMutex);
-        mFlushCV.wait_for(lock, std::chrono::milliseconds(timeoutMs),
+        mFlushCV.wait_for(lock, timeout,
                           [&] { return flushesReceived(sensorsToWaitFor, numCallsToFlush); });
     }
 
@@ -80,10 +82,9 @@
         return mEventMap[sensorHandle];
     }
 
-    void waitForEvents(const std::vector<SensorInfo>& sensorsToWaitFor, int32_t timeoutMs) {
+    void waitForEvents(const std::vector<SensorInfo>& sensorsToWaitFor, milliseconds timeout) {
         std::unique_lock<std::recursive_mutex> lock(mEventMutex);
-        mEventCV.wait_for(lock, std::chrono::milliseconds(timeoutMs),
-                          [&] { return eventsReceived(sensorsToWaitFor); });
+        mEventCV.wait_for(lock, timeout, [&] { return eventsReceived(sensorsToWaitFor); });
     }
 
    protected:
@@ -117,7 +118,13 @@
 // The main test class for SENSORS HIDL HAL.
 
 class SensorsHidlTest : public SensorsHidlTestBase {
-   protected:
+  public:
+    virtual void SetUp() override {
+        // Ensure that we have a valid environment before performing tests
+        ASSERT_NE(getSensors(), nullptr);
+    }
+
+  protected:
     SensorInfo defaultSensorByType(SensorType type) override;
     std::vector<SensorInfo> getSensorsList();
     // implementation wrapper
@@ -368,7 +375,7 @@
     }
 
     // Wait for events to be written back to the Event FMQ
-    callback.waitForEvents(sensors, 1000 /* timeoutMs */);
+    callback.waitForEvents(sensors, milliseconds(1000) /* timeout */);
 
     for (const auto& s : sensors) {
         auto events = callback.getEvents(s.sensorHandle);
@@ -614,6 +621,9 @@
     std::unique_ptr<SensorsHidlEnvironmentTest> newEnv =
         std::make_unique<SensorsHidlEnvironmentTest>();
     newEnv->HidlSetUp();
+    if (HasFatalFailure()) {
+        return;  // Exit early if setting up the new environment failed
+    }
 
     activateAllSensors(true);
     // Verify that the old environment does not receive any events
@@ -626,8 +636,11 @@
     newEnv->HidlTearDown();
 
     // Restore the test environment for future tests
-    SensorsHidlEnvironmentV2_0::Instance()->HidlTearDown();
-    SensorsHidlEnvironmentV2_0::Instance()->HidlSetUp();
+    getEnvironment()->HidlTearDown();
+    getEnvironment()->HidlSetUp();
+    if (HasFatalFailure()) {
+        return;  // Exit early if resetting the environment failed
+    }
 
     // Ensure that the original environment is receiving events
     activateAllSensors(true);
@@ -646,8 +659,11 @@
     // Clear the active sensor handles so they are not disabled during TearDown
     auto handles = mSensorHandles;
     mSensorHandles.clear();
-    getEnvironment()->TearDown();
-    getEnvironment()->SetUp();
+    getEnvironment()->HidlTearDown();
+    getEnvironment()->HidlSetUp();
+    if (HasFatalFailure()) {
+        return;  // Exit early if resetting the environment failed
+    }
 
     // Verify no events are received until sensors are re-activated
     ASSERT_EQ(collectEvents(kCollectionTimeoutUs, kNumEvents, getEnvironment()).size(), 0);
@@ -686,7 +702,7 @@
     }
 
     // Wait up to one second for the flush events
-    callback.waitForFlushEvents(sensors, flushCalls, 1000 /* timeoutMs */);
+    callback.waitForFlushEvents(sensors, flushCalls, milliseconds(1000) /* timeout */);
 
     // Deactivate all sensors after waiting for flush events so pending flush events are not
     // abandoned by the HAL.
@@ -807,17 +823,18 @@
 }
 
 TEST_F(SensorsHidlTest, NoStaleEvents) {
-    constexpr int64_t kFiveHundredMilliseconds = 500 * 1000;
-    constexpr int64_t kOneSecond = 1000 * 1000;
+    constexpr milliseconds kFiveHundredMs(500);
+    constexpr milliseconds kOneSecond(1000);
 
     // Register the callback to receive sensor events
     EventCallback callback;
     getEnvironment()->registerCallback(&callback);
 
     const std::vector<SensorInfo> sensors = getSensorsList();
-    int32_t maxMinDelay = 0;
+    milliseconds maxMinDelay(0);
     for (const SensorInfo& sensor : getSensorsList()) {
-        maxMinDelay = std::max(maxMinDelay, sensor.minDelay);
+        milliseconds minDelay = duration_cast<milliseconds>(microseconds(sensor.minDelay));
+        maxMinDelay = milliseconds(std::max(maxMinDelay.count(), minDelay.count()));
     }
 
     // Activate the sensors so that they start generating events
@@ -826,7 +843,7 @@
     // According to the CDD, the first sample must be generated within 400ms + 2 * sample_time
     // and the maximum reporting latency is 100ms + 2 * sample_time. Wait a sufficient amount
     // of time to guarantee that a sample has arrived.
-    callback.waitForEvents(sensors, kFiveHundredMilliseconds + (5 * maxMinDelay));
+    callback.waitForEvents(sensors, kFiveHundredMs + (5 * maxMinDelay));
     activateAllSensors(false);
 
     // Save the last received event for each sensor
@@ -838,21 +855,21 @@
     }
 
     // Allow some time to pass, reset the callback, then reactivate the sensors
-    usleep(kOneSecond + (5 * maxMinDelay));
+    usleep(duration_cast<microseconds>(kOneSecond + (5 * maxMinDelay)).count());
     callback.reset();
     activateAllSensors(true);
-    callback.waitForEvents(sensors, kFiveHundredMilliseconds + (5 * maxMinDelay));
+    callback.waitForEvents(sensors, kFiveHundredMs + (5 * maxMinDelay));
     activateAllSensors(false);
 
     for (const SensorInfo& sensor : sensors) {
         // Ensure that the first event received is not stale by ensuring that its timestamp is
         // sufficiently different from the previous event
         const Event newEvent = callback.getEvents(sensor.sensorHandle).front();
-        int64_t delta = newEvent.timestamp - lastEventTimestampMap[sensor.sensorHandle];
-        ASSERT_GE(delta, kFiveHundredMilliseconds + (3 * sensor.minDelay));
+        milliseconds delta = duration_cast<milliseconds>(
+                nanoseconds(newEvent.timestamp - lastEventTimestampMap[sensor.sensorHandle]));
+        milliseconds sensorMinDelay = duration_cast<milliseconds>(microseconds(sensor.minDelay));
+        ASSERT_GE(delta, kFiveHundredMs + (3 * sensorMinDelay));
     }
-
-    getEnvironment()->unregisterCallback();
 }
 
 void SensorsHidlTest::checkRateLevel(const SensorInfo& sensor, int32_t directChannelHandle,
@@ -1030,8 +1047,11 @@
     // Clear the active direct connections so they are not stopped during TearDown
     auto handles = mDirectChannelHandles;
     mDirectChannelHandles.clear();
-    getEnvironment()->TearDown();
-    getEnvironment()->SetUp();
+    getEnvironment()->HidlTearDown();
+    getEnvironment()->HidlSetUp();
+    if (HasFatalFailure()) {
+        return;  // Exit early if resetting the environment failed
+    }
 
     // Attempt to configure the direct channel and expect it to fail
     configDirectReport(
diff --git a/sensors/common/vts/utils/Android.bp b/sensors/common/vts/utils/Android.bp
index 95df425..8da554a 100644
--- a/sensors/common/vts/utils/Android.bp
+++ b/sensors/common/vts/utils/Android.bp
@@ -16,6 +16,7 @@
 
 cc_library_static {
     name: "VtsHalSensorsTargetTestUtils",
+    cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""],
     srcs: [
         "GrallocWrapper.cpp",
         "SensorsHidlEnvironmentBase.cpp",
diff --git a/sensors/common/vts/utils/GrallocWrapper.cpp b/sensors/common/vts/utils/GrallocWrapper.cpp
index 7bed16d..222ef96 100644
--- a/sensors/common/vts/utils/GrallocWrapper.cpp
+++ b/sensors/common/vts/utils/GrallocWrapper.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "GrallocWrapper"
-
 #include "GrallocWrapper.h"
 
 #include <utils/Log.h>
@@ -35,8 +33,7 @@
     mMapper = mapper2::IMapper::getService();
     if (mMapper == nullptr) {
         ALOGE("Failed to get mapper service");
-    }
-    if (mMapper->isRemote()) {
+    } else if (mMapper->isRemote()) {
         ALOGE("Mapper is not in passthrough mode");
     }
 }