diff --git a/android/Gnss.cpp b/android/Gnss.cpp index 878cd202..8f048e24 100644 --- a/android/Gnss.cpp +++ b/android/Gnss.cpp @@ -25,6 +25,8 @@ #include #include #include "Gnss.h" +#include + typedef void* (getLocationInterface)(); #define IMAGES_INFO_FILE "/sys/devices/soc0/images" @@ -368,6 +370,14 @@ Return> Gnss::getExtensionAGnssRil() { Return Gnss::setCallback_1_1(const sp& callback) { ENTRY_LOG_CALLFLOW(); callback->gnssNameCb(getVersionString()); + mGnssCbIface_1_1 = callback; + GnssInterface* gnssInterface = getGnssInterface(); + if (nullptr != gnssInterface) { + OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) { + odcpiRequestCb(odcpiRequest); + }; + gnssInterface->odcpiInit(cb); + } return setCallback(callback); } @@ -396,11 +406,36 @@ Return> Gnss::getExtensionGnssConfiguration_1_1() { return mGnssConfig; } -Return Gnss::injectBestLocation(const GnssLocation&) { +Return Gnss::injectBestLocation(const GnssLocation& gnssLocation) { ENTRY_LOG_CALLFLOW(); + GnssInterface* gnssInterface = getGnssInterface(); + if (nullptr != gnssInterface) { + Location location = {}; + convertGnssLocation(gnssLocation, location); + gnssInterface->odcpiInject(location); + } return true; } +void Gnss::odcpiRequestCb(const OdcpiRequestInfo& request) { + ENTRY_LOG_CALLFLOW(); + if (mGnssCbIface_1_1 != nullptr) { + // For emergency mode, request DBH (Device based hybrid) location + // Mark Independent from GNSS flag to false. + if (ODCPI_REQUEST_TYPE_START == request.type) { + if (request.isEmergencyMode) { + mGnssCbIface_1_1->gnssRequestLocationCb(false); + } else { + mGnssCbIface_1_1->gnssRequestLocationCb(true); + } + } else { + LOC_LOGv("Unsupported ODCPI request type: %d", request.type); + } + } else { + LOC_LOGe("ODCPI request not supported."); + } +} + IGnss* HIDL_FETCH_IGnss(const char* hal) { ENTRY_LOG_CALLFLOW(); IGnss* iface = nullptr; diff --git a/android/Gnss.h b/android/Gnss.h index c562b1fb..4c0c8b05 100644 --- a/android/Gnss.h +++ b/android/Gnss.h @@ -111,6 +111,9 @@ struct Gnss : public IGnss { Return updateConfiguration(GnssConfig& gnssConfig); GnssInterface* getGnssInterface(); + // Callback for ODCPI request + void odcpiRequestCb(const OdcpiRequestInfo& request); + private: struct GnssDeathRecipient : hidl_death_recipient { GnssDeathRecipient(sp gnss) : mGnss(gnss) { @@ -134,6 +137,7 @@ struct Gnss : public IGnss { GnssAPIClient* mApi = nullptr; sp mGnssCbIface = nullptr; + sp mGnssCbIface_1_1 = nullptr; sp mGnssNiCbIface = nullptr; GnssConfig mPendingConfig; GnssInterface* mGnssInterface = nullptr; diff --git a/android/location_api/LocationUtil.cpp b/android/location_api/LocationUtil.cpp index 7f3a74bc..21c2e397 100644 --- a/android/location_api/LocationUtil.cpp +++ b/android/location_api/LocationUtil.cpp @@ -70,6 +70,37 @@ void convertGnssLocation(Location& in, GnssLocation& out) out.timestamp = static_cast(in.timestamp); } +void convertGnssLocation(const GnssLocation& in, Location& out) +{ + memset(&out, 0, sizeof(out)); + if (in.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG) + out.flags |= LOCATION_HAS_LAT_LONG_BIT; + if (in.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE) + out.flags |= LOCATION_HAS_ALTITUDE_BIT; + if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED) + out.flags |= LOCATION_HAS_SPEED_BIT; + if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) + out.flags |= LOCATION_HAS_BEARING_BIT; + if (in.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) + out.flags |= LOCATION_HAS_ACCURACY_BIT; + if (in.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) + out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT; + if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) + out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT; + if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) + out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT; + out.latitude = in.latitudeDegrees; + out.longitude = in.longitudeDegrees; + out.altitude = in.altitudeMeters; + out.speed = in.speedMetersPerSec; + out.bearing = in.bearingDegrees; + out.accuracy = in.horizontalAccuracyMeters; + out.verticalAccuracy = in.verticalAccuracyMeters; + out.speedAccuracy = in.speedAccuracyMetersPerSecond; + out.bearingAccuracy = in.bearingAccuracyDegrees; + out.timestamp = static_cast(in.timestamp); +} + void convertGnssConstellationType(GnssSvType& in, GnssConstellationType& out) { switch(in) { diff --git a/android/location_api/LocationUtil.h b/android/location_api/LocationUtil.h index acc0eabc..63f4f6f0 100644 --- a/android/location_api/LocationUtil.h +++ b/android/location_api/LocationUtil.h @@ -41,6 +41,7 @@ namespace V1_1 { namespace implementation { void convertGnssLocation(Location& in, V1_0::GnssLocation& out); +void convertGnssLocation(const V1_0::GnssLocation& in, Location& out); void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out); void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out); void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out); diff --git a/core/LocAdapterBase.cpp b/core/LocAdapterBase.cpp index f3c999c2..d0da3dac 100644 --- a/core/LocAdapterBase.cpp +++ b/core/LocAdapterBase.cpp @@ -161,4 +161,8 @@ bool LocAdapterBase:: reportWwanZppFix(LocGpsLocation &/*zppLoc*/) DEFAULT_IMPL(false) +bool LocAdapterBase:: + reportOdcpiRequestEvent(OdcpiRequestInfo& /*request*/) +DEFAULT_IMPL(false) + } // namespace loc_core diff --git a/core/LocAdapterBase.h b/core/LocAdapterBase.h index e7beca83..35fc48e5 100644 --- a/core/LocAdapterBase.h +++ b/core/LocAdapterBase.h @@ -153,6 +153,7 @@ public: virtual void reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& measurements, int msInWeek); virtual bool reportWwanZppFix(LocGpsLocation &zppLoc); + virtual bool reportOdcpiRequestEvent(OdcpiRequestInfo& request); }; } // namespace loc_core diff --git a/core/LocApiBase.cpp b/core/LocApiBase.cpp index 1e326d94..13d0773b 100644 --- a/core/LocApiBase.cpp +++ b/core/LocApiBase.cpp @@ -264,6 +264,12 @@ void LocApiBase::reportWwanZppFix(LocGpsLocation &zppLoc) TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportWwanZppFix(zppLoc)); } +void LocApiBase::reportOdcpiRequest(OdcpiRequestInfo& request) +{ + // loop through adapters, and deliver to the first handling adapter. + TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportOdcpiRequestEvent(request)); +} + void LocApiBase::reportSv(GnssSvNotification& svNotify) { const char* constellationString[] = { "Unknown", "GPS", "SBAS", "GLONASS", @@ -440,6 +446,10 @@ enum loc_api_adapter_err LocApiBase:: injectPosition(double /*latitude*/, double /*longitude*/, float /*accuracy*/) DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) +enum loc_api_adapter_err LocApiBase:: + injectPosition(const Location& /*location*/) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + enum loc_api_adapter_err LocApiBase:: setTime(LocGpsUtcTime /*time*/, int64_t /*timeReference*/, int /*uncertainty*/) DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) diff --git a/core/LocApiBase.h b/core/LocApiBase.h index 25d95b2a..6563dead 100644 --- a/core/LocApiBase.h +++ b/core/LocApiBase.h @@ -134,6 +134,7 @@ public: void reportGnssMeasurementData(GnssMeasurementsNotification& measurements, int msInWeek); void saveSupportedFeatureList(uint8_t *featureList); void reportWwanZppFix(LocGpsLocation &zppLoc); + void reportOdcpiRequest(OdcpiRequestInfo& request); // downward calls // All below functions are to be defined by adapter specific modules: @@ -153,6 +154,8 @@ public: setAPN(char* apn, int len); virtual enum loc_api_adapter_err injectPosition(double latitude, double longitude, float accuracy); + virtual enum loc_api_adapter_err + injectPosition(const Location& location); virtual enum loc_api_adapter_err setTime(LocGpsUtcTime time, int64_t timeReference, int uncertainty); virtual enum loc_api_adapter_err diff --git a/gnss/GnssAdapter.cpp b/gnss/GnssAdapter.cpp index e2a7c37f..a482acc0 100644 --- a/gnss/GnssAdapter.cpp +++ b/gnss/GnssAdapter.cpp @@ -74,6 +74,9 @@ GnssAdapter::GnssAdapter() : mNiData(), mAgpsManager(), mAgpsCbInfo(), + mOdcpiRequestCb(nullptr), + mOdcpiRequestActive(false), + mOdcpiInjectedPositionCount(0), mSystemStatus(SystemStatus::getInstance(mMsgTask)), mServerUrl(":"), mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask) @@ -1179,6 +1182,11 @@ GnssAdapter::updateClientsEventMask() mask |= LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST; } + // Add ODCPI handling + if (nullptr != mOdcpiRequestCb) { + mask |= LOC_API_ADAPTER_BIT_REQUEST_WIFI; + } + updateEvtMask(mask, LOC_REGISTRATION_MASK_SET); } @@ -2512,6 +2520,109 @@ GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial) mUlpProxy->reportSvPolynomial(svPolynomial); } +bool +GnssAdapter::reportOdcpiRequestEvent(OdcpiRequestInfo& request) +{ + LOC_LOGd("ODCPI request: type %d, tbf %d, isEmergency %d", request.type, + request.tbfMillis, request.isEmergencyMode); + + struct MsgReportOdcpiRequest : public LocMsg { + GnssAdapter& mAdapter; + OdcpiRequestInfo mOdcpiRequest; + inline MsgReportOdcpiRequest(GnssAdapter& adapter, OdcpiRequestInfo& request) : + LocMsg(), + mAdapter(adapter), + mOdcpiRequest(request) {} + inline virtual void proc() const { + mAdapter.reportOdcpiRequest(mOdcpiRequest); + } + }; + + sendMsg(new MsgReportOdcpiRequest(*this, request)); + return true; +} + +void GnssAdapter::reportOdcpiRequest(const OdcpiRequestInfo& request) +{ + if (nullptr != mOdcpiRequestCb) { + mOdcpiInjectedPositionCount = 0; + if (ODCPI_REQUEST_TYPE_START == request.type) { + mOdcpiRequestCb(request); + mOdcpiRequestActive = true; + } else { + mOdcpiRequestActive = false; + } + } else { + LOC_LOGe("ODCPI request not supported"); + } +} + +void GnssAdapter::initOdcpiCommand(const OdcpiRequestCallback& callback) +{ + struct MsgInitOdcpi : public LocMsg { + GnssAdapter& mAdapter; + OdcpiRequestCallback mOdcpiCb; + inline MsgInitOdcpi(GnssAdapter& adapter, + const OdcpiRequestCallback& callback) : + LocMsg(), + mAdapter(adapter), + mOdcpiCb(callback) {} + inline virtual void proc() const { + mAdapter.initOdcpi(mOdcpiCb); + } + }; + + sendMsg(new MsgInitOdcpi(*this, callback)); +} + +void GnssAdapter::initOdcpi(const OdcpiRequestCallback& callback) +{ + mOdcpiRequestCb = callback; + + /* Register for WIFI request */ + updateEvtMask(LOC_API_ADAPTER_BIT_REQUEST_WIFI, + LOC_REGISTRATION_MASK_ENABLED); +} + +void GnssAdapter::injectOdcpiCommand(const Location& location) +{ + struct MsgInjectOdcpi : public LocMsg { + GnssAdapter& mAdapter; + Location mLocation; + inline MsgInjectOdcpi(GnssAdapter& adapter, const Location& location) : + LocMsg(), + mAdapter(adapter), + mLocation(location) {} + inline virtual void proc() const { + mAdapter.injectOdcpi(mLocation); + } + }; + + sendMsg(new MsgInjectOdcpi(*this, location)); +} + +void GnssAdapter::injectOdcpi(const Location& location) +{ + LOC_LOGd("ODCPI Injection: requestActive: %d, lat %.7f long %.7f", + mOdcpiRequestActive, location.latitude, location.longitude); + + if (mOdcpiRequestActive) { + loc_api_adapter_err err = mLocApi->injectPosition(location); + if (LOC_API_ADAPTER_ERR_SUCCESS == err) { + mOdcpiInjectedPositionCount++; + if (mOdcpiInjectedPositionCount >= + ODCPI_INJECTED_POSITION_COUNT_PER_REQUEST) { + mOdcpiRequestActive = false; + mOdcpiInjectedPositionCount = 0; + } + } else { + LOC_LOGe("Inject Position API error %d", err); + } + } else { + LOC_LOGv("ODCPI request inactive, injection dropped"); + } +} + void GnssAdapter::initDefaultAgps() { LOC_LOGD("%s]: ", __func__); diff --git a/gnss/GnssAdapter.h b/gnss/GnssAdapter.h index 99ce5c9a..e98c76ea 100644 --- a/gnss/GnssAdapter.h +++ b/gnss/GnssAdapter.h @@ -43,6 +43,7 @@ #define MAX_SATELLITES_IN_USE 12 #define LOC_NI_NO_RESPONSE_TIME 20 #define LOC_GPS_NI_RESPONSE_IGNORE 4 +#define ODCPI_INJECTED_POSITION_COUNT_PER_REQUEST 30 class GnssAdapter; @@ -102,12 +103,17 @@ class GnssAdapter : public LocAdapterBase { /* ==== NI ============================================================================= */ NiData mNiData; - /* ==== AGPS ========================================================*/ + /* ==== AGPS =========================================================================== */ // This must be initialized via initAgps() AgpsManager mAgpsManager; AgpsCbInfo mAgpsCbInfo; void initAgps(const AgpsCbInfo& cbInfo); + /* ==== ODCPI ========================================================================== */ + OdcpiRequestCallback mOdcpiRequestCb; + bool mOdcpiRequestActive; + uint32_t mOdcpiInjectedPositionCount; + /* === SystemStatus ===================================================================== */ SystemStatus* mSystemStatus; std::string mServerUrl; @@ -209,6 +215,14 @@ public: void dataConnClosedCommand(AGpsExtType agpsType); void dataConnFailedCommand(AGpsExtType agpsType); + /* ========= ODCPI ===================================================================== */ + /* ======== COMMANDS ====(Called from Client Thread)==================================== */ + void initOdcpiCommand(const OdcpiRequestCallback& callback); + void injectOdcpiCommand(const Location& location); + /* ======== UTILITIES ================================================================== */ + void initOdcpi(const OdcpiRequestCallback& callback); + void injectOdcpi(const Location& location); + /* ======== RESPONSES ================================================================== */ void reportResponse(LocationError err, uint32_t sessionId); void reportResponse(size_t count, LocationError* errs, uint32_t* ids); @@ -242,6 +256,7 @@ public: virtual bool requestSuplES(int connHandle); virtual bool reportDataCallOpened(); virtual bool reportDataCallClosed(); + virtual bool reportOdcpiRequestEvent(OdcpiRequestInfo& request); /* ======== UTILITIES ================================================================= */ bool needReport(const UlpLocation& ulpLocation, @@ -254,6 +269,7 @@ public: void reportNmea(const char* nmea, size_t length); bool requestNiNotify(const GnssNiNotification& notify, const void* data); void reportGnssMeasurementData(const GnssMeasurementsNotification& measurements); + void reportOdcpiRequest(const OdcpiRequestInfo& request); /*======== GNSSDEBUG ================================================================*/ bool getDebugReport(GnssDebugReport& report); diff --git a/gnss/location_gnss.cpp b/gnss/location_gnss.cpp index 3e989c97..21763dd1 100644 --- a/gnss/location_gnss.cpp +++ b/gnss/location_gnss.cpp @@ -62,6 +62,9 @@ static void agpsDataConnFailed(AGpsExtType agpsType); static void getDebugReport(GnssDebugReport& report); static void updateConnectionStatus(bool connected, int8_t type); +static void odcpiInit(const OdcpiRequestCallback& callback); +static void odcpiInject(const Location& location); + static const GnssInterface gGnssInterface = { sizeof(GnssInterface), initialize, @@ -87,6 +90,8 @@ static const GnssInterface gGnssInterface = { agpsDataConnFailed, getDebugReport, updateConnectionStatus, + odcpiInit, + odcpiInject, }; #ifndef DEBUG_X86 @@ -265,3 +270,18 @@ static void updateConnectionStatus(bool connected, int8_t type) { gGnssAdapter->getSystemStatus()->eventConnectionStatus(connected, type); } } + +static void odcpiInit(const OdcpiRequestCallback& callback) +{ + if (NULL != gGnssAdapter) { + gGnssAdapter->initOdcpiCommand(callback); + } +} + +static void odcpiInject(const Location& location) +{ + if (NULL != gGnssAdapter) { + gGnssAdapter->injectOdcpiCommand(location); + } +} + diff --git a/location/location_interface.h b/location/location_interface.h index 27589f71..92290521 100644 --- a/location/location_interface.h +++ b/location/location_interface.h @@ -57,6 +57,8 @@ struct GnssInterface { void (*agpsDataConnFailed)(AGpsExtType agpsType); void (*getDebugReport)(GnssDebugReport& report); void (*updateConnectionStatus)(bool connected, int8_t type); + void (*odcpiInit)(const OdcpiRequestCallback& callback); + void (*odcpiInject)(const Location& location); }; struct FlpInterface { diff --git a/utils/gps_extended_c.h b/utils/gps_extended_c.h index afe47ccc..f029a354 100644 --- a/utils/gps_extended_c.h +++ b/utils/gps_extended_c.h @@ -1293,6 +1293,20 @@ struct AGnssExtStatusIpV6 { uint8_t ipV6Addr[16]; }; +/* ODCPI Request Info */ +enum OdcpiRequestType { + ODCPI_REQUEST_TYPE_START, + ODCPI_REQUEST_TYPE_STOP +}; +struct OdcpiRequestInfo { + size_t size; + OdcpiRequestType type; + uint32_t tbfMillis; + bool isEmergencyMode; +}; +/* Callback to send ODCPI request to framework */ +typedef std::function OdcpiRequestCallback; + /* * Callback with AGNSS(IpV4) status information. *