diff --git a/android/Android.mk b/android/Android.mk index b493f5e7..000cd59a 100644 --- a/android/Android.mk +++ b/android/Android.mk @@ -12,6 +12,7 @@ LOCAL_SRC_FILES := \ GnssMeasurement.cpp \ GnssNi.cpp \ GnssConfiguration.cpp \ + GnssDebug.cpp \ LOCAL_SRC_FILES += \ location_api/LocationUtil.cpp \ diff --git a/android/Gnss.cpp b/android/Gnss.cpp index 1412883a..ce02eddb 100644 --- a/android/Gnss.cpp +++ b/android/Gnss.cpp @@ -309,6 +309,12 @@ Return> Gnss::getExtensionGnssBatching() { return mGnssBatching; } +Return> Gnss::getExtensionGnssDebug() { + ENTRY_LOG_CALLFLOW(); + mGnssDebug = new GnssDebug(this); + return mGnssDebug; +} + IGnss* HIDL_FETCH_IGnss(const char* hal) { ENTRY_LOG_CALLFLOW(); IGnss* iface = nullptr; diff --git a/android/Gnss.h b/android/Gnss.h index b338b08e..99c5e40b 100644 --- a/android/Gnss.h +++ b/android/Gnss.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -102,9 +103,7 @@ struct Gnss : public IGnss { return nullptr; } - inline Return> getExtensionGnssDebug() override { - return nullptr; - } + Return> getExtensionGnssDebug() override; // These methods are not part of the IGnss base class. GnssAPIClient* getApi(); @@ -130,6 +129,7 @@ struct Gnss : public IGnss { sp mGnssConfig = nullptr; sp mGnssGeofencingIface = nullptr; sp mGnssBatching = nullptr; + sp mGnssDebug = nullptr; GnssAPIClient* mApi = nullptr; sp mGnssCbIface = nullptr; diff --git a/android/GnssDebug.cpp b/android/GnssDebug.cpp new file mode 100644 index 00000000..3ab94d30 --- /dev/null +++ b/android/GnssDebug.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2016 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. + */ + +#define LOG_TAG "LocSvc_GnssDebugInterface" + +#include +#include +#include "Gnss.h" +#include "GnssDebug.h" +#include "LocationUtil.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::hidl_vec; + +GnssDebug::GnssDebug(Gnss* gnss) : mGnss(gnss) +{ +} + +/* + * This methods requests position, time and satellite ephemeris debug information + * from the HAL. + * + * @return void +*/ +Return GnssDebug::getDebugData(getDebugData_cb _hidl_cb) +{ + LOC_LOGI("GnssDebug - 0317a"); + + DebugData data = { }; + + if((nullptr == mGnss) || (nullptr == mGnss->getGnssInterface())){ + LOC_LOGE("GnssDebug - Null GNSS interface"); + _hidl_cb(data); + return Void(); + } + + // get debug report snapshot via hal interface + GnssDebugReport reports = { }; + mGnss->getGnssInterface()->getDebugReport(reports); + + // location block + data.position.valid = true; + data.position.latitudeDegrees = reports.mLocation.mLocation.latitude; + data.position.longitudeDegrees = reports.mLocation.mLocation.longitude; + data.position.altitudeMeters = reports.mLocation.mLocation.altitude; + data.position.speedMetersPerSec = (double)(reports.mLocation.mLocation.speed); + data.position.bearingDegrees = (double)(reports.mLocation.mLocation.bearing); + data.position.horizontalAccuracyMeters = (double)(reports.mLocation.mLocation.accuracy); + data.position.verticalAccuracyMeters = reports.mLocation.verticalAccuracyMeters; + data.position.speedAccuracyMetersPerSecond = reports.mLocation.speedAccuracyMetersPerSecond; + data.position.bearingAccuracyDegrees = reports.mLocation.bearingAccuracyDegrees; + + LOC_LOGV("GnssDebug - lat=%f lon=%f", data.position.latitudeDegrees, data.position.longitudeDegrees); + + timeval tv_now, tv_report; + tv_report.tv_sec = reports.mLocation.mLocation.timestamp / 1000ULL; + tv_report.tv_usec = (reports.mLocation.mLocation.timestamp % 1000ULL) * 1000ULL; + gettimeofday(&tv_now, NULL); + data.position.ageSeconds = + (tv_now.tv_sec - tv_report.tv_sec) + (float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000; + + LOC_LOGV("GnssDebug - time now=%lld:%lld", tv_now.tv_sec, tv_now.tv_usec); + LOC_LOGV("GnssDebug - time rep=%lld:%lld", tv_report.tv_sec, tv_report.tv_usec); + LOC_LOGV("GnssDebug - age=%f", data.position.ageSeconds); + + // time block + data.time.valid = true; + data.time.timeEstimate = reports.mTime.timeEstimate; + data.time.timeUncertaintyNs = reports.mTime.timeUncertaintyNs; + + LOC_LOGV("GnssDebug - timeestimate=%lld", data.time.timeEstimate); + + // satellite data block + SatelliteData s = { }; + std::vector s_array = { }; + + for (uint32_t i=0; i +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssDebug; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; +using ::android::sp; + +/* Interface for GNSS Debug support. */ +struct Gnss; +struct GnssDebug : public IGnssDebug { + GnssDebug(Gnss* gnss); + ~GnssDebug() {}; + + /* + * Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow. + * These declarations were generated from IGnssDebug.hal. + */ + Return getDebugData(getDebugData_cb _hidl_cb) override; + +private: + Gnss* mGnss = nullptr; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V1_1_GNSSDEBUG_H diff --git a/core/SystemStatus.cpp b/core/SystemStatus.cpp index 592344bd..7791410e 100644 --- a/core/SystemStatus.cpp +++ b/core/SystemStatus.cpp @@ -1078,6 +1078,29 @@ void SystemStatusPositionFailure::dump() return; } +/****************************************************************************** + SystemStatusLocation +******************************************************************************/ +bool SystemStatusLocation::equals(SystemStatusLocation& peer) +{ + if ((mLocation.gpsLocation.latitude != peer.mLocation.gpsLocation.latitude) || + (mLocation.gpsLocation.longitude != peer.mLocation.gpsLocation.longitude) || + (mLocation.gpsLocation.altitude != peer.mLocation.gpsLocation.altitude)) { + return false; + } + return true; +} + +void SystemStatusLocation::dump() +{ + LOC_LOGV("Location: lat=%f lon=%f alt=%f spd=%f", + mLocation.gpsLocation.latitude, + mLocation.gpsLocation.longitude, + mLocation.gpsLocation.altitude, + mLocation.gpsLocation.speed); + return; +} + /****************************************************************************** SystemStatus ******************************************************************************/ @@ -1085,6 +1108,8 @@ pthread_mutex_t SystemStatus::mMutexSystemStatus = PTHREAD_MUTEX_INITIALIZER; SystemStatus::SystemStatus() { + mCache.mLocation.clear(); + mCache.mTimeAndClock.clear(); mCache.mXoState.clear(); mCache.mRfAndParams.clear(); @@ -1269,7 +1294,7 @@ bool SystemStatus::setNmeaString(const char *data, uint32_t len) char buf[SystemStatusNmeaBase::NMEA_MAXSIZE + 1] = { 0 }; strncpy(buf, data, len); - LOC_LOGI("setNmeaString-0320a: len=%d str=%d nmea=%s", len, strlen(data), buf); + LOC_LOGI("setNmeaString-0321a: nmea=%s", buf); pthread_mutex_lock(&mMutexSystemStatus); @@ -1329,6 +1354,36 @@ bool SystemStatus::setNmeaString(const char *data, uint32_t len) return ret; } +/****************************************************************************** +@brief API to set report position data into internal buffer + +@param[In] UlpLocation + +@return true when successfully done +******************************************************************************/ +bool SystemStatus::eventPosition(const UlpLocation& location, + const GpsLocationExtended& locationEx) +{ + timespec ts; + ts.tv_sec = location.gpsLocation.timestamp / 1000ULL; + ts.tv_nsec = (location.gpsLocation.timestamp % 1000ULL) * 1000000ULL; + SystemStatusLocation s(location, locationEx, ts); + if ((mCache.mLocation.empty()) || !mCache.mLocation.back().equals(s)) { + mCache.mLocation.push_back(s); + if (mCache.mLocation.size() > maxLocation) { + mCache.mLocation.erase(mCache.mLocation.begin()); + } + + LOC_LOGV("eventPosition - lat=%f lon=%f alt=%f speed=%f", + s.mLocation.gpsLocation.latitude, + s.mLocation.gpsLocation.longitude, + s.mLocation.gpsLocation.altitude, + s.mLocation.gpsLocation.speed); + + } + return true; +} + /****************************************************************************** @brief API to get report data into a given buffer @@ -1343,6 +1398,12 @@ bool SystemStatus::getReport(SystemStatusReports& report, bool isLatestOnly) con if (isLatestOnly) { // push back only the latest report and return it + report.mLocation.clear(); + if (mCache.mLocation.size() >= 1) { + report.mLocation.push_back(mCache.mLocation.back()); + report.mLocation.back().dump(); + } + report.mTimeAndClock.clear(); if (mCache.mTimeAndClock.size() >= 1) { report.mTimeAndClock.push_back(mCache.mTimeAndClock.back()); @@ -1402,6 +1463,8 @@ bool SystemStatus::getReport(SystemStatusReports& report, bool isLatestOnly) con } else { // copy entire reports and return them + report.mLocation.clear(); + report.mTimeAndClock.clear(); report.mXoState.clear(); report.mRfAndParams.clear(); diff --git a/core/SystemStatus.h b/core/SystemStatus.h index 95f82da5..208c669b 100644 --- a/core/SystemStatus.h +++ b/core/SystemStatus.h @@ -29,7 +29,16 @@ #ifndef __SYSTEM_STATUS__ #define __SYSTEM_STATUS__ +#include #include +#include + +#define GPS_MIN (1) +#define SBAS_MIN (33) +#define GLO_MIN (65) +#define BDS_MIN (201) +#define QZSS_MIN (193) +#define GAL_MIN (301) namespace loc_core { @@ -46,6 +55,21 @@ public: virtual void dump(void) { }; }; +class SystemStatusLocation : public SystemStatusItemBase +{ +public: + UlpLocation mLocation; + GpsLocationExtended mLocationEx; + SystemStatusLocation(const UlpLocation& location, + const GpsLocationExtended& locationEx, + const timespec& ts) : + SystemStatusItemBase(ts), + mLocation(location), + mLocationEx(locationEx){ }; + bool equals(SystemStatusLocation& peer); + void dump(void); +}; + class SystemStatusPQWM1; class SystemStatusTimeAndClock : public SystemStatusItemBase { @@ -212,6 +236,8 @@ public: class SystemStatusReports { public: + std::vector mLocation; + std::vector mTimeAndClock; std::vector mXoState; std::vector mRfAndParams; @@ -233,6 +259,8 @@ class SystemStatus { static pthread_mutex_t mMutexSystemStatus; + static const uint32_t maxLocation = 5; + static const uint32_t maxTimeAndClock = 5; static const uint32_t maxXoState = 5; static const uint32_t maxRfAndParams = 5; @@ -248,6 +276,8 @@ class SystemStatus SystemStatusReports mCache; + bool setLocation(const UlpLocation& location); + bool setTimeAndCLock(const SystemStatusPQWM1& nmea); bool setXoState(const SystemStatusPQWM1& nmea); bool setRfAndParams(const SystemStatusPQWM1& nmea); @@ -265,6 +295,7 @@ public: SystemStatus(); ~SystemStatus() { } + bool eventPosition(const UlpLocation& location,const GpsLocationExtended& locationEx); bool setNmeaString(const char *data, uint32_t len); bool getReport(SystemStatusReports& reports, bool isLatestonly = false) const; }; diff --git a/gnss/GnssAdapter.cpp b/gnss/GnssAdapter.cpp index 5240a542..855b1af8 100644 --- a/gnss/GnssAdapter.cpp +++ b/gnss/GnssAdapter.cpp @@ -1813,6 +1813,11 @@ GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation, mStatus(status), mTechMask(techMask) {} inline virtual void proc() const { + // extract bug report info - this returns true if consumed by systemstatus + SystemStatus* s = LocDualContext::getSystemStatus(); + if (nullptr != s) { + s->eventPosition(mUlpLocation, mLocationExtended); + } mAdapter.reportPosition(mUlpLocation, mLocationExtended, mStatus, mTechMask); } }; @@ -1974,7 +1979,6 @@ GnssAdapter::reportSv(GnssSvNotification& svNotify) void GnssAdapter::reportNmeaEvent(const char* nmea, size_t length, bool fromUlp) { - //LOC_LOGD("%s]: fromUlp %u", __func__, fromUlp); // if this event is not called from ULP, then try to call into ULP and return if successfull if (!fromUlp) { @@ -3239,3 +3243,121 @@ void GnssAdapter::dataConnFailedCommand(AGpsExtType agpsType){ sendMsg( new AgpsMsgAtlOpenFailed(&mAgpsManager, (AGpsExtType)agpsType)); } + +void GnssAdapter::convertSatelliteInfo(std::vector& out, + const GnssSvType& in_constellation, + const SystemStatusReports& in) +{ + GnssDebugSatelliteInfo s = {}; + uint64_t mask = 0ULL; + float age = 0.0; + uint32_t svid_min = 0; + uint32_t mask_size = 0; + + switch (in_constellation) { + case GNSS_SV_TYPE_GPS: + svid_min = GPS_MIN; + mask_size = 32; + break; + case GNSS_SV_TYPE_GLONASS: + svid_min = GLO_MIN; + mask_size = 32; + break; + case GNSS_SV_TYPE_BEIDOU: + svid_min = BDS_MIN; + mask_size = 64; + break; + case GNSS_SV_TYPE_QZSS: + svid_min = QZSS_MIN; + mask_size = 32; + break; + case GNSS_SV_TYPE_GALILEO: + svid_min = GAL_MIN; + mask_size = 64; + break; + default: + return; + } + + if(!in.mEphemeris.empty()) { + mask = in.mEphemeris.back().mGpsEpheValid; + if(!in.mXtra.empty()) { + age = (float)(in.mXtra.back().mGpsXtraAge); + } + else { + age = 0.0; + } + + for(uint32_t i=0; igetReport(reports, true); + + r.size = sizeof(r); + + // location block + r.mLocation.size = sizeof(r.mLocation); + if(!reports.mLocation.empty()) { + r.mLocation.mLocation.latitude = reports.mLocation.back().mLocation.gpsLocation.latitude; + r.mLocation.mLocation.longitude = reports.mLocation.back().mLocation.gpsLocation.longitude; + r.mLocation.mLocation.altitude = reports.mLocation.back().mLocation.gpsLocation.altitude; + r.mLocation.mLocation.speed = (double)(reports.mLocation.back().mLocation.gpsLocation.speed); + r.mLocation.mLocation.bearing = (double)(reports.mLocation.back().mLocation.gpsLocation.bearing); + r.mLocation.mLocation.accuracy = (double)(reports.mLocation.back().mLocation.gpsLocation.accuracy); + + r.mLocation.verticalAccuracyMeters = reports.mLocation.back().mLocationEx.vert_unc; + r.mLocation.speedAccuracyMetersPerSecond = reports.mLocation.back().mLocationEx.speed_unc; + r.mLocation.bearingAccuracyDegrees = reports.mLocation.back().mLocationEx.bearing_unc; + } + else if(!reports.mBestPosition.empty()) { + r.mLocation.mLocation.latitude = (double)(reports.mBestPosition.back().mBestLat); + r.mLocation.mLocation.longitude = (double)(reports.mBestPosition.back().mBestLon); + r.mLocation.mLocation.altitude = reports.mBestPosition.back().mBestAlt; + } + LOC_LOGV("getDebugReport - lat=%f lon=%f alt=%f speed=%f", + r.mLocation.mLocation.latitude, + r.mLocation.mLocation.longitude, + r.mLocation.mLocation.altitude, + r.mLocation.mLocation.speed); + + // time block + if(!reports.mBestPosition.empty()) { + r.mTime.size = sizeof(r.mTime); + r.mTime.timeEstimate = reports.mBestPosition.back().mUtcTime.tv_sec; + r.mTime.timeUncertaintyNs = (float)(reports.mTimeAndClock.back().mTimeUnc); + } + LOC_LOGV("getDebugReport - timeestimate=%lld", r.mTime.timeEstimate); + + // satellite info block + convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GPS, reports); + convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GLONASS, reports); + convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_BEIDOU, reports); + convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_QZSS, reports); + convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GALILEO, reports); + LOC_LOGV("getDebugReport - satellite=%d", r.mSatelliteInfo.size()); + + return true; +} + diff --git a/gnss/GnssAdapter.h b/gnss/GnssAdapter.h index f5a53004..626b87ff 100644 --- a/gnss/GnssAdapter.h +++ b/gnss/GnssAdapter.h @@ -34,6 +34,7 @@ #include #include #include +#include #define MAX_URL_LEN 256 #define NMEA_SENTENCE_MAX_LENGTH 200 @@ -255,6 +256,9 @@ public: /*======== UTILITIES ================================================================*/ int nmeaPutChecksum(char *nmea, size_t maxSize); + /*======== GNSSDEBUG ================================================================*/ + bool getDebugReport(GnssDebugReport& report); + /*==== CONVERSION ===================================================================*/ static uint32_t convertGpsLock(const GnssConfigGpsLock gpsLock); static GnssConfigGpsLock convertGpsLock(const uint32_t gpsLock); @@ -270,6 +274,9 @@ public: static GnssConfigLppeUserPlaneMask convertLppeUp(const uint32_t lppeUserPlaneMask); static uint32_t convertAGloProt(const GnssConfigAGlonassPositionProtocolMask); static uint32_t convertSuplMode(const GnssConfigSuplModeMask suplModeMask); + static void convertSatelliteInfo(std::vector& out, + const GnssSvType& in_constellation, + const SystemStatusReports& in); void injectLocationCommand(double latitude, double longitude, float accuracy); void injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty); diff --git a/gnss/location_gnss.cpp b/gnss/location_gnss.cpp index 0995f4b2..018b7f71 100644 --- a/gnss/location_gnss.cpp +++ b/gnss/location_gnss.cpp @@ -58,6 +58,7 @@ static void agpsInit(void* statusV4Cb); static void agpsDataConnOpen(AGpsExtType agpsType, const char* apnName, int apnLen, int ipType); static void agpsDataConnClosed(AGpsExtType agpsType); static void agpsDataConnFailed(AGpsExtType agpsType); +static void getDebugReport(GnssDebugReport& report); static const GnssInterface gGnssInterface = { sizeof(GnssInterface), @@ -80,7 +81,8 @@ static const GnssInterface gGnssInterface = { agpsInit, agpsDataConnOpen, agpsDataConnClosed, - agpsDataConnFailed + agpsDataConnFailed, + getDebugReport, }; #ifndef DEBUG_X86 @@ -239,3 +241,10 @@ static void agpsDataConnFailed(AGpsExtType agpsType) { gGnssAdapter->dataConnFailedCommand(agpsType); } } + +static void getDebugReport(GnssDebugReport& report) { + + if (NULL != gGnssAdapter) { + gGnssAdapter->getDebugReport(report); + } +} diff --git a/location/LocationAPI.h b/location/LocationAPI.h index cc15ddd3..6c718f7b 100644 --- a/location/LocationAPI.h +++ b/location/LocationAPI.h @@ -29,6 +29,7 @@ #ifndef LOCATION_H #define LOCATION_H +#include #include #include @@ -553,6 +554,35 @@ typedef struct { GnssConfigSuplModeMask suplModeMask; //bitwise OR of GnssConfigSuplModeBits } GnssConfig; +typedef struct { + size_t size; // set to sizeof + Location mLocation; + double verticalAccuracyMeters; + double speedAccuracyMetersPerSecond; + double bearingAccuracyDegrees; +} GnssDebugLocation; + +typedef struct { + size_t size; // set to sizeof + int64_t timeEstimate; + float timeUncertaintyNs; +} GnssDebugTime; + +typedef struct { + size_t size; // set to sizeof + uint32_t svid; + GnssSvType constellation; + uint32_t ephemerisType; + float ephemerisAgeSeconds; +} GnssDebugSatelliteInfo; + +typedef struct { + size_t size; // set to sizeof + GnssDebugLocation mLocation; + GnssDebugTime mTime; + std::vector mSatelliteInfo; +} GnssDebugReport; + /* Provides the capabilities of the system capabilities callback is called once soon after createInstance is called */ typedef std::function