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