1 /* Copyright (c) 2017-2019, 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
50 #define RAD2DEG (180.0 / M_PI)
51 #define PROCESS_NAME_ENGINE_SERVICE "engine-service"
52 #define MIN_TRACKING_INTERVAL (100) // 100 msec
53
54 using namespace loc_core;
55
56 /* Method to fetch status cb from loc_net_iface library */
57 typedef AgpsCbInfo& (*LocAgpsGetAgpsCbInfo)(LocAgpsOpenResultCb openResultCb,
58 LocAgpsCloseResultCb closeResultCb, void* userDataPtr);
59
60 static void agpsOpenResultCb (bool isSuccess, AGpsExtType agpsType, const char* apn,
61 AGpsBearerType bearerType, void* userDataPtr);
62 static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userDataPtr);
63
GnssAdapter()64 GnssAdapter::GnssAdapter() :
65 LocAdapterBase(0,
66 LocContext::getLocContext(NULL,
67 NULL,
68 LocContext::mLocationHalName,
69 false),
70 true, nullptr, true),
71 mEngHubProxy(new EngineHubProxyBase()),
72 mLocPositionMode(),
73 mNHzNeeded(false),
74 mSPEAlreadyRunningAtHighestInterval(false),
75 mGnssSvIdUsedInPosition(),
76 mGnssSvIdUsedInPosAvail(false),
77 mControlCallbacks(),
78 mAfwControlId(0),
79 mNmeaMask(0),
80 mGnssSvIdConfig(),
81 mGnssSvTypeConfig(),
82 mGnssSvTypeConfigCb(nullptr),
83 mLocConfigInfo{},
84 mNiData(),
85 mAgpsManager(),
86 mOdcpiRequestCb(nullptr),
87 mOdcpiRequestActive(false),
88 mOdcpiTimer(this),
89 mOdcpiRequest(),
90 mSystemStatus(SystemStatus::getInstance(mMsgTask)),
91 mServerUrl(":"),
92 mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask),
93 mLocSystemInfo{},
94 mBlockCPIInfo{},
95 mNfwCb(NULL),
96 mPowerOn(false),
97 mAllowFlpNetworkFixes(0),
98 mGnssEnergyConsumedCb(nullptr),
99 mPowerStateCb(nullptr),
100 mIsE911Session(NULL),
101 mGnssMbSvIdUsedInPosition{},
102 mGnssMbSvIdUsedInPosAvail(false),
103 mSupportNfwControl(true),
104 mSystemPowerState(POWER_STATE_UNKNOWN)
105 {
106 LOC_LOGD("%s]: Constructor %p", __func__, this);
107 mLocPositionMode.mode = LOC_POSITION_MODE_INVALID;
108
109 pthread_condattr_t condAttr;
110 pthread_condattr_init(&condAttr);
111 pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC);
112 pthread_cond_init(&mNiData.session.tCond, &condAttr);
113 pthread_cond_init(&mNiData.sessionEs.tCond, &condAttr);
114 pthread_condattr_destroy(&condAttr);
115
116 /* Set ATL open/close callbacks */
117 AgpsAtlOpenStatusCb atlOpenStatusCb =
118 [this](int handle, int isSuccess, char* apn, uint32_t apnLen,
__anon7b860ba70102(int handle, int isSuccess, char* apn, uint32_t apnLen, AGpsBearerType bearerType, AGpsExtType agpsType, LocApnTypeMask mask) 119 AGpsBearerType bearerType, AGpsExtType agpsType, LocApnTypeMask mask) {
120
121 mLocApi->atlOpenStatus(
122 handle, isSuccess, apn, apnLen, bearerType, agpsType, mask);
123 };
124 AgpsAtlCloseStatusCb atlCloseStatusCb =
__anon7b860ba70202(int handle, int isSuccess) 125 [this](int handle, int isSuccess) {
126
127 mLocApi->atlCloseStatus(handle, isSuccess);
128 };
129 mAgpsManager.registerATLCallbacks(atlOpenStatusCb, atlCloseStatusCb);
130
131 readConfigCommand();
132 initDefaultAgpsCommand();
133 initEngHubProxyCommand();
134
135 // at last step, let us inform adapater base that we are done
136 // with initialization, e.g.: ready to process handleEngineUpEvent
137 doneInit();
138 }
139
140 void
setControlCallbacksCommand(LocationControlCallbacks & controlCallbacks)141 GnssAdapter::setControlCallbacksCommand(LocationControlCallbacks& controlCallbacks)
142 {
143 struct MsgSetControlCallbacks : public LocMsg {
144 GnssAdapter& mAdapter;
145 const LocationControlCallbacks mControlCallbacks;
146 inline MsgSetControlCallbacks(GnssAdapter& adapter,
147 LocationControlCallbacks& controlCallbacks) :
148 LocMsg(),
149 mAdapter(adapter),
150 mControlCallbacks(controlCallbacks) {}
151 inline virtual void proc() const {
152 mAdapter.setControlCallbacks(mControlCallbacks);
153 }
154 };
155
156 sendMsg(new MsgSetControlCallbacks(*this, controlCallbacks));
157 }
158
159 void
convertOptions(LocPosMode & out,const TrackingOptions & trackingOptions)160 GnssAdapter::convertOptions(LocPosMode& out, const TrackingOptions& trackingOptions)
161 {
162 switch (trackingOptions.mode) {
163 case GNSS_SUPL_MODE_MSB:
164 out.mode = LOC_POSITION_MODE_MS_BASED;
165 break;
166 case GNSS_SUPL_MODE_MSA:
167 out.mode = LOC_POSITION_MODE_MS_ASSISTED;
168 break;
169 default:
170 out.mode = LOC_POSITION_MODE_STANDALONE;
171 break;
172 }
173 out.share_position = true;
174 out.min_interval = trackingOptions.minInterval;
175 out.powerMode = trackingOptions.powerMode;
176 out.timeBetweenMeasurements = trackingOptions.tbm;
177 }
178
179 bool
checkAndSetSPEToRunforNHz(TrackingOptions & out)180 GnssAdapter::checkAndSetSPEToRunforNHz(TrackingOptions & out) {
181 // first check if NHz meas is needed at all, if not, just return false
182 // if a NHz capable engine is subscribed for NHz measurement or NHz positions,
183 // always run the SPE only session at 100ms TBF.
184 // If SPE session is already set to highest interval, no need to start it again.
185
186 bool isSPERunningAtHighestInterval = false;
187
188 if (!mNHzNeeded) {
189 LOC_LOGd("No nHz session needed.");
190 } else if (mSPEAlreadyRunningAtHighestInterval) {
191 LOC_LOGd("SPE is already running at highest interval.");
192 isSPERunningAtHighestInterval = true;
193 } else if (out.minInterval > MIN_TRACKING_INTERVAL) {
194 out.minInterval = MIN_TRACKING_INTERVAL;
195 LOC_LOGd("nHz session is needed, starting SPE only session at 100ms TBF.");
196 mSPEAlreadyRunningAtHighestInterval = true;
197 }
198
199 return isSPERunningAtHighestInterval;
200 }
201
202
203 void
convertLocation(Location & out,const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,const LocPosTechMask techMask)204 GnssAdapter::convertLocation(Location& out, const UlpLocation& ulpLocation,
205 const GpsLocationExtended& locationExtended,
206 const LocPosTechMask techMask)
207 {
208 memset(&out, 0, sizeof(Location));
209 out.size = sizeof(Location);
210 if (LOC_GPS_LOCATION_HAS_LAT_LONG & ulpLocation.gpsLocation.flags) {
211 out.flags |= LOCATION_HAS_LAT_LONG_BIT;
212 out.latitude = ulpLocation.gpsLocation.latitude;
213 out.longitude = ulpLocation.gpsLocation.longitude;
214 }
215 if (LOC_GPS_LOCATION_HAS_ALTITUDE & ulpLocation.gpsLocation.flags) {
216 out.flags |= LOCATION_HAS_ALTITUDE_BIT;
217 out.altitude = ulpLocation.gpsLocation.altitude;
218 }
219 if (LOC_GPS_LOCATION_HAS_SPEED & ulpLocation.gpsLocation.flags) {
220 out.flags |= LOCATION_HAS_SPEED_BIT;
221 out.speed = ulpLocation.gpsLocation.speed;
222 }
223 if (LOC_GPS_LOCATION_HAS_BEARING & ulpLocation.gpsLocation.flags) {
224 out.flags |= LOCATION_HAS_BEARING_BIT;
225 out.bearing = ulpLocation.gpsLocation.bearing;
226 }
227 if (LOC_GPS_LOCATION_HAS_ACCURACY & ulpLocation.gpsLocation.flags) {
228 out.flags |= LOCATION_HAS_ACCURACY_BIT;
229 out.accuracy = ulpLocation.gpsLocation.accuracy;
230 }
231 if (GPS_LOCATION_EXTENDED_HAS_VERT_UNC & locationExtended.flags) {
232 out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
233 out.verticalAccuracy = locationExtended.vert_unc;
234 }
235 if (GPS_LOCATION_EXTENDED_HAS_SPEED_UNC & locationExtended.flags) {
236 out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
237 out.speedAccuracy = locationExtended.speed_unc;
238 }
239 if (GPS_LOCATION_EXTENDED_HAS_BEARING_UNC & locationExtended.flags) {
240 out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
241 out.bearingAccuracy = locationExtended.bearing_unc;
242 }
243 out.timestamp = ulpLocation.gpsLocation.timestamp;
244 if (LOC_POS_TECH_MASK_SATELLITE & techMask) {
245 out.techMask |= LOCATION_TECHNOLOGY_GNSS_BIT;
246 }
247 if (LOC_POS_TECH_MASK_CELLID & techMask) {
248 out.techMask |= LOCATION_TECHNOLOGY_CELL_BIT;
249 }
250 if (LOC_POS_TECH_MASK_WIFI & techMask) {
251 out.techMask |= LOCATION_TECHNOLOGY_WIFI_BIT;
252 }
253 if (LOC_POS_TECH_MASK_SENSORS & techMask) {
254 out.techMask |= LOCATION_TECHNOLOGY_SENSORS_BIT;
255 }
256
257 if (LOC_GPS_LOCATION_HAS_SPOOF_MASK & ulpLocation.gpsLocation.flags) {
258 out.flags |= LOCATION_HAS_SPOOF_MASK;
259 out.spoofMask = ulpLocation.gpsLocation.spoof_mask;
260 }
261 }
262
263 /* This is utility routine that computes number of SV used
264 in the fix from the svUsedIdsMask.
265 */
266 #define MAX_SV_CNT_SUPPORTED_IN_ONE_CONSTELLATION 64
getNumSvUsed(uint64_t svUsedIdsMask,int totalSvCntInThisConstellation)267 uint16_t GnssAdapter::getNumSvUsed(uint64_t svUsedIdsMask,
268 int totalSvCntInThisConstellation)
269 {
270 if (totalSvCntInThisConstellation > MAX_SV_CNT_SUPPORTED_IN_ONE_CONSTELLATION) {
271 LOC_LOGe ("error: total SV count in this constellation %d exceeded limit of %d",
272 totalSvCntInThisConstellation, MAX_SV_CNT_SUPPORTED_IN_ONE_CONSTELLATION);
273 return 0;
274 }
275
276 uint16_t numSvUsed = 0;
277 uint64_t mask = 0x1;
278 for (int i = 0; i < totalSvCntInThisConstellation; i++) {
279 if (svUsedIdsMask & mask) {
280 numSvUsed++;
281 }
282 mask <<= 1;
283 }
284
285 return numSvUsed;
286 }
287
288 void
convertLocationInfo(GnssLocationInfoNotification & out,const GpsLocationExtended & locationExtended)289 GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out,
290 const GpsLocationExtended& locationExtended)
291 {
292 out.size = sizeof(GnssLocationInfoNotification);
293 if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL & locationExtended.flags) {
294 out.flags |= GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT;
295 out.altitudeMeanSeaLevel = locationExtended.altitudeMeanSeaLevel;
296 }
297 if (GPS_LOCATION_EXTENDED_HAS_EXT_DOP & locationExtended.flags) {
298 out.flags |= (GNSS_LOCATION_INFO_DOP_BIT|GNSS_LOCATION_INFO_EXT_DOP_BIT);
299 out.pdop = locationExtended.extDOP.PDOP;
300 out.hdop = locationExtended.extDOP.HDOP;
301 out.vdop = locationExtended.extDOP.VDOP;
302 out.gdop = locationExtended.extDOP.GDOP;
303 out.tdop = locationExtended.extDOP.TDOP;
304 } else if (GPS_LOCATION_EXTENDED_HAS_DOP & locationExtended.flags) {
305 out.flags |= GNSS_LOCATION_INFO_DOP_BIT;
306 out.pdop = locationExtended.pdop;
307 out.hdop = locationExtended.hdop;
308 out.vdop = locationExtended.vdop;
309 }
310 if (GPS_LOCATION_EXTENDED_HAS_MAG_DEV & locationExtended.flags) {
311 out.flags |= GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT;
312 out.magneticDeviation = locationExtended.magneticDeviation;
313 }
314 if (GPS_LOCATION_EXTENDED_HAS_HOR_RELIABILITY & locationExtended.flags) {
315 out.flags |= GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT;
316 switch (locationExtended.horizontal_reliability) {
317 case LOC_RELIABILITY_VERY_LOW:
318 out.horReliability = LOCATION_RELIABILITY_VERY_LOW;
319 break;
320 case LOC_RELIABILITY_LOW:
321 out.horReliability = LOCATION_RELIABILITY_LOW;
322 break;
323 case LOC_RELIABILITY_MEDIUM:
324 out.horReliability = LOCATION_RELIABILITY_MEDIUM;
325 break;
326 case LOC_RELIABILITY_HIGH:
327 out.horReliability = LOCATION_RELIABILITY_HIGH;
328 break;
329 default:
330 out.horReliability = LOCATION_RELIABILITY_NOT_SET;
331 break;
332 }
333 }
334 if (GPS_LOCATION_EXTENDED_HAS_VERT_RELIABILITY & locationExtended.flags) {
335 out.flags |= GNSS_LOCATION_INFO_VER_RELIABILITY_BIT;
336 switch (locationExtended.vertical_reliability) {
337 case LOC_RELIABILITY_VERY_LOW:
338 out.verReliability = LOCATION_RELIABILITY_VERY_LOW;
339 break;
340 case LOC_RELIABILITY_LOW:
341 out.verReliability = LOCATION_RELIABILITY_LOW;
342 break;
343 case LOC_RELIABILITY_MEDIUM:
344 out.verReliability = LOCATION_RELIABILITY_MEDIUM;
345 break;
346 case LOC_RELIABILITY_HIGH:
347 out.verReliability = LOCATION_RELIABILITY_HIGH;
348 break;
349 default:
350 out.verReliability = LOCATION_RELIABILITY_NOT_SET;
351 break;
352 }
353 }
354 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MAJOR & locationExtended.flags) {
355 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT;
356 out.horUncEllipseSemiMajor = locationExtended.horUncEllipseSemiMajor;
357 }
358 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MINOR & locationExtended.flags) {
359 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT;
360 out.horUncEllipseSemiMinor = locationExtended.horUncEllipseSemiMinor;
361 }
362 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_AZIMUTH & locationExtended.flags) {
363 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT;
364 out.horUncEllipseOrientAzimuth = locationExtended.horUncEllipseOrientAzimuth;
365 }
366 if (GPS_LOCATION_EXTENDED_HAS_NORTH_STD_DEV & locationExtended.flags) {
367 out.flags |= GNSS_LOCATION_INFO_NORTH_STD_DEV_BIT;
368 out.northStdDeviation = locationExtended.northStdDeviation;
369 }
370 if (GPS_LOCATION_EXTENDED_HAS_EAST_STD_DEV & locationExtended.flags) {
371 out.flags |= GNSS_LOCATION_INFO_EAST_STD_DEV_BIT;
372 out.eastStdDeviation = locationExtended.eastStdDeviation;
373 }
374 if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL & locationExtended.flags) {
375 out.flags |= GNSS_LOCATION_INFO_NORTH_VEL_BIT;
376 out.northVelocity = locationExtended.northVelocity;
377 }
378 if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC & locationExtended.flags) {
379 out.flags |= GNSS_LOCATION_INFO_NORTH_VEL_UNC_BIT;
380 out.northVelocityStdDeviation = locationExtended.northVelocityStdDeviation;
381 }
382 if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL & locationExtended.flags) {
383 out.flags |= GNSS_LOCATION_INFO_EAST_VEL_BIT;
384 out.eastVelocity = locationExtended.eastVelocity;
385 }
386 if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC & locationExtended.flags) {
387 out.flags |= GNSS_LOCATION_INFO_EAST_VEL_UNC_BIT;
388 out.eastVelocityStdDeviation = locationExtended.eastVelocityStdDeviation;
389 }
390 if (GPS_LOCATION_EXTENDED_HAS_UP_VEL & locationExtended.flags) {
391 out.flags |= GNSS_LOCATION_INFO_UP_VEL_BIT;
392 out.upVelocity = locationExtended.upVelocity;
393 }
394 if (GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC & locationExtended.flags) {
395 out.flags |= GNSS_LOCATION_INFO_UP_VEL_UNC_BIT;
396 out.upVelocityStdDeviation = locationExtended.upVelocityStdDeviation;
397 }
398 if (GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA & locationExtended.flags) {
399 out.flags |= GNSS_LOCATION_INFO_GNSS_SV_USED_DATA_BIT;
400 out.svUsedInPosition.gpsSvUsedIdsMask =
401 locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask;
402 out.svUsedInPosition.gloSvUsedIdsMask =
403 locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask;
404 out.svUsedInPosition.galSvUsedIdsMask =
405 locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask;
406 out.svUsedInPosition.bdsSvUsedIdsMask =
407 locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask;
408 out.svUsedInPosition.qzssSvUsedIdsMask =
409 locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask;
410
411 out.flags |= GNSS_LOCATION_INFO_NUM_SV_USED_IN_POSITION_BIT;
412 out.numSvUsedInPosition = getNumSvUsed(out.svUsedInPosition.gpsSvUsedIdsMask,
413 GPS_SV_PRN_MAX - GPS_SV_PRN_MIN + 1);
414 out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.gloSvUsedIdsMask,
415 GLO_SV_PRN_MAX - GLO_SV_PRN_MIN + 1);
416 out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.qzssSvUsedIdsMask,
417 QZSS_SV_PRN_MAX - QZSS_SV_PRN_MIN + 1);
418 out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.bdsSvUsedIdsMask,
419 BDS_SV_PRN_MAX - BDS_SV_PRN_MIN + 1);
420 out.numSvUsedInPosition += getNumSvUsed(out.svUsedInPosition.galSvUsedIdsMask,
421 GAL_SV_PRN_MAX - GAL_SV_PRN_MIN + 1);
422
423 out.numOfMeasReceived = locationExtended.numOfMeasReceived;
424 for (int idx =0; idx < locationExtended.numOfMeasReceived; idx++) {
425 out.measUsageInfo[idx].gnssSignalType =
426 locationExtended.measUsageInfo[idx].gnssSignalType;
427 out.measUsageInfo[idx].gnssSvId =
428 locationExtended.measUsageInfo[idx].gnssSvId;
429 out.measUsageInfo[idx].gnssConstellation =
430 locationExtended.measUsageInfo[idx].gnssConstellation;
431 }
432 }
433 if (GPS_LOCATION_EXTENDED_HAS_NAV_SOLUTION_MASK & locationExtended.flags) {
434 out.flags |= GNSS_LOCATION_INFO_NAV_SOLUTION_MASK_BIT;
435 out.navSolutionMask = locationExtended.navSolutionMask;
436 }
437 if (GPS_LOCATION_EXTENDED_HAS_POS_TECH_MASK & locationExtended.flags) {
438 out.flags |= GNSS_LOCATION_INFO_POS_TECH_MASK_BIT;
439 out.posTechMask = locationExtended.tech_mask;
440 }
441 if (GPS_LOCATION_EXTENDED_HAS_POS_DYNAMICS_DATA & locationExtended.flags) {
442 out.flags |= GPS_LOCATION_EXTENDED_HAS_POS_DYNAMICS_DATA;
443 if (locationExtended.bodyFrameData.bodyFrameDataMask &
444 LOCATION_NAV_DATA_HAS_LONG_ACCEL_BIT) {
445 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LONG_ACCEL_BIT;
446 }
447 if (locationExtended.bodyFrameData.bodyFrameDataMask &
448 LOCATION_NAV_DATA_HAS_LAT_ACCEL_BIT) {
449 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_LAT_ACCEL_BIT;
450 }
451 if (locationExtended.bodyFrameData.bodyFrameDataMask &
452 LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT) {
453 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_VERT_ACCEL_BIT;
454 }
455 if (locationExtended.bodyFrameData.bodyFrameDataMask & LOCATION_NAV_DATA_HAS_YAW_RATE_BIT) {
456 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_YAW_RATE_BIT;
457 }
458 if (locationExtended.bodyFrameData.bodyFrameDataMask & LOCATION_NAV_DATA_HAS_PITCH_BIT) {
459 out.bodyFrameData.bodyFrameDataMask |= LOCATION_NAV_DATA_HAS_PITCH_BIT;
460 }
461 out.bodyFrameData.longAccel = locationExtended.bodyFrameData.longAccel;
462 out.bodyFrameData.latAccel = locationExtended.bodyFrameData.latAccel;
463 out.bodyFrameData.vertAccel = locationExtended.bodyFrameData.vertAccel;
464 out.bodyFrameData.yawRate = locationExtended.bodyFrameData.yawRate;
465 out.bodyFrameData.pitch = locationExtended.bodyFrameData.pitch;
466 }
467 if (GPS_LOCATION_EXTENDED_HAS_GPS_TIME & locationExtended.flags) {
468 out.flags |= GPS_LOCATION_EXTENDED_HAS_GPS_TIME;
469 out.gnssSystemTime.gnssSystemTimeSrc = locationExtended.gnssSystemTime.gnssSystemTimeSrc;
470 out.gnssSystemTime.u = locationExtended.gnssSystemTime.u;
471 }
472 if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL & locationExtended.flags) {
473 out.flags |= GPS_LOCATION_EXTENDED_HAS_NORTH_VEL;
474 out.northVelocity = locationExtended.northVelocity;
475 }
476 if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL & locationExtended.flags) {
477 out.flags |= GPS_LOCATION_EXTENDED_HAS_EAST_VEL;
478 out.eastVelocity = locationExtended.eastVelocity;
479 }
480 if (GPS_LOCATION_EXTENDED_HAS_UP_VEL & locationExtended.flags) {
481 out.flags |= GPS_LOCATION_EXTENDED_HAS_UP_VEL;
482 out.upVelocity = locationExtended.upVelocity;
483 }
484 if (GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC & locationExtended.flags) {
485 out.flags |= GPS_LOCATION_EXTENDED_HAS_NORTH_VEL_UNC;
486 out.northVelocityStdDeviation = locationExtended.northVelocityStdDeviation;
487 }
488 if (GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC & locationExtended.flags) {
489 out.flags |= GPS_LOCATION_EXTENDED_HAS_EAST_VEL_UNC;
490 out.eastVelocityStdDeviation = locationExtended.eastVelocityStdDeviation;
491 }
492 if (GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC & locationExtended.flags) {
493 out.flags |= GPS_LOCATION_EXTENDED_HAS_UP_VEL_UNC;
494 out.upVelocityStdDeviation = locationExtended.upVelocityStdDeviation;
495 }
496
497 // Validity of this structure is established from the timeSrc of the GnssSystemTime structure.
498 out.gnssSystemTime = locationExtended.gnssSystemTime;
499
500 if (GPS_LOCATION_EXTENDED_HAS_LEAP_SECONDS & locationExtended.flags) {
501 out.flags |= GNSS_LOCATION_INFO_LEAP_SECONDS_BIT;
502 out.leapSeconds = locationExtended.leapSeconds;
503 }
504
505 if (GPS_LOCATION_EXTENDED_HAS_TIME_UNC & locationExtended.flags) {
506 out.flags |= GNSS_LOCATION_INFO_TIME_UNC_BIT;
507 out.timeUncMs = locationExtended.timeUncMs;
508 }
509
510 if (GPS_LOCATION_EXTENDED_HAS_CALIBRATION_CONFIDENCE & locationExtended.flags) {
511 out.flags |= GNSS_LOCATION_INFO_CALIBRATION_CONFIDENCE_BIT;
512 out.calibrationConfidence = locationExtended.calibrationConfidence;
513 }
514
515 if (GPS_LOCATION_EXTENDED_HAS_CALIBRATION_STATUS & locationExtended.flags) {
516 out.flags |= GNSS_LOCATION_INFO_CALIBRATION_STATUS_BIT;
517 out.calibrationStatus = locationExtended.calibrationStatus;
518 }
519
520 if (GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & locationExtended.flags) {
521 out.flags |= GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT;
522 out.locOutputEngType = locationExtended.locOutputEngType;
523 }
524
525 if (GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_MASK & locationExtended.flags) {
526 out.flags |= GNSS_LOCATION_INFO_OUTPUT_ENG_MASK_BIT;
527 out.locOutputEngMask = locationExtended.locOutputEngMask;
528 }
529 }
530
531
532
533 inline uint32_t
convertSuplVersion(const GnssConfigSuplVersion suplVersion)534 GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion)
535 {
536 switch (suplVersion) {
537 case GNSS_CONFIG_SUPL_VERSION_2_0_4:
538 return 0x00020004;
539 case GNSS_CONFIG_SUPL_VERSION_2_0_0:
540 return 0x00020000;
541 case GNSS_CONFIG_SUPL_VERSION_2_0_2:
542 return 0x00020002;
543 case GNSS_CONFIG_SUPL_VERSION_1_0_0:
544 default:
545 return 0x00010000;
546 }
547 }
548
549 inline uint32_t
convertLppProfile(const GnssConfigLppProfile lppProfile)550 GnssAdapter::convertLppProfile(const GnssConfigLppProfile lppProfile)
551 {
552 switch (lppProfile) {
553 case GNSS_CONFIG_LPP_PROFILE_USER_PLANE:
554 return 1;
555 case GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE:
556 return 2;
557 case GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE:
558 return 3;
559 case GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE:
560 default:
561 return 0;
562 }
563 }
564
565 uint32_t
convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)566 GnssAdapter::convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)
567 {
568 uint32_t mask = 0;
569 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT & lppeControlPlaneMask) {
570 mask |= (1<<0);
571 }
572 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
573 mask |= (1<<1);
574 }
575 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
576 mask |= (1<<2);
577 }
578 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeControlPlaneMask) {
579 mask |= (1<<3);
580 }
581 return mask;
582 }
583
584 uint32_t
convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)585 GnssAdapter::convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)
586 {
587 uint32_t mask = 0;
588 if (GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT & lppeUserPlaneMask) {
589 mask |= (1<<0);
590 }
591 if (GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
592 mask |= (1<<1);
593 }
594 if (GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
595 mask |= (1<<2);
596 }
597 if (GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeUserPlaneMask) {
598 mask |= (1<<3);
599 }
600 return mask;
601 }
602
603 uint32_t
convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)604 GnssAdapter::convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)
605 {
606 uint32_t mask = 0;
607 if (GNSS_CONFIG_RRC_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
608 mask |= (1<<0);
609 }
610 if (GNSS_CONFIG_RRLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
611 mask |= (1<<1);
612 }
613 if (GNSS_CONFIG_LLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
614 mask |= (1<<2);
615 }
616 if (GNSS_CONFIG_LLP_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
617 mask |= (1<<3);
618 }
619 return mask;
620 }
621
622 uint32_t
convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)623 GnssAdapter::convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)
624 {
625 switch (emergencyPdnForEmergencySupl) {
626 case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES:
627 return 1;
628 case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO:
629 default:
630 return 0;
631 }
632 }
633
634 uint32_t
convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)635 GnssAdapter::convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)
636 {
637 switch (suplEmergencyServices) {
638 case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES:
639 return 1;
640 case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO:
641 default:
642 return 0;
643 }
644 }
645
646 uint32_t
convertSuplMode(const GnssConfigSuplModeMask suplModeMask)647 GnssAdapter::convertSuplMode(const GnssConfigSuplModeMask suplModeMask)
648 {
649 uint32_t mask = 0;
650 if (GNSS_CONFIG_SUPL_MODE_MSB_BIT & suplModeMask) {
651 mask |= (1<<0);
652 }
653 if (GNSS_CONFIG_SUPL_MODE_MSA_BIT & suplModeMask) {
654 mask |= (1<<1);
655 }
656 return mask;
657 }
658
659 void
readConfigCommand()660 GnssAdapter::readConfigCommand()
661 {
662 LOC_LOGD("%s]: ", __func__);
663
664 struct MsgReadConfig : public LocMsg {
665 GnssAdapter* mAdapter;
666 ContextBase& mContext;
667 inline MsgReadConfig(GnssAdapter* adapter,
668 ContextBase& context) :
669 LocMsg(),
670 mAdapter(adapter),
671 mContext(context) {}
672 inline virtual void proc() const {
673 static bool confReadDone = false;
674 if (!confReadDone) {
675 confReadDone = true;
676 // reads config into mContext->mGps_conf
677 mContext.readConfig();
678
679 uint32_t allowFlpNetworkFixes = 0;
680 static const loc_param_s_type flp_conf_param_table[] =
681 {
682 {"ALLOW_NETWORK_FIXES", &allowFlpNetworkFixes, NULL, 'n'},
683 };
684 UTIL_READ_CONF(LOC_PATH_FLP_CONF, flp_conf_param_table);
685 LOC_LOGd("allowFlpNetworkFixes %u", allowFlpNetworkFixes);
686 mAdapter->setAllowFlpNetworkFixes(allowFlpNetworkFixes);
687 }
688 }
689 };
690
691 if (mContext != NULL) {
692 sendMsg(new MsgReadConfig(this, *mContext));
693 }
694 }
695
696 void
setSuplHostServer(const char * server,int port,LocServerType type)697 GnssAdapter::setSuplHostServer(const char* server, int port, LocServerType type)
698 {
699 if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
700 char serverUrl[MAX_URL_LEN] = {};
701 int32_t length = -1;
702 const char noHost[] = "NONE";
703
704 if ((NULL == server) || (server[0] == 0) ||
705 (strncasecmp(noHost, server, sizeof(noHost)) == 0)) {
706 serverUrl[0] = '\0';
707 length = 0;
708 } else if (port > 0) {
709 length = snprintf(serverUrl, sizeof(serverUrl), "%s:%u", server, port);
710 }
711 if (LOC_AGPS_SUPL_SERVER != type && LOC_AGPS_MO_SUPL_SERVER != type) {
712 LOC_LOGe("Invalid type=%d", type);
713 } else if (length >= 0) {
714 if (LOC_AGPS_SUPL_SERVER == type) {
715 getServerUrl().assign(serverUrl);
716 strlcpy(ContextBase::mGps_conf.SUPL_HOST, server, LOC_MAX_PARAM_STRING);
717 ContextBase::mGps_conf.SUPL_PORT = port;
718 } else {
719 if (strncasecmp(getMoServerUrl().c_str(), serverUrl, sizeof(serverUrl)) != 0) {
720 getMoServerUrl().assign(serverUrl);
721 }
722 }
723 }
724 }
725 }
726
727 void
setConfig()728 GnssAdapter::setConfig()
729 {
730 LOC_LOGD("%s]: ", __func__);
731
732 // set nmea mask type
733 uint32_t mask = 0;
734 if (NMEA_PROVIDER_MP == ContextBase::mGps_conf.NMEA_PROVIDER) {
735 mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK;
736 }
737 if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
738 mask |= LOC_NMEA_MASK_DEBUG_V02;
739 }
740 if (mNmeaMask != mask) {
741 mNmeaMask = mask;
742 if (mNmeaMask) {
743 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
744 if ((it->second.gnssNmeaCb != nullptr)) {
745 updateEvtMask(LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT,
746 LOC_REGISTRATION_MASK_ENABLED);
747 break;
748 }
749 }
750 }
751 }
752
753 std::string oldMoServerUrl = getMoServerUrl();
754 setSuplHostServer(ContextBase::mGps_conf.SUPL_HOST,
755 ContextBase::mGps_conf.SUPL_PORT,
756 LOC_AGPS_SUPL_SERVER);
757 setSuplHostServer(ContextBase::mGps_conf.MO_SUPL_HOST,
758 ContextBase::mGps_conf.MO_SUPL_PORT,
759 LOC_AGPS_MO_SUPL_SERVER);
760
761 // inject the configurations into modem
762 loc_gps_cfg_s gpsConf = ContextBase::mGps_conf;
763 loc_sap_cfg_s_type sapConf = ContextBase::mSap_conf;
764
765 //cache the injected configuration with GnssConfigRequested struct
766 GnssConfig gnssConfigRequested = {};
767 gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT |
768 GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
769 /* Here we process an SSR. We need to set the GPS_LOCK to the proper values, as follows:
770 1. Q behavior. This is identified by mSupportNfwControl being 1. In this case
771 ContextBase::mGps_conf.GPS_LOCK is a "state", meaning it should reflect the
772 NV value. Therefore we will set the NV to ContextBase::mGps_conf.GPS_LOCK
773 2. P behavior. This is identified by mSupportNfwControl being 0. In this case
774 ContextBase::mGps_conf.GPS_LOCK is a "configuration", meaning it should hold
775 the "mask" for NI. There are two subcases:
776 a. Location enabled in GUI (1 == getAfwControlId()). We need to set
777 the NV to GNSS_CONFIG_GPS_LOCK_NONE (both MO and NI enabled)
778 b. Location disabled in GUI (0 == getAfwControlId()). We need to set
779 the NV to ContextBase::mGps_conf.GPS_LOCK (the "mask", which is SIM-card
780 specific)
781 */
782 if (mSupportNfwControl || (0 == getAfwControlId())) {
783 gnssConfigRequested.gpsLock = gpsConf.GPS_LOCK;
784 } else {
785 gnssConfigRequested.gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
786 }
787 gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT |
788 GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT |
789 GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT |
790 GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
791 gnssConfigRequested.suplVersion =
792 mLocApi->convertSuplVersion(gpsConf.SUPL_VER);
793 gnssConfigRequested.lppProfile =
794 mLocApi->convertLppProfile(gpsConf.LPP_PROFILE);
795 gnssConfigRequested.aGlonassPositionProtocolMask =
796 gpsConf.A_GLONASS_POS_PROTOCOL_SELECT;
797 if (gpsConf.LPPE_CP_TECHNOLOGY) {
798 gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
799 gnssConfigRequested.lppeControlPlaneMask =
800 mLocApi->convertLppeCp(gpsConf.LPPE_CP_TECHNOLOGY);
801 }
802
803 if (gpsConf.LPPE_UP_TECHNOLOGY) {
804 gnssConfigRequested.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT;
805 gnssConfigRequested.lppeUserPlaneMask =
806 mLocApi->convertLppeUp(gpsConf.LPPE_UP_TECHNOLOGY);
807 }
808
809 gnssConfigRequested.blacklistedSvIds.assign(mBlacklistedSvIds.begin(),
810 mBlacklistedSvIds.end());
811 mLocApi->sendMsg(new LocApiMsg(
812 [this, gpsConf, sapConf, oldMoServerUrl, gnssConfigRequested] () mutable {
813 gnssUpdateConfig(oldMoServerUrl, gnssConfigRequested, gnssConfigRequested);
814
815 // set nmea mask type
816 uint32_t mask = 0;
817 if (NMEA_PROVIDER_MP == gpsConf.NMEA_PROVIDER) {
818 mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK;
819 }
820 if (ContextBase::isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) {
821 mask |= LOC_NMEA_MASK_DEBUG_V02;
822 }
823
824 if (mask != 0) {
825 mLocApi->setNMEATypesSync(mask);
826 }
827
828 mLocApi->setXtraVersionCheckSync(gpsConf.XTRA_VERSION_CHECK);
829
830 // load tunc configuration from config file on first boot-up,
831 // e.g.: adapter.mLocConfigInfo.tuncConfigInfo.isValid is false
832 if (mLocConfigInfo.tuncConfigInfo.isValid == false) {
833 mLocConfigInfo.tuncConfigInfo.isValid = true;
834 mLocConfigInfo.tuncConfigInfo.enable =
835 (gpsConf.CONSTRAINED_TIME_UNCERTAINTY_ENABLED == 1);
836 mLocConfigInfo.tuncConfigInfo.tuncThresholdMs =
837 (float)gpsConf.CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD;
838 mLocConfigInfo.tuncConfigInfo.energyBudget =
839 gpsConf.CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET;
840 }
841
842 mLocApi->setConstrainedTuncMode(
843 mLocConfigInfo.tuncConfigInfo.enable,
844 mLocConfigInfo.tuncConfigInfo.tuncThresholdMs,
845 mLocConfigInfo.tuncConfigInfo.energyBudget);
846
847 // load pace configuration from config file on first boot-up,
848 // e.g.: adapter.mLocConfigInfo.paceConfigInfo.isValid is false
849 if (mLocConfigInfo.paceConfigInfo.isValid == false) {
850 mLocConfigInfo.paceConfigInfo.isValid = true;
851 mLocConfigInfo.paceConfigInfo.enable =
852 (gpsConf.POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED==1);
853 }
854 mLocApi->setPositionAssistedClockEstimatorMode(
855 mLocConfigInfo.paceConfigInfo.enable);
856
857 if (sapConf.GYRO_BIAS_RANDOM_WALK_VALID ||
858 sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
859 sapConf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
860 sapConf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
861 sapConf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID ) {
862 mLocApi->setSensorPropertiesSync(
863 sapConf.GYRO_BIAS_RANDOM_WALK_VALID,
864 sapConf.GYRO_BIAS_RANDOM_WALK,
865 sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
866 sapConf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY,
867 sapConf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
868 sapConf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY,
869 sapConf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
870 sapConf.RATE_RANDOM_WALK_SPECTRAL_DENSITY,
871 sapConf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
872 sapConf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY);
873 }
874 mLocApi->setSensorPerfControlConfigSync(
875 sapConf.SENSOR_CONTROL_MODE,
876 sapConf.SENSOR_ACCEL_SAMPLES_PER_BATCH,
877 sapConf.SENSOR_ACCEL_BATCHES_PER_SEC,
878 sapConf.SENSOR_GYRO_SAMPLES_PER_BATCH,
879 sapConf.SENSOR_GYRO_BATCHES_PER_SEC,
880 sapConf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH,
881 sapConf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH,
882 sapConf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH,
883 sapConf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH,
884 sapConf.SENSOR_ALGORITHM_CONFIG_MASK);
885 } ));
886
887 }
888
gnssUpdateConfig(const std::string & oldMoServerUrl,GnssConfig & gnssConfigRequested,GnssConfig & gnssConfigNeedEngineUpdate,size_t count)889 std::vector<LocationError> GnssAdapter::gnssUpdateConfig(const std::string& oldMoServerUrl,
890 GnssConfig& gnssConfigRequested, GnssConfig& gnssConfigNeedEngineUpdate, size_t count) {
891 loc_gps_cfg_s gpsConf = ContextBase::mGps_conf;
892 size_t index = 0;
893 LocationError err = LOCATION_ERROR_SUCCESS;
894 std::vector<LocationError> errsList = {err};
895 if (count > 0) {
896 errsList.insert(errsList.begin(), count, LOCATION_ERROR_SUCCESS);
897 }
898
899 std::string serverUrl = getServerUrl();
900 std::string moServerUrl = getMoServerUrl();
901
902 int serverUrlLen = serverUrl.length();
903 int moServerUrlLen = moServerUrl.length();
904
905 if (!ContextBase::mGps_conf.AGPS_CONFIG_INJECT) {
906 LOC_LOGd("AGPS_CONFIG_INJECT is 0. Not setting flags for AGPS configurations");
907 gnssConfigRequested.flags &= ~(GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT |
908 GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT |
909 GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT |
910 GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT);
911 }
912
913 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
914 if (gnssConfigNeedEngineUpdate.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
915 err = mLocApi->setGpsLockSync(gnssConfigRequested.gpsLock);
916 if (index < count) {
917 errsList[index] = err;
918 }
919 }
920 index++;
921 }
922
923 if (gnssConfigRequested.flags &
924 GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
925 if (gnssConfigNeedEngineUpdate.flags &
926 GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
927 if (gnssConfigNeedEngineUpdate.assistanceServer.type ==
928 GNSS_ASSISTANCE_TYPE_SUPL) {
929 err = mLocApi->setServerSync(
930 serverUrl.c_str(), serverUrlLen, LOC_AGPS_SUPL_SERVER);
931 if (index < count) {
932 errsList[index] = err;
933 }
934 if (0 != oldMoServerUrl.compare(moServerUrl)) {
935 LocationError locErr =
936 mLocApi->setServerSync(moServerUrl.c_str(),
937 moServerUrlLen,
938 LOC_AGPS_MO_SUPL_SERVER);
939 if (locErr != LOCATION_ERROR_SUCCESS) {
940 LOC_LOGe("Error while setting MO SUPL_HOST server:%s",
941 moServerUrl.c_str());
942 }
943 }
944 } else if (gnssConfigNeedEngineUpdate.assistanceServer.type ==
945 GNSS_ASSISTANCE_TYPE_C2K) {
946 struct in_addr addr;
947 struct hostent* hp;
948 bool resolveAddrSuccess = true;
949
950 hp = gethostbyname(
951 gnssConfigNeedEngineUpdate.assistanceServer.hostName);
952 if (hp != NULL) { /* DNS OK */
953 memcpy(&addr, hp->h_addr_list[0], hp->h_length);
954 } else {
955 /* Try IP representation */
956 if (inet_aton(
957 gnssConfigNeedEngineUpdate.assistanceServer.hostName,
958 &addr) == 0) {
959 /* IP not valid */
960 LOC_LOGE("%s]: hostname '%s' cannot be resolved ",
961 __func__,
962 gnssConfigNeedEngineUpdate.assistanceServer.hostName);
963 if (index < count) {
964 errsList[index] = LOCATION_ERROR_INVALID_PARAMETER;
965 }
966 } else {
967 resolveAddrSuccess = false;
968 }
969 }
970
971 if (resolveAddrSuccess) {
972 unsigned int ip = htonl(addr.s_addr);
973 err = mLocApi->setServerSync(ip,
974 gnssConfigNeedEngineUpdate.assistanceServer.port,
975 LOC_AGPS_CDMA_PDE_SERVER);
976 if (index < count) {
977 errsList[index] = err;
978 }
979 }
980 }
981 }
982 index++;
983 }
984
985 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
986 if (gnssConfigNeedEngineUpdate.flags &
987 GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
988 err = mLocApi->setSUPLVersionSync(gnssConfigRequested.suplVersion);
989 if (index < count) {
990 errsList[index] = err;
991 }
992 }
993 index++;
994 }
995
996 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
997 /* Let HAL do nothing here, just set it by MBN
998 if (gnssConfigNeedEngineUpdate.flags &
999 GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
1000 err = mLocApi->setLPPConfigSync(gnssConfigRequested.lppProfile);
1001 if (index < count) {
1002 errsList[index] = err;
1003 }
1004 }
1005 */
1006 index++;
1007 }
1008
1009 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1010 /* Let HAL do nothing here, just set it by MBN
1011 if (gnssConfigNeedEngineUpdate.flags &
1012 GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1013 err = mLocApi->setLPPeProtocolCpSync(
1014 gnssConfigRequested.lppeControlPlaneMask);
1015 if (index < count) {
1016 errsList[index] = err;
1017 }
1018 }
1019 */
1020 index++;
1021 }
1022
1023 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1024 /* Let HAL do nothing here, just set it by MBN
1025 if (gnssConfigNeedEngineUpdate.flags &
1026 GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1027 err = mLocApi->setLPPeProtocolUpSync(
1028 gnssConfigRequested.lppeUserPlaneMask);
1029 if (index < count) {
1030 errsList[index] = err;
1031 }
1032 }
1033 */
1034 index++;
1035 }
1036
1037 if (gnssConfigRequested.flags &
1038 GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1039 if (gnssConfigNeedEngineUpdate.flags &
1040 GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1041 err = mLocApi->setAGLONASSProtocolSync(
1042 gnssConfigRequested.aGlonassPositionProtocolMask);
1043 if (index < count) {
1044 errsList[index] = err;
1045 }
1046 }
1047 index++;
1048 }
1049 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
1050 // Check if feature is supported
1051 if (!ContextBase::isFeatureSupported(
1052 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1053 LOC_LOGe("Feature constellation enablement not supported.");
1054 err = LOCATION_ERROR_NOT_SUPPORTED;
1055 } else {
1056 // Send the SV ID Config to Modem
1057 mBlacklistedSvIds.assign(gnssConfigRequested.blacklistedSvIds.begin(),
1058 gnssConfigRequested.blacklistedSvIds.end());
1059 err = gnssSvIdConfigUpdateSync(gnssConfigRequested.blacklistedSvIds);
1060 if (LOCATION_ERROR_SUCCESS != err) {
1061 LOC_LOGe("Failed to send config to modem, err %d", err);
1062 }
1063 }
1064 if (index < count) {
1065 errsList[index] = err;
1066 }
1067 index++;
1068 }
1069 if (gnssConfigRequested.flags &
1070 GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
1071 if (gnssConfigNeedEngineUpdate.flags &
1072 GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
1073 err = mLocApi->setEmergencyExtensionWindowSync(
1074 gnssConfigRequested.emergencyExtensionSeconds);
1075 if (index < count) {
1076 errsList[index] = err;
1077 }
1078 }
1079 index++;
1080 }
1081 return errsList;
1082 }
1083
1084 uint32_t*
gnssUpdateConfigCommand(GnssConfig config)1085 GnssAdapter::gnssUpdateConfigCommand(GnssConfig config)
1086 {
1087 // count the number of bits set
1088 GnssConfigFlagsMask flagsCopy = config.flags;
1089 size_t count = 0;
1090 while (flagsCopy > 0) {
1091 if (flagsCopy & 1) {
1092 count++;
1093 }
1094 flagsCopy >>= 1;
1095 }
1096 std::string idsString = "[";
1097 uint32_t* ids = NULL;
1098 if (count > 0) {
1099 ids = new uint32_t[count];
1100 if (ids == nullptr) {
1101 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
1102 return nullptr;
1103 }
1104 for (size_t i=0; i < count; ++i) {
1105 ids[i] = generateSessionId();
1106 IF_LOC_LOGD {
1107 idsString += std::to_string(ids[i]) + " ";
1108 }
1109 }
1110 }
1111 idsString += "]";
1112
1113 LOC_LOGD("%s]: ids %s flags 0x%X", __func__, idsString.c_str(), config.flags);
1114
1115 struct MsgGnssUpdateConfig : public LocMsg {
1116 GnssAdapter& mAdapter;
1117 LocApiBase& mApi;
1118 GnssConfig mConfig;
1119 size_t mCount;
1120 uint32_t* mIds;
1121 inline MsgGnssUpdateConfig(GnssAdapter& adapter,
1122 LocApiBase& api,
1123 GnssConfig config,
1124 uint32_t* ids,
1125 size_t count) :
1126 LocMsg(),
1127 mAdapter(adapter),
1128 mApi(api),
1129 mConfig(config),
1130 mCount(count),
1131 mIds(ids) {}
1132 inline MsgGnssUpdateConfig(const MsgGnssUpdateConfig& obj) :
1133 MsgGnssUpdateConfig(obj.mAdapter, obj.mApi, obj.mConfig,
1134 new uint32_t[obj.mCount], obj.mCount) {
1135 if (mIds != nullptr) {
1136 for (int i = 0; i < mCount; ++i) {
1137 mIds[i] = obj.mIds[i];
1138 }
1139 }
1140 }
1141 inline virtual ~MsgGnssUpdateConfig()
1142 {
1143 delete[] mIds;
1144 }
1145
1146 inline virtual void proc() const {
1147 if (!mAdapter.isEngineCapabilitiesKnown()) {
1148 mAdapter.mPendingMsgs.push_back(new MsgGnssUpdateConfig(*this));
1149 return;
1150 }
1151 GnssAdapter& adapter = mAdapter;
1152 size_t countOfConfigs = mCount;
1153 GnssConfig gnssConfigRequested = mConfig;
1154 GnssConfig gnssConfigNeedEngineUpdate = mConfig;
1155
1156 std::vector<uint32_t> sessionIds;
1157 sessionIds.assign(mIds, mIds + mCount);
1158 std::vector<LocationError> errs(mCount, LOCATION_ERROR_SUCCESS);
1159 int index = 0;
1160
1161 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
1162 GnssConfigGpsLock newGpsLock = gnssConfigRequested.gpsLock;
1163
1164 newGpsLock |= GNSS_CONFIG_GPS_LOCK_MO;
1165 ContextBase::mGps_conf.GPS_LOCK = newGpsLock;
1166 /* If we get here it means that the changes in the framework to request for
1167 'P' behavior were made, and therefore we need to "behave" as in 'P'
1168 However, we need to determine if enableCommand function has already been
1169 called, since it could get called before this function.*/
1170 if (0 != mAdapter.getAfwControlId()) {
1171 /* enableCommand function has already been called since getAfwControlId
1172 returns non zero. Now there are two possible cases:
1173 1. This is the first time this function is called
1174 (mSupportNfwControl is true). We need to behave as in 'P', but
1175 for the first time, meaning MO was enabled, but NI was not, so
1176 we need to unlock NI
1177 2. This is not the first time this function is called, meaning we
1178 are already behaving as in 'P'. No need to update the configuration
1179 in this case (return to 'P' code) */
1180 if (mAdapter.mSupportNfwControl) {
1181 // case 1 above
1182 newGpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
1183 } else {
1184 // case 2 above
1185 gnssConfigNeedEngineUpdate.flags &= ~(GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT);
1186 }
1187 }
1188 gnssConfigRequested.gpsLock = newGpsLock;
1189 mAdapter.mSupportNfwControl = false;
1190 index++;
1191 }
1192 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
1193 uint32_t newSuplVersion =
1194 mAdapter.convertSuplVersion(gnssConfigRequested.suplVersion);
1195 ContextBase::mGps_conf.SUPL_VER = newSuplVersion;
1196 index++;
1197 }
1198 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
1199 if (GNSS_ASSISTANCE_TYPE_SUPL == mConfig.assistanceServer.type) {
1200 mAdapter.setSuplHostServer(mConfig.assistanceServer.hostName,
1201 mConfig.assistanceServer.port,
1202 LOC_AGPS_SUPL_SERVER);
1203 } else {
1204 LOC_LOGE("%s]: Not a valid gnss assistance type %u",
1205 __func__, mConfig.assistanceServer.type);
1206 errs.at(index) = LOCATION_ERROR_INVALID_PARAMETER;
1207 gnssConfigNeedEngineUpdate.flags &=
1208 ~(GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT);
1209 }
1210 index++;
1211 }
1212 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
1213 uint32_t newLppProfile = mAdapter.convertLppProfile(gnssConfigRequested.lppProfile);
1214 ContextBase::mGps_conf.LPP_PROFILE = newLppProfile;
1215 index++;
1216 }
1217 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1218 uint32_t newLppeControlPlaneMask =
1219 mAdapter.convertLppeCp(gnssConfigRequested.lppeControlPlaneMask);
1220 ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY = newLppeControlPlaneMask;
1221 index++;
1222 }
1223 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1224 uint32_t newLppeUserPlaneMask =
1225 mAdapter.convertLppeUp(gnssConfigRequested.lppeUserPlaneMask);
1226 ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY = newLppeUserPlaneMask;
1227 index++;
1228 }
1229 if (gnssConfigRequested.flags &
1230 GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1231 uint32_t newAGloProtMask =
1232 mAdapter.convertAGloProt(gnssConfigRequested.aGlonassPositionProtocolMask);
1233 ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT = newAGloProtMask;
1234 index++;
1235 }
1236 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
1237 uint32_t newEP4ES = mAdapter.convertEP4ES(
1238 gnssConfigRequested.emergencyPdnForEmergencySupl);
1239 if (newEP4ES != ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
1240 ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = newEP4ES;
1241 }
1242 index++;
1243 }
1244 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
1245 uint32_t newSuplEs = mAdapter.convertSuplEs(
1246 gnssConfigRequested.suplEmergencyServices);
1247 if (newSuplEs != ContextBase::mGps_conf.SUPL_ES) {
1248 ContextBase::mGps_conf.SUPL_ES = newSuplEs;
1249 }
1250 index++;
1251 }
1252 if (gnssConfigRequested.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
1253 uint32_t newSuplMode = mAdapter.convertSuplMode(gnssConfigRequested.suplModeMask);
1254 ContextBase::mGps_conf.SUPL_MODE = newSuplMode;
1255 mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
1256 index++;
1257 }
1258
1259 LocApiCollectiveResponse *configCollectiveResponse = new LocApiCollectiveResponse(
1260 *adapter.getContext(),
1261 [&adapter, sessionIds, countOfConfigs] (std::vector<LocationError> errs) {
1262
1263 std::vector<uint32_t> ids(sessionIds);
1264 adapter.reportResponse(countOfConfigs, errs.data(), ids.data());
1265 });
1266
1267 mApi.sendMsg(new LocApiMsg(
1268 [&adapter, gnssConfigRequested, gnssConfigNeedEngineUpdate,
1269 countOfConfigs, configCollectiveResponse, errs] () mutable {
1270 std::vector<LocationError> errsList = adapter.gnssUpdateConfig("",
1271 gnssConfigRequested, gnssConfigNeedEngineUpdate, countOfConfigs);
1272
1273 configCollectiveResponse->returnToSender(errsList);
1274 }));
1275 }
1276 };
1277
1278 if (NULL != ids) {
1279 sendMsg(new MsgGnssUpdateConfig(*this, *mLocApi, config, ids, count));
1280 } else {
1281 LOC_LOGE("%s]: No GNSS config items to update", __func__);
1282 }
1283
1284 return ids;
1285 }
1286
1287 void
gnssSvIdConfigUpdate(const std::vector<GnssSvIdSource> & blacklistedSvIds)1288 GnssAdapter::gnssSvIdConfigUpdate(const std::vector<GnssSvIdSource>& blacklistedSvIds)
1289 {
1290 // Clear the existing config
1291 memset(&mGnssSvIdConfig, 0, sizeof(GnssSvIdConfig));
1292
1293 // Convert the sv id lists to masks
1294 bool convertSuccess = convertToGnssSvIdConfig(blacklistedSvIds, mGnssSvIdConfig);
1295
1296 // Now send to Modem if conversion successful
1297 if (convertSuccess) {
1298 gnssSvIdConfigUpdate();
1299 } else {
1300 LOC_LOGe("convertToGnssSvIdConfig failed");
1301 }
1302 }
1303
1304 void
gnssSvIdConfigUpdate()1305 GnssAdapter::gnssSvIdConfigUpdate()
1306 {
1307 LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1308 ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64,
1309 mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
1310 mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask);
1311
1312 // Now set required blacklisted SVs
1313 mLocApi->setBlacklistSv(mGnssSvIdConfig);
1314 }
1315
1316 LocationError
gnssSvIdConfigUpdateSync(const std::vector<GnssSvIdSource> & blacklistedSvIds)1317 GnssAdapter::gnssSvIdConfigUpdateSync(const std::vector<GnssSvIdSource>& blacklistedSvIds)
1318 {
1319 // Clear the existing config
1320 memset(&mGnssSvIdConfig, 0, sizeof(GnssSvIdConfig));
1321
1322 // Convert the sv id lists to masks
1323 convertToGnssSvIdConfig(blacklistedSvIds, mGnssSvIdConfig);
1324
1325 // Now send to Modem
1326 return gnssSvIdConfigUpdateSync();
1327 }
1328
1329 LocationError
gnssSvIdConfigUpdateSync()1330 GnssAdapter::gnssSvIdConfigUpdateSync()
1331 {
1332 LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1333 ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64,
1334 mGnssSvIdConfig.bdsBlacklistSvMask, mGnssSvIdConfig.gloBlacklistSvMask,
1335 mGnssSvIdConfig.qzssBlacklistSvMask, mGnssSvIdConfig.galBlacklistSvMask);
1336
1337 // Now set required blacklisted SVs
1338 return mLocApi->setBlacklistSvSync(mGnssSvIdConfig);
1339 }
1340
1341 uint32_t*
gnssGetConfigCommand(GnssConfigFlagsMask configMask)1342 GnssAdapter::gnssGetConfigCommand(GnssConfigFlagsMask configMask) {
1343
1344 // count the number of bits set
1345 GnssConfigFlagsMask flagsCopy = configMask;
1346 size_t count = 0;
1347 while (flagsCopy > 0) {
1348 if (flagsCopy & 1) {
1349 count++;
1350 }
1351 flagsCopy >>= 1;
1352 }
1353 std::string idsString = "[";
1354 uint32_t* ids = NULL;
1355 if (count > 0) {
1356 ids = new uint32_t[count];
1357 if (nullptr == ids) {
1358 LOC_LOGe("new allocation failed, fatal error.");
1359 return nullptr;
1360 }
1361 for (size_t i=0; i < count; ++i) {
1362 ids[i] = generateSessionId();
1363 IF_LOC_LOGD {
1364 idsString += std::to_string(ids[i]) + " ";
1365 }
1366 }
1367 }
1368 idsString += "]";
1369
1370 LOC_LOGd("ids %s flags 0x%X", idsString.c_str(), configMask);
1371
1372 struct MsgGnssGetConfig : public LocMsg {
1373 GnssAdapter& mAdapter;
1374 LocApiBase& mApi;
1375 GnssConfigFlagsMask mConfigMask;
1376 uint32_t* mIds;
1377 size_t mCount;
1378 inline MsgGnssGetConfig(GnssAdapter& adapter,
1379 LocApiBase& api,
1380 GnssConfigFlagsMask configMask,
1381 uint32_t* ids,
1382 size_t count) :
1383 LocMsg(),
1384 mAdapter(adapter),
1385 mApi(api),
1386 mConfigMask(configMask),
1387 mIds(ids),
1388 mCount(count) {}
1389
1390 inline MsgGnssGetConfig(const MsgGnssGetConfig& obj) :
1391 MsgGnssGetConfig(obj.mAdapter, obj.mApi, obj.mConfigMask,
1392 new uint32_t[obj.mCount], obj.mCount) {
1393 if (mIds != nullptr) {
1394 for (int i = 0; i < mCount; ++i) {
1395 mIds[i] = obj.mIds[i];
1396 }
1397 }
1398 }
1399 inline virtual ~MsgGnssGetConfig()
1400 {
1401 delete[] mIds;
1402 }
1403 inline virtual void proc() const {
1404 if (!mAdapter.isEngineCapabilitiesKnown()) {
1405 mAdapter.mPendingMsgs.push_back(new MsgGnssGetConfig(*this));
1406 return;
1407 }
1408 LocationError* errs = new LocationError[mCount];
1409 LocationError err = LOCATION_ERROR_SUCCESS;
1410 uint32_t index = 0;
1411
1412 if (nullptr == errs) {
1413 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
1414 return;
1415 }
1416
1417 if (mConfigMask & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
1418 if (index < mCount) {
1419 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1420 }
1421 }
1422 if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
1423 if (index < mCount) {
1424 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1425 }
1426 }
1427 if (mConfigMask & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
1428 if (index < mCount) {
1429 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1430 }
1431 }
1432 if (mConfigMask & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
1433 if (index < mCount) {
1434 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1435 }
1436 }
1437 if (mConfigMask & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
1438 if (index < mCount) {
1439 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1440 }
1441 }
1442 if (mConfigMask & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
1443 if (index < mCount) {
1444 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1445 }
1446 }
1447 if (mConfigMask & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
1448 if (index < mCount) {
1449 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1450 }
1451 }
1452 if (mConfigMask & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
1453 if (index < mCount) {
1454 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1455 }
1456 }
1457 if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
1458 if (index < mCount) {
1459 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1460 }
1461 }
1462 if (mConfigMask & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
1463 err = LOCATION_ERROR_NOT_SUPPORTED;
1464 if (index < mCount) {
1465 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1466 }
1467 }
1468 if (mConfigMask & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
1469 // Check if feature is supported
1470 if (!ContextBase::isFeatureSupported(
1471 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1472 LOC_LOGe("Feature not supported.");
1473 err = LOCATION_ERROR_NOT_SUPPORTED;
1474 } else {
1475 // Send request to Modem to fetch the config
1476 mApi.getBlacklistSv();
1477 err = LOCATION_ERROR_SUCCESS;
1478 }
1479 if (index < mCount) {
1480 errs[index++] = err;
1481 }
1482 }
1483 if (mConfigMask & GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
1484 err = LOCATION_ERROR_NOT_SUPPORTED;
1485 if (index < mCount) {
1486 errs[index++] = LOCATION_ERROR_NOT_SUPPORTED;
1487 }
1488 }
1489
1490 mAdapter.reportResponse(index, errs, mIds);
1491 delete[] errs;
1492
1493 }
1494 };
1495
1496 if (NULL != ids) {
1497 sendMsg(new MsgGnssGetConfig(*this, *mLocApi, configMask, ids, count));
1498 } else {
1499 LOC_LOGe("No GNSS config items to Get");
1500 }
1501
1502 return ids;
1503 }
1504
1505 bool
convertToGnssSvIdConfig(const std::vector<GnssSvIdSource> & blacklistedSvIds,GnssSvIdConfig & config)1506 GnssAdapter::convertToGnssSvIdConfig(
1507 const std::vector<GnssSvIdSource>& blacklistedSvIds, GnssSvIdConfig& config)
1508 {
1509 bool retVal = false;
1510 config.size = sizeof(GnssSvIdConfig);
1511
1512 // Empty vector => Clear any previous blacklisted SVs
1513 if (0 == blacklistedSvIds.size()) {
1514 config.gloBlacklistSvMask = 0;
1515 config.bdsBlacklistSvMask = 0;
1516 config.qzssBlacklistSvMask = 0;
1517 config.galBlacklistSvMask = 0;
1518 retVal = true;
1519 } else {
1520 // Parse the vector and convert SV IDs to mask values
1521 for (GnssSvIdSource source : blacklistedSvIds) {
1522 uint64_t* svMaskPtr = NULL;
1523 GnssSvId initialSvId = 0;
1524 switch(source.constellation) {
1525 case GNSS_SV_TYPE_GLONASS:
1526 svMaskPtr = &config.gloBlacklistSvMask;
1527 initialSvId = GNSS_SV_CONFIG_GLO_INITIAL_SV_ID;
1528 break;
1529 case GNSS_SV_TYPE_BEIDOU:
1530 svMaskPtr = &config.bdsBlacklistSvMask;
1531 initialSvId = GNSS_SV_CONFIG_BDS_INITIAL_SV_ID;
1532 break;
1533 case GNSS_SV_TYPE_QZSS:
1534 svMaskPtr = &config.qzssBlacklistSvMask;
1535 initialSvId = GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID;
1536 break;
1537 case GNSS_SV_TYPE_GALILEO:
1538 svMaskPtr = &config.galBlacklistSvMask;
1539 initialSvId = GNSS_SV_CONFIG_GAL_INITIAL_SV_ID;
1540 break;
1541 default:
1542 break;
1543 }
1544
1545 if (NULL == svMaskPtr) {
1546 LOC_LOGe("Invalid constellation %d", source.constellation);
1547 } else {
1548 // SV ID 0 = All SV IDs
1549 if (0 == source.svId) {
1550 *svMaskPtr = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1551 } else if (source.svId < initialSvId || source.svId >= initialSvId + 64) {
1552 LOC_LOGe("Invalid sv id %d for sv type %d",
1553 source.svId, source.constellation);
1554 } else {
1555 *svMaskPtr |= (1ULL << (source.svId - initialSvId));
1556 }
1557 }
1558 }
1559
1560 // Return true if any one source is valid
1561 if (0 != config.gloBlacklistSvMask ||
1562 0 != config.bdsBlacklistSvMask ||
1563 0 != config.galBlacklistSvMask ||
1564 0 != config.qzssBlacklistSvMask) {
1565 retVal = true;
1566 }
1567 }
1568
1569 return retVal;
1570 }
1571
convertFromGnssSvIdConfig(const GnssSvIdConfig & svConfig,GnssConfig & config)1572 void GnssAdapter::convertFromGnssSvIdConfig(
1573 const GnssSvIdConfig& svConfig, GnssConfig& config)
1574 {
1575 // Convert blacklisted SV mask values to vectors
1576 if (svConfig.bdsBlacklistSvMask) {
1577 convertGnssSvIdMaskToList(
1578 svConfig.bdsBlacklistSvMask, config.blacklistedSvIds,
1579 GNSS_SV_CONFIG_BDS_INITIAL_SV_ID, GNSS_SV_TYPE_BEIDOU);
1580 config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
1581 }
1582 if (svConfig.galBlacklistSvMask) {
1583 convertGnssSvIdMaskToList(
1584 svConfig.galBlacklistSvMask, config.blacklistedSvIds,
1585 GNSS_SV_CONFIG_GAL_INITIAL_SV_ID, GNSS_SV_TYPE_GALILEO);
1586 config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
1587 }
1588 if (svConfig.gloBlacklistSvMask) {
1589 convertGnssSvIdMaskToList(
1590 svConfig.gloBlacklistSvMask, config.blacklistedSvIds,
1591 GNSS_SV_CONFIG_GLO_INITIAL_SV_ID, GNSS_SV_TYPE_GLONASS);
1592 config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
1593 }
1594 if (svConfig.qzssBlacklistSvMask) {
1595 convertGnssSvIdMaskToList(
1596 svConfig.qzssBlacklistSvMask, config.blacklistedSvIds,
1597 GNSS_SV_CONFIG_QZSS_INITIAL_SV_ID, GNSS_SV_TYPE_QZSS);
1598 config.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
1599 }
1600 }
1601
convertGnssSvIdMaskToList(uint64_t svIdMask,std::vector<GnssSvIdSource> & svIds,GnssSvId initialSvId,GnssSvType svType)1602 void GnssAdapter::convertGnssSvIdMaskToList(
1603 uint64_t svIdMask, std::vector<GnssSvIdSource>& svIds,
1604 GnssSvId initialSvId, GnssSvType svType)
1605 {
1606 GnssSvIdSource source = {};
1607 source.size = sizeof(GnssSvIdSource);
1608 source.constellation = svType;
1609
1610 // SV ID 0 => All SV IDs in mask
1611 if (GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK == svIdMask) {
1612 source.svId = 0;
1613 svIds.push_back(source);
1614 return;
1615 }
1616
1617 // Convert each bit in svIdMask to vector entry
1618 uint32_t bitNumber = 0;
1619 while (svIdMask > 0) {
1620 if (svIdMask & 0x1) {
1621 source.svId = bitNumber + initialSvId;
1622 svIds.push_back(source);
1623 }
1624 bitNumber++;
1625 svIdMask >>= 1;
1626 }
1627 }
1628
reportGnssSvIdConfigEvent(const GnssSvIdConfig & config)1629 void GnssAdapter::reportGnssSvIdConfigEvent(const GnssSvIdConfig& config)
1630 {
1631 struct MsgReportGnssSvIdConfig : public LocMsg {
1632 GnssAdapter& mAdapter;
1633 const GnssSvIdConfig mConfig;
1634 inline MsgReportGnssSvIdConfig(GnssAdapter& adapter,
1635 const GnssSvIdConfig& config) :
1636 LocMsg(),
1637 mAdapter(adapter),
1638 mConfig(config) {}
1639 inline virtual void proc() const {
1640 mAdapter.reportGnssSvIdConfig(mConfig);
1641 }
1642 };
1643
1644 sendMsg(new MsgReportGnssSvIdConfig(*this, config));
1645 }
1646
reportGnssSvIdConfig(const GnssSvIdConfig & svIdConfig)1647 void GnssAdapter::reportGnssSvIdConfig(const GnssSvIdConfig& svIdConfig)
1648 {
1649 GnssConfig config = {};
1650 config.size = sizeof(GnssConfig);
1651
1652 // Invoke control clients config callback
1653 if (nullptr != mControlCallbacks.gnssConfigCb &&
1654 svIdConfig.size == sizeof(GnssSvIdConfig)) {
1655 convertFromGnssSvIdConfig(svIdConfig, config);
1656 LOC_LOGd("blacklist bds 0x%" PRIx64 ", glo 0x%" PRIx64
1657 ", qzss 0x%" PRIx64 ", gal 0x%" PRIx64,
1658 svIdConfig.bdsBlacklistSvMask, svIdConfig.gloBlacklistSvMask,
1659 svIdConfig.qzssBlacklistSvMask, svIdConfig.galBlacklistSvMask);
1660 mControlCallbacks.gnssConfigCb(config);
1661 } else {
1662 LOC_LOGe("Failed to report, size %d", (uint32_t)config.size);
1663 }
1664 }
1665
1666 void
gnssUpdateSvTypeConfigCommand(GnssSvTypeConfig config)1667 GnssAdapter::gnssUpdateSvTypeConfigCommand(GnssSvTypeConfig config)
1668 {
1669 struct MsgGnssUpdateSvTypeConfig : public LocMsg {
1670 GnssAdapter* mAdapter;
1671 LocApiBase* mApi;
1672 GnssSvTypeConfig mConfig;
1673 inline MsgGnssUpdateSvTypeConfig(
1674 GnssAdapter* adapter,
1675 LocApiBase* api,
1676 GnssSvTypeConfig& config) :
1677 LocMsg(),
1678 mAdapter(adapter),
1679 mApi(api),
1680 mConfig(config) {}
1681 inline virtual void proc() const {
1682 if (!mAdapter->isEngineCapabilitiesKnown()) {
1683 mAdapter->mPendingMsgs.push_back(new MsgGnssUpdateSvTypeConfig(*this));
1684 return;
1685 }
1686 // Check if feature is supported
1687 if (!ContextBase::isFeatureSupported(
1688 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1689 LOC_LOGe("Feature not supported.");
1690 } else {
1691 // Send update request to modem
1692 mAdapter->gnssSvTypeConfigUpdate(mConfig);
1693 }
1694 }
1695 };
1696
1697 sendMsg(new MsgGnssUpdateSvTypeConfig(this, mLocApi, config));
1698 }
1699
1700 void
gnssSvTypeConfigUpdate(const GnssSvTypeConfig & config)1701 GnssAdapter::gnssSvTypeConfigUpdate(const GnssSvTypeConfig& config)
1702 {
1703 // Gather bits removed from enabled mask
1704 GnssSvTypesMask enabledRemoved = mGnssSvTypeConfig.enabledSvTypesMask &
1705 (mGnssSvTypeConfig.enabledSvTypesMask ^ config.enabledSvTypesMask);
1706 // Send reset if any constellation is removed from the enabled list
1707 bool sendReset = (enabledRemoved != 0);
1708 // Save new config and update
1709 gnssSetSvTypeConfig(config);
1710 gnssSvTypeConfigUpdate(sendReset);
1711 }
1712
1713 void
gnssSvTypeConfigUpdate(bool sendReset)1714 GnssAdapter::gnssSvTypeConfigUpdate(bool sendReset)
1715 {
1716 LOC_LOGd("size %" PRIu32" constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64
1717 ", sendReset %d",
1718 mGnssSvTypeConfig.size, mGnssSvTypeConfig.blacklistedSvTypesMask,
1719 mGnssSvTypeConfig.enabledSvTypesMask, sendReset);
1720
1721 if (mGnssSvTypeConfig.size == sizeof(mGnssSvTypeConfig)) {
1722
1723 if (sendReset) {
1724 mLocApi->resetConstellationControl();
1725 }
1726
1727 GnssSvIdConfig blacklistConfig = {};
1728 // Revert to previously blacklisted SVs for each enabled constellation
1729 blacklistConfig = mGnssSvIdConfig;
1730 // Blacklist all SVs for each disabled constellation
1731 if (mGnssSvTypeConfig.blacklistedSvTypesMask) {
1732 if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_GLO_BIT) {
1733 blacklistConfig.gloBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1734 }
1735 if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_BDS_BIT) {
1736 blacklistConfig.bdsBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1737 }
1738 if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_QZSS_BIT) {
1739 blacklistConfig.qzssBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1740 }
1741 if (mGnssSvTypeConfig.blacklistedSvTypesMask & GNSS_SV_TYPES_MASK_GAL_BIT) {
1742 blacklistConfig.galBlacklistSvMask = GNSS_SV_CONFIG_ALL_BITS_ENABLED_MASK;
1743 }
1744 }
1745
1746 // Send blacklist info
1747 mLocApi->setBlacklistSv(blacklistConfig);
1748
1749 // Send only enabled constellation config
1750 if (mGnssSvTypeConfig.enabledSvTypesMask) {
1751 GnssSvTypeConfig svTypeConfig = {sizeof(GnssSvTypeConfig), 0, 0};
1752 svTypeConfig.enabledSvTypesMask = mGnssSvTypeConfig.enabledSvTypesMask;
1753 mLocApi->setConstellationControl(svTypeConfig);
1754 }
1755 }
1756 }
1757
1758 void
gnssGetSvTypeConfigCommand(GnssSvTypeConfigCallback callback)1759 GnssAdapter::gnssGetSvTypeConfigCommand(GnssSvTypeConfigCallback callback)
1760 {
1761 struct MsgGnssGetSvTypeConfig : public LocMsg {
1762 GnssAdapter* mAdapter;
1763 LocApiBase* mApi;
1764 GnssSvTypeConfigCallback mCallback;
1765 inline MsgGnssGetSvTypeConfig(
1766 GnssAdapter* adapter,
1767 LocApiBase* api,
1768 GnssSvTypeConfigCallback callback) :
1769 LocMsg(),
1770 mAdapter(adapter),
1771 mApi(api),
1772 mCallback(callback) {}
1773 inline virtual void proc() const {
1774 if (!mAdapter->isEngineCapabilitiesKnown()) {
1775 mAdapter->mPendingMsgs.push_back(new MsgGnssGetSvTypeConfig(*this));
1776 return;
1777 }
1778 if (!ContextBase::isFeatureSupported(
1779 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1780 LOC_LOGe("Feature not supported.");
1781 } else {
1782 // Save the callback
1783 mAdapter->gnssSetSvTypeConfigCallback(mCallback);
1784 // Send GET request to modem
1785 mApi->getConstellationControl();
1786 }
1787 }
1788 };
1789
1790 sendMsg(new MsgGnssGetSvTypeConfig(this, mLocApi, callback));
1791 }
1792
1793 void
gnssResetSvTypeConfigCommand()1794 GnssAdapter::gnssResetSvTypeConfigCommand()
1795 {
1796 struct MsgGnssResetSvTypeConfig : public LocMsg {
1797 GnssAdapter* mAdapter;
1798 LocApiBase* mApi;
1799 inline MsgGnssResetSvTypeConfig(
1800 GnssAdapter* adapter,
1801 LocApiBase* api) :
1802 LocMsg(),
1803 mAdapter(adapter),
1804 mApi(api) {}
1805 inline virtual void proc() const {
1806 if (!mAdapter->isEngineCapabilitiesKnown()) {
1807 mAdapter->mPendingMsgs.push_back(new MsgGnssResetSvTypeConfig(*this));
1808 return;
1809 }
1810 if (!ContextBase::isFeatureSupported(
1811 LOC_SUPPORTED_FEATURE_CONSTELLATION_ENABLEMENT_V02)) {
1812 LOC_LOGe("Feature not supported.");
1813 } else {
1814 // Reset constellation config
1815 mAdapter->gnssSetSvTypeConfig({sizeof(GnssSvTypeConfig), 0, 0});
1816 // Re-enforce SV blacklist config
1817 mAdapter->gnssSvIdConfigUpdate();
1818 // Send reset request to modem
1819 mApi->resetConstellationControl();
1820 }
1821 }
1822 };
1823
1824 sendMsg(new MsgGnssResetSvTypeConfig(this, mLocApi));
1825 }
1826
reportGnssSvTypeConfigEvent(const GnssSvTypeConfig & config)1827 void GnssAdapter::reportGnssSvTypeConfigEvent(const GnssSvTypeConfig& config)
1828 {
1829 struct MsgReportGnssSvTypeConfig : public LocMsg {
1830 GnssAdapter& mAdapter;
1831 const GnssSvTypeConfig mConfig;
1832 inline MsgReportGnssSvTypeConfig(GnssAdapter& adapter,
1833 const GnssSvTypeConfig& config) :
1834 LocMsg(),
1835 mAdapter(adapter),
1836 mConfig(config) {}
1837 inline virtual void proc() const {
1838 mAdapter.reportGnssSvTypeConfig(mConfig);
1839 }
1840 };
1841
1842 sendMsg(new MsgReportGnssSvTypeConfig(*this, config));
1843 }
1844
reportGnssSvTypeConfig(const GnssSvTypeConfig & config)1845 void GnssAdapter::reportGnssSvTypeConfig(const GnssSvTypeConfig& config)
1846 {
1847 // Invoke Get SV Type Callback
1848 if (NULL != mGnssSvTypeConfigCb &&
1849 config.size == sizeof(GnssSvTypeConfig)) {
1850 LOC_LOGd("constellations blacklisted 0x%" PRIx64 ", enabled 0x%" PRIx64,
1851 config.blacklistedSvTypesMask, config.enabledSvTypesMask);
1852 mGnssSvTypeConfigCb(config);
1853 } else {
1854 LOC_LOGe("Failed to report, size %d", (uint32_t)config.size);
1855 }
1856 }
1857
deleteAidingData(const GnssAidingData & data,uint32_t sessionId)1858 void GnssAdapter::deleteAidingData(const GnssAidingData &data, uint32_t sessionId) {
1859 mLocApi->deleteAidingData(data, new LocApiResponse(*getContext(),
1860 [this, sessionId] (LocationError err) {
1861 reportResponse(err, sessionId);
1862 }));
1863 }
1864
1865 uint32_t
gnssDeleteAidingDataCommand(GnssAidingData & data)1866 GnssAdapter::gnssDeleteAidingDataCommand(GnssAidingData& data)
1867 {
1868 uint32_t sessionId = generateSessionId();
1869 LOC_LOGD("%s]: id %u", __func__, sessionId);
1870
1871 struct MsgDeleteAidingData : public LocMsg {
1872 GnssAdapter& mAdapter;
1873 uint32_t mSessionId;
1874 GnssAidingData mData;
1875 inline MsgDeleteAidingData(GnssAdapter& adapter,
1876 uint32_t sessionId,
1877 GnssAidingData& data) :
1878 LocMsg(),
1879 mAdapter(adapter),
1880 mSessionId(sessionId),
1881 mData(data) {}
1882 inline virtual void proc() const {
1883 if ((mData.posEngineMask & STANDARD_POSITIONING_ENGINE) != 0) {
1884 mAdapter.deleteAidingData(mData, mSessionId);
1885
1886 SystemStatus* s = mAdapter.getSystemStatus();
1887 if ((nullptr != s) && (mData.deleteAll)) {
1888 s->setDefaultGnssEngineStates();
1889 }
1890 }
1891
1892 mAdapter.mEngHubProxy->gnssDeleteAidingData(mData);
1893 }
1894 };
1895
1896 sendMsg(new MsgDeleteAidingData(*this, sessionId, data));
1897 return sessionId;
1898 }
1899
1900 void
gnssUpdateXtraThrottleCommand(const bool enabled)1901 GnssAdapter::gnssUpdateXtraThrottleCommand(const bool enabled)
1902 {
1903 LOC_LOGD("%s] enabled:%d", __func__, enabled);
1904
1905 struct UpdateXtraThrottleMsg : public LocMsg {
1906 GnssAdapter& mAdapter;
1907 const bool mEnabled;
1908 inline UpdateXtraThrottleMsg(GnssAdapter& adapter, const bool enabled) :
1909 LocMsg(),
1910 mAdapter(adapter),
1911 mEnabled(enabled) {}
1912 inline virtual void proc() const {
1913 mAdapter.mXtraObserver.updateXtraThrottle(mEnabled);
1914 }
1915 };
1916
1917 sendMsg(new UpdateXtraThrottleMsg(*this, enabled));
1918 }
1919
1920 void
injectLocationCommand(double latitude,double longitude,float accuracy)1921 GnssAdapter::injectLocationCommand(double latitude, double longitude, float accuracy)
1922 {
1923 LOC_LOGD("%s]: latitude %8.4f longitude %8.4f accuracy %8.4f",
1924 __func__, latitude, longitude, accuracy);
1925
1926 struct MsgInjectLocation : public LocMsg {
1927 LocApiBase& mApi;
1928 ContextBase& mContext;
1929 BlockCPIInfo& mBlockCPI;
1930 double mLatitude;
1931 double mLongitude;
1932 float mAccuracy;
1933 inline MsgInjectLocation(LocApiBase& api,
1934 ContextBase& context,
1935 BlockCPIInfo& blockCPIInfo,
1936 double latitude,
1937 double longitude,
1938 float accuracy) :
1939 LocMsg(),
1940 mApi(api),
1941 mContext(context),
1942 mBlockCPI(blockCPIInfo),
1943 mLatitude(latitude),
1944 mLongitude(longitude),
1945 mAccuracy(accuracy) {}
1946 inline virtual void proc() const {
1947 if ((uptimeMillis() <= mBlockCPI.blockedTillTsMs) &&
1948 (fabs(mLatitude-mBlockCPI.latitude) <= mBlockCPI.latLonDiffThreshold) &&
1949 (fabs(mLongitude-mBlockCPI.longitude) <= mBlockCPI.latLonDiffThreshold)) {
1950
1951 LOC_LOGD("%s]: positon injeciton blocked: lat: %f, lon: %f, accuracy: %f",
1952 __func__, mLatitude, mLongitude, mAccuracy);
1953
1954 } else {
1955 mApi.injectPosition(mLatitude, mLongitude, mAccuracy);
1956 }
1957 }
1958 };
1959
1960 sendMsg(new MsgInjectLocation(*mLocApi, *mContext, mBlockCPIInfo,
1961 latitude, longitude, accuracy));
1962 }
1963
1964 void
injectLocationExtCommand(const GnssLocationInfoNotification & locationInfo)1965 GnssAdapter::injectLocationExtCommand(const GnssLocationInfoNotification &locationInfo)
1966 {
1967 LOC_LOGd("latitude %8.4f longitude %8.4f accuracy %8.4f, tech mask 0x%x",
1968 locationInfo.location.latitude, locationInfo.location.longitude,
1969 locationInfo.location.accuracy, locationInfo.location.techMask);
1970
1971 struct MsgInjectLocationExt : public LocMsg {
1972 LocApiBase& mApi;
1973 ContextBase& mContext;
1974 GnssLocationInfoNotification mLocationInfo;
1975 inline MsgInjectLocationExt(LocApiBase& api,
1976 ContextBase& context,
1977 GnssLocationInfoNotification locationInfo) :
1978 LocMsg(),
1979 mApi(api),
1980 mContext(context),
1981 mLocationInfo(locationInfo) {}
1982 inline virtual void proc() const {
1983 // false to indicate for none-ODCPI
1984 mApi.injectPosition(mLocationInfo, false);
1985 }
1986 };
1987
1988 sendMsg(new MsgInjectLocationExt(*mLocApi, *mContext, locationInfo));
1989 }
1990
1991 void
injectTimeCommand(int64_t time,int64_t timeReference,int32_t uncertainty)1992 GnssAdapter::injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty)
1993 {
1994 LOC_LOGD("%s]: time %lld timeReference %lld uncertainty %d",
1995 __func__, (long long)time, (long long)timeReference, uncertainty);
1996
1997 struct MsgInjectTime : public LocMsg {
1998 LocApiBase& mApi;
1999 ContextBase& mContext;
2000 int64_t mTime;
2001 int64_t mTimeReference;
2002 int32_t mUncertainty;
2003 inline MsgInjectTime(LocApiBase& api,
2004 ContextBase& context,
2005 int64_t time,
2006 int64_t timeReference,
2007 int32_t uncertainty) :
2008 LocMsg(),
2009 mApi(api),
2010 mContext(context),
2011 mTime(time),
2012 mTimeReference(timeReference),
2013 mUncertainty(uncertainty) {}
2014 inline virtual void proc() const {
2015 mApi.setTime(mTime, mTimeReference, mUncertainty);
2016 }
2017 };
2018
2019 sendMsg(new MsgInjectTime(*mLocApi, *mContext, time, timeReference, uncertainty));
2020 }
2021
2022 // This command is to called to block the position to be injected to the modem.
2023 // This can happen for network position that comes from modem.
2024 void
blockCPICommand(double latitude,double longitude,float accuracy,int blockDurationMsec,double latLonDiffThreshold)2025 GnssAdapter::blockCPICommand(double latitude, double longitude,
2026 float accuracy, int blockDurationMsec,
2027 double latLonDiffThreshold)
2028 {
2029 struct MsgBlockCPI : public LocMsg {
2030 BlockCPIInfo& mDstCPIInfo;
2031 BlockCPIInfo mSrcCPIInfo;
2032
2033 inline MsgBlockCPI(BlockCPIInfo& dstCPIInfo,
2034 BlockCPIInfo& srcCPIInfo) :
2035 mDstCPIInfo(dstCPIInfo),
2036 mSrcCPIInfo(srcCPIInfo) {}
2037 inline virtual void proc() const {
2038 // in the same hal thread, save the cpi to be blocked
2039 // the global variable
2040 mDstCPIInfo = mSrcCPIInfo;
2041 }
2042 };
2043
2044 // construct the new block CPI info and queue on the same thread
2045 // for processing
2046 BlockCPIInfo blockCPIInfo;
2047 blockCPIInfo.latitude = latitude;
2048 blockCPIInfo.longitude = longitude;
2049 blockCPIInfo.accuracy = accuracy;
2050 blockCPIInfo.blockedTillTsMs = uptimeMillis() + blockDurationMsec;
2051 blockCPIInfo.latLonDiffThreshold = latLonDiffThreshold;
2052
2053 LOC_LOGD("%s]: block CPI lat: %f, lon: %f ", __func__, latitude, longitude);
2054 // send a message to record down the coarse position
2055 // to be blocked from injection in the master copy (mBlockCPIInfo)
2056 sendMsg(new MsgBlockCPI(mBlockCPIInfo, blockCPIInfo));
2057 }
2058
2059 void
updateSystemPowerState(PowerStateType systemPowerState)2060 GnssAdapter::updateSystemPowerState(PowerStateType systemPowerState) {
2061 if (POWER_STATE_UNKNOWN != systemPowerState) {
2062 mSystemPowerState = systemPowerState;
2063 mLocApi->updateSystemPowerState(mSystemPowerState);
2064 }
2065 }
2066
2067 void
updateSystemPowerStateCommand(PowerStateType systemPowerState)2068 GnssAdapter::updateSystemPowerStateCommand(PowerStateType systemPowerState) {
2069 LOC_LOGd("power event %d", systemPowerState);
2070
2071 struct MsgUpdatePowerState : public LocMsg {
2072 GnssAdapter& mAdapter;
2073 PowerStateType mSystemPowerState;
2074
2075 inline MsgUpdatePowerState(GnssAdapter& adapter,
2076 PowerStateType systemPowerState) :
2077 LocMsg(),
2078 mAdapter(adapter),
2079 mSystemPowerState(systemPowerState) {}
2080 inline virtual void proc() const {
2081 mAdapter.updateSystemPowerState(mSystemPowerState);
2082 }
2083 };
2084
2085 sendMsg(new MsgUpdatePowerState(*this, systemPowerState));
2086 }
2087
2088 void
addClientCommand(LocationAPI * client,const LocationCallbacks & callbacks)2089 GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks)
2090 {
2091 LOC_LOGD("%s]: client %p", __func__, client);
2092
2093 struct MsgAddClient : public LocMsg {
2094 GnssAdapter& mAdapter;
2095 LocationAPI* mClient;
2096 const LocationCallbacks mCallbacks;
2097 inline MsgAddClient(GnssAdapter& adapter,
2098 LocationAPI* client,
2099 const LocationCallbacks& callbacks) :
2100 LocMsg(),
2101 mAdapter(adapter),
2102 mClient(client),
2103 mCallbacks(callbacks) {}
2104 inline virtual void proc() const {
2105 // check whether we need to notify client of cached location system info
2106 mAdapter.notifyClientOfCachedLocationSystemInfo(mClient, mCallbacks);
2107 mAdapter.saveClient(mClient, mCallbacks);
2108 }
2109 };
2110
2111 sendMsg(new MsgAddClient(*this, client, callbacks));
2112 }
2113
2114 void
stopClientSessions(LocationAPI * client)2115 GnssAdapter::stopClientSessions(LocationAPI* client)
2116 {
2117 LOC_LOGD("%s]: client %p", __func__, client);
2118
2119 /* Time-based Tracking */
2120 std::vector<LocationSessionKey> vTimeBasedTrackingClient;
2121 for (auto it : mTimeBasedTrackingSessions) {
2122 if (client == it.first.client) {
2123 vTimeBasedTrackingClient.emplace_back(it.first.client, it.first.id);
2124 }
2125 }
2126 for (auto key : vTimeBasedTrackingClient) {
2127 stopTimeBasedTrackingMultiplex(key.client, key.id);
2128 eraseTrackingSession(key.client, key.id);
2129 }
2130
2131 /* Distance-based Tracking */
2132 for (auto it = mDistanceBasedTrackingSessions.begin();
2133 it != mDistanceBasedTrackingSessions.end(); /* no increment here*/) {
2134 if (client == it->first.client) {
2135 mLocApi->stopDistanceBasedTracking(it->first.id, new LocApiResponse(*getContext(),
2136 [this, client, id=it->first.id] (LocationError err) {
2137 if (LOCATION_ERROR_SUCCESS == err) {
2138 eraseTrackingSession(client, id);
2139 }
2140 }
2141 ));
2142 }
2143 ++it; // increment only when not erasing an iterator
2144 }
2145
2146 }
2147
2148 void
updateClientsEventMask()2149 GnssAdapter::updateClientsEventMask()
2150 {
2151 LOC_API_ADAPTER_EVENT_MASK_T mask = 0;
2152 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2153 if (it->second.trackingCb != nullptr ||
2154 it->second.gnssLocationInfoCb != nullptr ||
2155 it->second.engineLocationsInfoCb != nullptr) {
2156 mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT;
2157 }
2158 if (it->second.gnssSvCb != nullptr) {
2159 mask |= LOC_API_ADAPTER_BIT_SATELLITE_REPORT;
2160 }
2161 if ((it->second.gnssNmeaCb != nullptr) && (mNmeaMask)) {
2162 mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT;
2163 }
2164 if (it->second.gnssMeasurementsCb != nullptr) {
2165 mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
2166 }
2167 if (it->second.gnssDataCb != nullptr) {
2168 mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT;
2169 mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT;
2170 updateNmeaMask(mNmeaMask | LOC_NMEA_MASK_DEBUG_V02);
2171 }
2172 }
2173
2174 /*
2175 ** For Automotive use cases we need to enable MEASUREMENT, POLY and EPHEMERIS
2176 ** when QDR is enabled (e.g.: either enabled via conf file or
2177 ** engine hub is loaded successfully).
2178 ** Note: this need to be called from msg queue thread.
2179 */
2180 if((1 == ContextBase::mGps_conf.EXTERNAL_DR_ENABLED) ||
2181 (true == initEngHubProxy())) {
2182 mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
2183 mask |= LOC_API_ADAPTER_BIT_GNSS_SV_POLYNOMIAL_REPORT;
2184 mask |= LOC_API_ADAPTER_BIT_PARSED_UNPROPAGATED_POSITION_REPORT;
2185 mask |= LOC_API_ADAPTER_BIT_GNSS_SV_EPHEMERIS_REPORT;
2186 mask |= LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO;
2187 mask |= LOC_API_ADAPTER_BIT_EVENT_REPORT_INFO;
2188
2189 // Nhz measurement bit is set based on callback from loc eng hub
2190 // for Nhz engines.
2191 mask |= checkMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT);
2192
2193 LOC_LOGd("Auto usecase, Enable MEAS/POLY/EPHEMERIS - mask 0x%" PRIx64 "",
2194 mask);
2195 }
2196
2197 if (mAgpsManager.isRegistered()) {
2198 mask |= LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST;
2199 }
2200 // Add ODCPI handling
2201 if (nullptr != mOdcpiRequestCb) {
2202 mask |= LOC_API_ADAPTER_BIT_REQUEST_WIFI;
2203 }
2204
2205 // need to register for leap second info
2206 // for proper nmea generation
2207 mask |= LOC_API_ADAPTER_BIT_LOC_SYSTEM_INFO;
2208
2209 // always register for NI NOTIFY VERIFY to handle internally in HAL
2210 mask |= LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST;
2211
2212 updateEvtMask(mask, LOC_REGISTRATION_MASK_SET);
2213 }
2214
2215 void
handleEngineUpEvent()2216 GnssAdapter::handleEngineUpEvent()
2217 {
2218 LOC_LOGD("%s]: ", __func__);
2219
2220 struct MsgHandleEngineUpEvent : public LocMsg {
2221 GnssAdapter& mAdapter;
2222 inline MsgHandleEngineUpEvent(GnssAdapter& adapter) :
2223 LocMsg(),
2224 mAdapter(adapter) {}
2225 virtual void proc() const {
2226 mAdapter.setEngineCapabilitiesKnown(true);
2227 mAdapter.broadcastCapabilities(mAdapter.getCapabilities());
2228 // must be called only after capabilities are known
2229 mAdapter.setConfig();
2230 mAdapter.gnssSvIdConfigUpdate();
2231 mAdapter.gnssSvTypeConfigUpdate();
2232 mAdapter.updateSystemPowerState(mAdapter.getSystemPowerState());
2233 mAdapter.restartSessions();
2234 for (auto msg: mAdapter.mPendingMsgs) {
2235 mAdapter.sendMsg(msg);
2236 }
2237 mAdapter.mPendingMsgs.clear();
2238 }
2239 };
2240
2241 readConfigCommand();
2242 sendMsg(new MsgHandleEngineUpEvent(*this));
2243 }
2244
2245 void
restartSessions()2246 GnssAdapter::restartSessions()
2247 {
2248 LOC_LOGD("%s]: ", __func__);
2249
2250 // odcpi session is no longer active after restart
2251 mOdcpiRequestActive = false;
2252
2253 // SPE will be restarted now, so set this variable to false.
2254 mSPEAlreadyRunningAtHighestInterval = false;
2255
2256 checkAndRestartTimeBasedSession();
2257
2258 for (auto it = mDistanceBasedTrackingSessions.begin();
2259 it != mDistanceBasedTrackingSessions.end(); ++it) {
2260 mLocApi->startDistanceBasedTracking(it->first.id, it->second,
2261 new LocApiResponse(*getContext(),
2262 [] (LocationError /*err*/) {}));
2263 }
2264 }
2265
checkAndRestartTimeBasedSession()2266 void GnssAdapter::checkAndRestartTimeBasedSession()
2267 {
2268 LOC_LOGD("%s]: ", __func__);
2269
2270 if (!mTimeBasedTrackingSessions.empty()) {
2271 // get the LocationOptions that has the smallest interval, which should be the active one
2272 TrackingOptions smallestIntervalOptions; // size is zero until set for the first time
2273 TrackingOptions highestPowerTrackingOptions;
2274 memset(&smallestIntervalOptions, 0, sizeof(smallestIntervalOptions));
2275 memset(&highestPowerTrackingOptions, 0, sizeof(highestPowerTrackingOptions));
2276 for (auto it = mTimeBasedTrackingSessions.begin();
2277 it != mTimeBasedTrackingSessions.end(); ++it) {
2278 // size of zero means we havent set it yet
2279 if (0 == smallestIntervalOptions.size ||
2280 it->second.minInterval < smallestIntervalOptions.minInterval) {
2281 smallestIntervalOptions = it->second;
2282 }
2283 GnssPowerMode powerMode = it->second.powerMode;
2284 // Size of zero means we havent set it yet
2285 if (0 == highestPowerTrackingOptions.size ||
2286 (GNSS_POWER_MODE_INVALID != powerMode &&
2287 powerMode < highestPowerTrackingOptions.powerMode)) {
2288 highestPowerTrackingOptions = it->second;
2289 }
2290 }
2291
2292 highestPowerTrackingOptions.setLocationOptions(smallestIntervalOptions);
2293 // want to run SPE session at a fixed min interval in some automotive scenarios
2294 if(!checkAndSetSPEToRunforNHz(highestPowerTrackingOptions)) {
2295 mLocApi->startTimeBasedTracking(highestPowerTrackingOptions, nullptr);
2296 }
2297 }
2298 }
2299
2300 void
notifyClientOfCachedLocationSystemInfo(LocationAPI * client,const LocationCallbacks & callbacks)2301 GnssAdapter::notifyClientOfCachedLocationSystemInfo(
2302 LocationAPI* client, const LocationCallbacks& callbacks) {
2303
2304 if (mLocSystemInfo.systemInfoMask) {
2305 // client need to be notified if client has not yet previously registered
2306 // for the info but now register for it.
2307 bool notifyClientOfSystemInfo = false;
2308 // check whether we need to notify client of cached location system info
2309 //
2310 // client need to be notified if client has not yet previously registered
2311 // for the info but now register for it.
2312 if (callbacks.locationSystemInfoCb) {
2313 notifyClientOfSystemInfo = true;
2314 auto it = mClientData.find(client);
2315 if (it != mClientData.end()) {
2316 LocationCallbacks oldCallbacks = it->second;
2317 if (oldCallbacks.locationSystemInfoCb) {
2318 notifyClientOfSystemInfo = false;
2319 }
2320 }
2321 }
2322
2323 if (notifyClientOfSystemInfo) {
2324 callbacks.locationSystemInfoCb(mLocSystemInfo);
2325 }
2326 }
2327 }
2328
2329 bool
isTimeBasedTrackingSession(LocationAPI * client,uint32_t sessionId)2330 GnssAdapter::isTimeBasedTrackingSession(LocationAPI* client, uint32_t sessionId)
2331 {
2332 LocationSessionKey key(client, sessionId);
2333 return (mTimeBasedTrackingSessions.find(key) != mTimeBasedTrackingSessions.end());
2334 }
2335
2336 bool
isDistanceBasedTrackingSession(LocationAPI * client,uint32_t sessionId)2337 GnssAdapter::isDistanceBasedTrackingSession(LocationAPI* client, uint32_t sessionId)
2338 {
2339 LocationSessionKey key(client, sessionId);
2340 return (mDistanceBasedTrackingSessions.find(key) != mDistanceBasedTrackingSessions.end());
2341 }
2342
2343 bool
hasCallbacksToStartTracking(LocationAPI * client)2344 GnssAdapter::hasCallbacksToStartTracking(LocationAPI* client)
2345 {
2346 bool allowed = false;
2347 auto it = mClientData.find(client);
2348 if (it != mClientData.end()) {
2349 if (it->second.trackingCb || it->second.gnssLocationInfoCb ||
2350 it->second.engineLocationsInfoCb || it->second.gnssMeasurementsCb) {
2351 allowed = true;
2352 } else {
2353 LOC_LOGi("missing right callback to start tracking")
2354 }
2355 } else {
2356 LOC_LOGi("client %p not found", client)
2357 }
2358 return allowed;
2359 }
2360
2361 bool
isTrackingSession(LocationAPI * client,uint32_t sessionId)2362 GnssAdapter::isTrackingSession(LocationAPI* client, uint32_t sessionId)
2363 {
2364 LocationSessionKey key(client, sessionId);
2365 return (mTimeBasedTrackingSessions.find(key) != mTimeBasedTrackingSessions.end());
2366 }
2367
2368 void
reportPowerStateIfChanged()2369 GnssAdapter::reportPowerStateIfChanged()
2370 {
2371 bool newPowerOn = !mTimeBasedTrackingSessions.empty() ||
2372 !mDistanceBasedTrackingSessions.empty();
2373 if (newPowerOn != mPowerOn) {
2374 mPowerOn = newPowerOn;
2375 if (mPowerStateCb != nullptr) {
2376 mPowerStateCb(mPowerOn);
2377 }
2378 }
2379 }
2380
2381 void
getPowerStateChangesCommand(void * powerStateCb)2382 GnssAdapter::getPowerStateChangesCommand(void* powerStateCb)
2383 {
2384 LOC_LOGD("%s]: ", __func__);
2385
2386 struct MsgReportLocation : public LocMsg {
2387 GnssAdapter& mAdapter;
2388 powerStateCallback mPowerStateCb;
2389 inline MsgReportLocation(GnssAdapter& adapter,
2390 powerStateCallback powerStateCb) :
2391 LocMsg(),
2392 mAdapter(adapter),
2393 mPowerStateCb(powerStateCb) {}
2394 inline virtual void proc() const {
2395 mAdapter.savePowerStateCallback(mPowerStateCb);
2396 mPowerStateCb(mAdapter.getPowerState());
2397 }
2398 };
2399
2400 sendMsg(new MsgReportLocation(*this, (powerStateCallback)powerStateCb));
2401 }
2402
2403 void
saveTrackingSession(LocationAPI * client,uint32_t sessionId,const TrackingOptions & options)2404 GnssAdapter::saveTrackingSession(LocationAPI* client, uint32_t sessionId,
2405 const TrackingOptions& options)
2406 {
2407 LocationSessionKey key(client, sessionId);
2408 if ((options.minDistance > 0) &&
2409 ContextBase::isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
2410 mDistanceBasedTrackingSessions[key] = options;
2411 } else {
2412 mTimeBasedTrackingSessions[key] = options;
2413 }
2414 reportPowerStateIfChanged();
2415 }
2416
2417 void
eraseTrackingSession(LocationAPI * client,uint32_t sessionId)2418 GnssAdapter::eraseTrackingSession(LocationAPI* client, uint32_t sessionId)
2419 {
2420 LocationSessionKey key(client, sessionId);
2421 auto it = mTimeBasedTrackingSessions.find(key);
2422 if (it != mTimeBasedTrackingSessions.end()) {
2423 mTimeBasedTrackingSessions.erase(it);
2424 } else {
2425 auto itr = mDistanceBasedTrackingSessions.find(key);
2426 if (itr != mDistanceBasedTrackingSessions.end()) {
2427 mDistanceBasedTrackingSessions.erase(itr);
2428 }
2429 }
2430 reportPowerStateIfChanged();
2431 }
2432
2433
setLocPositionMode(const LocPosMode & mode)2434 bool GnssAdapter::setLocPositionMode(const LocPosMode& mode) {
2435 if (!mLocPositionMode.equals(mode)) {
2436 mLocPositionMode = mode;
2437 return true;
2438 } else {
2439 return false;
2440 }
2441 }
2442
2443 void
reportResponse(LocationAPI * client,LocationError err,uint32_t sessionId)2444 GnssAdapter::reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId)
2445 {
2446 LOC_LOGD("%s]: client %p id %u err %u", __func__, client, sessionId, err);
2447
2448 auto it = mClientData.find(client);
2449 if (it != mClientData.end() && it->second.responseCb != nullptr) {
2450 it->second.responseCb(err, sessionId);
2451 } else {
2452 LOC_LOGW("%s]: client %p id %u not found in data", __func__, client, sessionId);
2453 }
2454 }
2455
2456 void
reportResponse(LocationError err,uint32_t sessionId)2457 GnssAdapter::reportResponse(LocationError err, uint32_t sessionId)
2458 {
2459 LOC_LOGD("%s]: id %u err %u", __func__, sessionId, err);
2460
2461 if (mControlCallbacks.size > 0 && mControlCallbacks.responseCb != nullptr) {
2462 mControlCallbacks.responseCb(err, sessionId);
2463 } else {
2464 LOC_LOGW("%s]: control client response callback not found", __func__);
2465 }
2466 }
2467
2468 void
reportResponse(size_t count,LocationError * errs,uint32_t * ids)2469 GnssAdapter::reportResponse(size_t count, LocationError* errs, uint32_t* ids)
2470 {
2471 IF_LOC_LOGD {
2472 std::string idsString = "[";
2473 std::string errsString = "[";
2474 if (NULL != ids && NULL != errs) {
2475 for (size_t i=0; i < count; ++i) {
2476 idsString += std::to_string(ids[i]) + " ";
2477 errsString += std::to_string(errs[i]) + " ";
2478 }
2479 }
2480 idsString += "]";
2481 errsString += "]";
2482
2483 LOC_LOGD("%s]: ids %s errs %s",
2484 __func__, idsString.c_str(), errsString.c_str());
2485 }
2486
2487 if (mControlCallbacks.size > 0 && mControlCallbacks.collectiveResponseCb != nullptr) {
2488 mControlCallbacks.collectiveResponseCb(count, errs, ids);
2489 } else {
2490 LOC_LOGW("%s]: control client callback not found", __func__);
2491 }
2492 }
2493
2494 uint32_t
startTrackingCommand(LocationAPI * client,TrackingOptions & options)2495 GnssAdapter::startTrackingCommand(LocationAPI* client, TrackingOptions& options)
2496 {
2497 uint32_t sessionId = generateSessionId();
2498 LOC_LOGD("%s]: client %p id %u minInterval %u minDistance %u mode %u powermode %u tbm %u",
2499 __func__, client, sessionId, options.minInterval, options.minDistance, options.mode,
2500 options.powerMode, options.tbm);
2501
2502 struct MsgStartTracking : public LocMsg {
2503 GnssAdapter& mAdapter;
2504 LocApiBase& mApi;
2505 LocationAPI* mClient;
2506 uint32_t mSessionId;
2507 mutable TrackingOptions mOptions;
2508 inline MsgStartTracking(GnssAdapter& adapter,
2509 LocApiBase& api,
2510 LocationAPI* client,
2511 uint32_t sessionId,
2512 TrackingOptions options) :
2513 LocMsg(),
2514 mAdapter(adapter),
2515 mApi(api),
2516 mClient(client),
2517 mSessionId(sessionId),
2518 mOptions(options) {}
2519 inline virtual void proc() const {
2520 // distance based tracking will need to know engine capabilities before it can start
2521 if (!mAdapter.isEngineCapabilitiesKnown() && mOptions.minDistance > 0) {
2522 mAdapter.mPendingMsgs.push_back(new MsgStartTracking(*this));
2523 return;
2524 }
2525 LocationError err = LOCATION_ERROR_SUCCESS;
2526 if (!mAdapter.hasCallbacksToStartTracking(mClient)) {
2527 err = LOCATION_ERROR_CALLBACK_MISSING;
2528 } else if (0 == mOptions.size) {
2529 err = LOCATION_ERROR_INVALID_PARAMETER;
2530 } else {
2531 if (mOptions.minInterval < MIN_TRACKING_INTERVAL) {
2532 mOptions.minInterval = MIN_TRACKING_INTERVAL;
2533 }
2534 if (mOptions.minDistance > 0 &&
2535 ContextBase::isMessageSupported(
2536 LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
2537 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
2538 mApi.startDistanceBasedTracking(mSessionId, mOptions,
2539 new LocApiResponse(*mAdapter.getContext(),
2540 [&mAdapter = mAdapter, mSessionId = mSessionId, mClient = mClient]
2541 (LocationError err) {
2542 if (LOCATION_ERROR_SUCCESS != err) {
2543 mAdapter.eraseTrackingSession(mClient, mSessionId);
2544 }
2545 mAdapter.reportResponse(mClient, err, mSessionId);
2546 }));
2547 } else {
2548 if (GNSS_POWER_MODE_M4 == mOptions.powerMode &&
2549 mOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) {
2550 LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode",
2551 mOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS);
2552 mOptions.powerMode = GNSS_POWER_MODE_M2;
2553 }
2554 // Api doesn't support multiple clients for time based tracking, so mutiplex
2555 bool reportToClientWithNoWait =
2556 mAdapter.startTimeBasedTrackingMultiplex(mClient, mSessionId, mOptions);
2557 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
2558
2559 if (reportToClientWithNoWait) {
2560 mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
2561 }
2562 }
2563 }
2564 }
2565 };
2566
2567 sendMsg(new MsgStartTracking(*this, *mLocApi, client, sessionId, options));
2568 return sessionId;
2569
2570 }
2571
2572 bool
startTimeBasedTrackingMultiplex(LocationAPI * client,uint32_t sessionId,const TrackingOptions & options)2573 GnssAdapter::startTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t sessionId,
2574 const TrackingOptions& options)
2575 {
2576 bool reportToClientWithNoWait = true;
2577
2578 if (mTimeBasedTrackingSessions.empty()) {
2579 startTimeBasedTracking(client, sessionId, options);
2580 // need to wait for QMI callback
2581 reportToClientWithNoWait = false;
2582 } else {
2583 // find the smallest interval and powerMode
2584 TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
2585 GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
2586 memset(&multiplexedOptions, 0, sizeof(multiplexedOptions));
2587 for (auto it = mTimeBasedTrackingSessions.begin(); it != mTimeBasedTrackingSessions.end(); ++it) {
2588 // if not set or there is a new smallest interval, then set the new interval
2589 if (0 == multiplexedOptions.size ||
2590 it->second.minInterval < multiplexedOptions.minInterval) {
2591 multiplexedOptions = it->second;
2592 }
2593 // if session is not the one we are updating and either powerMode
2594 // is not set or there is a new smallest powerMode, then set the new powerMode
2595 if (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
2596 it->second.powerMode < multiplexedPowerMode) {
2597 multiplexedPowerMode = it->second.powerMode;
2598 }
2599 }
2600 bool updateOptions = false;
2601 // if session we are starting has smaller interval then next smallest
2602 if (options.minInterval < multiplexedOptions.minInterval) {
2603 multiplexedOptions.minInterval = options.minInterval;
2604 updateOptions = true;
2605 }
2606
2607 // if session we are starting has smaller powerMode then next smallest
2608 if (options.powerMode < multiplexedPowerMode) {
2609 multiplexedOptions.powerMode = options.powerMode;
2610 updateOptions = true;
2611 }
2612 if (updateOptions) {
2613 // restart time based tracking with the newly updated options
2614
2615 startTimeBasedTracking(client, sessionId, multiplexedOptions);
2616 // need to wait for QMI callback
2617 reportToClientWithNoWait = false;
2618 }
2619 // else part: no QMI call is made, need to report back to client right away
2620 }
2621
2622 return reportToClientWithNoWait;
2623 }
2624
2625 void
startTimeBasedTracking(LocationAPI * client,uint32_t sessionId,const TrackingOptions & trackingOptions)2626 GnssAdapter::startTimeBasedTracking(LocationAPI* client, uint32_t sessionId,
2627 const TrackingOptions& trackingOptions)
2628 {
2629 LOC_LOGd("minInterval %u minDistance %u mode %u powermode %u tbm %u",
2630 trackingOptions.minInterval, trackingOptions.minDistance,
2631 trackingOptions.mode, trackingOptions.powerMode, trackingOptions.tbm);
2632
2633 LocPosMode locPosMode = {};
2634 convertOptions(locPosMode, trackingOptions);
2635
2636 // inform engine hub that GNSS session is about to start
2637 mEngHubProxy->gnssSetFixMode(locPosMode);
2638 mEngHubProxy->gnssStartFix();
2639
2640 // want to run SPE session at a fixed min interval in some automotive scenarios
2641 // use a local copy of TrackingOptions as the TBF may get modified in the
2642 // checkAndSetSPEToRunforNHz function
2643 TrackingOptions tempOptions(trackingOptions);
2644 if (!checkAndSetSPEToRunforNHz(tempOptions)) {
2645 mLocApi->startTimeBasedTracking(tempOptions, new LocApiResponse(*getContext(),
2646 [this, client, sessionId] (LocationError err) {
2647 if (LOCATION_ERROR_SUCCESS != err) {
2648 eraseTrackingSession(client, sessionId);
2649 }
2650
2651 reportResponse(client, err, sessionId);
2652 }
2653 ));
2654 } else {
2655 reportResponse(client, LOCATION_ERROR_SUCCESS, sessionId);
2656 }
2657
2658 }
2659
2660 void
updateTracking(LocationAPI * client,uint32_t sessionId,const TrackingOptions & updatedOptions,const TrackingOptions & oldOptions)2661 GnssAdapter::updateTracking(LocationAPI* client, uint32_t sessionId,
2662 const TrackingOptions& updatedOptions, const TrackingOptions& oldOptions)
2663 {
2664 LocPosMode locPosMode = {};
2665 convertOptions(locPosMode, updatedOptions);
2666
2667 // inform engine hub that GNSS session is about to start
2668 mEngHubProxy->gnssSetFixMode(locPosMode);
2669 mEngHubProxy->gnssStartFix();
2670
2671 // want to run SPE session at a fixed min interval in some automotive scenarios
2672 // use a local copy of TrackingOptions as the TBF may get modified in the
2673 // checkAndSetSPEToRunforNHz function
2674 TrackingOptions tempOptions(updatedOptions);
2675 if(!checkAndSetSPEToRunforNHz(tempOptions)) {
2676 mLocApi->startTimeBasedTracking(tempOptions, new LocApiResponse(*getContext(),
2677 [this, client, sessionId, oldOptions] (LocationError err) {
2678 if (LOCATION_ERROR_SUCCESS != err) {
2679 // restore the old LocationOptions
2680 saveTrackingSession(client, sessionId, oldOptions);
2681 }
2682 reportResponse(client, err, sessionId);
2683 }
2684 ));
2685 } else {
2686 reportResponse(client, LOCATION_ERROR_SUCCESS, sessionId);
2687 }
2688 }
2689
2690 void
updateTrackingOptionsCommand(LocationAPI * client,uint32_t id,TrackingOptions & options)2691 GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id,
2692 TrackingOptions& options)
2693 {
2694 LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
2695 __func__, client, id, options.minInterval, options.mode);
2696
2697 struct MsgUpdateTracking : public LocMsg {
2698 GnssAdapter& mAdapter;
2699 LocApiBase& mApi;
2700 LocationAPI* mClient;
2701 uint32_t mSessionId;
2702 mutable TrackingOptions mOptions;
2703 inline MsgUpdateTracking(GnssAdapter& adapter,
2704 LocApiBase& api,
2705 LocationAPI* client,
2706 uint32_t sessionId,
2707 TrackingOptions options) :
2708 LocMsg(),
2709 mAdapter(adapter),
2710 mApi(api),
2711 mClient(client),
2712 mSessionId(sessionId),
2713 mOptions(options) {}
2714 inline virtual void proc() const {
2715 // distance based tracking will need to know engine capabilities before it can start
2716 if (!mAdapter.isEngineCapabilitiesKnown() && mOptions.minDistance > 0) {
2717 mAdapter.mPendingMsgs.push_back(new MsgUpdateTracking(*this));
2718 return;
2719 }
2720 LocationError err = LOCATION_ERROR_SUCCESS;
2721 bool isTimeBased = mAdapter.isTimeBasedTrackingSession(mClient, mSessionId);
2722 bool isDistanceBased = mAdapter.isDistanceBasedTrackingSession(mClient, mSessionId);
2723 if (!isTimeBased && !isDistanceBased) {
2724 err = LOCATION_ERROR_ID_UNKNOWN;
2725 } else if (0 == mOptions.size) {
2726 err = LOCATION_ERROR_INVALID_PARAMETER;
2727 }
2728 if (LOCATION_ERROR_SUCCESS != err) {
2729 mAdapter.reportResponse(mClient, err, mSessionId);
2730 } else {
2731 if (GNSS_POWER_MODE_M4 == mOptions.powerMode &&
2732 mOptions.tbm > TRACKING_TBM_THRESHOLD_MILLIS) {
2733 LOC_LOGd("TBM (%d) > %d Falling back to M2 power mode",
2734 mOptions.tbm, TRACKING_TBM_THRESHOLD_MILLIS);
2735 mOptions.powerMode = GNSS_POWER_MODE_M2;
2736 }
2737 if (mOptions.minInterval < MIN_TRACKING_INTERVAL) {
2738 mOptions.minInterval = MIN_TRACKING_INTERVAL;
2739 }
2740 // Now update session as required
2741 if (isTimeBased && mOptions.minDistance > 0) {
2742 // switch from time based to distance based
2743 // Api doesn't support multiple clients for time based tracking, so mutiplex
2744 bool reportToClientWithNoWait =
2745 mAdapter.stopTimeBasedTrackingMultiplex(mClient, mSessionId);
2746 // erases the time based Session
2747 mAdapter.eraseTrackingSession(mClient, mSessionId);
2748 if (reportToClientWithNoWait) {
2749 mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
2750 }
2751 // saves as distance based Session
2752 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
2753 mApi.startDistanceBasedTracking(mSessionId, mOptions,
2754 new LocApiResponse(*mAdapter.getContext(),
2755 [] (LocationError /*err*/) {}));
2756 } else if (isDistanceBased && mOptions.minDistance == 0) {
2757 // switch from distance based to time based
2758 mAdapter.eraseTrackingSession(mClient, mSessionId);
2759 mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse(
2760 *mAdapter.getContext(),
2761 [&mAdapter = mAdapter, mSessionId = mSessionId, mOptions = mOptions,
2762 mClient = mClient] (LocationError /*err*/) {
2763 // Api doesn't support multiple clients for time based tracking,
2764 // so mutiplex
2765 bool reportToClientWithNoWait =
2766 mAdapter.startTimeBasedTrackingMultiplex(mClient, mSessionId,
2767 mOptions);
2768 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
2769
2770 if (reportToClientWithNoWait) {
2771 mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
2772 }
2773 }));
2774 } else if (isTimeBased) {
2775 // update time based tracking
2776 // Api doesn't support multiple clients for time based tracking, so mutiplex
2777 bool reportToClientWithNoWait =
2778 mAdapter.updateTrackingMultiplex(mClient, mSessionId, mOptions);
2779 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
2780
2781 if (reportToClientWithNoWait) {
2782 mAdapter.reportResponse(mClient, err, mSessionId);
2783 }
2784 } else if (isDistanceBased) {
2785 // restart distance based tracking
2786 mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse(
2787 *mAdapter.getContext(),
2788 [&mAdapter = mAdapter, mSessionId = mSessionId, mOptions = mOptions,
2789 mClient = mClient, &mApi = mApi] (LocationError err) {
2790 if (LOCATION_ERROR_SUCCESS == err) {
2791 mApi.startDistanceBasedTracking(mSessionId, mOptions,
2792 new LocApiResponse(*mAdapter.getContext(),
2793 [&mAdapter, mClient, mSessionId, mOptions]
2794 (LocationError err) {
2795 if (LOCATION_ERROR_SUCCESS == err) {
2796 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
2797 }
2798 mAdapter.reportResponse(mClient, err, mSessionId);
2799 }));
2800 }
2801 }));
2802 }
2803 }
2804 }
2805 };
2806
2807 sendMsg(new MsgUpdateTracking(*this, *mLocApi, client, id, options));
2808 }
2809
2810 bool
updateTrackingMultiplex(LocationAPI * client,uint32_t id,const TrackingOptions & trackingOptions)2811 GnssAdapter::updateTrackingMultiplex(LocationAPI* client, uint32_t id,
2812 const TrackingOptions& trackingOptions)
2813 {
2814 bool reportToClientWithNoWait = true;
2815
2816 LocationSessionKey key(client, id);
2817 // get the session we are updating
2818 auto it = mTimeBasedTrackingSessions.find(key);
2819
2820 // cache the clients existing LocationOptions
2821 TrackingOptions oldOptions = it->second;
2822
2823 // if session we are updating exists and the minInterval or powerMode has changed
2824 if (it != mTimeBasedTrackingSessions.end() &&
2825 (it->second.minInterval != trackingOptions.minInterval ||
2826 it->second.powerMode != trackingOptions.powerMode)) {
2827 // find the smallest interval and powerMode, other than the session we are updating
2828 TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
2829 GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
2830 memset(&multiplexedOptions, 0, sizeof(multiplexedOptions));
2831 for (auto it2 = mTimeBasedTrackingSessions.begin();
2832 it2 != mTimeBasedTrackingSessions.end(); ++it2) {
2833 // if session is not the one we are updating and either interval
2834 // is not set or there is a new smallest interval, then set the new interval
2835 if (it2->first != key && (0 == multiplexedOptions.size ||
2836 it2->second.minInterval < multiplexedOptions.minInterval)) {
2837 multiplexedOptions = it2->second;
2838 }
2839 // if session is not the one we are updating and either powerMode
2840 // is not set or there is a new smallest powerMode, then set the new powerMode
2841 if (it2->first != key && (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
2842 it2->second.powerMode < multiplexedPowerMode)) {
2843 multiplexedPowerMode = it2->second.powerMode;
2844 }
2845 // else part: no QMI call is made, need to report back to client right away
2846 }
2847 bool updateOptions = false;
2848 // if session we are updating has smaller interval then next smallest
2849 if (trackingOptions.minInterval < multiplexedOptions.minInterval) {
2850 multiplexedOptions.minInterval = trackingOptions.minInterval;
2851 updateOptions = true;
2852 }
2853 // if session we are updating has smaller powerMode then next smallest
2854 if (trackingOptions.powerMode < multiplexedPowerMode) {
2855 multiplexedOptions.powerMode = trackingOptions.powerMode;
2856 updateOptions = true;
2857 }
2858 // if only one session exists, then tracking should be updated with it
2859 if (1 == mTimeBasedTrackingSessions.size()) {
2860 multiplexedOptions = trackingOptions;
2861 updateOptions = true;
2862 }
2863 if (updateOptions) {
2864 // restart time based tracking with the newly updated options
2865 updateTracking(client, id, multiplexedOptions, oldOptions);
2866 // need to wait for QMI callback
2867 reportToClientWithNoWait = false;
2868 }
2869 }
2870
2871 return reportToClientWithNoWait;
2872 }
2873
2874 void
stopTrackingCommand(LocationAPI * client,uint32_t id)2875 GnssAdapter::stopTrackingCommand(LocationAPI* client, uint32_t id)
2876 {
2877 LOC_LOGD("%s]: client %p id %u", __func__, client, id);
2878
2879 struct MsgStopTracking : public LocMsg {
2880 GnssAdapter& mAdapter;
2881 LocApiBase& mApi;
2882 LocationAPI* mClient;
2883 uint32_t mSessionId;
2884 inline MsgStopTracking(GnssAdapter& adapter,
2885 LocApiBase& api,
2886 LocationAPI* client,
2887 uint32_t sessionId) :
2888 LocMsg(),
2889 mAdapter(adapter),
2890 mApi(api),
2891 mClient(client),
2892 mSessionId(sessionId) {}
2893 inline virtual void proc() const {
2894 bool isTimeBased = mAdapter.isTimeBasedTrackingSession(mClient, mSessionId);
2895 bool isDistanceBased = mAdapter.isDistanceBasedTrackingSession(mClient, mSessionId);
2896 if (isTimeBased || isDistanceBased) {
2897 if (isTimeBased) {
2898 // Api doesn't support multiple clients for time based tracking, so mutiplex
2899 bool reportToClientWithNoWait =
2900 mAdapter.stopTimeBasedTrackingMultiplex(mClient, mSessionId);
2901 mAdapter.eraseTrackingSession(mClient, mSessionId);
2902
2903 if (reportToClientWithNoWait) {
2904 mAdapter.reportResponse(mClient, LOCATION_ERROR_SUCCESS, mSessionId);
2905 }
2906 } else if (isDistanceBased) {
2907 mApi.stopDistanceBasedTracking(mSessionId, new LocApiResponse(
2908 *mAdapter.getContext(),
2909 [&mAdapter = mAdapter, mSessionId = mSessionId, mClient = mClient]
2910 (LocationError err) {
2911 if (LOCATION_ERROR_SUCCESS == err) {
2912 mAdapter.eraseTrackingSession(mClient, mSessionId);
2913 }
2914 mAdapter.reportResponse(mClient, err, mSessionId);
2915 }));
2916 }
2917 } else {
2918 mAdapter.reportResponse(mClient, LOCATION_ERROR_ID_UNKNOWN, mSessionId);
2919 }
2920
2921 }
2922 };
2923
2924 sendMsg(new MsgStopTracking(*this, *mLocApi, client, id));
2925 }
2926
2927 bool
stopTimeBasedTrackingMultiplex(LocationAPI * client,uint32_t id)2928 GnssAdapter::stopTimeBasedTrackingMultiplex(LocationAPI* client, uint32_t id)
2929 {
2930 bool reportToClientWithNoWait = true;
2931
2932 if (1 == mTimeBasedTrackingSessions.size()) {
2933 stopTracking(client, id);
2934 // need to wait for QMI callback
2935 reportToClientWithNoWait = false;
2936 } else {
2937 LocationSessionKey key(client, id);
2938
2939 // get the session we are stopping
2940 auto it = mTimeBasedTrackingSessions.find(key);
2941 if (it != mTimeBasedTrackingSessions.end()) {
2942 // find the smallest interval and powerMode, other than the session we are stopping
2943 TrackingOptions multiplexedOptions = {}; // size is 0 until set for the first time
2944 GnssPowerMode multiplexedPowerMode = GNSS_POWER_MODE_INVALID;
2945 memset(&multiplexedOptions, 0, sizeof(multiplexedOptions));
2946 for (auto it2 = mTimeBasedTrackingSessions.begin();
2947 it2 != mTimeBasedTrackingSessions.end(); ++it2) {
2948 // if session is not the one we are stopping and either interval
2949 // is not set or there is a new smallest interval, then set the new interval
2950 if (it2->first != key && (0 == multiplexedOptions.size ||
2951 it2->second.minInterval < multiplexedOptions.minInterval)) {
2952 multiplexedOptions = it2->second;
2953 }
2954 // if session is not the one we are stopping and either powerMode
2955 // is not set or there is a new smallest powerMode, then set the new powerMode
2956 if (it2->first != key && (GNSS_POWER_MODE_INVALID == multiplexedPowerMode ||
2957 it2->second.powerMode < multiplexedPowerMode)) {
2958 multiplexedPowerMode = it2->second.powerMode;
2959 }
2960 }
2961 // if session we are stopping has smaller interval then next smallest or
2962 // if session we are stopping has smaller powerMode then next smallest
2963 if (it->second.minInterval < multiplexedOptions.minInterval ||
2964 it->second.powerMode < multiplexedPowerMode) {
2965 multiplexedOptions.powerMode = multiplexedPowerMode;
2966 // restart time based tracking with the newly updated options
2967 startTimeBasedTracking(client, id, multiplexedOptions);
2968 // need to wait for QMI callback
2969 reportToClientWithNoWait = false;
2970 }
2971 // else part: no QMI call is made, need to report back to client right away
2972 }
2973 }
2974
2975 return reportToClientWithNoWait;
2976 }
2977
2978 void
stopTracking(LocationAPI * client,uint32_t id)2979 GnssAdapter::stopTracking(LocationAPI* client, uint32_t id)
2980 {
2981 // inform engine hub that GNSS session has stopped
2982 mEngHubProxy->gnssStopFix();
2983
2984 mLocApi->stopFix(new LocApiResponse(*getContext(),
2985 [this, client, id] (LocationError err) {
2986 reportResponse(client, err, id);
2987 }));
2988
2989 mSPEAlreadyRunningAtHighestInterval = false;
2990 }
2991
2992 bool
hasNiNotifyCallback(LocationAPI * client)2993 GnssAdapter::hasNiNotifyCallback(LocationAPI* client)
2994 {
2995 auto it = mClientData.find(client);
2996 return (it != mClientData.end() && it->second.gnssNiCb);
2997 }
2998
2999 void
gnssNiResponseCommand(LocationAPI * client,uint32_t id,GnssNiResponse response)3000 GnssAdapter::gnssNiResponseCommand(LocationAPI* client,
3001 uint32_t id,
3002 GnssNiResponse response)
3003 {
3004 LOC_LOGD("%s]: client %p id %u response %u", __func__, client, id, response);
3005
3006 struct MsgGnssNiResponse : public LocMsg {
3007 GnssAdapter& mAdapter;
3008 LocationAPI* mClient;
3009 uint32_t mSessionId;
3010 GnssNiResponse mResponse;
3011 inline MsgGnssNiResponse(GnssAdapter& adapter,
3012 LocationAPI* client,
3013 uint32_t sessionId,
3014 GnssNiResponse response) :
3015 LocMsg(),
3016 mAdapter(adapter),
3017 mClient(client),
3018 mSessionId(sessionId),
3019 mResponse(response) {}
3020 inline virtual void proc() const {
3021 NiData& niData = mAdapter.getNiData();
3022 LocationError err = LOCATION_ERROR_SUCCESS;
3023 if (!mAdapter.hasNiNotifyCallback(mClient)) {
3024 err = LOCATION_ERROR_ID_UNKNOWN;
3025 } else {
3026 NiSession* pSession = NULL;
3027 if (mSessionId == niData.sessionEs.reqID &&
3028 NULL != niData.sessionEs.rawRequest) {
3029 pSession = &niData.sessionEs;
3030 // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
3031 if (mResponse == GNSS_NI_RESPONSE_ACCEPT &&
3032 NULL != niData.session.rawRequest) {
3033 pthread_mutex_lock(&niData.session.tLock);
3034 niData.session.resp = GNSS_NI_RESPONSE_IGNORE;
3035 niData.session.respRecvd = true;
3036 pthread_cond_signal(&niData.session.tCond);
3037 pthread_mutex_unlock(&niData.session.tLock);
3038 }
3039 } else if (mSessionId == niData.session.reqID &&
3040 NULL != niData.session.rawRequest) {
3041 pSession = &niData.session;
3042 }
3043
3044 if (pSession) {
3045 LOC_LOGI("%s]: gnssNiResponseCommand: send user mResponse %u for id %u",
3046 __func__, mResponse, mSessionId);
3047 pthread_mutex_lock(&pSession->tLock);
3048 pSession->resp = mResponse;
3049 pSession->respRecvd = true;
3050 pthread_cond_signal(&pSession->tCond);
3051 pthread_mutex_unlock(&pSession->tLock);
3052 } else {
3053 err = LOCATION_ERROR_ID_UNKNOWN;
3054 LOC_LOGE("%s]: gnssNiResponseCommand: id %u not an active session",
3055 __func__, mSessionId);
3056 }
3057 }
3058 mAdapter.reportResponse(mClient, err, mSessionId);
3059 }
3060 };
3061
3062 sendMsg(new MsgGnssNiResponse(*this, client, id, response));
3063
3064 }
3065
3066 void
gnssNiResponseCommand(GnssNiResponse response,void * rawRequest)3067 GnssAdapter::gnssNiResponseCommand(GnssNiResponse response, void* rawRequest)
3068 {
3069 LOC_LOGD("%s]: response %u", __func__, response);
3070
3071 struct MsgGnssNiResponse : public LocMsg {
3072 GnssAdapter& mAdapter;
3073 LocApiBase& mApi;
3074 const GnssNiResponse mResponse;
3075 const void* mPayload;
3076 inline MsgGnssNiResponse(GnssAdapter& adapter,
3077 LocApiBase& api,
3078 const GnssNiResponse response,
3079 const void* rawRequest) :
3080 LocMsg(),
3081 mAdapter(adapter),
3082 mApi(api),
3083 mResponse(response),
3084 mPayload(rawRequest) {}
3085 inline virtual ~MsgGnssNiResponse() {
3086 }
3087 inline virtual void proc() const {
3088 mApi.informNiResponse(mResponse, mPayload);
3089 }
3090 };
3091
3092 sendMsg(new MsgGnssNiResponse(*this, *mLocApi, response, rawRequest));
3093
3094 }
3095
3096 uint32_t
enableCommand(LocationTechnologyType techType)3097 GnssAdapter::enableCommand(LocationTechnologyType techType)
3098 {
3099 uint32_t sessionId = generateSessionId();
3100 LOC_LOGD("%s]: id %u techType %u", __func__, sessionId, techType);
3101
3102 struct MsgEnableGnss : public LocMsg {
3103 GnssAdapter& mAdapter;
3104 LocApiBase& mApi;
3105 ContextBase& mContext;
3106 uint32_t mSessionId;
3107 LocationTechnologyType mTechType;
3108 inline MsgEnableGnss(GnssAdapter& adapter,
3109 LocApiBase& api,
3110 ContextBase& context,
3111 uint32_t sessionId,
3112 LocationTechnologyType techType) :
3113 LocMsg(),
3114 mAdapter(adapter),
3115 mApi(api),
3116 mContext(context),
3117 mSessionId(sessionId),
3118 mTechType(techType) {}
3119 inline virtual void proc() const {
3120 LocationError err = LOCATION_ERROR_SUCCESS;
3121 uint32_t afwControlId = mAdapter.getAfwControlId();
3122 if (mTechType != LOCATION_TECHNOLOGY_TYPE_GNSS) {
3123 err = LOCATION_ERROR_INVALID_PARAMETER;
3124 } else if (afwControlId > 0) {
3125 err = LOCATION_ERROR_ALREADY_STARTED;
3126 } else {
3127 mContext.modemPowerVote(true);
3128 mAdapter.setAfwControlId(mSessionId);
3129
3130 GnssConfigGpsLock gpsLock = GNSS_CONFIG_GPS_LOCK_NONE;
3131 if (mAdapter.mSupportNfwControl) {
3132 ContextBase::mGps_conf.GPS_LOCK &= GNSS_CONFIG_GPS_LOCK_NI;
3133 gpsLock = ContextBase::mGps_conf.GPS_LOCK;
3134 }
3135 mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() {
3136 mApi.setGpsLockSync(gpsLock);
3137 }));
3138 mAdapter.mXtraObserver.updateLockStatus(gpsLock);
3139 }
3140 mAdapter.reportResponse(err, mSessionId);
3141 }
3142 };
3143
3144 if (mContext != NULL) {
3145 sendMsg(new MsgEnableGnss(*this, *mLocApi, *mContext, sessionId, techType));
3146 } else {
3147 LOC_LOGE("%s]: Context is NULL", __func__);
3148 }
3149
3150 return sessionId;
3151 }
3152
3153 void
disableCommand(uint32_t id)3154 GnssAdapter::disableCommand(uint32_t id)
3155 {
3156 LOC_LOGD("%s]: id %u", __func__, id);
3157
3158 struct MsgDisableGnss : public LocMsg {
3159 GnssAdapter& mAdapter;
3160 LocApiBase& mApi;
3161 ContextBase& mContext;
3162 uint32_t mSessionId;
3163 inline MsgDisableGnss(GnssAdapter& adapter,
3164 LocApiBase& api,
3165 ContextBase& context,
3166 uint32_t sessionId) :
3167 LocMsg(),
3168 mAdapter(adapter),
3169 mApi(api),
3170 mContext(context),
3171 mSessionId(sessionId) {}
3172 inline virtual void proc() const {
3173 LocationError err = LOCATION_ERROR_SUCCESS;
3174 uint32_t afwControlId = mAdapter.getAfwControlId();
3175 if (afwControlId != mSessionId) {
3176 err = LOCATION_ERROR_ID_UNKNOWN;
3177 } else {
3178 mContext.modemPowerVote(false);
3179 mAdapter.setAfwControlId(0);
3180
3181 if (mAdapter.mSupportNfwControl) {
3182 /* We need to disable MO (AFW) */
3183 ContextBase::mGps_conf.GPS_LOCK |= GNSS_CONFIG_GPS_LOCK_MO;
3184 }
3185 GnssConfigGpsLock gpsLock = ContextBase::mGps_conf.GPS_LOCK;
3186 mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() {
3187 mApi.setGpsLockSync(gpsLock);
3188 }));
3189 mAdapter.mXtraObserver.updateLockStatus(gpsLock);
3190 }
3191 mAdapter.reportResponse(err, mSessionId);
3192 }
3193 };
3194
3195 if (mContext != NULL) {
3196 sendMsg(new MsgDisableGnss(*this, *mLocApi, *mContext, id));
3197 }
3198
3199 }
3200
3201 void
reportPositionEvent(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask,GnssDataNotification * pDataNotify,int msInWeek)3202 GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation,
3203 const GpsLocationExtended& locationExtended,
3204 enum loc_sess_status status,
3205 LocPosTechMask techMask,
3206 GnssDataNotification* pDataNotify,
3207 int msInWeek)
3208 {
3209 // this position is from QMI LOC API, then send report to engine hub
3210 // also, send out SPE fix promptly to the clients that have registered
3211 // with SPE report
3212 LOC_LOGd("reportPositionEvent, eng type: %d, unpro %d, sess status %d",
3213 locationExtended.locOutputEngType, ulpLocation.unpropagatedPosition,
3214 status);
3215
3216 if (true == initEngHubProxy()){
3217 // send the SPE fix to engine hub
3218 mEngHubProxy->gnssReportPosition(ulpLocation, locationExtended, status);
3219 // report out all SPE fix if it is not propagated, even for failed fix
3220 if (false == ulpLocation.unpropagatedPosition) {
3221 EngineLocationInfo engLocationInfo = {};
3222 engLocationInfo.location = ulpLocation;
3223 engLocationInfo.locationExtended = locationExtended;
3224 engLocationInfo.sessionStatus = status;
3225 reportEnginePositionsEvent(1, &engLocationInfo);
3226 }
3227 return;
3228 }
3229
3230 // unpropagated report: is only for engine hub to consume and no need
3231 // to send out to the clients
3232 if (true == ulpLocation.unpropagatedPosition) {
3233 return;
3234 }
3235
3236 // Fix is from QMI, and it is not an unpropagated position and engine hub
3237 // is not loaded, queue the message when message is processed, the position
3238 // can be dispatched to requesting client that registers for SPE report
3239 struct MsgReportPosition : public LocMsg {
3240 GnssAdapter& mAdapter;
3241 const UlpLocation mUlpLocation;
3242 const GpsLocationExtended mLocationExtended;
3243 loc_sess_status mStatus;
3244 LocPosTechMask mTechMask;
3245 GnssDataNotification mDataNotify;
3246 int mMsInWeek;
3247 bool mbIsDataValid;
3248 inline MsgReportPosition(GnssAdapter& adapter,
3249 const UlpLocation& ulpLocation,
3250 const GpsLocationExtended& locationExtended,
3251 loc_sess_status status,
3252 LocPosTechMask techMask,
3253 GnssDataNotification* pDataNotify,
3254 int msInWeek) :
3255 LocMsg(),
3256 mAdapter(adapter),
3257 mUlpLocation(ulpLocation),
3258 mLocationExtended(locationExtended),
3259 mStatus(status),
3260 mTechMask(techMask),
3261 mMsInWeek(msInWeek) {
3262 memset(&mDataNotify, 0, sizeof(mDataNotify));
3263 if (pDataNotify != nullptr) {
3264 mDataNotify = *pDataNotify;
3265 mbIsDataValid = true;
3266 } else {
3267 mbIsDataValid = false;
3268 }
3269 }
3270 inline virtual void proc() const {
3271 // extract bug report info - this returns true if consumed by systemstatus
3272 SystemStatus* s = mAdapter.getSystemStatus();
3273 if ((nullptr != s) &&
3274 ((LOC_SESS_SUCCESS == mStatus) || (LOC_SESS_INTERMEDIATE == mStatus))){
3275 s->eventPosition(mUlpLocation, mLocationExtended);
3276 }
3277 mAdapter.reportPosition(mUlpLocation, mLocationExtended, mStatus, mTechMask);
3278 if (true == mbIsDataValid) {
3279 if (-1 != mMsInWeek) {
3280 mAdapter.getDataInformation((GnssDataNotification&)mDataNotify,
3281 mMsInWeek);
3282 }
3283 mAdapter.reportData((GnssDataNotification&)mDataNotify);
3284 }
3285 }
3286 };
3287
3288 sendMsg(new MsgReportPosition(*this, ulpLocation, locationExtended,
3289 status, techMask,
3290 pDataNotify, msInWeek));
3291 }
3292
3293 void
reportEnginePositionsEvent(unsigned int count,EngineLocationInfo * locationArr)3294 GnssAdapter::reportEnginePositionsEvent(unsigned int count,
3295 EngineLocationInfo* locationArr)
3296 {
3297 struct MsgReportEnginePositions : public LocMsg {
3298 GnssAdapter& mAdapter;
3299 unsigned int mCount;
3300 EngineLocationInfo mEngLocInfo[LOC_OUTPUT_ENGINE_COUNT];
3301 inline MsgReportEnginePositions(GnssAdapter& adapter,
3302 unsigned int count,
3303 EngineLocationInfo* locationArr) :
3304 LocMsg(),
3305 mAdapter(adapter),
3306 mCount(count) {
3307 if (mCount > LOC_OUTPUT_ENGINE_COUNT) {
3308 mCount = LOC_OUTPUT_ENGINE_COUNT;
3309 }
3310 if (mCount > 0) {
3311 memcpy(mEngLocInfo, locationArr, sizeof(EngineLocationInfo)*mCount);
3312 }
3313 }
3314 inline virtual void proc() const {
3315 mAdapter.reportEnginePositions(mCount, mEngLocInfo);
3316 }
3317 };
3318
3319 sendMsg(new MsgReportEnginePositions(*this, count, locationArr));
3320 }
3321
3322 bool
needReportForGnssClient(const UlpLocation & ulpLocation,enum loc_sess_status status,LocPosTechMask techMask)3323 GnssAdapter::needReportForGnssClient(const UlpLocation& ulpLocation,
3324 enum loc_sess_status status,
3325 LocPosTechMask techMask) {
3326 bool reported = false;
3327
3328 // if engine hub is enabled, aka, any of the engine services is enabled,
3329 // then always output position reported by engine hub to requesting client
3330 if (true == initEngHubProxy()) {
3331 reported = true;
3332 } else {
3333 reported = LocApiBase::needReport(ulpLocation, status, techMask);
3334 }
3335 return reported;
3336 }
3337
3338 bool
needReportForFlpClient(enum loc_sess_status status,LocPosTechMask techMask)3339 GnssAdapter::needReportForFlpClient(enum loc_sess_status status,
3340 LocPosTechMask techMask) {
3341 if ((status == LOC_SESS_INTERMEDIATE) &&
3342 !(techMask & LOC_POS_TECH_MASK_SENSORS) &&
3343 (!getAllowFlpNetworkFixes())) {
3344 return false;
3345 } else {
3346 return true;
3347 }
3348 }
3349
3350 bool
isFlpClient(LocationCallbacks & locationCallbacks)3351 GnssAdapter::isFlpClient(LocationCallbacks& locationCallbacks)
3352 {
3353 return (locationCallbacks.gnssLocationInfoCb == nullptr &&
3354 locationCallbacks.gnssSvCb == nullptr &&
3355 locationCallbacks.gnssNmeaCb == nullptr &&
3356 locationCallbacks.gnssDataCb == nullptr &&
3357 locationCallbacks.gnssMeasurementsCb == nullptr);
3358 }
3359
3360 void
reportPosition(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask)3361 GnssAdapter::reportPosition(const UlpLocation& ulpLocation,
3362 const GpsLocationExtended& locationExtended,
3363 enum loc_sess_status status,
3364 LocPosTechMask techMask)
3365 {
3366 bool reportToGnssClient = needReportForGnssClient(ulpLocation, status, techMask);
3367 bool reportToFlpClient = needReportForFlpClient(status, techMask);
3368
3369 if (reportToGnssClient || reportToFlpClient) {
3370 GnssLocationInfoNotification locationInfo = {};
3371 convertLocationInfo(locationInfo, locationExtended);
3372 convertLocation(locationInfo.location, ulpLocation, locationExtended, techMask);
3373
3374 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3375 if ((reportToFlpClient && isFlpClient(it->second)) ||
3376 (reportToGnssClient && !isFlpClient(it->second))) {
3377 if (nullptr != it->second.gnssLocationInfoCb) {
3378 it->second.gnssLocationInfoCb(locationInfo);
3379 } else if ((nullptr != it->second.engineLocationsInfoCb) &&
3380 (false == initEngHubProxy())) {
3381 // if engine hub is disabled, this is SPE fix from modem
3382 // we need to mark one copy marked as fused and one copy marked as PPE
3383 // and dispatch it to the engineLocationsInfoCb
3384 GnssLocationInfoNotification engLocationsInfo[2];
3385 engLocationsInfo[0] = locationInfo;
3386 engLocationsInfo[0].locOutputEngType = LOC_OUTPUT_ENGINE_FUSED;
3387 engLocationsInfo[0].flags |= GNSS_LOCATION_INFO_OUTPUT_ENG_TYPE_BIT;
3388 engLocationsInfo[1] = locationInfo;
3389 it->second.engineLocationsInfoCb(2, engLocationsInfo);
3390 } else if (nullptr != it->second.trackingCb) {
3391 it->second.trackingCb(locationInfo.location);
3392 }
3393 }
3394 }
3395
3396 mGnssSvIdUsedInPosAvail = false;
3397 mGnssMbSvIdUsedInPosAvail = false;
3398 if (reportToGnssClient) {
3399 if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA) {
3400 mGnssSvIdUsedInPosAvail = true;
3401 mGnssSvIdUsedInPosition = locationExtended.gnss_sv_used_ids;
3402 if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_MULTIBAND) {
3403 mGnssMbSvIdUsedInPosAvail = true;
3404 mGnssMbSvIdUsedInPosition = locationExtended.gnss_mb_sv_used_ids;
3405 }
3406 }
3407
3408 // if PACE is enabled and engine hub is running and the fix is from sensor,
3409 // e.g.: DRE, inject DRE fix to modem
3410 if ((true == mLocConfigInfo.paceConfigInfo.isValid &&
3411 true == mLocConfigInfo.paceConfigInfo.enable) &&
3412 (true == initEngHubProxy()) && (LOC_POS_TECH_MASK_SENSORS & techMask)) {
3413 mLocApi->injectPosition(locationInfo, false);
3414 }
3415 }
3416 }
3417
3418 if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER &&
3419 !mTimeBasedTrackingSessions.empty()) {
3420 /*Only BlankNMEA sentence needs to be processed and sent, if both lat, long is 0 &
3421 horReliability is not set. */
3422 bool blank_fix = ((0 == ulpLocation.gpsLocation.latitude) &&
3423 (0 == ulpLocation.gpsLocation.longitude) &&
3424 (LOC_RELIABILITY_NOT_SET == locationExtended.horizontal_reliability));
3425 uint8_t generate_nmea = (reportToGnssClient && status != LOC_SESS_FAILURE && !blank_fix);
3426 bool custom_nmea_gga = (1 == ContextBase::mGps_conf.CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED);
3427 std::vector<std::string> nmeaArraystr;
3428 loc_nmea_generate_pos(ulpLocation, locationExtended, mLocSystemInfo,
3429 generate_nmea, custom_nmea_gga, nmeaArraystr);
3430 stringstream ss;
3431 for (auto itor = nmeaArraystr.begin(); itor != nmeaArraystr.end(); ++itor) {
3432 ss << *itor;
3433 }
3434 string s = ss.str();
3435 reportNmea(s.c_str(), s.length());
3436 }
3437 }
3438
3439 void
reportEnginePositions(unsigned int count,const EngineLocationInfo * locationArr)3440 GnssAdapter::reportEnginePositions(unsigned int count,
3441 const EngineLocationInfo* locationArr)
3442 {
3443 bool needReportEnginePositions = false;
3444 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3445 if (nullptr != it->second.engineLocationsInfoCb) {
3446 needReportEnginePositions = true;
3447 break;
3448 }
3449 }
3450
3451 GnssLocationInfoNotification locationInfo[LOC_OUTPUT_ENGINE_COUNT] = {};
3452 for (unsigned int i = 0; i < count; i++) {
3453 const EngineLocationInfo* engLocation = (locationArr+i);
3454 // if it is fused/default location, call reportPosition maintain legacy behavior
3455 if ((GPS_LOCATION_EXTENDED_HAS_OUTPUT_ENG_TYPE & engLocation->locationExtended.flags) &&
3456 (LOC_OUTPUT_ENGINE_FUSED == engLocation->locationExtended.locOutputEngType)) {
3457 reportPosition(engLocation->location,
3458 engLocation->locationExtended,
3459 engLocation->sessionStatus,
3460 engLocation->location.tech_mask);
3461 }
3462
3463 if (needReportEnginePositions) {
3464 convertLocationInfo(locationInfo[i], engLocation->locationExtended);
3465 convertLocation(locationInfo[i].location,
3466 engLocation->location,
3467 engLocation->locationExtended,
3468 engLocation->location.tech_mask);
3469 }
3470 }
3471
3472 if (needReportEnginePositions) {
3473 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3474 if (nullptr != it->second.engineLocationsInfoCb) {
3475 it->second.engineLocationsInfoCb(count, locationInfo);
3476 }
3477 }
3478 }
3479 }
3480
3481 void
reportSvEvent(const GnssSvNotification & svNotify,bool fromEngineHub)3482 GnssAdapter::reportSvEvent(const GnssSvNotification& svNotify,
3483 bool fromEngineHub)
3484 {
3485 if (!fromEngineHub) {
3486 mEngHubProxy->gnssReportSv(svNotify);
3487 if (true == initEngHubProxy()){
3488 return;
3489 }
3490 }
3491
3492 struct MsgReportSv : public LocMsg {
3493 GnssAdapter& mAdapter;
3494 const GnssSvNotification mSvNotify;
3495 inline MsgReportSv(GnssAdapter& adapter,
3496 const GnssSvNotification& svNotify) :
3497 LocMsg(),
3498 mAdapter(adapter),
3499 mSvNotify(svNotify) {}
3500 inline virtual void proc() const {
3501 mAdapter.reportSv((GnssSvNotification&)mSvNotify);
3502 }
3503 };
3504
3505 sendMsg(new MsgReportSv(*this, svNotify));
3506 }
3507
3508 void
reportSv(GnssSvNotification & svNotify)3509 GnssAdapter::reportSv(GnssSvNotification& svNotify)
3510 {
3511 int numSv = svNotify.count;
3512 int16_t gnssSvId = 0;
3513 uint64_t svUsedIdMask = 0;
3514 for (int i=0; i < numSv; i++) {
3515 svUsedIdMask = 0;
3516 gnssSvId = svNotify.gnssSvs[i].svId;
3517 GnssSignalTypeMask signalTypeMask = svNotify.gnssSvs[i].gnssSignalTypeMask;
3518 switch (svNotify.gnssSvs[i].type) {
3519 case GNSS_SV_TYPE_GPS:
3520 if (mGnssSvIdUsedInPosAvail) {
3521 if (mGnssMbSvIdUsedInPosAvail) {
3522 switch (signalTypeMask) {
3523 case GNSS_SIGNAL_GPS_L1CA:
3524 svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l1ca_sv_used_ids_mask;
3525 break;
3526 case GNSS_SIGNAL_GPS_L1C:
3527 svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l1c_sv_used_ids_mask;
3528 break;
3529 case GNSS_SIGNAL_GPS_L2:
3530 svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l2_sv_used_ids_mask;
3531 break;
3532 case GNSS_SIGNAL_GPS_L5:
3533 svUsedIdMask = mGnssMbSvIdUsedInPosition.gps_l5_sv_used_ids_mask;
3534 break;
3535 }
3536 } else {
3537 svUsedIdMask = mGnssSvIdUsedInPosition.gps_sv_used_ids_mask;
3538 }
3539 }
3540 break;
3541 case GNSS_SV_TYPE_GLONASS:
3542 if (mGnssSvIdUsedInPosAvail) {
3543 if (mGnssMbSvIdUsedInPosAvail) {
3544 switch (signalTypeMask) {
3545 case GNSS_SIGNAL_GLONASS_G1:
3546 svUsedIdMask = mGnssMbSvIdUsedInPosition.glo_g1_sv_used_ids_mask;
3547 break;
3548 case GNSS_SIGNAL_GLONASS_G2:
3549 svUsedIdMask = mGnssMbSvIdUsedInPosition.glo_g2_sv_used_ids_mask;
3550 break;
3551 }
3552 } else {
3553 svUsedIdMask = mGnssSvIdUsedInPosition.glo_sv_used_ids_mask;
3554 }
3555 }
3556 break;
3557 case GNSS_SV_TYPE_BEIDOU:
3558 if (mGnssSvIdUsedInPosAvail) {
3559 if (mGnssMbSvIdUsedInPosAvail) {
3560 switch (signalTypeMask) {
3561 case GNSS_SIGNAL_BEIDOU_B1I:
3562 svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b1i_sv_used_ids_mask;
3563 break;
3564 case GNSS_SIGNAL_BEIDOU_B1C:
3565 svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b1c_sv_used_ids_mask;
3566 break;
3567 case GNSS_SIGNAL_BEIDOU_B2I:
3568 svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b2i_sv_used_ids_mask;
3569 break;
3570 case GNSS_SIGNAL_BEIDOU_B2AI:
3571 svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b2ai_sv_used_ids_mask;
3572 break;
3573 case GNSS_SIGNAL_BEIDOU_B2AQ:
3574 svUsedIdMask = mGnssMbSvIdUsedInPosition.bds_b2aq_sv_used_ids_mask;
3575 break;
3576 }
3577 } else {
3578 svUsedIdMask = mGnssSvIdUsedInPosition.bds_sv_used_ids_mask;
3579 }
3580 }
3581 break;
3582 case GNSS_SV_TYPE_GALILEO:
3583 if (mGnssSvIdUsedInPosAvail) {
3584 if (mGnssMbSvIdUsedInPosAvail) {
3585 switch (signalTypeMask) {
3586 case GNSS_SIGNAL_GALILEO_E1:
3587 svUsedIdMask = mGnssMbSvIdUsedInPosition.gal_e1_sv_used_ids_mask;
3588 break;
3589 case GNSS_SIGNAL_GALILEO_E5A:
3590 svUsedIdMask = mGnssMbSvIdUsedInPosition.gal_e5a_sv_used_ids_mask;
3591 break;
3592 case GNSS_SIGNAL_GALILEO_E5B:
3593 svUsedIdMask = mGnssMbSvIdUsedInPosition.gal_e5b_sv_used_ids_mask;
3594 break;
3595 }
3596 } else {
3597 svUsedIdMask = mGnssSvIdUsedInPosition.gal_sv_used_ids_mask;
3598 }
3599 }
3600 break;
3601 case GNSS_SV_TYPE_QZSS:
3602 if (mGnssSvIdUsedInPosAvail) {
3603 if (mGnssMbSvIdUsedInPosAvail) {
3604 switch (signalTypeMask) {
3605 case GNSS_SIGNAL_QZSS_L1CA:
3606 svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l1ca_sv_used_ids_mask;
3607 break;
3608 case GNSS_SIGNAL_QZSS_L1S:
3609 svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l1s_sv_used_ids_mask;
3610 break;
3611 case GNSS_SIGNAL_QZSS_L2:
3612 svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l2_sv_used_ids_mask;
3613 break;
3614 case GNSS_SIGNAL_QZSS_L5:
3615 svUsedIdMask = mGnssMbSvIdUsedInPosition.qzss_l5_sv_used_ids_mask;
3616 break;
3617 }
3618 } else {
3619 svUsedIdMask = mGnssSvIdUsedInPosition.qzss_sv_used_ids_mask;
3620 }
3621 }
3622 // QZSS SV id's need to reported as it is to framework, since
3623 // framework expects it as it is. See GnssStatus.java.
3624 // SV id passed to here by LocApi is 1-based.
3625 svNotify.gnssSvs[i].svId += (QZSS_SV_PRN_MIN - 1);
3626 break;
3627 case GNSS_SV_TYPE_NAVIC:
3628 if (mGnssSvIdUsedInPosAvail) {
3629 svUsedIdMask = mGnssSvIdUsedInPosition.navic_sv_used_ids_mask;
3630 }
3631 break;
3632 default:
3633 svUsedIdMask = 0;
3634 break;
3635 }
3636
3637 // If SV ID was used in previous position fix, then set USED_IN_FIX
3638 // flag, else clear the USED_IN_FIX flag.
3639 if ((gnssSvId < 64) && (svUsedIdMask & (1ULL << (gnssSvId - 1)))) {
3640 svNotify.gnssSvs[i].gnssSvOptionsMask |= GNSS_SV_OPTIONS_USED_IN_FIX_BIT;
3641 }
3642 }
3643
3644 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3645 if (nullptr != it->second.gnssSvCb) {
3646 it->second.gnssSvCb(svNotify);
3647 }
3648 }
3649
3650 if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER &&
3651 !mTimeBasedTrackingSessions.empty()) {
3652 std::vector<std::string> nmeaArraystr;
3653 loc_nmea_generate_sv(svNotify, nmeaArraystr);
3654 stringstream ss;
3655 for (auto itor = nmeaArraystr.begin(); itor != nmeaArraystr.end(); ++itor) {
3656 ss << *itor;
3657 }
3658 string s = ss.str();
3659 reportNmea(s.c_str(), s.length());
3660 }
3661
3662 mGnssSvIdUsedInPosAvail = false;
3663 }
3664
3665 void
reportNmeaEvent(const char * nmea,size_t length)3666 GnssAdapter::reportNmeaEvent(const char* nmea, size_t length)
3667 {
3668 if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER &&
3669 !loc_nmea_is_debug(nmea, length)) {
3670 return;
3671 }
3672
3673 struct MsgReportNmea : public LocMsg {
3674 GnssAdapter& mAdapter;
3675 const char* mNmea;
3676 size_t mLength;
3677 inline MsgReportNmea(GnssAdapter& adapter,
3678 const char* nmea,
3679 size_t length) :
3680 LocMsg(),
3681 mAdapter(adapter),
3682 mNmea(new char[length+1]),
3683 mLength(length) {
3684 if (mNmea == nullptr) {
3685 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
3686 return;
3687 }
3688 strlcpy((char*)mNmea, nmea, length+1);
3689 }
3690 inline virtual ~MsgReportNmea()
3691 {
3692 delete[] mNmea;
3693 }
3694 inline virtual void proc() const {
3695 // extract bug report info - this returns true if consumed by systemstatus
3696 bool ret = false;
3697 SystemStatus* s = mAdapter.getSystemStatus();
3698 if (nullptr != s) {
3699 ret = s->setNmeaString(mNmea, mLength);
3700 }
3701 if (false == ret) {
3702 // forward NMEA message to upper layer
3703 mAdapter.reportNmea(mNmea, mLength);
3704 }
3705 }
3706 };
3707
3708 sendMsg(new MsgReportNmea(*this, nmea, length));
3709 }
3710
3711 void
reportNmea(const char * nmea,size_t length)3712 GnssAdapter::reportNmea(const char* nmea, size_t length)
3713 {
3714 GnssNmeaNotification nmeaNotification = {};
3715 nmeaNotification.size = sizeof(GnssNmeaNotification);
3716
3717 struct timeval tv;
3718 gettimeofday(&tv, (struct timezone *) NULL);
3719 int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
3720 nmeaNotification.timestamp = now;
3721 nmeaNotification.nmea = nmea;
3722 nmeaNotification.length = length;
3723
3724 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3725 if (nullptr != it->second.gnssNmeaCb) {
3726 it->second.gnssNmeaCb(nmeaNotification);
3727 }
3728 }
3729 }
3730
3731 void
reportDataEvent(const GnssDataNotification & dataNotify,int msInWeek)3732 GnssAdapter::reportDataEvent(const GnssDataNotification& dataNotify,
3733 int msInWeek)
3734 {
3735 struct MsgReportData : public LocMsg {
3736 GnssAdapter& mAdapter;
3737 GnssDataNotification mDataNotify;
3738 int mMsInWeek;
3739 inline MsgReportData(GnssAdapter& adapter,
3740 const GnssDataNotification& dataNotify,
3741 int msInWeek) :
3742 LocMsg(),
3743 mAdapter(adapter),
3744 mDataNotify(dataNotify),
3745 mMsInWeek(msInWeek) {
3746 }
3747 inline virtual void proc() const {
3748 if (-1 != mMsInWeek) {
3749 mAdapter.getDataInformation((GnssDataNotification&)mDataNotify,
3750 mMsInWeek);
3751 }
3752 mAdapter.reportData((GnssDataNotification&)mDataNotify);
3753 }
3754 };
3755
3756 sendMsg(new MsgReportData(*this, dataNotify, msInWeek));
3757 }
3758
3759 void
reportData(GnssDataNotification & dataNotify)3760 GnssAdapter::reportData(GnssDataNotification& dataNotify)
3761 {
3762 for (int sig = 0; sig < GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES; sig++) {
3763 if (GNSS_LOC_DATA_JAMMER_IND_BIT ==
3764 (dataNotify.gnssDataMask[sig] & GNSS_LOC_DATA_JAMMER_IND_BIT)) {
3765 LOC_LOGv("jammerInd[%d]=%f", sig, dataNotify.jammerInd[sig]);
3766 }
3767 if (GNSS_LOC_DATA_AGC_BIT ==
3768 (dataNotify.gnssDataMask[sig] & GNSS_LOC_DATA_AGC_BIT)) {
3769 LOC_LOGv("agc[%d]=%f", sig, dataNotify.agc[sig]);
3770 }
3771 }
3772 for (auto it = mClientData.begin(); it != mClientData.end(); ++it) {
3773 if (nullptr != it->second.gnssDataCb) {
3774 it->second.gnssDataCb(dataNotify);
3775 }
3776 }
3777 }
3778
3779 bool
requestNiNotifyEvent(const GnssNiNotification & notify,const void * data,const LocInEmergency emergencyState)3780 GnssAdapter::requestNiNotifyEvent(const GnssNiNotification ¬ify, const void* data,
3781 const LocInEmergency emergencyState)
3782 {
3783 LOC_LOGI("%s]: notif_type: %d, timeout: %d, default_resp: %d"
3784 "requestor_id: %s (encoding: %d) text: %s text (encoding: %d) extras: %s",
3785 __func__, notify.type, notify.timeout, notify.timeoutResponse,
3786 notify.requestor, notify.requestorEncoding,
3787 notify.message, notify.messageEncoding, notify.extras);
3788
3789 struct MsgReportNiNotify : public LocMsg {
3790 GnssAdapter& mAdapter;
3791 LocApiBase& mApi;
3792 const GnssNiNotification mNotify;
3793 const void* mData;
3794 const LocInEmergency mEmergencyState;
3795 inline MsgReportNiNotify(GnssAdapter& adapter,
3796 LocApiBase& api,
3797 const GnssNiNotification& notify,
3798 const void* data,
3799 const LocInEmergency emergencyState) :
3800 LocMsg(),
3801 mAdapter(adapter),
3802 mApi(api),
3803 mNotify(notify),
3804 mData(data),
3805 mEmergencyState(emergencyState) {}
3806 inline virtual void proc() const {
3807 bool bIsInEmergency = false;
3808 bool bInformNiAccept = false;
3809
3810 bIsInEmergency = ((LOC_IN_EMERGENCY_UNKNOWN == mEmergencyState) &&
3811 mAdapter.getE911State()) || // older modems
3812 (LOC_IN_EMERGENCY_SET == mEmergencyState); // newer modems
3813
3814 if ((mAdapter.mSupportNfwControl || 0 == mAdapter.getAfwControlId()) &&
3815 (GNSS_NI_TYPE_SUPL == mNotify.type || GNSS_NI_TYPE_EMERGENCY_SUPL == mNotify.type)
3816 && !bIsInEmergency &&
3817 !(GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT & mNotify.options) &&
3818 (GNSS_CONFIG_GPS_LOCK_NI & ContextBase::mGps_conf.GPS_LOCK) &&
3819 1 == ContextBase::mGps_conf.NI_SUPL_DENY_ON_NFW_LOCKED) {
3820 /* If all these conditions are TRUE, then deny the NI Request:
3821 -'Q' Lock behavior OR 'P' Lock behavior and GNSS is Locked
3822 -NI SUPL Request type or NI SUPL Emergency Request type
3823 -NOT in an Emergency Call Session
3824 -NOT Privacy Override option
3825 -NFW is locked and config item NI_SUPL_DENY_ON_NFW_LOCKED = 1 */
3826 mApi.informNiResponse(GNSS_NI_RESPONSE_DENY, mData);
3827 } else if (GNSS_NI_TYPE_EMERGENCY_SUPL == mNotify.type) {
3828 bInformNiAccept = bIsInEmergency ||
3829 (GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO == ContextBase::mGps_conf.SUPL_ES);
3830
3831 if (bInformNiAccept) {
3832 mAdapter.requestNiNotify(mNotify, mData, bInformNiAccept);
3833 } else {
3834 mApi.informNiResponse(GNSS_NI_RESPONSE_DENY, mData);
3835 }
3836 } else if (GNSS_NI_TYPE_CONTROL_PLANE == mNotify.type) {
3837 if (bIsInEmergency && (1 == ContextBase::mGps_conf.CP_MTLR_ES)) {
3838 mApi.informNiResponse(GNSS_NI_RESPONSE_ACCEPT, mData);
3839 }
3840 else {
3841 mAdapter.requestNiNotify(mNotify, mData, false);
3842 }
3843 } else {
3844 mAdapter.requestNiNotify(mNotify, mData, false);
3845 }
3846 }
3847 };
3848
3849 sendMsg(new MsgReportNiNotify(*this, *mLocApi, notify, data, emergencyState));
3850
3851 return true;
3852 }
3853
3854 void
reportLocationSystemInfoEvent(const LocationSystemInfo & locationSystemInfo)3855 GnssAdapter::reportLocationSystemInfoEvent(const LocationSystemInfo & locationSystemInfo) {
3856
3857 // send system info to engine hub
3858 mEngHubProxy->gnssReportSystemInfo(locationSystemInfo);
3859
3860 struct MsgLocationSystemInfo : public LocMsg {
3861 GnssAdapter& mAdapter;
3862 LocationSystemInfo mSystemInfo;
3863 inline MsgLocationSystemInfo(GnssAdapter& adapter,
3864 const LocationSystemInfo& systemInfo) :
3865 LocMsg(),
3866 mAdapter(adapter),
3867 mSystemInfo(systemInfo) {}
3868 inline virtual void proc() const {
3869 mAdapter.reportLocationSystemInfo(mSystemInfo);
3870 }
3871 };
3872
3873 sendMsg(new MsgLocationSystemInfo(*this, locationSystemInfo));
3874 }
3875
3876 void
reportLocationSystemInfo(const LocationSystemInfo & locationSystemInfo)3877 GnssAdapter::reportLocationSystemInfo(const LocationSystemInfo & locationSystemInfo) {
3878 // save the info into the master copy piece by piece, as other system info
3879 // may come at different time
3880 if (locationSystemInfo.systemInfoMask & LOCATION_SYS_INFO_LEAP_SECOND) {
3881 mLocSystemInfo.systemInfoMask |= LOCATION_SYS_INFO_LEAP_SECOND;
3882
3883 const LeapSecondSystemInfo &srcLeapSecondSysInfo = locationSystemInfo.leapSecondSysInfo;
3884 LeapSecondSystemInfo &dstLeapSecondSysInfo = mLocSystemInfo.leapSecondSysInfo;
3885 if (srcLeapSecondSysInfo.leapSecondInfoMask &
3886 LEAP_SECOND_SYS_INFO_CURRENT_LEAP_SECONDS_BIT) {
3887 dstLeapSecondSysInfo.leapSecondInfoMask |=
3888 LEAP_SECOND_SYS_INFO_CURRENT_LEAP_SECONDS_BIT;
3889 dstLeapSecondSysInfo.leapSecondCurrent = srcLeapSecondSysInfo.leapSecondCurrent;
3890 }
3891 // once leap second change event is complete, modem may send up event invalidate the leap
3892 // second change info while AP is still processing report during leap second transition
3893 // so, we choose to keep this info around even though it is old
3894 if (srcLeapSecondSysInfo.leapSecondInfoMask & LEAP_SECOND_SYS_INFO_LEAP_SECOND_CHANGE_BIT) {
3895 dstLeapSecondSysInfo.leapSecondInfoMask |= LEAP_SECOND_SYS_INFO_LEAP_SECOND_CHANGE_BIT;
3896 dstLeapSecondSysInfo.leapSecondChangeInfo = srcLeapSecondSysInfo.leapSecondChangeInfo;
3897 }
3898 }
3899
3900 // we received new info, inform client of the newly received info
3901 if (locationSystemInfo.systemInfoMask) {
3902 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3903 if (it->second.locationSystemInfoCb != nullptr) {
3904 it->second.locationSystemInfoCb(locationSystemInfo);
3905 }
3906 }
3907 }
3908 }
3909
niThreadProc(void * args)3910 static void* niThreadProc(void *args)
3911 {
3912 NiSession* pSession = (NiSession*)args;
3913 int rc = 0; /* return code from pthread calls */
3914
3915 struct timespec present_time;
3916 struct timespec expire_time;
3917
3918 pthread_mutex_lock(&pSession->tLock);
3919 /* Calculate absolute expire time */
3920 clock_gettime(CLOCK_MONOTONIC, &present_time);
3921 expire_time.tv_sec = present_time.tv_sec + pSession->respTimeLeft;
3922 expire_time.tv_nsec = present_time.tv_nsec;
3923 LOC_LOGD("%s]: time out set for abs time %ld with delay %d sec",
3924 __func__, (long)expire_time.tv_sec, pSession->respTimeLeft);
3925
3926 while (!pSession->respRecvd) {
3927 rc = pthread_cond_timedwait(&pSession->tCond,
3928 &pSession->tLock,
3929 &expire_time);
3930 if (rc == ETIMEDOUT) {
3931 pSession->resp = GNSS_NI_RESPONSE_NO_RESPONSE;
3932 LOC_LOGD("%s]: time out after valting for specified time. Ret Val %d",
3933 __func__, rc);
3934 break;
3935 }
3936 }
3937 LOC_LOGD("%s]: Java layer has sent us a user response and return value from "
3938 "pthread_cond_timedwait = %d pSession->resp is %u", __func__, rc, pSession->resp);
3939 pSession->respRecvd = false; /* Reset the user response flag for the next session*/
3940
3941 // adding this check to support modem restart, in which case, we need the thread
3942 // to exit without calling sending data. We made sure that rawRequest is NULL in
3943 // loc_eng_ni_reset_on_engine_restart()
3944 GnssAdapter* adapter = pSession->adapter;
3945 GnssNiResponse resp;
3946 void* rawRequest = NULL;
3947 bool sendResponse = false;
3948
3949 if (NULL != pSession->rawRequest) {
3950 if (pSession->resp != GNSS_NI_RESPONSE_IGNORE) {
3951 resp = pSession->resp;
3952 rawRequest = pSession->rawRequest;
3953 sendResponse = true;
3954 } else {
3955 free(pSession->rawRequest);
3956 }
3957 pSession->rawRequest = NULL;
3958 }
3959 pthread_mutex_unlock(&pSession->tLock);
3960
3961 pSession->respTimeLeft = 0;
3962 pSession->reqID = 0;
3963
3964 if (sendResponse) {
3965 adapter->gnssNiResponseCommand(resp, rawRequest);
3966 }
3967
3968 return NULL;
3969 }
3970
3971 bool
requestNiNotify(const GnssNiNotification & notify,const void * data,const bool bInformNiAccept)3972 GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data,
3973 const bool bInformNiAccept)
3974 {
3975 NiSession* pSession = NULL;
3976 gnssNiCallback gnssNiCb = nullptr;
3977
3978 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
3979 if (nullptr != it->second.gnssNiCb) {
3980 gnssNiCb = it->second.gnssNiCb;
3981 break;
3982 }
3983 }
3984 if (nullptr == gnssNiCb) {
3985 if (GNSS_NI_TYPE_EMERGENCY_SUPL == notify.type) {
3986 if (bInformNiAccept) {
3987 mLocApi->informNiResponse(GNSS_NI_RESPONSE_ACCEPT, data);
3988 NiData& niData = getNiData();
3989 // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
3990 if (NULL != niData.session.rawRequest) {
3991 pthread_mutex_lock(&niData.session.tLock);
3992 niData.session.resp = GNSS_NI_RESPONSE_IGNORE;
3993 niData.session.respRecvd = true;
3994 pthread_cond_signal(&niData.session.tCond);
3995 pthread_mutex_unlock(&niData.session.tLock);
3996 }
3997 }
3998 }
3999 EXIT_LOG(%s, "no clients with gnssNiCb.");
4000 return false;
4001 }
4002
4003 if (notify.type == GNSS_NI_TYPE_EMERGENCY_SUPL) {
4004 if (NULL != mNiData.sessionEs.rawRequest) {
4005 LOC_LOGI("%s]: supl es NI in progress, new supl es NI ignored, type: %d",
4006 __func__, notify.type);
4007 if (NULL != data) {
4008 free((void*)data);
4009 }
4010 } else {
4011 pSession = &mNiData.sessionEs;
4012 }
4013 } else {
4014 if (NULL != mNiData.session.rawRequest ||
4015 NULL != mNiData.sessionEs.rawRequest) {
4016 LOC_LOGI("%s]: supl NI in progress, new supl NI ignored, type: %d",
4017 __func__, notify.type);
4018 if (NULL != data) {
4019 free((void*)data);
4020 }
4021 } else {
4022 pSession = &mNiData.session;
4023 }
4024 }
4025
4026 if (pSession) {
4027 /* Save request */
4028 pSession->rawRequest = (void*)data;
4029 pSession->reqID = ++mNiData.reqIDCounter;
4030 pSession->adapter = this;
4031
4032 int sessionId = pSession->reqID;
4033
4034 /* For robustness, spawn a thread at this point to timeout to clear up the notification
4035 * status, even though the OEM layer in java does not do so.
4036 **/
4037 pSession->respTimeLeft =
4038 5 + (notify.timeout != 0 ? notify.timeout : LOC_NI_NO_RESPONSE_TIME);
4039
4040 int rc = 0;
4041 rc = pthread_create(&pSession->thread, NULL, niThreadProc, pSession);
4042 if (rc) {
4043 LOC_LOGE("%s]: Loc NI thread is not created.", __func__);
4044 }
4045 rc = pthread_detach(pSession->thread);
4046 if (rc) {
4047 LOC_LOGE("%s]: Loc NI thread is not detached.", __func__);
4048 }
4049
4050 if (nullptr != gnssNiCb) {
4051 gnssNiCb(sessionId, notify);
4052 }
4053 }
4054
4055 return true;
4056 }
4057
4058 void
reportGnssMeasurementsEvent(const GnssMeasurements & gnssMeasurements,int msInWeek)4059 GnssAdapter::reportGnssMeasurementsEvent(const GnssMeasurements& gnssMeasurements,
4060 int msInWeek)
4061 {
4062 LOC_LOGD("%s]: msInWeek=%d", __func__, msInWeek);
4063
4064 if (0 != gnssMeasurements.gnssMeasNotification.count) {
4065 struct MsgReportGnssMeasurementData : public LocMsg {
4066 GnssAdapter& mAdapter;
4067 GnssMeasurements mGnssMeasurements;
4068 GnssMeasurementsNotification mMeasurementsNotify;
4069 inline MsgReportGnssMeasurementData(GnssAdapter& adapter,
4070 const GnssMeasurements& gnssMeasurements,
4071 int msInWeek) :
4072 LocMsg(),
4073 mAdapter(adapter),
4074 mMeasurementsNotify(gnssMeasurements.gnssMeasNotification) {
4075 if (-1 != msInWeek) {
4076 mAdapter.getAgcInformation(mMeasurementsNotify, msInWeek);
4077 }
4078 }
4079 inline virtual void proc() const {
4080 mAdapter.reportGnssMeasurementData(mMeasurementsNotify);
4081 }
4082 };
4083
4084 sendMsg(new MsgReportGnssMeasurementData(*this, gnssMeasurements, msInWeek));
4085 }
4086 mEngHubProxy->gnssReportSvMeasurement(gnssMeasurements.gnssSvMeasurementSet);
4087 }
4088
4089 void
reportGnssMeasurementData(const GnssMeasurementsNotification & measurements)4090 GnssAdapter::reportGnssMeasurementData(const GnssMeasurementsNotification& measurements)
4091 {
4092 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
4093 if (nullptr != it->second.gnssMeasurementsCb) {
4094 it->second.gnssMeasurementsCb(measurements);
4095 }
4096 }
4097 }
4098
4099 void
reportSvPolynomialEvent(GnssSvPolynomial & svPolynomial)4100 GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial)
4101 {
4102 LOC_LOGD("%s]: ", __func__);
4103 mEngHubProxy->gnssReportSvPolynomial(svPolynomial);
4104 }
4105
4106 void
reportSvEphemerisEvent(GnssSvEphemerisReport & svEphemeris)4107 GnssAdapter::reportSvEphemerisEvent(GnssSvEphemerisReport & svEphemeris)
4108 {
4109 LOC_LOGD("%s]:", __func__);
4110 mEngHubProxy->gnssReportSvEphemeris(svEphemeris);
4111 }
4112
4113
4114 bool
requestOdcpiEvent(OdcpiRequestInfo & request)4115 GnssAdapter::requestOdcpiEvent(OdcpiRequestInfo& request)
4116 {
4117 struct MsgRequestOdcpi : public LocMsg {
4118 GnssAdapter& mAdapter;
4119 OdcpiRequestInfo mOdcpiRequest;
4120 inline MsgRequestOdcpi(GnssAdapter& adapter, OdcpiRequestInfo& request) :
4121 LocMsg(),
4122 mAdapter(adapter),
4123 mOdcpiRequest(request) {}
4124 inline virtual void proc() const {
4125 mAdapter.requestOdcpi(mOdcpiRequest);
4126 }
4127 };
4128
4129 sendMsg(new MsgRequestOdcpi(*this, request));
4130 return true;
4131 }
4132
requestOdcpi(const OdcpiRequestInfo & request)4133 void GnssAdapter::requestOdcpi(const OdcpiRequestInfo& request)
4134 {
4135 if (nullptr != mOdcpiRequestCb) {
4136 LOC_LOGd("request: type %d, tbf %d, isEmergency %d"
4137 " requestActive: %d timerActive: %d",
4138 request.type, request.tbfMillis, request.isEmergencyMode,
4139 mOdcpiRequestActive, mOdcpiTimer.isActive());
4140 // ODCPI START and ODCPI STOP from modem can come in quick succession
4141 // so the mOdcpiTimer helps avoid spamming the framework as well as
4142 // extending the odcpi session past 30 seconds if needed
4143 if (ODCPI_REQUEST_TYPE_START == request.type) {
4144 if (false == mOdcpiRequestActive && false == mOdcpiTimer.isActive()) {
4145 mOdcpiRequestCb(request);
4146 mOdcpiRequestActive = true;
4147 mOdcpiTimer.start();
4148 // if the current active odcpi session is non-emergency, and the new
4149 // odcpi request is emergency, replace the odcpi request with new request
4150 // and restart the timer
4151 } else if (false == mOdcpiRequest.isEmergencyMode &&
4152 true == request.isEmergencyMode) {
4153 mOdcpiRequestCb(request);
4154 mOdcpiRequestActive = true;
4155 if (true == mOdcpiTimer.isActive()) {
4156 mOdcpiTimer.restart();
4157 } else {
4158 mOdcpiTimer.start();
4159 }
4160 // if ODCPI request is not active but the timer is active, then
4161 // just update the active state and wait for timer to expire
4162 // before requesting new ODCPI to avoid spamming ODCPI requests
4163 } else if (false == mOdcpiRequestActive && true == mOdcpiTimer.isActive()) {
4164 mOdcpiRequestActive = true;
4165 }
4166 mOdcpiRequest = request;
4167 // the request is being stopped, but allow timer to expire first
4168 // before stopping the timer just in case more ODCPI requests come
4169 // to avoid spamming more odcpi requests to the framework
4170 } else {
4171 mOdcpiRequestActive = false;
4172 }
4173 } else {
4174 LOC_LOGw("ODCPI request not supported");
4175 }
4176 }
4177
reportDeleteAidingDataEvent(GnssAidingData & aidingData)4178 bool GnssAdapter::reportDeleteAidingDataEvent(GnssAidingData& aidingData)
4179 {
4180 LOC_LOGD("%s]:", __func__);
4181 mEngHubProxy->gnssDeleteAidingData(aidingData);
4182 return true;
4183 }
4184
reportKlobucharIonoModelEvent(GnssKlobucharIonoModel & ionoModel)4185 bool GnssAdapter::reportKlobucharIonoModelEvent(GnssKlobucharIonoModel & ionoModel)
4186 {
4187 LOC_LOGD("%s]:", __func__);
4188 mEngHubProxy->gnssReportKlobucharIonoModel(ionoModel);
4189 return true;
4190 }
4191
reportGnssAdditionalSystemInfoEvent(GnssAdditionalSystemInfo & additionalSystemInfo)4192 bool GnssAdapter::reportGnssAdditionalSystemInfoEvent(
4193 GnssAdditionalSystemInfo & additionalSystemInfo)
4194 {
4195 LOC_LOGD("%s]:", __func__);
4196 mEngHubProxy->gnssReportAdditionalSystemInfo(additionalSystemInfo);
4197 return true;
4198 }
4199
initOdcpiCommand(const OdcpiRequestCallback & callback)4200 void GnssAdapter::initOdcpiCommand(const OdcpiRequestCallback& callback)
4201 {
4202 struct MsgInitOdcpi : public LocMsg {
4203 GnssAdapter& mAdapter;
4204 OdcpiRequestCallback mOdcpiCb;
4205 inline MsgInitOdcpi(GnssAdapter& adapter,
4206 const OdcpiRequestCallback& callback) :
4207 LocMsg(),
4208 mAdapter(adapter),
4209 mOdcpiCb(callback) {}
4210 inline virtual void proc() const {
4211 mAdapter.initOdcpi(mOdcpiCb);
4212 }
4213 };
4214
4215 sendMsg(new MsgInitOdcpi(*this, callback));
4216 }
4217
initOdcpi(const OdcpiRequestCallback & callback)4218 void GnssAdapter::initOdcpi(const OdcpiRequestCallback& callback)
4219 {
4220 mOdcpiRequestCb = callback;
4221
4222 /* Register for WIFI request */
4223 updateEvtMask(LOC_API_ADAPTER_BIT_REQUEST_WIFI,
4224 LOC_REGISTRATION_MASK_ENABLED);
4225 }
4226
injectOdcpiCommand(const Location & location)4227 void GnssAdapter::injectOdcpiCommand(const Location& location)
4228 {
4229 struct MsgInjectOdcpi : public LocMsg {
4230 GnssAdapter& mAdapter;
4231 Location mLocation;
4232 inline MsgInjectOdcpi(GnssAdapter& adapter, const Location& location) :
4233 LocMsg(),
4234 mAdapter(adapter),
4235 mLocation(location) {}
4236 inline virtual void proc() const {
4237 mAdapter.injectOdcpi(mLocation);
4238 }
4239 };
4240
4241 sendMsg(new MsgInjectOdcpi(*this, location));
4242 }
4243
injectOdcpi(const Location & location)4244 void GnssAdapter::injectOdcpi(const Location& location)
4245 {
4246 LOC_LOGd("ODCPI Injection: requestActive: %d timerActive: %d"
4247 "lat %.7f long %.7f",
4248 mOdcpiRequestActive, mOdcpiTimer.isActive(),
4249 location.latitude, location.longitude);
4250
4251 mLocApi->injectPosition(location, true);
4252 }
4253
4254 // Called in the context of LocTimer thread
timeOutCallback()4255 void OdcpiTimer::timeOutCallback()
4256 {
4257 if (nullptr != mAdapter) {
4258 mAdapter->odcpiTimerExpireEvent();
4259 }
4260 }
4261
4262 // Called in the context of LocTimer thread
odcpiTimerExpireEvent()4263 void GnssAdapter::odcpiTimerExpireEvent()
4264 {
4265 struct MsgOdcpiTimerExpire : public LocMsg {
4266 GnssAdapter& mAdapter;
4267 inline MsgOdcpiTimerExpire(GnssAdapter& adapter) :
4268 LocMsg(),
4269 mAdapter(adapter) {}
4270 inline virtual void proc() const {
4271 mAdapter.odcpiTimerExpire();
4272 }
4273 };
4274 sendMsg(new MsgOdcpiTimerExpire(*this));
4275 }
odcpiTimerExpire()4276 void GnssAdapter::odcpiTimerExpire()
4277 {
4278 LOC_LOGd("requestActive: %d timerActive: %d",
4279 mOdcpiRequestActive, mOdcpiTimer.isActive());
4280
4281 // if ODCPI request is still active after timer
4282 // expires, request again and restart timer
4283 if (mOdcpiRequestActive) {
4284 mOdcpiRequestCb(mOdcpiRequest);
4285 mOdcpiTimer.restart();
4286 } else {
4287 mOdcpiTimer.stop();
4288 }
4289 }
4290
4291 void
invokeGnssEnergyConsumedCallback(uint64_t energyConsumedSinceFirstBoot)4292 GnssAdapter::invokeGnssEnergyConsumedCallback(uint64_t energyConsumedSinceFirstBoot) {
4293 if (mGnssEnergyConsumedCb) {
4294 mGnssEnergyConsumedCb(energyConsumedSinceFirstBoot);
4295 mGnssEnergyConsumedCb = nullptr;
4296 }
4297 }
4298
4299 bool
reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot)4300 GnssAdapter::reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot){
4301 LOC_LOGD("%s]: %" PRIu64 " ", __func__, energyConsumedSinceFirstBoot);
4302
4303 struct MsgReportGnssGnssEngEnergyConsumed : public LocMsg {
4304 GnssAdapter& mAdapter;
4305 uint64_t mGnssEnergyConsumedSinceFirstBoot;
4306 inline MsgReportGnssGnssEngEnergyConsumed(GnssAdapter& adapter,
4307 uint64_t energyConsumed) :
4308 LocMsg(),
4309 mAdapter(adapter),
4310 mGnssEnergyConsumedSinceFirstBoot(energyConsumed) {}
4311 inline virtual void proc() const {
4312 mAdapter.invokeGnssEnergyConsumedCallback(mGnssEnergyConsumedSinceFirstBoot);
4313 }
4314 };
4315
4316 sendMsg(new MsgReportGnssGnssEngEnergyConsumed(*this, energyConsumedSinceFirstBoot));
4317 return true;
4318 }
4319
initDefaultAgps()4320 void GnssAdapter::initDefaultAgps() {
4321 LOC_LOGD("%s]: ", __func__);
4322
4323 void *handle = nullptr;
4324 if ((handle = dlopen("libloc_net_iface.so", RTLD_NOW)) == nullptr) {
4325 LOC_LOGD("%s]: libloc_net_iface.so not found !", __func__);
4326 return;
4327 }
4328
4329 LocAgpsGetAgpsCbInfo getAgpsCbInfo = (LocAgpsGetAgpsCbInfo)
4330 dlsym(handle, "LocNetIfaceAgps_getAgpsCbInfo");
4331 if (getAgpsCbInfo == nullptr) {
4332 LOC_LOGE("%s]: Failed to get method LocNetIfaceAgps_getStatusCb", __func__);
4333 dlclose(handle);
4334 return;
4335 }
4336
4337 AgpsCbInfo& cbInfo = getAgpsCbInfo(agpsOpenResultCb, agpsCloseResultCb, this);
4338
4339 if (cbInfo.statusV4Cb == nullptr) {
4340 LOC_LOGE("%s]: statusV4Cb is nullptr!", __func__);
4341 dlclose(handle);
4342 return;
4343 }
4344
4345 initAgps(cbInfo);
4346 }
4347
initDefaultAgpsCommand()4348 void GnssAdapter::initDefaultAgpsCommand() {
4349 LOC_LOGD("%s]: ", __func__);
4350
4351 struct MsgInitDefaultAgps : public LocMsg {
4352 GnssAdapter& mAdapter;
4353 inline MsgInitDefaultAgps(GnssAdapter& adapter) :
4354 LocMsg(),
4355 mAdapter(adapter) {
4356 }
4357 inline virtual void proc() const {
4358 mAdapter.initDefaultAgps();
4359 }
4360 };
4361
4362 sendMsg(new MsgInitDefaultAgps(*this));
4363 }
4364
4365 /* INIT LOC AGPS MANAGER */
4366
initAgps(const AgpsCbInfo & cbInfo)4367 void GnssAdapter::initAgps(const AgpsCbInfo& cbInfo) {
4368 LOC_LOGD("%s]:cbInfo.atlType - %d", __func__, cbInfo.atlType);
4369
4370 if (!((ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSB) ||
4371 (ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSA))) {
4372 return;
4373 }
4374
4375 mAgpsManager.createAgpsStateMachines(cbInfo);
4376 /* Register for AGPS event mask */
4377 updateEvtMask(LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST,
4378 LOC_REGISTRATION_MASK_ENABLED);
4379 }
4380
initAgpsCommand(const AgpsCbInfo & cbInfo)4381 void GnssAdapter::initAgpsCommand(const AgpsCbInfo& cbInfo){
4382 LOC_LOGI("GnssAdapter::initAgpsCommand");
4383
4384 /* Message to initialize AGPS module */
4385 struct AgpsMsgInit: public LocMsg {
4386 const AgpsCbInfo mCbInfo;
4387 GnssAdapter& mAdapter;
4388
4389 inline AgpsMsgInit(const AgpsCbInfo& cbInfo,
4390 GnssAdapter& adapter) :
4391 LocMsg(), mCbInfo(cbInfo), mAdapter(adapter) {
4392 LOC_LOGV("AgpsMsgInit");
4393 }
4394
4395 inline virtual void proc() const {
4396 LOC_LOGV("AgpsMsgInit::proc()");
4397 mAdapter.initAgps(mCbInfo);
4398 }
4399 };
4400
4401 /* Send message to initialize AGPS Manager */
4402 sendMsg(new AgpsMsgInit(cbInfo, *this));
4403 }
4404
initNfwCommand(const NfwCbInfo & cbInfo)4405 void GnssAdapter::initNfwCommand(const NfwCbInfo& cbInfo) {
4406 LOC_LOGi("GnssAdapter::initNfwCommand");
4407
4408 /* Message to initialize NFW */
4409 struct MsgInitNfw : public LocMsg {
4410 const NfwCbInfo mCbInfo;
4411 GnssAdapter& mAdapter;
4412
4413 inline MsgInitNfw(const NfwCbInfo& cbInfo,
4414 GnssAdapter& adapter) :
4415 LocMsg(), mCbInfo(cbInfo), mAdapter(adapter) {
4416 LOC_LOGv("MsgInitNfw");
4417 }
4418
4419 inline virtual void proc() const {
4420 LOC_LOGv("MsgInitNfw::proc()");
4421 mAdapter.initNfw(mCbInfo);
4422 }
4423 };
4424
4425 /* Send message to initialize NFW */
4426 sendMsg(new MsgInitNfw(cbInfo, *this));
4427 }
4428
reportNfwNotificationEvent(GnssNfwNotification & notification)4429 void GnssAdapter::reportNfwNotificationEvent(GnssNfwNotification& notification) {
4430 LOC_LOGi("GnssAdapter::reportNfwNotificationEvent");
4431
4432 struct MsgReportNfwNotification : public LocMsg {
4433 const GnssNfwNotification mNotification;
4434 GnssAdapter& mAdapter;
4435
4436 inline MsgReportNfwNotification(const GnssNfwNotification& notification,
4437 GnssAdapter& adapter) :
4438 LocMsg(), mNotification(notification), mAdapter(adapter) {
4439 LOC_LOGv("MsgReportNfwNotification");
4440 }
4441
4442 inline virtual void proc() const {
4443 LOC_LOGv("MsgReportNfwNotification::proc()");
4444 mAdapter.reportNfwNotification(mNotification);
4445 }
4446 };
4447
4448 sendMsg(new MsgReportNfwNotification(notification, *this));
4449 }
4450
4451 /* GnssAdapter::requestATL
4452 * Method triggered in QMI thread as part of handling below message:
4453 * eQMI_LOC_SERVER_REQUEST_OPEN_V02
4454 * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
4455 * eQMI_LOC_WWAN_TYPE_INTERNET_V02
4456 * eQMI_LOC_WWAN_TYPE_AGNSS_V02
4457 * eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02 */
requestATL(int connHandle,LocAGpsType agpsType,LocApnTypeMask apnTypeMask)4458 bool GnssAdapter::requestATL(int connHandle, LocAGpsType agpsType,
4459 LocApnTypeMask apnTypeMask){
4460
4461 LOC_LOGI("GnssAdapter::requestATL handle=%d agpsType=0x%X apnTypeMask=0x%X",
4462 connHandle, agpsType, apnTypeMask);
4463
4464 sendMsg( new AgpsMsgRequestATL(
4465 &mAgpsManager, connHandle, (AGpsExtType)agpsType,
4466 apnTypeMask));
4467
4468 return true;
4469 }
4470
4471 /* GnssAdapter::releaseATL
4472 * Method triggered in QMI thread as part of handling below message:
4473 * eQMI_LOC_SERVER_REQUEST_CLOSE_V02
4474 * Triggers teardown of an existing AGPS call */
releaseATL(int connHandle)4475 bool GnssAdapter::releaseATL(int connHandle){
4476
4477 LOC_LOGI("GnssAdapter::releaseATL");
4478
4479 /* Release SUPL/INTERNET/SUPL_ES ATL */
4480 struct AgpsMsgReleaseATL: public LocMsg {
4481
4482 AgpsManager* mAgpsManager;
4483 int mConnHandle;
4484
4485 inline AgpsMsgReleaseATL(AgpsManager* agpsManager, int connHandle) :
4486 LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle) {
4487
4488 LOC_LOGV("AgpsMsgReleaseATL");
4489 }
4490
4491 inline virtual void proc() const {
4492
4493 LOC_LOGV("AgpsMsgReleaseATL::proc()");
4494 mAgpsManager->releaseATL(mConnHandle);
4495 }
4496 };
4497
4498 sendMsg( new AgpsMsgReleaseATL(&mAgpsManager, connHandle));
4499
4500 return true;
4501 }
4502
dataConnOpenCommand(AGpsExtType agpsType,const char * apnName,int apnLen,AGpsBearerType bearerType)4503 void GnssAdapter::dataConnOpenCommand(
4504 AGpsExtType agpsType,
4505 const char* apnName, int apnLen, AGpsBearerType bearerType){
4506
4507 LOC_LOGI("GnssAdapter::frameworkDataConnOpen");
4508
4509 struct AgpsMsgAtlOpenSuccess: public LocMsg {
4510
4511 AgpsManager* mAgpsManager;
4512 AGpsExtType mAgpsType;
4513 char* mApnName;
4514 int mApnLen;
4515 AGpsBearerType mBearerType;
4516
4517 inline AgpsMsgAtlOpenSuccess(AgpsManager* agpsManager, AGpsExtType agpsType,
4518 const char* apnName, int apnLen, AGpsBearerType bearerType) :
4519 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType), mApnName(
4520 new char[apnLen + 1]), mApnLen(apnLen), mBearerType(bearerType) {
4521
4522 LOC_LOGV("AgpsMsgAtlOpenSuccess");
4523 if (mApnName == nullptr) {
4524 LOC_LOGE("%s] new allocation failed, fatal error.", __func__);
4525 // Reporting the failure here
4526 mAgpsManager->reportAtlClosed(mAgpsType);
4527 return;
4528 }
4529 memcpy(mApnName, apnName, apnLen);
4530 mApnName[apnLen] = 0;
4531 }
4532
4533 inline ~AgpsMsgAtlOpenSuccess() {
4534 delete[] mApnName;
4535 }
4536
4537 inline virtual void proc() const {
4538
4539 LOC_LOGV("AgpsMsgAtlOpenSuccess::proc()");
4540 mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, mApnLen, mBearerType);
4541 }
4542 };
4543 // Added inital length checks for apnlen check to avoid security issues
4544 // In case of failure reporting the same
4545 if (NULL == apnName || apnLen <= 0 || apnLen > MAX_APN_LEN || (strlen(apnName) != apnLen)) {
4546 LOC_LOGe("%s]: incorrect apnlen length or incorrect apnName", __func__);
4547 mAgpsManager.reportAtlClosed(agpsType);
4548 } else {
4549 sendMsg( new AgpsMsgAtlOpenSuccess(
4550 &mAgpsManager, agpsType, apnName, apnLen, bearerType));
4551 }
4552 }
4553
dataConnClosedCommand(AGpsExtType agpsType)4554 void GnssAdapter::dataConnClosedCommand(AGpsExtType agpsType){
4555
4556 LOC_LOGI("GnssAdapter::frameworkDataConnClosed");
4557
4558 struct AgpsMsgAtlClosed: public LocMsg {
4559
4560 AgpsManager* mAgpsManager;
4561 AGpsExtType mAgpsType;
4562
4563 inline AgpsMsgAtlClosed(AgpsManager* agpsManager, AGpsExtType agpsType) :
4564 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
4565
4566 LOC_LOGV("AgpsMsgAtlClosed");
4567 }
4568
4569 inline virtual void proc() const {
4570
4571 LOC_LOGV("AgpsMsgAtlClosed::proc()");
4572 mAgpsManager->reportAtlClosed(mAgpsType);
4573 }
4574 };
4575
4576 sendMsg( new AgpsMsgAtlClosed(&mAgpsManager, (AGpsExtType)agpsType));
4577 }
4578
dataConnFailedCommand(AGpsExtType agpsType)4579 void GnssAdapter::dataConnFailedCommand(AGpsExtType agpsType){
4580
4581 LOC_LOGI("GnssAdapter::frameworkDataConnFailed");
4582
4583 struct AgpsMsgAtlOpenFailed: public LocMsg {
4584
4585 AgpsManager* mAgpsManager;
4586 AGpsExtType mAgpsType;
4587
4588 inline AgpsMsgAtlOpenFailed(AgpsManager* agpsManager, AGpsExtType agpsType) :
4589 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
4590
4591 LOC_LOGV("AgpsMsgAtlOpenFailed");
4592 }
4593
4594 inline virtual void proc() const {
4595
4596 LOC_LOGV("AgpsMsgAtlOpenFailed::proc()");
4597 mAgpsManager->reportAtlOpenFailed(mAgpsType);
4598 }
4599 };
4600
4601 sendMsg( new AgpsMsgAtlOpenFailed(&mAgpsManager, (AGpsExtType)agpsType));
4602 }
4603
convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo> & out,const GnssSvType & in_constellation,const SystemStatusReports & in)4604 void GnssAdapter::convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo>& out,
4605 const GnssSvType& in_constellation,
4606 const SystemStatusReports& in)
4607 {
4608 uint64_t sv_mask = 0ULL;
4609 uint32_t svid_min = 0;
4610 uint32_t svid_num = 0;
4611 uint32_t svid_idx = 0;
4612
4613 uint64_t eph_health_good_mask = 0ULL;
4614 uint64_t eph_health_bad_mask = 0ULL;
4615 uint64_t server_perdiction_available_mask = 0ULL;
4616 float server_perdiction_age = 0.0f;
4617
4618 // set constellationi based parameters
4619 switch (in_constellation) {
4620 case GNSS_SV_TYPE_GPS:
4621 svid_min = GNSS_BUGREPORT_GPS_MIN;
4622 svid_num = GPS_NUM;
4623 svid_idx = 0;
4624 if (!in.mSvHealth.empty()) {
4625 eph_health_good_mask = in.mSvHealth.back().mGpsGoodMask;
4626 eph_health_bad_mask = in.mSvHealth.back().mGpsBadMask;
4627 }
4628 if (!in.mXtra.empty()) {
4629 server_perdiction_available_mask = in.mXtra.back().mGpsXtraValid;
4630 server_perdiction_age = (float)(in.mXtra.back().mGpsXtraAge);
4631 }
4632 break;
4633 case GNSS_SV_TYPE_GLONASS:
4634 svid_min = GNSS_BUGREPORT_GLO_MIN;
4635 svid_num = GLO_NUM;
4636 svid_idx = GPS_NUM;
4637 if (!in.mSvHealth.empty()) {
4638 eph_health_good_mask = in.mSvHealth.back().mGloGoodMask;
4639 eph_health_bad_mask = in.mSvHealth.back().mGloBadMask;
4640 }
4641 if (!in.mXtra.empty()) {
4642 server_perdiction_available_mask = in.mXtra.back().mGloXtraValid;
4643 server_perdiction_age = (float)(in.mXtra.back().mGloXtraAge);
4644 }
4645 break;
4646 case GNSS_SV_TYPE_QZSS:
4647 svid_min = GNSS_BUGREPORT_QZSS_MIN;
4648 svid_num = QZSS_NUM;
4649 svid_idx = GPS_NUM+GLO_NUM+BDS_NUM+GAL_NUM;
4650 if (!in.mSvHealth.empty()) {
4651 eph_health_good_mask = in.mSvHealth.back().mQzssGoodMask;
4652 eph_health_bad_mask = in.mSvHealth.back().mQzssBadMask;
4653 }
4654 if (!in.mXtra.empty()) {
4655 server_perdiction_available_mask = in.mXtra.back().mQzssXtraValid;
4656 server_perdiction_age = (float)(in.mXtra.back().mQzssXtraAge);
4657 }
4658 break;
4659 case GNSS_SV_TYPE_BEIDOU:
4660 svid_min = GNSS_BUGREPORT_BDS_MIN;
4661 svid_num = BDS_NUM;
4662 svid_idx = GPS_NUM+GLO_NUM;
4663 if (!in.mSvHealth.empty()) {
4664 eph_health_good_mask = in.mSvHealth.back().mBdsGoodMask;
4665 eph_health_bad_mask = in.mSvHealth.back().mBdsBadMask;
4666 }
4667 if (!in.mXtra.empty()) {
4668 server_perdiction_available_mask = in.mXtra.back().mBdsXtraValid;
4669 server_perdiction_age = (float)(in.mXtra.back().mBdsXtraAge);
4670 }
4671 break;
4672 case GNSS_SV_TYPE_GALILEO:
4673 svid_min = GNSS_BUGREPORT_GAL_MIN;
4674 svid_num = GAL_NUM;
4675 svid_idx = GPS_NUM+GLO_NUM+BDS_NUM;
4676 if (!in.mSvHealth.empty()) {
4677 eph_health_good_mask = in.mSvHealth.back().mGalGoodMask;
4678 eph_health_bad_mask = in.mSvHealth.back().mGalBadMask;
4679 }
4680 if (!in.mXtra.empty()) {
4681 server_perdiction_available_mask = in.mXtra.back().mGalXtraValid;
4682 server_perdiction_age = (float)(in.mXtra.back().mGalXtraAge);
4683 }
4684 break;
4685 case GNSS_SV_TYPE_NAVIC:
4686 svid_min = GNSS_BUGREPORT_NAVIC_MIN;
4687 svid_num = NAVIC_NUM;
4688 svid_idx = GPS_NUM+GLO_NUM+QZSS_NUM+BDS_NUM+GAL_NUM;
4689 if (!in.mSvHealth.empty()) {
4690 eph_health_good_mask = in.mSvHealth.back().mNavicGoodMask;
4691 eph_health_bad_mask = in.mSvHealth.back().mNavicBadMask;
4692 }
4693 if (!in.mXtra.empty()) {
4694 server_perdiction_available_mask = in.mXtra.back().mNavicXtraValid;
4695 server_perdiction_age = (float)(in.mXtra.back().mNavicXtraAge);
4696 }
4697 break;
4698 default:
4699 return;
4700 }
4701
4702 // extract each sv info from systemstatus report
4703 for(uint32_t i=0; i<svid_num && (svid_idx+i)<SV_ALL_NUM; i++) {
4704
4705 GnssDebugSatelliteInfo s = {};
4706 s.size = sizeof(s);
4707 s.svid = i + svid_min;
4708 s.constellation = in_constellation;
4709
4710 if (!in.mNavData.empty()) {
4711 s.mEphemerisType = in.mNavData.back().mNav[svid_idx+i].mType;
4712 s.mEphemerisSource = in.mNavData.back().mNav[svid_idx+i].mSource;
4713 }
4714 else {
4715 s.mEphemerisType = GNSS_EPH_TYPE_UNKNOWN;
4716 s.mEphemerisSource = GNSS_EPH_SOURCE_UNKNOWN;
4717 }
4718
4719 sv_mask = 0x1ULL << i;
4720 if (eph_health_good_mask & sv_mask) {
4721 s.mEphemerisHealth = GNSS_EPH_HEALTH_GOOD;
4722 }
4723 else if (eph_health_bad_mask & sv_mask) {
4724 s.mEphemerisHealth = GNSS_EPH_HEALTH_BAD;
4725 }
4726 else {
4727 s.mEphemerisHealth = GNSS_EPH_HEALTH_UNKNOWN;
4728 }
4729
4730 if (!in.mNavData.empty()) {
4731 s.ephemerisAgeSeconds =
4732 (float)(in.mNavData.back().mNav[svid_idx+i].mAgeSec);
4733 }
4734 else {
4735 s.ephemerisAgeSeconds = 0.0f;
4736 }
4737
4738 if (server_perdiction_available_mask & sv_mask) {
4739 s.serverPredictionIsAvailable = true;
4740 }
4741 else {
4742 s.serverPredictionIsAvailable = false;
4743 }
4744
4745 s.serverPredictionAgeSeconds = server_perdiction_age;
4746 out.push_back(s);
4747 }
4748
4749 return;
4750 }
4751
getDebugReport(GnssDebugReport & r)4752 bool GnssAdapter::getDebugReport(GnssDebugReport& r)
4753 {
4754 LOC_LOGD("%s]: ", __func__);
4755
4756 SystemStatus* systemstatus = getSystemStatus();
4757 if (nullptr == systemstatus) {
4758 return false;
4759 }
4760
4761 SystemStatusReports reports = {};
4762 systemstatus->getReport(reports, true);
4763
4764 r.size = sizeof(r);
4765
4766 // location block
4767 r.mLocation.size = sizeof(r.mLocation);
4768 if(!reports.mLocation.empty() && reports.mLocation.back().mValid) {
4769 r.mLocation.mValid = true;
4770 r.mLocation.mLocation.latitude =
4771 reports.mLocation.back().mLocation.gpsLocation.latitude;
4772 r.mLocation.mLocation.longitude =
4773 reports.mLocation.back().mLocation.gpsLocation.longitude;
4774 r.mLocation.mLocation.altitude =
4775 reports.mLocation.back().mLocation.gpsLocation.altitude;
4776 r.mLocation.mLocation.speed =
4777 (double)(reports.mLocation.back().mLocation.gpsLocation.speed);
4778 r.mLocation.mLocation.bearing =
4779 (double)(reports.mLocation.back().mLocation.gpsLocation.bearing);
4780 r.mLocation.mLocation.accuracy =
4781 (double)(reports.mLocation.back().mLocation.gpsLocation.accuracy);
4782
4783 r.mLocation.verticalAccuracyMeters =
4784 reports.mLocation.back().mLocationEx.vert_unc;
4785 r.mLocation.speedAccuracyMetersPerSecond =
4786 reports.mLocation.back().mLocationEx.speed_unc;
4787 r.mLocation.bearingAccuracyDegrees =
4788 reports.mLocation.back().mLocationEx.bearing_unc;
4789
4790 r.mLocation.mUtcReported =
4791 reports.mLocation.back().mUtcReported;
4792 }
4793 else if(!reports.mBestPosition.empty() && reports.mBestPosition.back().mValid) {
4794 r.mLocation.mValid = true;
4795 r.mLocation.mLocation.latitude =
4796 (double)(reports.mBestPosition.back().mBestLat) * RAD2DEG;
4797 r.mLocation.mLocation.longitude =
4798 (double)(reports.mBestPosition.back().mBestLon) * RAD2DEG;
4799 r.mLocation.mLocation.altitude = reports.mBestPosition.back().mBestAlt;
4800 r.mLocation.mLocation.accuracy =
4801 (double)(reports.mBestPosition.back().mBestHepe);
4802
4803 r.mLocation.mUtcReported = reports.mBestPosition.back().mUtcReported;
4804 }
4805 else {
4806 r.mLocation.mValid = false;
4807 }
4808
4809 if (r.mLocation.mValid) {
4810 LOC_LOGV("getDebugReport - lat=%f lon=%f alt=%f speed=%f",
4811 r.mLocation.mLocation.latitude,
4812 r.mLocation.mLocation.longitude,
4813 r.mLocation.mLocation.altitude,
4814 r.mLocation.mLocation.speed);
4815 }
4816
4817 // time block
4818 r.mTime.size = sizeof(r.mTime);
4819 if(!reports.mTimeAndClock.empty() && reports.mTimeAndClock.back().mTimeValid) {
4820 r.mTime.mValid = true;
4821 r.mTime.timeEstimate =
4822 (((int64_t)(reports.mTimeAndClock.back().mGpsWeek)*7 +
4823 GNSS_UTC_TIME_OFFSET)*24*60*60 -
4824 (int64_t)(reports.mTimeAndClock.back().mLeapSeconds))*1000ULL +
4825 (int64_t)(reports.mTimeAndClock.back().mGpsTowMs);
4826
4827 if (reports.mTimeAndClock.back().mTimeUncNs > 0) {
4828 // TimeUncNs value is available
4829 r.mTime.timeUncertaintyNs =
4830 (float)(reports.mTimeAndClock.back().mLeapSecUnc)*1000.0f +
4831 (float)(reports.mTimeAndClock.back().mTimeUncNs);
4832 } else {
4833 // fall back to legacy TimeUnc
4834 r.mTime.timeUncertaintyNs =
4835 ((float)(reports.mTimeAndClock.back().mTimeUnc) +
4836 (float)(reports.mTimeAndClock.back().mLeapSecUnc))*1000.0f;
4837 }
4838
4839 r.mTime.frequencyUncertaintyNsPerSec =
4840 (float)(reports.mTimeAndClock.back().mClockFreqBiasUnc);
4841 LOC_LOGV("getDebugReport - timeestimate=%" PRIu64 " unc=%f frequnc=%f",
4842 r.mTime.timeEstimate,
4843 r.mTime.timeUncertaintyNs, r.mTime.frequencyUncertaintyNsPerSec);
4844 }
4845 else {
4846 r.mTime.mValid = false;
4847 }
4848
4849 // satellite info block
4850 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GPS, reports);
4851 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GLONASS, reports);
4852 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_QZSS, reports);
4853 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_BEIDOU, reports);
4854 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GALILEO, reports);
4855 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_NAVIC, reports);
4856 LOC_LOGV("getDebugReport - satellite=%zu", r.mSatelliteInfo.size());
4857
4858 return true;
4859 }
4860
4861 /* get AGC information from system status and fill it */
4862 void
getAgcInformation(GnssMeasurementsNotification & measurements,int msInWeek)4863 GnssAdapter::getAgcInformation(GnssMeasurementsNotification& measurements, int msInWeek)
4864 {
4865 SystemStatus* systemstatus = getSystemStatus();
4866
4867 if (nullptr != systemstatus) {
4868 SystemStatusReports reports = {};
4869 systemstatus->getReport(reports, true);
4870
4871 if ((!reports.mRfAndParams.empty()) && (!reports.mTimeAndClock.empty()) &&
4872 (abs(msInWeek - (int)reports.mTimeAndClock.back().mGpsTowMs) < 2000)) {
4873
4874 for (size_t i = 0; i < measurements.count; i++) {
4875 switch (measurements.measurements[i].svType) {
4876 case GNSS_SV_TYPE_GPS:
4877 case GNSS_SV_TYPE_QZSS:
4878 measurements.measurements[i].agcLevelDb =
4879 reports.mRfAndParams.back().mAgcGps;
4880 measurements.measurements[i].flags |=
4881 GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
4882 break;
4883
4884 case GNSS_SV_TYPE_GALILEO:
4885 measurements.measurements[i].agcLevelDb =
4886 reports.mRfAndParams.back().mAgcGal;
4887 measurements.measurements[i].flags |=
4888 GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
4889 break;
4890
4891 case GNSS_SV_TYPE_GLONASS:
4892 measurements.measurements[i].agcLevelDb =
4893 reports.mRfAndParams.back().mAgcGlo;
4894 measurements.measurements[i].flags |=
4895 GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
4896 break;
4897
4898 case GNSS_SV_TYPE_BEIDOU:
4899 measurements.measurements[i].agcLevelDb =
4900 reports.mRfAndParams.back().mAgcBds;
4901 measurements.measurements[i].flags |=
4902 GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT;
4903 break;
4904
4905 case GNSS_SV_TYPE_SBAS:
4906 case GNSS_SV_TYPE_UNKNOWN:
4907 default:
4908 break;
4909 }
4910 }
4911 }
4912 }
4913 }
4914
4915 /* get Data information from system status and fill it */
4916 void
getDataInformation(GnssDataNotification & data,int msInWeek)4917 GnssAdapter::getDataInformation(GnssDataNotification& data, int msInWeek)
4918 {
4919 SystemStatus* systemstatus = getSystemStatus();
4920
4921 LOC_LOGV("%s]: msInWeek=%d", __func__, msInWeek);
4922 if (nullptr != systemstatus) {
4923 SystemStatusReports reports = {};
4924 systemstatus->getReport(reports, true);
4925
4926 if ((!reports.mRfAndParams.empty()) && (!reports.mTimeAndClock.empty()) &&
4927 (abs(msInWeek - (int)reports.mTimeAndClock.back().mGpsTowMs) < 2000)) {
4928
4929 for (int sig = GNSS_LOC_SIGNAL_TYPE_GPS_L1CA;
4930 sig < GNSS_LOC_MAX_NUMBER_OF_SIGNAL_TYPES; sig++) {
4931 data.gnssDataMask[sig] = 0;
4932 data.jammerInd[sig] = 0.0;
4933 data.agc[sig] = 0.0;
4934 }
4935 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcGps) {
4936 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] |=
4937 GNSS_LOC_DATA_AGC_BIT;
4938 data.agc[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] =
4939 reports.mRfAndParams.back().mAgcGps;
4940 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] |=
4941 GNSS_LOC_DATA_AGC_BIT;
4942 data.agc[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] =
4943 reports.mRfAndParams.back().mAgcGps;
4944 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] |=
4945 GNSS_LOC_DATA_AGC_BIT;
4946 data.agc[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] =
4947 reports.mRfAndParams.back().mAgcGps;
4948 }
4949 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGps) {
4950 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] |=
4951 GNSS_LOC_DATA_JAMMER_IND_BIT;
4952 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GPS_L1CA] =
4953 (double)reports.mRfAndParams.back().mJammerGps;
4954 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] |=
4955 GNSS_LOC_DATA_JAMMER_IND_BIT;
4956 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_QZSS_L1CA] =
4957 (double)reports.mRfAndParams.back().mJammerGps;
4958 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] |=
4959 GNSS_LOC_DATA_JAMMER_IND_BIT;
4960 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_SBAS_L1_CA] =
4961 (double)reports.mRfAndParams.back().mJammerGps;
4962 }
4963 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcGlo) {
4964 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] |=
4965 GNSS_LOC_DATA_AGC_BIT;
4966 data.agc[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] =
4967 reports.mRfAndParams.back().mAgcGlo;
4968 }
4969 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGlo) {
4970 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] |=
4971 GNSS_LOC_DATA_JAMMER_IND_BIT;
4972 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GLONASS_G1] =
4973 (double)reports.mRfAndParams.back().mJammerGlo;
4974 }
4975 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcBds) {
4976 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] |=
4977 GNSS_LOC_DATA_AGC_BIT;
4978 data.agc[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] =
4979 reports.mRfAndParams.back().mAgcBds;
4980 }
4981 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerBds) {
4982 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] |=
4983 GNSS_LOC_DATA_JAMMER_IND_BIT;
4984 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_BEIDOU_B1_I] =
4985 (double)reports.mRfAndParams.back().mJammerBds;
4986 }
4987 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mAgcGal) {
4988 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] |=
4989 GNSS_LOC_DATA_AGC_BIT;
4990 data.agc[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] =
4991 reports.mRfAndParams.back().mAgcGal;
4992 }
4993 if (GNSS_INVALID_JAMMER_IND != reports.mRfAndParams.back().mJammerGal) {
4994 data.gnssDataMask[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] |=
4995 GNSS_LOC_DATA_JAMMER_IND_BIT;
4996 data.jammerInd[GNSS_LOC_SIGNAL_TYPE_GALILEO_E1_C] =
4997 (double)reports.mRfAndParams.back().mJammerGal;
4998 }
4999 }
5000 }
5001 }
5002
5003 /* Callbacks registered with loc_net_iface library */
agpsOpenResultCb(bool isSuccess,AGpsExtType agpsType,const char * apn,AGpsBearerType bearerType,void * userDataPtr)5004 static void agpsOpenResultCb (bool isSuccess, AGpsExtType agpsType, const char* apn,
5005 AGpsBearerType bearerType, void* userDataPtr) {
5006 LOC_LOGD("%s]: ", __func__);
5007 if (userDataPtr == nullptr) {
5008 LOC_LOGE("%s]: userDataPtr is nullptr.", __func__);
5009 return;
5010 }
5011 if (apn == nullptr) {
5012 LOC_LOGE("%s]: apn is nullptr.", __func__);
5013 return;
5014 }
5015 GnssAdapter* adapter = (GnssAdapter*)userDataPtr;
5016 if (isSuccess) {
5017 adapter->dataConnOpenCommand(agpsType, apn, strlen(apn), bearerType);
5018 } else {
5019 adapter->dataConnFailedCommand(agpsType);
5020 }
5021 }
5022
agpsCloseResultCb(bool isSuccess,AGpsExtType agpsType,void * userDataPtr)5023 static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userDataPtr) {
5024 LOC_LOGD("%s]: ", __func__);
5025 if (userDataPtr == nullptr) {
5026 LOC_LOGE("%s]: userDataPtr is nullptr.", __func__);
5027 return;
5028 }
5029 GnssAdapter* adapter = (GnssAdapter*)userDataPtr;
5030 if (isSuccess) {
5031 adapter->dataConnClosedCommand(agpsType);
5032 } else {
5033 adapter->dataConnFailedCommand(agpsType);
5034 }
5035 }
5036
5037 void
saveGnssEnergyConsumedCallback(GnssEnergyConsumedCallback energyConsumedCb)5038 GnssAdapter::saveGnssEnergyConsumedCallback(GnssEnergyConsumedCallback energyConsumedCb) {
5039 mGnssEnergyConsumedCb = energyConsumedCb;
5040 }
5041
5042 void
getGnssEnergyConsumedCommand(GnssEnergyConsumedCallback energyConsumedCb)5043 GnssAdapter::getGnssEnergyConsumedCommand(GnssEnergyConsumedCallback energyConsumedCb) {
5044 struct MsgGetGnssEnergyConsumed : public LocMsg {
5045 GnssAdapter& mAdapter;
5046 LocApiBase& mApi;
5047 GnssEnergyConsumedCallback mEnergyConsumedCb;
5048 inline MsgGetGnssEnergyConsumed(GnssAdapter& adapter, LocApiBase& api,
5049 GnssEnergyConsumedCallback energyConsumedCb) :
5050 LocMsg(),
5051 mAdapter(adapter),
5052 mApi(api),
5053 mEnergyConsumedCb(energyConsumedCb){}
5054 inline virtual void proc() const {
5055 mAdapter.saveGnssEnergyConsumedCallback(mEnergyConsumedCb);
5056 mApi.getGnssEnergyConsumed();
5057 }
5058 };
5059
5060 sendMsg(new MsgGetGnssEnergyConsumed(*this, *mLocApi, energyConsumedCb));
5061 }
5062
5063 void
nfwControlCommand(bool enable)5064 GnssAdapter::nfwControlCommand(bool enable) {
5065 struct MsgControlNfwLocationAccess : public LocMsg {
5066 GnssAdapter& mAdapter;
5067 LocApiBase& mApi;
5068 bool mEnable;
5069 inline MsgControlNfwLocationAccess(GnssAdapter& adapter, LocApiBase& api,
5070 bool enable) :
5071 LocMsg(),
5072 mAdapter(adapter),
5073 mApi(api),
5074 mEnable(enable) {}
5075 inline virtual void proc() const {
5076 GnssConfigGpsLock gpsLock;
5077
5078 gpsLock = ContextBase::mGps_conf.GPS_LOCK;
5079 if (mEnable) {
5080 gpsLock &= ~GNSS_CONFIG_GPS_LOCK_NI;
5081 } else {
5082 gpsLock |= GNSS_CONFIG_GPS_LOCK_NI;
5083 }
5084 ContextBase::mGps_conf.GPS_LOCK = gpsLock;
5085 mApi.sendMsg(new LocApiMsg([&mApi = mApi, gpsLock]() {
5086 mApi.setGpsLockSync((GnssConfigGpsLock)gpsLock);
5087 }));
5088 }
5089 };
5090
5091 if (mSupportNfwControl) {
5092 sendMsg(new MsgControlNfwLocationAccess(*this, *mLocApi, enable));
5093 } else {
5094 LOC_LOGw("NFW control is not supported, do not use this for NFW");
5095 }
5096 }
5097
5098 // Set tunc constrained mode, use 0 session id to indicate
5099 // that no callback is needed. Session id 0 is used for calls that
5100 // are not invoked from the integration api, e.g.: initial configuration
5101 // from the configure file
5102 void
setConstrainedTunc(bool enable,float tuncConstraint,uint32_t energyBudget,uint32_t sessionId)5103 GnssAdapter::setConstrainedTunc(bool enable, float tuncConstraint,
5104 uint32_t energyBudget, uint32_t sessionId) {
5105
5106 mLocConfigInfo.tuncConfigInfo.isValid = true;
5107 mLocConfigInfo.tuncConfigInfo.enable = enable;
5108 mLocConfigInfo.tuncConfigInfo.tuncThresholdMs = tuncConstraint;
5109 mLocConfigInfo.tuncConfigInfo.energyBudget = energyBudget;
5110
5111 LocApiResponse* locApiResponse = nullptr;
5112 if (sessionId != 0) {
5113 locApiResponse =
5114 new LocApiResponse(*getContext(),
5115 [this, sessionId] (LocationError err) {
5116 reportResponse(err, sessionId);});
5117 if (!locApiResponse) {
5118 LOC_LOGe("memory alloc failed");
5119 }
5120 }
5121 mLocApi->setConstrainedTuncMode(
5122 enable, tuncConstraint, energyBudget, locApiResponse);
5123 }
5124
5125 uint32_t
setConstrainedTuncCommand(bool enable,float tuncConstraint,uint32_t energyBudget)5126 GnssAdapter::setConstrainedTuncCommand (bool enable, float tuncConstraint,
5127 uint32_t energyBudget) {
5128 // generated session id will be none-zero
5129 uint32_t sessionId = generateSessionId();
5130 LOC_LOGd("session id %u", sessionId);
5131
5132 struct MsgEnableTUNC : public LocMsg {
5133 GnssAdapter& mAdapter;
5134 uint32_t mSessionId;
5135 bool mEnable;
5136 float mTuncConstraint;
5137 uint32_t mEnergyBudget;
5138
5139 inline MsgEnableTUNC(GnssAdapter& adapter,
5140 uint32_t sessionId,
5141 bool enable,
5142 float tuncConstraint,
5143 uint32_t energyBudget) :
5144 LocMsg(),
5145 mAdapter(adapter),
5146 mSessionId(sessionId),
5147 mEnable(enable),
5148 mTuncConstraint(tuncConstraint),
5149 mEnergyBudget(energyBudget) {}
5150 inline virtual void proc() const {
5151 mAdapter.setConstrainedTunc(mEnable, mTuncConstraint,
5152 mEnergyBudget, mSessionId);
5153 }
5154 };
5155
5156 sendMsg(new MsgEnableTUNC(*this, sessionId, enable,
5157 tuncConstraint, energyBudget));
5158
5159 return sessionId;
5160 }
5161
5162 // Set position assisted clock estimator, use 0 session id to indicate
5163 // that no callback is needed. Session id 0 is used for calls that are
5164 // not invoked from the integration api, e.g.: initial configuration
5165 // from the configure file.
5166 void
setPositionAssistedClockEstimator(bool enable,uint32_t sessionId)5167 GnssAdapter::setPositionAssistedClockEstimator(bool enable,
5168 uint32_t sessionId) {
5169
5170 mLocConfigInfo.paceConfigInfo.isValid = true;
5171 mLocConfigInfo.paceConfigInfo.enable = enable;
5172 LocApiResponse* locApiResponse = nullptr;
5173 if (sessionId != 0) {
5174 locApiResponse =
5175 new LocApiResponse(*getContext(),
5176 [this, sessionId] (LocationError err) {
5177 reportResponse(err, sessionId);});
5178 if (!locApiResponse) {
5179 LOC_LOGe("memory alloc failed");
5180 }
5181 }
5182 mLocApi->setPositionAssistedClockEstimatorMode(enable, locApiResponse);
5183 }
5184
5185 uint32_t
setPositionAssistedClockEstimatorCommand(bool enable)5186 GnssAdapter::setPositionAssistedClockEstimatorCommand(bool enable) {
5187 // generated session id will be none-zero
5188 uint32_t sessionId = generateSessionId();
5189 LOC_LOGd("session id %u", sessionId);
5190
5191 struct MsgEnablePACE : public LocMsg {
5192 GnssAdapter& mAdapter;
5193 uint32_t mSessionId;
5194 bool mEnable;
5195 inline MsgEnablePACE(GnssAdapter& adapter,
5196 uint32_t sessionId, bool enable) :
5197 LocMsg(),
5198 mAdapter(adapter),
5199 mSessionId(sessionId),
5200 mEnable(enable){}
5201 inline virtual void proc() const {
5202 mAdapter.setPositionAssistedClockEstimator(mEnable, mSessionId);
5203 }
5204 };
5205
5206 sendMsg(new MsgEnablePACE(*this, sessionId, enable));
5207 return sessionId;
5208 }
5209
5210 void
updateSvConfig(uint32_t sessionId,const GnssSvTypeConfig & svTypeConfig,const GnssSvIdConfig & svIdConfig)5211 GnssAdapter::updateSvConfig(uint32_t sessionId,
5212 const GnssSvTypeConfig& svTypeConfig,
5213 const GnssSvIdConfig& svIdConfig) {
5214
5215 // check whether if any constellation is removed from the new config
5216 GnssSvTypesMask enabledRemoved = mGnssSvTypeConfig.enabledSvTypesMask &
5217 (mGnssSvTypeConfig.enabledSvTypesMask ^ svTypeConfig.enabledSvTypesMask);
5218 // Send reset if any constellation is removed from the enabled list
5219 if (enabledRemoved != 0) {
5220 mLocApi->resetConstellationControl();
5221 }
5222
5223 mGnssSvTypeConfig = svTypeConfig;
5224 mGnssSvIdConfig = svIdConfig;
5225
5226 // Send blacklist info
5227 mLocApi->setBlacklistSv(mGnssSvIdConfig);
5228
5229 // Send only enabled constellation config
5230 GnssSvTypeConfig svTypeConfigCopy = {sizeof(GnssSvTypeConfig), 0, 0};
5231 svTypeConfigCopy.enabledSvTypesMask = mGnssSvTypeConfig.enabledSvTypesMask;
5232 LocApiResponse* locApiResponse = new LocApiResponse(*getContext(),
5233 [this, sessionId] (LocationError err) {
5234 reportResponse(err, sessionId);});
5235 if (!locApiResponse) {
5236 LOC_LOGe("memory alloc failed");
5237 }
5238 mLocApi->setConstellationControl(svTypeConfigCopy, locApiResponse);
5239 }
5240
gnssUpdateSvConfigCommand(const GnssSvTypeConfig & svTypeConfig,const GnssSvIdConfig & svIdConfig)5241 uint32_t GnssAdapter::gnssUpdateSvConfigCommand(
5242 const GnssSvTypeConfig& svTypeConfig,
5243 const GnssSvIdConfig& svIdConfig) {
5244
5245 // generated session id will be none-zero
5246 uint32_t sessionId = generateSessionId();
5247 LOC_LOGd("session id %u", sessionId);
5248
5249 struct MsgUpdateSvConfig : public LocMsg {
5250 GnssAdapter& mAdapter;
5251 uint32_t mSessionId;
5252 GnssSvTypeConfig mSvTypeConfig;
5253 GnssSvIdConfig mSvIdConfig;
5254
5255 inline MsgUpdateSvConfig(GnssAdapter& adapter,
5256 uint32_t sessionId,
5257 const GnssSvTypeConfig& svTypeConfig,
5258 const GnssSvIdConfig& svIdConfig) :
5259 LocMsg(),
5260 mAdapter(adapter),
5261 mSessionId(sessionId),
5262 mSvTypeConfig(svTypeConfig),
5263 mSvIdConfig(svIdConfig) {}
5264 inline virtual void proc() const {
5265 mAdapter.updateSvConfig(mSessionId, mSvTypeConfig, mSvIdConfig);
5266 }
5267 };
5268
5269 if (sessionId != 0) {
5270 sendMsg(new MsgUpdateSvConfig(*this, sessionId,
5271 svTypeConfig, svIdConfig));
5272 }
5273 return sessionId;
5274 }
5275
5276 void
resetSvConfig(uint32_t sessionId)5277 GnssAdapter::resetSvConfig(uint32_t sessionId) {
5278
5279 LocApiResponse* locApiResponse = nullptr;
5280 if (sessionId != 0) {
5281 locApiResponse =
5282 new LocApiResponse(*getContext(),
5283 [this, sessionId] (LocationError err) {
5284 reportResponse(err, sessionId);});
5285 if (!locApiResponse) {
5286 LOC_LOGe("memory alloc failed");
5287 }
5288 }
5289 mLocApi->resetConstellationControl(locApiResponse);
5290 }
5291
gnssResetSvConfigCommand()5292 uint32_t GnssAdapter::gnssResetSvConfigCommand() {
5293
5294 // generated session id will be none-zero
5295 uint32_t sessionId = generateSessionId();
5296 LOC_LOGd("session id %u", sessionId);
5297
5298 struct MsgResetSvConfig : public LocMsg {
5299 GnssAdapter& mAdapter;
5300 uint32_t mSessionId;
5301
5302 inline MsgResetSvConfig(GnssAdapter& adapter,
5303 uint32_t sessionId) :
5304 LocMsg(),
5305 mAdapter(adapter),
5306 mSessionId(sessionId) {}
5307 inline virtual void proc() const {
5308 mAdapter.resetSvConfig(mSessionId);
5309 }
5310 };
5311
5312 sendMsg(new MsgResetSvConfig(*this, sessionId));
5313 return sessionId;
5314 }
5315
5316 void
configLeverArm(uint32_t sessionId,const LeverArmConfigInfo & configInfo)5317 GnssAdapter::configLeverArm(uint32_t sessionId,
5318 const LeverArmConfigInfo& configInfo) {
5319
5320 LocationError err = LOCATION_ERROR_NOT_SUPPORTED;
5321 if (true == mEngHubProxy->configLeverArm(configInfo)) {
5322 err = LOCATION_ERROR_SUCCESS;
5323 }
5324 reportResponse(err, sessionId);
5325 }
5326
5327 uint32_t
configLeverArmCommand(const LeverArmConfigInfo & configInfo)5328 GnssAdapter::configLeverArmCommand(const LeverArmConfigInfo& configInfo) {
5329
5330 // generated session id will be none-zero
5331 uint32_t sessionId = generateSessionId();
5332 LOC_LOGd("session id %u", sessionId);
5333
5334 struct MsgConfigLeverArm : public LocMsg {
5335 GnssAdapter& mAdapter;
5336 uint32_t mSessionId;
5337 LeverArmConfigInfo mConfigInfo;
5338
5339 inline MsgConfigLeverArm(GnssAdapter& adapter,
5340 uint32_t sessionId,
5341 const LeverArmConfigInfo& configInfo) :
5342 LocMsg(),
5343 mAdapter(adapter),
5344 mSessionId(sessionId),
5345 mConfigInfo(configInfo) {}
5346 inline virtual void proc() const {
5347 mAdapter.configLeverArm(mSessionId, mConfigInfo);
5348 }
5349 };
5350
5351 sendMsg(new MsgConfigLeverArm(*this, sessionId, configInfo));
5352 return sessionId;
5353 }
5354
5355 /* ==== Eng Hub Proxy ================================================================= */
5356 /* ======== UTILITIES ================================================================= */
5357 void
initEngHubProxyCommand()5358 GnssAdapter::initEngHubProxyCommand() {
5359 LOC_LOGD("%s]: ", __func__);
5360
5361 struct MsgInitEngHubProxy : public LocMsg {
5362 GnssAdapter* mAdapter;
5363 inline MsgInitEngHubProxy(GnssAdapter* adapter) :
5364 LocMsg(),
5365 mAdapter(adapter) {}
5366 inline virtual void proc() const {
5367 mAdapter->initEngHubProxy();
5368 }
5369 };
5370
5371 sendMsg(new MsgInitEngHubProxy(this));
5372 }
5373
5374 bool
initEngHubProxy()5375 GnssAdapter::initEngHubProxy() {
5376 static bool firstTime = true;
5377 static bool engHubLoadSuccessful = false;
5378
5379 const char *error = nullptr;
5380 unsigned int processListLength = 0;
5381 loc_process_info_s_type* processInfoList = nullptr;
5382
5383 do {
5384 // load eng hub only once
5385 if (firstTime == false) {
5386 break;
5387 }
5388
5389 int rc = loc_read_process_conf(LOC_PATH_IZAT_CONF, &processListLength,
5390 &processInfoList);
5391 if (rc != 0) {
5392 LOC_LOGE("%s]: failed to parse conf file", __func__);
5393 break;
5394 }
5395
5396 bool pluginDaemonEnabled = false;
5397 // go over the conf table to see whether any plugin daemon is enabled
5398 for (unsigned int i = 0; i < processListLength; i++) {
5399 if ((strncmp(processInfoList[i].name[0], PROCESS_NAME_ENGINE_SERVICE,
5400 strlen(PROCESS_NAME_ENGINE_SERVICE)) == 0) &&
5401 (processInfoList[i].proc_status == ENABLED)) {
5402 pluginDaemonEnabled = true;
5403 break;
5404 }
5405 }
5406
5407 // no plugin daemon is enabled for this platform, no need to load eng hub .so
5408 if (pluginDaemonEnabled == false) {
5409 break;
5410 }
5411
5412 // load the engine hub .so, if the .so is not present
5413 // all EngHubProxyBase calls will turn into no-op.
5414 void *handle = nullptr;
5415 if ((handle = dlopen("libloc_eng_hub.so", RTLD_NOW)) == nullptr) {
5416 if ((error = dlerror()) != nullptr) {
5417 LOC_LOGE("%s]: libloc_eng_hub.so not found %s !", __func__, error);
5418 }
5419 break;
5420 }
5421
5422 // prepare the callback functions
5423 // callback function for engine hub to report back position event
5424 GnssAdapterReportEnginePositionsEventCb reportPositionEventCb =
5425 [this](int count, EngineLocationInfo* locationArr) {
5426 // report from engine hub on behalf of PPE will be treated as fromUlp
5427 reportEnginePositionsEvent(count, locationArr);
5428 };
5429
5430 // callback function for engine hub to report back sv event
5431 GnssAdapterReportSvEventCb reportSvEventCb =
5432 [this](const GnssSvNotification& svNotify, bool fromEngineHub) {
5433 reportSvEvent(svNotify, fromEngineHub);
5434 };
5435
5436 // callback function for engine hub to request for complete aiding data
5437 GnssAdapterReqAidingDataCb reqAidingDataCb =
5438 [this] (const GnssAidingDataSvMask& svDataMask) {
5439 mLocApi->requestForAidingData(svDataMask);
5440 };
5441
5442 GnssAdapterUpdateNHzRequirementCb updateNHzRequirementCb =
5443 [this] (bool nHzNeeded, bool nHzMeasNeeded) {
5444
5445 if (nHzMeasNeeded &&
5446 (!checkMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT))) {
5447 updateEvtMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT,
5448 LOC_REGISTRATION_MASK_ENABLED);
5449 } else if (checkMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT)) {
5450 updateEvtMask(LOC_API_ADAPTER_BIT_GNSS_NHZ_MEASUREMENT,
5451 LOC_REGISTRATION_MASK_DISABLED);
5452 }
5453
5454 if (mNHzNeeded != nHzNeeded) {
5455 mNHzNeeded = nHzNeeded;
5456 checkAndRestartTimeBasedSession();
5457 }
5458 };
5459
5460 getEngHubProxyFn* getter = (getEngHubProxyFn*) dlsym(handle, "getEngHubProxy");
5461 if(getter != nullptr) {
5462 EngineHubProxyBase* hubProxy = (*getter) (mMsgTask, mSystemStatus->getOsObserver(),
5463 reportPositionEventCb,
5464 reportSvEventCb, reqAidingDataCb,
5465 updateNHzRequirementCb);
5466 if (hubProxy != nullptr) {
5467 mEngHubProxy = hubProxy;
5468 engHubLoadSuccessful = true;
5469 }
5470 }
5471 else {
5472 LOC_LOGD("%s]: entered, did not find function", __func__);
5473 }
5474
5475 LOC_LOGD("%s]: first time initialization %d, returned %d",
5476 __func__, firstTime, engHubLoadSuccessful);
5477
5478 } while (0);
5479
5480 if (processInfoList != nullptr) {
5481 free (processInfoList);
5482 processInfoList = nullptr;
5483 }
5484
5485 firstTime = false;
5486 return engHubLoadSuccessful;
5487 }
5488