blob: 7560bff547a67ad29a0ed2628205343480b37178 [file] [log] [blame]
Michael Bestas3a0209e2023-05-04 01:15:47 +03001/* Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation, nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29#define LOG_NDEBUG 0
30#define LOG_TAG "LocSvc_GnssAdapter"
31
32#include <inttypes.h>
33#include <sys/stat.h>
34#include <errno.h>
35#include <ctype.h>
36#include <cutils/properties.h>
37#include <math.h>
38#include <arpa/inet.h>
39#include <netinet/in.h>
40#include <netdb.h>
41#include <GnssAdapter.h>
42#include <string>
43#include <sstream>
44#include <loc_log.h>
45#include <loc_nmea.h>
46#include <Agps.h>
47#include <SystemStatus.h>
48#include <vector>
49#include <loc_misc_utils.h>
50#include <gps_extended_c.h>
51
52#define RAD2DEG (180.0 / M_PI)
53#define DEG2RAD (M_PI / 180.0)
54#define PROCESS_NAME_ENGINE_SERVICE "engine-service"
55#define MIN_TRACKING_INTERVAL (100) // 100 msec
56
57#define BILLION_NSEC (1000000000ULL)
58#define NMEA_MIN_THRESHOLD_MSEC (99)
59#define NMEA_MAX_THRESHOLD_MSEC (975)
60
61#define DGNSS_RANGE_UPDATE_TIME_10MIN_IN_MILLI 600000
62
63using namespace loc_core;
64
65static int loadEngHubForExternalEngine = 0;
66static loc_param_s_type izatConfParamTable[] = {
67 {"LOAD_ENGHUB_FOR_EXTERNAL_ENGINE", &loadEngHubForExternalEngine, nullptr,'n'}
68};
69
70/* Method to fetch status cb from loc_net_iface library */
71typedef AgpsCbInfo& (*LocAgpsGetAgpsCbInfo)(LocAgpsOpenResultCb openResultCb,
72 LocAgpsCloseResultCb closeResultCb, void* userDataPtr);
73
74static void agpsOpenResultCb (bool isSuccess, AGpsExtType agpsType, const char* apn,
75 AGpsBearerType bearerType, void* userDataPtr);
76static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userDataPtr);
77
78typedef const CdfwInterface* (*getCdfwInterface)();
79
80typedef void getPdnTypeFromWds(const std::string& apnName, std::function<void(int)> pdnCb);
81
82inline bool GnssReportLoggerUtil::isLogEnabled() {
83 return (mLogLatency != nullptr);
84}
85
86inline void GnssReportLoggerUtil::log(const GnssLatencyInfo& gnssLatencyMeasInfo) {
87 if (mLogLatency != nullptr) {
88 mLogLatency(gnssLatencyMeasInfo);
89 }
90}
91
92GnssAdapter::GnssAdapter() :
93 LocAdapterBase(0,
94 LocContext::getLocContext(LocContext::mLocationHalName),
95 true, nullptr, true),
96 mEngHubProxy(new EngineHubProxyBase()),
Michael Bestas3a0209e2023-05-04 01:15:47 +030097 mNHzNeeded(false),
98 mSPEAlreadyRunningAtHighestInterval(false),
Albert Ib8416c92021-06-25 19:34:31 +080099 mLocPositionMode(),
Michael Bestas3a0209e2023-05-04 01:15:47 +0300100 mGnssSvIdUsedInPosition(),
101 mGnssSvIdUsedInPosAvail(false),
Albert Ib8416c92021-06-25 19:34:31 +0800102 mGnssMbSvIdUsedInPosition{},
103 mGnssMbSvIdUsedInPosAvail(false),
Michael Bestas3a0209e2023-05-04 01:15:47 +0300104 mControlCallbacks(),
105 mAfwControlId(0),
106 mNmeaMask(0),
107 mGnssSvIdConfig(),
108 mGnssSeconaryBandConfig(),
109 mGnssSvTypeConfig(),
110 mGnssSvTypeConfigCb(nullptr),
Albert Ib8416c92021-06-25 19:34:31 +0800111 mSupportNfwControl(true),
Michael Bestas3a0209e2023-05-04 01:15:47 +0300112 mLocConfigInfo{},
113 mNiData(),
114 mAgpsManager(),
Albert Ib8416c92021-06-25 19:34:31 +0800115 mNfwCb(NULL),
116 mIsE911Session(NULL),
117 mIsMeasCorrInterfaceOpen(false),
118 mIsAntennaInfoInterfaceOpened(false),
119 mQDgnssListenerHDL(nullptr),
120 mCdfwInterface(nullptr),
121 mDGnssNeedReport(false),
122 mDGnssDataUsage(false),
Michael Bestas3a0209e2023-05-04 01:15:47 +0300123 mOdcpiRequestCb(nullptr),
124 mOdcpiRequestActive(false),
Albert Ib8416c92021-06-25 19:34:31 +0800125 mCallbackPriority(OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW),
Michael Bestasf2732b92024-08-31 05:34:13 +0300126 mOdcpiStateMask(0),
Michael Bestas3a0209e2023-05-04 01:15:47 +0300127 mOdcpiTimer(this),
128 mOdcpiRequest(),
Albert Ib8416c92021-06-25 19:34:31 +0800129 mLastDeleteAidingDataTime(0),
Michael Bestas3a0209e2023-05-04 01:15:47 +0300130 mSystemStatus(SystemStatus::getInstance(mMsgTask)),
131 mServerUrl(":"),
132 mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask),
Michael Bestas3a0209e2023-05-04 01:15:47 +0300133 mLocSystemInfo{},
Albert Ib8416c92021-06-25 19:34:31 +0800134 mSystemPowerState(POWER_STATE_UNKNOWN),
135 mBlockCPIInfo{},
Michael Bestas3a0209e2023-05-04 01:15:47 +0300136 mPowerOn(false),
137 mAllowFlpNetworkFixes(0),
Albert Ib8416c92021-06-25 19:34:31 +0800138 mDreIntEnabled(false),
139 mNativeAgpsHandler(mSystemStatus->getOsObserver(), *this),
Michael Bestas3a0209e2023-05-04 01:15:47 +0300140 mGnssEnergyConsumedCb(nullptr),
141 mPowerStateCb(nullptr),
Michael Bestas3a0209e2023-05-04 01:15:47 +0300142 mSendNmeaConsent(false),
Albert Ib8416c92021-06-25 19:34:31 +0800143 mDgnssState(0),
144 mDgnssLastNmeaBootTimeMilli(0)
Michael Bestas3a0209e2023-05-04 01:15:47 +0300145{
146 LOC_LOGD("%s]: Constructor %p", __func__, this);
147 mLocPositionMode.mode = LOC_POSITION_MODE_INVALID;
148
149 pthread_condattr_t condAttr;
150 pthread_condattr_init(&condAttr);
151 pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC);
152 pthread_cond_init(&mNiData.session.tCond, &condAttr);
153 pthread_cond_init(&mNiData.sessionEs.tCond, &condAttr);
154 pthread_condattr_destroy(&condAttr);
155
156 /* Set ATL open/close callbacks */
157 AgpsAtlOpenStatusCb atlOpenStatusCb =
158 [this](int handle, int isSuccess, char* apn, uint32_t apnLen,
159 AGpsBearerType bearerType, AGpsExtType agpsType, LocApnTypeMask mask) {
160
161 mLocApi->atlOpenStatus(
162 handle, isSuccess, apn, apnLen, bearerType, agpsType, mask);
163 };
164 AgpsAtlCloseStatusCb atlCloseStatusCb =
165 [this](int handle, int isSuccess) {
166
167 mLocApi->atlCloseStatus(handle, isSuccess);
168 };
169 mAgpsManager.registerATLCallbacks(atlOpenStatusCb, atlCloseStatusCb);
170
171 readConfigCommand();
172 initDefaultAgpsCommand();
173 initEngHubProxyCommand();
174
175 // at last step, let us inform adapater base that we are done
176 // with initialization, e.g.: ready to process handleEngineUpEvent
177 doneInit();
178}
179
Michael Bestas9f1f76e2024-05-28 23:23:20 +0300180void GnssAdapter::setControlCallbacksCommand(LocationControlCallbacks& controlCallbacks)
Michael Bestas3a0209e2023-05-04 01:15:47 +0300181{
182 struct MsgSetControlCallbacks : public LocMsg {
183 GnssAdapter& mAdapter;
184 const LocationControlCallbacks mControlCallbacks;
185 inline MsgSetControlCallbacks(GnssAdapter& adapter,
186 LocationControlCallbacks& controlCallbacks) :
187 LocMsg(),
188 mAdapter(adapter),
189 mControlCallbacks(controlCallbacks) {}
190 inline virtual void proc() const {
191 mAdapter.setControlCallbacks(mControlCallbacks);
192 }
193 };
194
195 sendMsg(new MsgSetControlCallbacks(*this, controlCallbacks));
196}
197
198void
199GnssAdapter::convertOptions(LocPosMode& out, const TrackingOptions& trackingOptions)
200{
201 switch (trackingOptions.mode) {
202 case GNSS_SUPL_MODE_MSB:
203 out.mode = LOC_POSITION_MODE_MS_BASED;
204 break;
205 case GNSS_SUPL_MODE_MSA:
206 out.mode = LOC_POSITION_MODE_MS_ASSISTED;
207 break;
208 default:
209 out.mode = LOC_POSITION_MODE_STANDALONE;
210 break;
211 }
212 out.share_position = true;
213 out.min_interval = trackingOptions.minInterval;
214 out.powerMode = trackingOptions.powerMode;
215 out.timeBetweenMeasurements = trackingOptions.tbm;
216}
217
218bool
219GnssAdapter::checkAndSetSPEToRunforNHz(TrackingOptions & out) {
220
221 // first check if NHz meas is needed at all, if not, just return false
222 // if a NHz capable engine is subscribed for NHz measurement or NHz positions,
223 // always run the SPE only session at 100ms TBF.
224 // If SPE session is already set to highest interval, no need to start it again.
225
226 bool isSPERunningAtHighestInterval = false;
227
228 if (!mNHzNeeded) {
229 LOC_LOGd("No nHz session needed.");
230 } else if (mSPEAlreadyRunningAtHighestInterval) {
231 LOC_LOGd("SPE is already running at highest interval.");
232 isSPERunningAtHighestInterval = true;
233 } else if (out.minInterval > MIN_TRACKING_INTERVAL) {
234 out.minInterval = MIN_TRACKING_INTERVAL;
235 LOC_LOGd("nHz session is needed, starting SPE only session at 100ms TBF.");
236 mSPEAlreadyRunningAtHighestInterval = true;
237 }
238
239 return isSPERunningAtHighestInterval;
240}
241
242
243void
244GnssAdapter::convertLocation(Location& out, const UlpLocation& ulpLocation,
245 const GpsLocationExtended& locationExtended)
246{
247 memset(&out, 0, sizeof(Location));
248 out.size = sizeof(Location);
249 if (LOC_GPS_LOCATION_HAS_LAT_LONG & ulpLocation.gpsLocation.flags) {
250 out.flags |= LOCATION_HAS_LAT_LONG_BIT;
251 out.latitude = ulpLocation.gpsLocation.latitude;
252 out.longitude = ulpLocation.gpsLocation.longitude;
253 }
254 if (LOC_GPS_LOCATION_HAS_ALTITUDE & ulpLocation.gpsLocation.flags) {
255 out.flags |= LOCATION_HAS_ALTITUDE_BIT;
256 out.altitude = ulpLocation.gpsLocation.altitude;
257 }
258 if (LOC_GPS_LOCATION_HAS_SPEED & ulpLocation.gpsLocation.flags) {
259 out.flags |= LOCATION_HAS_SPEED_BIT;
260 out.speed = ulpLocation.gpsLocation.speed;
261 }
262 if (LOC_GPS_LOCATION_HAS_BEARING & ulpLocation.gpsLocation.flags) {
263 out.flags |= LOCATION_HAS_BEARING_BIT;
264 out.bearing = ulpLocation.gpsLocation.bearing;
265 }
266 if (LOC_GPS_LOCATION_HAS_ACCURACY & ulpLocation.gpsLocation.flags) {
267 out.flags |= LOCATION_HAS_ACCURACY_BIT;
268 out.accuracy = ulpLocation.gpsLocation.accuracy;
269 }
270 if (GPS_LOCATION_EXTENDED_HAS_VERT_UNC & locationExtended.flags) {
271 out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
272 out.verticalAccuracy = locationExtended.vert_unc;
273 }
274 if (GPS_LOCATION_EXTENDED_HAS_SPEED_UNC & locationExtended.flags) {
275 out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
276 out.speedAccuracy = locationExtended.speed_unc;
277 }
278 if (GPS_LOCATION_EXTENDED_HAS_BEARING_UNC & locationExtended.flags) {
279 out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
280 out.bearingAccuracy = locationExtended.bearing_unc;
281 }
282 if (GPS_LOCATION_EXTENDED_HAS_CONFORMITY_INDEX & locationExtended.flags) {
283 out.flags |= LOCATION_HAS_CONFORMITY_INDEX_BIT;
284 out.conformityIndex = locationExtended.conformityIndex;
285 }
286 out.timestamp = ulpLocation.gpsLocation.timestamp;
287 if (LOC_POS_TECH_MASK_SATELLITE & locationExtended.tech_mask) {
288 out.techMask |= LOCATION_TECHNOLOGY_GNSS_BIT;
289 }
290 if (LOC_POS_TECH_MASK_CELLID & locationExtended.tech_mask) {
291 out.techMask |= LOCATION_TECHNOLOGY_CELL_BIT;
292 }
293 if (LOC_POS_TECH_MASK_WIFI & locationExtended.tech_mask) {
294 out.techMask |= LOCATION_TECHNOLOGY_WIFI_BIT;
295 }
296 if (LOC_POS_TECH_MASK_SENSORS & locationExtended.tech_mask) {
297 out.techMask |= LOCATION_TECHNOLOGY_SENSORS_BIT;
298 }
299 if (LOC_POS_TECH_MASK_REFERENCE_LOCATION & locationExtended.tech_mask) {
300 out.techMask |= LOCATION_TECHNOLOGY_REFERENCE_LOCATION_BIT;
301 }
302 if (LOC_POS_TECH_MASK_INJECTED_COARSE_POSITION & locationExtended.tech_mask) {
303 out.techMask |= LOCATION_TECHNOLOGY_INJECTED_COARSE_POSITION_BIT;
304 }
305 if (LOC_POS_TECH_MASK_AFLT & locationExtended.tech_mask) {
306 out.techMask |= LOCATION_TECHNOLOGY_AFLT_BIT;
307 }
308 if (LOC_POS_TECH_MASK_HYBRID & locationExtended.tech_mask) {
309 out.techMask |= LOCATION_TECHNOLOGY_HYBRID_BIT;
310 }
311 if (LOC_POS_TECH_MASK_PPE & locationExtended.tech_mask) {
312 out.techMask |= LOCATION_TECHNOLOGY_PPE_BIT;
313 }
314 if (LOC_POS_TECH_MASK_VEH & locationExtended.tech_mask) {
315 out.techMask |= LOCATION_TECHNOLOGY_VEH_BIT;
316 }
317 if (LOC_POS_TECH_MASK_VIS & locationExtended.tech_mask) {
318 out.techMask |= LOCATION_TECHNOLOGY_VIS_BIT;
319 }
320 if (LOC_NAV_MASK_DGNSS_CORRECTION & locationExtended.navSolutionMask) {
321 out.techMask |= LOCATION_TECHNOLOGY_DGNSS_BIT;
322 }
323
324 if (LOC_GPS_LOCATION_HAS_SPOOF_MASK & ulpLocation.gpsLocation.flags) {
325 out.flags |= LOCATION_HAS_SPOOF_MASK;
326 out.spoofMask = ulpLocation.gpsLocation.spoof_mask;
327 }
328 if (LOC_GPS_LOCATION_HAS_ELAPSED_REAL_TIME & ulpLocation.gpsLocation.flags) {
329 out.flags |= LOCATION_HAS_ELAPSED_REAL_TIME;
330 out.elapsedRealTime = ulpLocation.gpsLocation.elapsedRealTime;
331 out.elapsedRealTimeUnc = ulpLocation.gpsLocation.elapsedRealTimeUnc;
332 }
333}
334
335/* This is utility routine that computes number of SV used
336 in the fix from the svUsedIdsMask.
337 */
338#define MAX_SV_CNT_SUPPORTED_IN_ONE_CONSTELLATION 64
339uint16_t GnssAdapter::getNumSvUsed(uint64_t svUsedIdsMask,
340 int totalSvCntInThisConstellation)
341{
342 if (totalSvCntInThisConstellation > MAX_SV_CNT_SUPPORTED_IN_ONE_CONSTELLATION) {
343 LOC_LOGe ("error: total SV count in this constellation %d exceeded limit of %d",
344 totalSvCntInThisConstellation, MAX_SV_CNT_SUPPORTED_IN_ONE_CONSTELLATION);
345 return 0;
346 }
347
348 uint16_t numSvUsed = 0;
349 uint64_t mask = 0x1;
350 for (int i = 0; i < totalSvCntInThisConstellation; i++) {
351 if (svUsedIdsMask & mask) {
352 numSvUsed++;
353 }
354 mask <<= 1;
355 }
356
357 return numSvUsed;
358}
359
360void
361GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out,
362 const GpsLocationExtended& locationExtended,
363 enum loc_sess_status status)
364{
365 out.size = sizeof(GnssLocationInfoNotification);
366 if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL & locationExtended.flags) {
367 out.flags |= GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT;
368 out.altitudeMeanSeaLevel = locationExtended.altitudeMeanSeaLevel;
369 }
370 if (GPS_LOCATION_EXTENDED_HAS_EXT_DOP & locationExtended.flags) {
371 out.flags |= (GNSS_LOCATION_INFO_DOP_BIT|GNSS_LOCATION_INFO_EXT_DOP_BIT);
372 out.pdop = locationExtended.extDOP.PDOP;
373 out.hdop = locationExtended.extDOP.HDOP;
374 out.vdop = locationExtended.extDOP.VDOP;
375 out.gdop = locationExtended.extDOP.GDOP;
376 out.tdop = locationExtended.extDOP.TDOP;
377 } else if (GPS_LOCATION_EXTENDED_HAS_DOP & locationExtended.flags) {
378 out.flags |= GNSS_LOCATION_INFO_DOP_BIT;
379 out.pdop = locationExtended.pdop;
380 out.hdop = locationExtended.hdop;
381 out.vdop = locationExtended.vdop;
382 }
383 if (GPS_LOCATION_EXTENDED_HAS_MAG_DEV & locationExtended.flags) {
384 out.flags |= GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT;
385 out.magneticDeviation = locationExtended.magneticDeviation;
386 }
387 if (GPS_LOCATION_EXTENDED_HAS_HOR_RELIABILITY & locationExtended.flags) {
388 out.flags |= GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT;
389 switch (locationExtended.horizontal_reliability) {
390 case LOC_RELIABILITY_VERY_LOW:
391 out.horReliability = LOCATION_RELIABILITY_VERY_LOW;
392 break;
393 case LOC_RELIABILITY_LOW:
394 out.horReliability = LOCATION_RELIABILITY_LOW;
395 break;
396 case LOC_RELIABILITY_MEDIUM:
397 out.horReliability = LOCATION_RELIABILITY_MEDIUM;
398 break;
399 case LOC_RELIABILITY_HIGH:
400 out.horReliability = LOCATION_RELIABILITY_HIGH;
401 break;
402 default:
403 out.horReliability = LOCATION_RELIABILITY_NOT_SET;
404 break;
405 }
406 }
407 if (GPS_LOCATION_EXTENDED_HAS_VERT_RELIABILITY & locationExtended.flags) {
408 out.flags |= GNSS_LOCATION_INFO_VER_RELIABILITY_BIT;
409 switch (locationExtended.vertical_reliability) {
410 case LOC_RELIABILITY_VERY_LOW:
411 out.verReliability = LOCATION_RELIABILITY_VERY_LOW;
412 break;
413 case LOC_RELIABILITY_LOW:
414 out.verReliability = LOCATION_RELIABILITY_LOW;
415 break;
416 case LOC_RELIABILITY_MEDIUM:
417 out.verReliability = LOCATION_RELIABILITY_MEDIUM;
418 break;
419 case LOC_RELIABILITY_HIGH:
420 out.verReliability = LOCATION_RELIABILITY_HIGH;
421 break;
422 default:
423 out.verReliability = LOCATION_RELIABILITY_NOT_SET;
424 break;
425 }
426 }
427 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MAJOR & locationExtended.flags) {
428 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT;
429 out.horUncEllipseSemiMajor = locationExtended.horUncEllipseSemiMajor;
430 }
431 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MINOR & locationExtended.flags) {
432 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT;
433 out.horUncEllipseSemiMinor = locationExtended.horUncEllipseSemiMinor;
434 }
435 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_AZIMUTH & locationExtended.flags) {
436 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT;
437 out.horUncEllipseOrientAzimuth = locationExtended.horUncEllipseOrientAzimuth;
438 }
439 if (GPS_LOCATION_EXTENDED_HAS_NORTH_STD_DEV & locationExtended.flags) {
440 out.flags |= GNSS_LOCATION_INFO_NORTH_STD_DEV_BIT;
441 out.northStdDeviation = locationExtended.northStdDeviation;
442 }
443 if (GPS_LOCATION_EXTENDED_HAS_EAST_STD_DEV & locationExtended.flags) {
444 out.flags |= GNSS_LOCATION_INFO_EAST_STD_DEV_BIT;
445 out.eastStdDeviation = locationExtended.eastStdDeviation;
446 }
447 if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL & locationExtended.flags) {
448 out.flags |= GNSS_LOCATION_INFO_NORTH_VEL_BIT;
449 out.northVelocity = locationExtended.northVelocity;
450 }
451 if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC & locationExtended.flags) {
452 out.flags |= GNSS_LOCATION_INFO_NORTH_VEL_UNC_BIT;
453 out.northVelocityStdDeviation = locationExtended.northVelocityStdDeviation;
454 }
455 if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL & locationExtended.flags) {
456 out.flags |= GNSS_LOCATION_INFO_EAST_VEL_BIT;
457 out.eastVelocity = locationExtended.eastVelocity;
458 }
459 if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC & locationExtended.flags) {
460 out.flags |= GNSS_LOCATION_INFO_EAST_VEL_UNC_BIT;
461 out.eastVelocityStdDeviation = locationExtended.eastVelocityStdDeviation;
462 }
463 if (GPS_LOCATION_EXTENDED_HAS_UP_VEL & locationExtended.flags) {
464 out.flags |= GNSS_LOCATION_INFO_UP_VEL_BIT;
465 out.upVelocity = locationExtended.upVelocity;
466 }
467 if (GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC & locationExtended.flags) {
468 out.flags |= GNSS_LOCATION_INFO_UP_VEL_UNC_BIT;
469 out.upVelocityStdDeviation = locationExtended.upVelocityStdDeviation;
470 }
471 if (GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA & locationExtended.flags) {
472 out.flags |= GNSS_LOCATION_INFO_GNSS_SV_USED_DATA_BIT;
473 out.svUsedInPosition.gpsSvUsedIdsMask =
474 locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask;
475 out.svUsedInPosition.gloSvUsedIdsMask =
476 locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask;
477 out.svUsedInPosition.galSvUsedIdsMask =
478 locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask;
479 out.svUsedInPosition.bdsSvUsedIdsMask =
480 locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask;
481 out.svUsedInPosition.qzssSvUsedIdsMask =
482 locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask;
483 out.svUsedInPosition.navicSvUsedIdsMask =
484 locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask;
485
486 out.flags |= GNSS_LOCATION_INFO_NUM_SV_USED_IN_POSITION_BIT;
487 out.numSvUsedInPosition = getNumSvUsed(out.svUsedInPosition.gpsSvUsedIdsMask,
488 GPS_SV_PRN_MAX - GPS_SV_PRN_MIN + 1);
489 out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.gloSvUsedIdsMask,
490 GLO_SV_PRN_MAX - GLO_SV_PRN_MIN + 1);
491 out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.qzssSvUsedIdsMask,
492 QZSS_SV_PRN_MAX - QZSS_SV_PRN_MIN + 1);
493 out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.bdsSvUsedIdsMask,
494 BDS_SV_PRN_MAX - BDS_SV_PRN_MIN + 1);
495 out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.galSvUsedIdsMask,
496 GAL_SV_PRN_MAX - GAL_SV_PRN_MIN + 1);
497 out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.navicSvUsedIdsMask,
498 NAVIC_SV_PRN_MAX - NAVIC_SV_PRN_MIN + 1);
499
500 out.numOfMeasReceived = locationExtended.numOfMeasReceived;
501 for (int idx =0; idx < locationExtended.numOfMeasReceived; idx++) {
502 out.measUsageInfo[idx].gnssSignalType =
503 locationExtended.measUsageInfo[idx].gnssSignalType;
504 out.measUsageInfo[idx].gnssSvId =
505 locationExtended.measUsageInfo[idx].gnssSvId;
506 out.measUsageInfo[idx].gnssConstellation =
507 locationExtended.measUsageInfo[idx].gnssConstellation;
508 }
509 }
510 if (GPS_LOCATION_EXTENDED_HAS_NAV_SOLUTION_MASK & locationExtended.flags) {
511 out.flags |= GNSS_LOCATION_INFO_NAV_SOLUTION_MASK_BIT;
512 out.navSolutionMask = locationExtended.navSolutionMask;
513 }
514 if (GPS_LOCATION_EXTENDED_HAS_POS_DYNAMICS_DATA & locationExtended.flags) {
515 out.flags |= GPS_LOCATION_EXTENDED_HAS_POS_DYNAMICS_DATA;
516 if (locationExtended.bodyFrameData.bodyFrameDataMask &
517 LOCATION_NAV_DATA_HAS_LONG_ACCEL_BIT) {
518 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LONG_ACCEL_BIT;
519 }
520 if (locationExtended.bodyFrameData.bodyFrameDataMask &
521 LOCATION_NAV_DATA_HAS_LAT_ACCEL_BIT) {
522 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LAT_ACCEL_BIT;
523 }
524 if (locationExtended.bodyFrameData.bodyFrameDataMask &
525 LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT) {
526 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT;
527 }
528 if (locationExtended.bodyFrameData.bodyFrameDataMask &
529 LOCATION_NAV_DATA_HAS_YAW_RATE_BIT) {
530 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_RATE_BIT;
531 }
532 if (locationExtended.bodyFrameData.bodyFrameDataMask &
533 LOCATION_NAV_DATA_HAS_PITCH_BIT) {
534 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_BIT;
535 }
536
537 if (locationExtended.bodyFrameData.bodyFrameDataMask &
538 LOCATION_NAV_DATA_HAS_LONG_ACCEL_UNC_BIT) {
539 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LONG_ACCEL_UNC_BIT;
540 }
541 if (locationExtended.bodyFrameData.bodyFrameDataMask &
542 LOCATION_NAV_DATA_HAS_LAT_ACCEL_UNC_BIT) {
543 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LAT_ACCEL_UNC_BIT;
544 }
545 if (locationExtended.bodyFrameData.bodyFrameDataMask &
546 LOCATION_NAV_DATA_HAS_VERT_ACCEL_UNC_BIT) {
547 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_VERT_ACCEL_UNC_BIT;
548 }
549 if (locationExtended.bodyFrameData.bodyFrameDataMask &
550 LOCATION_NAV_DATA_HAS_YAW_RATE_UNC_BIT) {
551 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_RATE_UNC_BIT;
552 }
553 if (locationExtended.bodyFrameData.bodyFrameDataMask &
554 LOCATION_NAV_DATA_HAS_PITCH_UNC_BIT) {
555 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_UNC_BIT;
556 }
557
558 if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
559 LOCATION_NAV_DATA_HAS_PITCH_RATE_BIT) {
560 out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_RATE_BIT;
561 }
562 if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
563 LOCATION_NAV_DATA_HAS_PITCH_RATE_UNC_BIT) {
564 out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_RATE_UNC_BIT;
565 }
566 if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
567 LOCATION_NAV_DATA_HAS_ROLL_BIT) {
568 out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_BIT;
569 }
570 if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
571 LOCATION_NAV_DATA_HAS_ROLL_UNC_BIT) {
572 out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_UNC_BIT;
573 }
574 if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
575 LOCATION_NAV_DATA_HAS_ROLL_RATE_BIT) {
576 out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_RATE_BIT;
577 }
578 if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
579 LOCATION_NAV_DATA_HAS_ROLL_RATE_UNC_BIT) {
580 out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_ROLL_RATE_UNC_BIT;
581 }
582 if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
583 LOCATION_NAV_DATA_HAS_YAW_BIT) {
584 out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_BIT;
585 }
586 if (locationExtended.bodyFrameDataExt.bodyFrameDataMask &
587 LOCATION_NAV_DATA_HAS_YAW_UNC_BIT) {
588 out.bodyFrameDataExt.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_UNC_BIT;
589 }
590
591 out.bodyFrameData.longAccel = locationExtended.bodyFrameData.longAccel;
592 out.bodyFrameData.latAccel = locationExtended.bodyFrameData.latAccel;
593 out.bodyFrameData.vertAccel = locationExtended.bodyFrameData.vertAccel;
594 out.bodyFrameData.yawRate = locationExtended.bodyFrameData.yawRate;
595 out.bodyFrameData.pitch = locationExtended.bodyFrameData.pitch;
596 out.bodyFrameData.longAccelUnc = locationExtended.bodyFrameData.longAccelUnc;
597 out.bodyFrameData.latAccelUnc = locationExtended.bodyFrameData.latAccelUnc;
598 out.bodyFrameData.vertAccelUnc = locationExtended.bodyFrameData.vertAccelUnc;
599 out.bodyFrameData.yawRateUnc = locationExtended.bodyFrameData.yawRateUnc;
600 out.bodyFrameData.pitchUnc = locationExtended.bodyFrameData.pitchUnc;
601
602 out.bodyFrameDataExt.pitchRate = locationExtended.bodyFrameDataExt.pitchRate;
603 out.bodyFrameDataExt.pitchRateUnc = locationExtended.bodyFrameDataExt.pitchRateUnc;
604 out.bodyFrameDataExt.roll = locationExtended.bodyFrameDataExt.roll;
605 out.bodyFrameDataExt.rollUnc = locationExtended.bodyFrameDataExt.rollUnc;
606 out.bodyFrameDataExt.rollRate = locationExtended.bodyFrameDataExt.rollRate;
607 out.bodyFrameDataExt.rollRateUnc = locationExtended.bodyFrameDataExt.rollRateUnc;
608 out.bodyFrameDataExt.yaw = locationExtended.bodyFrameDataExt.yaw;
609 out.bodyFrameDataExt.yawUnc = locationExtended.bodyFrameDataExt.yawUnc;
610 }
611
612 // Validity of this structure is established from the timeSrc of the GnssSystemTime structure.
613 out.gnssSystemTime = locationExtended.gnssSystemTime;
614
615 if (GPS_LOCATION_EXTENDED_HAS_LEAP_SECONDS & locationExtended.flags) {
616 out.flags |= GNSS_LOCATION_INFO_LEAP_SECONDS_BIT;
617 out.leapSeconds = locationExtended.leapSeconds;
618 }
619
620 if (GPS_LOCATION_EXTENDED_HAS_TIME_UNC & locationExtended.flags) {
621 out.flags |= GNSS_LOCATION_INFO_TIME_UNC_BIT;
622 out.timeUncMs = locationExtended.timeUncMs;
623 }
624
625 if (GPS_LOCATION_EXTENDED_HAS_CALIBRATION_CONFIDENCE & locationExtended.flags) {
626 out.flags |= GNSS_LOCATION_INFO_CALIBRATION_CONFIDENCE_BIT;
627 out.calibrationConfidence = locationExtended.calibrationConfidence;
628 }
629
630 if (GPS_LOCATION_EXTENDED_HAS_CALIBRATION_STATUS & locationExtended.flags) {
631 out.flags |= GNSS_LOCATION_INFO_CALIBRATION_STATUS_BIT;
632 out.calibrationStatus = locationExtended.calibrationStatus;
633 }
634
635 if (GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & locationExtended.flags) {
636 out.flags |= GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT;
637 out.locOutputEngType = locationExtended.locOutputEngType;
638 }
639
640 if (GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_MASK & locationExtended.flags) {
641 out.flags |= GNSS_LOCATION_INFO_OUTPUT_ENG_MASK_BIT;
642 out.locOutputEngMask = locationExtended.locOutputEngMask;
643 }
644
645 if (GPS_LOCATION_EXTENDED_HAS_CONFORMITY_INDEX & locationExtended.flags) {
646 out.flags |= GNSS_LOCATION_INFO_CONFORMITY_INDEX_BIT;
647 out.conformityIndex = locationExtended.conformityIndex;
648 }
649
650 if (GPS_LOCATION_EXTENDED_HAS_LLA_VRP_BASED & locationExtended.flags) {
651 out.flags |= GNSS_LOCATION_INFO_LLA_VRP_BASED_BIT;
652 out.llaVRPBased = locationExtended.llaVRPBased;
653 }
654
655 if (GPS_LOCATION_EXTENDED_HAS_ENU_VELOCITY_LLA_VRP_BASED & locationExtended.flags) {
656 out.flags |= GNSS_LOCATION_INFO_ENU_VELOCITY_VRP_BASED_BIT;
657 // copy over east, north and up vrp based velocity
658 out.enuVelocityVRPBased[0] = locationExtended.enuVelocityVRPBased[0];
659 out.enuVelocityVRPBased[1] = locationExtended.enuVelocityVRPBased[1];
660 out.enuVelocityVRPBased[2] = locationExtended.enuVelocityVRPBased[2];
661 }
662
663 if (GPS_LOCATION_EXTENDED_HAS_DR_SOLUTION_STATUS_MASK & locationExtended.flags) {
664 out.flags |= GNSS_LOCATION_INFO_DR_SOLUTION_STATUS_MASK_BIT;
665 out.drSolutionStatusMask = locationExtended.drSolutionStatusMask;
666 }
667
668 if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_ASSUMED & locationExtended.flags) {
669 out.flags |= GNSS_LOCATION_INFO_ALTITUDE_ASSUMED_BIT;
670 out.altitudeAssumed = locationExtended.altitudeAssumed;
671 }
672
673 out.flags |= GNSS_LOCATION_INFO_SESSION_STATUS_BIT;
674 out.sessionStatus = status;
675}
676
677inline uint32_t
678GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion)
679{
680 switch (suplVersion) {
681 case GNSS_CONFIG_SUPL_VERSION_2_0_4:
682 return 0x00020004;
683 case GNSS_CONFIG_SUPL_VERSION_2_0_0:
684 return 0x00020000;
685 case GNSS_CONFIG_SUPL_VERSION_2_0_2:
686 return 0x00020002;
687 case GNSS_CONFIG_SUPL_VERSION_1_0_0:
688 default:
689 return 0x00010000;
690 }
691}
692
693uint32_t
694GnssAdapter::convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)
695{
696 uint32_t mask = 0;
697 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT & lppeControlPlaneMask) {
698 mask |= (1<<0);
699 }
700 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
701 mask |= (1<<1);
702 }
703 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
704 mask |= (1<<2);
705 }
706 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeControlPlaneMask) {
707 mask |= (1<<3);
708 }
709 return mask;
710}
711
712uint32_t
713GnssAdapter::convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)
714{
715 uint32_t mask = 0;
716 if (GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT & lppeUserPlaneMask) {
717 mask |= (1<<0);
718 }
719 if (GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
720 mask |= (1<<1);
721 }
722 if (GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
723 mask |= (1<<2);
724 }
725 if (GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeUserPlaneMask) {
726 mask |= (1<<3);
727 }
728 return mask;
729}
730
731uint32_t
732GnssAdapter::convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)
733{
734 uint32_t mask = 0;
735 if (GNSS_CONFIG_RRC_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
736 mask |= (1<<0);
737 }
738 if (GNSS_CONFIG_RRLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
739 mask |= (1<<1);
740 }
741 if (GNSS_CONFIG_LLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
742 mask |= (1<<2);
743 }
744 if (GNSS_CONFIG_LLP_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
745 mask |= (1<<3);
746 }
747 return mask;
748}
749
750uint32_t
751GnssAdapter::convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)
752{
753 switch (emergencyPdnForEmergencySupl) {
754 case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES:
755 return 1;
756 case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO:
757 default:
758 return 0;
759 }
760}
761
762uint32_t
763GnssAdapter::convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)
764{
765 switch (suplEmergencyServices) {
766 case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES:
767 return 1;
768 case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO:
769 default:
770 return 0;
771 }
772}
773
774uint32_t
775GnssAdapter::convertSuplMode(const GnssConfigSuplModeMask suplModeMask)
776{
777 uint32_t mask = 0;
778 if (GNSS_CONFIG_SUPL_MODE_MSB_BIT & suplModeMask) {
779 mask |= (1<<0);
780 }
781 if (GNSS_CONFIG_SUPL_MODE_MSA_BIT & suplModeMask) {
782 mask |= (1<<1);
783 }
784 return mask;
785}
786
787void
788GnssAdapter::readConfigCommand()
789{
790 LOC_LOGD("%s]: ", __func__);
791
792 struct MsgReadConfig : public LocMsg {
793 GnssAdapter* mAdapter;
794 ContextBase& mContext;
795 inline MsgReadConfig(GnssAdapter* adapter,
796 ContextBase& context) :
797 LocMsg(),
798 mAdapter(adapter),
799 mContext(context) {}
800 inline virtual void proc() const {
801 static bool confReadDone = false;
802 if (!confReadDone) {
803 confReadDone = true;
804 // reads config into mContext->mGps_conf
805 mContext.readConfig();
806
807 uint32_t allowFlpNetworkFixes = 0;
808 static const loc_param_s_type flp_conf_param_table[] =
809 {
810 {"ALLOW_NETWORK_FIXES", &allowFlpNetworkFixes, NULL, 'n'},
811 };
812 UTIL_READ_CONF(LOC_PATH_FLP_CONF, flp_conf_param_table);
813 LOC_LOGd("allowFlpNetworkFixes %u", allowFlpNetworkFixes);
814 mAdapter->setAllowFlpNetworkFixes(allowFlpNetworkFixes);
815 }
816 }
817 };
818
819 if (mContext != NULL) {
820 sendMsg(new MsgReadConfig(this, *mContext));
821 }
822}
823
824void
825GnssAdapter::setSuplHostServer(const char* server, int port, LocServerType type)
826{
827 if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
828 char serverUrl[MAX_URL_LEN] = {};
829 int32_t length = -1;
830 const char noHost[] = "NONE";
831
832 if ((NULL == server) || (server[0] == 0) ||
833 (strncasecmp(noHost, server, sizeof(noHost)) == 0)) {
834 serverUrl[0] = '\0';
835 length = 0;
836 } else if (port > 0) {
837 length = snprintf(serverUrl, sizeof(serverUrl), "%s:%u", server, port);
838 }
839 if (LOC_AGPS_SUPL_SERVER != type && LOC_AGPS_MO_SUPL_SERVER != type) {
840 LOC_LOGe("Invalid type=%d", type);
841 } else if (length >= 0) {
842 if (LOC_AGPS_SUPL_SERVER == type) {
843 getServerUrl().assign(serverUrl);
844 strlcpy(ContextBase::mGps_conf.SUPL_HOST,
845 (nullptr == server) ? serverUrl : server,
846 LOC_MAX_PARAM_STRING);
847 ContextBase::mGps_conf.SUPL_PORT = port;
848 } else {
849 if (strncasecmp(getMoServerUrl().c_str(), serverUrl, sizeof(serverUrl)) != 0) {
850 getMoServerUrl().assign(serverUrl);
851 }
852 }
853 }
854 }
855}
856
857void
858GnssAdapter::setConfig()
859{
860 LOC_LOGD("%s]: ", __func__);
861
862 // set nmea mask type
863 uint32_t mask = 0;
864 if (NMEA_PROVIDER_MP == ContextBase::mGps_conf.NMEA_PROVIDER) {
865 mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK;
866 if (ContextBase::mGps_conf.NMEA_TAG_BLOCK_GROUPING_ENABLED) {
867 mask |= LOC_NMEA_MASK_TAGBLOCK_V02;
868 }
869 }
870 if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
871 mask |= LOC_NMEA_MASK_DEBUG_V02;
872 }
873 if (mNmeaMask != mask) {
874 mNmeaMask = mask;
875 if (mNmeaMask) {
876 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
877 if ((it->second.gnssNmeaCb != nullptr)) {
878 updateEvtMask(LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT,
879 LOC_REGISTRATION_MASK_ENABLED);
880 break;
881 }
882 }
883 }
884 }
885
886 std::string oldMoServerUrl = getMoServerUrl();
887 setSuplHostServer(ContextBase::mGps_conf.SUPL_HOST,
888 ContextBase::mGps_conf.SUPL_PORT,
889 LOC_AGPS_SUPL_SERVER);
890 setSuplHostServer(ContextBase::mGps_conf.MO_SUPL_HOST,
891 ContextBase::mGps_conf.MO_SUPL_PORT,
892 LOC_AGPS_MO_SUPL_SERVER);
893
894 std::string moServerUrl = getMoServerUrl();
895 std::string serverUrl = getServerUrl();
896 // inject the configurations into modem
897 loc_gps_cfg_s gpsConf = ContextBase::mGps_conf;
898 loc_sap_cfg_s_type sapConf = ContextBase::mSap_conf;
899
900 //cache the injected configuration with GnssConfigRequested struct
901 GnssConfig gnssConfigRequested = {};
902 gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT |
903 GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
904 /* Here we process an SSR. We need to set the GPS_LOCK to the proper values, as follows:
905 1. Q behavior. This is identified by mSupportNfwControl being 1. In this case
906 ContextBase::mGps_conf.GPS_LOCK is a "state", meaning it should reflect the
907 NV value. Therefore we will set the NV to ContextBase::mGps_conf.GPS_LOCK
908 2. P behavior. This is identified by mSupportNfwControl being 0. In this case
909 ContextBase::mGps_conf.GPS_LOCK is a "configuration", meaning it should hold
910 the "mask" for NI. There are two subcases:
911 a. Location enabled in GUI (1 == getAfwControlId()). We need to set
912 the NV to GNSS_CONFIG_GPS_LOCK_NONE (both MO and NI enabled)
913 b. Location disabled in GUI (0 == getAfwControlId()). We need to set
914 the NV to ContextBase::mGps_conf.GPS_LOCK (the "mask", which is SIM-card
915 specific)
916 */
917 if (mSupportNfwControl || (0 == getAfwControlId())) {
918 gnssConfigRequested.gpsLock = gpsConf.GPS_LOCK;
919 } else {
920 gnssConfigRequested.gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
921 }
922 gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT |
923 GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT |
924 GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT |
925 GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
926 gnssConfigRequested.suplVersion = mLocApi->convertSuplVersion(gpsConf.SUPL_VER);
927 gnssConfigRequested.lppProfileMask = gpsConf.LPP_PROFILE;
928 gnssConfigRequested.aGlonassPositionProtocolMask = gpsConf.A_GLONASS_POS_PROTOCOL_SELECT;
929 if (gpsConf.LPPE_CP_TECHNOLOGY) {
930 gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
931 gnssConfigRequested.lppeControlPlaneMask =
932 mLocApi->convertLppeCp(gpsConf.LPPE_CP_TECHNOLOGY);
933 }
934
935 if (gpsConf.LPPE_UP_TECHNOLOGY) {
936 gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT;
937 gnssConfigRequested.lppeUserPlaneMask =
938 mLocApi->convertLppeUp(gpsConf.LPPE_UP_TECHNOLOGY);
939 }
940 gnssConfigRequested.blacklistedSvIds.assign(mBlacklistedSvIds.begin(),
941 mBlacklistedSvIds.end());
942 mLocApi->sendMsg(new LocApiMsg(
943 [this, gpsConf, sapConf, oldMoServerUrl, moServerUrl,
944 serverUrl, gnssConfigRequested] () mutable {
945 gnssUpdateConfig(oldMoServerUrl, moServerUrl, serverUrl,
946 gnssConfigRequested, gnssConfigRequested);
947
948 // set nmea mask type
949 uint32_t mask = 0;
950 if (NMEA_PROVIDER_MP == gpsConf.NMEA_PROVIDER) {
951 mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK;
952 if (gpsConf.NMEA_TAG_BLOCK_GROUPING_ENABLED) {
953 mask |= LOC_NMEA_MASK_TAGBLOCK_V02;
954 }
955 }
956 if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
957 mask |= LOC_NMEA_MASK_DEBUG_V02;
958 }
959
960 if (mask != 0) {
961 mLocApi->setNMEATypesSync(mask);
962 }
963
964 // load tunc configuration from config file on first boot-up,
965 // e.g.: adapter.mLocConfigInfo.tuncConfigInfo.isValid is false
966 if (mLocConfigInfo.tuncConfigInfo.isValid == false) {
967 mLocConfigInfo.tuncConfigInfo.isValid = true;
968 mLocConfigInfo.tuncConfigInfo.enable =
969 (gpsConf.CONSTRAINED_TIME_UNCERTAINTY_ENABLED == 1);
970 mLocConfigInfo.tuncConfigInfo.tuncThresholdMs =
971 (float)gpsConf.CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD;
972 mLocConfigInfo.tuncConfigInfo.energyBudget =
973 gpsConf.CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET;
974 }
975
976 mLocApi->setConstrainedTuncMode(
977 mLocConfigInfo.tuncConfigInfo.enable,
978 mLocConfigInfo.tuncConfigInfo.tuncThresholdMs,
979 mLocConfigInfo.tuncConfigInfo.energyBudget);
980
981 // load pace configuration from config file on first boot-up,
982 // e.g.: adapter.mLocConfigInfo.paceConfigInfo.isValid is false
983 if (mLocConfigInfo.paceConfigInfo.isValid == false) {
984 mLocConfigInfo.paceConfigInfo.isValid = true;
985 mLocConfigInfo.paceConfigInfo.enable =
986 (gpsConf.POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED==1);
987 }
988 mLocApi->setPositionAssistedClockEstimatorMode(
989 mLocConfigInfo.paceConfigInfo.enable);
990
991 // we do not support control robust location from gps.conf
992 if (mLocConfigInfo.robustLocationConfigInfo.isValid == true) {
993 mLocApi->configRobustLocation(
994 mLocConfigInfo.robustLocationConfigInfo.enable,
995 mLocConfigInfo.robustLocationConfigInfo.enableFor911);
996 }
997
998 if (sapConf.GYRO_BIAS_RANDOM_WALK_VALID ||
999 sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
1000 sapConf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
1001 sapConf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
1002 sapConf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID ) {
1003 mLocApi->setSensorPropertiesSync(
1004 sapConf.GYRO_BIAS_RANDOM_WALK_VALID,
1005 sapConf.GYRO_BIAS_RANDOM_WALK,
1006 sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
1007 sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY,
1008 sapConf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
1009 sapConf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY,
1010 sapConf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
1011 sapConf.RATE_RANDOM_WALK_SPECTRAL_DENSITY,
1012 sapConf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
1013 sapConf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY);
1014 }
1015 mLocApi->setSensorPerfControlConfigSync(
1016 sapConf.SENSOR_CONTROL_MODE,
1017 sapConf.SENSOR_ACCEL_SAMPLES_PER_BATCH,
1018 sapConf.SENSOR_ACCEL_BATCHES_PER_SEC,
1019 sapConf.SENSOR_GYRO_SAMPLES_PER_BATCH,
1020 sapConf.SENSOR_GYRO_BATCHES_PER_SEC,
1021 sapConf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH,
1022 sapConf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH,
1023 sapConf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH,
1024 sapConf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH,
1025 sapConf.SENSOR_ALGORITHM_CONFIG_MASK);
1026 } ));
1027 // deal with Measurement Corrections
1028 if (true == mIsMeasCorrInterfaceOpen) {
1029 initMeasCorr(true);
1030 }
1031}
1032
1033std::vector<LocationError> GnssAdapter::gnssUpdateConfig(const std::string& oldMoServerUrl,
1034 const std::string& moServerUrl, const std::string& serverUrl,
1035 GnssConfig& gnssConfigRequested, GnssConfig& gnssConfigNeedEngineUpdate, size_t count) {
1036 loc_gps_cfg_s gpsConf = ContextBase::mGps_conf;
1037 size_t index = 0;
1038 LocationError err = LOCATION_ERROR_SUCCESS;
1039 std::vector<LocationError> errsList = {err};
1040 if (count > 0) {
1041 errsList.insert(errsList.begin(), count, LOCATION_ERROR_SUCCESS);
1042 }
1043
1044 int serverUrlLen = serverUrl.length();
1045 int moServerUrlLen = moServerUrl.length();
1046
1047 if (!ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
1048 LOC_LOGd("AGPS_CONFIG_INJECT is 0. Not setting flags for AGPS configurations");
1049 gnssConfigRequested.flags &= ~(GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT |
1050 GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT |
1051 GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT |
1052 GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT);
1053 }
1054
1055 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
1056 if (gnssConfigNeedEngineUpdate.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
1057 err = mLocApi->setGpsLockSync(gnssConfigRequested.gpsLock);
1058 if (index < count) {
1059 errsList[index] = err;
1060 }
1061 }
1062 index++;
1063 }
1064
1065 if (gnssConfigRequested.flags &
1066 GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
1067 if (gnssConfigNeedEngineUpdate.flags &
1068 GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
1069 if (gnssConfigNeedEngineUpdate.assistanceServer.type ==
1070 GNSS_ASSISTANCE_TYPE_SUPL) {
1071 err = mLocApi->setServerSync(
1072 serverUrl.c_str(), serverUrlLen, LOC_AGPS_SUPL_SERVER);
1073 if (index < count) {
1074 errsList[index] = err;
1075 }
1076 if (0 != oldMoServerUrl.compare(moServerUrl)) {
1077 LocationError locErr =
1078 mLocApi->setServerSync(moServerUrl.c_str(),
1079 moServerUrlLen,
1080 LOC_AGPS_MO_SUPL_SERVER);
1081 if (locErr != LOCATION_ERROR_SUCCESS) {
1082 LOC_LOGe("Error while setting MO SUPL_HOST server:%s",
1083 moServerUrl.c_str());
1084 }
1085 }
1086 } else if (gnssConfigNeedEngineUpdate.assistanceServer.type ==
1087 GNSS_ASSISTANCE_TYPE_C2K) {
1088 struct in_addr addr;
1089 struct hostent* hp;
1090 bool resolveAddrSuccess = true;
1091
1092 hp = gethostbyname(
1093 gnssConfigNeedEngineUpdate.assistanceServer.hostName);
1094 if (hp != NULL) { /* DNS OK */
1095 memcpy(&addr, hp->h_addr_list[0], hp->h_length);
1096 } else {
1097 /* Try IP representation */
1098 if (inet_aton(
1099 gnssConfigNeedEngineUpdate.assistanceServer.hostName,
1100 &addr) == 0) {
1101 /* IP not valid */
1102 LOC_LOGE("%s]: hostname '%s' cannot be resolved ",
1103 __func__,
1104 gnssConfigNeedEngineUpdate.assistanceServer.hostName);
1105 if (index < count) {
1106 errsList[index] = LOCATION_ERROR_INVALID_PARAMETER;
1107 }
1108 } else {
1109 resolveAddrSuccess = false;
1110 }
1111 }
1112
1113 if (resolveAddrSuccess) {
1114 unsigned int ip = htonl(addr.s_addr);
1115 err = mLocApi->setServerSync(ip,
1116 gnssConfigNeedEngineUpdate.assistanceServer.port,
1117 LOC_AGPS_CDMA_PDE_SERVER);
1118 if (index < count) {
1119 errsList[index] = err;
1120 }
1121 }
1122 }
1123 }
1124 index++;
1125 }
1126
1127 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
1128 if (gnssConfigNeedEngineUpdate.flags &
1129 GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
1130 err = mLocApi->setSUPLVersionSync(gnssConfigRequested.suplVersion);
1131 if (index < count) {
1132 errsList[index] = err;
1133 }
1134 }
1135 index++;
1136 }
1137
1138 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
1139 if (gnssConfigNeedEngineUpdate.flags &
1140 GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
1141 err = mLocApi->setLPPConfigSync(gnssConfigRequested.lppProfileMask);
1142 if (index < count) {
1143 errsList[index] = err;
1144 }
1145 }
1146 index++;
1147 }
1148
1149 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1150 if (gnssConfigNeedEngineUpdate.flags &
1151 GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1152 err = mLocApi->setLPPeProtocolCpSync(
1153 gnssConfigRequested.lppeControlPlaneMask);
1154 if (index < count) {
1155 errsList[index] = err;
1156 }
1157 }
1158 index++;
1159 }
1160
1161 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1162 if (gnssConfigNeedEngineUpdate.flags &
1163 GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1164 err = mLocApi->setLPPeProtocolUpSync(
1165 gnssConfigRequested.lppeUserPlaneMask);
1166 if (index < count) {
1167 errsList[index] = err;
1168 }
1169 }
1170 index++;
1171 }
1172
1173 if (gnssConfigRequested.flags &
1174 GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1175 if (gnssConfigNeedEngineUpdate.flags &
1176 GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1177 err = mLocApi->setAGLONASSProtocolSync(
1178 gnssConfigRequested.aGlonassPositionProtocolMask);
1179 if (index < count) {
1180 errsList[index] = err;
1181 }
1182 }
1183 index++;
1184 }
1185 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
1186 // Check if feature is supported
1187 if (!ContextBase::isFeatureSupported(
1188 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1189 LOC_LOGe("Feature constellation enablement not supported.");
1190 err = LOCATION_ERROR_NOT_SUPPORTED;
1191 } else {
1192 // Send the SV ID Config to Modem
1193 mBlacklistedSvIds.assign(gnssConfigRequested.blacklistedSvIds.begin(),
1194 gnssConfigRequested.blacklistedSvIds.end());
1195 err = gnssSvIdConfigUpdateSync(gnssConfigRequested.blacklistedSvIds);
1196 if (LOCATION_ERROR_SUCCESS != err) {
1197 LOC_LOGe("Failed to send config to modem, err %d", err);
1198 }
1199 }
1200 if (index < count) {
1201 errsList[index] = err;
1202 }
1203 index++;
1204 }
1205 if (gnssConfigRequested.flags &
1206 GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
1207 if (gnssConfigNeedEngineUpdate.flags &
1208 GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
1209 err = mLocApi->setEmergencyExtensionWindowSync(
1210 gnssConfigRequested.emergencyExtensionSeconds);
1211 if (index < count) {
1212 errsList[index] = err;
1213 }
1214 }
1215 index++;
1216 }
1217
1218 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT) {
1219 GnssConfig gnssConfig = {};
1220 gnssConfig.flags = GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT;
1221 gnssConfig.minSvElevation = gnssConfigRequested.minSvElevation;
1222 err = mLocApi->setParameterSync(gnssConfig);
1223 if (index < count) {
1224 errsList[index] = err;
1225 }
1226 index++;
1227 }
1228
1229 return errsList;
1230}
1231
1232uint32_t*
1233GnssAdapter::gnssUpdateConfigCommand(const GnssConfig& config)
1234{
1235 // count the number of bits set
1236 GnssConfigFlagsMask flagsCopy = config.flags;
1237 size_t count = 0;
1238 while (flagsCopy > 0) {
1239 if (flagsCopy & 1) {
1240 count++;
1241 }
1242 flagsCopy >>= 1;
1243 }
1244 std::string idsString = "[";
1245 uint32_t* ids = NULL;
1246 if (count > 0) {
1247 ids = new uint32_t[count];
1248 if (ids == nullptr) {
1249 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
1250 return nullptr;
1251 }
1252 for (size_t i=0; i < count; ++i) {
1253 ids[i] = generateSessionId();
1254 IF_LOC_LOGD {
1255 idsString += std::to_string(ids[i]) + " ";
1256 }
1257 }
1258 }
1259 idsString += "]";
1260
1261 LOC_LOGD("%s]: ids %s flags 0x%X", __func__, idsString.c_str(), config.flags);
1262
1263 struct MsgGnssUpdateConfig : public LocMsg {
1264 GnssAdapter& mAdapter;
1265 LocApiBase& mApi;
1266 GnssConfig mConfig;
1267 size_t mCount;
1268 uint32_t* mIds;
1269 inline MsgGnssUpdateConfig(GnssAdapter& adapter,
1270 LocApiBase& api,
1271 GnssConfig config,
1272 uint32_t* ids,
1273 size_t count) :
1274 LocMsg(),
1275 mAdapter(adapter),
1276 mApi(api),
1277 mConfig(config),
1278 mCount(count),
1279 mIds(nullptr) {
1280 if (mCount > 0) {
1281 mIds = new uint32_t[count];
1282 if (mIds) {
1283 for (uint32_t index = 0; index < count; index++) {
1284 mIds[index] = ids[index];
1285 }
1286 } else {
1287 LOC_LOGe("memory allocation for mIds failed");
1288 }
1289 }
1290 }
1291
1292 inline MsgGnssUpdateConfig(const MsgGnssUpdateConfig& obj) :
1293 MsgGnssUpdateConfig(obj.mAdapter, obj.mApi, obj.mConfig,
1294 obj.mIds, obj.mCount) {}
1295
1296 inline virtual ~MsgGnssUpdateConfig()
1297 {
1298 if (nullptr != mIds) delete[] mIds;
1299 }
1300
1301 inline virtual void proc() const {
1302 if (!mAdapter.isEngineCapabilitiesKnown()) {
1303 mAdapter.mPendingMsgs.push_back(new MsgGnssUpdateConfig(*this));
1304 return;
1305 }
1306 GnssAdapter& adapter = mAdapter;
1307 size_t countOfConfigs = mCount;
1308 GnssConfig gnssConfigRequested = mConfig;
1309 GnssConfig gnssConfigNeedEngineUpdate = mConfig;
1310
1311 std::vector<uint32_t> sessionIds;
1312 sessionIds.assign(mIds, mIds + mCount);
1313 std::vector<LocationError> errs(mCount, LOCATION_ERROR_SUCCESS);
1314 int index = 0;
1315 bool needSuspendResume = false;
1316
1317 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
1318 GnssConfigGpsLock newGpsLock = gnssConfigRequested.gpsLock;
1319
1320 newGpsLock |= GNSS_CONFIG_GPS_LOCK_MO;
1321 ContextBase::mGps_conf.GPS_LOCK = newGpsLock;
1322 /* If we get here it means that the changes in the framework to request for
1323 'P' behavior were made, and therefore we need to "behave" as in 'P'
1324 However, we need to determine if enableCommand function has already been
1325 called, since it could get called before this function.*/
1326 if (0 != mAdapter.getAfwControlId()) {
1327 /* enableCommand function has already been called since getAfwControlId
1328 returns non zero. Now there are two possible cases:
1329 1. This is the first time this function is called
1330 (mSupportNfwControl is true). We need to behave as in 'P', but
1331 for the first time, meaning MO was enabled, but NI was not, so
1332 we need to unlock NI
1333 2. This is not the first time this function is called, meaning we
1334 are already behaving as in 'P'. No need to update the configuration
1335 in this case (return to 'P' code) */
1336 if (mAdapter.mSupportNfwControl) {
1337 // case 1 above
1338 newGpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
1339 } else {
1340 // case 2 above
1341 gnssConfigNeedEngineUpdate.flags &= ~(GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT);
1342 }
1343 }
1344 gnssConfigRequested.gpsLock = newGpsLock;
1345 mAdapter.mSupportNfwControl = false;
1346 index++;
1347 }
1348 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
1349 uint32_t newSuplVersion =
1350 mAdapter.convertSuplVersion(gnssConfigRequested.suplVersion);
1351 ContextBase::mGps_conf.SUPL_VER = newSuplVersion;
1352 index++;
1353 }
1354 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
1355 if (GNSS_ASSISTANCE_TYPE_SUPL == mConfig.assistanceServer.type) {
1356 mAdapter.setSuplHostServer(mConfig.assistanceServer.hostName,
1357 mConfig.assistanceServer.port,
1358 LOC_AGPS_SUPL_SERVER);
1359 } else {
1360 LOC_LOGE("%s]: Not a valid gnss assistance type %u",
1361 __func__, mConfig.assistanceServer.type);
1362 errs.at(index) = LOCATION_ERROR_INVALID_PARAMETER;
1363 gnssConfigNeedEngineUpdate.flags &=
1364 ~(GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT);
1365 }
1366 index++;
1367 }
1368 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
1369 uint32_t newLppProfileMask = gnssConfigRequested.lppProfileMask;
1370 ContextBase::mGps_conf.LPP_PROFILE = newLppProfileMask;
1371 index++;
1372 }
1373 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1374 uint32_t newLppeControlPlaneMask =
1375 mAdapter.convertLppeCp(gnssConfigRequested.lppeControlPlaneMask);
1376 ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY = newLppeControlPlaneMask;
1377 index++;
1378 }
1379 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1380 uint32_t newLppeUserPlaneMask =
1381 mAdapter.convertLppeUp(gnssConfigRequested.lppeUserPlaneMask);
1382 ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY = newLppeUserPlaneMask;
1383 index++;
1384 }
1385 if (gnssConfigRequested.flags &
1386 GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1387 uint32_t newAGloProtMask =
1388 mAdapter.convertAGloProt(gnssConfigRequested.aGlonassPositionProtocolMask);
1389 ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT = newAGloProtMask;
1390 index++;
1391 }
1392 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
1393 uint32_t newEP4ES = mAdapter.convertEP4ES(
1394 gnssConfigRequested.emergencyPdnForEmergencySupl);
1395 if (newEP4ES != ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
1396 ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = newEP4ES;
1397 }
1398 index++;
1399 }
1400 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
1401 uint32_t newSuplEs = mAdapter.convertSuplEs(
1402 gnssConfigRequested.suplEmergencyServices);
1403 if (newSuplEs != ContextBase::mGps_conf.SUPL_ES) {
1404 ContextBase::mGps_conf.SUPL_ES = newSuplEs;
1405 }
1406 index++;
1407 }
1408 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
1409 uint32_t newSuplMode = mAdapter.convertSuplMode(gnssConfigRequested.suplModeMask);
1410 ContextBase::mGps_conf.SUPL_MODE = newSuplMode;
1411 mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
1412 index++;
1413 }
1414
1415 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT) {
1416 needSuspendResume = true;
1417 index++;
1418 }
1419
1420 if (needSuspendResume == true) {
1421 mAdapter.suspendSessions();
1422 }
1423 LocApiCollectiveResponse *configCollectiveResponse = new LocApiCollectiveResponse(
1424 *adapter.getContext(),
1425 [&adapter, sessionIds, countOfConfigs] (std::vector<LocationError> errs) {
1426
1427 std::vector<uint32_t> ids(sessionIds);
1428 adapter.reportResponse(countOfConfigs, errs.data(), ids.data());
1429 });
1430
1431 std::string moServerUrl = adapter.getMoServerUrl();
1432 std::string serverUrl = adapter.getServerUrl();
1433 mApi.sendMsg(new LocApiMsg(
1434 [&adapter, gnssConfigRequested, gnssConfigNeedEngineUpdate,
1435 moServerUrl, serverUrl, countOfConfigs, configCollectiveResponse,
1436 errs] () mutable {
1437 std::vector<LocationError> errsList = adapter.gnssUpdateConfig("",
1438 moServerUrl, serverUrl,
1439 gnssConfigRequested, gnssConfigNeedEngineUpdate, countOfConfigs);
1440
1441 configCollectiveResponse->returnToSender(errsList);
1442 }));
1443
1444 if (needSuspendResume == true) {
1445 mAdapter.restartSessions();
1446 }
1447 }
1448 };
1449
1450 if (NULL != ids) {
1451 sendMsg(new MsgGnssUpdateConfig(*this, *mLocApi, config, ids, count));
1452 } else {
1453 LOC_LOGE("%s]: No GNSS config items to update", __func__);
1454 }
1455
1456 return ids;
1457}
1458
1459void
1460GnssAdapter::gnssSvIdConfigUpdate(const std::vector<GnssSvIdSource>& blacklistedSvIds)
1461{
1462 // Clear the existing config
1463 memset(&mGnssSvIdConfig, 0, sizeof(GnssSvIdConfig));
1464
1465 // Convert the sv id lists to masks
1466 bool convertSuccess = convertToGnssSvIdConfig(blacklistedSvIds, mGnssSvIdConfig);
1467
1468 // Now send to Modem if conversion successful
1469 if (convertSuccess) {
1470 gnssSvIdConfigUpdate();
1471 } else {
1472 LOC_LOGe("convertToGnssSvIdConfig failed");
1473 }
1474}
1475
1476void
1477GnssAdapter::gnssSvIdConfigUpdate()
1478{
1479 LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1480 ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
1481 mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
1482 mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
1483 mGnssSvIdConfig.sbasBlacklistSvMask, mGnssSvIdConfig.navicBlacklistSvMask);
1484 // Now set required blacklisted SVs
1485 mLocApi->setBlacklistSv(mGnssSvIdConfig);
1486}
1487
1488LocationError
1489GnssAdapter::gnssSvIdConfigUpdateSync(const std::vector<GnssSvIdSource>& blacklistedSvIds)
1490{
1491 // Clear the existing config
1492 memset(&mGnssSvIdConfig, 0, sizeof(GnssSvIdConfig));
1493
1494 // Convert the sv id lists to masks
1495 convertToGnssSvIdConfig(blacklistedSvIds, mGnssSvIdConfig);
1496
1497 // Now send to Modem
1498 return gnssSvIdConfigUpdateSync();
1499}
1500
1501LocationError
1502GnssAdapter::gnssSvIdConfigUpdateSync()
1503{
1504 LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1505 ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
1506 mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
1507 mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
1508 mGnssSvIdConfig.sbasBlacklistSvMask, mGnssSvIdConfig.navicBlacklistSvMask);
1509
1510 // Now set required blacklisted SVs
1511 return mLocApi->setBlacklistSvSync(mGnssSvIdConfig);
1512}
1513
1514void
1515GnssAdapter::gnssSecondaryBandConfigUpdate(LocApiResponse* locApiResponse)
1516{
1517 LOC_LOGd("secondary band config, size %d, enabled constellation 0x%" PRIx64 ","
1518 "disabled constellation 0x%" PRIx64 "", mGnssSeconaryBandConfig.size,
1519 mGnssSeconaryBandConfig.enabledSvTypesMask,
1520 mGnssSeconaryBandConfig.blacklistedSvTypesMask);
1521 if (mGnssSeconaryBandConfig.size == sizeof(mGnssSeconaryBandConfig)) {
1522 // Now set required secondary band config
1523 mLocApi->configConstellationMultiBand(mGnssSeconaryBandConfig, locApiResponse);
1524 }
1525}
1526
1527uint32_t*
1528GnssAdapter::gnssGetConfigCommand(GnssConfigFlagsMask configMask) {
1529
1530 // count the number of bits set
1531 GnssConfigFlagsMask flagsCopy = configMask;
1532 size_t count = 0;
1533 while (flagsCopy > 0) {
1534 if (flagsCopy & 1) {
1535 count++;
1536 }
1537 flagsCopy >>= 1;
1538 }
1539 std::string idsString = "[";
1540 uint32_t* ids = NULL;
1541 if (count > 0) {
1542 ids = new uint32_t[count];
1543 if (nullptr == ids) {
1544 LOC_LOGe("new allocation failed, fatal error.");
1545 return nullptr;
1546 }
1547 for (size_t i=0; i < count; ++i) {
1548 ids[i] = generateSessionId();
1549 IF_LOC_LOGD {
1550 idsString += std::to_string(ids[i]) + " ";
1551 }
1552 }
1553 }
1554 idsString += "]";
1555
1556 LOC_LOGd("ids %s flags 0x%X", idsString.c_str(), configMask);
1557
1558 struct MsgGnssGetConfig : public LocMsg {
1559 GnssAdapter& mAdapter;
1560 LocApiBase& mApi;
1561 GnssConfigFlagsMask mConfigMask;
1562 uint32_t* mIds;
1563 size_t mCount;
1564 inline MsgGnssGetConfig(GnssAdapter& adapter,
1565 LocApiBase& api,
1566 GnssConfigFlagsMask configMask,
1567 uint32_t* ids,
1568 size_t count) :
1569 LocMsg(),
1570 mAdapter(adapter),
1571 mApi(api),
1572 mConfigMask(configMask),
Albert Ib8416c92021-06-25 19:34:31 +08001573 mIds(nullptr),
1574 mCount(count) {
Michael Bestas3a0209e2023-05-04 01:15:47 +03001575 if (mCount > 0) {
1576 mIds = new uint32_t[count];
1577 if (mIds) {
1578 for (uint32_t index = 0; index < count; index++) {
1579 mIds[index] = ids[index];
1580 }
1581 } else {
1582 LOC_LOGe("memory allocation for mIds failed");
1583 }
1584 }
1585 }
1586
1587 inline MsgGnssGetConfig(const MsgGnssGetConfig& obj) :
1588 MsgGnssGetConfig(obj.mAdapter, obj.mApi, obj.mConfigMask,
1589 obj.mIds, obj.mCount) {}
1590
1591 inline virtual ~MsgGnssGetConfig()
1592 {
1593 if (nullptr != mIds) delete[] mIds;
1594 }
1595 inline virtual void proc() const {
1596 if (!mAdapter.isEngineCapabilitiesKnown()) {
1597 mAdapter.mPendingMsgs.push_back(new MsgGnssGetConfig(*this));
1598 return;
1599 }
1600 LocationError* errs = new LocationError[mCount];
1601 LocationError err = LOCATION_ERROR_SUCCESS;
1602 uint32_t index = 0;
1603
1604 if (nullptr == errs) {
1605 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
1606 return;
1607 }
1608
1609 if (mConfigMask & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
1610 if (index < mCount) {
1611 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1612 }
1613 }
1614 if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
1615 if (index < mCount) {
1616 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1617 }
1618 }
1619 if (mConfigMask & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
1620 if (index < mCount) {
1621 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1622 }
1623 }
1624 if (mConfigMask & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
1625 if (index < mCount) {
1626 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1627 }
1628 }
1629 if (mConfigMask & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1630 if (index < mCount) {
1631 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1632 }
1633 }
1634 if (mConfigMask & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1635 if (index < mCount) {
1636 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1637 }
1638 }
1639 if (mConfigMask & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1640 if (index < mCount) {
1641 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1642 }
1643 }
1644 if (mConfigMask & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
1645 if (index < mCount) {
1646 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1647 }
1648 }
1649 if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
1650 if (index < mCount) {
1651 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1652 }
1653 }
1654 if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
1655 err = LOCATION_ERROR_NOT_SUPPORTED;
1656 if (index < mCount) {
1657 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1658 }
1659 }
1660 if (mConfigMask & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
1661 // Check if feature is supported
1662 if (!ContextBase::isFeatureSupported(
1663 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1664 LOC_LOGe("Feature not supported.");
1665 err = LOCATION_ERROR_NOT_SUPPORTED;
1666 } else {
1667 // Send request to Modem to fetch the config
1668 mApi.getBlacklistSv();
1669 err = LOCATION_ERROR_SUCCESS;
1670 }
1671 if (index < mCount) {
1672 errs[index++] = err;
1673 }
1674 }
1675 if (mConfigMask & GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
1676 err = LOCATION_ERROR_NOT_SUPPORTED;
1677 if (index < mCount) {
1678 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1679 }
1680 }
1681 if (mConfigMask & GNSS_CONFIG_FLAGS_ROBUST_LOCATION_BIT) {
1682 uint32_t sessionId = *(mIds+index);
1683 LocApiResponse* locApiResponse =
1684 new LocApiResponse(*mAdapter.getContext(),
1685 [this, sessionId] (LocationError err) {
1686 mAdapter.reportResponse(err, sessionId);});
1687 if (!locApiResponse) {
1688 LOC_LOGe("memory alloc failed");
1689 mAdapter.reportResponse(LOCATION_ERROR_GENERAL_FAILURE, sessionId);
1690 } else {
1691 mApi.getRobustLocationConfig(sessionId, locApiResponse);
1692 }
1693 }
1694
1695 if (mConfigMask & GNSS_CONFIG_FLAGS_MIN_GPS_WEEK_BIT) {
1696 uint32_t sessionId = *(mIds+index);
1697 LocApiResponse* locApiResponse =
1698 new LocApiResponse(*mAdapter.getContext(),
1699 [this, sessionId] (LocationError err) {
1700 mAdapter.reportResponse(err, sessionId);});
1701 if (!locApiResponse) {
1702 LOC_LOGe("memory alloc failed");
1703 mAdapter.reportResponse(LOCATION_ERROR_GENERAL_FAILURE, sessionId);
1704 } else {
1705 mApi.getMinGpsWeek(sessionId, locApiResponse);
1706 }
1707 }
1708
1709 if (mConfigMask & GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT) {
1710 uint32_t sessionId = *(mIds+index);
1711 LocApiResponse* locApiResponse =
1712 new LocApiResponse(*mAdapter.getContext(),
1713 [this, sessionId] (LocationError err) {
1714 mAdapter.reportResponse(err, sessionId);});
1715 if (!locApiResponse) {
1716 LOC_LOGe("memory alloc failed");
1717 mAdapter.reportResponse(LOCATION_ERROR_GENERAL_FAILURE, sessionId);
1718 } else {
1719 mApi.getParameter(sessionId, GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT,
1720 locApiResponse);
1721 }
1722 }
1723
1724 mAdapter.reportResponse(index, errs, mIds);
1725 delete[] errs;
1726
1727 }
1728 };
1729
1730 if (NULL != ids) {
1731 sendMsg(new MsgGnssGetConfig(*this, *mLocApi, configMask, ids, count));
1732 } else {
1733 LOC_LOGe("No GNSS config items to Get");
1734 }
1735
1736 return ids;
1737}
1738
1739bool
1740GnssAdapter::convertToGnssSvIdConfig(
1741 const std::vector<GnssSvIdSource>& blacklistedSvIds, GnssSvIdConfig& config)
1742{
1743 bool retVal = false;
1744 config.size = sizeof(GnssSvIdConfig);
1745
1746 // Empty vector => Clear any previous blacklisted SVs
1747 if (0 == blacklistedSvIds.size()) {
1748 config.gloBlacklistSvMask = 0;
1749 config.bdsBlacklistSvMask = 0;
1750 config.qzssBlacklistSvMask = 0;
1751 config.galBlacklistSvMask = 0;
1752 config.sbasBlacklistSvMask = 0;
1753 config.navicBlacklistSvMask = 0;
1754 retVal = true;
1755 } else {
1756 // Parse the vector and convert SV IDs to mask values
1757 for (GnssSvIdSource source : blacklistedSvIds) {
1758 uint64_t* svMaskPtr = NULL;
1759 GnssSvId initialSvId = 0;
1760 uint16_t svIndexOffset = 0;
1761 switch(source.constellation) {
1762 case GNSS_SV_TYPE_GLONASS:
1763 svMaskPtr = &config.gloBlacklistSvMask;
1764 initialSvId = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID;
1765 break;
1766 case GNSS_SV_TYPE_BEIDOU:
1767 svMaskPtr = &config.bdsBlacklistSvMask;
1768 initialSvId = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID;
1769 break;
1770 case GNSS_SV_TYPE_QZSS:
1771 svMaskPtr = &config.qzssBlacklistSvMask;
1772 initialSvId = GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID;
1773 break;
1774 case GNSS_SV_TYPE_GALILEO:
1775 svMaskPtr = &config.galBlacklistSvMask;
1776 initialSvId = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID;
1777 break;
1778 case GNSS_SV_TYPE_SBAS:
1779 // SBAS does not support enable/disable whole constellation
1780 // so do not set up svTypeMask for SBAS
1781 svMaskPtr = &config.sbasBlacklistSvMask;
1782 // SBAS currently has two ranges, [120, 158] and [183, 191]
1783 if (0 == source.svId) {
1784 LOC_LOGd("blacklist all SBAS SV");
1785 } else if (source.svId >= GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID) {
1786 // handle SV id in range [183, 191]
1787 initialSvId = GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID;
1788 svIndexOffset = GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH;
1789 } else if ((source.svId >= GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID) &&
1790 (source.svId < (GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID +
1791 GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH))){
1792 // handle SV id in range of [120, 158]
1793 initialSvId = GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID;
1794 } else {
1795 LOC_LOGe("invalid SBAS sv id %d", source.svId);
1796 svMaskPtr = nullptr;
1797 }
1798 break;
1799 case GNSS_SV_TYPE_NAVIC:
1800 svMaskPtr = &config.navicBlacklistSvMask;
1801 initialSvId = GNSS_SV_CONFIG_NAVIC_INITIAL_SV_ID;
1802 break;
1803 default:
1804 break;
1805 }
1806
1807 if (NULL == svMaskPtr) {
1808 LOC_LOGe("Invalid constellation %d", source.constellation);
1809 } else {
1810 // SV ID 0 = All SV IDs
1811 if (0 == source.svId) {
1812 *svMaskPtr = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1813 } else if (source.svId < initialSvId || source.svId >= initialSvId + 64) {
1814 LOC_LOGe("Invalid sv id %d for sv type %d",
1815 source.svId, source.constellation);
1816 } else {
1817 uint32_t shiftCnt = source.svId + svIndexOffset - initialSvId;
1818 *svMaskPtr |= (1ULL << shiftCnt);
1819 }
1820 }
1821 }
1822
1823 // Return true if any one source is valid
1824 if (0 != config.gloBlacklistSvMask ||
1825 0 != config.bdsBlacklistSvMask ||
1826 0 != config.galBlacklistSvMask ||
1827 0 != config.qzssBlacklistSvMask ||
1828 0 != config.sbasBlacklistSvMask ||
1829 0 != config.navicBlacklistSvMask) {
1830 retVal = true;
1831 }
1832 }
1833
1834 LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1835 ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
1836 config.bdsBlacklistSvMask, config.gloBlacklistSvMask,
1837 config.qzssBlacklistSvMask, config.galBlacklistSvMask,
1838 config.sbasBlacklistSvMask, config.navicBlacklistSvMask);
1839
1840 return retVal;
1841}
1842
1843void GnssAdapter::convertFromGnssSvIdConfig(
1844 const GnssSvIdConfig& svConfig, std::vector<GnssSvIdSource>& blacklistedSvIds)
1845{
1846 // Convert blacklisted SV mask values to vectors
1847 if (svConfig.bdsBlacklistSvMask) {
1848 convertGnssSvIdMaskToList(
1849 svConfig.bdsBlacklistSvMask, blacklistedSvIds,
1850 GNSS_SV_CONFIG_BDS_INITIAL_SV_ID, GNSS_SV_TYPE_BEIDOU);
1851 }
1852 if (svConfig.galBlacklistSvMask) {
1853 convertGnssSvIdMaskToList(
1854 svConfig.galBlacklistSvMask, blacklistedSvIds,
1855 GNSS_SV_CONFIG_GAL_INITIAL_SV_ID, GNSS_SV_TYPE_GALILEO);
1856 }
1857 if (svConfig.gloBlacklistSvMask) {
1858 convertGnssSvIdMaskToList(
1859 svConfig.gloBlacklistSvMask, blacklistedSvIds,
1860 GNSS_SV_CONFIG_GLO_INITIAL_SV_ID, GNSS_SV_TYPE_GLONASS);
1861 }
1862 if (svConfig.qzssBlacklistSvMask) {
1863 convertGnssSvIdMaskToList(
1864 svConfig.qzssBlacklistSvMask, blacklistedSvIds,
1865 GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID, GNSS_SV_TYPE_QZSS);
1866 }
1867 if (svConfig.sbasBlacklistSvMask) {
1868 // SBAS - SV 120 to 158, maps to 0 to 38
1869 // SV 183 to 191, maps to 39 to 47
1870 uint64_t sbasBlacklistSvMask = svConfig.sbasBlacklistSvMask;
1871 // operate on 120 and 158 first
1872 sbasBlacklistSvMask <<= (64 - GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH);
1873 sbasBlacklistSvMask >>= (64 - GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH);
1874 convertGnssSvIdMaskToList(
1875 sbasBlacklistSvMask, blacklistedSvIds,
1876 GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID, GNSS_SV_TYPE_SBAS);
1877 // operate on the second range
1878 sbasBlacklistSvMask = svConfig.sbasBlacklistSvMask;
1879 sbasBlacklistSvMask >>= GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH;
1880 convertGnssSvIdMaskToList(
1881 sbasBlacklistSvMask, blacklistedSvIds,
1882 GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID, GNSS_SV_TYPE_SBAS);
1883 }
1884 if (svConfig.navicBlacklistSvMask) {
1885 convertGnssSvIdMaskToList(
1886 svConfig.navicBlacklistSvMask, blacklistedSvIds,
1887 GNSS_SV_CONFIG_NAVIC_INITIAL_SV_ID, GNSS_SV_TYPE_NAVIC);
1888 }
1889}
1890
1891void GnssAdapter::convertGnssSvIdMaskToList(
1892 uint64_t svIdMask, std::vector<GnssSvIdSource>& svIds,
1893 GnssSvId initialSvId, GnssSvType svType)
1894{
1895 GnssSvIdSource source = {};
1896 source.size = sizeof(GnssSvIdSource);
1897 source.constellation = svType;
1898
1899 // SV ID 0 => All SV IDs in mask
1900 if (GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK == svIdMask) {
1901 LOC_LOGd("blacklist all SVs in constellation %d", source.constellation);
1902 source.svId = 0;
1903 svIds.push_back(source);
1904 return;
1905 }
1906
1907 // Convert each bit in svIdMask to vector entry
1908 uint32_t bitNumber = 0;
1909 while (svIdMask > 0) {
1910 if (svIdMask & 0x1) {
1911 source.svId = bitNumber + initialSvId;
1912 // SBAS has two ranges:
1913 // SBAS - SV 120 to 158, maps to 0 to 38
1914 // SV 183 to 191, maps to 39 to 47
1915 // #define GNSS_SV_CONFIG_SBAS_INITIAL_SV_ID 120
1916 // #define GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH 39
1917 // #define GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID 183
1918 if (svType == GNSS_SV_TYPE_SBAS) {
1919 if (bitNumber >= GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH) {
1920 source.svId = bitNumber - GNSS_SV_CONFIG_SBAS_INITIAL_SV_LENGTH +
1921 GNSS_SV_CONFIG_SBAS_INITIAL2_SV_ID;
1922 }
1923 }
1924 svIds.push_back(source);
1925 }
1926 bitNumber++;
1927 svIdMask >>= 1;
1928 }
1929}
1930
1931void GnssAdapter::reportGnssSvIdConfigEvent(const GnssSvIdConfig& config)
1932{
1933 struct MsgReportGnssSvIdConfig : public LocMsg {
1934 GnssAdapter& mAdapter;
1935 const GnssSvIdConfig mConfig;
1936 inline MsgReportGnssSvIdConfig(GnssAdapter& adapter,
1937 const GnssSvIdConfig& config) :
1938 LocMsg(),
1939 mAdapter(adapter),
1940 mConfig(config) {}
1941 inline virtual void proc() const {
1942 mAdapter.reportGnssSvIdConfig(mConfig);
1943 }
1944 };
1945
1946 sendMsg(new MsgReportGnssSvIdConfig(*this, config));
1947}
1948
1949void GnssAdapter::reportGnssSvIdConfig(const GnssSvIdConfig& svIdConfig)
1950{
1951 GnssConfig config = {};
1952 config.size = sizeof(GnssConfig);
1953
1954 // Invoke control clients config callback
1955 if (nullptr != mControlCallbacks.gnssConfigCb &&
1956 svIdConfig.size == sizeof(GnssSvIdConfig)) {
1957
1958 convertFromGnssSvIdConfig(svIdConfig, config.blacklistedSvIds);
1959 if (config.blacklistedSvIds.size() > 0) {
1960 config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
1961 }
1962 LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64 ", "
1963 "qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", navic 0x%" PRIx64,
1964 svIdConfig.bdsBlacklistSvMask, svIdConfig.gloBlacklistSvMask,
1965 svIdConfig.qzssBlacklistSvMask, svIdConfig.galBlacklistSvMask,
1966 svIdConfig.sbasBlacklistSvMask, svIdConfig.navicBlacklistSvMask);
1967 // use 0 session id to indicate that receiver does not yet care about session id
1968 mControlCallbacks.gnssConfigCb(0, config);
1969 } else {
1970 LOC_LOGe("Failed to report, size %d", (uint32_t)config.size);
1971 }
1972}
1973
1974void
1975GnssAdapter::gnssUpdateSvTypeConfigCommand(GnssSvTypeConfig config)
1976{
1977 struct MsgGnssUpdateSvTypeConfig : public LocMsg {
1978 GnssAdapter* mAdapter;
1979 LocApiBase* mApi;
1980 GnssSvTypeConfig mConfig;
1981 inline MsgGnssUpdateSvTypeConfig(
1982 GnssAdapter* adapter,
1983 LocApiBase* api,
1984 GnssSvTypeConfig& config) :
1985 LocMsg(),
1986 mAdapter(adapter),
1987 mApi(api),
1988 mConfig(config) {}
1989 inline virtual void proc() const {
1990 if (!mAdapter->isEngineCapabilitiesKnown()) {
1991 mAdapter->mPendingMsgs.push_back(new MsgGnssUpdateSvTypeConfig(*this));
1992 return;
1993 }
1994 // Check if feature is supported
1995 if (!ContextBase::isFeatureSupported(
1996 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1997 LOC_LOGe("Feature not supported.");
1998 } else {
1999 // Send update request to modem
2000 mAdapter->gnssSvTypeConfigUpdate(mConfig);
2001 }
2002 }
2003 };
2004
2005 sendMsg(new MsgGnssUpdateSvTypeConfig(this, mLocApi, config));
2006}
2007
2008void
2009GnssAdapter::gnssSvTypeConfigUpdate(const GnssSvTypeConfig& config)
2010{
2011 // Gather bits removed from enabled mask
2012 GnssSvTypesMask enabledRemoved = mGnssSvTypeConfig.enabledSvTypesMask &
2013 (mGnssSvTypeConfig.enabledSvTypesMask ^ config.enabledSvTypesMask);
2014 // Send reset if any constellation is removed from the enabled list
2015 bool sendReset = (enabledRemoved != 0);
2016 // Save new config and update
2017 gnssSetSvTypeConfig(config);
2018 gnssSvTypeConfigUpdate(sendReset);
2019}
2020
2021void
2022GnssAdapter::gnssSvTypeConfigUpdate(bool sendReset)
2023{
2024 LOC_LOGd("size %" PRIu32" constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64
2025 ", sendReset %d",
2026 mGnssSvTypeConfig.size, mGnssSvTypeConfig.blacklistedSvTypesMask,
2027 mGnssSvTypeConfig.enabledSvTypesMask, sendReset);
2028
2029 LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
2030 ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", Navic 0x%" PRIx64,
2031 mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
2032 mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
2033 mGnssSvIdConfig.sbasBlacklistSvMask, mGnssSvIdConfig.navicBlacklistSvMask);
2034
2035 LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
2036 ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64 ", sbas 0x%" PRIx64 ", Navic 0x%" PRIx64,
2037 mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
2038 mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask,
2039 mGnssSvIdConfig.sbasBlacklistSvMask, mGnssSvIdConfig.navicBlacklistSvMask);
2040
2041 if (mGnssSvTypeConfig.size == sizeof(mGnssSvTypeConfig)) {
2042
2043 if (sendReset) {
2044 mLocApi->resetConstellationControl();
2045 }
2046
2047 GnssSvIdConfig blacklistConfig = {};
2048 // Revert to previously blacklisted SVs for each enabled constellation
2049 blacklistConfig = mGnssSvIdConfig;
2050 // Blacklist all SVs for each disabled constellation
2051 if (mGnssSvTypeConfig.blacklistedSvTypesMask) {
2052 if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_GLO_BIT) {
2053 blacklistConfig.gloBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
2054 }
2055 if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_BDS_BIT) {
2056 blacklistConfig.bdsBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
2057 }
2058 if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_QZSS_BIT) {
2059 blacklistConfig.qzssBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
2060 }
2061 if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_GAL_BIT) {
2062 blacklistConfig.galBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
2063 }
2064 if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_NAVIC_BIT) {
2065 blacklistConfig.navicBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
2066 }
2067 }
2068
2069 // Send blacklist info
2070 mLocApi->setBlacklistSv(blacklistConfig);
2071
2072 // Send only enabled constellation config
2073 if (mGnssSvTypeConfig.enabledSvTypesMask) {
2074 GnssSvTypeConfig svTypeConfig = {sizeof(GnssSvTypeConfig), 0, 0};
2075 svTypeConfig.enabledSvTypesMask = mGnssSvTypeConfig.enabledSvTypesMask;
2076 mLocApi->setConstellationControl(svTypeConfig);
2077 }
2078 }
2079}
2080
2081void
2082GnssAdapter::gnssGetSvTypeConfigCommand(GnssSvTypeConfigCallback callback)
2083{
2084 struct MsgGnssGetSvTypeConfig : public LocMsg {
2085 GnssAdapter* mAdapter;
2086 LocApiBase* mApi;
2087 GnssSvTypeConfigCallback mCallback;
2088 inline MsgGnssGetSvTypeConfig(
2089 GnssAdapter* adapter,
2090 LocApiBase* api,
2091 GnssSvTypeConfigCallback callback) :
2092 LocMsg(),
2093 mAdapter(adapter),
2094 mApi(api),
2095 mCallback(callback) {}
2096 inline virtual void proc() const {
2097 if (!mAdapter->isEngineCapabilitiesKnown()) {
2098 mAdapter->mPendingMsgs.push_back(new MsgGnssGetSvTypeConfig(*this));
2099 return;
2100 }
2101 if (!ContextBase::isFeatureSupported(
2102 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
2103 LOC_LOGe("Feature not supported.");
2104 } else {
2105 // Save the callback
2106 mAdapter->gnssSetSvTypeConfigCallback(mCallback);
2107 // Send GET request to modem
2108 mApi->getConstellationControl();
2109 }
2110 }
2111 };
2112
2113 sendMsg(new MsgGnssGetSvTypeConfig(this, mLocApi, callback));
2114}
2115
2116void
2117GnssAdapter::gnssResetSvTypeConfigCommand()
2118{
2119 struct MsgGnssResetSvTypeConfig : public LocMsg {
2120 GnssAdapter* mAdapter;
2121 LocApiBase* mApi;
2122 inline MsgGnssResetSvTypeConfig(
2123 GnssAdapter* adapter,
2124 LocApiBase* api) :
2125 LocMsg(),
2126 mAdapter(adapter),
2127 mApi(api) {}
2128 inline virtual void proc() const {
2129 if (!mAdapter->isEngineCapabilitiesKnown()) {
2130 mAdapter->mPendingMsgs.push_back(new MsgGnssResetSvTypeConfig(*this));
2131 return;
2132 }
2133 if (!ContextBase::isFeatureSupported(
2134 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
2135 LOC_LOGe("Feature not supported.");
2136 } else {
2137 // Reset constellation config
2138 mAdapter->gnssSetSvTypeConfig({sizeof(GnssSvTypeConfig), 0, 0});
2139 // Re-enforce SV blacklist config
2140 mAdapter->gnssSvIdConfigUpdate();
2141 // Send reset request to modem
2142 mApi->resetConstellationControl();
2143 }
2144 }
2145 };
2146
2147 sendMsg(new MsgGnssResetSvTypeConfig(this, mLocApi));
2148}
2149
2150void GnssAdapter::reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& config)
2151{
2152 struct MsgReportGnssSvTypeConfig : public LocMsg {
2153 GnssAdapter& mAdapter;
2154 const GnssSvTypeConfig mConfig;
2155 inline MsgReportGnssSvTypeConfig(GnssAdapter& adapter,
2156 const GnssSvTypeConfig& config) :
2157 LocMsg(),
2158 mAdapter(adapter),
2159 mConfig(config) {}
2160 inline virtual void proc() const {
2161 mAdapter.reportGnssSvTypeConfig(mConfig);
2162 }
2163 };
2164
2165 sendMsg(new MsgReportGnssSvTypeConfig(*this, config));
2166}
2167
2168void GnssAdapter::reportGnssSvTypeConfig(const GnssSvTypeConfig& config)
2169{
2170 // Invoke Get SV Type Callback
2171 if (NULL != mGnssSvTypeConfigCb &&
2172 config.size == sizeof(GnssSvTypeConfig)) {
2173 LOC_LOGd("constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64,
2174 config.blacklistedSvTypesMask, config.enabledSvTypesMask);
2175 mGnssSvTypeConfigCb(config);
2176 } else {
2177 LOC_LOGe("Failed to report, size %d", (uint32_t)config.size);
2178 }
2179}
2180
2181void GnssAdapter::deleteAidingData(const GnssAidingData &data, uint32_t sessionId) {
2182 struct timespec bootDeleteAidingDataTime;
2183 int64_t bootDeleteTimeMs;
2184 if (clock_gettime(CLOCK_BOOTTIME, &bootDeleteAidingDataTime) == 0) {
2185 bootDeleteTimeMs = bootDeleteAidingDataTime.tv_sec * 1000000;
2186 int64_t diffTimeBFirSecDelete = bootDeleteTimeMs - mLastDeleteAidingDataTime;
2187 if (diffTimeBFirSecDelete > DELETE_AIDING_DATA_EXPECTED_TIME_MS) {
2188 mLocApi->deleteAidingData(data, new LocApiResponse(*getContext(),
2189 [this, sessionId] (LocationError err) {
2190 reportResponse(err, sessionId);
2191 }));
2192 mLastDeleteAidingDataTime = bootDeleteTimeMs;
2193 }
2194 }
2195}
2196
2197uint32_t
2198GnssAdapter::gnssDeleteAidingDataCommand(GnssAidingData& data)
2199{
2200 uint32_t sessionId = generateSessionId();
2201 LOC_LOGD("%s]: id %u", __func__, sessionId);
2202
2203 struct MsgDeleteAidingData : public LocMsg {
2204 GnssAdapter& mAdapter;
2205 uint32_t mSessionId;
2206 GnssAidingData mData;
2207 inline MsgDeleteAidingData(GnssAdapter& adapter,
2208 uint32_t sessionId,
2209 GnssAidingData& data) :
2210 LocMsg(),
2211 mAdapter(adapter),
2212 mSessionId(sessionId),
2213 mData(data) {}
2214 inline virtual void proc() const {
2215 if ((mData.posEngineMask & STANDARD_POSITIONING_ENGINE) != 0) {
2216 mAdapter.deleteAidingData(mData, mSessionId);
2217 SystemStatus* s = mAdapter.getSystemStatus();
2218 if ((nullptr != s) && (mData.deleteAll)) {
2219 s->setDefaultGnssEngineStates();
2220 }
2221 }
2222
2223 bool retVal = mAdapter.mEngHubProxy->gnssDeleteAidingData(mData);
2224 // When SPE engine is invoked, responseCb will be invoked
2225 // from QMI Loc API call.
2226 // When SPE engine is not invoked, we also need to deliver responseCb
2227 if ((mData.posEngineMask & STANDARD_POSITIONING_ENGINE) == 0) {
2228 LocationError err = LOCATION_ERROR_NOT_SUPPORTED;
2229 if (retVal == true) {
2230 err = LOCATION_ERROR_SUCCESS;
2231 }
2232 mAdapter.reportResponse(err, mSessionId);
2233 }
2234 }
2235 };
2236
2237 sendMsg(new MsgDeleteAidingData(*this, sessionId, data));
2238 return sessionId;
2239}
2240
2241void
2242GnssAdapter::gnssUpdateXtraThrottleCommand(const bool enabled)
2243{
2244 LOC_LOGD("%s] enabled:%d", __func__, enabled);
2245
2246 struct UpdateXtraThrottleMsg : public LocMsg {
2247 GnssAdapter& mAdapter;
2248 const bool mEnabled;
2249 inline UpdateXtraThrottleMsg(GnssAdapter& adapter, const bool enabled) :
2250 LocMsg(),
2251 mAdapter(adapter),
2252 mEnabled(enabled) {}
2253 inline virtual void proc() const {
2254 mAdapter.mXtraObserver.updateXtraThrottle(mEnabled);
2255 }
2256 };
2257
2258 sendMsg(new UpdateXtraThrottleMsg(*this, enabled));
2259}
2260
2261void
2262GnssAdapter::injectLocationCommand(double latitude, double longitude, float accuracy)
2263{
2264 LOC_LOGD("%s]: latitude %8.4f longitude %8.4f accuracy %8.4f",
2265 __func__, latitude, longitude, accuracy);
2266
2267 struct MsgInjectLocation : public LocMsg {
2268 LocApiBase& mApi;
2269 ContextBase& mContext;
2270 BlockCPIInfo& mBlockCPI;
2271 double mLatitude;
2272 double mLongitude;
2273 float mAccuracy;
2274 bool mOnDemandCpi;
2275 inline MsgInjectLocation(LocApiBase& api,
2276 ContextBase& context,
2277 BlockCPIInfo& blockCPIInfo,
2278 double latitude,
2279 double longitude,
2280 float accuracy,
2281 bool onDemandCpi) :
2282 LocMsg(),
2283 mApi(api),
2284 mContext(context),
2285 mBlockCPI(blockCPIInfo),
2286 mLatitude(latitude),
2287 mLongitude(longitude),
2288 mAccuracy(accuracy),
2289 mOnDemandCpi(onDemandCpi) {}
2290 inline virtual void proc() const {
2291 if ((uptimeMillis() <= mBlockCPI.blockedTillTsMs) &&
2292 (fabs(mLatitude-mBlockCPI.latitude) <= mBlockCPI.latLonDiffThreshold) &&
2293 (fabs(mLongitude-mBlockCPI.longitude) <= mBlockCPI.latLonDiffThreshold)) {
2294
2295 LOC_LOGD("%s]: positon injection blocked: lat: %f, lon: %f, accuracy: %f",
2296 __func__, mLatitude, mLongitude, mAccuracy);
2297
2298 } else {
2299 mApi.injectPosition(mLatitude, mLongitude, mAccuracy, mOnDemandCpi);
2300 }
2301 }
2302 };
2303
2304 sendMsg(new MsgInjectLocation(*mLocApi, *mContext, mBlockCPIInfo,
2305 latitude, longitude, accuracy, mOdcpiRequestActive));
2306}
2307
2308void
2309GnssAdapter::injectLocationExtCommand(const GnssLocationInfoNotification &locationInfo)
2310{
2311 LOC_LOGd("latitude %8.4f longitude %8.4f accuracy %8.4f, tech mask 0x%x",
2312 locationInfo.location.latitude, locationInfo.location.longitude,
2313 locationInfo.location.accuracy, locationInfo.location.techMask);
2314
2315 struct MsgInjectLocationExt : public LocMsg {
2316 LocApiBase& mApi;
2317 ContextBase& mContext;
2318 GnssLocationInfoNotification mLocationInfo;
2319 inline MsgInjectLocationExt(LocApiBase& api,
2320 ContextBase& context,
2321 GnssLocationInfoNotification locationInfo) :
2322 LocMsg(),
2323 mApi(api),
2324 mContext(context),
2325 mLocationInfo(locationInfo) {}
2326 inline virtual void proc() const {
2327 // false to indicate for none-ODCPI
2328 mApi.injectPosition(mLocationInfo, false);
2329 }
2330 };
2331
2332 sendMsg(new MsgInjectLocationExt(*mLocApi, *mContext, locationInfo));
2333}
2334
2335void
2336GnssAdapter::injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty)
2337{
2338 LOC_LOGD("%s]: time %lld timeReference %lld uncertainty %d",
2339 __func__, (long long)time, (long long)timeReference, uncertainty);
2340
2341 struct MsgInjectTime : public LocMsg {
2342 LocApiBase& mApi;
2343 ContextBase& mContext;
2344 int64_t mTime;
2345 int64_t mTimeReference;
2346 int32_t mUncertainty;
2347 inline MsgInjectTime(LocApiBase& api,
2348 ContextBase& context,
2349 int64_t time,
2350 int64_t timeReference,
2351 int32_t uncertainty) :
2352 LocMsg(),
2353 mApi(api),
2354 mContext(context),
2355 mTime(time),
2356 mTimeReference(timeReference),
2357 mUncertainty(uncertainty) {}
2358 inline virtual void proc() const {
2359 mApi.setTime(mTime, mTimeReference, mUncertainty);
2360 }
2361 };
2362
2363 sendMsg(new MsgInjectTime(*mLocApi, *mContext, time, timeReference, uncertainty));
2364}
2365
2366// This command is to called to block the position to be injected to the modem.
2367// This can happen for network position that comes from modem.
2368void
2369GnssAdapter::blockCPICommand(double latitude, double longitude,
2370 float accuracy, int blockDurationMsec,
2371 double latLonDiffThreshold)
2372{
2373 struct MsgBlockCPI : public LocMsg {
2374 BlockCPIInfo& mDstCPIInfo;
2375 BlockCPIInfo mSrcCPIInfo;
2376
2377 inline MsgBlockCPI(BlockCPIInfo& dstCPIInfo,
2378 BlockCPIInfo& srcCPIInfo) :
2379 mDstCPIInfo(dstCPIInfo),
2380 mSrcCPIInfo(srcCPIInfo) {}
2381 inline virtual void proc() const {
2382 // in the same hal thread, save the cpi to be blocked
2383 // the global variable
2384 mDstCPIInfo = mSrcCPIInfo;
2385 }
2386 };
2387
2388 // construct the new block CPI info and queue on the same thread
2389 // for processing
2390 BlockCPIInfo blockCPIInfo;
2391 blockCPIInfo.latitude = latitude;
2392 blockCPIInfo.longitude = longitude;
2393 blockCPIInfo.accuracy = accuracy;
2394 blockCPIInfo.blockedTillTsMs = uptimeMillis() + blockDurationMsec;
2395 blockCPIInfo.latLonDiffThreshold = latLonDiffThreshold;
2396
2397 LOC_LOGD("%s]: block CPI lat: %f, lon: %f ", __func__, latitude, longitude);
2398 // send a message to record down the coarse position
2399 // to be blocked from injection in the master copy (mBlockCPIInfo)
2400 sendMsg(new MsgBlockCPI(mBlockCPIInfo, blockCPIInfo));
2401}
2402
2403void
2404GnssAdapter::updateSystemPowerState(PowerStateType systemPowerState) {
2405 if (POWER_STATE_UNKNOWN != systemPowerState) {
2406 mSystemPowerState = systemPowerState;
2407 mLocApi->updateSystemPowerState(mSystemPowerState);
2408 }
2409}
2410
2411void
2412GnssAdapter::updateSystemPowerStateCommand(PowerStateType systemPowerState) {
2413 LOC_LOGd("power event %d", systemPowerState);
2414
2415 struct MsgUpdatePowerState : public LocMsg {
2416 GnssAdapter& mAdapter;
2417 PowerStateType mSystemPowerState;
2418
2419 inline MsgUpdatePowerState(GnssAdapter& adapter,
2420 PowerStateType systemPowerState) :
2421 LocMsg(),
2422 mAdapter(adapter),
2423 mSystemPowerState(systemPowerState) {}
2424 inline virtual void proc() const {
2425 mAdapter.updateSystemPowerState(mSystemPowerState);
2426 }
2427 };
2428
2429 sendMsg(new MsgUpdatePowerState(*this, systemPowerState));
2430}
2431
2432void
2433GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks)
2434{
2435 LOC_LOGD("%s]: client %p", __func__, client);
2436
2437 struct MsgAddClient : public LocMsg {
2438 GnssAdapter& mAdapter;
2439 LocationAPI* mClient;
2440 const LocationCallbacks mCallbacks;
2441 inline MsgAddClient(GnssAdapter& adapter,
2442 LocationAPI* client,
2443 const LocationCallbacks& callbacks) :
2444 LocMsg(),
2445 mAdapter(adapter),
2446 mClient(client),
2447 mCallbacks(callbacks) {}
2448 inline virtual void proc() const {
2449 // check whether we need to notify client of cached location system info
2450 mAdapter.notifyClientOfCachedLocationSystemInfo(mClient, mCallbacks);
2451 mAdapter.saveClient(mClient, mCallbacks);
2452 }
2453 };
2454
2455 sendMsg(new MsgAddClient(*this, client, callbacks));
2456}
2457
2458void
2459GnssAdapter::stopClientSessions(LocationAPI* client)
2460{
2461 LOC_LOGD("%s]: client %p", __func__, client);
2462
2463 /* Time-based Tracking */
2464 std::vector<LocationSessionKey> vTimeBasedTrackingClient;
2465 for (auto it : mTimeBasedTrackingSessions) {
2466 if (client == it.first.client) {
2467 vTimeBasedTrackingClient.emplace_back(it.first.client, it.first.id);
2468 }
2469 }
2470 for (auto key : vTimeBasedTrackingClient) {
2471 stopTimeBasedTrackingMultiplex(key.client, key.id);
2472 eraseTrackingSession(key.client, key.id);
2473 }
2474
2475 /* Distance-based Tracking */
2476 for (auto it = mDistanceBasedTrackingSessions.begin();
2477 it != mDistanceBasedTrackingSessions.end(); /* no increment here*/) {
2478 if (client == it->first.client) {
2479 mLocApi->stopDistanceBasedTracking(it->first.id, new LocApiResponse(*getContext(),
2480 [this, client, id=it->first.id] (LocationError err) {
2481 if (LOCATION_ERROR_SUCCESS == err) {
2482 eraseTrackingSession(client, id);
2483 }
2484 }
2485 ));
2486 }
2487 ++it; // increment only when not erasing an iterator
2488 }
2489
2490}
2491
2492void
2493GnssAdapter::updateClientsEventMask()
2494{
2495 // need to register for leap second info
2496 // for proper nmea generation
2497 LOC_API_ADAPTER_EVENT_MASK_T mask = LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO |
2498 LOC_API_ADAPTER_BIT_EVENT_REPORT_INFO;
2499 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2500 if (it->second.trackingCb != nullptr ||
2501 it->second.gnssLocationInfoCb != nullptr ||
2502 it->second.engineLocationsInfoCb != nullptr) {
2503 mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT;
2504 }
2505 if (it->second.gnssSvCb != nullptr) {
2506 mask |= LOC_API_ADAPTER_BIT_SATELLITE_REPORT;
2507 }
2508 if ((it->second.gnssNmeaCb != nullptr) && (mNmeaMask)) {
2509 mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT;
2510 }
2511 if (it->second.gnssMeasurementsCb != nullptr) {
2512 mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
2513 }
2514 if (it->second.gnssDataCb != nullptr) {
2515 mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT;
2516 mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT;
2517 updateNmeaMask(mNmeaMask | LOC_NMEA_MASK_DEBUG_V02);
2518 }
2519 }
2520
2521 /*
2522 ** For Automotive use cases we need to enable MEASUREMENT, POLY and EPHEMERIS
2523 ** when QDR is enabled (e.g.: either enabled via conf file or
2524 ** engine hub is loaded successfully).
2525 ** Note: this need to be called from msg queue thread.
2526 */
2527 if((1 == ContextBase::mGps_conf.EXTERNAL_DR_ENABLED) ||
2528 (true == initEngHubProxy())) {
2529 mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
2530 mask |= LOC_API_ADAPTER_BIT_GNSS_SV_POLYNOMIAL_REPORT;
2531 mask |= LOC_API_ADAPTER_BIT_PARSED_UNPROPAGATED_POSITION_REPORT;
2532 mask |= LOC_API_ADAPTER_BIT_GNSS_SV_EPHEMERIS_REPORT;
2533
2534 // Nhz measurement bit is set based on callback from loc eng hub
2535 // for Nhz engines.
2536 mask |= checkMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT);
2537
2538 LOC_LOGd("Auto usecase, Enable MEAS/POLY/EPHEMERIS - mask 0x%" PRIx64 "",
2539 mask);
2540 }
2541
2542 if (mAgpsManager.isRegistered()) {
2543 mask |= LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST;
2544 }
2545 // Add ODCPI handling
2546 if (nullptr != mOdcpiRequestCb) {
2547 mask |= LOC_API_ADAPTER_BIT_REQUEST_WIFI;
2548 }
2549
2550 // need to register for leap second info
2551 // for proper nmea generation
2552 mask |= LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO;
2553
2554 // always register for NI NOTIFY VERIFY to handle internally in HAL
2555 mask |= LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST;
2556
2557 // Enable the latency report
2558 if (mask & LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT) {
2559 if (mLogger.isLogEnabled()) {
2560 mask |= LOC_API_ADAPTER_BIT_LATENCY_INFORMATION;
2561 }
2562 }
2563
2564 updateEvtMask(mask, LOC_REGISTRATION_MASK_SET);
2565}
2566
2567void
2568GnssAdapter::handleEngineUpEvent()
2569{
2570 LOC_LOGD("%s]: ", __func__);
2571
2572 struct MsgHandleEngineUpEvent : public LocMsg {
2573 GnssAdapter& mAdapter;
2574 inline MsgHandleEngineUpEvent(GnssAdapter& adapter) :
2575 LocMsg(),
2576 mAdapter(adapter) {}
2577 virtual void proc() const {
2578 mAdapter.setEngineCapabilitiesKnown(true);
2579 mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
2580 // must be called only after capabilities are known
2581 mAdapter.setConfig();
2582 mAdapter.gnssSvIdConfigUpdate();
2583 mAdapter.gnssSvTypeConfigUpdate();
2584 mAdapter.updateSystemPowerState(mAdapter.getSystemPowerState());
2585 mAdapter.gnssSecondaryBandConfigUpdate();
2586 // start CDFW service
2587 mAdapter.initCDFWService();
2588 // restart sessions
2589 mAdapter.restartSessions(true);
2590 for (auto msg: mAdapter.mPendingMsgs) {
2591 mAdapter.sendMsg(msg);
2592 }
2593 mAdapter.mPendingMsgs.clear();
2594 }
2595 };
2596
2597 readConfigCommand();
2598 sendMsg(new MsgHandleEngineUpEvent(*this));
2599}
2600
2601void
2602GnssAdapter::restartSessions(bool modemSSR)
2603{
2604 LOC_LOGi(":enter");
2605
2606 if (modemSSR) {
2607 // odcpi session is no longer active after restart
2608 mOdcpiRequestActive = false;
2609 }
2610
2611 // SPE will be restarted now, so set this variable to false.
2612 mSPEAlreadyRunningAtHighestInterval = false;
2613
2614 if (false == mTimeBasedTrackingSessions.empty()) {
2615 // inform engine hub that GNSS session is about to start
2616 mEngHubProxy->gnssSetFixMode(mLocPositionMode);
2617 mEngHubProxy->gnssStartFix();
2618 checkUpdateDgnssNtrip(false);
2619 }
2620
2621 checkAndRestartSPESession();
2622}
2623
2624void GnssAdapter::checkAndRestartSPESession()
2625{
2626 LOC_LOGD("%s]: ", __func__);
2627
2628 // SPE will be restarted now, so set this variable to false.
2629 mSPEAlreadyRunningAtHighestInterval = false;
2630
2631 checkAndRestartTimeBasedSession();
2632
2633 for (auto it = mDistanceBasedTrackingSessions.begin();
2634 it != mDistanceBasedTrackingSessions.end(); ++it) {
2635 mLocApi->startDistanceBasedTracking(it->first.id, it->second,
2636 new LocApiResponse(*getContext(),
2637 [] (LocationError /*err*/) {}));
2638 }
2639}
2640
2641// suspend all on-going sessions
2642void
2643GnssAdapter::suspendSessions()
2644{
2645 LOC_LOGi(":enter");
2646
2647 if (!mTimeBasedTrackingSessions.empty()) {
2648 // inform engine hub that GNSS session has stopped
2649 mEngHubProxy->gnssStopFix();
2650 mLocApi->stopFix(nullptr);
2651 if (isDgnssNmeaRequired()) {
2652 mDgnssState &= ~DGNSS_STATE_NO_NMEA_PENDING;
2653 }
2654 stopDgnssNtrip();
2655 mSPEAlreadyRunningAtHighestInterval = false;
2656 }
2657}
2658
2659void GnssAdapter::checkAndRestartTimeBasedSession()
2660{
2661 LOC_LOGD("%s]: ", __func__);
2662
2663 if (!mTimeBasedTrackingSessions.empty()) {
2664 // get the LocationOptions that has the smallest interval, which should be the active one
2665 TrackingOptions smallestIntervalOptions; // size is zero until set for the first time
2666 TrackingOptions highestPowerTrackingOptions;
2667 memset(&smallestIntervalOptions, 0, sizeof(smallestIntervalOptions));
2668 memset(&highestPowerTrackingOptions, 0, sizeof(highestPowerTrackingOptions));
2669 for (auto it = mTimeBasedTrackingSessions.begin();
2670 it != mTimeBasedTrackingSessions.end(); ++it) {
2671 // size of zero means we havent set it yet
2672 if (0 == smallestIntervalOptions.size ||
2673 it->second.minInterval < smallestIntervalOptions.minInterval) {
2674 smallestIntervalOptions = it->second;
2675 }
2676 GnssPowerMode powerMode = it->second.powerMode;
2677 // Size of zero means we havent set it yet
2678 if (0 == highestPowerTrackingOptions.size ||
2679 (GNSS_POWER_MODE_INVALID != powerMode &&
2680 powerMode < highestPowerTrackingOptions.powerMode)) {
2681 highestPowerTrackingOptions = it->second;
2682 }
2683 }
2684
2685 highestPowerTrackingOptions.setLocationOptions(smallestIntervalOptions);
2686 // want to run SPE session at a fixed min interval in some automotive scenarios
2687 if(!checkAndSetSPEToRunforNHz(highestPowerTrackingOptions)) {
2688 mLocApi->startTimeBasedTracking(highestPowerTrackingOptions, nullptr);
2689 }
2690 }
2691}
2692
Michael Bestas3a0209e2023-05-04 01:15:47 +03002693void
2694GnssAdapter::notifyClientOfCachedLocationSystemInfo(
2695 LocationAPI* client, const LocationCallbacks& callbacks) {
2696
2697 if (mLocSystemInfo.systemInfoMask) {
2698 // client need to be notified if client has not yet previously registered
2699 // for the info but now register for it.
2700 bool notifyClientOfSystemInfo = false;
2701 // check whether we need to notify client of cached location system info
2702 //
2703 // client need to be notified if client has not yet previously registered
2704 // for the info but now register for it.
2705 if (callbacks.locationSystemInfoCb) {
2706 notifyClientOfSystemInfo = true;
2707 auto it = mClientData.find(client);
2708 if (it != mClientData.end()) {
2709 LocationCallbacks oldCallbacks = it->second;
2710 if (oldCallbacks.locationSystemInfoCb) {
2711 notifyClientOfSystemInfo = false;
2712 }
2713 }
2714 }
2715
2716 if (notifyClientOfSystemInfo) {
2717 callbacks.locationSystemInfoCb(mLocSystemInfo);
2718 }
2719 }
2720}
2721
2722bool
2723GnssAdapter::isTimeBasedTrackingSession(LocationAPI* client, uint32_t sessionId)
2724{
2725 LocationSessionKey key(client, sessionId);
2726 return (mTimeBasedTrackingSessions.find(key) != mTimeBasedTrackingSessions.end());
2727}
2728
2729bool
2730GnssAdapter::isDistanceBasedTrackingSession(LocationAPI* client, uint32_t sessionId)
2731{
2732 LocationSessionKey key(client, sessionId);
2733 return (mDistanceBasedTrackingSessions.find(key) != mDistanceBasedTrackingSessions.end());
2734}
2735
2736bool
2737GnssAdapter::hasCallbacksToStartTracking(LocationAPI* client)
2738{
2739 bool allowed = false;
2740 auto it = mClientData.find(client);
2741 if (it != mClientData.end()) {
2742 if (it->second.trackingCb || it->second.gnssLocationInfoCb ||
2743 it->second.engineLocationsInfoCb || it->second.gnssMeasurementsCb ||
2744 it->second.gnssDataCb || it->second.gnssSvCb || it->second.gnssNmeaCb) {
2745 allowed = true;
2746 } else {
2747 LOC_LOGi("missing right callback to start tracking")
2748 }
2749 } else {
2750 LOC_LOGi("client %p not found", client)
2751 }
2752 return allowed;
2753}
2754
2755bool
2756GnssAdapter::isTrackingSession(LocationAPI* client, uint32_t sessionId)
2757{
2758 LocationSessionKey key(client, sessionId);
2759 return (mTimeBasedTrackingSessions.find(key) != mTimeBasedTrackingSessions.end());
2760}
2761
2762void
2763GnssAdapter::reportPowerStateIfChanged()
2764{
2765 bool newPowerOn = !mTimeBasedTrackingSessions.empty() ||
2766 !mDistanceBasedTrackingSessions.empty();
2767 if (newPowerOn != mPowerOn) {
2768 mPowerOn = newPowerOn;
2769 if (mPowerStateCb != nullptr) {
2770 mPowerStateCb(mPowerOn);
2771 }
2772 }
2773}
2774
2775void
2776GnssAdapter::getPowerStateChangesCommand(std::function<void(bool)> powerStateCb)
2777{
2778 LOC_LOGD("%s]: ", __func__);
2779
2780 struct MsgReportLocation : public LocMsg {
2781 GnssAdapter& mAdapter;
2782 std::function<void(bool)> mPowerStateCb;
2783 inline MsgReportLocation(GnssAdapter& adapter,
2784 std::function<void(bool)> powerStateCb) :
2785 LocMsg(),
2786 mAdapter(adapter),
2787 mPowerStateCb(powerStateCb) {}
2788 inline virtual void proc() const {
2789 mAdapter.savePowerStateCallback(mPowerStateCb);
2790 mPowerStateCb(mAdapter.getPowerState());
2791 }
2792 };
2793
2794 sendMsg(new MsgReportLocation(*this, powerStateCb));
2795}
2796
2797void
2798GnssAdapter::saveTrackingSession(LocationAPI* client, uint32_t sessionId,
2799 const TrackingOptions& options)
2800{
2801 LocationSessionKey key(client, sessionId);
2802 if ((options.minDistance > 0) &&
2803 ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
2804 mDistanceBasedTrackingSessions[key] = options;
2805 } else {
2806 mTimeBasedTrackingSessions[key] = options;
2807 }
2808 reportPowerStateIfChanged();
2809}
2810
2811void
2812GnssAdapter::eraseTrackingSession(LocationAPI* client, uint32_t sessionId)
2813{
2814 LocationSessionKey key(client, sessionId);
2815 auto it = mTimeBasedTrackingSessions.find(key);
2816 if (it != mTimeBasedTrackingSessions.end()) {
2817 mTimeBasedTrackingSessions.erase(it);
2818 } else {
2819 auto itr = mDistanceBasedTrackingSessions.find(key);
2820 if (itr != mDistanceBasedTrackingSessions.end()) {
2821 mDistanceBasedTrackingSessions.erase(itr);
2822 }
2823 }
2824 reportPowerStateIfChanged();
2825}
2826
2827bool GnssAdapter::setLocPositionMode(const LocPosMode& mode) {
2828 if (!mLocPositionMode.equals(mode)) {
2829 mLocPositionMode = mode;
2830 return true;
2831 } else {
2832 return false;
2833 }
2834}
2835
2836void
2837GnssAdapter::reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId)
2838{
2839 LOC_LOGD("%s]: client %p id %u err %u", __func__, client, sessionId, err);
2840
2841 auto it = mClientData.find(client);
2842 if (it != mClientData.end() && it->second.responseCb != nullptr) {
2843 it->second.responseCb(err, sessionId);
2844 } else {
2845 LOC_LOGW("%s]: client %p id %u not found in data", __func__, client, sessionId);
2846 }
2847}
2848
2849void
2850GnssAdapter::reportResponse(LocationError err, uint32_t sessionId)
2851{
2852 LOC_LOGD("%s]: id %u err %u", __func__, sessionId, err);
2853
2854 if (mControlCallbacks.size > 0 && mControlCallbacks.responseCb != nullptr) {
2855 mControlCallbacks.responseCb(err, sessionId);
2856 } else {
2857 LOC_LOGW("%s]: control client response callback not found", __func__);
2858 }
2859}
2860
2861void
2862GnssAdapter::reportResponse(size_t count, LocationError* errs, uint32_t* ids)
2863{
2864 IF_LOC_LOGD {
2865 std::string idsString = "[";
2866 std::string errsString = "[";
2867 if (NULL != ids && NULL != errs) {
2868 for (size_t i=0; i < count; ++i) {
2869 idsString += std::to_string(ids[i]) + " ";
2870 errsString += std::to_string(errs[i]) + " ";
2871 }
2872 }
2873 idsString += "]";
2874 errsString += "]";
2875
2876 LOC_LOGD("%s]: ids %s errs %s",
2877 __func__, idsString.c_str(), errsString.c_str());
2878 }
2879
2880 if (mControlCallbacks.size > 0 && mControlCallbacks.collectiveResponseCb != nullptr) {
2881 mControlCallbacks.collectiveResponseCb(count, errs, ids);
2882 } else {
2883 LOC_LOGW("%s]: control client callback not found", __func__);
2884 }
2885}
2886
2887uint32_t
2888GnssAdapter::startTrackingCommand(LocationAPI* client, TrackingOptions& options)
2889{
2890 uint32_t sessionId = generateSessionId();
2891 LOC_LOGD("%s]: client %p id %u minInterval %u minDistance %u mode %u powermode %u tbm %u",
2892 __func__, client, sessionId, options.minInterval, options.minDistance, options.mode,
2893 options.powerMode, options.tbm);
2894
2895 struct MsgStartTracking : public LocMsg {
2896 GnssAdapter& mAdapter;
2897 LocApiBase& mApi;
2898 LocationAPI* mClient;
2899 uint32_t mSessionId;
2900 mutable TrackingOptions mOptions;
2901 inline MsgStartTracking(GnssAdapter& adapter,
2902 LocApiBase& api,
2903 LocationAPI* client,
2904 uint32_t sessionId,
2905 TrackingOptions options) :
2906 LocMsg(),
2907 mAdapter(adapter),
2908 mApi(api),
2909 mClient(client),
2910 mSessionId(sessionId),
2911 mOptions(options) {}
2912 inline virtual void proc() const {
2913 // distance based tracking will need to know engine capabilities before it can start
2914 if (!mAdapter.isEngineCapabilitiesKnown() && mOptions.minDistance > 0) {
2915 mAdapter.mPendingMsgs.push_back(new MsgStartTracking(*this));
2916 return;
2917 }
2918 LocationError err = LOCATION_ERROR_SUCCESS;
2919 if (!mAdapter.hasCallbacksToStartTracking(mClient)) {
2920 err = LOCATION_ERROR_CALLBACK_MISSING;
2921 } else if (0 == mOptions.size) {
2922 err = LOCATION_ERROR_INVALID_PARAMETER;
2923 } else {
2924 if (mOptions.minInterval < MIN_TRACKING_INTERVAL) {
2925 mOptions.minInterval = MIN_TRACKING_INTERVAL;
2926 }
2927 if (mOptions.minDistance > 0 &&
2928 ContextBase::isMessageSupported(
2929 LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
2930 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
2931 mApi.startDistanceBasedTracking(mSessionId, mOptions,
2932 new LocApiResponse(*mAdapter.getContext(),
2933 [&mAdapter = mAdapter, mSessionId = mSessionId, mClient = mClient]
2934 (LocationError err) {
2935 if (LOCATION_ERROR_SUCCESS != err) {
2936 mAdapter.eraseTrackingSession(mClient, mSessionId);
2937 }
2938 mAdapter.reportResponse(mClient, err, mSessionId);
2939 }));
2940 } else {
2941 if (GNSS_POWER_MODE_M4 == mOptions.powerMode &&
2942 mOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) {
2943 LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode",
2944 mOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS);
2945 mOptions.powerMode = GNSS_POWER_MODE_M2;
2946 }
2947 // Api doesn't support multiple clients for time based tracking, so mutiplex
2948 bool reportToClientWithNoWait =
2949 mAdapter.startTimeBasedTrackingMultiplex(mClient, mSessionId, mOptions);
2950 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
2951
2952 if (reportToClientWithNoWait) {
2953 mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
2954 }
2955 }
2956 }
2957 }
2958 };
2959
2960 sendMsg(new MsgStartTracking(*this, *mLocApi, client, sessionId, options));
2961 return sessionId;
2962
2963}
2964
2965bool
2966GnssAdapter::startTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t sessionId,
2967 const TrackingOptions& options)
2968{
2969 bool reportToClientWithNoWait = true;
2970
2971 if (mTimeBasedTrackingSessions.empty()) {
2972 /*Reset previous NMEA reported time stamp */
2973 mPrevNmeaRptTimeNsec = 0;
2974 startTimeBasedTracking(client, sessionId, options);
2975 // need to wait for QMI callback
2976 reportToClientWithNoWait = false;
2977 } else {
2978 // find the smallest interval and powerMode
2979 TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
2980 GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
2981 memset(&multiplexedOptions, 0, sizeof(multiplexedOptions));
2982 for (auto it = mTimeBasedTrackingSessions.begin(); it != mTimeBasedTrackingSessions.end(); ++it) {
2983 // if not set or there is a new smallest interval, then set the new interval
2984 if (0 == multiplexedOptions.size ||
2985 it->second.minInterval < multiplexedOptions.minInterval) {
2986 multiplexedOptions = it->second;
2987 }
2988 // if session is not the one we are updating and either powerMode
2989 // is not set or there is a new smallest powerMode, then set the new powerMode
2990 if (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
2991 it->second.powerMode < multiplexedPowerMode) {
2992 multiplexedPowerMode = it->second.powerMode;
2993 }
2994 }
2995 bool updateOptions = false;
2996 // if session we are starting has smaller interval then next smallest
2997 if (options.minInterval < multiplexedOptions.minInterval) {
2998 multiplexedOptions.minInterval = options.minInterval;
2999 updateOptions = true;
3000 }
3001
3002 // if session we are starting has smaller powerMode then next smallest
3003 if (options.powerMode < multiplexedPowerMode) {
3004 multiplexedOptions.powerMode = options.powerMode;
3005 updateOptions = true;
3006 }
3007 if (updateOptions) {
3008 // restart time based tracking with the newly updated options
3009
3010 startTimeBasedTracking(client, sessionId, multiplexedOptions);
3011 // need to wait for QMI callback
3012 reportToClientWithNoWait = false;
3013 }
3014 // else part: no QMI call is made, need to report back to client right away
3015 }
3016
3017 return reportToClientWithNoWait;
3018}
3019
3020void
3021GnssAdapter::startTimeBasedTracking(LocationAPI* client, uint32_t sessionId,
3022 const TrackingOptions& trackingOptions)
3023{
3024 LOC_LOGd("minInterval %u minDistance %u mode %u powermode %u tbm %u",
3025 trackingOptions.minInterval, trackingOptions.minDistance,
3026 trackingOptions.mode, trackingOptions.powerMode, trackingOptions.tbm);
3027 LocPosMode locPosMode = {};
3028 convertOptions(locPosMode, trackingOptions);
3029 // save position mode parameters
3030 setLocPositionMode(locPosMode);
3031 // inform engine hub that GNSS session is about to start
3032 mEngHubProxy->gnssSetFixMode(mLocPositionMode);
3033 mEngHubProxy->gnssStartFix();
3034
3035 // want to run SPE session at a fixed min interval in some automotive scenarios
3036 // use a local copy of TrackingOptions as the TBF may get modified in the
3037 // checkAndSetSPEToRunforNHz function
3038 TrackingOptions tempOptions(trackingOptions);
3039 if (!checkAndSetSPEToRunforNHz(tempOptions)) {
3040 mLocApi->startTimeBasedTracking(tempOptions, new LocApiResponse(*getContext(),
3041 [this, client, sessionId] (LocationError err) {
3042 if (LOCATION_ERROR_SUCCESS != err) {
3043 eraseTrackingSession(client, sessionId);
3044 } else {
3045 checkUpdateDgnssNtrip(false);
3046 }
3047
3048 reportResponse(client, err, sessionId);
3049 }
3050 ));
3051 } else {
3052 reportResponse(client, LOCATION_ERROR_SUCCESS, sessionId);
3053 }
3054
3055}
3056
3057void
3058GnssAdapter::updateTracking(LocationAPI* client, uint32_t sessionId,
3059 const TrackingOptions& updatedOptions, const TrackingOptions& oldOptions)
3060{
3061 LocPosMode locPosMode = {};
3062 convertOptions(locPosMode, updatedOptions);
3063 // save position mode parameters
3064 setLocPositionMode(locPosMode);
3065
3066 // inform engine hub that GNSS session is about to start
3067 mEngHubProxy->gnssSetFixMode(mLocPositionMode);
3068 mEngHubProxy->gnssStartFix();
3069
3070 // want to run SPE session at a fixed min interval in some automotive scenarios
3071 // use a local copy of TrackingOptions as the TBF may get modified in the
3072 // checkAndSetSPEToRunforNHz function
3073 TrackingOptions tempOptions(updatedOptions);
3074 if(!checkAndSetSPEToRunforNHz(tempOptions)) {
3075 mLocApi->startTimeBasedTracking(tempOptions, new LocApiResponse(*getContext(),
3076 [this, client, sessionId, oldOptions] (LocationError err) {
3077 if (LOCATION_ERROR_SUCCESS != err) {
3078 // restore the old LocationOptions
3079 saveTrackingSession(client, sessionId, oldOptions);
3080 }
3081 reportResponse(client, err, sessionId);
3082 }
3083 ));
3084 } else {
3085 reportResponse(client, LOCATION_ERROR_SUCCESS, sessionId);
3086 }
3087}
3088
3089void
3090GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id,
3091 TrackingOptions& options)
3092{
3093 LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
3094 __func__, client, id, options.minInterval, options.mode);
3095
3096 struct MsgUpdateTracking : public LocMsg {
3097 GnssAdapter& mAdapter;
3098 LocApiBase& mApi;
3099 LocationAPI* mClient;
3100 uint32_t mSessionId;
3101 mutable TrackingOptions mOptions;
3102 inline MsgUpdateTracking(GnssAdapter& adapter,
3103 LocApiBase& api,
3104 LocationAPI* client,
3105 uint32_t sessionId,
3106 TrackingOptions options) :
3107 LocMsg(),
3108 mAdapter(adapter),
3109 mApi(api),
3110 mClient(client),
3111 mSessionId(sessionId),
3112 mOptions(options) {}
3113 inline virtual void proc() const {
3114 // distance based tracking will need to know engine capabilities before it can start
3115 if (!mAdapter.isEngineCapabilitiesKnown() && mOptions.minDistance > 0) {
3116 mAdapter.mPendingMsgs.push_back(new MsgUpdateTracking(*this));
3117 return;
3118 }
3119 LocationError err = LOCATION_ERROR_SUCCESS;
3120 bool isTimeBased = mAdapter.isTimeBasedTrackingSession(mClient, mSessionId);
3121 bool isDistanceBased = mAdapter.isDistanceBasedTrackingSession(mClient, mSessionId);
3122 if (!isTimeBased && !isDistanceBased) {
3123 err = LOCATION_ERROR_ID_UNKNOWN;
3124 } else if (0 == mOptions.size) {
3125 err = LOCATION_ERROR_INVALID_PARAMETER;
3126 }
3127 if (LOCATION_ERROR_SUCCESS != err) {
3128 mAdapter.reportResponse(mClient, err, mSessionId);
3129 } else {
3130 if (GNSS_POWER_MODE_M4 == mOptions.powerMode &&
3131 mOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) {
3132 LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode",
3133 mOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS);
3134 mOptions.powerMode = GNSS_POWER_MODE_M2;
3135 }
3136 if (mOptions.minInterval < MIN_TRACKING_INTERVAL) {
3137 mOptions.minInterval = MIN_TRACKING_INTERVAL;
3138 }
3139 // Now update session as required
3140 if (isTimeBased && mOptions.minDistance > 0) {
3141 // switch from time based to distance based
3142 // Api doesn't support multiple clients for time based tracking, so mutiplex
3143 bool reportToClientWithNoWait =
3144 mAdapter.stopTimeBasedTrackingMultiplex(mClient, mSessionId);
3145 // erases the time based Session
3146 mAdapter.eraseTrackingSession(mClient, mSessionId);
3147 if (reportToClientWithNoWait) {
3148 mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
3149 }
3150 // saves as distance based Session
3151 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
3152 mApi.startDistanceBasedTracking(mSessionId, mOptions,
3153 new LocApiResponse(*mAdapter.getContext(),
3154 [] (LocationError /*err*/) {}));
3155 } else if (isDistanceBased && mOptions.minDistance == 0) {
3156 // switch from distance based to time based
3157 mAdapter.eraseTrackingSession(mClient, mSessionId);
3158 mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse(
3159 *mAdapter.getContext(),
3160 [&mAdapter = mAdapter, mSessionId = mSessionId, mOptions = mOptions,
3161 mClient = mClient] (LocationError /*err*/) {
3162 // Api doesn't support multiple clients for time based tracking,
3163 // so mutiplex
3164 bool reportToClientWithNoWait =
3165 mAdapter.startTimeBasedTrackingMultiplex(mClient, mSessionId,
3166 mOptions);
3167 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
3168
3169 if (reportToClientWithNoWait) {
3170 mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
3171 }
3172 }));
3173 } else if (isTimeBased) {
3174 // update time based tracking
3175 // Api doesn't support multiple clients for time based tracking, so mutiplex
3176 bool reportToClientWithNoWait =
3177 mAdapter.updateTrackingMultiplex(mClient, mSessionId, mOptions);
3178 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
3179
3180 if (reportToClientWithNoWait) {
3181 mAdapter.reportResponse(mClient, err, mSessionId);
3182 }
3183 } else if (isDistanceBased) {
3184 // restart distance based tracking
3185 mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse(
3186 *mAdapter.getContext(),
3187 [&mAdapter = mAdapter, mSessionId = mSessionId, mOptions = mOptions,
3188 mClient = mClient, &mApi = mApi] (LocationError err) {
3189 if (LOCATION_ERROR_SUCCESS == err) {
3190 mApi.startDistanceBasedTracking(mSessionId, mOptions,
3191 new LocApiResponse(*mAdapter.getContext(),
3192 [&mAdapter, mClient, mSessionId, mOptions]
3193 (LocationError err) {
3194 if (LOCATION_ERROR_SUCCESS == err) {
3195 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
3196 }
3197 mAdapter.reportResponse(mClient, err, mSessionId);
3198 }));
3199 }
3200 }));
3201 }
3202 }
3203 }
3204 };
3205
3206 sendMsg(new MsgUpdateTracking(*this, *mLocApi, client, id, options));
3207}
3208
3209bool
3210GnssAdapter::updateTrackingMultiplex(LocationAPI* client, uint32_t id,
3211 const TrackingOptions& trackingOptions)
3212{
3213 bool reportToClientWithNoWait = true;
3214
3215 LocationSessionKey key(client, id);
3216 // get the session we are updating
3217 auto it = mTimeBasedTrackingSessions.find(key);
3218
3219 // cache the clients existing LocationOptions
3220 TrackingOptions oldOptions = it->second;
3221
3222 // if session we are updating exists and the minInterval or powerMode has changed
3223 if (it != mTimeBasedTrackingSessions.end() &&
3224 (it->second.minInterval != trackingOptions.minInterval ||
3225 it->second.powerMode != trackingOptions.powerMode)) {
3226 // find the smallest interval and powerMode, other than the session we are updating
3227 TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
3228 GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
3229 memset(&multiplexedOptions, 0, sizeof(multiplexedOptions));
3230 for (auto it2 = mTimeBasedTrackingSessions.begin();
3231 it2 != mTimeBasedTrackingSessions.end(); ++it2) {
3232 // if session is not the one we are updating and either interval
3233 // is not set or there is a new smallest interval, then set the new interval
3234 if (it2->first != key && (0 == multiplexedOptions.size ||
3235 it2->second.minInterval < multiplexedOptions.minInterval)) {
3236 multiplexedOptions = it2->second;
3237 }
3238 // if session is not the one we are updating and either powerMode
3239 // is not set or there is a new smallest powerMode, then set the new powerMode
3240 if (it2->first != key && (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
3241 it2->second.powerMode < multiplexedPowerMode)) {
3242 multiplexedPowerMode = it2->second.powerMode;
3243 }
3244 // else part: no QMI call is made, need to report back to client right away
3245 }
3246 bool updateOptions = false;
3247 // if session we are updating has smaller interval then next smallest
3248 if (trackingOptions.minInterval < multiplexedOptions.minInterval) {
3249 multiplexedOptions.minInterval = trackingOptions.minInterval;
3250 updateOptions = true;
3251 }
3252 // if session we are updating has smaller powerMode then next smallest
3253 if (trackingOptions.powerMode < multiplexedPowerMode) {
3254 multiplexedOptions.powerMode = trackingOptions.powerMode;
3255 updateOptions = true;
3256 }
3257 // if only one session exists, then tracking should be updated with it
3258 if (1 == mTimeBasedTrackingSessions.size()) {
3259 multiplexedOptions = trackingOptions;
3260 updateOptions = true;
3261 }
3262 if (updateOptions) {
3263 // restart time based tracking with the newly updated options
3264 updateTracking(client, id, multiplexedOptions, oldOptions);
3265 // need to wait for QMI callback
3266 reportToClientWithNoWait = false;
3267 }
3268 }
3269
3270 return reportToClientWithNoWait;
3271}
3272
3273void
3274GnssAdapter::stopTrackingCommand(LocationAPI* client, uint32_t id)
3275{
3276 LOC_LOGD("%s]: client %p id %u", __func__, client, id);
3277
3278 struct MsgStopTracking : public LocMsg {
3279 GnssAdapter& mAdapter;
3280 LocApiBase& mApi;
3281 LocationAPI* mClient;
3282 uint32_t mSessionId;
3283 inline MsgStopTracking(GnssAdapter& adapter,
3284 LocApiBase& api,
3285 LocationAPI* client,
3286 uint32_t sessionId) :
3287 LocMsg(),
3288 mAdapter(adapter),
3289 mApi(api),
3290 mClient(client),
3291 mSessionId(sessionId) {}
3292 inline virtual void proc() const {
3293 bool isTimeBased = mAdapter.isTimeBasedTrackingSession(mClient, mSessionId);
3294 bool isDistanceBased = mAdapter.isDistanceBasedTrackingSession(mClient, mSessionId);
3295 if (isTimeBased || isDistanceBased) {
3296 if (isTimeBased) {
3297 // Api doesn't support multiple clients for time based tracking, so mutiplex
3298 bool reportToClientWithNoWait =
3299 mAdapter.stopTimeBasedTrackingMultiplex(mClient, mSessionId);
3300 mAdapter.eraseTrackingSession(mClient, mSessionId);
3301
3302 if (reportToClientWithNoWait) {
3303 mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
3304 }
3305 } else if (isDistanceBased) {
3306 mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse(
3307 *mAdapter.getContext(),
3308 [&mAdapter = mAdapter, mSessionId = mSessionId, mClient = mClient]
3309 (LocationError err) {
3310 if (LOCATION_ERROR_SUCCESS == err) {
3311 mAdapter.eraseTrackingSession(mClient, mSessionId);
3312 }
3313 mAdapter.reportResponse(mClient, err, mSessionId);
3314 }));
3315 }
3316 } else {
3317 mAdapter.reportResponse(mClient, LOCATION_ERROR_ID_UNKNOWN, mSessionId);
3318 }
3319
3320 }
3321 };
3322
3323 sendMsg(new MsgStopTracking(*this, *mLocApi, client, id));
3324}
3325
3326bool
3327GnssAdapter::stopTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t id)
3328{
3329 bool reportToClientWithNoWait = true;
3330
3331 if (1 == mTimeBasedTrackingSessions.size()) {
3332 stopTracking(client, id);
3333 // need to wait for QMI callback
3334 reportToClientWithNoWait = false;
3335 } else {
3336 LocationSessionKey key(client, id);
3337
3338 // get the session we are stopping
3339 auto it = mTimeBasedTrackingSessions.find(key);
3340 if (it != mTimeBasedTrackingSessions.end()) {
3341 // find the smallest interval and powerMode, other than the session we are stopping
3342 TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
3343 GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
3344 memset(&multiplexedOptions, 0, sizeof(multiplexedOptions));
3345 for (auto it2 = mTimeBasedTrackingSessions.begin();
3346 it2 != mTimeBasedTrackingSessions.end(); ++it2) {
3347 // if session is not the one we are stopping and either interval
3348 // is not set or there is a new smallest interval, then set the new interval
3349 if (it2->first != key && (0 == multiplexedOptions.size ||
3350 it2->second.minInterval < multiplexedOptions.minInterval)) {
3351 multiplexedOptions = it2->second;
3352 }
3353 // if session is not the one we are stopping and either powerMode
3354 // is not set or there is a new smallest powerMode, then set the new powerMode
3355 if (it2->first != key && (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
3356 it2->second.powerMode < multiplexedPowerMode)) {
3357 multiplexedPowerMode = it2->second.powerMode;
3358 }
3359 }
3360 // if session we are stopping has smaller interval then next smallest or
3361 // if session we are stopping has smaller powerMode then next smallest
3362 if (it->second.minInterval < multiplexedOptions.minInterval ||
3363 it->second.powerMode < multiplexedPowerMode) {
3364 multiplexedOptions.powerMode = multiplexedPowerMode;
3365 // restart time based tracking with the newly updated options
3366 startTimeBasedTracking(client, id, multiplexedOptions);
3367 // need to wait for QMI callback
3368 reportToClientWithNoWait = false;
3369 }
3370 // else part: no QMI call is made, need to report back to client right away
3371 }
3372 }
3373 return reportToClientWithNoWait;
3374}
3375
3376void
3377GnssAdapter::stopTracking(LocationAPI* client, uint32_t id)
3378{
3379 // inform engine hub that GNSS session has stopped
3380 mEngHubProxy->gnssStopFix();
3381
3382 mLocApi->stopFix(new LocApiResponse(*getContext(),
3383 [this, client, id] (LocationError err) {
3384 reportResponse(client, err, id);
3385 }));
3386
3387 if (isDgnssNmeaRequired()) {
3388 mDgnssState &= ~DGNSS_STATE_NO_NMEA_PENDING;
3389 }
3390 stopDgnssNtrip();
3391
3392 mSPEAlreadyRunningAtHighestInterval = false;
3393}
3394
3395bool
3396GnssAdapter::hasNiNotifyCallback(LocationAPI* client)
3397{
3398 auto it = mClientData.find(client);
3399 return (it != mClientData.end() && it->second.gnssNiCb);
3400}
3401
3402void
3403GnssAdapter::gnssNiResponseCommand(LocationAPI* client,
3404 uint32_t id,
3405 GnssNiResponse response)
3406{
3407 LOC_LOGD("%s]: client %p id %u response %u", __func__, client, id, response);
3408
3409 struct MsgGnssNiResponse : public LocMsg {
3410 GnssAdapter& mAdapter;
3411 LocationAPI* mClient;
3412 uint32_t mSessionId;
3413 GnssNiResponse mResponse;
3414 inline MsgGnssNiResponse(GnssAdapter& adapter,
3415 LocationAPI* client,
3416 uint32_t sessionId,
3417 GnssNiResponse response) :
3418 LocMsg(),
3419 mAdapter(adapter),
3420 mClient(client),
3421 mSessionId(sessionId),
3422 mResponse(response) {}
3423 inline virtual void proc() const {
3424 NiData& niData = mAdapter.getNiData();
3425 LocationError err = LOCATION_ERROR_SUCCESS;
3426 if (!mAdapter.hasNiNotifyCallback(mClient)) {
3427 err = LOCATION_ERROR_ID_UNKNOWN;
3428 } else {
3429 NiSession* pSession = NULL;
3430 if (mSessionId == niData.sessionEs.reqID &&
3431 NULL != niData.sessionEs.rawRequest) {
3432 pSession = &niData.sessionEs;
3433 // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
3434 if (mResponse == GNSS_NI_RESPONSE_ACCEPT &&
3435 NULL != niData.session.rawRequest) {
3436 pthread_mutex_lock(&niData.session.tLock);
3437 niData.session.resp = GNSS_NI_RESPONSE_IGNORE;
3438 niData.session.respRecvd = true;
3439 pthread_cond_signal(&niData.session.tCond);
3440 pthread_mutex_unlock(&niData.session.tLock);
3441 }
3442 } else if (mSessionId == niData.session.reqID &&
3443 NULL != niData.session.rawRequest) {
3444 pSession = &niData.session;
3445 }
3446
3447 if (pSession) {
3448 LOC_LOGI("%s]: gnssNiResponseCommand: send user mResponse %u for id %u",
3449 __func__, mResponse, mSessionId);
3450 pthread_mutex_lock(&pSession->tLock);
3451 pSession->resp = mResponse;
3452 pSession->respRecvd = true;
3453 pthread_cond_signal(&pSession->tCond);
3454 pthread_mutex_unlock(&pSession->tLock);
3455 } else {
3456 err = LOCATION_ERROR_ID_UNKNOWN;
3457 LOC_LOGE("%s]: gnssNiResponseCommand: id %u not an active session",
3458 __func__, mSessionId);
3459 }
3460 }
3461 mAdapter.reportResponse(mClient, err, mSessionId);
3462 }
3463 };
3464
3465 sendMsg(new MsgGnssNiResponse(*this, client, id, response));
3466
3467}
3468
3469void
3470GnssAdapter::gnssNiResponseCommand(GnssNiResponse response, void* rawRequest)
3471{
3472 LOC_LOGD("%s]: response %u", __func__, response);
3473
3474 struct MsgGnssNiResponse : public LocMsg {
3475 GnssAdapter& mAdapter;
3476 LocApiBase& mApi;
3477 const GnssNiResponse mResponse;
3478 const void* mPayload;
3479 inline MsgGnssNiResponse(GnssAdapter& adapter,
3480 LocApiBase& api,
3481 const GnssNiResponse response,
3482 const void* rawRequest) :
3483 LocMsg(),
3484 mAdapter(adapter),
3485 mApi(api),
3486 mResponse(response),
3487 mPayload(rawRequest) {}
3488 inline virtual ~MsgGnssNiResponse() {
3489 }
3490 inline virtual void proc() const {
3491 mApi.informNiResponse(mResponse, mPayload);
3492 }
3493 };
3494
3495 sendMsg(new MsgGnssNiResponse(*this, *mLocApi, response, rawRequest));
3496
3497}
3498
3499uint32_t
3500GnssAdapter::enableCommand(LocationTechnologyType techType)
3501{
3502 uint32_t sessionId = generateSessionId();
3503 LOC_LOGD("%s]: id %u techType %u", __func__, sessionId, techType);
3504
3505 struct MsgEnableGnss : public LocMsg {
3506 GnssAdapter& mAdapter;
3507 LocApiBase& mApi;
3508 ContextBase& mContext;
3509 uint32_t mSessionId;
3510 LocationTechnologyType mTechType;
3511 inline MsgEnableGnss(GnssAdapter& adapter,
3512 LocApiBase& api,
3513 ContextBase& context,
3514 uint32_t sessionId,
3515 LocationTechnologyType techType) :
3516 LocMsg(),
3517 mAdapter(adapter),
3518 mApi(api),
3519 mContext(context),
3520 mSessionId(sessionId),
3521 mTechType(techType) {}
3522 inline virtual void proc() const {
3523 LocationError err = LOCATION_ERROR_SUCCESS;
3524 uint32_t afwControlId = mAdapter.getAfwControlId();
3525 if (mTechType != LOCATION_TECHNOLOGY_TYPE_GNSS) {
3526 err = LOCATION_ERROR_INVALID_PARAMETER;
3527 } else if (afwControlId > 0) {
3528 err = LOCATION_ERROR_ALREADY_STARTED;
3529 } else {
3530 mContext.modemPowerVote(true);
3531 mAdapter.setAfwControlId(mSessionId);
3532
3533 GnssConfigGpsLock gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
3534 if (mAdapter.mSupportNfwControl) {
3535 ContextBase::mGps_conf.GPS_LOCK &= GNSS_CONFIG_GPS_LOCK_NI;
3536 gpsLock = ContextBase::mGps_conf.GPS_LOCK;
3537 }
3538 mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() {
3539 mApi.setGpsLockSync(gpsLock);
3540 }));
3541 mAdapter.mXtraObserver.updateLockStatus(gpsLock);
3542 }
3543 mAdapter.reportResponse(err, mSessionId);
3544 }
3545 };
3546
3547 if (mContext != NULL) {
3548 sendMsg(new MsgEnableGnss(*this, *mLocApi, *mContext, sessionId, techType));
3549 } else {
3550 LOC_LOGE("%s]: Context is NULL", __func__);
3551 }
3552
3553 return sessionId;
3554}
3555
3556void
3557GnssAdapter::disableCommand(uint32_t id)
3558{
3559 LOC_LOGD("%s]: id %u", __func__, id);
3560
3561 struct MsgDisableGnss : public LocMsg {
3562 GnssAdapter& mAdapter;
3563 LocApiBase& mApi;
3564 ContextBase& mContext;
3565 uint32_t mSessionId;
3566 inline MsgDisableGnss(GnssAdapter& adapter,
3567 LocApiBase& api,
3568 ContextBase& context,
3569 uint32_t sessionId) :
3570 LocMsg(),
3571 mAdapter(adapter),
3572 mApi(api),
3573 mContext(context),
3574 mSessionId(sessionId) {}
3575 inline virtual void proc() const {
3576 LocationError err = LOCATION_ERROR_SUCCESS;
3577 uint32_t afwControlId = mAdapter.getAfwControlId();
3578 if (afwControlId != mSessionId) {
3579 err = LOCATION_ERROR_ID_UNKNOWN;
3580 } else {
3581 mContext.modemPowerVote(false);
3582 mAdapter.setAfwControlId(0);
3583
3584 if (mAdapter.mSupportNfwControl) {
3585 /* We need to disable MO (AFW) */
3586 ContextBase::mGps_conf.GPS_LOCK |= GNSS_CONFIG_GPS_LOCK_MO;
3587 }
3588 GnssConfigGpsLock gpsLock = ContextBase::mGps_conf.GPS_LOCK;
3589 mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() {
3590 mApi.setGpsLockSync(gpsLock);
3591 }));
3592 mAdapter.mXtraObserver.updateLockStatus(gpsLock);
3593 }
3594 mAdapter.reportResponse(err, mSessionId);
3595 }
3596 };
3597
3598 if (mContext != NULL) {
3599 sendMsg(new MsgDisableGnss(*this, *mLocApi, *mContext, id));
3600 }
3601
3602}
3603
3604// This function computes the VRP based latitude, longitude and alittude, and
3605// north, east and up velocity and save the result into EHubTechReport.
3606void
3607GnssAdapter::computeVRPBasedLla(const UlpLocation& loc, GpsLocationExtended& locExt,
3608 const LeverArmConfigInfo& leverArmConfigInfo) {
3609
3610 float leverArm[3];
3611 float rollPitchYaw[3];
3612 double lla[3];
3613
3614 uint16_t locFlags = loc.gpsLocation.flags;
3615 uint64_t locExtFlags = locExt.flags;
3616
3617 // check for SPE fix
3618 if (!((locExtFlags & GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE) &&
3619 (locExt.locOutputEngType == LOC_OUTPUT_ENGINE_SPE))){
3620 LOC_LOGv("not SPE fix, return");
3621 return;
3622 }
3623
3624 // we can only do translation if we have VRP based lever ARM info
3625 LeverArmTypeMask leverArmFlags = leverArmConfigInfo.leverArmValidMask;
3626 if (!(leverArmFlags & LEVER_ARM_TYPE_GNSS_TO_VRP_BIT)) {
3627 LOC_LOGd("no VRP based lever ARM info");
3628 return;
3629 }
3630
3631 leverArm[0] = leverArmConfigInfo.gnssToVRP.forwardOffsetMeters;
3632 leverArm[1] = leverArmConfigInfo.gnssToVRP.sidewaysOffsetMeters;
3633 leverArm[2] = leverArmConfigInfo.gnssToVRP.upOffsetMeters;
3634
3635 if ((locFlags & LOC_GPS_LOCATION_HAS_LAT_LONG) &&
3636 (locFlags & LOC_GPS_LOCATION_HAS_ALTITUDE) &&
3637 (locFlags & LOCATION_HAS_BEARING_BIT)) {
3638
3639 lla[0] = loc.gpsLocation.latitude * DEG2RAD;
3640 lla[1] = loc.gpsLocation.longitude * DEG2RAD;
3641 lla[2] = loc.gpsLocation.altitude;
3642
3643 rollPitchYaw[0] = 0.0f;
3644 rollPitchYaw[1] = 0.0f;
3645 rollPitchYaw[2] = loc.gpsLocation.bearing * DEG2RAD;
3646
3647 loc_convert_lla_gnss_to_vrp(lla, rollPitchYaw, leverArm);
3648
3649 // assign the converted value into position report and
3650 // set up valid mask
3651 locExt.llaVRPBased.latitude = lla[0] * RAD2DEG;
3652 locExt.llaVRPBased.longitude = lla[1] * RAD2DEG;
3653 locExt.llaVRPBased.altitude = lla[2];
3654 locExt.flags |= GPS_LOCATION_EXTENDED_HAS_LLA_VRP_BASED;
3655 } else {
3656 LOC_LOGd("SPE fix missing latitude/longitude/alitutde");
3657 return;
3658 }
3659}
3660
3661void
3662GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation,
3663 const GpsLocationExtended& locationExtended,
3664 enum loc_sess_status status,
3665 LocPosTechMask techMask,
3666 GnssDataNotification* pDataNotify,
3667 int msInWeek)
3668{
3669 // this position is from QMI LOC API, then send report to engine hub
3670 // also, send out SPE fix promptly to the clients that have registered
3671 // with SPE report
3672 LOC_LOGd("reportPositionEvent, eng type: %d, unpro %d, sess status %d msInWeek %d",
3673 locationExtended.locOutputEngType,
3674 ulpLocation.unpropagatedPosition, status, msInWeek);
3675
3676 struct MsgReportSPEPosition : public LocMsg {
3677 GnssAdapter& mAdapter;
3678 mutable UlpLocation mUlpLocation;
3679 mutable GpsLocationExtended mLocationExtended;
3680 enum loc_sess_status mStatus;
3681 LocPosTechMask mTechMask;
3682 mutable GnssDataNotification mDataNotify;
3683 int mMsInWeek;
3684
3685 inline MsgReportSPEPosition(GnssAdapter& adapter,
3686 const UlpLocation& ulpLocation,
3687 const GpsLocationExtended& locationExtended,
3688 enum loc_sess_status status,
3689 LocPosTechMask techMask,
3690 GnssDataNotification dataNotify,
3691 int msInWeek) :
3692 LocMsg(),
3693 mAdapter(adapter),
3694 mUlpLocation(ulpLocation),
3695 mLocationExtended(locationExtended),
3696 mStatus(status),
3697 mTechMask(techMask),
3698 mDataNotify(dataNotify),
3699 mMsInWeek(msInWeek) {}
3700 inline virtual void proc() const {
3701 if (mAdapter.mTimeBasedTrackingSessions.empty() &&
3702 mAdapter.mDistanceBasedTrackingSessions.empty()) {
3703 LOC_LOGd("reportPositionEvent, no session on-going, throw away the SPE reports");
3704 return;
3705 }
3706
3707 if (false == mUlpLocation.unpropagatedPosition && mDataNotify.size != 0) {
3708 if (mMsInWeek >= 0) {
3709 mAdapter.getDataInformation((GnssDataNotification&)mDataNotify,
3710 mMsInWeek);
3711 }
3712 mAdapter.reportData(mDataNotify);
3713 }
3714
3715 if (true == mAdapter.initEngHubProxy()){
3716 // send the SPE fix to engine hub
3717 mAdapter.mEngHubProxy->gnssReportPosition(mUlpLocation, mLocationExtended, mStatus);
3718 // report out all SPE fix if it is not propagated, even for failed fix
3719 if (false == mUlpLocation.unpropagatedPosition) {
3720 EngineLocationInfo engLocationInfo = {};
3721 engLocationInfo.location = mUlpLocation;
3722 engLocationInfo.locationExtended = mLocationExtended;
3723 engLocationInfo.sessionStatus = mStatus;
3724
3725 // obtain the VRP based latitude/longitude/altitude for SPE fix
3726 computeVRPBasedLla(engLocationInfo.location,
3727 engLocationInfo.locationExtended,
3728 mAdapter.mLocConfigInfo.leverArmConfigInfo);
3729 mAdapter.reportEnginePositions(1, &engLocationInfo);
3730 }
3731 return;
3732 }
3733
3734 // unpropagated report: is only for engine hub to consume and no need
3735 // to send out to the clients
3736 if (true == mUlpLocation.unpropagatedPosition) {
3737 return;
3738 }
3739
3740 // extract bug report info - this returns true if consumed by systemstatus
3741 SystemStatus* s = mAdapter.getSystemStatus();
3742 if ((nullptr != s) &&
3743 ((LOC_SESS_SUCCESS == mStatus) || (LOC_SESS_INTERMEDIATE == mStatus))){
3744 s->eventPosition(mUlpLocation, mLocationExtended);
3745 }
3746
3747 mAdapter.reportPosition(mUlpLocation, mLocationExtended, mStatus, mTechMask);
3748 }
3749 };
3750
3751 if (mContext != NULL) {
3752 GnssDataNotification dataNotifyCopy = {};
3753 if (pDataNotify) {
3754 dataNotifyCopy = *pDataNotify;
3755 dataNotifyCopy.size = sizeof(dataNotifyCopy);
3756 }
3757 sendMsg(new MsgReportSPEPosition(*this, ulpLocation, locationExtended,
3758 status, techMask, dataNotifyCopy, msInWeek));
3759 }
3760}
3761
3762void
3763GnssAdapter::reportEnginePositionsEvent(unsigned int count,
3764 EngineLocationInfo* locationArr)
3765{
3766 struct MsgReportEnginePositions : public LocMsg {
3767 GnssAdapter& mAdapter;
3768 unsigned int mCount;
3769 EngineLocationInfo mEngLocInfo[LOC_OUTPUT_ENGINE_COUNT];
3770 inline MsgReportEnginePositions(GnssAdapter& adapter,
3771 unsigned int count,
3772 EngineLocationInfo* locationArr) :
3773 LocMsg(),
3774 mAdapter(adapter),
3775 mCount(count) {
3776 if (mCount > LOC_OUTPUT_ENGINE_COUNT) {
3777 mCount = LOC_OUTPUT_ENGINE_COUNT;
3778 }
3779 if (mCount > 0) {
3780 memcpy(mEngLocInfo, locationArr, sizeof(EngineLocationInfo)*mCount);
3781 }
3782 }
3783 inline virtual void proc() const {
3784 mAdapter.reportEnginePositions(mCount, mEngLocInfo);
3785 }
3786 };
3787
3788 sendMsg(new MsgReportEnginePositions(*this, count, locationArr));
3789}
3790
3791bool
3792GnssAdapter::needReportForGnssClient(const UlpLocation& ulpLocation,
3793 enum loc_sess_status status,
3794 LocPosTechMask techMask) {
3795 bool reported = false;
3796
3797 // if engine hub is enabled, aka, any of the engine services is enabled,
3798 // then always output position reported by engine hub to requesting client
3799 if (true == initEngHubProxy()) {
3800 reported = true;
3801 } else {
3802 reported = LocApiBase::needReport(ulpLocation, status, techMask);
3803 }
3804 return reported;
3805}
3806
3807bool
3808GnssAdapter::needReportForFlpClient(enum loc_sess_status status,
3809 LocPosTechMask techMask) {
3810 if (((LOC_SESS_INTERMEDIATE == status) && !(techMask & LOC_POS_TECH_MASK_SENSORS) &&
3811 (!getAllowFlpNetworkFixes())) ||
3812 (LOC_SESS_FAILURE == status)) {
3813 return false;
3814 } else {
3815 return true;
3816 }
3817}
3818
3819bool
3820GnssAdapter::isFlpClient(LocationCallbacks& locationCallbacks)
3821{
3822 return (locationCallbacks.gnssLocationInfoCb == nullptr &&
3823 locationCallbacks.gnssSvCb == nullptr &&
3824 locationCallbacks.gnssNmeaCb == nullptr &&
3825 locationCallbacks.gnssDataCb == nullptr &&
3826 locationCallbacks.gnssMeasurementsCb == nullptr);
3827}
3828
3829bool GnssAdapter::needToGenerateNmeaReport(const uint32_t &gpsTimeOfWeekMs,
3830 const struct timespec32_t &apTimeStamp)
3831{
3832 bool retVal = false;
3833 uint64_t currentTimeNsec = 0;
3834
3835 if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTimeBasedTrackingSessions.empty()) {
3836 currentTimeNsec = (apTimeStamp.tv_sec * BILLION_NSEC + apTimeStamp.tv_nsec);
3837 if ((GNSS_NMEA_REPORT_RATE_NHZ == ContextBase::sNmeaReportRate) ||
3838 (GPS_DEFAULT_FIX_INTERVAL_MS <= mLocPositionMode.min_interval)) {
3839 retVal = true;
3840 } else { /*tbf is less than 1000 milli-seconds and NMEA reporting rate is set to 1Hz */
3841 /* Always send NMEA string for first position report
3842 * Send when gpsTimeOfWeekMs is closely aligned with integer boundary
3843 */
3844 if ((0 == mPrevNmeaRptTimeNsec) ||
Albert Ic861b412021-06-25 19:46:27 +08003845 ((0 != gpsTimeOfWeekMs) && (NMEA_MIN_THRESHOLD_MSEC >= (gpsTimeOfWeekMs % 1000)))) {
Michael Bestas3a0209e2023-05-04 01:15:47 +03003846 retVal = true;
3847 } else {
3848 uint64_t timeDiffMsec = ((currentTimeNsec - mPrevNmeaRptTimeNsec) / 1000000);
3849 // Send when the delta time becomes >= 1 sec
3850 if (NMEA_MAX_THRESHOLD_MSEC <= timeDiffMsec) {
3851 retVal = true;
3852 }
3853 }
3854 }
3855 if (true == retVal) {
3856 mPrevNmeaRptTimeNsec = currentTimeNsec;
3857 }
3858 }
3859 return retVal;
3860}
3861
3862void
3863GnssAdapter::logLatencyInfo()
3864{
3865 if (0 == mGnssLatencyInfoQueue.size()) {
3866 LOC_LOGv("mGnssLatencyInfoQueue.size is 0");
3867 return;
3868 }
3869 mGnssLatencyInfoQueue.front().hlosQtimer5 = getQTimerTickCount();
3870 if (0 == mGnssLatencyInfoQueue.front().hlosQtimer3) {
3871 /* if SPE from engine hub is not reported then hlosQtimer3 = 0, set it
3872 equal to hlosQtimer2 to make sense */
3873 LOC_LOGv("hlosQtimer3 is 0, setting it to hlosQtimer2");
3874 mGnssLatencyInfoQueue.front().hlosQtimer3 = mGnssLatencyInfoQueue.front().hlosQtimer2;
3875 }
3876 if (0 == mGnssLatencyInfoQueue.front().hlosQtimer4) {
3877 /* if PPE from engine hub is not reported then hlosQtimer4 = 0, set it
3878 equal to hlosQtimer3 to make sense */
3879 LOC_LOGv("hlosQtimer4 is 0, setting it to hlosQtimer3");
3880 mGnssLatencyInfoQueue.front().hlosQtimer4 = mGnssLatencyInfoQueue.front().hlosQtimer3;
3881 }
3882 if (mGnssLatencyInfoQueue.front().hlosQtimer4 < mGnssLatencyInfoQueue.front().hlosQtimer3) {
3883 /* hlosQtimer3 is timestamped when SPE from engine hub is reported,
3884 and hlosQtimer4 is timestamped when PPE from engine hub is reported.
3885 The order is random though, hence making sure the timestamps are sorted */
3886 LOC_LOGv("hlosQtimer4 is < hlosQtimer3, swapping them");
3887 std::swap(mGnssLatencyInfoQueue.front().hlosQtimer3,
3888 mGnssLatencyInfoQueue.front().hlosQtimer4);
3889 }
3890 LOC_LOGv("meQtimer1=%" PRIi64 " "
3891 "meQtimer2=%" PRIi64 " "
3892 "meQtimer3=%" PRIi64 " "
3893 "peQtimer1=%" PRIi64 " "
3894 "peQtimer2=%" PRIi64 " "
3895 "peQtimer3=%" PRIi64 " "
3896 "smQtimer1=%" PRIi64 " "
3897 "smQtimer2=%" PRIi64 " "
3898 "smQtimer3=%" PRIi64 " "
3899 "locMwQtimer=%" PRIi64 " "
3900 "hlosQtimer1=%" PRIi64 " "
3901 "hlosQtimer2=%" PRIi64 " "
3902 "hlosQtimer3=%" PRIi64 " "
3903 "hlosQtimer4=%" PRIi64 " "
3904 "hlosQtimer5=%" PRIi64 " ",
3905 mGnssLatencyInfoQueue.front().meQtimer1, mGnssLatencyInfoQueue.front().meQtimer2,
3906 mGnssLatencyInfoQueue.front().meQtimer3, mGnssLatencyInfoQueue.front().peQtimer1,
3907 mGnssLatencyInfoQueue.front().peQtimer2, mGnssLatencyInfoQueue.front().peQtimer3,
3908 mGnssLatencyInfoQueue.front().smQtimer1, mGnssLatencyInfoQueue.front().smQtimer2,
3909 mGnssLatencyInfoQueue.front().smQtimer3, mGnssLatencyInfoQueue.front().locMwQtimer,
3910 mGnssLatencyInfoQueue.front().hlosQtimer1, mGnssLatencyInfoQueue.front().hlosQtimer2,
3911 mGnssLatencyInfoQueue.front().hlosQtimer3, mGnssLatencyInfoQueue.front().hlosQtimer4,
3912 mGnssLatencyInfoQueue.front().hlosQtimer5);
3913 mLogger.log(mGnssLatencyInfoQueue.front());
3914 mGnssLatencyInfoQueue.pop();
3915 LOC_LOGv("mGnssLatencyInfoQueue.size after pop=%zu", mGnssLatencyInfoQueue.size());
3916}
3917
3918// only fused report (when engine hub is enabled) or
3919// SPE report (when engine hub is disabled) will reach this function
3920void
3921GnssAdapter::reportPosition(const UlpLocation& ulpLocation,
3922 const GpsLocationExtended& locationExtended,
3923 enum loc_sess_status status,
3924 LocPosTechMask techMask)
3925{
3926 bool reportToGnssClient = needReportForGnssClient(ulpLocation, status, techMask);
3927 bool reportToFlpClient = needReportForFlpClient(status, techMask);
3928
3929 if (reportToGnssClient || reportToFlpClient) {
3930 GnssLocationInfoNotification locationInfo = {};
3931 convertLocationInfo(locationInfo, locationExtended, status);
3932 convertLocation(locationInfo.location, ulpLocation, locationExtended);
3933 logLatencyInfo();
3934 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3935 if ((reportToFlpClient && isFlpClient(it->second)) ||
3936 (reportToGnssClient && !isFlpClient(it->second))) {
3937 if (nullptr != it->second.gnssLocationInfoCb) {
3938 it->second.gnssLocationInfoCb(locationInfo);
3939 } else if ((nullptr != it->second.engineLocationsInfoCb) &&
3940 (false == initEngHubProxy())) {
3941 // if engine hub is disabled, this is SPE fix from modem
3942 // we need to mark one copy marked as fused and one copy marked as PPE
3943 // and dispatch it to the engineLocationsInfoCb
3944 GnssLocationInfoNotification engLocationsInfo[2];
3945 engLocationsInfo[0] = locationInfo;
3946 engLocationsInfo[0].locOutputEngType = LOC_OUTPUT_ENGINE_FUSED;
3947 engLocationsInfo[0].flags |= GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT;
3948 engLocationsInfo[1] = locationInfo;
3949 it->second.engineLocationsInfoCb(2, engLocationsInfo);
3950 } else if (nullptr != it->second.trackingCb) {
3951 it->second.trackingCb(locationInfo.location);
3952 }
3953 }
3954 }
3955
3956 mGnssSvIdUsedInPosAvail = false;
3957 mGnssMbSvIdUsedInPosAvail = false;
3958 if (reportToGnssClient) {
3959 if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA) {
3960 mGnssSvIdUsedInPosAvail = true;
3961 mGnssSvIdUsedInPosition = locationExtended.gnss_sv_used_ids;
3962 if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_MULTIBAND) {
3963 mGnssMbSvIdUsedInPosAvail = true;
3964 mGnssMbSvIdUsedInPosition = locationExtended.gnss_mb_sv_used_ids;
3965 }
3966 }
3967
3968 // if PACE is enabled
3969 if ((true == mLocConfigInfo.paceConfigInfo.isValid) &&
3970 (true == mLocConfigInfo.paceConfigInfo.enable)) {
3971 // If fix has sensor contribution, and it is fused fix with DRE engine
3972 // contributing to the fix, inject to modem
3973 if ((LOC_POS_TECH_MASK_SENSORS & techMask) &&
3974 (locationInfo.flags & GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT) &&
3975 (locationInfo.locOutputEngType == LOC_OUTPUT_ENGINE_FUSED) &&
3976 (locationInfo.flags & GNSS_LOCATION_INFO_OUTPUT_ENG_MASK_BIT) &&
3977 (locationInfo.locOutputEngMask & DEAD_RECKONING_ENGINE)) {
3978 mLocApi->injectPosition(locationInfo, false);
3979 }
3980 }
3981 }
3982 }
3983
3984 if (needToGenerateNmeaReport(locationExtended.gpsTime.gpsTimeOfWeekMs,
3985 locationExtended.timeStamp.apTimeStamp)) {
3986 /*Only BlankNMEA sentence needs to be processed and sent, if both lat, long is 0 &
3987 horReliability is not set. */
3988 bool blank_fix = ((0 == ulpLocation.gpsLocation.latitude) &&
3989 (0 == ulpLocation.gpsLocation.longitude) &&
3990 (LOC_RELIABILITY_NOT_SET == locationExtended.horizontal_reliability));
3991 uint8_t generate_nmea = (reportToGnssClient && status != LOC_SESS_FAILURE && !blank_fix);
3992 bool custom_nmea_gga = (1 == ContextBase::mGps_conf.CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED);
3993 bool isTagBlockGroupingEnabled =
3994 (1 == ContextBase::mGps_conf.NMEA_TAG_BLOCK_GROUPING_ENABLED);
3995 std::vector<std::string> nmeaArraystr;
3996 int indexOfGGA = -1;
3997 loc_nmea_generate_pos(ulpLocation, locationExtended, mLocSystemInfo, generate_nmea,
3998 custom_nmea_gga, nmeaArraystr, indexOfGGA, isTagBlockGroupingEnabled);
3999 stringstream ss;
4000 for (auto itor = nmeaArraystr.begin(); itor != nmeaArraystr.end(); ++itor) {
4001 ss << *itor;
4002 }
4003 string s = ss.str();
4004 reportNmea(s.c_str(), s.length());
4005
4006 /* DgnssNtrip */
4007 if (-1 != indexOfGGA && isDgnssNmeaRequired()) {
4008 mDgnssState |= DGNSS_STATE_NO_NMEA_PENDING;
4009 mStartDgnssNtripParams.nmea = std::move(nmeaArraystr[indexOfGGA]);
4010 bool isLocationValid = (0 != ulpLocation.gpsLocation.latitude) ||
4011 (0 != ulpLocation.gpsLocation.longitude);
4012 checkUpdateDgnssNtrip(isLocationValid);
4013 }
4014 }
4015}
4016
4017void
4018GnssAdapter::reportLatencyInfoEvent(const GnssLatencyInfo& gnssLatencyInfo)
4019{
4020 struct MsgReportLatencyInfo : public LocMsg {
4021 GnssAdapter& mAdapter;
4022 GnssLatencyInfo mGnssLatencyInfo;
4023 inline MsgReportLatencyInfo(GnssAdapter& adapter,
4024 const GnssLatencyInfo& gnssLatencyInfo) :
Albert Ib8416c92021-06-25 19:34:31 +08004025 mAdapter(adapter),
4026 mGnssLatencyInfo(gnssLatencyInfo) {}
Michael Bestas3a0209e2023-05-04 01:15:47 +03004027 inline virtual void proc() const {
4028 mAdapter.mGnssLatencyInfoQueue.push(mGnssLatencyInfo);
4029 LOC_LOGv("mGnssLatencyInfoQueue.size after push=%zu",
4030 mAdapter.mGnssLatencyInfoQueue.size());
4031 }
4032 };
4033 sendMsg(new MsgReportLatencyInfo(*this, gnssLatencyInfo));
4034}
4035
4036void
4037GnssAdapter::reportEnginePositions(unsigned int count,
4038 const EngineLocationInfo* locationArr)
4039{
4040 bool needReportEnginePositions = false;
4041 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
4042 if (nullptr != it->second.engineLocationsInfoCb) {
4043 needReportEnginePositions = true;
4044 break;
4045 }
4046 }
4047
4048 GnssLocationInfoNotification locationInfo[LOC_OUTPUT_ENGINE_COUNT] = {};
4049 for (unsigned int i = 0; i < count; i++) {
4050 const EngineLocationInfo* engLocation = (locationArr+i);
4051 // if it is fused/default location, call reportPosition maintain legacy behavior
4052 if ((GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & engLocation->locationExtended.flags) &&
4053 (LOC_OUTPUT_ENGINE_FUSED == engLocation->locationExtended.locOutputEngType)) {
4054 reportPosition(engLocation->location,
4055 engLocation->locationExtended,
4056 engLocation->sessionStatus,
4057 engLocation->location.tech_mask);
4058 }
4059
4060 if (needReportEnginePositions) {
4061 convertLocationInfo(locationInfo[i], engLocation->locationExtended,
4062 engLocation->sessionStatus);
4063 convertLocation(locationInfo[i].location,
4064 engLocation->location,
4065 engLocation->locationExtended);
4066 }
4067 }
4068
4069 const EngineLocationInfo* engLocation = locationArr;
4070 LOC_LOGv("engLocation->locationExtended.locOutputEngType=%d",
4071 engLocation->locationExtended.locOutputEngType);
4072
4073 if (0 != mGnssLatencyInfoQueue.size()) {
4074 if ((GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & engLocation->locationExtended.flags) &&
4075 (LOC_OUTPUT_ENGINE_SPE == engLocation->locationExtended.locOutputEngType)) {
4076 mGnssLatencyInfoQueue.front().hlosQtimer3 = getQTimerTickCount();
4077 LOC_LOGv("SPE hlosQtimer3=%" PRIi64 " ", mGnssLatencyInfoQueue.front().hlosQtimer3);
4078 }
4079 if ((GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & engLocation->locationExtended.flags) &&
4080 (LOC_OUTPUT_ENGINE_PPE == engLocation->locationExtended.locOutputEngType)) {
4081 mGnssLatencyInfoQueue.front().hlosQtimer4 = getQTimerTickCount();
4082 LOC_LOGv("PPE hlosQtimer4=%" PRIi64 " ", mGnssLatencyInfoQueue.front().hlosQtimer4);
4083 }
4084 }
4085 if (needReportEnginePositions) {
4086 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
4087 if (nullptr != it->second.engineLocationsInfoCb) {
4088 it->second.engineLocationsInfoCb(count, locationInfo);
4089 }
4090 }
4091 }
4092}
4093
4094void
4095GnssAdapter::reportSvEvent(const GnssSvNotification& svNotify,
4096 bool fromEngineHub)
4097{
4098 if (!fromEngineHub) {
4099 mEngHubProxy->gnssReportSv(svNotify);
4100 if (true == initEngHubProxy()){
4101 return;
4102 }
4103 }
4104
4105 struct MsgReportSv : public LocMsg {
4106 GnssAdapter& mAdapter;
4107 const GnssSvNotification mSvNotify;
4108 inline MsgReportSv(GnssAdapter& adapter,
4109 const GnssSvNotification& svNotify) :
4110 LocMsg(),
4111 mAdapter(adapter),
4112 mSvNotify(svNotify) {}
4113 inline virtual void proc() const {
4114 mAdapter.reportSv((GnssSvNotification&)mSvNotify);
4115 }
4116 };
4117
4118 sendMsg(new MsgReportSv(*this, svNotify));
4119}
4120
4121void
4122GnssAdapter::reportSv(GnssSvNotification& svNotify)
4123{
4124 int numSv = svNotify.count;
4125 uint16_t gnssSvId = 0;
4126 uint64_t svUsedIdMask = 0;
4127 for (int i=0; i < numSv; i++) {
4128 svUsedIdMask = 0;
4129 gnssSvId = svNotify.gnssSvs[i].svId;
4130 GnssSignalTypeMask signalTypeMask = svNotify.gnssSvs[i].gnssSignalTypeMask;
4131 switch (svNotify.gnssSvs[i].type) {
4132 case GNSS_SV_TYPE_GPS:
4133 if (mGnssSvIdUsedInPosAvail) {
4134 if (mGnssMbSvIdUsedInPosAvail) {
4135 switch (signalTypeMask) {
4136 case GNSS_SIGNAL_GPS_L1CA:
4137 svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l1ca_sv_used_ids_mask;
4138 break;
4139 case GNSS_SIGNAL_GPS_L1C:
4140 svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l1c_sv_used_ids_mask;
4141 break;
4142 case GNSS_SIGNAL_GPS_L2:
4143 svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l2_sv_used_ids_mask;
4144 break;
4145 case GNSS_SIGNAL_GPS_L5:
4146 svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l5_sv_used_ids_mask;
4147 break;
4148 }
4149 } else {
4150 svUsedIdMask = mGnssSvIdUsedInPosition.gps_sv_used_ids_mask;
4151 }
4152 }
4153 break;
4154 case GNSS_SV_TYPE_GLONASS:
4155 if (mGnssSvIdUsedInPosAvail) {
4156 if (mGnssMbSvIdUsedInPosAvail) {
4157 switch (signalTypeMask) {
4158 case GNSS_SIGNAL_GLONASS_G1:
4159 svUsedIdMask = mGnssMbSvIdUsedInPosition.glo_g1_sv_used_ids_mask;
4160 break;
4161 case GNSS_SIGNAL_GLONASS_G2:
4162 svUsedIdMask = mGnssMbSvIdUsedInPosition.glo_g2_sv_used_ids_mask;
4163 break;
4164 }
4165 } else {
4166 svUsedIdMask = mGnssSvIdUsedInPosition.glo_sv_used_ids_mask;
4167 }
4168 }
4169 // map the svid to respective constellation range 1..xx
4170 // then repective constellation svUsedIdMask map correctly to svid
4171 gnssSvId = gnssSvId - GLO_SV_PRN_MIN + 1;
4172 break;
4173 case GNSS_SV_TYPE_BEIDOU:
4174 if (mGnssSvIdUsedInPosAvail) {
4175 if (mGnssMbSvIdUsedInPosAvail) {
4176 switch (signalTypeMask) {
4177 case GNSS_SIGNAL_BEIDOU_B1I:
4178 svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b1i_sv_used_ids_mask;
4179 break;
4180 case GNSS_SIGNAL_BEIDOU_B1C:
4181 svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b1c_sv_used_ids_mask;
4182 break;
4183 case GNSS_SIGNAL_BEIDOU_B2I:
4184 svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b2i_sv_used_ids_mask;
4185 break;
4186 case GNSS_SIGNAL_BEIDOU_B2AI:
4187 svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b2ai_sv_used_ids_mask;
4188 break;
4189 case GNSS_SIGNAL_BEIDOU_B2AQ:
4190 svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b2aq_sv_used_ids_mask;
4191 break;
4192 }
4193 } else {
4194 svUsedIdMask = mGnssSvIdUsedInPosition.bds_sv_used_ids_mask;
4195 }
4196 }
4197 gnssSvId = gnssSvId - BDS_SV_PRN_MIN + 1;
4198 break;
4199 case GNSS_SV_TYPE_GALILEO:
4200 if (mGnssSvIdUsedInPosAvail) {
4201 if (mGnssMbSvIdUsedInPosAvail) {
4202 switch (signalTypeMask) {
4203 case GNSS_SIGNAL_GALILEO_E1:
4204 svUsedIdMask = mGnssMbSvIdUsedInPosition.gal_e1_sv_used_ids_mask;
4205 break;
4206 case GNSS_SIGNAL_GALILEO_E5A:
4207 svUsedIdMask = mGnssMbSvIdUsedInPosition.gal_e5a_sv_used_ids_mask;
4208 break;
4209 case GNSS_SIGNAL_GALILEO_E5B:
4210 svUsedIdMask = mGnssMbSvIdUsedInPosition.gal_e5b_sv_used_ids_mask;
4211 break;
4212 }
4213 } else {
4214 svUsedIdMask = mGnssSvIdUsedInPosition.gal_sv_used_ids_mask;
4215 }
4216 }
4217 gnssSvId = gnssSvId - GAL_SV_PRN_MIN + 1;
4218 break;
4219 case GNSS_SV_TYPE_QZSS:
4220 if (mGnssSvIdUsedInPosAvail) {
4221 if (mGnssMbSvIdUsedInPosAvail) {
4222 switch (signalTypeMask) {
4223 case GNSS_SIGNAL_QZSS_L1CA:
4224 svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l1ca_sv_used_ids_mask;
4225 break;
4226 case GNSS_SIGNAL_QZSS_L1S:
4227 svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l1s_sv_used_ids_mask;
4228 break;
4229 case GNSS_SIGNAL_QZSS_L2:
4230 svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l2_sv_used_ids_mask;
4231 break;
4232 case GNSS_SIGNAL_QZSS_L5:
4233 svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l5_sv_used_ids_mask;
4234 break;
4235 }
4236 } else {
4237 svUsedIdMask = mGnssSvIdUsedInPosition.qzss_sv_used_ids_mask;
4238 }
4239 }
4240 gnssSvId = gnssSvId - QZSS_SV_PRN_MIN + 1;
4241 break;
4242 case GNSS_SV_TYPE_NAVIC:
4243 if (mGnssSvIdUsedInPosAvail) {
4244 svUsedIdMask = mGnssSvIdUsedInPosition.navic_sv_used_ids_mask;
4245 }
4246 gnssSvId = gnssSvId - NAVIC_SV_PRN_MIN + 1;
4247 break;
4248 default:
4249 svUsedIdMask = 0;
4250 break;
4251 }
4252
4253 // If SV ID was used in previous position fix, then set USED_IN_FIX
4254 // flag, else clear the USED_IN_FIX flag.
4255 if (svFitsMask(svUsedIdMask, gnssSvId) && (svUsedIdMask & (1ULL << (gnssSvId - 1)))) {
4256 svNotify.gnssSvs[i].gnssSvOptionsMask |= GNSS_SV_OPTIONS_USED_IN_FIX_BIT;
4257 }
4258 }
4259
4260 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
4261 if (nullptr != it->second.gnssSvCb) {
4262 it->second.gnssSvCb(svNotify);
4263 }
4264 }
4265
4266 if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER &&
4267 !mTimeBasedTrackingSessions.empty()) {
4268 std::vector<std::string> nmeaArraystr;
4269 loc_nmea_generate_sv(svNotify, nmeaArraystr);
4270 stringstream ss;
4271 for (auto itor = nmeaArraystr.begin(); itor != nmeaArraystr.end(); ++itor) {
4272 ss << *itor;
4273 }
4274 string s = ss.str();
4275 reportNmea(s.c_str(), s.length());
4276 }
4277
4278 mGnssSvIdUsedInPosAvail = false;
4279 mGnssMbSvIdUsedInPosAvail = false;
4280}
4281
4282void
4283GnssAdapter::reportNmeaEvent(const char* nmea, size_t length)
4284{
4285 if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER &&
4286 !loc_nmea_is_debug(nmea, length)) {
4287 return;
4288 }
4289
4290 struct MsgReportNmea : public LocMsg {
4291 GnssAdapter& mAdapter;
4292 const char* mNmea;
4293 size_t mLength;
4294 inline MsgReportNmea(GnssAdapter& adapter,
4295 const char* nmea,
4296 size_t length) :
4297 LocMsg(),
4298 mAdapter(adapter),
4299 mNmea(new char[length+1]),
4300 mLength(length) {
4301 if (mNmea == nullptr) {
4302 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
4303 return;
4304 }
4305 strlcpy((char*)mNmea, nmea, length+1);
4306 }
4307 inline virtual ~MsgReportNmea()
4308 {
4309 delete[] mNmea;
4310 }
4311 inline virtual void proc() const {
4312 // extract bug report info - this returns true if consumed by systemstatus
4313 bool ret = false;
4314 SystemStatus* s = mAdapter.getSystemStatus();
4315 if (nullptr != s) {
4316 ret = s->setNmeaString(mNmea, mLength);
4317 }
4318 if (false == ret) {
4319 // forward NMEA message to upper layer
4320 mAdapter.reportNmea(mNmea, mLength);
4321 // DgnssNtrip
4322 mAdapter.reportGGAToNtrip(mNmea);
4323 }
4324 }
4325 };
4326
4327 sendMsg(new MsgReportNmea(*this, nmea, length));
4328}
4329
4330void
4331GnssAdapter::reportNmea(const char* nmea, size_t length)
4332{
4333 GnssNmeaNotification nmeaNotification = {};
4334 nmeaNotification.size = sizeof(GnssNmeaNotification);
4335
4336 struct timeval tv;
4337 gettimeofday(&tv, (struct timezone *) NULL);
4338 int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
4339 nmeaNotification.timestamp = now;
4340 nmeaNotification.nmea = nmea;
4341 nmeaNotification.length = length;
4342
4343 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
4344 if (nullptr != it->second.gnssNmeaCb) {
4345 it->second.gnssNmeaCb(nmeaNotification);
4346 }
4347 }
4348
4349 if (isNMEAPrintEnabled()) {
4350 LOC_LOGd("[%" PRId64 ", %zu] %s", now, length, nmea);
4351 }
4352}
4353
4354void
4355GnssAdapter::reportDataEvent(const GnssDataNotification& dataNotify,
4356 int msInWeek)
4357{
4358 struct MsgReportData : public LocMsg {
4359 GnssAdapter& mAdapter;
4360 GnssDataNotification mDataNotify;
4361 int mMsInWeek;
4362 inline MsgReportData(GnssAdapter& adapter,
4363 const GnssDataNotification& dataNotify,
4364 int msInWeek) :
4365 LocMsg(),
4366 mAdapter(adapter),
4367 mDataNotify(dataNotify),
4368 mMsInWeek(msInWeek) {
4369 }
4370 inline virtual void proc() const {
4371 if (mMsInWeek >= 0) {
4372 mAdapter.getDataInformation((GnssDataNotification&)mDataNotify,
4373 mMsInWeek);
4374 }
4375 mAdapter.reportData((GnssDataNotification&)mDataNotify);
4376 }
4377 };
4378
4379 sendMsg(new MsgReportData(*this, dataNotify, msInWeek));
4380}
4381
4382void
4383GnssAdapter::reportData(GnssDataNotification& dataNotify)
4384{
4385 for (int sig = 0; sig < GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES; sig++) {
4386 if (GNSS_LOC_DATA_JAMMER_IND_BIT ==
4387 (dataNotify.gnssDataMask[sig] & GNSS_LOC_DATA_JAMMER_IND_BIT)) {
4388 LOC_LOGv("jammerInd[%d]=%f", sig, dataNotify.jammerInd[sig]);
4389 }
4390 if (GNSS_LOC_DATA_AGC_BIT ==
4391 (dataNotify.gnssDataMask[sig] & GNSS_LOC_DATA_AGC_BIT)) {
4392 LOC_LOGv("agc[%d]=%f", sig, dataNotify.agc[sig]);
4393 }
4394 }
4395 for (auto it = mClientData.begin(); it != mClientData.end(); ++it) {
4396 if (nullptr != it->second.gnssDataCb) {
4397 it->second.gnssDataCb(dataNotify);
4398 }
4399 }
4400}
4401
4402bool
4403GnssAdapter::requestNiNotifyEvent(const GnssNiNotification &notify, const void* data,
4404 const LocInEmergency emergencyState)
4405{
4406 LOC_LOGI("%s]: notif_type: %d, timeout: %d, default_resp: %d"
4407 "requestor_id: %s (encoding: %d) text: %s text (encoding: %d) extras: %s",
4408 __func__, notify.type, notify.timeout, notify.timeoutResponse,
4409 notify.requestor, notify.requestorEncoding,
4410 notify.message, notify.messageEncoding, notify.extras);
4411
4412 struct MsgReportNiNotify : public LocMsg {
4413 GnssAdapter& mAdapter;
4414 LocApiBase& mApi;
4415 const GnssNiNotification mNotify;
4416 const void* mData;
4417 const LocInEmergency mEmergencyState;
4418 inline MsgReportNiNotify(GnssAdapter& adapter,
4419 LocApiBase& api,
4420 const GnssNiNotification& notify,
4421 const void* data,
4422 const LocInEmergency emergencyState) :
4423 LocMsg(),
4424 mAdapter(adapter),
4425 mApi(api),
4426 mNotify(notify),
4427 mData(data),
4428 mEmergencyState(emergencyState) {}
4429 inline virtual void proc() const {
4430 bool bIsInEmergency = false;
4431 bool bInformNiAccept = false;
4432
4433 bIsInEmergency = ((LOC_IN_EMERGENCY_UNKNOWN == mEmergencyState) &&
4434 mAdapter.getE911State()) || // older modems
4435 (LOC_IN_EMERGENCY_SET == mEmergencyState); // newer modems
4436
4437 if ((mAdapter.mSupportNfwControl || 0 == mAdapter.getAfwControlId()) &&
4438 (GNSS_NI_TYPE_SUPL == mNotify.type || GNSS_NI_TYPE_EMERGENCY_SUPL == mNotify.type)
4439 && !bIsInEmergency &&
4440 !(GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT & mNotify.options) &&
4441 (GNSS_CONFIG_GPS_LOCK_NI & ContextBase::mGps_conf.GPS_LOCK) &&
4442 1 == ContextBase::mGps_conf.NI_SUPL_DENY_ON_NFW_LOCKED) {
4443 /* If all these conditions are TRUE, then deny the NI Request:
4444 -'Q' Lock behavior OR 'P' Lock behavior and GNSS is Locked
4445 -NI SUPL Request type or NI SUPL Emergency Request type
4446 -NOT in an Emergency Call Session
4447 -NOT Privacy Override option
4448 -NFW is locked and config item NI_SUPL_DENY_ON_NFW_LOCKED = 1 */
4449 mApi.informNiResponse(GNSS_NI_RESPONSE_DENY, mData);
4450 } else if (GNSS_NI_TYPE_EMERGENCY_SUPL == mNotify.type) {
4451 bInformNiAccept = bIsInEmergency ||
4452 (GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO == ContextBase::mGps_conf.SUPL_ES);
4453
4454 if (bInformNiAccept) {
4455 mAdapter.requestNiNotify(mNotify, mData, bInformNiAccept);
4456 } else {
4457 mApi.informNiResponse(GNSS_NI_RESPONSE_DENY, mData);
4458 }
4459 } else if (GNSS_NI_TYPE_CONTROL_PLANE == mNotify.type) {
4460 if (bIsInEmergency && (1 == ContextBase::mGps_conf.CP_MTLR_ES)) {
4461 mApi.informNiResponse(GNSS_NI_RESPONSE_ACCEPT, mData);
4462 }
4463 else {
4464 mAdapter.requestNiNotify(mNotify, mData, false);
4465 }
4466 } else {
4467 mAdapter.requestNiNotify(mNotify, mData, false);
4468 }
4469 }
4470 };
4471
4472 sendMsg(new MsgReportNiNotify(*this, *mLocApi, notify, data, emergencyState));
4473
4474 return true;
4475}
4476
4477void
4478GnssAdapter::reportLocationSystemInfoEvent(const LocationSystemInfo & locationSystemInfo) {
4479
4480 // send system info to engine hub
4481 mEngHubProxy->gnssReportSystemInfo(locationSystemInfo);
4482
4483 struct MsgLocationSystemInfo : public LocMsg {
4484 GnssAdapter& mAdapter;
4485 LocationSystemInfo mSystemInfo;
4486 inline MsgLocationSystemInfo(GnssAdapter& adapter,
4487 const LocationSystemInfo& systemInfo) :
4488 LocMsg(),
4489 mAdapter(adapter),
4490 mSystemInfo(systemInfo) {}
4491 inline virtual void proc() const {
4492 mAdapter.reportLocationSystemInfo(mSystemInfo);
4493 }
4494 };
4495
4496 sendMsg(new MsgLocationSystemInfo(*this, locationSystemInfo));
4497}
4498
4499void
4500GnssAdapter::reportLocationSystemInfo(const LocationSystemInfo & locationSystemInfo) {
4501 // save the info into the master copy piece by piece, as other system info
4502 // may come at different time
4503 if (locationSystemInfo.systemInfoMask & LOCATION_SYS_INFO_LEAP_SECOND) {
4504 mLocSystemInfo.systemInfoMask |= LOCATION_SYS_INFO_LEAP_SECOND;
4505
4506 const LeapSecondSystemInfo &srcLeapSecondSysInfo = locationSystemInfo.leapSecondSysInfo;
4507 LeapSecondSystemInfo &dstLeapSecondSysInfo = mLocSystemInfo.leapSecondSysInfo;
4508 if (srcLeapSecondSysInfo.leapSecondInfoMask &
4509 LEAP_SECOND_SYS_INFO_CURRENT_LEAP_SECONDS_BIT) {
4510 dstLeapSecondSysInfo.leapSecondInfoMask |=
4511 LEAP_SECOND_SYS_INFO_CURRENT_LEAP_SECONDS_BIT;
4512 dstLeapSecondSysInfo.leapSecondCurrent = srcLeapSecondSysInfo.leapSecondCurrent;
4513 }
4514 // once leap second change event is complete, modem may send up event invalidate the leap
4515 // second change info while AP is still processing report during leap second transition
4516 // so, we choose to keep this info around even though it is old
4517 if (srcLeapSecondSysInfo.leapSecondInfoMask & LEAP_SECOND_SYS_INFO_LEAP_SECOND_CHANGE_BIT) {
4518 dstLeapSecondSysInfo.leapSecondInfoMask |= LEAP_SECOND_SYS_INFO_LEAP_SECOND_CHANGE_BIT;
4519 dstLeapSecondSysInfo.leapSecondChangeInfo = srcLeapSecondSysInfo.leapSecondChangeInfo;
4520 }
4521 }
4522
4523 // we received new info, inform client of the newly received info
4524 if (locationSystemInfo.systemInfoMask) {
4525 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
4526 if (it->second.locationSystemInfoCb != nullptr) {
4527 it->second.locationSystemInfoCb(locationSystemInfo);
4528 }
4529 }
4530 }
4531}
4532
4533static void* niThreadProc(void *args)
4534{
4535 NiSession* pSession = (NiSession*)args;
4536 int rc = 0; /* return code from pthread calls */
4537
4538 struct timespec present_time;
4539 struct timespec expire_time;
4540
4541 pthread_mutex_lock(&pSession->tLock);
4542 /* Calculate absolute expire time */
4543 clock_gettime(CLOCK_MONOTONIC, &present_time);
4544 expire_time.tv_sec = present_time.tv_sec + pSession->respTimeLeft;
4545 expire_time.tv_nsec = present_time.tv_nsec;
4546 LOC_LOGD("%s]: time out set for abs time %ld with delay %d sec",
4547 __func__, (long)expire_time.tv_sec, pSession->respTimeLeft);
4548
4549 while (!pSession->respRecvd) {
4550 rc = pthread_cond_timedwait(&pSession->tCond,
4551 &pSession->tLock,
4552 &expire_time);
4553 if (rc == ETIMEDOUT) {
4554 pSession->resp = GNSS_NI_RESPONSE_NO_RESPONSE;
4555 LOC_LOGD("%s]: time out after valting for specified time. Ret Val %d",
4556 __func__, rc);
4557 break;
4558 }
4559 }
4560 LOC_LOGD("%s]: Java layer has sent us a user response and return value from "
4561 "pthread_cond_timedwait = %d pSession->resp is %u", __func__, rc, pSession->resp);
4562 pSession->respRecvd = false; /* Reset the user response flag for the next session*/
4563
4564 // adding this check to support modem restart, in which case, we need the thread
4565 // to exit without calling sending data. We made sure that rawRequest is NULL in
4566 // loc_eng_ni_reset_on_engine_restart()
4567 GnssAdapter* adapter = pSession->adapter;
4568 GnssNiResponse resp;
4569 void* rawRequest = NULL;
4570 bool sendResponse = false;
4571
4572 if (NULL != pSession->rawRequest) {
4573 if (pSession->resp != GNSS_NI_RESPONSE_IGNORE) {
4574 resp = pSession->resp;
4575 rawRequest = pSession->rawRequest;
4576 sendResponse = true;
4577 } else {
4578 free(pSession->rawRequest);
4579 }
4580 pSession->rawRequest = NULL;
4581 }
4582 pthread_mutex_unlock(&pSession->tLock);
4583
4584 pSession->respTimeLeft = 0;
4585 pSession->reqID = 0;
4586
4587 if (sendResponse) {
4588 adapter->gnssNiResponseCommand(resp, rawRequest);
4589 }
4590
4591 return NULL;
4592}
4593
4594bool
4595GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data,
4596 const bool bInformNiAccept)
4597{
4598 NiSession* pSession = NULL;
4599 gnssNiCallback gnssNiCb = nullptr;
4600
4601 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
4602 if (nullptr != it->second.gnssNiCb) {
4603 gnssNiCb = it->second.gnssNiCb;
4604 break;
4605 }
4606 }
4607 if (nullptr == gnssNiCb) {
4608 if (GNSS_NI_TYPE_EMERGENCY_SUPL == notify.type) {
4609 if (bInformNiAccept) {
4610 mLocApi->informNiResponse(GNSS_NI_RESPONSE_ACCEPT, data);
4611 NiData& niData = getNiData();
4612 // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
4613 if (NULL != niData.session.rawRequest) {
4614 pthread_mutex_lock(&niData.session.tLock);
4615 niData.session.resp = GNSS_NI_RESPONSE_IGNORE;
4616 niData.session.respRecvd = true;
4617 pthread_cond_signal(&niData.session.tCond);
4618 pthread_mutex_unlock(&niData.session.tLock);
4619 }
4620 }
4621 }
4622 EXIT_LOG(%s, "no clients with gnssNiCb.");
4623 return false;
4624 }
4625
4626 if (notify.type == GNSS_NI_TYPE_EMERGENCY_SUPL) {
4627 if (NULL != mNiData.sessionEs.rawRequest) {
4628 LOC_LOGI("%s]: supl es NI in progress, new supl es NI ignored, type: %d",
4629 __func__, notify.type);
4630 if (NULL != data) {
4631 free((void*)data);
4632 }
4633 } else {
4634 pSession = &mNiData.sessionEs;
4635 }
4636 } else {
4637 if (NULL != mNiData.session.rawRequest ||
4638 NULL != mNiData.sessionEs.rawRequest) {
4639 LOC_LOGI("%s]: supl NI in progress, new supl NI ignored, type: %d",
4640 __func__, notify.type);
4641 if (NULL != data) {
4642 free((void*)data);
4643 }
4644 } else {
4645 pSession = &mNiData.session;
4646 }
4647 }
4648
4649 if (pSession) {
4650 /* Save request */
4651 pSession->rawRequest = (void*)data;
4652 pSession->reqID = ++mNiData.reqIDCounter;
4653 pSession->adapter = this;
4654
4655 int sessionId = pSession->reqID;
4656
4657 /* For robustness, spawn a thread at this point to timeout to clear up the notification
4658 * status, even though the OEM layer in java does not do so.
4659 **/
4660 pSession->respTimeLeft =
4661 5 + (notify.timeout != 0 ? notify.timeout : LOC_NI_NO_RESPONSE_TIME);
4662
4663 int rc = 0;
4664 rc = pthread_create(&pSession->thread, NULL, niThreadProc, pSession);
4665 if (rc) {
4666 LOC_LOGE("%s]: Loc NI thread is not created.", __func__);
4667 }
4668 rc = pthread_detach(pSession->thread);
4669 if (rc) {
4670 LOC_LOGE("%s]: Loc NI thread is not detached.", __func__);
4671 }
4672
4673 if (nullptr != gnssNiCb) {
4674 gnssNiCb(sessionId, notify);
4675 }
4676 }
4677
4678 return true;
4679}
4680
4681void
4682GnssAdapter::reportGnssMeasurementsEvent(const GnssMeasurements& gnssMeasurements,
4683 int msInWeek)
4684{
4685 LOC_LOGD("%s]: msInWeek=%d", __func__, msInWeek);
4686
4687 if (0 != gnssMeasurements.gnssMeasNotification.count) {
4688 struct MsgReportGnssMeasurementData : public LocMsg {
4689 GnssAdapter& mAdapter;
4690 GnssMeasurements mGnssMeasurements;
4691 GnssMeasurementsNotification mMeasurementsNotify;
4692 inline MsgReportGnssMeasurementData(GnssAdapter& adapter,
4693 const GnssMeasurements& gnssMeasurements,
4694 int msInWeek) :
4695 LocMsg(),
4696 mAdapter(adapter),
4697 mMeasurementsNotify(gnssMeasurements.gnssMeasNotification) {
4698 if (-1 != msInWeek) {
4699 mAdapter.getAgcInformation(mMeasurementsNotify, msInWeek);
4700 }
4701 }
4702 inline virtual void proc() const {
4703 mAdapter.reportGnssMeasurementData(mMeasurementsNotify);
4704 }
4705 };
4706
4707 sendMsg(new MsgReportGnssMeasurementData(*this, gnssMeasurements, msInWeek));
4708 }
4709 mEngHubProxy->gnssReportSvMeasurement(gnssMeasurements.gnssSvMeasurementSet);
4710 if (mDGnssNeedReport) {
4711 reportDGnssDataUsable(gnssMeasurements.gnssSvMeasurementSet);
4712 }
4713}
4714
4715void
4716GnssAdapter::reportGnssMeasurementData(const GnssMeasurementsNotification& measurements)
4717{
4718 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
4719 if (nullptr != it->second.gnssMeasurementsCb) {
4720 it->second.gnssMeasurementsCb(measurements);
4721 }
4722 }
4723}
4724
4725void
4726GnssAdapter::reportDGnssDataUsable(const GnssSvMeasurementSet &svMeasurementSet)
4727{
4728 uint32_t i;
4729 bool preDGnssDataUsage = mDGnssDataUsage;
4730
4731 mDGnssDataUsage = false;
4732 for (i = 0; i < svMeasurementSet.svMeasCount; i++) {
4733 const Gnss_SVMeasurementStructType& svMeas = svMeasurementSet.svMeas[i];
4734 if (svMeas.dgnssSvMeas.dgnssMeasStatus) {
4735 mDGnssDataUsage = true;
4736 break;
4737 }
4738 }
4739 if (mDGnssDataUsage != preDGnssDataUsage) {
4740 if (mCdfwInterface) {
4741 mCdfwInterface->reportUsable(mQDgnssListenerHDL, mDGnssDataUsage);
4742 }
4743 }
4744}
4745
4746void
4747GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial)
4748{
4749 LOC_LOGD("%s]: ", __func__);
4750 mEngHubProxy->gnssReportSvPolynomial(svPolynomial);
4751}
4752
4753void
4754GnssAdapter::reportSvEphemerisEvent(GnssSvEphemerisReport & svEphemeris)
4755{
4756 LOC_LOGD("%s]:", __func__);
4757 mEngHubProxy->gnssReportSvEphemeris(svEphemeris);
4758}
4759
4760
4761bool
4762GnssAdapter::requestOdcpiEvent(OdcpiRequestInfo& request)
4763{
4764 struct MsgRequestOdcpi : public LocMsg {
4765 GnssAdapter& mAdapter;
4766 OdcpiRequestInfo mOdcpiRequest;
4767 inline MsgRequestOdcpi(GnssAdapter& adapter, OdcpiRequestInfo& request) :
4768 LocMsg(),
4769 mAdapter(adapter),
4770 mOdcpiRequest(request) {}
4771 inline virtual void proc() const {
4772 mAdapter.requestOdcpi(mOdcpiRequest);
4773 }
4774 };
4775
4776 sendMsg(new MsgRequestOdcpi(*this, request));
4777 return true;
4778}
4779
4780void GnssAdapter::requestOdcpi(const OdcpiRequestInfo& request)
4781{
4782 if (nullptr != mOdcpiRequestCb) {
Michael Bestas9f1f76e2024-05-28 23:23:20 +03004783 bool sendEmergencyCallStatusEvent = false;
Michael Bestas3a0209e2023-05-04 01:15:47 +03004784 LOC_LOGd("request: type %d, tbf %d, isEmergency %d"
4785 " requestActive: %d timerActive: %d",
4786 request.type, request.tbfMillis, request.isEmergencyMode,
4787 mOdcpiRequestActive, mOdcpiTimer.isActive());
4788 // ODCPI START and ODCPI STOP from modem can come in quick succession
4789 // so the mOdcpiTimer helps avoid spamming the framework as well as
4790 // extending the odcpi session past 30 seconds if needed
Michael Bestas9f1f76e2024-05-28 23:23:20 +03004791
Michael Bestas3a0209e2023-05-04 01:15:47 +03004792 if (ODCPI_REQUEST_TYPE_START == request.type) {
Michael Bestas9f1f76e2024-05-28 23:23:20 +03004793 if (!(mOdcpiStateMask & ODCPI_REQ_ACTIVE) && false == mOdcpiTimer.isActive()) {
4794 fireOdcpiRequest(request);
4795 mOdcpiStateMask |= ODCPI_REQ_ACTIVE;
Michael Bestas3a0209e2023-05-04 01:15:47 +03004796 mOdcpiTimer.start();
Michael Bestas9f1f76e2024-05-28 23:23:20 +03004797 sendEmergencyCallStatusEvent = true;
Michael Bestas3a0209e2023-05-04 01:15:47 +03004798 // if the current active odcpi session is non-emergency, and the new
4799 // odcpi request is emergency, replace the odcpi request with new request
4800 // and restart the timer
4801 } else if (false == mOdcpiRequest.isEmergencyMode &&
4802 true == request.isEmergencyMode) {
Michael Bestas9f1f76e2024-05-28 23:23:20 +03004803 fireOdcpiRequest(request);
4804 mOdcpiStateMask |= ODCPI_REQ_ACTIVE;
Michael Bestas3a0209e2023-05-04 01:15:47 +03004805 if (true == mOdcpiTimer.isActive()) {
4806 mOdcpiTimer.restart();
4807 } else {
4808 mOdcpiTimer.start();
4809 }
Michael Bestas9f1f76e2024-05-28 23:23:20 +03004810 sendEmergencyCallStatusEvent = true;
Michael Bestas3a0209e2023-05-04 01:15:47 +03004811 // if ODCPI request is not active but the timer is active, then
4812 // just update the active state and wait for timer to expire
4813 // before requesting new ODCPI to avoid spamming ODCPI requests
4814 } else if (false == mOdcpiRequestActive && true == mOdcpiTimer.isActive()) {
4815 mOdcpiRequestActive = true;
4816 }
4817 mOdcpiRequest = request;
4818 // the request is being stopped, but allow timer to expire first
4819 // before stopping the timer just in case more ODCPI requests come
4820 // to avoid spamming more odcpi requests to the framework
4821 } else if (ODCPI_REQUEST_TYPE_STOP == request.type) {
4822 LOC_LOGd("request: type %d, isEmergency %d", request.type, request.isEmergencyMode);
Michael Bestas9f1f76e2024-05-28 23:23:20 +03004823 fireOdcpiRequest(request);
4824 mOdcpiStateMask = 0;
4825 sendEmergencyCallStatusEvent = true;
Michael Bestas3a0209e2023-05-04 01:15:47 +03004826 } else {
4827 LOC_LOGE("Invalid ODCPI request type..");
4828 }
Michael Bestas9f1f76e2024-05-28 23:23:20 +03004829
4830 // Raise InEmergencyCall event
4831 if (sendEmergencyCallStatusEvent && request.isEmergencyMode) {
4832 SystemStatus* systemstatus = getSystemStatus();
4833 if (nullptr != systemstatus) {
4834 systemstatus->eventInEmergencyCall(0 != mOdcpiStateMask);
4835 } else {
4836 LOC_LOGe("Failed to get system status instance.");
4837 }
4838 }
Michael Bestas3a0209e2023-05-04 01:15:47 +03004839 } else {
4840 LOC_LOGw("ODCPI request not supported");
4841 }
4842}
4843
4844bool GnssAdapter::reportDeleteAidingDataEvent(GnssAidingData& aidingData)
4845{
4846 LOC_LOGD("%s]:", __func__);
4847 mEngHubProxy->gnssDeleteAidingData(aidingData);
4848 return true;
4849}
4850
4851bool GnssAdapter::reportKlobucharIonoModelEvent(GnssKlobucharIonoModel & ionoModel)
4852{
4853 LOC_LOGD("%s]:", __func__);
4854 mEngHubProxy->gnssReportKlobucharIonoModel(ionoModel);
4855 return true;
4856}
4857
4858bool GnssAdapter::reportGnssAdditionalSystemInfoEvent(
4859 GnssAdditionalSystemInfo & additionalSystemInfo)
4860{
4861 LOC_LOGD("%s]:", __func__);
4862 mEngHubProxy->gnssReportAdditionalSystemInfo(additionalSystemInfo);
4863 return true;
4864}
4865
4866bool GnssAdapter::reportQwesCapabilities(
4867 const std::unordered_map<LocationQwesFeatureType, bool> &featureMap)
4868{
4869 struct MsgReportQwesFeatureStatus : public LocMsg {
4870 GnssAdapter& mAdapter;
4871 const std::unordered_map<LocationQwesFeatureType, bool> mFeatureMap;
4872 inline MsgReportQwesFeatureStatus(GnssAdapter& adapter,
4873 const std::unordered_map<LocationQwesFeatureType, bool> &featureMap) :
4874 LocMsg(),
4875 mAdapter(adapter),
4876 mFeatureMap(std::move(featureMap)) {}
4877 inline virtual void proc() const {
Michael Bestas3a0209e2023-05-04 01:15:47 +03004878 LOC_LOGi("ReportQwesFeatureStatus After caps %" PRIx64 " ",
4879 mAdapter.getCapabilities());
4880 mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
4881 }
4882 };
4883
4884 sendMsg(new MsgReportQwesFeatureStatus(*this, featureMap));
4885 return true;
4886}
4887
4888void GnssAdapter::initOdcpiCommand(const OdcpiRequestCallback& callback,
Michael Bestas9f1f76e2024-05-28 23:23:20 +03004889 OdcpiPrioritytype priority,
4890 OdcpiCallbackTypeMask typeMask)
Michael Bestas3a0209e2023-05-04 01:15:47 +03004891{
4892 struct MsgInitOdcpi : public LocMsg {
4893 GnssAdapter& mAdapter;
4894 OdcpiRequestCallback mOdcpiCb;
4895 OdcpiPrioritytype mPriority;
Michael Bestas9f1f76e2024-05-28 23:23:20 +03004896 OdcpiCallbackTypeMask mTypeMask;
Michael Bestas3a0209e2023-05-04 01:15:47 +03004897 inline MsgInitOdcpi(GnssAdapter& adapter,
4898 const OdcpiRequestCallback& callback,
Michael Bestas9f1f76e2024-05-28 23:23:20 +03004899 OdcpiPrioritytype priority,
4900 OdcpiCallbackTypeMask typeMask) :
Michael Bestas3a0209e2023-05-04 01:15:47 +03004901 LocMsg(),
4902 mAdapter(adapter),
Michael Bestas9f1f76e2024-05-28 23:23:20 +03004903 mOdcpiCb(callback), mPriority(priority),
4904 mTypeMask(typeMask) {}
Michael Bestas3a0209e2023-05-04 01:15:47 +03004905 inline virtual void proc() const {
Michael Bestas9f1f76e2024-05-28 23:23:20 +03004906 mAdapter.initOdcpi(mOdcpiCb, mPriority, mTypeMask);
Michael Bestas3a0209e2023-05-04 01:15:47 +03004907 }
4908 };
4909
Michael Bestas9f1f76e2024-05-28 23:23:20 +03004910 sendMsg(new MsgInitOdcpi(*this, callback, priority, typeMask));
4911}
4912
4913void GnssAdapter::deRegisterOdcpiCommand(OdcpiPrioritytype priority,
4914 OdcpiCallbackTypeMask typeMask) {
4915 struct MsgDeRegisterNonEsOdcpi : public LocMsg {
4916 GnssAdapter& mAdapter;
4917 OdcpiPrioritytype mPriority;
4918 OdcpiCallbackTypeMask mTypeMask;
4919 inline MsgDeRegisterNonEsOdcpi(GnssAdapter& adapter,
4920 OdcpiPrioritytype priority,
4921 OdcpiCallbackTypeMask typeMask) :
4922 LocMsg(),
4923 mAdapter(adapter),
4924 mPriority(priority),
4925 mTypeMask(typeMask) {}
4926 inline virtual void proc() const {
4927 mAdapter.deRegisterOdcpi(mPriority, mTypeMask);
4928 }
4929 };
4930
4931 sendMsg(new MsgDeRegisterNonEsOdcpi(*this, priority, typeMask));
4932}
4933
4934void GnssAdapter::fireOdcpiRequest(const OdcpiRequestInfo& request) {
4935 if (request.isEmergencyMode) {
4936 mOdcpiRequestCb(request);
4937 } else {
4938 std::unordered_map<OdcpiPrioritytype, OdcpiRequestCallback>::iterator iter;
4939 for (int priority = ODCPI_HANDLER_PRIORITY_HIGH;
4940 priority >= ODCPI_HANDLER_PRIORITY_LOW && iter == mNonEsOdcpiReqCbMap.end();
4941 priority--) {
4942 iter = mNonEsOdcpiReqCbMap.find((OdcpiPrioritytype)priority);
4943 }
4944 if (iter != mNonEsOdcpiReqCbMap.end()) {
4945 iter->second(request);
4946 }
4947 }
Michael Bestas3a0209e2023-05-04 01:15:47 +03004948}
4949
4950void GnssAdapter::initOdcpi(const OdcpiRequestCallback& callback,
Michael Bestas9f1f76e2024-05-28 23:23:20 +03004951 OdcpiPrioritytype priority, OdcpiCallbackTypeMask typeMask) {
4952 if (typeMask & EMERGENCY_ODCPI) {
4953 LOC_LOGd("In priority: %d, Curr priority: %d", priority, mCallbackPriority);
4954 if (priority >= mCallbackPriority) {
4955 mOdcpiRequestCb = callback;
4956 mCallbackPriority = priority;
4957 /* Register for WIFI request */
4958 updateEvtMask(LOC_API_ADAPTER_BIT_REQUEST_WIFI,
4959 LOC_REGISTRATION_MASK_ENABLED);
4960 }
4961 }
4962 if (typeMask & NON_EMERGENCY_ODCPI) {
4963 //If this is for non emergency odcpi,
4964 //Only set callback to mNonEsOdcpiReqCbMap according to its priority
4965 //Will overwrite callback with same priority in this map
4966 mNonEsOdcpiReqCbMap[priority] = callback;
Michael Bestas3a0209e2023-05-04 01:15:47 +03004967 }
4968}
4969
4970void GnssAdapter::injectOdcpiCommand(const Location& location)
4971{
4972 struct MsgInjectOdcpi : public LocMsg {
4973 GnssAdapter& mAdapter;
4974 Location mLocation;
4975 inline MsgInjectOdcpi(GnssAdapter& adapter, const Location& location) :
4976 LocMsg(),
4977 mAdapter(adapter),
4978 mLocation(location) {}
4979 inline virtual void proc() const {
4980 mAdapter.injectOdcpi(mLocation);
4981 }
4982 };
4983
4984 sendMsg(new MsgInjectOdcpi(*this, location));
4985}
4986
4987void GnssAdapter::injectOdcpi(const Location& location)
4988{
4989 LOC_LOGd("ODCPI Injection: requestActive: %d timerActive: %d"
4990 "lat %.7f long %.7f",
4991 mOdcpiRequestActive, mOdcpiTimer.isActive(),
4992 location.latitude, location.longitude);
4993
4994 mLocApi->injectPosition(location, true);
4995}
4996
4997// Called in the context of LocTimer thread
4998void OdcpiTimer::timeOutCallback()
4999{
5000 if (nullptr != mAdapter) {
5001 mAdapter->odcpiTimerExpireEvent();
5002 }
5003}
5004
5005// Called in the context of LocTimer thread
5006void GnssAdapter::odcpiTimerExpireEvent()
5007{
5008 struct MsgOdcpiTimerExpire : public LocMsg {
5009 GnssAdapter& mAdapter;
5010 inline MsgOdcpiTimerExpire(GnssAdapter& adapter) :
5011 LocMsg(),
5012 mAdapter(adapter) {}
5013 inline virtual void proc() const {
5014 mAdapter.odcpiTimerExpire();
5015 }
5016 };
5017 sendMsg(new MsgOdcpiTimerExpire(*this));
5018}
5019void GnssAdapter::odcpiTimerExpire()
5020{
5021 LOC_LOGd("requestActive: %d timerActive: %d",
5022 mOdcpiRequestActive, mOdcpiTimer.isActive());
5023
5024 // if ODCPI request is still active after timer
5025 // expires, request again and restart timer
Michael Bestas9f1f76e2024-05-28 23:23:20 +03005026 if (mOdcpiStateMask & ODCPI_REQ_ACTIVE) {
5027 fireOdcpiRequest(mOdcpiRequest);
Michael Bestas3a0209e2023-05-04 01:15:47 +03005028 mOdcpiTimer.restart();
5029 } else {
5030 mOdcpiTimer.stop();
5031 }
5032}
5033
5034void
5035GnssAdapter::invokeGnssEnergyConsumedCallback(uint64_t energyConsumedSinceFirstBoot) {
5036 if (mGnssEnergyConsumedCb) {
5037 mGnssEnergyConsumedCb(energyConsumedSinceFirstBoot);
5038 mGnssEnergyConsumedCb = nullptr;
5039 }
5040}
5041
5042bool
5043GnssAdapter::reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot){
5044 LOC_LOGD("%s]: %" PRIu64 " ", __func__, energyConsumedSinceFirstBoot);
5045
5046 struct MsgReportGnssGnssEngEnergyConsumed : public LocMsg {
5047 GnssAdapter& mAdapter;
5048 uint64_t mGnssEnergyConsumedSinceFirstBoot;
5049 inline MsgReportGnssGnssEngEnergyConsumed(GnssAdapter& adapter,
5050 uint64_t energyConsumed) :
5051 LocMsg(),
5052 mAdapter(adapter),
5053 mGnssEnergyConsumedSinceFirstBoot(energyConsumed) {}
5054 inline virtual void proc() const {
5055 mAdapter.invokeGnssEnergyConsumedCallback(mGnssEnergyConsumedSinceFirstBoot);
5056 }
5057 };
5058
5059 sendMsg(new MsgReportGnssGnssEngEnergyConsumed(*this, energyConsumedSinceFirstBoot));
5060 return true;
5061}
5062
5063void GnssAdapter::initDefaultAgps() {
5064 LOC_LOGD("%s]: ", __func__);
5065 void *handle = nullptr;
5066
5067 LocAgpsGetAgpsCbInfo getAgpsCbInfo =
5068 (LocAgpsGetAgpsCbInfo)dlGetSymFromLib(handle, "libloc_net_iface.so",
5069 "LocNetIfaceAgps_getAgpsCbInfo");
5070 // Below step is to make sure we init nativeAgpsHandler
5071 // for Android platforms only
5072 AgpsCbInfo cbInfo = {};
5073 if (nullptr != getAgpsCbInfo) {
5074 cbInfo = getAgpsCbInfo(agpsOpenResultCb, agpsCloseResultCb, this);
5075 } else {
5076 cbInfo = mNativeAgpsHandler.getAgpsCbInfo();
5077 }
5078
5079 if (cbInfo.statusV4Cb == nullptr) {
5080 LOC_LOGE("%s]: statusV4Cb is nullptr!", __func__);
5081 dlclose(handle);
5082 return;
5083 }
5084
5085 initAgps(cbInfo);
5086}
5087
5088void GnssAdapter::initDefaultAgpsCommand() {
5089 LOC_LOGD("%s]: ", __func__);
5090
5091 struct MsgInitDefaultAgps : public LocMsg {
5092 GnssAdapter& mAdapter;
5093 inline MsgInitDefaultAgps(GnssAdapter& adapter) :
5094 LocMsg(),
5095 mAdapter(adapter) {
5096 }
5097 inline virtual void proc() const {
5098 mAdapter.initDefaultAgps();
5099 }
5100 };
5101
5102 sendMsg(new MsgInitDefaultAgps(*this));
5103}
5104
5105/* INIT LOC AGPS MANAGER */
5106
5107void GnssAdapter::initAgps(const AgpsCbInfo& cbInfo) {
5108 LOC_LOGD("%s]:cbInfo.atlType - %d", __func__, cbInfo.atlType);
5109
5110 if (!((ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSB) ||
5111 (ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSA))) {
5112 return;
5113 }
5114
5115 mAgpsManager.createAgpsStateMachines(cbInfo);
5116 /* Register for AGPS event mask */
5117 updateEvtMask(LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST,
5118 LOC_REGISTRATION_MASK_ENABLED);
5119}
5120
5121void GnssAdapter::initAgpsCommand(const AgpsCbInfo& cbInfo){
5122 LOC_LOGI("GnssAdapter::initAgpsCommand");
5123
5124 /* Message to initialize AGPS module */
5125 struct AgpsMsgInit: public LocMsg {
5126 const AgpsCbInfo mCbInfo;
5127 GnssAdapter& mAdapter;
5128
5129 inline AgpsMsgInit(const AgpsCbInfo& cbInfo,
5130 GnssAdapter& adapter) :
5131 LocMsg(), mCbInfo(cbInfo), mAdapter(adapter) {
5132 LOC_LOGV("AgpsMsgInit");
5133 }
5134
5135 inline virtual void proc() const {
5136 LOC_LOGV("AgpsMsgInit::proc()");
5137 mAdapter.initAgps(mCbInfo);
5138 }
5139 };
5140
5141 /* Send message to initialize AGPS Manager */
5142 sendMsg(new AgpsMsgInit(cbInfo, *this));
5143}
5144
5145void GnssAdapter::initNfwCommand(const NfwCbInfo& cbInfo) {
5146 LOC_LOGi("GnssAdapter::initNfwCommand");
5147
5148 /* Message to initialize NFW */
5149 struct MsgInitNfw : public LocMsg {
5150 const NfwCbInfo mCbInfo;
5151 GnssAdapter& mAdapter;
5152
5153 inline MsgInitNfw(const NfwCbInfo& cbInfo,
5154 GnssAdapter& adapter) :
5155 LocMsg(), mCbInfo(cbInfo), mAdapter(adapter) {
5156 LOC_LOGv("MsgInitNfw");
5157 }
5158
5159 inline virtual void proc() const {
5160 LOC_LOGv("MsgInitNfw::proc()");
5161 mAdapter.initNfw(mCbInfo);
5162 }
5163 };
5164
5165 /* Send message to initialize NFW */
5166 sendMsg(new MsgInitNfw(cbInfo, *this));
5167}
5168
5169void GnssAdapter::reportNfwNotificationEvent(GnssNfwNotification& notification) {
5170 LOC_LOGi("GnssAdapter::reportNfwNotificationEvent");
5171
5172 struct MsgReportNfwNotification : public LocMsg {
5173 const GnssNfwNotification mNotification;
5174 GnssAdapter& mAdapter;
5175
5176 inline MsgReportNfwNotification(const GnssNfwNotification& notification,
5177 GnssAdapter& adapter) :
5178 LocMsg(), mNotification(notification), mAdapter(adapter) {
5179 LOC_LOGv("MsgReportNfwNotification");
5180 }
5181
5182 inline virtual void proc() const {
5183 LOC_LOGv("MsgReportNfwNotification::proc()");
5184 mAdapter.reportNfwNotification(mNotification);
5185 }
5186 };
5187
5188 sendMsg(new MsgReportNfwNotification(notification, *this));
5189}
5190
5191/* GnssAdapter::requestATL
5192 * Method triggered in QMI thread as part of handling below message:
5193 * eQMI_LOC_SERVER_REQUEST_OPEN_V02
5194 * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
5195 * eQMI_LOC_WWAN_TYPE_INTERNET_V02
5196 * eQMI_LOC_WWAN_TYPE_AGNSS_V02
5197 * eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02 */
5198bool GnssAdapter::requestATL(int connHandle, LocAGpsType agpsType,
5199 LocApnTypeMask apnTypeMask){
5200
5201 LOC_LOGI("GnssAdapter::requestATL handle=%d agpsType=0x%X apnTypeMask=0x%X",
5202 connHandle, agpsType, apnTypeMask);
5203
5204 sendMsg( new AgpsMsgRequestATL(
5205 &mAgpsManager, connHandle, (AGpsExtType)agpsType,
5206 apnTypeMask));
5207
5208 return true;
5209}
5210
5211/* GnssAdapter::releaseATL
5212 * Method triggered in QMI thread as part of handling below message:
5213 * eQMI_LOC_SERVER_REQUEST_CLOSE_V02
5214 * Triggers teardown of an existing AGPS call */
5215bool GnssAdapter::releaseATL(int connHandle){
5216
5217 LOC_LOGI("GnssAdapter::releaseATL");
5218
5219 /* Release SUPL/INTERNET/SUPL_ES ATL */
5220 struct AgpsMsgReleaseATL: public LocMsg {
5221
5222 AgpsManager* mAgpsManager;
5223 int mConnHandle;
5224
5225 inline AgpsMsgReleaseATL(AgpsManager* agpsManager, int connHandle) :
5226 LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle) {
5227
5228 LOC_LOGV("AgpsMsgReleaseATL");
5229 }
5230
5231 inline virtual void proc() const {
5232
5233 LOC_LOGV("AgpsMsgReleaseATL::proc()");
5234 mAgpsManager->releaseATL(mConnHandle);
5235 }
5236 };
5237
5238 sendMsg( new AgpsMsgReleaseATL(&mAgpsManager, connHandle));
5239
5240 return true;
5241}
5242
5243void GnssAdapter::reportPdnTypeFromWds(int pdnType, AGpsExtType agpsType, std::string apnName,
5244 AGpsBearerType bearerType) {
5245 LOC_LOGd("pdnType from WDS QMI: %d, agpsType: %d, apnName: %s, bearerType: %d",
5246 pdnType, agpsType, apnName.c_str(), bearerType);
5247
5248 struct MsgReportAtlPdn : public LocMsg {
5249 GnssAdapter& mAdapter;
5250 int mPdnType;
5251 AgpsManager* mAgpsManager;
5252 AGpsExtType mAgpsType;
5253 string mApnName;
5254 AGpsBearerType mBearerType;
5255
5256 inline MsgReportAtlPdn(GnssAdapter& adapter, int pdnType,
5257 AgpsManager* agpsManager, AGpsExtType agpsType,
5258 const string& apnName, AGpsBearerType bearerType) :
Albert Ib8416c92021-06-25 19:34:31 +08005259 LocMsg(), mAdapter(adapter), mPdnType(pdnType),
5260 mAgpsManager(agpsManager), mAgpsType(agpsType),
5261 mApnName(apnName), mBearerType(bearerType) {}
Michael Bestas3a0209e2023-05-04 01:15:47 +03005262 inline virtual void proc() const {
5263 mAgpsManager->reportAtlOpenSuccess(mAgpsType,
5264 const_cast<char*>(mApnName.c_str()),
5265 mApnName.length(), mPdnType<=0? mBearerType:mPdnType);
5266 }
5267 };
5268
5269 AGpsBearerType atlPdnType = (pdnType+1) & 3; // convert WDS QMI pdn type to AgpsBearerType
5270 sendMsg(new MsgReportAtlPdn(*this, atlPdnType, &mAgpsManager,
5271 agpsType, apnName, bearerType));
5272}
5273
5274
5275void GnssAdapter::dataConnOpenCommand(
5276 AGpsExtType agpsType,
5277 const char* apnName, int apnLen, AGpsBearerType bearerType){
5278
5279 LOC_LOGI("GnssAdapter::frameworkDataConnOpen");
5280
5281 struct AgpsMsgAtlOpenSuccess: public LocMsg {
5282 GnssAdapter& mAdapter;
5283 AgpsManager* mAgpsManager;
5284 AGpsExtType mAgpsType;
5285 char* mApnName;
5286 AGpsBearerType mBearerType;
5287
5288 inline AgpsMsgAtlOpenSuccess(GnssAdapter& adapter, AgpsManager* agpsManager,
5289 AGpsExtType agpsType, const char* apnName, int apnLen, AGpsBearerType bearerType) :
Albert Ib8416c92021-06-25 19:34:31 +08005290 LocMsg(), mAdapter(adapter), mAgpsManager(agpsManager), mAgpsType(agpsType),
5291 mApnName(new char[apnLen + 1]), mBearerType(bearerType) {
Michael Bestas3a0209e2023-05-04 01:15:47 +03005292
5293 LOC_LOGV("AgpsMsgAtlOpenSuccess");
5294 if (mApnName == nullptr) {
5295 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
5296 // Reporting the failure here
5297 mAgpsManager->reportAtlClosed(mAgpsType);
5298 return;
5299 }
5300 memcpy(mApnName, apnName, apnLen);
5301 mApnName[apnLen] = 0;
5302 }
5303
5304 inline ~AgpsMsgAtlOpenSuccess() {
5305 delete[] mApnName;
5306 }
5307
5308 inline virtual void proc() const {
5309 LOC_LOGv("AgpsMsgAtlOpenSuccess::proc()");
5310 string apn(mApnName);
5311 //Use QMI WDS API to query IP Protocol from modem profile
5312 void* libHandle = nullptr;
5313 getPdnTypeFromWds* getPdnTypeFunc = (getPdnTypeFromWds*)dlGetSymFromLib(libHandle,
5314 #ifdef USE_GLIB
5315 "libloc_api_wds.so", "_Z10getPdnTypeRKNSt7__cxx1112basic_string"\
5316 "IcSt11char_traitsIcESaIcEEESt8functionIFviEE");
5317 #else
5318 "libloc_api_wds.so", "_Z10getPdnTypeRKNSt3__112basic_stringIcNS_11char_traits"\
5319 "IcEENS_9allocatorIcEEEENS_8functionIFviEEE");
5320 #endif
5321
5322 std::function<void(int)> wdsPdnTypeCb = std::bind(&GnssAdapter::reportPdnTypeFromWds,
5323 &mAdapter, std::placeholders::_1, mAgpsType, apn, mBearerType);
5324 if (getPdnTypeFunc != nullptr) {
5325 LOC_LOGv("dlGetSymFromLib success");
5326 (*getPdnTypeFunc)(apn, wdsPdnTypeCb);
5327 } else {
5328 mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, apn.length(), mBearerType);
5329 }
5330 }
5331 };
5332 // Added inital length checks for apnlen check to avoid security issues
5333 // In case of failure reporting the same
5334 if (NULL == apnName || apnLen > MAX_APN_LEN || (strlen(apnName) != apnLen)) {
5335 LOC_LOGe("%s]: incorrect apnlen length or incorrect apnName", __func__);
5336 mAgpsManager.reportAtlClosed(agpsType);
5337 } else {
5338 sendMsg( new AgpsMsgAtlOpenSuccess(*this,
5339 &mAgpsManager, agpsType, apnName, apnLen, bearerType));
5340 }
5341}
5342
5343void GnssAdapter::dataConnClosedCommand(AGpsExtType agpsType){
5344
5345 LOC_LOGI("GnssAdapter::frameworkDataConnClosed");
5346
5347 struct AgpsMsgAtlClosed: public LocMsg {
5348
5349 AgpsManager* mAgpsManager;
5350 AGpsExtType mAgpsType;
5351
5352 inline AgpsMsgAtlClosed(AgpsManager* agpsManager, AGpsExtType agpsType) :
5353 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
5354
5355 LOC_LOGV("AgpsMsgAtlClosed");
5356 }
5357
5358 inline virtual void proc() const {
5359
5360 LOC_LOGV("AgpsMsgAtlClosed::proc()");
5361 mAgpsManager->reportAtlClosed(mAgpsType);
5362 }
5363 };
5364
5365 sendMsg( new AgpsMsgAtlClosed(&mAgpsManager, (AGpsExtType)agpsType));
5366}
5367
5368void GnssAdapter::dataConnFailedCommand(AGpsExtType agpsType){
5369
5370 LOC_LOGI("GnssAdapter::frameworkDataConnFailed");
5371
5372 struct AgpsMsgAtlOpenFailed: public LocMsg {
5373
5374 AgpsManager* mAgpsManager;
5375 AGpsExtType mAgpsType;
5376
5377 inline AgpsMsgAtlOpenFailed(AgpsManager* agpsManager, AGpsExtType agpsType) :
5378 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
5379
5380 LOC_LOGV("AgpsMsgAtlOpenFailed");
5381 }
5382
5383 inline virtual void proc() const {
5384
5385 LOC_LOGV("AgpsMsgAtlOpenFailed::proc()");
5386 mAgpsManager->reportAtlOpenFailed(mAgpsType);
5387 }
5388 };
5389
5390 sendMsg( new AgpsMsgAtlOpenFailed(&mAgpsManager, (AGpsExtType)agpsType));
5391}
5392
5393void GnssAdapter::convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo>& out,
5394 const GnssSvType& in_constellation,
5395 const SystemStatusReports& in)
5396{
5397 uint64_t sv_mask = 0ULL;
5398 uint32_t svid_min = 0;
5399 uint32_t svid_num = 0;
5400 uint32_t svid_idx = 0;
5401
5402 uint64_t eph_health_good_mask = 0ULL;
5403 uint64_t eph_health_bad_mask = 0ULL;
5404 uint64_t server_perdiction_available_mask = 0ULL;
5405 float server_perdiction_age = 0.0f;
5406
5407 // set constellationi based parameters
5408 switch (in_constellation) {
5409 case GNSS_SV_TYPE_GPS:
5410 svid_min = GNSS_BUGREPORT_GPS_MIN;
5411 svid_num = GPS_NUM;
5412 svid_idx = 0;
5413 if (!in.mSvHealth.empty()) {
5414 eph_health_good_mask = in.mSvHealth.back().mGpsGoodMask;
5415 eph_health_bad_mask = in.mSvHealth.back().mGpsBadMask;
5416 }
5417 if (!in.mXtra.empty()) {
5418 server_perdiction_available_mask = in.mXtra.back().mGpsXtraValid;
5419 server_perdiction_age = (float)(in.mXtra.back().mGpsXtraAge);
5420 }
5421 break;
5422 case GNSS_SV_TYPE_GLONASS:
5423 svid_min = GNSS_BUGREPORT_GLO_MIN;
5424 svid_num = GLO_NUM;
5425 svid_idx = GPS_NUM;
5426 if (!in.mSvHealth.empty()) {
5427 eph_health_good_mask = in.mSvHealth.back().mGloGoodMask;
5428 eph_health_bad_mask = in.mSvHealth.back().mGloBadMask;
5429 }
5430 if (!in.mXtra.empty()) {
5431 server_perdiction_available_mask = in.mXtra.back().mGloXtraValid;
5432 server_perdiction_age = (float)(in.mXtra.back().mGloXtraAge);
5433 }
5434 break;
5435 case GNSS_SV_TYPE_QZSS:
5436 svid_min = GNSS_BUGREPORT_QZSS_MIN;
5437 svid_num = QZSS_NUM;
5438 svid_idx = GPS_NUM+GLO_NUM+BDS_NUM+GAL_NUM;
5439 if (!in.mSvHealth.empty()) {
5440 eph_health_good_mask = in.mSvHealth.back().mQzssGoodMask;
5441 eph_health_bad_mask = in.mSvHealth.back().mQzssBadMask;
5442 }
5443 if (!in.mXtra.empty()) {
5444 server_perdiction_available_mask = in.mXtra.back().mQzssXtraValid;
5445 server_perdiction_age = (float)(in.mXtra.back().mQzssXtraAge);
5446 }
5447 break;
5448 case GNSS_SV_TYPE_BEIDOU:
5449 svid_min = GNSS_BUGREPORT_BDS_MIN;
5450 svid_num = BDS_NUM;
5451 svid_idx = GPS_NUM+GLO_NUM;
5452 if (!in.mSvHealth.empty()) {
5453 eph_health_good_mask = in.mSvHealth.back().mBdsGoodMask;
5454 eph_health_bad_mask = in.mSvHealth.back().mBdsBadMask;
5455 }
5456 if (!in.mXtra.empty()) {
5457 server_perdiction_available_mask = in.mXtra.back().mBdsXtraValid;
5458 server_perdiction_age = (float)(in.mXtra.back().mBdsXtraAge);
5459 }
5460 break;
5461 case GNSS_SV_TYPE_GALILEO:
5462 svid_min = GNSS_BUGREPORT_GAL_MIN;
5463 svid_num = GAL_NUM;
5464 svid_idx = GPS_NUM+GLO_NUM+BDS_NUM;
5465 if (!in.mSvHealth.empty()) {
5466 eph_health_good_mask = in.mSvHealth.back().mGalGoodMask;
5467 eph_health_bad_mask = in.mSvHealth.back().mGalBadMask;
5468 }
5469 if (!in.mXtra.empty()) {
5470 server_perdiction_available_mask = in.mXtra.back().mGalXtraValid;
5471 server_perdiction_age = (float)(in.mXtra.back().mGalXtraAge);
5472 }
5473 break;
5474 case GNSS_SV_TYPE_NAVIC:
5475 svid_min = GNSS_BUGREPORT_NAVIC_MIN;
5476 svid_num = NAVIC_NUM;
5477 svid_idx = GPS_NUM+GLO_NUM+QZSS_NUM+BDS_NUM+GAL_NUM;
5478 if (!in.mSvHealth.empty()) {
5479 eph_health_good_mask = in.mSvHealth.back().mNavicGoodMask;
5480 eph_health_bad_mask = in.mSvHealth.back().mNavicBadMask;
5481 }
5482 if (!in.mXtra.empty()) {
5483 server_perdiction_available_mask = in.mXtra.back().mNavicXtraValid;
5484 server_perdiction_age = (float)(in.mXtra.back().mNavicXtraAge);
5485 }
5486 break;
5487 default:
5488 return;
5489 }
5490
5491 // extract each sv info from systemstatus report
5492 for(uint32_t i=0; i<svid_num && (svid_idx+i)<SV_ALL_NUM; i++) {
5493
5494 GnssDebugSatelliteInfo s = {};
5495 s.size = sizeof(s);
5496 s.svid = i + svid_min;
5497 s.constellation = in_constellation;
5498
5499 if (!in.mNavData.empty()) {
5500 s.mEphemerisType = in.mNavData.back().mNav[svid_idx+i].mType;
5501 s.mEphemerisSource = in.mNavData.back().mNav[svid_idx+i].mSource;
5502 }
5503 else {
5504 s.mEphemerisType = GNSS_EPH_TYPE_UNKNOWN;
5505 s.mEphemerisSource = GNSS_EPH_SOURCE_UNKNOWN;
5506 }
5507
5508 sv_mask = 0x1ULL << i;
5509 if (eph_health_good_mask & sv_mask) {
5510 s.mEphemerisHealth = GNSS_EPH_HEALTH_GOOD;
5511 }
5512 else if (eph_health_bad_mask & sv_mask) {
5513 s.mEphemerisHealth = GNSS_EPH_HEALTH_BAD;
5514 }
5515 else {
5516 s.mEphemerisHealth = GNSS_EPH_HEALTH_UNKNOWN;
5517 }
5518
5519 if (!in.mNavData.empty()) {
5520 s.ephemerisAgeSeconds =
5521 (float)(in.mNavData.back().mNav[svid_idx+i].mAgeSec);
5522 }
5523 else {
5524 s.ephemerisAgeSeconds = 0.0f;
5525 }
5526
5527 if (server_perdiction_available_mask & sv_mask) {
5528 s.serverPredictionIsAvailable = true;
5529 }
5530 else {
5531 s.serverPredictionIsAvailable = false;
5532 }
5533
5534 s.serverPredictionAgeSeconds = server_perdiction_age;
5535 out.push_back(s);
5536 }
5537
5538 return;
5539}
5540
5541bool GnssAdapter::getDebugReport(GnssDebugReport& r)
5542{
5543 LOC_LOGD("%s]: ", __func__);
5544
5545 SystemStatus* systemstatus = getSystemStatus();
5546 if (nullptr == systemstatus) {
5547 return false;
5548 }
5549
5550 SystemStatusReports reports = {};
5551 systemstatus->getReport(reports, true);
5552
5553 r.size = sizeof(r);
5554
5555 // location block
5556 r.mLocation.size = sizeof(r.mLocation);
5557 if(!reports.mLocation.empty() && reports.mLocation.back().mValid) {
5558 r.mLocation.mValid = true;
5559 r.mLocation.mLocation.latitude =
5560 reports.mLocation.back().mLocation.gpsLocation.latitude;
5561 r.mLocation.mLocation.longitude =
5562 reports.mLocation.back().mLocation.gpsLocation.longitude;
5563 r.mLocation.mLocation.altitude =
5564 reports.mLocation.back().mLocation.gpsLocation.altitude;
5565 r.mLocation.mLocation.speed =
5566 (double)(reports.mLocation.back().mLocation.gpsLocation.speed);
5567 r.mLocation.mLocation.bearing =
5568 (double)(reports.mLocation.back().mLocation.gpsLocation.bearing);
5569 r.mLocation.mLocation.accuracy =
5570 (double)(reports.mLocation.back().mLocation.gpsLocation.accuracy);
5571
5572 r.mLocation.verticalAccuracyMeters =
5573 reports.mLocation.back().mLocationEx.vert_unc;
5574 r.mLocation.speedAccuracyMetersPerSecond =
5575 reports.mLocation.back().mLocationEx.speed_unc;
5576 r.mLocation.bearingAccuracyDegrees =
5577 reports.mLocation.back().mLocationEx.bearing_unc;
5578
5579 r.mLocation.mUtcReported =
5580 reports.mLocation.back().mUtcReported;
5581 }
5582 else if(!reports.mBestPosition.empty() && reports.mBestPosition.back().mValid) {
5583 r.mLocation.mValid = true;
5584 r.mLocation.mLocation.latitude =
5585 (double)(reports.mBestPosition.back().mBestLat) * RAD2DEG;
5586 r.mLocation.mLocation.longitude =
5587 (double)(reports.mBestPosition.back().mBestLon) * RAD2DEG;
5588 r.mLocation.mLocation.altitude = reports.mBestPosition.back().mBestAlt;
5589 r.mLocation.mLocation.accuracy =
5590 (double)(reports.mBestPosition.back().mBestHepe);
5591
5592 r.mLocation.mUtcReported = reports.mBestPosition.back().mUtcReported;
5593 }
5594 else {
5595 r.mLocation.mValid = false;
5596 }
5597
5598 if (r.mLocation.mValid) {
5599 LOC_LOGV("getDebugReport - lat=%f lon=%f alt=%f speed=%f",
5600 r.mLocation.mLocation.latitude,
5601 r.mLocation.mLocation.longitude,
5602 r.mLocation.mLocation.altitude,
5603 r.mLocation.mLocation.speed);
5604 }
5605
5606 // time block
5607 r.mTime.size = sizeof(r.mTime);
5608 if(!reports.mTimeAndClock.empty() && reports.mTimeAndClock.back().mTimeValid) {
5609 r.mTime.mValid = true;
5610 r.mTime.timeEstimate =
5611 (((int64_t)(reports.mTimeAndClock.back().mGpsWeek)*7 +
5612 GNSS_UTC_TIME_OFFSET)*24*60*60 -
5613 (int64_t)(reports.mTimeAndClock.back().mLeapSeconds))*1000ULL +
5614 (int64_t)(reports.mTimeAndClock.back().mGpsTowMs);
5615
5616 if (reports.mTimeAndClock.back().mTimeUncNs > 0) {
5617 // TimeUncNs value is available
5618 r.mTime.timeUncertaintyNs =
5619 (float)(reports.mTimeAndClock.back().mLeapSecUnc)*1000.0f +
5620 (float)(reports.mTimeAndClock.back().mTimeUncNs);
5621 } else {
5622 // fall back to legacy TimeUnc
5623 r.mTime.timeUncertaintyNs =
5624 ((float)(reports.mTimeAndClock.back().mTimeUnc) +
5625 (float)(reports.mTimeAndClock.back().mLeapSecUnc))*1000.0f;
5626 }
5627
5628 r.mTime.frequencyUncertaintyNsPerSec =
5629 (float)(reports.mTimeAndClock.back().mClockFreqBiasUnc);
5630 LOC_LOGV("getDebugReport - timeestimate=%" PRIu64 " unc=%f frequnc=%f",
5631 r.mTime.timeEstimate,
5632 r.mTime.timeUncertaintyNs, r.mTime.frequencyUncertaintyNsPerSec);
5633 }
5634 else {
5635 r.mTime.mValid = false;
5636 }
5637
5638 // satellite info block
5639 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GPS, reports);
5640 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GLONASS, reports);
5641 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_QZSS, reports);
5642 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_BEIDOU, reports);
5643 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GALILEO, reports);
5644 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_NAVIC, reports);
5645 LOC_LOGV("getDebugReport - satellite=%zu", r.mSatelliteInfo.size());
5646
5647 return true;
5648}
5649
5650/* get AGC information from system status and fill it */
5651void
5652GnssAdapter::getAgcInformation(GnssMeasurementsNotification& measurements, int msInWeek)
5653{
5654 SystemStatus* systemstatus = getSystemStatus();
5655
5656 if (nullptr != systemstatus) {
5657 SystemStatusReports reports = {};
5658 systemstatus->getReport(reports, true);
5659
5660 if ((!reports.mRfAndParams.empty()) && (!reports.mTimeAndClock.empty()) &&
5661 (abs(msInWeek - (int)reports.mTimeAndClock.back().mGpsTowMs) < 2000)) {
5662
5663 for (size_t i = 0; i < measurements.count; i++) {
5664 switch (measurements.measurements[i].svType) {
5665 case GNSS_SV_TYPE_GPS:
5666 case GNSS_SV_TYPE_QZSS:
5667 measurements.measurements[i].agcLevelDb =
5668 reports.mRfAndParams.back().mAgcGps;
5669 measurements.measurements[i].flags |=
5670 GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
5671 break;
5672
5673 case GNSS_SV_TYPE_GALILEO:
5674 measurements.measurements[i].agcLevelDb =
5675 reports.mRfAndParams.back().mAgcGal;
5676 measurements.measurements[i].flags |=
5677 GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
5678 break;
5679
5680 case GNSS_SV_TYPE_GLONASS:
5681 measurements.measurements[i].agcLevelDb =
5682 reports.mRfAndParams.back().mAgcGlo;
5683 measurements.measurements[i].flags |=
5684 GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
5685 break;
5686
5687 case GNSS_SV_TYPE_BEIDOU:
5688 measurements.measurements[i].agcLevelDb =
5689 reports.mRfAndParams.back().mAgcBds;
5690 measurements.measurements[i].flags |=
5691 GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
5692 break;
5693
5694 case GNSS_SV_TYPE_SBAS:
5695 case GNSS_SV_TYPE_UNKNOWN:
5696 default:
5697 break;
5698 }
5699 }
5700 }
5701 }
5702}
5703
5704/* get Data information from system status and fill it */
5705void
5706GnssAdapter::getDataInformation(GnssDataNotification& data, int msInWeek)
5707{
5708 SystemStatus* systemstatus = getSystemStatus();
5709
5710 LOC_LOGV("%s]: msInWeek=%d", __func__, msInWeek);
5711 if (nullptr != systemstatus) {
5712 SystemStatusReports reports = {};
5713 systemstatus->getReport(reports, true);
5714
5715 if ((!reports.mRfAndParams.empty()) && (!reports.mTimeAndClock.empty()) &&
5716 (abs(msInWeek - (int)reports.mTimeAndClock.back().mGpsTowMs) < 2000)) {
5717
5718 for (int sig = GNSS_LOC_SIGNAL_TYPE_GPS_L1CA;
5719 sig < GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES; sig++) {
5720 data.gnssDataMask[sig] = 0;
5721 data.jammerInd[sig] = 0.0;
5722 data.agc[sig] = 0.0;
5723 }
5724 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcGps) {
5725 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] |=
5726 GNSS_LOC_DATA_AGC_BIT;
5727 data.agc[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] =
5728 reports.mRfAndParams.back().mAgcGps;
5729 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] |=
5730 GNSS_LOC_DATA_AGC_BIT;
5731 data.agc[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] =
5732 reports.mRfAndParams.back().mAgcGps;
5733 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] |=
5734 GNSS_LOC_DATA_AGC_BIT;
5735 data.agc[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] =
5736 reports.mRfAndParams.back().mAgcGps;
5737 }
5738 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGps) {
5739 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] |=
5740 GNSS_LOC_DATA_JAMMER_IND_BIT;
5741 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] =
5742 (double)reports.mRfAndParams.back().mJammerGps;
5743 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] |=
5744 GNSS_LOC_DATA_JAMMER_IND_BIT;
5745 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] =
5746 (double)reports.mRfAndParams.back().mJammerGps;
5747 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] |=
5748 GNSS_LOC_DATA_JAMMER_IND_BIT;
5749 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] =
5750 (double)reports.mRfAndParams.back().mJammerGps;
5751 }
5752 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcGlo) {
5753 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] |=
5754 GNSS_LOC_DATA_AGC_BIT;
5755 data.agc[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] =
5756 reports.mRfAndParams.back().mAgcGlo;
5757 }
5758 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGlo) {
5759 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] |=
5760 GNSS_LOC_DATA_JAMMER_IND_BIT;
5761 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] =
5762 (double)reports.mRfAndParams.back().mJammerGlo;
5763 }
5764 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcBds) {
5765 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] |=
5766 GNSS_LOC_DATA_AGC_BIT;
5767 data.agc[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] =
5768 reports.mRfAndParams.back().mAgcBds;
5769 }
5770 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerBds) {
5771 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] |=
5772 GNSS_LOC_DATA_JAMMER_IND_BIT;
5773 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] =
5774 (double)reports.mRfAndParams.back().mJammerBds;
5775 }
5776 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcGal) {
5777 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] |=
5778 GNSS_LOC_DATA_AGC_BIT;
5779 data.agc[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] =
5780 reports.mRfAndParams.back().mAgcGal;
5781 }
5782 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGal) {
5783 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] |=
5784 GNSS_LOC_DATA_JAMMER_IND_BIT;
5785 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] =
5786 (double)reports.mRfAndParams.back().mJammerGal;
5787 }
5788 }
5789 }
5790}
5791
5792/* Callbacks registered with loc_net_iface library */
5793static void agpsOpenResultCb (bool isSuccess, AGpsExtType agpsType, const char* apn,
5794 AGpsBearerType bearerType, void* userDataPtr) {
5795 LOC_LOGD("%s]: ", __func__);
5796 if (userDataPtr == nullptr) {
5797 LOC_LOGE("%s]: userDataPtr is nullptr.", __func__);
5798 return;
5799 }
5800 if (apn == nullptr) {
5801 LOC_LOGE("%s]: apn is nullptr.", __func__);
5802 return;
5803 }
5804 GnssAdapter* adapter = (GnssAdapter*)userDataPtr;
5805 if (isSuccess) {
5806 adapter->dataConnOpenCommand(agpsType, apn, strlen(apn), bearerType);
5807 } else {
5808 adapter->dataConnFailedCommand(agpsType);
5809 }
5810}
5811
5812static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userDataPtr) {
5813 LOC_LOGD("%s]: ", __func__);
5814 if (userDataPtr == nullptr) {
5815 LOC_LOGE("%s]: userDataPtr is nullptr.", __func__);
5816 return;
5817 }
5818 GnssAdapter* adapter = (GnssAdapter*)userDataPtr;
5819 if (isSuccess) {
5820 adapter->dataConnClosedCommand(agpsType);
5821 } else {
5822 adapter->dataConnFailedCommand(agpsType);
5823 }
5824}
5825
5826void
5827GnssAdapter::saveGnssEnergyConsumedCallback(GnssEnergyConsumedCallback energyConsumedCb) {
5828 mGnssEnergyConsumedCb = energyConsumedCb;
5829}
5830
5831void
5832GnssAdapter::getGnssEnergyConsumedCommand(GnssEnergyConsumedCallback energyConsumedCb) {
5833 struct MsgGetGnssEnergyConsumed : public LocMsg {
5834 GnssAdapter& mAdapter;
5835 LocApiBase& mApi;
5836 GnssEnergyConsumedCallback mEnergyConsumedCb;
5837 inline MsgGetGnssEnergyConsumed(GnssAdapter& adapter, LocApiBase& api,
5838 GnssEnergyConsumedCallback energyConsumedCb) :
5839 LocMsg(),
5840 mAdapter(adapter),
5841 mApi(api),
5842 mEnergyConsumedCb(energyConsumedCb){}
5843 inline virtual void proc() const {
5844 mAdapter.saveGnssEnergyConsumedCallback(mEnergyConsumedCb);
5845 mApi.getGnssEnergyConsumed();
5846 }
5847 };
5848
5849 sendMsg(new MsgGetGnssEnergyConsumed(*this, *mLocApi, energyConsumedCb));
5850}
5851
5852void
5853GnssAdapter::nfwControlCommand(bool enable) {
5854 struct MsgControlNfwLocationAccess : public LocMsg {
5855 GnssAdapter& mAdapter;
5856 LocApiBase& mApi;
5857 bool mEnable;
5858 inline MsgControlNfwLocationAccess(GnssAdapter& adapter, LocApiBase& api,
5859 bool enable) :
5860 LocMsg(),
5861 mAdapter(adapter),
5862 mApi(api),
5863 mEnable(enable) {}
5864 inline virtual void proc() const {
Michael Bestas3a0209e2023-05-04 01:15:47 +03005865
Michael Bestas9f1f76e2024-05-28 23:23:20 +03005866 if (mAdapter.mSupportNfwControl) {
5867 GnssConfigGpsLock gpsLock;
5868
5869 gpsLock = ContextBase::mGps_conf.GPS_LOCK;
5870 if (mEnable) {
5871 gpsLock &= ~GNSS_CONFIG_GPS_LOCK_NI;
5872 } else {
5873 gpsLock |= GNSS_CONFIG_GPS_LOCK_NI;
5874 }
5875 ContextBase::mGps_conf.GPS_LOCK = gpsLock;
5876 mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() {
5877 mApi.setGpsLockSync((GnssConfigGpsLock)gpsLock);
5878 }));
Michael Bestas3a0209e2023-05-04 01:15:47 +03005879 } else {
Michael Bestas9f1f76e2024-05-28 23:23:20 +03005880 LOC_LOGw("NFW control is not supported, do not use this for NFW");
Michael Bestas3a0209e2023-05-04 01:15:47 +03005881 }
Michael Bestas3a0209e2023-05-04 01:15:47 +03005882 }
5883 };
5884
Michael Bestas9f1f76e2024-05-28 23:23:20 +03005885 sendMsg(new MsgControlNfwLocationAccess(*this, *mLocApi, enable));
Michael Bestas3a0209e2023-05-04 01:15:47 +03005886}
5887
5888// Set tunc constrained mode, use 0 session id to indicate
5889// that no callback is needed. Session id 0 is used for calls that
5890// are not invoked from the integration api, e.g.: initial configuration
5891// from the configure file
5892void
5893GnssAdapter::setConstrainedTunc(bool enable, float tuncConstraint,
5894 uint32_t energyBudget, uint32_t sessionId) {
5895
5896 mLocConfigInfo.tuncConfigInfo.isValid = true;
5897 mLocConfigInfo.tuncConfigInfo.enable = enable;
5898 mLocConfigInfo.tuncConfigInfo.tuncThresholdMs = tuncConstraint;
5899 mLocConfigInfo.tuncConfigInfo.energyBudget = energyBudget;
5900
5901 LocApiResponse* locApiResponse = nullptr;
5902 if (sessionId != 0) {
5903 locApiResponse =
5904 new LocApiResponse(*getContext(),
5905 [this, sessionId] (LocationError err) {
5906 reportResponse(err, sessionId);});
5907 if (!locApiResponse) {
5908 LOC_LOGe("memory alloc failed");
5909 }
5910 }
5911 mLocApi->setConstrainedTuncMode(
5912 enable, tuncConstraint, energyBudget, locApiResponse);
5913}
5914
5915uint32_t
5916GnssAdapter::setConstrainedTuncCommand (bool enable, float tuncConstraint,
5917 uint32_t energyBudget) {
5918 // generated session id will be none-zero
5919 uint32_t sessionId = generateSessionId();
5920 LOC_LOGd("session id %u", sessionId);
5921
5922 struct MsgEnableTUNC : public LocMsg {
5923 GnssAdapter& mAdapter;
5924 uint32_t mSessionId;
5925 bool mEnable;
5926 float mTuncConstraint;
5927 uint32_t mEnergyBudget;
5928
5929 inline MsgEnableTUNC(GnssAdapter& adapter,
5930 uint32_t sessionId,
5931 bool enable,
5932 float tuncConstraint,
5933 uint32_t energyBudget) :
5934 LocMsg(),
5935 mAdapter(adapter),
5936 mSessionId(sessionId),
5937 mEnable(enable),
5938 mTuncConstraint(tuncConstraint),
5939 mEnergyBudget(energyBudget) {}
5940 inline virtual void proc() const {
5941 mAdapter.setConstrainedTunc(mEnable, mTuncConstraint,
5942 mEnergyBudget, mSessionId);
5943 }
5944 };
5945
5946 sendMsg(new MsgEnableTUNC(*this, sessionId, enable,
5947 tuncConstraint, energyBudget));
5948
5949 return sessionId;
5950}
5951
5952// Set position assisted clock estimator, use 0 session id to indicate
5953// that no callback is needed. Session id 0 is used for calls that are
5954// not invoked from the integration api, e.g.: initial configuration
5955// from the configure file.
5956void
5957GnssAdapter::setPositionAssistedClockEstimator(bool enable,
5958 uint32_t sessionId) {
5959
5960 mLocConfigInfo.paceConfigInfo.isValid = true;
5961 mLocConfigInfo.paceConfigInfo.enable = enable;
5962 LocApiResponse* locApiResponse = nullptr;
5963 if (sessionId != 0) {
5964 locApiResponse =
5965 new LocApiResponse(*getContext(),
5966 [this, sessionId] (LocationError err) {
5967 reportResponse(err, sessionId);});
5968 if (!locApiResponse) {
5969 LOC_LOGe("memory alloc failed");
5970 }
5971 }
5972 mLocApi->setPositionAssistedClockEstimatorMode(enable, locApiResponse);
5973}
5974
5975uint32_t
5976GnssAdapter::setPositionAssistedClockEstimatorCommand(bool enable) {
5977 // generated session id will be none-zero
5978 uint32_t sessionId = generateSessionId();
5979 LOC_LOGd("session id %u", sessionId);
5980
5981 struct MsgEnablePACE : public LocMsg {
5982 GnssAdapter& mAdapter;
5983 uint32_t mSessionId;
5984 bool mEnable;
5985 inline MsgEnablePACE(GnssAdapter& adapter,
5986 uint32_t sessionId, bool enable) :
5987 LocMsg(),
5988 mAdapter(adapter),
5989 mSessionId(sessionId),
5990 mEnable(enable){}
5991 inline virtual void proc() const {
5992 mAdapter.setPositionAssistedClockEstimator(mEnable, mSessionId);
5993 }
5994 };
5995
5996 sendMsg(new MsgEnablePACE(*this, sessionId, enable));
5997 return sessionId;
5998}
5999
6000void GnssAdapter::gnssUpdateSvConfig(
6001 uint32_t sessionId, const GnssSvTypeConfig& constellationEnablementConfig,
6002 const GnssSvIdConfig& blacklistSvConfig) {
6003
6004 // suspend all tracking sessions to apply the constellation config
6005 suspendSessions();
6006 if (constellationEnablementConfig.size == sizeof(constellationEnablementConfig)) {
6007 // check whether if any constellation is removed from the new config
6008 GnssSvTypesMask currentEnabledMask = mGnssSvTypeConfig.enabledSvTypesMask;
6009 GnssSvTypesMask newEnabledMask = constellationEnablementConfig.enabledSvTypesMask;
6010 GnssSvTypesMask enabledRemoved = currentEnabledMask & (currentEnabledMask ^ newEnabledMask);
6011 // Send reset if any constellation is removed from the enabled list
6012 if (enabledRemoved != 0) {
6013 mLocApi->resetConstellationControl();
6014 }
6015
6016 // if the constellation config is valid, issue request to modem
6017 // to enable/disable constellation
6018 mLocApi->setConstellationControl(mGnssSvTypeConfig);
6019 } else if (constellationEnablementConfig.size == 0) {
6020 // when the size is not set, meaning reset to modem default
6021 mLocApi->resetConstellationControl();
6022 }
6023 // save the constellation settings to be used for modem SSR
6024 mGnssSvTypeConfig = constellationEnablementConfig;
6025
6026 // handle blacklisted SV settings
6027 mGnssSvIdConfig = blacklistSvConfig;
6028 // process blacklist svs info
6029 mBlacklistedSvIds.clear();
6030 // need to save the balcklisted sv info into mBlacklistedSvIds as well
6031 convertFromGnssSvIdConfig(blacklistSvConfig, mBlacklistedSvIds);
6032 LocApiResponse* locApiResponse = new LocApiResponse(*getContext(),
6033 [this, sessionId] (LocationError err) {
6034 reportResponse(err, sessionId);});
6035 if (!locApiResponse) {
6036 LOC_LOGe("memory alloc failed");
6037 }
6038 mLocApi->setBlacklistSv(mGnssSvIdConfig, locApiResponse);
6039
6040 // resume all tracking sessions after the constellation config has been applied
6041 restartSessions(false);
6042}
6043
6044uint32_t
6045GnssAdapter::gnssUpdateSvConfigCommand(
6046 const GnssSvTypeConfig& constellationEnablementConfig,
6047 const GnssSvIdConfig& blacklistSvConfig) {
6048
6049 // generated session id will be none-zero
6050 uint32_t sessionId = generateSessionId();
6051 LOC_LOGd("session id %u", sessionId);
6052
6053 struct MsgUpdateSvConfig : public LocMsg {
6054 GnssAdapter& mAdapter;
6055 uint32_t mSessionId;
6056 GnssSvTypeConfig mConstellationEnablementConfig;
6057 GnssSvIdConfig mBlacklistSvIdConfig;
6058
6059 inline MsgUpdateSvConfig(GnssAdapter& adapter,
6060 uint32_t sessionId,
6061 const GnssSvTypeConfig& constellationEnablementConfig,
6062 const GnssSvIdConfig& blacklistSvConfig) :
6063 LocMsg(),
6064 mAdapter(adapter),
6065 mSessionId(sessionId),
6066 mConstellationEnablementConfig(constellationEnablementConfig),
6067 mBlacklistSvIdConfig(blacklistSvConfig) {}
6068 inline virtual void proc() const {
6069 mAdapter.gnssUpdateSvConfig(mSessionId, mConstellationEnablementConfig,
6070 mBlacklistSvIdConfig);
6071 }
6072 };
6073
6074 if (sessionId != 0) {
6075 sendMsg(new MsgUpdateSvConfig(*this, sessionId, constellationEnablementConfig,
6076 blacklistSvConfig));
6077 }
6078 return sessionId;
6079}
6080
6081void GnssAdapter::gnssUpdateSecondaryBandConfig(
6082 uint32_t sessionId, const GnssSvTypeConfig& secondaryBandConfig) {
6083
6084 LocApiResponse* locApiResponse = new LocApiResponse(*getContext(),
6085 [this, sessionId] (LocationError err) {
6086 reportResponse(err, sessionId);});
6087 if (!locApiResponse) {
6088 LOC_LOGe("memory alloc failed");
6089 }
6090
6091 // handle secondary band info
6092 mGnssSeconaryBandConfig = secondaryBandConfig;
6093 gnssSecondaryBandConfigUpdate(locApiResponse);
6094}
6095
6096uint32_t
6097GnssAdapter::gnssUpdateSecondaryBandConfigCommand(
6098 const GnssSvTypeConfig& secondaryBandConfig) {
6099
6100 // generated session id will be none-zero
6101 uint32_t sessionId = generateSessionId();
6102 LOC_LOGd("session id %u", sessionId);
6103
6104 struct MsgUpdateSecondaryBandConfig : public LocMsg {
6105 GnssAdapter& mAdapter;
6106 uint32_t mSessionId;
6107 GnssSvTypeConfig mSecondaryBandConfig;
6108
6109 inline MsgUpdateSecondaryBandConfig(GnssAdapter& adapter,
6110 uint32_t sessionId,
6111 const GnssSvTypeConfig& secondaryBandConfig) :
6112 LocMsg(),
6113 mAdapter(adapter),
6114 mSessionId(sessionId),
6115 mSecondaryBandConfig(secondaryBandConfig) {}
6116 inline virtual void proc() const {
6117 mAdapter.gnssUpdateSecondaryBandConfig(mSessionId, mSecondaryBandConfig);
6118 }
6119 };
6120
6121 if (sessionId != 0) {
6122 sendMsg(new MsgUpdateSecondaryBandConfig(*this, sessionId, secondaryBandConfig));
6123 }
6124 return sessionId;
6125}
6126
6127// This function currently retrieves secondary band configuration
6128// for constellation enablement/disablement.
6129void
6130GnssAdapter::gnssGetSecondaryBandConfig(uint32_t sessionId) {
6131
6132 LocApiResponse* locApiResponse = new LocApiResponse(*getContext(),
6133 [this, sessionId] (LocationError err) {
6134 reportResponse(err, sessionId);});
6135 if (!locApiResponse) {
6136 LOC_LOGe("memory alloc failed");
6137 }
6138
6139 mLocApi->getConstellationMultiBandConfig(sessionId, locApiResponse);
6140}
6141
6142uint32_t
6143GnssAdapter::gnssGetSecondaryBandConfigCommand() {
6144
6145 // generated session id will be none-zero
6146 uint32_t sessionId = generateSessionId();
6147 LOC_LOGd("session id %u", sessionId);
6148
6149 struct MsgGetSecondaryBandConfig : public LocMsg {
6150 GnssAdapter& mAdapter;
6151 uint32_t mSessionId;
6152 inline MsgGetSecondaryBandConfig(GnssAdapter& adapter,
6153 uint32_t sessionId) :
6154 LocMsg(),
6155 mAdapter(adapter),
6156 mSessionId(sessionId) {}
6157 inline virtual void proc() const {
6158 mAdapter.gnssGetSecondaryBandConfig(mSessionId);
6159 }
6160 };
6161
6162 if (sessionId != 0) {
6163 sendMsg(new MsgGetSecondaryBandConfig(*this, sessionId));
6164 }
6165 return sessionId;
6166}
6167
6168void
6169GnssAdapter::configLeverArm(uint32_t sessionId,
6170 const LeverArmConfigInfo& configInfo) {
6171
6172 LocationError err = LOCATION_ERROR_NOT_SUPPORTED;
6173 if (true == mEngHubProxy->configLeverArm(configInfo)) {
6174 err = LOCATION_ERROR_SUCCESS;
6175 }
6176 reportResponse(err, sessionId);
6177}
6178
6179uint32_t
6180GnssAdapter::configLeverArmCommand(const LeverArmConfigInfo& configInfo) {
6181
6182 // generated session id will be none-zero
6183 uint32_t sessionId = generateSessionId();
6184 LOC_LOGd("session id %u", sessionId);
6185
6186 struct MsgConfigLeverArm : public LocMsg {
6187 GnssAdapter& mAdapter;
6188 uint32_t mSessionId;
6189 LeverArmConfigInfo mConfigInfo;
6190
6191 inline MsgConfigLeverArm(GnssAdapter& adapter,
6192 uint32_t sessionId,
6193 const LeverArmConfigInfo& configInfo) :
6194 LocMsg(),
6195 mAdapter(adapter),
6196 mSessionId(sessionId),
6197 mConfigInfo(configInfo) {}
6198 inline virtual void proc() const {
6199 // save the lever ARM config info for translating position from GNSS antenna based
6200 // to VRP based
6201 if (mConfigInfo.leverArmValidMask & LEVER_ARM_TYPE_GNSS_TO_VRP_BIT) {
6202 mAdapter.mLocConfigInfo.leverArmConfigInfo.leverArmValidMask |=
6203 LEVER_ARM_TYPE_GNSS_TO_VRP_BIT;
6204 mAdapter.mLocConfigInfo.leverArmConfigInfo.gnssToVRP = mConfigInfo.gnssToVRP;
6205 }
6206 mAdapter.configLeverArm(mSessionId, mConfigInfo);
6207 }
6208 };
6209
6210 sendMsg(new MsgConfigLeverArm(*this, sessionId, configInfo));
6211 return sessionId;
6212}
6213
6214bool GnssAdapter::initMeasCorr(bool bSendCbWhenNotSupported) {
6215 LOC_LOGv("GnssAdapter::initMeasCorr");
6216 /* Message to initialize Measurement Corrections */
6217 struct MsgInitMeasCorr : public LocMsg {
6218 GnssAdapter& mAdapter;
6219 GnssMeasurementCorrectionsCapabilitiesMask mCapMask;
6220
6221 inline MsgInitMeasCorr(GnssAdapter& adapter,
6222 GnssMeasurementCorrectionsCapabilitiesMask capMask) :
6223 LocMsg(), mAdapter(adapter), mCapMask(capMask) {
6224 LOC_LOGv("MsgInitMeasCorr");
6225 }
6226
6227 inline virtual void proc() const {
6228 LOC_LOGv("MsgInitMeasCorr::proc()");
6229
6230 mAdapter.mMeasCorrSetCapabilitiesCb(mCapMask);
6231 }
6232 };
6233 if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION)) {
6234 sendMsg(new MsgInitMeasCorr(*this, GNSS_MEAS_CORR_LOS_SATS |
6235 GNSS_MEAS_CORR_EXCESS_PATH_LENGTH | GNSS_MEAS_CORR_REFLECTING_PLANE));
6236 return true;
6237 } else {
6238 LOC_LOGv("MEASUREMENTS_CORRECTION feature is not supported in the modem");
6239 if (bSendCbWhenNotSupported) {
6240 sendMsg(new MsgInitMeasCorr(*this, 0));
6241 }
6242 return false;
6243 }
6244}
6245
6246bool GnssAdapter::openMeasCorrCommand(const measCorrSetCapabilitiesCb setCapabilitiesCb) {
6247 LOC_LOGi("GnssAdapter::openMeasCorrCommand");
6248
6249 /* Send message to initialize Measurement Corrections */
6250 mMeasCorrSetCapabilitiesCb = setCapabilitiesCb;
6251 mIsMeasCorrInterfaceOpen = true;
6252 if (isEngineCapabilitiesKnown()) {
6253 LOC_LOGv("Capabilities are known, proceed with measurement corrections init");
6254 return initMeasCorr(false);
6255 } else {
6256 LOC_LOGv("Capabilities are not known, wait for open");
6257 return true;
6258 }
6259}
6260
6261bool GnssAdapter::measCorrSetCorrectionsCommand(const GnssMeasurementCorrections gnssMeasCorr) {
6262 LOC_LOGi("GnssAdapter::measCorrSetCorrectionsCommand");
6263
6264 /* Message to set Measurement Corrections */
6265 struct MsgSetCorrectionsMeasCorr : public LocMsg {
6266 const GnssMeasurementCorrections mGnssMeasCorr;
6267 GnssAdapter& mAdapter;
6268 LocApiBase& mApi;
6269
6270 inline MsgSetCorrectionsMeasCorr(
6271 const GnssMeasurementCorrections gnssMeasCorr,
6272 GnssAdapter& adapter,
6273 LocApiBase& api) :
6274 LocMsg(),
6275 mGnssMeasCorr(gnssMeasCorr),
6276 mAdapter(adapter),
6277 mApi(api) {
6278 LOC_LOGv("MsgSetCorrectionsMeasCorr");
6279 }
6280
6281 inline virtual void proc() const {
6282 LOC_LOGv("MsgSetCorrectionsMeasCorr::proc()");
6283 mApi.setMeasurementCorrections(mGnssMeasCorr);
6284 }
6285 };
6286
6287 if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_MEASUREMENTS_CORRECTION)) {
6288 sendMsg(new MsgSetCorrectionsMeasCorr(gnssMeasCorr, *this, *mLocApi));
6289 return true;
6290 } else {
6291 LOC_LOGw("Measurement Corrections are not supported!");
6292 return false;
6293 }
6294}
6295uint32_t GnssAdapter::antennaInfoInitCommand(const antennaInfoCb antennaInfoCallback) {
6296 LOC_LOGi("GnssAdapter::antennaInfoInitCommand");
6297
6298 /* Message to initialize Antenna Information */
6299 struct MsgInitAi : public LocMsg {
6300 const antennaInfoCb mAntennaInfoCb;
6301 GnssAdapter& mAdapter;
6302
6303 inline MsgInitAi(const antennaInfoCb antennaInfoCallback, GnssAdapter& adapter) :
6304 LocMsg(), mAntennaInfoCb(antennaInfoCallback), mAdapter(adapter) {
6305 LOC_LOGv("MsgInitAi");
6306 }
6307
6308 inline virtual void proc() const {
6309 LOC_LOGv("MsgInitAi::proc()");
6310 mAdapter.reportGnssAntennaInformation(mAntennaInfoCb);
6311 }
6312 };
6313 if (mIsAntennaInfoInterfaceOpened) {
6314 return ANTENNA_INFO_ERROR_ALREADY_INIT;
6315 } else {
6316 mIsAntennaInfoInterfaceOpened = true;
6317 sendMsg(new MsgInitAi(antennaInfoCallback, *this));
6318 return ANTENNA_INFO_SUCCESS;
6319 }
6320}
6321
6322void
6323GnssAdapter::configRobustLocation(uint32_t sessionId,
6324 bool enable, bool enableForE911) {
6325
6326 mLocConfigInfo.robustLocationConfigInfo.isValid = true;
6327 mLocConfigInfo.robustLocationConfigInfo.enable = enable;
6328 mLocConfigInfo.robustLocationConfigInfo.enableFor911 = enableForE911;
6329
6330 LocApiResponse* locApiResponse = nullptr;
6331 if (sessionId != 0) {
6332 locApiResponse =
6333 new LocApiResponse(*getContext(),
6334 [this, sessionId] (LocationError err) {
6335 reportResponse(err, sessionId);});
6336 if (!locApiResponse) {
6337 LOC_LOGe("memory alloc failed");
6338 }
6339 }
6340 mLocApi->configRobustLocation(enable, enableForE911, locApiResponse);
6341}
6342
6343uint32_t GnssAdapter::configRobustLocationCommand(
6344 bool enable, bool enableForE911) {
6345
6346 // generated session id will be none-zero
6347 uint32_t sessionId = generateSessionId();
6348 LOC_LOGd("session id %u", sessionId);
6349
6350 struct MsgConfigRobustLocation : public LocMsg {
6351 GnssAdapter& mAdapter;
6352 uint32_t mSessionId;
6353 bool mEnable;
6354 bool mEnableForE911;
6355
6356 inline MsgConfigRobustLocation(GnssAdapter& adapter,
6357 uint32_t sessionId,
6358 bool enable,
6359 bool enableForE911) :
6360 LocMsg(),
6361 mAdapter(adapter),
6362 mSessionId(sessionId),
6363 mEnable(enable),
6364 mEnableForE911(enableForE911) {}
6365 inline virtual void proc() const {
6366 mAdapter.configRobustLocation(mSessionId, mEnable, mEnableForE911);
6367 }
6368 };
6369
6370 sendMsg(new MsgConfigRobustLocation(*this, sessionId, enable, enableForE911));
6371 return sessionId;
6372}
6373
6374void
6375GnssAdapter::configMinGpsWeek(uint32_t sessionId, uint16_t minGpsWeek) {
6376 // suspend all sessions for modem to take the min GPS week config
6377 suspendSessions();
6378
6379 LocApiResponse* locApiResponse = nullptr;
6380 if (sessionId != 0) {
6381 locApiResponse =
6382 new LocApiResponse(*getContext(),
6383 [this, sessionId] (LocationError err) {
6384 reportResponse(err, sessionId);});
6385 if (!locApiResponse) {
6386 LOC_LOGe("memory alloc failed");
6387 }
6388 }
6389 mLocApi->configMinGpsWeek(minGpsWeek, locApiResponse);
6390
6391 // resume all tracking sessions after the min GPS week config
6392 // has been changed
6393 restartSessions(false);
6394}
6395
6396uint32_t GnssAdapter::configMinGpsWeekCommand(uint16_t minGpsWeek) {
6397 // generated session id will be none-zero
6398 uint32_t sessionId = generateSessionId();
6399 LOC_LOGd("session id %u", sessionId);
6400
6401 struct MsgConfigMinGpsWeek : public LocMsg {
6402 GnssAdapter& mAdapter;
6403 uint32_t mSessionId;
6404 uint16_t mMinGpsWeek;
6405
6406 inline MsgConfigMinGpsWeek(GnssAdapter& adapter,
6407 uint32_t sessionId,
6408 uint16_t minGpsWeek) :
6409 LocMsg(),
6410 mAdapter(adapter),
6411 mSessionId(sessionId),
6412 mMinGpsWeek(minGpsWeek) {}
6413 inline virtual void proc() const {
6414 mAdapter.configMinGpsWeek(mSessionId, mMinGpsWeek);
6415 }
6416 };
6417
6418 sendMsg(new MsgConfigMinGpsWeek(*this, sessionId, minGpsWeek));
6419 return sessionId;
6420}
6421
6422uint32_t GnssAdapter::configDeadReckoningEngineParamsCommand(
6423 const DeadReckoningEngineConfig& dreConfig) {
6424
6425 // generated session id will be none-zero
6426 uint32_t sessionId = generateSessionId();
6427 LOC_LOGd("session id %u", sessionId);
6428
6429 struct MsgConfigDrEngine : public LocMsg {
6430 GnssAdapter& mAdapter;
6431 uint32_t mSessionId;
6432 DeadReckoningEngineConfig mDreConfig;
6433
6434 inline MsgConfigDrEngine(GnssAdapter& adapter,
6435 uint32_t sessionId,
6436 const DeadReckoningEngineConfig& dreConfig) :
6437 LocMsg(),
6438 mAdapter(adapter),
6439 mSessionId(sessionId),
6440 mDreConfig(dreConfig) {}
6441 inline virtual void proc() const {
6442 LocationError err = LOCATION_ERROR_NOT_SUPPORTED;
6443 if (true == mAdapter.mEngHubProxy->configDeadReckoningEngineParams(mDreConfig)) {
6444 err = LOCATION_ERROR_SUCCESS;
6445 }
6446 mAdapter.reportResponse(err, mSessionId);
6447 }
6448 };
6449
6450 sendMsg(new MsgConfigDrEngine(*this, sessionId, dreConfig));
6451 return sessionId;
6452}
6453
6454uint32_t GnssAdapter::configEngineRunStateCommand(
6455 PositioningEngineMask engType, LocEngineRunState engState) {
6456
6457 // generated session id will be none-zero
6458 uint32_t sessionId = generateSessionId();
6459 LOC_LOGe("session id %u, eng type 0x%x, eng state %d, dre enabled %d",
6460 sessionId, engType, engState, mDreIntEnabled);
6461
6462 struct MsgConfigEngineRunState : public LocMsg {
6463 GnssAdapter& mAdapter;
6464 uint32_t mSessionId;
6465 PositioningEngineMask mEngType;
6466 LocEngineRunState mEngState;
6467
6468 inline MsgConfigEngineRunState(GnssAdapter& adapter,
6469 uint32_t sessionId,
6470 PositioningEngineMask engType,
6471 LocEngineRunState engState) :
6472 LocMsg(),
6473 mAdapter(adapter),
6474 mSessionId(sessionId),
6475 mEngType(engType),
6476 mEngState(engState) {}
6477 inline virtual void proc() const {
6478 LocationError err = LOCATION_ERROR_NOT_SUPPORTED;
6479 // Currently, only DR engine supports pause/resume request
6480 if ((mEngType == DEAD_RECKONING_ENGINE) &&
6481 (mAdapter.mDreIntEnabled == true)) {
6482 if (true == mAdapter.mEngHubProxy->configEngineRunState(mEngType, mEngState)) {
6483 err = LOCATION_ERROR_SUCCESS;
6484 }
6485 }
6486 mAdapter.reportResponse(err, mSessionId);
6487 }
6488 };
6489
6490 sendMsg(new MsgConfigEngineRunState(*this, sessionId, engType, engState));
6491
6492 return sessionId;
6493}
6494
6495void GnssAdapter::reportGnssConfigEvent(uint32_t sessionId, const GnssConfig& gnssConfig)
6496{
6497 struct MsgReportGnssConfig : public LocMsg {
6498 GnssAdapter& mAdapter;
6499 uint32_t mSessionId;
6500 mutable GnssConfig mGnssConfig;
6501 inline MsgReportGnssConfig(GnssAdapter& adapter,
6502 uint32_t sessionId,
6503 const GnssConfig& gnssConfig) :
6504 LocMsg(),
6505 mAdapter(adapter),
6506 mSessionId(sessionId),
6507 mGnssConfig(gnssConfig) {}
6508 inline virtual void proc() const {
6509 // Invoke control clients config callback
6510 if (nullptr != mAdapter.mControlCallbacks.gnssConfigCb) {
6511 mAdapter.mControlCallbacks.gnssConfigCb(mSessionId, mGnssConfig);
6512 } else {
6513 LOC_LOGe("Failed to report, callback not registered");
6514 }
6515 }
6516 };
6517
6518 sendMsg(new MsgReportGnssConfig(*this, sessionId, gnssConfig));
6519}
6520
6521/* ==== Eng Hub Proxy ================================================================= */
6522/* ======== UTILITIES ================================================================= */
6523void
6524GnssAdapter::initEngHubProxyCommand() {
6525 LOC_LOGD("%s]: ", __func__);
6526
6527 struct MsgInitEngHubProxy : public LocMsg {
6528 GnssAdapter* mAdapter;
6529 inline MsgInitEngHubProxy(GnssAdapter* adapter) :
6530 LocMsg(),
6531 mAdapter(adapter) {}
6532 inline virtual void proc() const {
6533 mAdapter->initEngHubProxy();
6534 }
6535 };
6536
6537 sendMsg(new MsgInitEngHubProxy(this));
6538}
6539
Michael Bestas9f1f76e2024-05-28 23:23:20 +03006540bool GnssAdapter::initEngHubProxy() {
Michael Bestas3a0209e2023-05-04 01:15:47 +03006541 static bool firstTime = true;
6542 static bool engHubLoadSuccessful = false;
6543
6544 const char *error = nullptr;
6545 unsigned int processListLength = 0;
6546 loc_process_info_s_type* processInfoList = nullptr;
6547
6548 do {
6549 // load eng hub only once
6550 if (firstTime == false) {
6551 break;
6552 }
6553
6554 int rc = loc_read_process_conf(LOC_PATH_IZAT_CONF, &processListLength,
6555 &processInfoList);
6556 if (rc != 0) {
6557 LOC_LOGE("%s]: failed to parse conf file", __func__);
6558 break;
6559 }
6560
6561 bool pluginDaemonEnabled = false;
6562 // go over the conf table to see whether any plugin daemon is enabled
6563 for (unsigned int i = 0; i < processListLength; i++) {
6564 if ((strncmp(processInfoList[i].name[0], PROCESS_NAME_ENGINE_SERVICE,
6565 strlen(PROCESS_NAME_ENGINE_SERVICE)) == 0) &&
6566 (processInfoList[i].proc_status == ENABLED)) {
6567 pluginDaemonEnabled = true;
6568 // check if this is DRE-INT engine
6569 if ((processInfoList[i].args[1]!= nullptr) &&
6570 (strncmp(processInfoList[i].args[1], "DRE-INT", sizeof("DRE-INT")) == 0)) {
6571 mDreIntEnabled = true;
6572 break;
6573 }
6574 }
6575 }
6576
6577 // no plugin daemon is enabled for this platform,
6578 // check if external engine is present for which we need
6579 // libloc_eng_hub.so to be loaded
6580 if (pluginDaemonEnabled == false) {
6581 UTIL_READ_CONF(LOC_PATH_IZAT_CONF, izatConfParamTable);
6582 if (!loadEngHubForExternalEngine) {
6583 break;
6584 }
6585 }
6586
6587 // load the engine hub .so, if the .so is not present
6588 // all EngHubProxyBase calls will turn into no-op.
6589 void *handle = nullptr;
6590 if ((handle = dlopen("libloc_eng_hub.so", RTLD_NOW)) == nullptr) {
6591 if ((error = dlerror()) != nullptr) {
6592 LOC_LOGE("%s]: libloc_eng_hub.so not found %s !", __func__, error);
6593 }
6594 break;
6595 }
6596
6597 // prepare the callback functions
6598 // callback function for engine hub to report back position event
6599 GnssAdapterReportEnginePositionsEventCb reportPositionEventCb =
6600 [this](int count, EngineLocationInfo* locationArr) {
6601 // report from engine hub on behalf of PPE will be treated as fromUlp
6602 reportEnginePositionsEvent(count, locationArr);
6603 };
6604
6605 // callback function for engine hub to report back sv event
6606 GnssAdapterReportSvEventCb reportSvEventCb =
6607 [this](const GnssSvNotification& svNotify, bool fromEngineHub) {
6608 reportSvEvent(svNotify, fromEngineHub);
6609 };
6610
6611 // callback function for engine hub to request for complete aiding data
6612 GnssAdapterReqAidingDataCb reqAidingDataCb =
6613 [this] (const GnssAidingDataSvMask& svDataMask) {
6614 mLocApi->requestForAidingData(svDataMask);
6615 };
6616
6617 GnssAdapterUpdateNHzRequirementCb updateNHzRequirementCb =
6618 [this] (bool nHzNeeded, bool nHzMeasNeeded) {
6619
6620 if (nHzMeasNeeded &&
6621 (!checkMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT))) {
6622 updateEvtMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT,
6623 LOC_REGISTRATION_MASK_ENABLED);
6624 } else if (checkMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT)) {
6625 updateEvtMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT,
6626 LOC_REGISTRATION_MASK_DISABLED);
6627 }
6628
6629 if (mNHzNeeded != nHzNeeded) {
6630 mNHzNeeded = nHzNeeded;
6631 checkAndRestartSPESession();
6632 }
6633 };
6634
6635 GnssAdapterUpdateQwesFeatureStatusCb updateQwesFeatureStatusCb =
6636 [this] (const std::unordered_map<LocationQwesFeatureType, bool> &featureMap) {
Michael Bestas9f1f76e2024-05-28 23:23:20 +03006637 ContextBase::setQwesFeatureStatus(featureMap);
Michael Bestas3a0209e2023-05-04 01:15:47 +03006638 reportQwesCapabilities(featureMap);
6639 };
6640
6641 getEngHubProxyFn* getter = (getEngHubProxyFn*) dlsym(handle, "getEngHubProxy");
6642 if(getter != nullptr) {
Michael Bestas9f1f76e2024-05-28 23:23:20 +03006643 // Wait for the script(rootdir/etc/init.qcom.rc) to create socket folder
6644
6645 EngineHubProxyBase* hubProxy = (*getter) (mMsgTask, mContext,
6646 mSystemStatus->getOsObserver(),
6647 reportPositionEventCb, reportSvEventCb, reqAidingDataCb,
6648 updateNHzRequirementCb, updateQwesFeatureStatusCb);
6649
Michael Bestas3a0209e2023-05-04 01:15:47 +03006650 if (hubProxy != nullptr) {
6651 mEngHubProxy = hubProxy;
6652 engHubLoadSuccessful = true;
6653 }
6654 }
6655 else {
6656 LOC_LOGD("%s]: entered, did not find function", __func__);
6657 }
6658
6659 LOC_LOGD("%s]: first time initialization %d, returned %d",
6660 __func__, firstTime, engHubLoadSuccessful);
6661
6662 } while (0);
6663
6664 if (processInfoList != nullptr) {
6665 free (processInfoList);
6666 processInfoList = nullptr;
6667 }
6668
6669 firstTime = false;
6670 return engHubLoadSuccessful;
6671}
6672
6673std::vector<double>
6674GnssAdapter::parseDoublesString(char* dString) {
6675 std::vector<double> dVector;
6676 char* tmp = NULL;
6677 char* substr;
6678
6679 dVector.clear();
6680 for (substr = strtok_r(dString, " ", &tmp);
6681 substr != NULL;
6682 substr = strtok_r(NULL, " ", &tmp)) {
6683 dVector.push_back(std::stod(substr));
6684 }
6685 return dVector;
6686}
6687
6688void
6689GnssAdapter::reportGnssAntennaInformation(const antennaInfoCb antennaInfoCallback)
6690{
6691#define MAX_TEXT_WIDTH 50
6692#define MAX_COLUMN_WIDTH 20
6693
6694 /* parse antenna_corrections file and fill in
6695 a vector of GnssAntennaInformation data structure */
6696
6697 std::vector<GnssAntennaInformation> gnssAntennaInformations;
6698 GnssAntennaInformation gnssAntennaInfo;
6699
6700 uint32_t antennaInfoVectorSize;
6701 loc_param_s_type ant_info_vector_table[] =
6702 {
6703 { "ANTENNA_INFO_VECTOR_SIZE", &antennaInfoVectorSize, NULL, 'n' }
6704 };
6705 UTIL_READ_CONF(LOC_PATH_ANT_CORR, ant_info_vector_table);
6706
6707 for (uint32_t i = 0; i < antennaInfoVectorSize; i++) {
6708 double carrierFrequencyMHz;
6709 char pcOffsetStr[LOC_MAX_PARAM_STRING];
6710 uint32_t numberOfRows = 0;
6711 uint32_t numberOfColumns = 0;
6712 uint32_t numberOfRowsSGC = 0;
6713 uint32_t numberOfColumnsSGC = 0;
6714
6715 gnssAntennaInfo.phaseCenterVariationCorrectionMillimeters.clear();
6716 gnssAntennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters.clear();
6717 gnssAntennaInfo.signalGainCorrectionDbi.clear();
6718 gnssAntennaInfo.signalGainCorrectionUncertaintyDbi.clear();
6719 string s1 = "CARRIER_FREQUENCY_";
6720 s1 += to_string(i);
6721 string s2 = "PC_OFFSET_";
6722 s2 += to_string(i);
6723 string s3 = "NUMBER_OF_ROWS_";
6724 s3 += to_string(i);
6725 string s4 = "NUMBER_OF_COLUMNS_";
6726 s4 += to_string(i);
6727 string s5 = "NUMBER_OF_ROWS_SGC_";
6728 s5 += to_string(i);
6729 string s6 = "NUMBER_OF_COLUMNS_SGC_";
6730 s6 += to_string(i);
6731
6732 gnssAntennaInfo.size = sizeof(gnssAntennaInfo);
6733 loc_param_s_type ant_cf_table[] =
6734 {
6735 { s1.c_str(), &carrierFrequencyMHz, NULL, 'f' },
6736 { s2.c_str(), &pcOffsetStr, NULL, 's' },
6737 { s3.c_str(), &numberOfRows, NULL, 'n' },
6738 { s4.c_str(), &numberOfColumns, NULL, 'n' },
6739 { s5.c_str(), &numberOfRowsSGC, NULL, 'n' },
6740 { s6.c_str(), &numberOfColumnsSGC, NULL, 'n' },
6741 };
6742 UTIL_READ_CONF(LOC_PATH_ANT_CORR, ant_cf_table);
6743
6744 if (0 == numberOfRowsSGC) {
6745 numberOfRowsSGC = numberOfRows;
6746 }
6747 if (0 == numberOfColumnsSGC) {
6748 numberOfColumnsSGC = numberOfColumns;
6749 }
6750
6751 gnssAntennaInfo.carrierFrequencyMHz = carrierFrequencyMHz;
6752
6753 // now parse pcOffsetStr to get each entry
6754 std::vector<double> pcOffset;
6755 pcOffset = parseDoublesString(pcOffsetStr);
6756 gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.size =
6757 sizeof(gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters);
6758 gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.x = pcOffset[0];
6759 gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.xUncertainty = pcOffset[1];
6760 gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.y = pcOffset[2];
6761 gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.yUncertainty = pcOffset[3];
6762 gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.z = pcOffset[4];
6763 gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.zUncertainty = pcOffset[5];
6764
6765 uint16_t array_size = MAX_TEXT_WIDTH + MAX_COLUMN_WIDTH*numberOfColumns;
6766 uint16_t array_size_SGC = MAX_TEXT_WIDTH + MAX_COLUMN_WIDTH*numberOfColumnsSGC;
6767 for (uint32_t j = 0; j < numberOfRows; j++) {
6768 char pcVarCorrStr[array_size];
6769 char pcVarCorrUncStr[array_size];
6770
6771 string s1 = "PC_VARIATION_CORRECTION_" + to_string(i) + "_ROW_";
6772 s1 += to_string(j);
6773 string s2 = "PC_VARIATION_CORRECTION_UNC_" + to_string(i) + "_ROW_";
6774 s2 += to_string(j);
6775
6776 loc_param_s_type ant_row_table[] =
6777 {
6778 { s1.c_str(), &pcVarCorrStr, NULL, 's' },
6779 { s2.c_str(), &pcVarCorrUncStr, NULL, 's' },
6780 };
6781 UTIL_READ_CONF_LONG(LOC_PATH_ANT_CORR, ant_row_table, array_size);
6782
6783 gnssAntennaInfo.phaseCenterVariationCorrectionMillimeters.push_back(
6784 parseDoublesString(pcVarCorrStr));
6785 gnssAntennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters.push_back(
6786 parseDoublesString(pcVarCorrUncStr));
6787 }
6788 for (uint32_t j = 0; j < numberOfRowsSGC; j++) {
6789 char sigGainCorrStr[array_size_SGC];
6790 char sigGainCorrUncStr[array_size_SGC];
6791
6792 string s3 = "SIGNAL_GAIN_CORRECTION_" + to_string(i) + "_ROW_";
6793 s3 += to_string(j);
6794 string s4 = "SIGNAL_GAIN_CORRECTION_UNC_" + to_string(i) + "_ROW_";
6795 s4 += to_string(j);
6796
6797 loc_param_s_type ant_row_table[] =
6798 {
6799 { s3.c_str(), &sigGainCorrStr, NULL, 's' },
6800 { s4.c_str(), &sigGainCorrUncStr, NULL, 's' },
6801 };
6802 UTIL_READ_CONF_LONG(LOC_PATH_ANT_CORR, ant_row_table, array_size_SGC);
6803
6804 gnssAntennaInfo.signalGainCorrectionDbi.push_back(
6805 parseDoublesString(sigGainCorrStr));
6806 gnssAntennaInfo.signalGainCorrectionUncertaintyDbi.push_back(
6807 parseDoublesString(sigGainCorrUncStr));
6808 }
6809 gnssAntennaInformations.push_back(std::move(gnssAntennaInfo));
6810 }
6811 if (antennaInfoVectorSize > 0) {
6812 antennaInfoCallback(gnssAntennaInformations);
6813 }
6814}
6815
6816/* ==== DGnss Usable Reporter ========================================================= */
6817/* ======== UTILITIES ================================================================= */
6818
6819void GnssAdapter::initCDFWService()
6820{
6821 LOC_LOGv("mCdfwInterface %p", mCdfwInterface);
6822 if (nullptr == mCdfwInterface) {
6823 void* libHandle = nullptr;
6824 const char* libName = "libcdfw.so";
6825
6826 libHandle = nullptr;
6827 getCdfwInterface getter = (getCdfwInterface)dlGetSymFromLib(libHandle,
6828 libName, "getQCdfwInterface");
6829 if (nullptr == getter) {
6830 LOC_LOGe("dlGetSymFromLib getQCdfwInterface failed");
6831 } else {
6832 mCdfwInterface = getter();
6833 }
6834
6835 if (nullptr != mCdfwInterface) {
6836 QDgnssSessionActiveCb qDgnssSessionActiveCb = [this] (bool sessionActive) {
6837 mDGnssNeedReport = sessionActive;
6838 };
6839 mCdfwInterface->startDgnssApiService(*mMsgTask);
6840 mQDgnssListenerHDL = mCdfwInterface->createUsableReporter(qDgnssSessionActiveCb);
6841 }
6842 }
6843}
6844
6845/*==== DGnss Ntrip Source ==========================================================*/
6846void GnssAdapter::enablePPENtripStreamCommand(const GnssNtripConnectionParams& params,
6847 bool enableRTKEngine) {
6848
6849 (void)enableRTKEngine; //future parameter, not used
6850 if (0 == params.size || params.hostNameOrIp.empty() || params.mountPoint.empty() ||
6851 params.username.empty() || params.password.empty()) {
6852 LOC_LOGe("Ntrip parameters are invalid!");
6853 return;
6854 }
6855
6856 struct enableNtripMsg : public LocMsg {
6857 GnssAdapter& mAdapter;
6858 const GnssNtripConnectionParams mParams;
6859
6860 inline enableNtripMsg(GnssAdapter& adapter,
6861 const GnssNtripConnectionParams& params) :
6862 LocMsg(),
6863 mAdapter(adapter),
6864 mParams(std::move(params)) {}
6865 inline virtual void proc() const {
6866 mAdapter.handleEnablePPENtrip(mParams);
6867 }
6868 };
6869 sendMsg(new enableNtripMsg(*this, params));
6870}
6871
6872void GnssAdapter::handleEnablePPENtrip(const GnssNtripConnectionParams& params) {
6873 LOC_LOGd("%d %s %d %s %s %s %d mSendNmeaConsent %d",
6874 params.useSSL, params.hostNameOrIp.data(), params.port,
6875 params.mountPoint.data(), params.username.data(), params.password.data(),
6876 params.requiresNmeaLocation, mSendNmeaConsent);
6877
6878 GnssNtripConnectionParams* pNtripParams = &(mStartDgnssNtripParams.ntripParams);
6879
6880 if (pNtripParams->useSSL == params.useSSL &&
6881 0 == pNtripParams->hostNameOrIp.compare(params.hostNameOrIp) &&
6882 pNtripParams->port == params.port &&
6883 0 == pNtripParams->mountPoint.compare(params.mountPoint) &&
6884 0 == pNtripParams->username.compare(params.username) &&
6885 0 == pNtripParams->password.compare(params.password) &&
6886 pNtripParams->requiresNmeaLocation == params.requiresNmeaLocation &&
6887 mDgnssState & DGNSS_STATE_ENABLE_NTRIP_COMMAND) {
6888 LOC_LOGd("received same Ntrip param");
6889 return;
6890 }
6891
6892 mDgnssState |= DGNSS_STATE_ENABLE_NTRIP_COMMAND;
6893 mDgnssState |= DGNSS_STATE_NO_NMEA_PENDING;
6894 mDgnssState &= ~DGNSS_STATE_NTRIP_SESSION_STARTED;
6895
6896 mStartDgnssNtripParams.ntripParams = std::move(params);
6897 mStartDgnssNtripParams.nmea.clear();
6898 if (mSendNmeaConsent && pNtripParams->requiresNmeaLocation) {
6899 mDgnssState &= ~DGNSS_STATE_NO_NMEA_PENDING;
6900 mDgnssLastNmeaBootTimeMilli = 0;
6901 return;
6902 }
6903
6904 checkUpdateDgnssNtrip(false);
6905}
6906
6907void GnssAdapter::disablePPENtripStreamCommand() {
6908 struct disableNtripMsg : public LocMsg {
6909 GnssAdapter& mAdapter;
6910
6911 inline disableNtripMsg(GnssAdapter& adapter) :
6912 LocMsg(),
6913 mAdapter(adapter) {}
6914 inline virtual void proc() const {
6915 mAdapter.handleDisablePPENtrip();
6916 }
6917 };
6918 sendMsg(new disableNtripMsg(*this));
6919}
6920
6921void GnssAdapter::handleDisablePPENtrip() {
6922 mDgnssState &= ~DGNSS_STATE_ENABLE_NTRIP_COMMAND;
6923 mDgnssState |= DGNSS_STATE_NO_NMEA_PENDING;
6924 stopDgnssNtrip();
6925}
6926
6927void GnssAdapter::checkUpdateDgnssNtrip(bool isLocationValid) {
6928 LOC_LOGd("isInSession %d mDgnssState 0x%x isLocationValid %d",
6929 isInSession(), mDgnssState, isLocationValid);
6930 if (isInSession()) {
6931 uint64_t curBootTime = getBootTimeMilliSec();
6932 if (mDgnssState == (DGNSS_STATE_ENABLE_NTRIP_COMMAND | DGNSS_STATE_NO_NMEA_PENDING)) {
6933 mDgnssState |= DGNSS_STATE_NTRIP_SESSION_STARTED;
6934 mXtraObserver.startDgnssSource(mStartDgnssNtripParams);
6935 if (isDgnssNmeaRequired()) {
6936 mDgnssLastNmeaBootTimeMilli = curBootTime;
6937 }
6938 } else if ((mDgnssState & DGNSS_STATE_NTRIP_SESSION_STARTED) && isLocationValid &&
6939 isDgnssNmeaRequired() &&
6940 curBootTime - mDgnssLastNmeaBootTimeMilli > DGNSS_RANGE_UPDATE_TIME_10MIN_IN_MILLI ) {
6941 mXtraObserver.updateNmeaToDgnssServer(mStartDgnssNtripParams.nmea);
6942 mDgnssLastNmeaBootTimeMilli = curBootTime;
6943 }
6944 }
6945}
6946
6947void GnssAdapter::stopDgnssNtrip() {
6948 LOC_LOGd("isInSession %d mDgnssState 0x%x", isInSession(), mDgnssState);
6949 mStartDgnssNtripParams.nmea.clear();
6950 if (mDgnssState & DGNSS_STATE_NTRIP_SESSION_STARTED) {
6951 mDgnssState &= ~DGNSS_STATE_NTRIP_SESSION_STARTED;
6952 mXtraObserver.stopDgnssSource();
6953 }
6954}
6955
6956void GnssAdapter::reportGGAToNtrip(const char* nmea) {
6957
6958#define POS_OF_GGA (3) //start position of "GGA"
6959#define COMMAS_BEFORE_VALID (6) //"$GPGGA,,,,,,0,,,,,,,,*hh"
6960
6961 if (!isDgnssNmeaRequired()) {
6962 return;
6963 }
6964
6965 if (nullptr == nmea || 0 == strlen(nmea)) {
6966 return;
6967 }
6968
6969 string nmeaString(nmea);
6970 size_t foundPos = nmeaString.find("GGA");
6971 size_t foundNth = 0;
6972 string GGAString;
6973
6974 if (foundPos != string::npos && foundPos >= POS_OF_GGA) {
6975 size_t foundNextSentence = nmeaString.find("$", foundPos);
6976 if (foundNextSentence != string::npos) {
6977 /* remove other sentences after GGA */
6978 GGAString = nmeaString.substr(foundPos - POS_OF_GGA, foundNextSentence);
6979 } else {
6980 /* GGA is the last sentence */
6981 GGAString = nmeaString.substr(foundPos - POS_OF_GGA);
6982 }
6983 LOC_LOGd("GGAString %s", GGAString.c_str());
6984
6985 foundPos = GGAString.find(",");
6986 while (foundPos != string::npos && foundNth < COMMAS_BEFORE_VALID) {
6987 foundPos++;
6988 foundNth++;
6989 foundPos = GGAString.find(",", foundPos);
6990 }
6991
6992 if (COMMAS_BEFORE_VALID == foundNth && GGAString.at(foundPos-1) != '0') {
6993 mDgnssState |= DGNSS_STATE_NO_NMEA_PENDING;
6994 mStartDgnssNtripParams.nmea = std::move(GGAString);
6995 checkUpdateDgnssNtrip(true);
6996 }
6997 }
6998
6999 return;
7000}