Refactor and reuse some read device file logic

Add skeleton on HAL for Gnss raw measurement injection

Bug: 190757198
Test: manual test
Merged-In: I9b58043d5ed321aa71ff4f23031df251ae89c407
Change-Id: I9b58043d5ed321aa71ff4f23031df251ae89c407
This commit is contained in:
Yuchen He 2021-06-10 17:10:15 -07:00 committed by Hao Chen
parent 6f876987a6
commit 95276a229b
7 changed files with 178 additions and 47 deletions

View file

@ -19,11 +19,13 @@
#include "GnssMeasurementInterface.h"
#include <aidl/android/hardware/gnss/BnGnss.h>
#include <log/log.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;
std::shared_ptr<IGnssMeasurementCallback> GnssMeasurementInterface::sCallback = nullptr;
@ -63,9 +65,22 @@ void GnssMeasurementInterface::start(const bool enableCorrVecOutputs) {
mIsActive = true;
mThread = std::thread([this, enableCorrVecOutputs]() {
while (mIsActive == true) {
std::string rawMeasurementStr = "";
if (ReplayUtils::hasGnssDeviceFile() &&
ReplayUtils::isGnssRawMeasurement(
rawMeasurementStr = ReplayUtils::getDataFromDeviceFile(
std::string(
::android::hardware::gnss::common::CMD_GET_RAWMEASUREMENT),
mMinIntervalMillis))) {
// TODO: implement rawMeasurementStr parser and report measurement.
ALOGD("rawMeasurementStr(size: %zu) from device file: %s", rawMeasurementStr.size(),
rawMeasurementStr.c_str());
auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs);
this->reportMeasurement(measurement);
} else {
auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs);
this->reportMeasurement(measurement);
}
std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis));
}
});

View file

@ -41,6 +41,7 @@ cc_library_static {
"MockLocation.cpp",
"Utils.cpp",
"NmeaFixInfo.cpp",
"GnssReplayUtils.cpp",
],
export_include_dirs: ["include"],
shared_libs: [

View file

@ -0,0 +1,88 @@
/*
* 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"
namespace android {
namespace hardware {
namespace gnss {
namespace common {
const char* ReplayUtils::getGnssPath() {
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;
}
return gnss_dev_path;
}
bool ReplayUtils::hasGnssDeviceFile() {
struct stat sb;
return stat(getGnssPath(), &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.rfind("$GPRMC,", 0) == 0 || inputStr.rfind("$GPRMA,", 0) == 0);
}
std::string ReplayUtils::getDataFromDeviceFile(const std::string& command, int mMinIntervalMs) {
char inputBuffer[INPUT_BUFFER_SIZE];
int mGnssFd = open(getGnssPath(), O_RDWR | O_NONBLOCK);
if (mGnssFd == -1) {
return "";
}
int bytes_write = write(mGnssFd, command.c_str(), command.size());
if (bytes_write <= 0) {
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) {
return "";
}
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 inputStr;
}
} // namespace common
} // namespace gnss
} // namespace hardware
} // namespace android

View file

@ -34,6 +34,18 @@ 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 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,54 @@
/*
* 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 const char* getGnssPath();
static std::string getDataFromDeviceFile(const std::string& command, int mMinIntervalMs);
static bool hasGnssDeviceFile();
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

@ -35,6 +35,7 @@
#include "GnssDebug.h"
#include "GnssMeasurement.h"
#include "GnssMeasurementCorrections.h"
#include "GnssReplayUtils.h"
#include "MockLocation.h"
#include "NmeaFixInfo.h"
#include "Utils.h"
@ -159,15 +160,9 @@ 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);
}
// default using /dev/gnss0
const char* gnss_dev_path = ReplayUtils::getGnssPath();
mGnssFd = open(gnss_dev_path, O_RDWR | O_NONBLOCK);
if (mGnssFd == -1) {
@ -176,35 +171,8 @@ std::unique_ptr<V2_0::GnssLocation> GnssTemplate<T_IGnss>::getLocationFromHW() {
mHardwareModeChecked = true;
}
if (mGnssFd == -1) {
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);
}
std::string inputStr = ::android::hardware::gnss::common::ReplayUtils::getDataFromDeviceFile(
CMD_GET_LOCATION, mMinIntervalMs);
return NmeaFixInfo::getLocationFromInputStr(inputStr);
}