Merge Android 12 QPR3 ab/8391262

Bug: 226662282
Merged-In: I6a50f6d5abc485cb4fb38df7383a5cc83ad20a86
Change-Id: I2c341bf993066cbfa416fed868dd889577fa67d1
This commit is contained in:
Xin Li
2022-04-01 20:32:38 +00:00
15 changed files with 1007 additions and 57 deletions

View File

@@ -19,11 +19,17 @@
#include "GnssMeasurementInterface.h"
#include <aidl/android/hardware/gnss/BnGnss.h>
#include <log/log.h>
#include "DeviceFileReader.h"
#include "GnssRawMeasurementParser.h"
#include "GnssReplayUtils.h"
#include "Utils.h"
namespace aidl::android::hardware::gnss {
using Utils = ::android::hardware::gnss::common::Utils;
using ReplayUtils = ::android::hardware::gnss::common::ReplayUtils;
using GnssRawMeasurementParser = ::android::hardware::gnss::common::GnssRawMeasurementParser;
using DeviceFileReader = ::android::hardware::gnss::common::DeviceFileReader;
std::shared_ptr<IGnssMeasurementCallback> GnssMeasurementInterface::sCallback = nullptr;
@@ -63,9 +69,22 @@ void GnssMeasurementInterface::start(const bool enableCorrVecOutputs) {
mIsActive = true;
mThread = std::thread([this, enableCorrVecOutputs]() {
while (mIsActive == true) {
auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs);
this->reportMeasurement(measurement);
std::string rawMeasurementStr = "";
if (ReplayUtils::hasGnssDeviceFile() &&
ReplayUtils::isGnssRawMeasurement(
rawMeasurementStr =
DeviceFileReader::Instance().getGnssRawMeasurementData())) {
ALOGD("rawMeasurementStr(size: %zu) from device file: %s", rawMeasurementStr.size(),
rawMeasurementStr.c_str());
auto measurement =
GnssRawMeasurementParser::getMeasurementFromStrs(rawMeasurementStr);
if (measurement != nullptr) {
this->reportMeasurement(*measurement);
}
} else {
auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs);
this->reportMeasurement(measurement);
}
std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis));
}
});

View File

@@ -38,9 +38,14 @@ cc_library_static {
"v2_1/GnssDebug.cpp",
"v2_1/GnssMeasurement.cpp",
"v2_1/GnssMeasurementCorrections.cpp",
"DeviceFileReader.cpp",
"FixLocationParser.cpp",
"GnssRawMeasurementParser.cpp",
"GnssReplayUtils.cpp",
"MockLocation.cpp",
"Utils.cpp",
"NmeaFixInfo.cpp",
"ParseUtils.cpp",
"Utils.cpp",
],
export_include_dirs: ["include"],
shared_libs: [

View File

@@ -0,0 +1,109 @@
/*
* Copyright (C) 2021 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 "DeviceFileReader.h"
namespace android {
namespace hardware {
namespace gnss {
namespace common {
void DeviceFileReader::getDataFromDeviceFile(const std::string& command, int mMinIntervalMs) {
char inputBuffer[INPUT_BUFFER_SIZE];
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;
}
int bytes_write = write(mGnssFd, command.c_str(), command.size());
if (bytes_write <= 0) {
close(mGnssFd);
return;
}
struct epoll_event ev, events[1];
ev.data.fd = mGnssFd;
ev.events = EPOLLIN;
int epoll_fd = epoll_create1(0);
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, mGnssFd, &ev);
int bytes_read = -1;
std::string inputStr = "";
int epoll_ret = epoll_wait(epoll_fd, events, 1, mMinIntervalMs);
if (epoll_ret == -1) {
close(mGnssFd);
return;
}
while (true) {
memset(inputBuffer, 0, INPUT_BUFFER_SIZE);
bytes_read = read(mGnssFd, &inputBuffer, INPUT_BUFFER_SIZE);
if (bytes_read <= 0) {
break;
}
s_buffer_ += std::string(inputBuffer, bytes_read);
}
close(mGnssFd);
// Trim end of file mark(\n\n\n\n).
auto pos = s_buffer_.find("\n\n\n\n");
if (pos != std::string::npos) {
inputStr = s_buffer_.substr(0, pos);
s_buffer_ = s_buffer_.substr(pos + 4);
} else {
return;
}
// Cache the injected data.
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;
}
}
}
std::string DeviceFileReader::getLocationData() {
std::unique_lock<std::mutex> lock(mMutex);
getDataFromDeviceFile(CMD_GET_LOCATION, 20);
return data_[CMD_GET_LOCATION];
}
std::string DeviceFileReader::getGnssRawMeasurementData() {
std::unique_lock<std::mutex> lock(mMutex);
getDataFromDeviceFile(CMD_GET_RAWMEASUREMENT, 20);
return data_[CMD_GET_RAWMEASUREMENT];
}
DeviceFileReader::DeviceFileReader() {}
DeviceFileReader::~DeviceFileReader() {}
} // namespace common
} // namespace gnss
} // namespace hardware
} // namespace android

View File

@@ -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 <android/hardware/gnss/1.0/IGnss.h>
namespace android {
namespace hardware {
namespace gnss {
namespace common {
std::unique_ptr<V2_0::GnssLocation> 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<std::string> locationStrRecords;
ParseUtils::splitStr(locationStr, LINE_SEPARATOR, locationStrRecords);
if (locationStrRecords.empty()) {
return nullptr;
}
std::vector<std::string> 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<uint64_t>(::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<V2_0::GnssLocation>(locationV2);
}
} // namespace common
} // namespace gnss
} // namespace hardware
} // namespace android

View File

@@ -0,0 +1,305 @@
/*
* Copyright (C) 2021 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 "GnssRawMeasurementParser.h"
namespace android {
namespace hardware {
namespace gnss {
namespace common {
using aidl::android::hardware::gnss::ElapsedRealtime;
using aidl::android::hardware::gnss::GnssClock;
using aidl::android::hardware::gnss::GnssConstellationType;
using aidl::android::hardware::gnss::GnssData;
using aidl::android::hardware::gnss::GnssMeasurement;
using aidl::android::hardware::gnss::GnssMultipathIndicator;
using aidl::android::hardware::gnss::GnssSignalType;
using ParseUtils = ::android::hardware::gnss::common::ParseUtils;
std::unordered_map<std::string, int> GnssRawMeasurementParser::getColumnIdNameMappingFromHeader(
const std::string& header) {
std::vector<std::string> columnNames;
std::unordered_map<std::string, int> columnNameIdMapping;
std::string s = header;
// Trim left spaces
s.erase(s.begin(),
std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); }));
// Trim right spaces
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); })
.base(),
s.end());
// Remove comment symbol, start from `Raw`.
s = s.substr(s.find("Raw"));
ParseUtils::splitStr(s, COMMA_SEPARATOR, columnNames);
int columnId = 0;
for (auto& name : columnNames) {
columnNameIdMapping[name] = columnId++;
}
return columnNameIdMapping;
}
int GnssRawMeasurementParser::getClockFlags(
const std::vector<std::string>& rawMeasurementRecordValues,
const std::unordered_map<std::string, int>& columnNameIdMapping) {
int clockFlags = 0;
if (!rawMeasurementRecordValues[columnNameIdMapping.at("LeapSecond")].empty()) {
clockFlags |= GnssClock::HAS_LEAP_SECOND;
}
if (!rawMeasurementRecordValues[columnNameIdMapping.at("FullBiasNanos")].empty()) {
clockFlags |= GnssClock::HAS_FULL_BIAS;
}
if (!rawMeasurementRecordValues[columnNameIdMapping.at("BiasNanos")].empty()) {
clockFlags |= GnssClock::HAS_BIAS;
}
if (!rawMeasurementRecordValues[columnNameIdMapping.at("BiasUncertaintyNanos")].empty()) {
clockFlags |= GnssClock::HAS_BIAS_UNCERTAINTY;
}
if (!rawMeasurementRecordValues[columnNameIdMapping.at("DriftNanosPerSecond")].empty()) {
clockFlags |= GnssClock::HAS_DRIFT;
}
if (!rawMeasurementRecordValues[columnNameIdMapping.at("DriftUncertaintyNanosPerSecond")]
.empty()) {
clockFlags |= GnssClock::HAS_DRIFT_UNCERTAINTY;
}
return clockFlags;
}
int GnssRawMeasurementParser::getElapsedRealtimeFlags(
const std::vector<std::string>& rawMeasurementRecordValues,
const std::unordered_map<std::string, int>& columnNameIdMapping) {
int elapsedRealtimeFlags = ElapsedRealtime::HAS_TIMESTAMP_NS;
if (!rawMeasurementRecordValues[columnNameIdMapping.at("TimeUncertaintyNanos")].empty()) {
elapsedRealtimeFlags |= ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS;
}
return elapsedRealtimeFlags;
}
int GnssRawMeasurementParser::getRawMeasurementFlags(
const std::vector<std::string>& rawMeasurementRecordValues,
const std::unordered_map<std::string, int>& columnNameIdMapping) {
int rawMeasurementFlags = 0;
if (!rawMeasurementRecordValues[columnNameIdMapping.at("SnrInDb")].empty()) {
rawMeasurementFlags |= GnssMeasurement::HAS_SNR;
}
if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierFrequencyHz")].empty()) {
rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_FREQUENCY;
}
if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierCycles")].empty()) {
rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_CYCLES;
}
if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierPhase")].empty()) {
rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_PHASE;
}
if (!rawMeasurementRecordValues[columnNameIdMapping.at("CarrierPhaseUncertainty")].empty()) {
rawMeasurementFlags |= GnssMeasurement::HAS_CARRIER_PHASE_UNCERTAINTY;
}
if (!rawMeasurementRecordValues[columnNameIdMapping.at("AgcDb")].empty()) {
rawMeasurementFlags |= GnssMeasurement::HAS_AUTOMATIC_GAIN_CONTROL;
}
if (!rawMeasurementRecordValues[columnNameIdMapping.at("FullInterSignalBiasNanos")].empty()) {
rawMeasurementFlags |= GnssMeasurement::HAS_FULL_ISB;
}
if (!rawMeasurementRecordValues[columnNameIdMapping.at("FullInterSignalBiasUncertaintyNanos")]
.empty()) {
rawMeasurementFlags |= GnssMeasurement::HAS_FULL_ISB_UNCERTAINTY;
}
if (!rawMeasurementRecordValues[columnNameIdMapping.at("SatelliteInterSignalBiasNanos")]
.empty()) {
rawMeasurementFlags |= GnssMeasurement::HAS_SATELLITE_ISB;
}
if (!rawMeasurementRecordValues[columnNameIdMapping.at(
"SatelliteInterSignalBiasUncertaintyNanos")]
.empty()) {
rawMeasurementFlags |= GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY;
}
// HAS_SATELLITE_PVT and HAS_CORRELATION_VECTOR fields currently not in rawmeasurement
// output, need add them later.
return rawMeasurementFlags;
}
GnssConstellationType GnssRawMeasurementParser::getGnssConstellationType(int constellationType) {
GnssConstellationType gnssConstellationType =
aidl::android::hardware::gnss::GnssConstellationType::UNKNOWN;
switch (constellationType) {
case 1:
gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::GPS;
break;
case 2:
gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::SBAS;
break;
case 3:
gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::GLONASS;
break;
case 4:
gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::QZSS;
break;
case 5:
gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::BEIDOU;
break;
case 6:
gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::GALILEO;
break;
default:
gnssConstellationType = aidl::android::hardware::gnss::GnssConstellationType::UNKNOWN;
}
return gnssConstellationType;
}
std::unique_ptr<GnssData> GnssRawMeasurementParser::getMeasurementFromStrs(
std::string& rawMeasurementStr) {
/*
* Raw,utcTimeMillis,TimeNanos,LeapSecond,TimeUncertaintyNanos,FullBiasNanos,BiasNanos,
* BiasUncertaintyNanos,DriftNanosPerSecond,DriftUncertaintyNanosPerSecond,
* HardwareClockDiscontinuityCount,Svid,TimeOffsetNanos,State,ReceivedSvTimeNanos,
* ReceivedSvTimeUncertaintyNanos,Cn0DbHz,PseudorangeRateMetersPerSecond,
* PseudorangeRateUncertaintyMetersPerSecond,AccumulatedDeltaRangeState,
* AccumulatedDeltaRangeMeters,AccumulatedDeltaRangeUncertaintyMeters,CarrierFrequencyHz,
* CarrierCycles,CarrierPhase,CarrierPhaseUncertainty,MultipathIndicator,SnrInDb,
* ConstellationType,AgcDb,BasebandCn0DbHz,FullInterSignalBiasNanos,
* FullInterSignalBiasUncertaintyNanos,SatelliteInterSignalBiasNanos,
* SatelliteInterSignalBiasUncertaintyNanos,CodeType,ChipsetElapsedRealtimeNanos
*/
ALOGD("Parsing %zu bytes rawMeasurementStr.", rawMeasurementStr.size());
if (rawMeasurementStr.empty()) {
return nullptr;
}
std::vector<std::string> rawMeasurementStrRecords;
ParseUtils::splitStr(rawMeasurementStr, LINE_SEPARATOR, rawMeasurementStrRecords);
if (rawMeasurementStrRecords.size() <= 1) {
ALOGE("Raw GNSS Measurements parser failed. (No records) ");
return nullptr;
}
// Get the column name mapping from the header.
std::unordered_map<std::string, int> columnNameIdMapping =
getColumnIdNameMappingFromHeader(rawMeasurementStrRecords[0]);
if (columnNameIdMapping.size() < 37 || !ParseUtils::isValidHeader(columnNameIdMapping)) {
ALOGE("Raw GNSS Measurements parser failed. (No header or missing columns.) ");
return nullptr;
}
// Set GnssClock from 1st record.
std::size_t pointer = 1;
std::vector<std::string> firstRecordValues;
ParseUtils::splitStr(rawMeasurementStrRecords[pointer], COMMA_SEPARATOR, firstRecordValues);
GnssClock clock = {
.gnssClockFlags = getClockFlags(firstRecordValues, columnNameIdMapping),
.timeNs = ParseUtils::tryParseLongLong(
firstRecordValues[columnNameIdMapping.at("TimeNanos")], 0),
.fullBiasNs = ParseUtils::tryParseLongLong(
firstRecordValues[columnNameIdMapping.at("FullBiasNanos")], 0),
.biasNs = ParseUtils::tryParseDouble(
firstRecordValues[columnNameIdMapping.at("BiasNanos")], 0),
.biasUncertaintyNs = ParseUtils::tryParseDouble(
firstRecordValues[columnNameIdMapping.at("BiasUncertaintyNanos")], 0),
.driftNsps = ParseUtils::tryParseDouble(
firstRecordValues[columnNameIdMapping.at("DriftNanosPerSecond")], 0),
.driftUncertaintyNsps = ParseUtils::tryParseDouble(
firstRecordValues[columnNameIdMapping.at("DriftNanosPerSecond")], 0),
.hwClockDiscontinuityCount = ParseUtils::tryParseInt(
firstRecordValues[columnNameIdMapping.at("HardwareClockDiscontinuityCount")],
0)};
ElapsedRealtime timestamp = {
.flags = getElapsedRealtimeFlags(firstRecordValues, columnNameIdMapping),
.timestampNs = ParseUtils::tryParseLongLong(
firstRecordValues[columnNameIdMapping.at("ChipsetElapsedRealtimeNanos")]),
.timeUncertaintyNs = ParseUtils::tryParseDouble(
firstRecordValues[columnNameIdMapping.at("TimeUncertaintyNanos")], 0)};
std::vector<GnssMeasurement> measurementsVec;
for (pointer = 1; pointer < rawMeasurementStrRecords.size(); pointer++) {
std::vector<std::string> rawMeasurementValues;
std::string line = rawMeasurementStrRecords[pointer];
ParseUtils::splitStr(line, COMMA_SEPARATOR, rawMeasurementValues);
GnssSignalType signalType = {
.constellation = getGnssConstellationType(ParseUtils::tryParseInt(
rawMeasurementValues[columnNameIdMapping.at("ConstellationType")], 0)),
.carrierFrequencyHz = ParseUtils::tryParseDouble(
rawMeasurementValues[columnNameIdMapping.at("CarrierFrequencyHz")], 0),
.codeType = rawMeasurementValues[columnNameIdMapping.at("CodeType")],
};
GnssMeasurement measurement = {
.flags = getRawMeasurementFlags(rawMeasurementValues, columnNameIdMapping),
.svid = ParseUtils::tryParseInt(
rawMeasurementValues[columnNameIdMapping.at("Svid")], 0),
.signalType = signalType,
.receivedSvTimeInNs = ParseUtils::tryParseLongLong(
rawMeasurementValues[columnNameIdMapping.at("ReceivedSvTimeNanos")], 0),
.receivedSvTimeUncertaintyInNs =
ParseUtils::tryParseLongLong(rawMeasurementValues[columnNameIdMapping.at(
"ReceivedSvTimeUncertaintyNanos")],
0),
.antennaCN0DbHz = ParseUtils::tryParseDouble(
rawMeasurementValues[columnNameIdMapping.at("Cn0DbHz")], 0),
.basebandCN0DbHz = ParseUtils::tryParseDouble(
rawMeasurementValues[columnNameIdMapping.at("BasebandCn0DbHz")], 0),
.agcLevelDb = ParseUtils::tryParseDouble(
rawMeasurementValues[columnNameIdMapping.at("AgcDb")], 0),
.pseudorangeRateMps =
ParseUtils::tryParseDouble(rawMeasurementValues[columnNameIdMapping.at(
"PseudorangeRateMetersPerSecond")],
0),
.pseudorangeRateUncertaintyMps = ParseUtils::tryParseDouble(
rawMeasurementValues[columnNameIdMapping.at(
"PseudorangeRateUncertaintyMetersPerSecond")],
0),
.accumulatedDeltaRangeState = ParseUtils::tryParseInt(
rawMeasurementValues[columnNameIdMapping.at("AccumulatedDeltaRangeState")],
0),
.accumulatedDeltaRangeM = ParseUtils::tryParseDouble(
rawMeasurementValues[columnNameIdMapping.at("AccumulatedDeltaRangeMeters")],
0),
.accumulatedDeltaRangeUncertaintyM = ParseUtils::tryParseDouble(
rawMeasurementValues[columnNameIdMapping.at(
"AccumulatedDeltaRangeUncertaintyMeters")],
0),
.multipathIndicator = GnssMultipathIndicator::UNKNOWN, // Not in GnssLogger yet.
.state = ParseUtils::tryParseInt(
rawMeasurementValues[columnNameIdMapping.at("State")], 0),
.fullInterSignalBiasNs = ParseUtils::tryParseDouble(rawMeasurementValues[31], 0),
.fullInterSignalBiasUncertaintyNs = ParseUtils::tryParseDouble(
rawMeasurementValues[columnNameIdMapping.at("FullInterSignalBiasNanos")],
0),
.satelliteInterSignalBiasNs =
ParseUtils::tryParseDouble(rawMeasurementValues[columnNameIdMapping.at(
"SatelliteInterSignalBiasNanos")],
0),
.satelliteInterSignalBiasUncertaintyNs = ParseUtils::tryParseDouble(
rawMeasurementValues[columnNameIdMapping.at(
"SatelliteInterSignalBiasUncertaintyNanos")],
0),
.satellitePvt = {},
.correlationVectors = {}};
measurementsVec.push_back(measurement);
}
GnssData gnssData = {
.measurements = measurementsVec, .clock = clock, .elapsedRealtime = timestamp};
return std::make_unique<GnssData>(gnssData);
}
} // namespace common
} // namespace gnss
} // namespace hardware
} // namespace android

View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2021 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 "GnssReplayUtils.h"
#include <array>
namespace android {
namespace hardware {
namespace gnss {
namespace common {
std::string ReplayUtils::getGnssPath() {
std::array<char, PROPERTY_VALUE_MAX> devname_value;
devname_value.fill(0);
if (property_get("debug.location.gnss.devname", devname_value.begin(), NULL) > 0) {
return devname_value.begin();
}
devname_value.fill(0);
if (property_get("vendor.ser.gnss-uart", devname_value.begin(), NULL) > 0) {
return devname_value.begin();
}
return GNSS_PATH;
}
std::string ReplayUtils::getFixedLocationPath() {
std::array<char, PROPERTY_VALUE_MAX> devname_value;
devname_value.fill(0);
if (property_get("debug.location.fixedlocation.devname", devname_value.begin(), NULL) > 0) {
return devname_value.begin();
}
devname_value.fill(0);
if (property_get("vendor.ser.gnss-uart", devname_value.begin(), NULL) > 0) {
return devname_value.begin();
}
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);
}
bool ReplayUtils::isNMEA(const std::string& inputStr) {
return !inputStr.empty() && (inputStr.find("$GPRMC,", 0) != std::string::npos ||
inputStr.find("$GPRMA,", 0) != std::string::npos);
}
} // namespace common
} // namespace gnss
} // namespace hardware
} // namespace android

View File

@@ -0,0 +1,127 @@
/*
* Copyright (C) 2021 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 <ParseUtils.h>
#include <sstream>
#include <stdexcept>
namespace android {
namespace hardware {
namespace gnss {
namespace common {
int ParseUtils::tryParseInt(const std::string& s, int defaultVal) {
if (s.empty()) {
return defaultVal;
} else {
return std::stoi(s);
}
}
float ParseUtils::tryParsefloat(const std::string& s, float defaultVal) {
if (s.empty()) {
return defaultVal;
} else {
return std::stof(s);
}
}
double ParseUtils::tryParseDouble(const std::string& s, double defaultVal) {
if (s.empty()) {
return defaultVal;
} else {
return std::stod(s);
}
}
long ParseUtils::tryParseLong(const std::string& s, long defaultVal) {
if (s.empty()) {
return defaultVal;
} else {
return std::stol(s);
}
}
long long ParseUtils::tryParseLongLong(const std::string& s, long long defaultVal) {
if (s.empty()) {
return defaultVal;
} else {
return std::stoll(s);
}
}
void ParseUtils::splitStr(const std::string& line, const char& delimiter,
std::vector<std::string>& out) {
std::istringstream iss(line);
std::string item;
while (std::getline(iss, item, delimiter)) {
out.push_back(item);
}
}
bool ParseUtils::isValidHeader(const std::unordered_map<std::string, int>& columnNameIdMapping) {
std::vector<std::string> requiredHeaderColumns = {"Raw",
"utcTimeMillis",
"TimeNanos",
"LeapSecond",
"TimeUncertaintyNanos",
"FullBiasNanos",
"BiasNanos",
"BiasUncertaintyNanos",
"DriftNanosPerSecond",
"DriftUncertaintyNanosPerSecond",
"HardwareClockDiscontinuityCount",
"Svid",
"TimeOffsetNanos",
"State",
"ReceivedSvTimeNanos",
"ReceivedSvTimeUncertaintyNanos",
"Cn0DbHz",
"PseudorangeRateMetersPerSecond",
"PseudorangeRateUncertaintyMetersPerSecond",
"AccumulatedDeltaRangeState",
"AccumulatedDeltaRangeMeters",
"AccumulatedDeltaRangeUncertaintyMeters",
"CarrierFrequencyHz",
"CarrierCycles",
"CarrierPhase",
"CarrierPhaseUncertainty",
"MultipathIndicator",
"SnrInDb",
"ConstellationType",
"AgcDb",
"BasebandCn0DbHz",
"FullInterSignalBiasNanos",
"FullInterSignalBiasUncertaintyNanos",
"SatelliteInterSignalBiasNanos",
"SatelliteInterSignalBiasUncertaintyNanos",
"CodeType",
"ChipsetElapsedRealtimeNanos"};
for (const auto& columnName : requiredHeaderColumns) {
if (columnNameIdMapping.find(columnName) == columnNameIdMapping.end()) {
ALOGE("Missing column %s in header.", columnName.c_str());
return false;
}
}
return true;
}
} // namespace common
} // namespace gnss
} // namespace hardware
} // namespace android

View File

@@ -34,6 +34,19 @@ const float kGpsL5FreqHz = 1176.45 * 1e6;
const float kGloG1FreqHz = 1602.0 * 1e6;
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";
constexpr char LINE_SEPARATOR = '\n';
constexpr char COMMA_SEPARATOR = ',';
constexpr char GPGA_RECORD_TAG[] = "$GPGGA";
constexpr char GPRMC_RECORD_TAG[] = "$GPRMC";
constexpr double TIMESTAMP_EPSILON = 0.001;
constexpr int MIN_COL_NUM = 13;
} // namespace common
} // namespace gnss
} // namespace hardware

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2021 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_DeviceFileReader_H_
#define android_hardware_gnss_common_default_DeviceFileReader_H_
#include <log/log.h>
#include <mutex>
#include <string>
#include <unordered_map>
#include "Constants.h"
#include "GnssReplayUtils.h"
namespace android {
namespace hardware {
namespace gnss {
namespace common {
class DeviceFileReader {
public:
static DeviceFileReader& Instance() {
static DeviceFileReader reader;
return reader;
}
std::string getLocationData();
std::string getGnssRawMeasurementData();
void getDataFromDeviceFile(const std::string& command, int mMinIntervalMs);
private:
DeviceFileReader();
~DeviceFileReader();
std::unordered_map<std::string, std::string> data_;
std::string s_buffer_;
std::mutex mMutex;
};
} // namespace common
} // namespace gnss
} // namespace hardware
} // namespace android
#endif // android_hardware_gnss_common_default_DeviceFileReader_H_

View File

@@ -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 <android/hardware/gnss/2.0/IGnss.h>
#include <utils/SystemClock.h>
#include <string>
#include <vector>
#include <Constants.h>
#include <Utils.h>
#include <log/log.h>
#include "Constants.h"
#include "ParseUtils.h"
namespace android {
namespace hardware {
namespace gnss {
namespace common {
struct FixLocationParser {
public:
static std::unique_ptr<V2_0::GnssLocation> getLocationFromInputStr(const std::string& inputStr);
};
} // namespace common
} // namespace gnss
} // namespace hardware
} // namespace android
#endif // android_hardware_gnss_common_default_FixLocationParser_H_

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2021 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_GnssRawMeasurementParser_H_
#define android_hardware_gnss_common_default_GnssRawMeasurementParser_H_
#include <aidl/android/hardware/gnss/BnGnss.h>
#include <log/log.h>
#include <utils/SystemClock.h>
#include <string>
#include <unordered_map>
#include "Constants.h"
#include "ParseUtils.h"
namespace android {
namespace hardware {
namespace gnss {
namespace common {
struct GnssRawMeasurementParser {
static std::unique_ptr<aidl::android::hardware::gnss::GnssData> getMeasurementFromStrs(
std::string& rawMeasurementStr);
static int getClockFlags(const std::vector<std::string>& rawMeasurementRecordValues,
const std::unordered_map<std::string, int>& columnNameIdMapping);
static int getElapsedRealtimeFlags(
const std::vector<std::string>& rawMeasurementRecordValues,
const std::unordered_map<std::string, int>& columnNameIdMapping);
static int getRawMeasurementFlags(
const std::vector<std::string>& rawMeasurementRecordValues,
const std::unordered_map<std::string, int>& columnNameIdMapping);
static std::unordered_map<std::string, int> getColumnIdNameMappingFromHeader(
const std::string& header);
static aidl::android::hardware::gnss::GnssConstellationType getGnssConstellationType(
int constellationType);
};
} // namespace common
} // namespace gnss
} // namespace hardware
} // namespace android
#endif // android_hardware_gnss_common_default_GnssRawMeasurementParser_H_

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2021 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_GnssReplayUtils_H_
#define android_hardware_gnss_common_GnssReplayUtils_H_
#include <cutils/properties.h>
#include <errno.h>
#include <fcntl.h>
#include <log/log.h>
#include <sys/epoll.h>
#include <sys/stat.h>
#include <chrono>
#include <string>
#include <thread>
#include "Constants.h"
namespace android {
namespace hardware {
namespace gnss {
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);
};
} // namespace common
} // namespace gnss
} // namespace hardware
} // namespace android
#endif // android_hardware_gnss_common_GnssReplayUtils_H_

View File

@@ -27,13 +27,6 @@ namespace hardware {
namespace gnss {
namespace common {
constexpr char GPGA_RECORD_TAG[] = "$GPGGA";
constexpr char GPRMC_RECORD_TAG[] = "$GPRMC";
constexpr char LINE_SEPARATOR = '\n';
constexpr char COMMA_SEPARATOR = ',';
constexpr double TIMESTAMP_EPSILON = 0.001;
constexpr int MIN_COL_NUM = 13;
/** Helper class to parse and store the GNSS fix details information. */
class NmeaFixInfo {
private:

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2021 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_ParseUtils_H_
#define android_hardware_gnss_common_default_ParseUtils_H_
#include <log/log.h>
#include <string>
#include <unordered_map>
#include <vector>
namespace android {
namespace hardware {
namespace gnss {
namespace common {
struct ParseUtils {
static int tryParseInt(const std::string& s, int defaultVal = 0);
static float tryParsefloat(const std::string& s, float defaultVal = 0.0);
static double tryParseDouble(const std::string& s, double defaultVal = 0.0);
static long tryParseLong(const std::string& s, long defaultVal = 0);
static long long tryParseLongLong(const std::string& s, long long defaultVal = 0);
static void splitStr(const std::string& line, const char& delimiter,
std::vector<std::string>& out);
static bool isValidHeader(const std::unordered_map<std::string, int>& columnNameIdMapping);
};
} // namespace common
} // namespace gnss
} // namespace hardware
} // namespace android
#endif // android_hardware_gnss_common_default_ParseUtils_H_

View File

@@ -30,13 +30,15 @@
#include <cutils/properties.h>
#include "DeviceFileReader.h"
#include "FixLocationParser.h"
#include "GnssAntennaInfo.h"
#include "GnssConfiguration.h"
#include "GnssDebug.h"
#include "GnssMeasurement.h"
#include "GnssMeasurementCorrections.h"
#include "GnssReplayUtils.h"
#include "MockLocation.h"
#include "NmeaFixInfo.h"
#include "Utils.h"
namespace android::hardware::gnss::common::implementation {
@@ -159,53 +161,13 @@ GnssTemplate<T_IGnss>::~GnssTemplate() {
template <class T_IGnss>
std::unique_ptr<V2_0::GnssLocation> GnssTemplate<T_IGnss>::getLocationFromHW() {
char inputBuffer[INPUT_BUFFER_SIZE];
if (!mHardwareModeChecked) {
// default using gnss0
const char * gnss_dev_path = GNSS_PATH;
char devname_value[PROPERTY_VALUE_MAX] = "";
if (property_get("debug.location.gnss.devname", devname_value, NULL) > 0) {
gnss_dev_path = devname_value;
ALOGD("using %s instead of the default %s", gnss_dev_path, GNSS_PATH);
}
mGnssFd = open(gnss_dev_path, O_RDWR | O_NONBLOCK);
if (mGnssFd == -1) {
ALOGW("Failed to open %s errno: %d", gnss_dev_path, errno);
}
mHardwareModeChecked = true;
}
if (mGnssFd == -1) {
mHardwareModeChecked = true;
if (!ReplayUtils::hasFixedLocationDeviceFile()) {
return nullptr;
}
int bytes_write = write(mGnssFd, CMD_GET_LOCATION, strlen(CMD_GET_LOCATION));
if (bytes_write <= 0) {
return nullptr;
}
struct epoll_event ev, events[1];
ev.data.fd = mGnssFd;
ev.events = EPOLLIN;
int epoll_fd = epoll_create1(0);
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, mGnssFd, &ev);
int bytes_read = -1;
std::string inputStr = "";
int epoll_ret = epoll_wait(epoll_fd, events, 1, mMinIntervalMs);
if (epoll_ret == -1) {
return nullptr;
}
while (true) {
memset(inputBuffer, 0, INPUT_BUFFER_SIZE);
bytes_read = read(mGnssFd, &inputBuffer, INPUT_BUFFER_SIZE);
if (bytes_read <= 0) {
break;
}
inputStr += std::string(inputBuffer, bytes_read);
}
return NmeaFixInfo::getLocationFromInputStr(inputStr);
std::string inputStr =
::android::hardware::gnss::common::DeviceFileReader::Instance().getLocationData();
return FixLocationParser::getLocationFromInputStr(inputStr);
}
template <class T_IGnss>