From be47920e9ff70fcf5b372c7cd149ba78a127554a Mon Sep 17 00:00:00 2001 From: Yuchen He Date: Thu, 13 Jan 2022 18:39:50 +0000 Subject: [PATCH 1/2] Add parser to support CSV location data Bug: 213225295 Test: launch_cvd -cpus 16 -memory_mb 16192 --start_gnss_proxy --gnss_file_path=/google/data/rw/users/yu/yuchenhe/input.txt (Running blue dot in Google Maps) Almost a cherry-pick but changed the data type from AIDL GnssLocation to the HIDL type, since there are no AIDL GnssLocation Type in SC-V2. Merged-In: I572315888c2f57ce701e695acb03aa6b28787f31 Change-Id: I572315888c2f57ce701e695acb03aa6b28787f31 --- gnss/common/utils/default/Android.bp | 1 + .../utils/default/FixLocationParser.cpp | 76 +++++++++++++++++++ .../utils/default/include/FixLocationParser.h | 47 ++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 gnss/common/utils/default/FixLocationParser.cpp create mode 100644 gnss/common/utils/default/include/FixLocationParser.h diff --git a/gnss/common/utils/default/Android.bp b/gnss/common/utils/default/Android.bp index ea445a276a..bdb1569105 100644 --- a/gnss/common/utils/default/Android.bp +++ b/gnss/common/utils/default/Android.bp @@ -39,6 +39,7 @@ cc_library_static { "v2_1/GnssMeasurement.cpp", "v2_1/GnssMeasurementCorrections.cpp", "DeviceFileReader.cpp", + "FixLocationParser.cpp", "GnssRawMeasurementParser.cpp", "GnssReplayUtils.cpp", "MockLocation.cpp", diff --git a/gnss/common/utils/default/FixLocationParser.cpp b/gnss/common/utils/default/FixLocationParser.cpp new file mode 100644 index 0000000000..f0177b49c5 --- /dev/null +++ b/gnss/common/utils/default/FixLocationParser.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "FixLocationParser.h" + +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace common { + +std::unique_ptr FixLocationParser::getLocationFromInputStr( + const std::string& locationStr) { + /* + * Fix,Provider,LatitudeDegrees,LongitudeDegrees,AltitudeMeters,SpeedMps, + * AccuracyMeters,BearingDegrees,UnixTimeMillis,SpeedAccuracyMps,BearingAccuracyDegrees, + * elapsedRealtimeNanos + */ + if (locationStr.empty()) { + return nullptr; + } + std::vector locationStrRecords; + ParseUtils::splitStr(locationStr, LINE_SEPARATOR, locationStrRecords); + if (locationStrRecords.empty()) { + return nullptr; + } + + std::vector locationValues; + ParseUtils::splitStr(locationStrRecords[0], COMMA_SEPARATOR, locationValues); + if (locationValues.size() < 12) { + return nullptr; + } + V2_0::ElapsedRealtime elapsedRealtime = { + .flags = V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS | + V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS, + .timestampNs = static_cast(::android::elapsedRealtimeNano()), + // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks. + // In an actual implementation provide an estimate of the synchronization uncertainty + // or don't set the field. + .timeUncertaintyNs = 1020400}; + + V1_0::GnssLocation locationV1 = { + .gnssLocationFlags = 0xFF, + .latitudeDegrees = ParseUtils::tryParseDouble(locationValues[2], 0), + .longitudeDegrees = ParseUtils::tryParseDouble(locationValues[3], 0), + .altitudeMeters = ParseUtils::tryParseDouble(locationValues[4], 0), + .speedMetersPerSec = ParseUtils::tryParsefloat(locationValues[5], 0), + .bearingDegrees = ParseUtils::tryParsefloat(locationValues[7], 0), + .horizontalAccuracyMeters = ParseUtils::tryParsefloat(locationValues[6], 0), + .verticalAccuracyMeters = ParseUtils::tryParsefloat(locationValues[6], 0), + .speedAccuracyMetersPerSecond = ParseUtils::tryParsefloat(locationValues[9], 0), + .bearingAccuracyDegrees = ParseUtils::tryParsefloat(locationValues[10], 0), + .timestamp = ParseUtils::tryParseLongLong(locationValues[8], 0)}; + + V2_0::GnssLocation locationV2 = {.v1_0 = locationV1, .elapsedRealtime = elapsedRealtime}; + return std::make_unique(locationV2); +} + +} // namespace common +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gnss/common/utils/default/include/FixLocationParser.h b/gnss/common/utils/default/include/FixLocationParser.h new file mode 100644 index 0000000000..19748a9dd1 --- /dev/null +++ b/gnss/common/utils/default/include/FixLocationParser.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_gnss_common_default_FixLocationParser_H_ +#define android_hardware_gnss_common_default_FixLocationParser_H_ + +#include + +#include +#include +#include + +#include +#include +#include +#include "Constants.h" +#include "ParseUtils.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace common { + +struct FixLocationParser { + public: + static std::unique_ptr getLocationFromInputStr(const std::string& inputStr); +}; + +} // namespace common +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // android_hardware_gnss_common_default_FixLocationParser_H_ From 55c22f897eafc6eb0177bc5e93cd8f86fa4dcd95 Mon Sep 17 00:00:00 2001 From: Yuchen He Date: Thu, 20 Jan 2022 22:57:09 +0000 Subject: [PATCH 2/2] Supported synchronized fixed location and measurement from device files Replace NMEA by one row fixed location data Test: atest VtsHalGnssTargetTest Test: launch_cvd -cpus 16 -memory_mb 16192 --start_gnss_proxy --gnss_file_path=/usr/local/google/home/yuchenhe/Downloads/raw.txt --fixed_location_file_path=/google/data/rw/users/yu/yuchenhe/input.txt Bug: 213225295 Merged-In: Ide7bbb3e81a90414496084691227bd95a2e7af18 Change-Id: Ide7bbb3e81a90414496084691227bd95a2e7af18 --- .../common/utils/default/DeviceFileReader.cpp | 22 ++++++++++++++----- gnss/common/utils/default/GnssReplayUtils.cpp | 13 +++++++++++ gnss/common/utils/default/include/Constants.h | 1 + .../utils/default/include/GnssReplayUtils.h | 4 ++++ .../utils/default/include/v2_1/GnssTemplate.h | 7 ++++-- 5 files changed, 40 insertions(+), 7 deletions(-) diff --git a/gnss/common/utils/default/DeviceFileReader.cpp b/gnss/common/utils/default/DeviceFileReader.cpp index 7d4fb04339..dfc086a8b8 100644 --- a/gnss/common/utils/default/DeviceFileReader.cpp +++ b/gnss/common/utils/default/DeviceFileReader.cpp @@ -22,8 +22,17 @@ namespace common { void DeviceFileReader::getDataFromDeviceFile(const std::string& command, int mMinIntervalMs) { char inputBuffer[INPUT_BUFFER_SIZE]; - int mGnssFd = open(ReplayUtils::getGnssPath().c_str(), - O_RDWR | O_NONBLOCK); + std::string deviceFilePath = ""; + if (command == CMD_GET_LOCATION) { + deviceFilePath = ReplayUtils::getFixedLocationPath(); + } else if (command == CMD_GET_RAWMEASUREMENT) { + deviceFilePath = ReplayUtils::getGnssPath(); + } else { + // Invalid command + return; + } + + int mGnssFd = open(deviceFilePath.c_str(), O_RDWR | O_NONBLOCK); if (mGnssFd == -1) { return; @@ -68,10 +77,13 @@ void DeviceFileReader::getDataFromDeviceFile(const std::string& command, int mMi } // Cache the injected data. - if (ReplayUtils::isGnssRawMeasurement(inputStr)) { - data_[CMD_GET_RAWMEASUREMENT] = inputStr; - } else if (ReplayUtils::isNMEA(inputStr)) { + if (command == CMD_GET_LOCATION) { + // TODO validate data data_[CMD_GET_LOCATION] = inputStr; + } else if (command == CMD_GET_RAWMEASUREMENT) { + if (ReplayUtils::isGnssRawMeasurement(inputStr)) { + data_[CMD_GET_RAWMEASUREMENT] = inputStr; + } } } diff --git a/gnss/common/utils/default/GnssReplayUtils.cpp b/gnss/common/utils/default/GnssReplayUtils.cpp index e3f4ff82a0..b27943e6ed 100644 --- a/gnss/common/utils/default/GnssReplayUtils.cpp +++ b/gnss/common/utils/default/GnssReplayUtils.cpp @@ -29,11 +29,24 @@ std::string ReplayUtils::getGnssPath() { return GNSS_PATH; } +std::string ReplayUtils::getFixedLocationPath() { + char devname_value[PROPERTY_VALUE_MAX] = ""; + if (property_get("debug.location.fixedlocation.devname", devname_value, NULL) > 0) { + return devname_value; + } + return FIXED_LOCATION_PATH; +} + bool ReplayUtils::hasGnssDeviceFile() { struct stat sb; return stat(getGnssPath().c_str(), &sb) != -1; } +bool ReplayUtils::hasFixedLocationDeviceFile() { + struct stat sb; + return stat(getFixedLocationPath().c_str(), &sb) != -1; +} + bool ReplayUtils::isGnssRawMeasurement(const std::string& inputStr) { // TODO: add more logic check to by pass invalid data. return !inputStr.empty() && (inputStr.find("Raw") != std::string::npos); diff --git a/gnss/common/utils/default/include/Constants.h b/gnss/common/utils/default/include/Constants.h index f205ba603c..489413e21d 100644 --- a/gnss/common/utils/default/include/Constants.h +++ b/gnss/common/utils/default/include/Constants.h @@ -36,6 +36,7 @@ const float kIrnssL5FreqHz = 1176.45 * 1e6; // Location replay constants constexpr char GNSS_PATH[] = "/dev/gnss0"; +constexpr char FIXED_LOCATION_PATH[] = "/dev/gnss1"; constexpr int INPUT_BUFFER_SIZE = 256; constexpr char CMD_GET_LOCATION[] = "CMD_GET_LOCATION"; constexpr char CMD_GET_RAWMEASUREMENT[] = "CMD_GET_RAWMEASUREMENT"; diff --git a/gnss/common/utils/default/include/GnssReplayUtils.h b/gnss/common/utils/default/include/GnssReplayUtils.h index 32c0e58c0c..d1bbed4b41 100644 --- a/gnss/common/utils/default/include/GnssReplayUtils.h +++ b/gnss/common/utils/default/include/GnssReplayUtils.h @@ -37,10 +37,14 @@ namespace common { struct ReplayUtils { static std::string getGnssPath(); + static std::string getFixedLocationPath(); + static std::string getDataFromDeviceFile(const std::string& command, int mMinIntervalMs); static bool hasGnssDeviceFile(); + static bool hasFixedLocationDeviceFile(); + static bool isGnssRawMeasurement(const std::string& inputStr); static bool isNMEA(const std::string& inputStr); diff --git a/gnss/common/utils/default/include/v2_1/GnssTemplate.h b/gnss/common/utils/default/include/v2_1/GnssTemplate.h index fbf04b3c41..473e587762 100644 --- a/gnss/common/utils/default/include/v2_1/GnssTemplate.h +++ b/gnss/common/utils/default/include/v2_1/GnssTemplate.h @@ -31,6 +31,7 @@ #include #include "DeviceFileReader.h" +#include "FixLocationParser.h" #include "GnssAntennaInfo.h" #include "GnssConfiguration.h" #include "GnssDebug.h" @@ -38,7 +39,6 @@ #include "GnssMeasurementCorrections.h" #include "GnssReplayUtils.h" #include "MockLocation.h" -#include "NmeaFixInfo.h" #include "Utils.h" namespace android::hardware::gnss::common::implementation { @@ -162,9 +162,12 @@ GnssTemplate::~GnssTemplate() { template std::unique_ptr GnssTemplate::getLocationFromHW() { mHardwareModeChecked = true; + if (!ReplayUtils::hasFixedLocationDeviceFile()) { + return nullptr; + } std::string inputStr = ::android::hardware::gnss::common::DeviceFileReader::Instance().getLocationData(); - return NmeaFixInfo::getLocationFromInputStr(inputStr); + return FixLocationParser::getLocationFromInputStr(inputStr); } template