Merge "Add more GnssDebug validity tests" into main
This commit is contained in:
commit
53a9a09a65
7 changed files with 276 additions and 41 deletions
|
@ -162,12 +162,13 @@ ScopedAStatus Gnss::close() {
|
|||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
void Gnss::reportLocation(const GnssLocation& location) const {
|
||||
void Gnss::reportLocation(const GnssLocation& location) {
|
||||
std::unique_lock<std::mutex> lock(mMutex);
|
||||
if (sGnssCallback == nullptr) {
|
||||
ALOGE("%s: GnssCallback is null.", __func__);
|
||||
return;
|
||||
}
|
||||
mLastLocation = std::make_shared<GnssLocation>(location);
|
||||
auto status = sGnssCallback->gnssLocationCb(location);
|
||||
if (!status.isOk()) {
|
||||
ALOGE("%s: Unable to invoke gnssLocationCb", __func__);
|
||||
|
@ -359,7 +360,6 @@ ScopedAStatus Gnss::getExtensionGnssNavigationMessage(
|
|||
|
||||
ndk::ScopedAStatus Gnss::getExtensionGnssDebug(std::shared_ptr<IGnssDebug>* iGnssDebug) {
|
||||
ALOGD("Gnss::getExtensionGnssDebug");
|
||||
|
||||
*iGnssDebug = SharedRefBase::make<GnssDebug>();
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
@ -398,4 +398,8 @@ void Gnss::setGnssMeasurementInterval(const long intervalMs) {
|
|||
mGnssMeasurementIntervalMs = intervalMs;
|
||||
}
|
||||
|
||||
std::shared_ptr<GnssLocation> Gnss::getLastLocation() const {
|
||||
return mLastLocation;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::gnss
|
||||
|
|
|
@ -87,18 +87,19 @@ class Gnss : public BnGnss {
|
|||
void reportSvStatus() const;
|
||||
void setGnssMeasurementEnabled(const bool enabled);
|
||||
void setGnssMeasurementInterval(const long intervalMs);
|
||||
std::shared_ptr<GnssLocation> getLastLocation() const;
|
||||
std::shared_ptr<GnssConfiguration> mGnssConfiguration;
|
||||
std::shared_ptr<GnssPowerIndication> mGnssPowerIndication;
|
||||
std::shared_ptr<GnssMeasurementInterface> mGnssMeasurementInterface;
|
||||
|
||||
private:
|
||||
void reportLocation(const GnssLocation&) const;
|
||||
void reportLocation(const GnssLocation&);
|
||||
void reportSvStatus(const std::vector<IGnssCallback::GnssSvInfo>& svInfoList) const;
|
||||
void reportGnssStatusValue(const IGnssCallback::GnssStatusValue gnssStatusValue) const;
|
||||
void reportNmea() const;
|
||||
std::vector<IGnssCallback::GnssSvInfo> filterBlocklistedSatellites(
|
||||
std::vector<IGnssCallback::GnssSvInfo> gnssSvInfoList) const;
|
||||
void reportGnssStatusValue(const IGnssCallback::GnssStatusValue gnssStatusValue) const;
|
||||
std::unique_ptr<GnssLocation> getLocationFromHW();
|
||||
void reportNmea() const;
|
||||
|
||||
static std::shared_ptr<IGnssCallback> sGnssCallback;
|
||||
|
||||
|
@ -109,6 +110,7 @@ class Gnss : public BnGnss {
|
|||
std::atomic<bool> mIsNmeaActive;
|
||||
std::atomic<bool> mFirstFixReceived;
|
||||
std::atomic<bool> mGnssMeasurementEnabled;
|
||||
std::shared_ptr<GnssLocation> mLastLocation;
|
||||
std::thread mThread;
|
||||
::android::hardware::gnss::common::ThreadBlocker mThreadBlocker;
|
||||
|
||||
|
|
|
@ -18,10 +18,15 @@
|
|||
|
||||
#include "GnssDebug.h"
|
||||
#include <log/log.h>
|
||||
#include <utils/SystemClock.h>
|
||||
#include "Constants.h"
|
||||
#include "Gnss.h"
|
||||
#include "MockLocation.h"
|
||||
|
||||
namespace aidl::android::hardware::gnss {
|
||||
|
||||
using ::android::hardware::gnss::common::kMockTimestamp;
|
||||
|
||||
ndk::ScopedAStatus GnssDebug::getDebugData(DebugData* debugData) {
|
||||
ALOGD("GnssDebug::getDebugData");
|
||||
|
||||
|
@ -36,10 +41,94 @@ ndk::ScopedAStatus GnssDebug::getDebugData(DebugData* debugData) {
|
|||
.speedAccuracyMetersPerSecond = 1,
|
||||
.bearingAccuracyDegrees = 90,
|
||||
.ageSeconds = 0.99};
|
||||
TimeDebug timeDebug = {.timeEstimateMs = 1519930775453L,
|
||||
TimeDebug timeDebug = {.timeEstimateMs = static_cast<int64_t>(
|
||||
kMockTimestamp + ::android::elapsedRealtimeNano() / 1e6),
|
||||
.timeUncertaintyNs = 1000,
|
||||
.frequencyUncertaintyNsPerSec = 5.0e4};
|
||||
std::vector<SatelliteData> satelliteDataArrayDebug = {};
|
||||
.frequencyUncertaintyNsPerSec = 800};
|
||||
SatelliteData satelliteData1 = {
|
||||
.svid = 3,
|
||||
.constellation = GnssConstellationType::GPS,
|
||||
.ephemerisType = SatelliteEphemerisType::EPHEMERIS,
|
||||
.ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
|
||||
.ephemerisHealth = SatelliteEphemerisHealth::GOOD,
|
||||
.ephemerisAgeSeconds = 12,
|
||||
.serverPredictionIsAvailable = true,
|
||||
.serverPredictionAgeSeconds = 30};
|
||||
SatelliteData satelliteData2 = {
|
||||
.svid = 5,
|
||||
.constellation = GnssConstellationType::GPS,
|
||||
.ephemerisType = SatelliteEphemerisType::EPHEMERIS,
|
||||
.ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
|
||||
.ephemerisHealth = SatelliteEphemerisHealth::GOOD,
|
||||
.ephemerisAgeSeconds = 12,
|
||||
.serverPredictionIsAvailable = true,
|
||||
.serverPredictionAgeSeconds = 30};
|
||||
SatelliteData satelliteData3 = {
|
||||
.svid = 17,
|
||||
.constellation = GnssConstellationType::GPS,
|
||||
.ephemerisType = SatelliteEphemerisType::EPHEMERIS,
|
||||
.ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
|
||||
.ephemerisHealth = SatelliteEphemerisHealth::GOOD,
|
||||
.ephemerisAgeSeconds = 12,
|
||||
.serverPredictionIsAvailable = true,
|
||||
.serverPredictionAgeSeconds = 30};
|
||||
SatelliteData satelliteData4 = {
|
||||
.svid = 26,
|
||||
.constellation = GnssConstellationType::GPS,
|
||||
.ephemerisType = SatelliteEphemerisType::EPHEMERIS,
|
||||
.ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
|
||||
.ephemerisHealth = SatelliteEphemerisHealth::GOOD,
|
||||
.ephemerisAgeSeconds = 12,
|
||||
.serverPredictionIsAvailable = true,
|
||||
.serverPredictionAgeSeconds = 30};
|
||||
SatelliteData satelliteData5 = {
|
||||
.svid = 5,
|
||||
.constellation = GnssConstellationType::GLONASS,
|
||||
.ephemerisType = SatelliteEphemerisType::EPHEMERIS,
|
||||
.ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
|
||||
.ephemerisHealth = SatelliteEphemerisHealth::GOOD,
|
||||
.ephemerisAgeSeconds = 12,
|
||||
.serverPredictionIsAvailable = true,
|
||||
.serverPredictionAgeSeconds = 30};
|
||||
SatelliteData satelliteData6 = {
|
||||
.svid = 17,
|
||||
.constellation = GnssConstellationType::GLONASS,
|
||||
.ephemerisType = SatelliteEphemerisType::EPHEMERIS,
|
||||
.ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
|
||||
.ephemerisHealth = SatelliteEphemerisHealth::GOOD,
|
||||
.ephemerisAgeSeconds = 12,
|
||||
.serverPredictionIsAvailable = true,
|
||||
.serverPredictionAgeSeconds = 30};
|
||||
SatelliteData satelliteData7 = {
|
||||
.svid = 18,
|
||||
.constellation = GnssConstellationType::GLONASS,
|
||||
.ephemerisType = SatelliteEphemerisType::EPHEMERIS,
|
||||
.ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
|
||||
.ephemerisHealth = SatelliteEphemerisHealth::GOOD,
|
||||
.ephemerisAgeSeconds = 12,
|
||||
.serverPredictionIsAvailable = true,
|
||||
.serverPredictionAgeSeconds = 30};
|
||||
SatelliteData satelliteData8 = {
|
||||
.svid = 10,
|
||||
.constellation = GnssConstellationType::GLONASS,
|
||||
.ephemerisType = SatelliteEphemerisType::EPHEMERIS,
|
||||
.ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
|
||||
.ephemerisHealth = SatelliteEphemerisHealth::GOOD,
|
||||
.ephemerisAgeSeconds = 12,
|
||||
.serverPredictionIsAvailable = true,
|
||||
.serverPredictionAgeSeconds = 30};
|
||||
SatelliteData satelliteData9 = {
|
||||
.svid = 3,
|
||||
.constellation = GnssConstellationType::IRNSS,
|
||||
.ephemerisType = SatelliteEphemerisType::EPHEMERIS,
|
||||
.ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
|
||||
.ephemerisHealth = SatelliteEphemerisHealth::GOOD,
|
||||
.ephemerisAgeSeconds = 12,
|
||||
.serverPredictionIsAvailable = true,
|
||||
.serverPredictionAgeSeconds = 30};
|
||||
std::vector<SatelliteData> satelliteDataArrayDebug = {
|
||||
satelliteData1, satelliteData2, satelliteData3, satelliteData4, satelliteData5,
|
||||
satelliteData6, satelliteData7, satelliteData8, satelliteData9};
|
||||
debugData->position = positionDebug;
|
||||
debugData->time = timeDebug;
|
||||
debugData->satelliteDataArray = satelliteDataArrayDebug;
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
namespace aidl::android::hardware::gnss {
|
||||
|
||||
class Gnss;
|
||||
|
||||
struct GnssDebug : public BnGnssDebug {
|
||||
public:
|
||||
ndk::ScopedAStatus getDebugData(DebugData* debugData) override;
|
||||
|
|
|
@ -1149,40 +1149,139 @@ TEST_P(GnssHalTest, GnssDebugValuesSanityTest) {
|
|||
sp<IGnssDebug> iGnssDebug;
|
||||
auto status = aidl_gnss_hal_->getExtensionGnssDebug(&iGnssDebug);
|
||||
ASSERT_TRUE(status.isOk());
|
||||
|
||||
if (!IsAutomotiveDevice()) {
|
||||
ASSERT_TRUE(iGnssDebug != nullptr);
|
||||
|
||||
IGnssDebug::DebugData data;
|
||||
auto status = iGnssDebug->getDebugData(&data);
|
||||
ASSERT_TRUE(status.isOk());
|
||||
|
||||
if (data.position.valid) {
|
||||
ASSERT_TRUE(data.position.latitudeDegrees >= -90 &&
|
||||
data.position.latitudeDegrees <= 90);
|
||||
ASSERT_TRUE(data.position.longitudeDegrees >= -180 &&
|
||||
data.position.longitudeDegrees <= 180);
|
||||
ASSERT_TRUE(data.position.altitudeMeters >= -1000 && // Dead Sea: -414m
|
||||
data.position.altitudeMeters <= 20000); // Mount Everest: 8850m
|
||||
ASSERT_TRUE(data.position.speedMetersPerSec >= 0 &&
|
||||
data.position.speedMetersPerSec <= 600);
|
||||
ASSERT_TRUE(data.position.bearingDegrees >= -360 &&
|
||||
data.position.bearingDegrees <= 360);
|
||||
ASSERT_TRUE(data.position.horizontalAccuracyMeters > 0 &&
|
||||
data.position.horizontalAccuracyMeters <= 20000000);
|
||||
ASSERT_TRUE(data.position.verticalAccuracyMeters > 0 &&
|
||||
data.position.verticalAccuracyMeters <= 20000);
|
||||
ASSERT_TRUE(data.position.speedAccuracyMetersPerSecond > 0 &&
|
||||
data.position.speedAccuracyMetersPerSecond <= 500);
|
||||
ASSERT_TRUE(data.position.bearingAccuracyDegrees > 0 &&
|
||||
data.position.bearingAccuracyDegrees <= 180);
|
||||
ASSERT_TRUE(data.position.ageSeconds >= 0);
|
||||
}
|
||||
ASSERT_TRUE(data.time.timeEstimateMs >= 1483228800000); // Jan 01 2017 00:00:00 GMT.
|
||||
ASSERT_TRUE(data.time.timeUncertaintyNs > 0);
|
||||
ASSERT_TRUE(data.time.frequencyUncertaintyNsPerSec > 0 &&
|
||||
data.time.frequencyUncertaintyNsPerSec <= 2.0e5); // 200 ppm
|
||||
if (IsAutomotiveDevice()) {
|
||||
return;
|
||||
}
|
||||
ASSERT_TRUE(iGnssDebug != nullptr);
|
||||
|
||||
IGnssDebug::DebugData data;
|
||||
status = iGnssDebug->getDebugData(&data);
|
||||
ASSERT_TRUE(status.isOk());
|
||||
Utils::checkPositionDebug(data);
|
||||
|
||||
// Additional GnssDebug tests for AIDL version >= 4 (launched in Android 15(V)+)
|
||||
if (aidl_gnss_hal_->getInterfaceVersion() <= 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Start location and check the consistency between SvStatus and DebugData
|
||||
aidl_gnss_cb_->location_cbq_.reset();
|
||||
aidl_gnss_cb_->sv_info_list_cbq_.reset();
|
||||
StartAndCheckLocations(/* count= */ 2);
|
||||
int location_called_count = aidl_gnss_cb_->location_cbq_.calledCount();
|
||||
ALOGD("Observed %d GnssSvStatus, while awaiting 2 locations (%d received)",
|
||||
aidl_gnss_cb_->sv_info_list_cbq_.size(), location_called_count);
|
||||
|
||||
// Wait for up to kNumSvInfoLists events for kTimeoutSeconds for each event.
|
||||
int kTimeoutSeconds = 2;
|
||||
int kNumSvInfoLists = 4;
|
||||
std::list<std::vector<IGnssCallback::GnssSvInfo>> sv_info_lists;
|
||||
std::vector<IGnssCallback::GnssSvInfo> last_sv_info_list;
|
||||
|
||||
do {
|
||||
EXPECT_GT(aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_lists, kNumSvInfoLists,
|
||||
kTimeoutSeconds),
|
||||
0);
|
||||
if (!sv_info_lists.empty()) {
|
||||
last_sv_info_list = sv_info_lists.back();
|
||||
ALOGD("last_sv_info size = %d", (int)last_sv_info_list.size());
|
||||
}
|
||||
} while (!sv_info_lists.empty() && last_sv_info_list.size() == 0);
|
||||
|
||||
StopAndClearLocations();
|
||||
|
||||
status = iGnssDebug->getDebugData(&data);
|
||||
Utils::checkPositionDebug(data);
|
||||
|
||||
// Validate SatelliteEphemerisType, SatelliteEphemerisSource, SatelliteEphemerisHealth
|
||||
for (auto sv_info : last_sv_info_list) {
|
||||
if ((sv_info.svFlag & static_cast<int>(IGnssCallback::GnssSvFlags::USED_IN_FIX)) == 0) {
|
||||
continue;
|
||||
}
|
||||
ALOGD("Found usedInFix const: %d, svid: %d", static_cast<int>(sv_info.constellation),
|
||||
sv_info.svid);
|
||||
bool foundDebugData = false;
|
||||
for (auto satelliteData : data.satelliteDataArray) {
|
||||
if (satelliteData.constellation == sv_info.constellation &&
|
||||
satelliteData.svid == sv_info.svid) {
|
||||
foundDebugData = true;
|
||||
ALOGD("Found GnssDebug data for this sv.");
|
||||
EXPECT_TRUE(satelliteData.serverPredictionIsAvailable ||
|
||||
satelliteData.ephemerisType ==
|
||||
IGnssDebug::SatelliteEphemerisType::EPHEMERIS);
|
||||
// for satellites with ephType=0, they need ephHealth=0 if used-in-fix
|
||||
if (satelliteData.ephemerisType == IGnssDebug::SatelliteEphemerisType::EPHEMERIS) {
|
||||
EXPECT_TRUE(satelliteData.ephemerisHealth ==
|
||||
IGnssDebug::SatelliteEphemerisHealth::GOOD);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Every Satellite where GnssStatus says it is used-in-fix has a valid ephemeris - i.e. it's
|
||||
// it shows either a serverPredAvail: 1, or a ephType=0
|
||||
EXPECT_TRUE(foundDebugData);
|
||||
}
|
||||
|
||||
bool hasServerPredictionAvailable = false;
|
||||
bool hasNoneZeroServerPredictionAgeSeconds = false;
|
||||
bool hasNoneDemodEphSource = false;
|
||||
for (auto satelliteData : data.satelliteDataArray) {
|
||||
// for satellites with serverPredAvail: 1, the serverPredAgeSec: is not 0 for all
|
||||
// satellites (at least not on 2 fixes in a row - it could get lucky once)
|
||||
if (satelliteData.serverPredictionIsAvailable) {
|
||||
hasServerPredictionAvailable = true;
|
||||
if (satelliteData.serverPredictionAgeSeconds != 0) {
|
||||
hasNoneZeroServerPredictionAgeSeconds = true;
|
||||
}
|
||||
}
|
||||
// for satellites with ephType=0, they need ephSource 0-3
|
||||
if (satelliteData.ephemerisType == IGnssDebug::SatelliteEphemerisType::EPHEMERIS) {
|
||||
EXPECT_TRUE(satelliteData.ephemerisSource >=
|
||||
SatellitePvt::SatelliteEphemerisSource::DEMODULATED &&
|
||||
satelliteData.ephemerisSource <=
|
||||
SatellitePvt::SatelliteEphemerisSource::OTHER);
|
||||
if (satelliteData.ephemerisSource !=
|
||||
SatellitePvt::SatelliteEphemerisSource::DEMODULATED) {
|
||||
hasNoneDemodEphSource = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasNoneDemodEphSource && hasServerPredictionAvailable) {
|
||||
EXPECT_TRUE(hasNoneZeroServerPredictionAgeSeconds);
|
||||
}
|
||||
|
||||
/**
|
||||
- Gnss Location Data:: should show some valid information, ideally reasonably close (+/-1km) to
|
||||
the Location output - at least after the 2nd valid location output (maybe in general, wait
|
||||
for 2 good Location outputs before checking this, in case they don't update the assistance
|
||||
until after they output the Location)
|
||||
*/
|
||||
double distanceM =
|
||||
Utils::distanceMeters(data.position.latitudeDegrees, data.position.longitudeDegrees,
|
||||
aidl_gnss_cb_->last_location_.latitudeDegrees,
|
||||
aidl_gnss_cb_->last_location_.longitudeDegrees);
|
||||
ALOGD("distance between debug position and last position: %.2lf", distanceM);
|
||||
EXPECT_LT(distanceM, 1000.0); // 1km
|
||||
|
||||
/**
|
||||
- Gnss Time Data:: timeEstimate should be reasonably close to the current GPS time.
|
||||
- Gnss Time Data:: timeUncertaintyNs should always be > 0 and < 5e9 (could be large due
|
||||
to solve-for-time type solutions)
|
||||
- Gnss Time Data:: frequencyUncertaintyNsPerSec: should always be > 0 and < 1000 (1000 ns/s
|
||||
corresponds to roughly a 300 m/s speed error, which should be pretty rare)
|
||||
*/
|
||||
ALOGD("debug time: %" PRId64 ", position time: %" PRId64, data.time.timeEstimateMs,
|
||||
aidl_gnss_cb_->last_location_.timestampMillis);
|
||||
// Allowing 5s between the last location time and the current GPS time
|
||||
EXPECT_LT(abs(data.time.timeEstimateMs - aidl_gnss_cb_->last_location_.timestampMillis), 5000);
|
||||
|
||||
ALOGD("debug time uncertainty: %f ns", data.time.timeUncertaintyNs);
|
||||
EXPECT_GT(data.time.timeUncertaintyNs, 0);
|
||||
EXPECT_LT(data.time.timeUncertaintyNs, 5e9);
|
||||
|
||||
ALOGD("debug freq uncertainty: %f ns/s", data.time.frequencyUncertaintyNsPerSec);
|
||||
EXPECT_GT(data.time.frequencyUncertaintyNsPerSec, 0);
|
||||
EXPECT_LT(data.time.frequencyUncertaintyNsPerSec, 1000);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "gtest/gtest.h"
|
||||
|
||||
#include <cutils/properties.h>
|
||||
#include <math.h>
|
||||
#include <utils/SystemClock.h>
|
||||
|
||||
namespace android {
|
||||
|
@ -58,6 +59,31 @@ void Utils::checkLocationElapsedRealtime(const android::hardware::gnss::GnssLoca
|
|||
checkElapsedRealtime(location.elapsedRealtime);
|
||||
}
|
||||
|
||||
void Utils::checkPositionDebug(android::hardware::gnss::IGnssDebug::DebugData data) {
|
||||
if (data.position.valid) {
|
||||
ASSERT_TRUE(data.position.latitudeDegrees >= -90 && data.position.latitudeDegrees <= 90);
|
||||
ASSERT_TRUE(data.position.longitudeDegrees >= -180 &&
|
||||
data.position.longitudeDegrees <= 180);
|
||||
ASSERT_TRUE(data.position.altitudeMeters >= -1000 && // Dead Sea: -414m
|
||||
data.position.altitudeMeters <= 20000); // Mount Everest: 8850m
|
||||
ASSERT_TRUE(data.position.speedMetersPerSec >= 0 && data.position.speedMetersPerSec <= 600);
|
||||
ASSERT_TRUE(data.position.bearingDegrees >= -360 && data.position.bearingDegrees <= 360);
|
||||
ASSERT_TRUE(data.position.horizontalAccuracyMeters > 0 &&
|
||||
data.position.horizontalAccuracyMeters <= 20000000);
|
||||
ASSERT_TRUE(data.position.verticalAccuracyMeters > 0 &&
|
||||
data.position.verticalAccuracyMeters <= 20000);
|
||||
ASSERT_TRUE(data.position.speedAccuracyMetersPerSecond > 0 &&
|
||||
data.position.speedAccuracyMetersPerSecond <= 500);
|
||||
ASSERT_TRUE(data.position.bearingAccuracyDegrees > 0 &&
|
||||
data.position.bearingAccuracyDegrees <= 180);
|
||||
ASSERT_TRUE(data.position.ageSeconds >= 0);
|
||||
}
|
||||
ASSERT_TRUE(data.time.timeEstimateMs >= 1483228800000); // Jan 01 2017 00:00:00 GMT.
|
||||
ASSERT_TRUE(data.time.timeUncertaintyNs > 0);
|
||||
ASSERT_TRUE(data.time.frequencyUncertaintyNsPerSec > 0 &&
|
||||
data.time.frequencyUncertaintyNsPerSec <= 2.0e5); // 200 ppm
|
||||
}
|
||||
|
||||
void Utils::checkElapsedRealtime(const ElapsedRealtime& elapsedRealtime) {
|
||||
ASSERT_TRUE(elapsedRealtime.flags >= 0 &&
|
||||
elapsedRealtime.flags <= (ElapsedRealtime::HAS_TIMESTAMP_NS |
|
||||
|
@ -282,6 +308,17 @@ bool Utils::isAutomotiveDevice() {
|
|||
return strncmp(buffer, "automotive", PROPERTY_VALUE_MAX) == 0;
|
||||
}
|
||||
|
||||
double Utils::distanceMeters(double lat1, double lon1, double lat2, double lon2) {
|
||||
double R = 6378.137; // Radius of earth in KM
|
||||
double dLat = lat2 * M_PI / 180 - lat1 * M_PI / 180;
|
||||
double dLon = lon2 * M_PI / 180 - lon1 * M_PI / 180;
|
||||
double a = sin(dLat / 2) * sin(dLat / 2) +
|
||||
cos(lat1 * M_PI / 180) * cos(lat2 * M_PI / 180) * sin(dLon / 2) * sin(dLon / 2);
|
||||
double c = 2 * atan2(sqrt(a), sqrt(1 - a));
|
||||
double d = R * c;
|
||||
return d * 1000; // meters
|
||||
}
|
||||
|
||||
} // namespace common
|
||||
} // namespace gnss
|
||||
} // namespace hardware
|
||||
|
|
|
@ -43,6 +43,7 @@ struct Utils {
|
|||
|
||||
static void checkElapsedRealtime(
|
||||
const android::hardware::gnss::ElapsedRealtime& elapsedRealtime);
|
||||
static void checkPositionDebug(android::hardware::gnss::IGnssDebug::DebugData data);
|
||||
|
||||
static const android::hardware::gnss::GnssLocation getMockLocation(
|
||||
double latitudeDegrees, double longitudeDegrees, double horizontalAccuracyMeters);
|
||||
|
@ -57,6 +58,7 @@ struct Utils {
|
|||
V2_0::GnssConstellationType constellation);
|
||||
|
||||
static bool isAutomotiveDevice();
|
||||
static double distanceMeters(double lat1, double lon1, double lat2, double lon2);
|
||||
|
||||
private:
|
||||
template <class T>
|
||||
|
|
Loading…
Reference in a new issue