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