GNSS Service handling System death
Stops all GNSS HAL operations, as system doesn't need them any more:
normal, measurements, navigation message, batching
Update default implementation to resend capabilities and system info
and corresponding VTS to enforce
Minor fixes completing the location check
Softens GPS VTS to pass with no signal (still applies better checks
if there is signal)
Bug:36291274
Bug:36066672
Bug:35678469
Bug:35799723
Fixes:36291274
Fixes:36066672
Fixes:35799723
Test: VTS test passes, GPS stops after system server is killed
Basic GPS tests (including delete Xtra) work (before VTS is run)
Change-Id: Ic2ab0f8a79b4aff26eef468615bfee97a83e672f
diff --git a/gnss/1.0/default/Gnss.cpp b/gnss/1.0/default/Gnss.cpp
index 9493737..afb659c 100644
--- a/gnss/1.0/default/Gnss.cpp
+++ b/gnss/1.0/default/Gnss.cpp
@@ -46,7 +46,11 @@
.gnss_sv_status_cb = gnssSvStatusCb,
};
-Gnss::Gnss(gps_device_t* gnssDevice) {
+uint32_t Gnss::sCapabilitiesCached = 0;
+uint16_t Gnss::sYearOfHwCached = 0;
+
+Gnss::Gnss(gps_device_t* gnssDevice) :
+ mDeathRecipient(new GnssHidlDeathRecipient(this)) {
/* Error out if an instance of the interface already exists. */
LOG_ALWAYS_FATAL_IF(sInterfaceExists);
sInterfaceExists = true;
@@ -271,6 +275,9 @@
if (!ret.isOk()) {
ALOGE("%s: Unable to invoke callback", __func__);
}
+
+ // Save for reconnection when some legacy hal's don't resend this info
+ sCapabilitiesCached = capabilities;
}
void Gnss::acquireWakelockCb() {
@@ -373,6 +380,9 @@
if (!ret.isOk()) {
ALOGE("%s: Unable to invoke callback", __func__);
}
+
+ // Save for reconnection when some legacy hal's don't resend this info
+ sYearOfHwCached = info->year_of_hw;
}
@@ -383,7 +393,30 @@
return false;
}
+ if (callback == nullptr) {
+ ALOGE("%s: Null callback ignored", __func__);
+ return false;
+ }
+
+ if (sGnssCbIface != NULL) {
+ ALOGW("%s called more than once. Unexpected unless test.", __func__);
+ sGnssCbIface->unlinkToDeath(mDeathRecipient);
+ }
+
sGnssCbIface = callback;
+ callback->linkToDeath(mDeathRecipient, 0 /*cookie*/);
+
+ // If this was received in the past, send it up again to refresh caller.
+ // mGnssIface will override after init() is called below, if needed
+ // (though it's unlikely the gps.h capabilities or system info will change.)
+ if (sCapabilitiesCached != 0) {
+ setCapabilitiesCb(sCapabilitiesCached);
+ }
+ if (sYearOfHwCached != 0) {
+ LegacyGnssSystemInfo info;
+ info.year_of_hw = sYearOfHwCached;
+ setSystemInfoCb(&info);
+ }
return (mGnssIface->init(&sGnssCb) == 0);
}
@@ -676,6 +709,30 @@
return mGnssBatching;
}
+void Gnss::handleHidlDeath() {
+ ALOGW("GNSS service noticed HIDL death. Stopping all GNSS operations.");
+
+ // commands down to the HAL implementation
+ stop(); // stop ongoing GPS tracking
+ if (mGnssMeasurement != nullptr) {
+ mGnssMeasurement->close();
+ }
+ if (mGnssNavigationMessage != nullptr) {
+ mGnssNavigationMessage->close();
+ }
+ if (mGnssBatching != nullptr) {
+ mGnssBatching->stop();
+ mGnssBatching->cleanup();
+ }
+ cleanup();
+
+ /*
+ * This has died, so close it off in case (race condition) callbacks happen
+ * before HAL processes above messages.
+ */
+ sGnssCbIface = nullptr;
+}
+
IGnss* HIDL_FETCH_IGnss(const char* /* hal */) {
hw_module_t* module;
IGnss* iface = nullptr;
diff --git a/gnss/1.0/default/Gnss.h b/gnss/1.0/default/Gnss.h
index 63614fa..faf903c 100644
--- a/gnss/1.0/default/Gnss.h
+++ b/gnss/1.0/default/Gnss.h
@@ -52,7 +52,8 @@
* Represents the standard GNSS interface. Also contains wrapper methods to allow methods from
* IGnssCallback interface to be passed into the conventional implementation of the GNSS HAL.
*/
-struct Gnss : public IGnss {
+class Gnss : public IGnss {
+ public:
Gnss(gps_device_t* gnss_device);
~Gnss();
@@ -122,6 +123,22 @@
static GpsCallbacks sGnssCb;
private:
+ /*
+ * For handling system-server death while GNSS service lives on.
+ */
+ class GnssHidlDeathRecipient : public hidl_death_recipient {
+ public:
+ GnssHidlDeathRecipient(const sp<Gnss> gnss) : mGnss(gnss) {
+ }
+
+ virtual void serviceDied(uint64_t /*cookie*/,
+ const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
+ mGnss->handleHidlDeath();
+ }
+ private:
+ sp<Gnss> mGnss;
+ };
+
// for wakelock consolidation, see above
static void acquireWakelockGnss();
static void releaseWakelockGnss();
@@ -129,6 +146,11 @@
static bool sWakelockHeldGnss;
static bool sWakelockHeldFused;
+ /*
+ * Cleanup for death notification
+ */
+ void handleHidlDeath();
+
sp<GnssXtra> mGnssXtraIface = nullptr;
sp<AGnssRil> mGnssRil = nullptr;
sp<GnssGeofencing> mGnssGeofencingIface = nullptr;
@@ -139,10 +161,17 @@
sp<GnssDebug> mGnssDebug = nullptr;
sp<GnssConfiguration> mGnssConfig = nullptr;
sp<GnssBatching> mGnssBatching = nullptr;
+
+ sp<GnssHidlDeathRecipient> mDeathRecipient;
+
const GpsInterface* mGnssIface = nullptr;
static sp<IGnssCallback> sGnssCbIface;
static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
static bool sInterfaceExists;
+
+ // Values saved for resend
+ static uint32_t sCapabilitiesCached;
+ static uint16_t sYearOfHwCached;
};
extern "C" IGnss* HIDL_FETCH_IGnss(const char* name);
diff --git a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
index 8f131cf..21b7136 100644
--- a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
+++ b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
@@ -33,17 +33,16 @@
using android::hardware::gnss::V1_0::IGnssCallback;
using android::sp;
-#define TIMEOUT_SECONDS 5 // for basic commands/responses
+#define TIMEOUT_SEC 3 // for basic commands/responses
// The main test class for GNSS HAL.
class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase {
public:
virtual void SetUp() override {
- /* TODO(b/35678469): Setup the init.rc for VTS such that there's a
- * single caller
- * to the GNSS HAL - as part of confirming that the info & capabilities
- * callbacks trigger.
- */
+ // Clean between tests
+ capabilities_called_count_ = 0;
+ location_called_count_ = 0;
+ info_called_count_ = 0;
gnss_hal_ = ::testing::VtsHalHidlTargetTestBase::getService<IGnss>();
ASSERT_NE(gnss_hal_, nullptr);
@@ -53,15 +52,35 @@
auto result = gnss_hal_->setCallback(gnss_cb_);
if (!result.isOk()) {
- ALOGE("result of failed callback set %s", result.description().c_str());
+ ALOGE("result of failed setCallback %s", result.description().c_str());
}
ASSERT_TRUE(result.isOk());
ASSERT_TRUE(result);
- /* TODO(b/35678469): Implement the capabilities & info (year) checks &
- * value store here.
+ /*
+ * At least one callback should trigger - it may be capabilites, or
+ * system info first, so wait again if capabilities not received.
*/
+ EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
+ if (capabilities_called_count_ == 0) {
+ EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
+ }
+
+ /*
+ * Generally should be 1 capabilites callback -
+ * or possibly 2 in some recovery cases (default cached & refreshed)
+ */
+ EXPECT_GE(capabilities_called_count_, 1);
+ EXPECT_LE(capabilities_called_count_, 2);
+
+ /*
+ * Clear notify/waiting counter, allowing up till the timeout after
+ * the last reply for final startup messages to arrive (esp. system
+ * info.)
+ */
+ while (wait(TIMEOUT_SEC) == std::cv_status::no_timeout) {
+ }
}
virtual void TearDown() override {
@@ -93,9 +112,9 @@
/* Callback class for data & Event. */
class GnssCallback : public IGnssCallback {
+ public:
GnssHalTest& parent_;
- public:
GnssCallback(GnssHalTest& parent) : parent_(parent){};
virtual ~GnssCallback() = default;
@@ -171,16 +190,33 @@
* Sets up the callback, awaits the capabilities, and calls cleanup
*
* Since this is just the basic operation of SetUp() and TearDown(),
- * the function definition is intentionally kept empty
+ * the function definition is intentionally empty
*/
TEST_F(GnssHalTest, SetCallbackCapabilitiesCleanup) {}
-void CheckLocation(GnssLocation& location) {
+/*
+ * CheckLocation:
+ * Helper function to vet Location fields
+ */
+
+void CheckLocation(GnssLocation& location, bool checkAccuracies) {
EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG);
EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE);
EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED);
EXPECT_TRUE(location.gnssLocationFlags &
GnssLocationFlags::HAS_HORIZONTAL_ACCURACY);
+ // New uncertainties available in O must be provided,
+ // at least when paired with modern hardware (2017+)
+ if (checkAccuracies) {
+ EXPECT_TRUE(location.gnssLocationFlags &
+ GnssLocationFlags::HAS_VERTICAL_ACCURACY);
+ EXPECT_TRUE(location.gnssLocationFlags &
+ GnssLocationFlags::HAS_SPEED_ACCURACY);
+ if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
+ EXPECT_TRUE(location.gnssLocationFlags &
+ GnssLocationFlags::HAS_BEARING_ACCURACY);
+ }
+ }
EXPECT_GE(location.latitudeDegrees, -90.0);
EXPECT_LE(location.latitudeDegrees, 90.0);
EXPECT_GE(location.longitudeDegrees, -180.0);
@@ -190,12 +226,17 @@
EXPECT_GE(location.speedMetersPerSec, 0.0);
EXPECT_LE(location.speedMetersPerSec, 5.0); // VTS tests are stationary.
+ // Non-zero speeds must be reported with an associated bearing
+ if (location.speedMetersPerSec > 0.0) {
+ EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING);
+ }
+
/*
* Tolerating some especially high values for accuracy estimate, in case of
- * first fix with especially poor geoemtry (happens occasionally)
+ * first fix with especially poor geometry (happens occasionally)
*/
EXPECT_GT(location.horizontalAccuracyMeters, 0.0);
- EXPECT_LE(location.horizontalAccuracyMeters, 200.0);
+ EXPECT_LE(location.horizontalAccuracyMeters, 250.0);
/*
* Some devices may define bearing as -180 to +180, others as 0 to 360.
@@ -220,11 +261,6 @@
// Check timestamp > 1.48e12 (47 years in msec - 1970->2017+)
EXPECT_GT(location.timestamp, 1.48e12);
-
- /* TODO(b/35678469): Check if the hardware year is 2017+, and if so,
- * that bearing, plus vertical, speed & bearing accuracy are present.
- * And allow bearing to be not present, only if associated with a speed of 0.0
- */
}
/*
@@ -241,6 +277,9 @@
#define LOCATION_TIMEOUT_SUBSEQUENT_SEC 3
#define LOCATIONS_TO_CHECK 5
+ bool checkMoreAccuracies =
+ (info_called_count_ > 0 && last_info_.yearOfHw >= 2017);
+
auto result = gnss_hal_->setPositionMode(
IGnss::GnssPositionMode::MS_BASED,
IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC, MIN_INTERVAL_MSEC,
@@ -254,15 +293,18 @@
ASSERT_TRUE(result.isOk());
ASSERT_TRUE(result);
- EXPECT_EQ(std::cv_status::no_timeout, wait(LOCATION_TIMEOUT_FIRST_SEC));
- EXPECT_EQ(location_called_count_, 1);
- CheckLocation(last_location_);
+ // GPS signals initially optional for this test, so don't expect no timeout
+ // yet
+ wait(LOCATION_TIMEOUT_FIRST_SEC);
+ if (location_called_count_ > 0) {
+ CheckLocation(last_location_, checkMoreAccuracies);
+ }
for (int i = 1; i < LOCATIONS_TO_CHECK; i++) {
- EXPECT_EQ(std::cv_status::no_timeout,
- wait(LOCATION_TIMEOUT_SUBSEQUENT_SEC));
- EXPECT_EQ(location_called_count_, i + 1);
- CheckLocation(last_location_);
+ wait(LOCATION_TIMEOUT_SUBSEQUENT_SEC);
+ if (location_called_count_ > 0) {
+ CheckLocation(last_location_, checkMoreAccuracies);
+ }
}
result = gnss_hal_->stop();
@@ -276,4 +318,4 @@
int status = RUN_ALL_TESTS();
ALOGI("Test result = %d", status);
return status;
-}
+}
\ No newline at end of file