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