• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2017, 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_TAG "LocSvc_GnssAdapter"
30 
31 #include <sys/stat.h>
32 #include <errno.h>
33 #include <ctype.h>
34 #include <cutils/properties.h>
35 #include <math.h>
36 #include <arpa/inet.h>
37 #include <netinet/in.h>
38 #include <netdb.h>
39 #include <GnssAdapter.h>
40 #include <string>
41 #include <loc_log.h>
42 #include <loc_nmea.h>
43 #include <Agps.h>
44 #include <SystemStatus.h>
45 
46 #include <loc_nmea.h>
47 #include <vector>
48 #include <string>
49 
50 #define RAD2DEG    (180.0 / M_PI)
51 
52 using namespace loc_core;
53 
GnssAdapter()54 GnssAdapter::GnssAdapter() :
55     LocAdapterBase(0,
56                    LocDualContext::getLocFgContext(NULL,
57                                                    NULL,
58                                                    LocDualContext::mLocationHalName,
59                                                    false)),
60     mUlpProxy(new UlpProxyBase()),
61     mUlpPositionMode(),
62     mGnssSvIdUsedInPosition(),
63     mGnssSvIdUsedInPosAvail(false),
64     mControlCallbacks(),
65     mPowerVoteId(0),
66     mNiData(),
67     mAgpsManager()
68 {
69     LOC_LOGD("%s]: Constructor %p", __func__, this);
70     mUlpPositionMode.mode = LOC_POSITION_MODE_INVALID;
71     readConfigCommand();
72     setConfigCommand();
73 
74 }
75 
76 inline
~GnssAdapter()77 GnssAdapter::~GnssAdapter()
78 {
79     LOC_LOGD("%s]: Destructor", __func__);
80     delete mUlpProxy;
81 }
82 
83 void
setControlCallbacksCommand(LocationControlCallbacks & controlCallbacks)84 GnssAdapter::setControlCallbacksCommand(LocationControlCallbacks& controlCallbacks)
85 {
86     struct MsgSetControlCallbacks : public LocMsg {
87         GnssAdapter& mAdapter;
88         const LocationControlCallbacks mControlCallbacks;
89         inline MsgSetControlCallbacks(GnssAdapter& adapter,
90                                       LocationControlCallbacks& controlCallbacks) :
91             LocMsg(),
92             mAdapter(adapter),
93             mControlCallbacks(controlCallbacks) {}
94         inline virtual void proc() const {
95             mAdapter.setControlCallbacks(mControlCallbacks);
96         }
97     };
98 
99     sendMsg(new MsgSetControlCallbacks(*this, controlCallbacks));
100 }
101 
102 void
convertOptions(LocPosMode & out,const LocationOptions & options)103 GnssAdapter::convertOptions(LocPosMode& out, const LocationOptions& options)
104 {
105     LocPosMode locPosMode = {};
106     switch (options.mode) {
107     case GNSS_SUPL_MODE_MSB:
108         out.mode = LOC_POSITION_MODE_MS_BASED;
109         break;
110     case GNSS_SUPL_MODE_MSA:
111         out.mode = LOC_POSITION_MODE_MS_ASSISTED;
112         break;
113     default:
114         out.mode = LOC_POSITION_MODE_STANDALONE;
115         break;
116     }
117     out.share_position = true;
118     out.min_interval = options.minInterval;
119 }
120 
121 void
convertLocation(Location & out,const LocGpsLocation & locGpsLocation,const GpsLocationExtended & locationExtended,const LocPosTechMask techMask)122 GnssAdapter::convertLocation(Location& out, const LocGpsLocation& locGpsLocation,
123                              const GpsLocationExtended& locationExtended,
124                              const LocPosTechMask techMask)
125 {
126     out.size = sizeof(Location);
127     if (LOC_GPS_LOCATION_HAS_LAT_LONG & locGpsLocation.flags) {
128         out.flags |= LOCATION_HAS_LAT_LONG_BIT;
129         out.latitude = locGpsLocation.latitude;
130         out.longitude = locGpsLocation.longitude;
131     }
132     if (LOC_GPS_LOCATION_HAS_ALTITUDE & locGpsLocation.flags) {
133         out.flags |= LOCATION_HAS_ALTITUDE_BIT;
134         out.altitude = locGpsLocation.altitude;
135     }
136     if (LOC_GPS_LOCATION_HAS_SPEED & locGpsLocation.flags) {
137         out.flags |= LOCATION_HAS_SPEED_BIT;
138         out.speed = locGpsLocation.speed;
139     }
140     if (LOC_GPS_LOCATION_HAS_BEARING & locGpsLocation.flags) {
141         out.flags |= LOCATION_HAS_BEARING_BIT;
142         out.bearing = locGpsLocation.bearing;
143     }
144     if (LOC_GPS_LOCATION_HAS_ACCURACY & locGpsLocation.flags) {
145         out.flags |= LOCATION_HAS_ACCURACY_BIT;
146         out.accuracy = locGpsLocation.accuracy;
147     }
148     if (GPS_LOCATION_EXTENDED_HAS_VERT_UNC & locationExtended.flags) {
149         out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT;
150         out.verticalAccuracy = locationExtended.vert_unc;
151     }
152     if (GPS_LOCATION_EXTENDED_HAS_SPEED_UNC & locationExtended.flags) {
153         out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT;
154         out.speedAccuracy = locationExtended.speed_unc;
155     }
156     if (GPS_LOCATION_EXTENDED_HAS_BEARING_UNC & locationExtended.flags) {
157         out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT;
158         out.bearingAccuracy = locationExtended.bearing_unc;
159     }
160     out.timestamp = locGpsLocation.timestamp;
161     if (LOC_POS_TECH_MASK_SATELLITE & techMask) {
162         out.techMask |= LOCATION_TECHNOLOGY_GNSS_BIT;
163     }
164     if (LOC_POS_TECH_MASK_CELLID & techMask) {
165         out.techMask |= LOCATION_TECHNOLOGY_CELL_BIT;
166     }
167     if (LOC_POS_TECH_MASK_WIFI & techMask) {
168         out.techMask |= LOCATION_TECHNOLOGY_WIFI_BIT;
169     }
170     if (LOC_POS_TECH_MASK_SENSORS & techMask) {
171         out.techMask |= LOCATION_TECHNOLOGY_SENSORS_BIT;
172     }
173 }
174 
175 void
convertLocationInfo(GnssLocationInfoNotification & out,const GpsLocationExtended & locationExtended)176 GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out,
177                                  const GpsLocationExtended& locationExtended)
178 {
179     out.size = sizeof(GnssLocationInfoNotification);
180     if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL & locationExtended.flags) {
181         out.flags |= GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT;
182         out.altitudeMeanSeaLevel = locationExtended.altitudeMeanSeaLevel;
183     }
184     if (GPS_LOCATION_EXTENDED_HAS_DOP & locationExtended.flags) {
185         out.flags |= GNSS_LOCATION_INFO_DOP_BIT;
186         out.pdop = locationExtended.pdop;
187         out.hdop = locationExtended.hdop;
188         out.vdop = locationExtended.vdop;
189     }
190     if (GPS_LOCATION_EXTENDED_HAS_MAG_DEV & locationExtended.flags) {
191         out.flags |= GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT;
192         out.magneticDeviation = locationExtended.magneticDeviation;
193     }
194     if (GPS_LOCATION_EXTENDED_HAS_HOR_RELIABILITY & locationExtended.flags) {
195         out.flags |= GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT;
196         switch (locationExtended.horizontal_reliability) {
197             case LOC_RELIABILITY_VERY_LOW:
198                 out.horReliability = LOCATION_RELIABILITY_VERY_LOW;
199                 break;
200             case LOC_RELIABILITY_LOW:
201                 out.horReliability = LOCATION_RELIABILITY_LOW;
202                 break;
203             case LOC_RELIABILITY_MEDIUM:
204                 out.horReliability = LOCATION_RELIABILITY_MEDIUM;
205                 break;
206             case LOC_RELIABILITY_HIGH:
207                 out.horReliability = LOCATION_RELIABILITY_HIGH;
208                 break;
209             default:
210                 out.horReliability = LOCATION_RELIABILITY_NOT_SET;
211                 break;
212         }
213     }
214     if (GPS_LOCATION_EXTENDED_HAS_VERT_RELIABILITY & locationExtended.flags) {
215         out.flags |= GNSS_LOCATION_INFO_VER_RELIABILITY_BIT;
216         switch (locationExtended.vertical_reliability) {
217             case LOC_RELIABILITY_VERY_LOW:
218                 out.verReliability = LOCATION_RELIABILITY_VERY_LOW;
219                 break;
220             case LOC_RELIABILITY_LOW:
221                 out.verReliability = LOCATION_RELIABILITY_LOW;
222                 break;
223             case LOC_RELIABILITY_MEDIUM:
224                 out.verReliability = LOCATION_RELIABILITY_MEDIUM;
225                 break;
226             case LOC_RELIABILITY_HIGH:
227                 out.verReliability = LOCATION_RELIABILITY_HIGH;
228                 break;
229             default:
230                 out.verReliability = LOCATION_RELIABILITY_NOT_SET;
231                 break;
232         }
233     }
234     if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MAJOR & locationExtended.flags) {
235         out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT;
236         out.horUncEllipseSemiMajor = locationExtended.horUncEllipseSemiMajor;
237     }
238     if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MINOR & locationExtended.flags) {
239         out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT;
240         out.horUncEllipseSemiMinor = locationExtended.horUncEllipseSemiMinor;
241     }
242     if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_AZIMUTH & locationExtended.flags) {
243         out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT;
244         out.horUncEllipseOrientAzimuth = locationExtended.horUncEllipseOrientAzimuth;
245     }
246 }
247 
248 inline uint32_t
convertGpsLock(const GnssConfigGpsLock gpsLock)249 GnssAdapter::convertGpsLock(const GnssConfigGpsLock gpsLock)
250 {
251     switch (gpsLock) {
252         case GNSS_CONFIG_GPS_LOCK_MO:
253             return 1;
254         case GNSS_CONFIG_GPS_LOCK_NI:
255             return 2;
256         case GNSS_CONFIG_GPS_LOCK_MO_AND_NI:
257             return 3;
258         case GNSS_CONFIG_GPS_LOCK_NONE:
259         default:
260             return 0;
261     }
262 }
263 
264 inline GnssConfigGpsLock
convertGpsLock(const uint32_t gpsLock)265 GnssAdapter::convertGpsLock(const uint32_t gpsLock)
266 {
267     switch (gpsLock) {
268         case 1:
269             return GNSS_CONFIG_GPS_LOCK_MO;
270         case 2:
271             return GNSS_CONFIG_GPS_LOCK_NI;
272         case 3:
273             return GNSS_CONFIG_GPS_LOCK_MO_AND_NI;
274         case 0:
275         default:
276             return GNSS_CONFIG_GPS_LOCK_NONE;
277     }
278 }
279 
280 inline uint32_t
convertSuplVersion(const GnssConfigSuplVersion suplVersion)281 GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion)
282 {
283     switch (suplVersion) {
284         case GNSS_CONFIG_SUPL_VERSION_2_0_0:
285             return 0x00020000;
286         case GNSS_CONFIG_SUPL_VERSION_2_0_2:
287             return 0x00020002;
288         case GNSS_CONFIG_SUPL_VERSION_1_0_0:
289         default:
290             return 0x00010000;
291     }
292 }
293 
294 inline GnssConfigSuplVersion
convertSuplVersion(const uint32_t suplVersion)295 GnssAdapter::convertSuplVersion(const uint32_t suplVersion)
296 {
297     switch (suplVersion) {
298         case 0x00020000:
299             return GNSS_CONFIG_SUPL_VERSION_2_0_0;
300         case 0x00020002:
301             return GNSS_CONFIG_SUPL_VERSION_2_0_2;
302         case 0x00010000:
303         default:
304             return GNSS_CONFIG_SUPL_VERSION_1_0_0;
305     }
306 }
307 
308 inline uint32_t
convertLppProfile(const GnssConfigLppProfile lppProfile)309 GnssAdapter::convertLppProfile(const GnssConfigLppProfile lppProfile)
310 {
311     switch (lppProfile) {
312         case GNSS_CONFIG_LPP_PROFILE_USER_PLANE:
313             return 1;
314         case GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE:
315             return 2;
316         case GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE:
317             return 3;
318         case GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE:
319         default:
320             return 0;
321     }
322 }
323 
324 inline GnssConfigLppProfile
convertLppProfile(const uint32_t lppProfile)325 GnssAdapter::convertLppProfile(const uint32_t lppProfile)
326 {
327     switch (lppProfile) {
328         case 1:
329             return GNSS_CONFIG_LPP_PROFILE_USER_PLANE;
330         case 2:
331             return GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE;
332         case 3:
333             return GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE;
334         case 0:
335         default:
336             return GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE;
337     }
338 }
339 
340 uint32_t
convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)341 GnssAdapter::convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)
342 {
343     uint32_t mask = 0;
344     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT & lppeControlPlaneMask) {
345         mask |= (1<<0);
346     }
347     if (GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
348         mask |= (1<<1);
349     }
350     return mask;
351 }
352 
353 GnssConfigLppeControlPlaneMask
convertLppeCp(const uint32_t lppeControlPlaneMask)354 GnssAdapter::convertLppeCp(const uint32_t lppeControlPlaneMask)
355 {
356     GnssConfigLppeControlPlaneMask mask = 0;
357     if ((1<<0) & lppeControlPlaneMask) {
358         mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT;
359     }
360     if ((1<<1) & lppeControlPlaneMask) {
361         mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT;
362     }
363     return mask;
364 }
365 
366 
367 uint32_t
convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)368 GnssAdapter::convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)
369 {
370     uint32_t mask = 0;
371     if (GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT & lppeUserPlaneMask) {
372         mask |= (1<<0);
373     }
374     if (GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
375         mask |= (1<<1);
376     }
377     return mask;
378 }
379 
380 GnssConfigLppeUserPlaneMask
convertLppeUp(const uint32_t lppeUserPlaneMask)381 GnssAdapter::convertLppeUp(const uint32_t lppeUserPlaneMask)
382 {
383     GnssConfigLppeUserPlaneMask mask = 0;
384     if ((1<<0) & lppeUserPlaneMask) {
385         mask |= GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT;
386     }
387     if ((1<<1) & lppeUserPlaneMask) {
388         mask |= GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT;
389     }
390     return mask;
391 }
392 
393 uint32_t
convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)394 GnssAdapter::convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)
395 {
396     uint32_t mask = 0;
397     if (GNSS_CONFIG_RRC_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
398         mask |= (1<<0);
399     }
400     if (GNSS_CONFIG_RRLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
401         mask |= (1<<1);
402     }
403     if (GNSS_CONFIG_LLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
404         mask |= (1<<2);
405     }
406     if (GNSS_CONFIG_LLP_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
407         mask |= (1<<3);
408     }
409     return mask;
410 }
411 
412 uint32_t
convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)413 GnssAdapter::convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)
414 {
415     switch (emergencyPdnForEmergencySupl) {
416        case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES:
417            return 1;
418        case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO:
419        default:
420            return 0;
421     }
422 }
423 
424 uint32_t
convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)425 GnssAdapter::convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)
426 {
427     switch (suplEmergencyServices) {
428        case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES:
429            return 1;
430        case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO:
431        default:
432            return 0;
433     }
434 }
435 
436 uint32_t
convertSuplMode(const GnssConfigSuplModeMask suplModeMask)437 GnssAdapter::convertSuplMode(const GnssConfigSuplModeMask suplModeMask)
438 {
439     uint32_t mask = 0;
440     if (GNSS_CONFIG_SUPL_MODE_MSB_BIT & suplModeMask) {
441         mask |= (1<<0);
442     }
443     if (GNSS_CONFIG_SUPL_MODE_MSA_BIT & suplModeMask) {
444         mask |= (1<<1);
445     }
446     return mask;
447 }
448 
449 bool
resolveInAddress(const char * hostAddress,struct in_addr * inAddress)450 GnssAdapter::resolveInAddress(const char* hostAddress, struct in_addr* inAddress)
451 {
452     bool ret = true;
453 
454     struct hostent* hp;
455     hp = gethostbyname(hostAddress);
456     if (hp != NULL) { /* DNS OK */
457         memcpy(inAddress, hp->h_addr_list[0], hp->h_length);
458     } else {
459         /* Try IP representation */
460         if (inet_aton(hostAddress, inAddress) == 0) {
461             /* IP not valid */
462             LOC_LOGE("%s]: DNS query on '%s' failed", __func__, hostAddress);
463             ret = false;
464         }
465     }
466 
467     return ret;
468 }
469 
470 void
readConfigCommand()471 GnssAdapter::readConfigCommand()
472 {
473     LOC_LOGD("%s]: ", __func__);
474 
475     struct MsgReadConfig : public LocMsg {
476         GnssAdapter* mAdapter;
477         ContextBase& mContext;
478         inline MsgReadConfig(GnssAdapter* adapter,
479                              ContextBase& context) :
480             LocMsg(),
481             mAdapter(adapter),
482             mContext(context) {}
483         inline virtual void proc() const {
484             // reads config into mContext->mGps_conf
485             mContext.readConfig();
486             mContext.requestUlp((LocAdapterBase*)mAdapter, mContext.getCarrierCapabilities());
487         }
488     };
489 
490     if (mContext != NULL) {
491         sendMsg(new MsgReadConfig(this, *mContext));
492     }
493 }
494 
495 void
setConfigCommand()496 GnssAdapter::setConfigCommand()
497 {
498     LOC_LOGD("%s]: ", __func__);
499 
500     struct MsgSetConfig : public LocMsg {
501         GnssAdapter& mAdapter;
502         LocApiBase& mApi;
503         inline MsgSetConfig(GnssAdapter& adapter,
504                             LocApiBase& api) :
505             LocMsg(),
506             mAdapter(adapter),
507             mApi(api) {}
508         inline virtual void proc() const {
509             LocDualContext::injectFeatureConfig(mAdapter.getContext());
510             mApi.setSUPLVersion(mAdapter.convertSuplVersion(ContextBase::mGps_conf.SUPL_VER));
511             mApi.setLPPConfig(mAdapter.convertLppProfile(ContextBase::mGps_conf.LPP_PROFILE));
512             mApi.setSensorControlConfig(ContextBase::mSap_conf.SENSOR_USAGE,
513                                            ContextBase::mSap_conf.SENSOR_PROVIDER);
514             mApi.setAGLONASSProtocol(ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT);
515             mApi.setLPPeProtocolCp(
516                 mAdapter.convertLppeCp(ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY));
517             mApi.setLPPeProtocolUp(
518                 mAdapter.convertLppeUp(ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY));
519 
520             // set nmea mask type
521             uint32_t mask = 0;
522             if (NMEA_PROVIDER_MP == ContextBase::mGps_conf.NMEA_PROVIDER) {
523                 mask = LOC_NMEA_ALL_SUPPORTED_MASK;
524             } else {
525                 mask = LOC_NMEA_MASK_DEBUG_V02;
526             }
527             mApi.setNMEATypes(mask);
528 
529             mApi.setXtraVersionCheck(ContextBase::mGps_conf.XTRA_VERSION_CHECK);
530             if (ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID ||
531                 ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
532                 ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
533                 ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
534                 ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID ) {
535                 mApi.setSensorProperties(
536                     ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID,
537                     ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK,
538                     ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
539                     ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY,
540                     ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
541                     ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY,
542                     ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
543                     ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY,
544                     ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
545                     ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY);
546             }
547             mApi.setSensorPerfControlConfig(
548                 ContextBase::mSap_conf.SENSOR_CONTROL_MODE,
549                    ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH,
550                    ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC,
551                    ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH,
552                    ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC,
553                    ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH,
554                    ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH,
555                    ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH,
556                    ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH,
557                    ContextBase::mSap_conf.SENSOR_ALGORITHM_CONFIG_MASK);
558         }
559     };
560 
561     sendMsg(new MsgSetConfig(*this, *mLocApi));
562 }
563 
564 uint32_t*
gnssUpdateConfigCommand(GnssConfig config)565 GnssAdapter::gnssUpdateConfigCommand(GnssConfig config)
566 {
567     // count the number of bits set
568     GnssConfigFlagsMask flagsCopy = config.flags;
569     size_t count = 0;
570     while (flagsCopy > 0) {
571         if (flagsCopy & 1) {
572             count++;
573         }
574         flagsCopy >>= 1;
575     }
576     std::string idsString = "[";
577     uint32_t* ids = NULL;
578     if (count > 0) {
579         ids = new uint32_t[count];
580         for (size_t i=0; i < count; ++i) {
581             ids[i] = generateSessionId();
582             IF_LOC_LOGD {
583                 idsString += std::to_string(ids[i]) + " ";
584             }
585         }
586     }
587     idsString += "]";
588 
589     LOC_LOGD("%s]: ids %s flags 0x%X", __func__, idsString.c_str(), config.flags);
590 
591     struct MsgGnssUpdateConfig : public LocMsg {
592         GnssAdapter& mAdapter;
593         LocApiBase& mApi;
594         GnssConfig mConfig;
595         uint32_t* mIds;
596         size_t mCount;
597         inline MsgGnssUpdateConfig(GnssAdapter& adapter,
598                                    LocApiBase& api,
599                                    GnssConfig config,
600                                    uint32_t* ids,
601                                    size_t count) :
602             LocMsg(),
603             mAdapter(adapter),
604             mApi(api),
605             mConfig(config),
606             mIds(ids),
607             mCount(count) {}
608         inline virtual ~MsgGnssUpdateConfig()
609         {
610             delete[] mIds;
611         }
612         inline virtual void proc() const {
613             //const size_t MAX_BITS_COUNT = 10;
614             //LocationError errs[MAX_BITS_COUNT] = {};
615             LocationError* errs = new LocationError[mCount];
616             LocationError err = LOCATION_ERROR_SUCCESS;
617             uint32_t index = 0;
618 
619             if (mConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
620                 uint32_t newGpsLock = mAdapter.convertGpsLock(mConfig.gpsLock);
621                 ContextBase::mGps_conf.GPS_LOCK = newGpsLock;
622                 if (0 == mAdapter.getPowerVoteId()) {
623                     err = mApi.setGpsLock(mConfig.gpsLock);
624                 }
625                 if (index < mCount) {
626                     errs[index++] = err;
627                 }
628             }
629             if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
630                 uint32_t newSuplVersion = mAdapter.convertSuplVersion(mConfig.suplVersion);
631                 if (newSuplVersion != ContextBase::mGps_conf.SUPL_VER) {
632                     ContextBase::mGps_conf.SUPL_VER = newSuplVersion;
633                     err = mApi.setSUPLVersion(mConfig.suplVersion);
634                 } else {
635                     err = LOCATION_ERROR_SUCCESS;
636                 }
637                 if (index < mCount) {
638                     errs[index++] = err;
639                 }
640             }
641             if (mConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
642                 if (GNSS_ASSISTANCE_TYPE_SUPL == mConfig.assistanceServer.type) {
643                     char serverUrl[MAX_URL_LEN] = {};
644                     uint32_t length = 0;
645                     const char noHost[] = "NONE";
646                     if (NULL == mConfig.assistanceServer.hostName ||
647                         strncasecmp(noHost,
648                                     mConfig.assistanceServer.hostName,
649                                     sizeof(noHost)) == 0) {
650                     } else {
651                         length = snprintf(serverUrl, sizeof(serverUrl), "%s:%u",
652                                           mConfig.assistanceServer.hostName,
653                                           mConfig.assistanceServer.port);
654                     }
655 
656                     if (sizeof(serverUrl) > length) {
657                         err = mApi.setServer(serverUrl, length);
658                     } else {
659                         err = LOCATION_ERROR_INVALID_PARAMETER;
660                     }
661                 } else if (GNSS_ASSISTANCE_TYPE_C2K == mConfig.assistanceServer.type) {
662                     struct in_addr addr;
663                     if (!mAdapter.resolveInAddress(mConfig.assistanceServer.hostName, &addr)) {
664                         LOC_LOGE("%s]: hostName %s cannot be resolved",
665                                  __func__, mConfig.assistanceServer.hostName);
666                         err = LOCATION_ERROR_INVALID_PARAMETER;
667                     } else {
668                         unsigned int ip = htonl(addr.s_addr);
669                         err = mApi.setServer(ip, mConfig.assistanceServer.port,
670                                                 LOC_AGPS_CDMA_PDE_SERVER);
671                     }
672                 } else {
673                     LOC_LOGE("%s]: Not a valid gnss assistance type %u",
674                              __func__, mConfig.assistanceServer.type);
675                     err = LOCATION_ERROR_INVALID_PARAMETER;
676                 }
677                 if (index < mCount) {
678                     errs[index++] = err;
679                 }
680             }
681             if (mConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
682                 uint32_t newLppProfile = mAdapter.convertLppProfile(mConfig.lppProfile);
683                 if (newLppProfile != ContextBase::mGps_conf.LPP_PROFILE) {
684                     ContextBase::mGps_conf.LPP_PROFILE = newLppProfile;
685                     err = mApi.setLPPConfig(mConfig.lppProfile);
686                 } else {
687                     err = LOCATION_ERROR_SUCCESS;
688                 }
689                 if (index < mCount) {
690                     errs[index++] = err;
691                 }
692             }
693             if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
694                 uint32_t newLppeControlPlaneMask =
695                     mAdapter.convertLppeCp(mConfig.lppeControlPlaneMask);
696                 if (newLppeControlPlaneMask != ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY) {
697                     ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY = newLppeControlPlaneMask;
698                     err = mApi.setLPPeProtocolCp(mConfig.lppeControlPlaneMask);
699                 } else {
700                     err = LOCATION_ERROR_SUCCESS;
701                 }
702                 if (index < mCount) {
703                     errs[index++] = err;
704                 }
705             }
706             if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
707                 uint32_t newLppeUserPlaneMask =
708                     mAdapter.convertLppeUp(mConfig.lppeUserPlaneMask);
709                 if (newLppeUserPlaneMask != ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY) {
710                     ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY = newLppeUserPlaneMask;
711                     err = mApi.setLPPeProtocolUp(mConfig.lppeUserPlaneMask);
712                 } else {
713                     err = LOCATION_ERROR_SUCCESS;
714                 }
715                 if (index < mCount) {
716                     errs[index++] = err;
717                 }
718             }
719             if (mConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
720                 uint32_t newAGloProtMask =
721                     mAdapter.convertAGloProt(mConfig.aGlonassPositionProtocolMask);
722                 if (newAGloProtMask != ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT) {
723                     ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT = newAGloProtMask;
724                     err = mApi.setAGLONASSProtocol(mConfig.aGlonassPositionProtocolMask);
725                 } else {
726                     err = LOCATION_ERROR_SUCCESS;
727                 }
728                 if (index < mCount) {
729                     errs[index++] = err;
730                 }
731             }
732             if (mConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
733                 uint32_t newEP4ES = mAdapter.convertEP4ES(mConfig.emergencyPdnForEmergencySupl);
734                 if (newEP4ES != ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
735                     ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = newEP4ES;
736                 }
737                 err = LOCATION_ERROR_SUCCESS;
738                 if (index < mCount) {
739                     errs[index++] = err;
740                 }
741             }
742             if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
743                 uint32_t newSuplEs = mAdapter.convertSuplEs(mConfig.suplEmergencyServices);
744                 if (newSuplEs != ContextBase::mGps_conf.SUPL_ES) {
745                     ContextBase::mGps_conf.SUPL_ES = newSuplEs;
746                 }
747                 err = LOCATION_ERROR_SUCCESS;
748                 if (index < mCount) {
749                     errs[index++] = err;
750                 }
751             }
752             if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
753                 uint32_t newSuplMode = mAdapter.convertSuplMode(mConfig.suplModeMask);
754                 if (newSuplMode != ContextBase::mGps_conf.SUPL_MODE) {
755                     ContextBase::mGps_conf.SUPL_MODE = newSuplMode;
756                     mAdapter.getUlpProxy()->setCapabilities(
757                         ContextBase::getCarrierCapabilities());
758                 }
759                 err = LOCATION_ERROR_SUCCESS;
760                 if (index < mCount) {
761                     errs[index++] = err;
762                 }
763             }
764 
765             mAdapter.reportResponse(index, errs, mIds);
766             delete[] errs;
767         }
768     };
769 
770     if (NULL != ids) {
771         sendMsg(new MsgGnssUpdateConfig(*this, *mLocApi, config, ids, count));
772     } else {
773         LOC_LOGE("%s]: No GNSS config items to update", __func__);
774     }
775 
776     return ids;
777 }
778 
779 uint32_t
gnssDeleteAidingDataCommand(GnssAidingData & data)780 GnssAdapter::gnssDeleteAidingDataCommand(GnssAidingData& data)
781 {
782     uint32_t sessionId = generateSessionId();
783     LOC_LOGD("%s]: id %u", __func__, sessionId);
784 
785     struct MsgDeleteAidingData : public LocMsg {
786         GnssAdapter& mAdapter;
787         LocApiBase& mApi;
788         uint32_t mSessionId;
789         GnssAidingData mData;
790         inline MsgDeleteAidingData(GnssAdapter& adapter,
791                                    LocApiBase& api,
792                                    uint32_t sessionId,
793                                    GnssAidingData& data) :
794             LocMsg(),
795             mAdapter(adapter),
796             mApi(api),
797             mSessionId(sessionId),
798             mData(data) {}
799         inline virtual void proc() const {
800             LocationError err = LOCATION_ERROR_SUCCESS;
801             err = mApi.deleteAidingData(mData);
802             mAdapter.reportResponse(err, mSessionId);
803         }
804     };
805 
806     sendMsg(new MsgDeleteAidingData(*this, *mLocApi, sessionId, data));
807     return sessionId;
808 }
809 
810 void
injectLocationCommand(double latitude,double longitude,float accuracy)811 GnssAdapter::injectLocationCommand(double latitude, double longitude, float accuracy)
812 {
813     LOC_LOGD("%s]: latitude %8.4f longitude %8.4f accuracy %8.4f",
814              __func__, latitude, longitude, accuracy);
815 
816     struct MsgInjectLocation : public LocMsg {
817         LocApiBase& mApi;
818         ContextBase& mContext;
819         double mLatitude;
820         double mLongitude;
821         float mAccuracy;
822         inline MsgInjectLocation(LocApiBase& api,
823                                  ContextBase& context,
824                                  double latitude,
825                                  double longitude,
826                                  float accuracy) :
827             LocMsg(),
828             mApi(api),
829             mContext(context),
830             mLatitude(latitude),
831             mLongitude(longitude),
832             mAccuracy(accuracy) {}
833         inline virtual void proc() const {
834             if (!mContext.hasCPIExtendedCapabilities()) {
835                 mApi.injectPosition(mLatitude, mLongitude, mAccuracy);
836             }
837         }
838     };
839 
840     sendMsg(new MsgInjectLocation(*mLocApi, *mContext, latitude, longitude, accuracy));
841 }
842 
843 void
injectTimeCommand(int64_t time,int64_t timeReference,int32_t uncertainty)844 GnssAdapter::injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty)
845 {
846     LOC_LOGD("%s]: time %lld timeReference %lld uncertainty %d",
847              __func__, (long long)time, (long long)timeReference, uncertainty);
848 
849     struct MsgInjectTime : public LocMsg {
850         LocApiBase& mApi;
851         ContextBase& mContext;
852         int64_t mTime;
853         int64_t mTimeReference;
854         int32_t mUncertainty;
855         inline MsgInjectTime(LocApiBase& api,
856                              ContextBase& context,
857                              int64_t time,
858                              int64_t timeReference,
859                              int32_t uncertainty) :
860             LocMsg(),
861             mApi(api),
862             mContext(context),
863             mTime(time),
864             mTimeReference(timeReference),
865             mUncertainty(uncertainty) {}
866         inline virtual void proc() const {
867             mApi.setTime(mTime, mTimeReference, mUncertainty);
868         }
869     };
870 
871     sendMsg(new MsgInjectTime(*mLocApi, *mContext, time, timeReference, uncertainty));
872 }
873 
874 void
setUlpProxyCommand(UlpProxyBase * ulp)875 GnssAdapter::setUlpProxyCommand(UlpProxyBase* ulp)
876 {
877     LOC_LOGD("%s]: ", __func__);
878 
879     struct MsgSetUlpProxy : public LocMsg {
880         GnssAdapter& mAdapter;
881         UlpProxyBase* mUlp;
882         inline MsgSetUlpProxy(GnssAdapter& adapter,
883                               UlpProxyBase* ulp) :
884             LocMsg(),
885             mAdapter(adapter),
886             mUlp(ulp) {}
887         inline virtual void proc() const {
888             mAdapter.setUlpProxy(mUlp);
889         }
890     };
891 
892     sendMsg(new MsgSetUlpProxy(*this, ulp));
893 }
894 
895 void
setUlpProxy(UlpProxyBase * ulp)896 GnssAdapter::setUlpProxy(UlpProxyBase* ulp)
897 {
898     if (ulp == mUlpProxy) {
899         //This takes care of the case when double initalization happens
900         //and we get the same object back for UlpProxyBase . Do nothing
901         return;
902     }
903 
904     LOC_LOGV("%s]: %p", __func__, ulp);
905     if (NULL == ulp) {
906         LOC_LOGE("%s]: ulp pointer is NULL", __func__);
907         ulp = new UlpProxyBase();
908     }
909 
910     if (LOC_POSITION_MODE_INVALID != mUlpProxy->mPosMode.mode) {
911         // need to send this mode and start msg to ULP
912         ulp->sendFixMode(mUlpProxy->mPosMode);
913     }
914 
915     if (mUlpProxy->mFixSet) {
916         ulp->sendStartFix();
917     }
918 
919     delete mUlpProxy;
920     mUlpProxy = ulp;
921 }
922 
923 void
addClientCommand(LocationAPI * client,const LocationCallbacks & callbacks)924 GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks)
925 {
926     LOC_LOGD("%s]: client %p", __func__, client);
927 
928     struct MsgAddClient : public LocMsg {
929         GnssAdapter& mAdapter;
930         LocationAPI* mClient;
931         const LocationCallbacks mCallbacks;
932         inline MsgAddClient(GnssAdapter& adapter,
933                             LocationAPI* client,
934                             const LocationCallbacks& callbacks) :
935             LocMsg(),
936             mAdapter(adapter),
937             mClient(client),
938             mCallbacks(callbacks) {}
939         inline virtual void proc() const {
940             mAdapter.saveClient(mClient, mCallbacks);
941         }
942     };
943 
944     sendMsg(new MsgAddClient(*this, client, callbacks));
945 }
946 
947 void
removeClientCommand(LocationAPI * client)948 GnssAdapter::removeClientCommand(LocationAPI* client)
949 {
950     LOC_LOGD("%s]: client %p", __func__, client);
951 
952     struct MsgRemoveClient : public LocMsg {
953         GnssAdapter& mAdapter;
954         LocationAPI* mClient;
955         inline MsgRemoveClient(GnssAdapter& adapter,
956                                LocationAPI* client) :
957             LocMsg(),
958             mAdapter(adapter),
959             mClient(client) {}
960         inline virtual void proc() const {
961             mAdapter.stopClientSessions(mClient);
962             mAdapter.eraseClient(mClient);
963         }
964     };
965 
966     sendMsg(new MsgRemoveClient(*this, client));
967 }
968 
969 void
stopClientSessions(LocationAPI * client)970 GnssAdapter::stopClientSessions(LocationAPI* client)
971 {
972     LOC_LOGD("%s]: client %p", __func__, client);
973     for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end();) {
974         if (client == it->first.client) {
975             LocationError err = stopTrackingMultiplex(it->first.client, it->first.id);
976             if (LOCATION_ERROR_SUCCESS == err) {
977                 it = mTrackingSessions.erase(it);
978                 continue;
979             }
980         }
981         ++it; // increment only when not erasing an iterator
982     }
983 
984 }
985 
986 void
updateClientsEventMask()987 GnssAdapter::updateClientsEventMask()
988 {
989     LOC_API_ADAPTER_EVENT_MASK_T mask = 0;
990     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
991         if (it->second.trackingCb != nullptr) {
992             mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT;
993         }
994         if (it->second.gnssNiCb != nullptr) {
995             mask |= LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST;
996         }
997         if (it->second.gnssSvCb != nullptr) {
998             mask |= LOC_API_ADAPTER_BIT_SATELLITE_REPORT;
999         }
1000         if (it->second.gnssNmeaCb != nullptr) {
1001             mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT;
1002         }
1003         if (it->second.gnssMeasurementsCb != nullptr) {
1004             mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
1005         }
1006     }
1007     updateEvtMask(mask, LOC_REGISTRATION_MASK_SET);
1008 }
1009 
1010 void
handleEngineUpEvent()1011 GnssAdapter::handleEngineUpEvent()
1012 {
1013     struct MsgRestartSessions : public LocMsg {
1014         GnssAdapter& mAdapter;
1015         inline MsgRestartSessions(GnssAdapter& adapter) :
1016             LocMsg(),
1017             mAdapter(adapter) {}
1018         virtual void proc() const {
1019             mAdapter.restartSessions();
1020         }
1021     };
1022 
1023     setConfigCommand();
1024     sendMsg(new MsgRestartSessions(*this));
1025 }
1026 
1027 void
restartSessions()1028 GnssAdapter::restartSessions()
1029 {
1030     LOC_LOGD("%s]: ", __func__);
1031 
1032     if (mTrackingSessions.empty()) {
1033         return;
1034     }
1035 
1036     // get the LocationOptions that has the smallest interval, which should be the active one
1037     LocationOptions smallestIntervalOptions = {}; // size is zero until set for the first time
1038     for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) {
1039         if (0 == smallestIntervalOptions.size || //size of zero means we havent set it yet
1040             it->second.minInterval < smallestIntervalOptions.minInterval) {
1041              smallestIntervalOptions = it->second;
1042         }
1043     }
1044 
1045     LocPosMode locPosMode = {};
1046     convertOptions(locPosMode, smallestIntervalOptions);
1047     mLocApi->startFix(locPosMode);
1048 }
1049 
1050 void
requestCapabilitiesCommand(LocationAPI * client)1051 GnssAdapter::requestCapabilitiesCommand(LocationAPI* client)
1052 {
1053     LOC_LOGD("%s]: ", __func__);
1054 
1055     struct MsgRequestCapabilities : public LocMsg {
1056         GnssAdapter& mAdapter;
1057         LocApiBase& mApi;
1058         LocationAPI* mClient;
1059         inline MsgRequestCapabilities(GnssAdapter& adapter,
1060                                       LocApiBase& api,
1061                                       LocationAPI* client) :
1062             LocMsg(),
1063             mAdapter(adapter),
1064             mApi(api),
1065             mClient(client) {}
1066         inline virtual void proc() const {
1067             LocationCallbacks callbacks = mAdapter.getClientCallbacks(mClient);
1068             if (callbacks.capabilitiesCb == nullptr) {
1069                 LOC_LOGE("%s]: capabilitiesCb is NULL", __func__);
1070                 return;
1071             }
1072 
1073             LocationCapabilitiesMask mask = {};
1074             // time based tracking always supported
1075             mask |= LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT;
1076             if (mApi.isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING)){
1077                 mask |= LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT |
1078                         LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT;
1079             }
1080             if (mApi.isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
1081                 mask |= LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT;
1082             }
1083             // geofence always supported
1084             mask |= LOCATION_CAPABILITIES_GEOFENCE_BIT;
1085             if (mApi.gnssConstellationConfig()) {
1086                 mask |= LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT;
1087             }
1088             uint32_t carrierCapabilities = ContextBase::getCarrierCapabilities();
1089             if (carrierCapabilities & LOC_GPS_CAPABILITY_MSB) {
1090                 mask |= LOCATION_CAPABILITIES_GNSS_MSB_BIT;
1091             }
1092             if (LOC_GPS_CAPABILITY_MSA & carrierCapabilities) {
1093                 mask |= LOCATION_CAPABILITIES_GNSS_MSA_BIT;
1094             }
1095 
1096             callbacks.capabilitiesCb(mask);
1097         }
1098     };
1099 
1100     sendMsg(new MsgRequestCapabilities(*this, *mLocApi, client));
1101 }
1102 
1103 LocationCallbacks
getClientCallbacks(LocationAPI * client)1104 GnssAdapter::getClientCallbacks(LocationAPI* client)
1105 {
1106     LocationCallbacks callbacks = {};
1107     auto it = mClientData.find(client);
1108     if (it != mClientData.end()) {
1109         callbacks = it->second;
1110     }
1111     return callbacks;
1112 }
1113 
1114 void
saveClient(LocationAPI * client,const LocationCallbacks & callbacks)1115 GnssAdapter::saveClient(LocationAPI* client, const LocationCallbacks& callbacks)
1116 {
1117     mClientData[client] = callbacks;
1118     updateClientsEventMask();
1119 }
1120 
1121 void
eraseClient(LocationAPI * client)1122 GnssAdapter::eraseClient(LocationAPI* client)
1123 {
1124     auto it = mClientData.find(client);
1125     if (it != mClientData.end()) {
1126         mClientData.erase(it);
1127     }
1128     updateClientsEventMask();
1129 }
1130 
1131 bool
hasTrackingCallback(LocationAPI * client)1132 GnssAdapter::hasTrackingCallback(LocationAPI* client)
1133 {
1134     auto it = mClientData.find(client);
1135     return (it != mClientData.end() && it->second.trackingCb);
1136 }
1137 
1138 bool
hasMeasurementsCallback(LocationAPI * client)1139 GnssAdapter::hasMeasurementsCallback(LocationAPI* client)
1140 {
1141     auto it = mClientData.find(client);
1142     return (it != mClientData.end() && it->second.gnssMeasurementsCb);
1143 }
1144 
1145 bool
isTrackingSession(LocationAPI * client,uint32_t sessionId)1146 GnssAdapter::isTrackingSession(LocationAPI* client, uint32_t sessionId)
1147 {
1148     LocationSessionKey key(client, sessionId);
1149     return (mTrackingSessions.find(key) != mTrackingSessions.end());
1150 }
1151 
1152 void
saveTrackingSession(LocationAPI * client,uint32_t sessionId,const LocationOptions & options)1153 GnssAdapter::saveTrackingSession(LocationAPI* client, uint32_t sessionId,
1154                                  const LocationOptions& options)
1155 {
1156     LocationSessionKey key(client, sessionId);
1157     mTrackingSessions[key] = options;
1158 }
1159 
1160 void
eraseTrackingSession(LocationAPI * client,uint32_t sessionId)1161 GnssAdapter::eraseTrackingSession(LocationAPI* client, uint32_t sessionId)
1162 {
1163     LocationSessionKey key(client, sessionId);
1164     auto it = mTrackingSessions.find(key);
1165     if (it != mTrackingSessions.end()) {
1166         mTrackingSessions.erase(it);
1167     }
1168 
1169 }
1170 
1171 void
reportResponse(LocationAPI * client,LocationError err,uint32_t sessionId)1172 GnssAdapter::reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId)
1173 {
1174     LOC_LOGD("%s]: client %p id %u err %u", __func__, client, sessionId, err);
1175 
1176     auto it = mClientData.find(client);
1177     if (it != mClientData.end() &&
1178         it->second.responseCb != nullptr) {
1179         it->second.responseCb(err, sessionId);
1180     } else {
1181         LOC_LOGW("%s]: client %p id %u not found in data", __func__, client, sessionId);
1182     }
1183 }
1184 
1185 void
reportResponse(LocationError err,uint32_t sessionId)1186 GnssAdapter::reportResponse(LocationError err, uint32_t sessionId)
1187 {
1188     LOC_LOGD("%s]: id %u err %u", __func__, sessionId, err);
1189 
1190     if (mControlCallbacks.size > 0 && mControlCallbacks.responseCb != nullptr) {
1191         mControlCallbacks.responseCb(err, sessionId);
1192     } else {
1193         LOC_LOGW("%s]: control client response callback not found", __func__);
1194     }
1195 }
1196 
1197 void
reportResponse(size_t count,LocationError * errs,uint32_t * ids)1198 GnssAdapter::reportResponse(size_t count, LocationError* errs, uint32_t* ids)
1199 {
1200     IF_LOC_LOGD {
1201         std::string idsString = "[";
1202         std::string errsString = "[";
1203         if (NULL != ids && NULL != errs) {
1204             for (size_t i=0; i < count; ++i) {
1205                 idsString += std::to_string(ids[i]) + " ";
1206                 errsString += std::to_string(errs[i]) + " ";
1207             }
1208         }
1209         idsString += "]";
1210         errsString += "]";
1211 
1212         LOC_LOGD("%s]: ids %s errs %s",
1213                  __func__, idsString.c_str(), errsString.c_str());
1214     }
1215 
1216     if (mControlCallbacks.size > 0 && mControlCallbacks.collectiveResponseCb != nullptr) {
1217         mControlCallbacks.collectiveResponseCb(count, errs, ids);
1218     } else {
1219         LOC_LOGW("%s]: control client callback not found", __func__);
1220     }
1221 }
1222 
1223 uint32_t
startTrackingCommand(LocationAPI * client,LocationOptions & options)1224 GnssAdapter::startTrackingCommand(LocationAPI* client, LocationOptions& options)
1225 {
1226     uint32_t sessionId = generateSessionId();
1227     LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
1228              __func__, client, sessionId, options.minInterval, options.mode);
1229 
1230     struct MsgStartTracking : public LocMsg {
1231         GnssAdapter& mAdapter;
1232         LocApiBase& mApi;
1233         LocationAPI* mClient;
1234         uint32_t mSessionId;
1235         LocationOptions mOptions;
1236         inline MsgStartTracking(GnssAdapter& adapter,
1237                                LocApiBase& api,
1238                                LocationAPI* client,
1239                                uint32_t sessionId,
1240                                LocationOptions options) :
1241             LocMsg(),
1242             mAdapter(adapter),
1243             mApi(api),
1244             mClient(client),
1245             mSessionId(sessionId),
1246             mOptions(options) {}
1247         inline virtual void proc() const {
1248             LocationError err = LOCATION_ERROR_SUCCESS;
1249             if (!mAdapter.hasTrackingCallback(mClient) &&
1250                 !mAdapter.hasMeasurementsCallback(mClient)) {
1251                 err = LOCATION_ERROR_CALLBACK_MISSING;
1252             } else if (0 == mOptions.size) {
1253                 err = LOCATION_ERROR_INVALID_PARAMETER;
1254             } else {
1255                 // Api doesn't support multiple clients for time based tracking, so mutiplex
1256                 err = mAdapter.startTrackingMultiplex(mOptions);
1257                 if (LOCATION_ERROR_SUCCESS == err) {
1258                     mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
1259                 }
1260             }
1261             mAdapter.reportResponse(mClient, err, mSessionId);
1262         }
1263     };
1264 
1265     sendMsg(new MsgStartTracking(*this, *mLocApi, client, sessionId, options));
1266     return sessionId;
1267 
1268 }
1269 
1270 LocationError
startTrackingMultiplex(const LocationOptions & options)1271 GnssAdapter::startTrackingMultiplex(const LocationOptions& options)
1272 {
1273     LocationError err = LOCATION_ERROR_SUCCESS;
1274 
1275     if (mTrackingSessions.empty()) {
1276         err = startTracking(options);
1277     } else {
1278         // get the LocationOptions that has the smallest interval, which should be the active one
1279         LocationOptions smallestIntervalOptions = {}; // size is zero until set for the first time
1280         for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) {
1281             if (0 == smallestIntervalOptions.size || //size of zero means we havent set it yet
1282                 it->second.minInterval < smallestIntervalOptions.minInterval) {
1283                  smallestIntervalOptions = it->second;
1284             }
1285         }
1286         // if new session's minInterval is smaller than any in other sessions
1287         if (options.minInterval < smallestIntervalOptions.minInterval) {
1288             // restart time based tracking with new options
1289             err = startTracking(options);
1290         }
1291     }
1292 
1293     return err;
1294 }
1295 
1296 LocationError
startTracking(const LocationOptions & options)1297 GnssAdapter::startTracking(const LocationOptions& options)
1298 {
1299     LocationError err = LOCATION_ERROR_SUCCESS;
1300     LocPosMode locPosMode = {};
1301     convertOptions(locPosMode, options);
1302     if (!mUlpProxy->sendFixMode(locPosMode)) {
1303         // do nothing
1304     }
1305     if (!mUlpProxy->sendStartFix()) {
1306         loc_api_adapter_err apiErr = mLocApi->startFix(locPosMode);
1307         if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) {
1308             err = LOCATION_ERROR_SUCCESS;
1309         } else {
1310             err = LOCATION_ERROR_GENERAL_FAILURE;
1311         }
1312     }
1313 
1314     return err;
1315 }
1316 
1317 void
setPositionModeCommand(LocPosMode & locPosMode)1318 GnssAdapter::setPositionModeCommand(LocPosMode& locPosMode)
1319 {
1320     LOC_LOGD("%s]: min_interval %u mode %u",
1321              __func__, locPosMode.min_interval, locPosMode.mode);
1322 
1323     struct MsgSetPositionMode : public LocMsg {
1324         GnssAdapter& mAdapter;
1325         LocApiBase& mApi;
1326         LocPosMode mLocPosMode;
1327         inline MsgSetPositionMode(GnssAdapter& adapter,
1328                                   LocApiBase& api,
1329                                   LocPosMode& locPosMode) :
1330             LocMsg(),
1331             mAdapter(adapter),
1332             mApi(api),
1333             mLocPosMode(locPosMode) {}
1334         inline virtual void proc() const {
1335              // saves the mode in adapter to be used when startTrackingCommand is called from ULP
1336             mAdapter.setUlpPositionMode(mLocPosMode);
1337             mApi.setPositionMode(mLocPosMode);
1338         }
1339     };
1340 
1341     sendMsg(new MsgSetPositionMode(*this, *mLocApi, locPosMode));
1342 }
1343 
1344 void
startTrackingCommand()1345 GnssAdapter::startTrackingCommand()
1346 {
1347     LOC_LOGD("%s]: ", __func__);
1348 
1349     struct MsgStartTracking : public LocMsg {
1350         GnssAdapter& mAdapter;
1351         LocApiBase& mApi;
1352         inline MsgStartTracking(GnssAdapter& adapter,
1353                                 LocApiBase& api) :
1354             LocMsg(),
1355             mAdapter(adapter),
1356             mApi(api) {}
1357         inline virtual void proc() const {
1358             // we get this call from ULP, so just call LocApi without multiplexing because
1359             // ulp would be doing the multiplexing for us if it is present
1360             LocPosMode& ulpPositionMode = mAdapter.getUlpPositionMode();
1361             mApi.startFix(ulpPositionMode);
1362         }
1363     };
1364 
1365     sendMsg(new MsgStartTracking(*this, *mLocApi));
1366 }
1367 
1368 void
updateTrackingOptionsCommand(LocationAPI * client,uint32_t id,LocationOptions & options)1369 GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id,
1370                                           LocationOptions& options)
1371 {
1372     LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
1373              __func__, client, id, options.minInterval, options.mode);
1374 
1375     struct MsgUpdateTracking : public LocMsg {
1376         GnssAdapter& mAdapter;
1377         LocApiBase& mApi;
1378         LocationAPI* mClient;
1379         uint32_t mSessionId;
1380         LocationOptions mOptions;
1381         inline MsgUpdateTracking(GnssAdapter& adapter,
1382                                 LocApiBase& api,
1383                                 LocationAPI* client,
1384                                 uint32_t sessionId,
1385                                 LocationOptions options) :
1386             LocMsg(),
1387             mAdapter(adapter),
1388             mApi(api),
1389             mClient(client),
1390             mSessionId(sessionId),
1391             mOptions(options) {}
1392         inline virtual void proc() const {
1393             if (mAdapter.isTrackingSession(mClient, mSessionId)) {
1394                 LocationError err = LOCATION_ERROR_SUCCESS;
1395                 if (0 == mOptions.size) {
1396                     err = LOCATION_ERROR_INVALID_PARAMETER;
1397                 } else {
1398                     // Api doesn't support multiple clients for time based tracking, so mutiplex
1399                     err = mAdapter.updateTrackingMultiplex(mClient, mSessionId, mOptions);
1400                     if (LOCATION_ERROR_SUCCESS == err) {
1401                         mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
1402                     }
1403                 }
1404                 mAdapter.reportResponse(mClient, err, mSessionId);
1405             }
1406             // we do not reportResponse for the case where there is no existing tracking session
1407             // for the client and id being used, since updateTrackingCommand can be sent to both
1408             // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response
1409         }
1410     };
1411 
1412     sendMsg(new MsgUpdateTracking(*this, *mLocApi, client, id, options));
1413 }
1414 
1415 LocationError
updateTrackingMultiplex(LocationAPI * client,uint32_t id,const LocationOptions & options)1416 GnssAdapter::updateTrackingMultiplex(LocationAPI* client, uint32_t id,
1417                                      const LocationOptions& options)
1418 {
1419     LocationError err = LOCATION_ERROR_SUCCESS;
1420 
1421     if (1 == mTrackingSessions.size()) {
1422         err = startTracking(options);
1423     } else {
1424         LocationSessionKey key(client, id);
1425 
1426         // get the session we are updating
1427         auto it = mTrackingSessions.find(key);
1428         if (it != mTrackingSessions.end()) {
1429             // find the smallest interval, other than the session we are updating
1430             LocationOptions smallestIntervalOptions = {}; // size is 0 until set for the first time
1431             for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) {
1432                 // if session is not the one we are updating and either smallest interval is not set
1433                 // or there is a new smallest interval, then set the new smallest interval
1434                 if (it2->first != key && (0 == smallestIntervalOptions.size ||
1435                     it2->second.minInterval < smallestIntervalOptions.minInterval)) {
1436                      smallestIntervalOptions = it2->second;
1437                 }
1438             }
1439             // if session we are updating has smaller interval then next smallest
1440             if (options.minInterval < smallestIntervalOptions.minInterval) {
1441                 // restart time based tracking with the newly updated interval
1442                 err = startTracking(options);
1443             // else if the session we are updating used to be the smallest
1444             } else if (it->second.minInterval < smallestIntervalOptions.minInterval) {
1445                 // restart time based tracking with the next smallest
1446                 err = startTracking(smallestIntervalOptions);
1447             }
1448         }
1449     }
1450 
1451     return err;
1452 }
1453 
1454 void
stopTrackingCommand(LocationAPI * client,uint32_t id)1455 GnssAdapter::stopTrackingCommand(LocationAPI* client, uint32_t id)
1456 {
1457     LOC_LOGD("%s]: client %p id %u", __func__, client, id);
1458 
1459     struct MsgStopTracking : public LocMsg {
1460         GnssAdapter& mAdapter;
1461         LocApiBase& mApi;
1462         LocationAPI* mClient;
1463         uint32_t mSessionId;
1464         inline MsgStopTracking(GnssAdapter& adapter,
1465                                LocApiBase& api,
1466                                LocationAPI* client,
1467                                uint32_t sessionId) :
1468             LocMsg(),
1469             mAdapter(adapter),
1470             mApi(api),
1471             mClient(client),
1472             mSessionId(sessionId) {}
1473         inline virtual void proc() const {
1474             if (mAdapter.isTrackingSession(mClient, mSessionId)) {
1475                 LocationError err = LOCATION_ERROR_SUCCESS;
1476                 // Api doesn't support multiple clients for time based tracking, so mutiplex
1477                 err = mAdapter.stopTrackingMultiplex(mClient, mSessionId);
1478                 if (LOCATION_ERROR_SUCCESS == err) {
1479                     mAdapter.eraseTrackingSession(mClient, mSessionId);
1480                 }
1481                 mAdapter.reportResponse(mClient, err, mSessionId);
1482             }
1483             // we do not reportResponse for the case where there is no existing tracking session
1484             // for the client and id being used, since stopTrackingCommand can be sent to both
1485             // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response
1486 
1487         }
1488     };
1489 
1490     sendMsg(new MsgStopTracking(*this, *mLocApi, client, id));
1491 }
1492 
1493 LocationError
stopTrackingMultiplex(LocationAPI * client,uint32_t id)1494 GnssAdapter::stopTrackingMultiplex(LocationAPI* client, uint32_t id)
1495 {
1496     LocationError err = LOCATION_ERROR_SUCCESS;
1497 
1498     if (1 == mTrackingSessions.size()) {
1499         err = stopTracking();
1500     } else {
1501         LocationSessionKey key(client, id);
1502 
1503         // get the session we are stopping
1504         auto it = mTrackingSessions.find(key);
1505         if (it != mTrackingSessions.end()) {
1506             // find the next smallest interval, other than the session we are stopping
1507             LocationOptions smallestIntervalOptions = {}; // size is 0 until set for the first time
1508             for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) {
1509                 // if session is not the one we are stopping and either smallest interval is not set
1510                 // or there is a new smallest interval, then set the new smallest interval
1511                 if (it2->first != key && (0 == smallestIntervalOptions.size ||
1512                     it2->second.minInterval < smallestIntervalOptions.minInterval)) {
1513                      smallestIntervalOptions = it2->second;
1514                 }
1515             }
1516             // if session we are stopping has smaller interval then next smallest
1517             if (it->second.minInterval < smallestIntervalOptions.minInterval) {
1518                 // restart time based tracking with next smallest interval
1519                 err = startTracking(smallestIntervalOptions);
1520             }
1521         }
1522     }
1523 
1524     return err;
1525 }
1526 
1527 LocationError
stopTracking()1528 GnssAdapter::stopTracking()
1529 {
1530     LocationError err = LOCATION_ERROR_SUCCESS;
1531     if (!mUlpProxy->sendStopFix()) {
1532         loc_api_adapter_err apiErr = mLocApi->stopFix();
1533         if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) {
1534             err = LOCATION_ERROR_SUCCESS;
1535         } else {
1536             err = LOCATION_ERROR_GENERAL_FAILURE;
1537         }
1538     }
1539 
1540     return err;
1541 }
1542 
1543 void
stopTrackingCommand()1544 GnssAdapter::stopTrackingCommand()
1545 {
1546     LOC_LOGD("%s]: ", __func__);
1547 
1548     struct MsgStopTracking : public LocMsg {
1549         GnssAdapter& mAdapter;
1550         LocApiBase& mApi;
1551         inline MsgStopTracking(GnssAdapter& adapter,
1552                                LocApiBase& api) :
1553             LocMsg(),
1554             mAdapter(adapter),
1555             mApi(api) {}
1556         inline virtual void proc() const {
1557             // clear the position mode
1558             LocPosMode mLocPosMode = {};
1559             mLocPosMode.mode = LOC_POSITION_MODE_INVALID;
1560             mAdapter.setUlpPositionMode(mLocPosMode);
1561             // don't need to multiplex because ULP will do that for us if it is present
1562             mApi.stopFix();
1563         }
1564     };
1565 
1566     sendMsg(new MsgStopTracking(*this, *mLocApi));
1567 }
1568 
1569 void
getZppCommand()1570 GnssAdapter::getZppCommand()
1571 {
1572     LOC_LOGD("%s]: ", __func__);
1573 
1574     struct MsgGetZpp : public LocMsg {
1575         GnssAdapter& mAdapter;
1576         LocApiBase& mApi;
1577         inline MsgGetZpp(GnssAdapter& adapter,
1578                          LocApiBase& api) :
1579             LocMsg(),
1580             mAdapter(adapter),
1581             mApi(api) {}
1582         inline virtual void proc() const {
1583             UlpLocation location = {};
1584             LocPosTechMask techMask = LOC_POS_TECH_MASK_DEFAULT;
1585             GpsLocationExtended locationExtended = {};
1586             locationExtended.size = sizeof(locationExtended);
1587 
1588             mApi.getBestAvailableZppFix(location.gpsLocation, techMask);
1589             //Mark the location source as from ZPP
1590             location.gpsLocation.flags |= LOCATION_HAS_SOURCE_INFO;
1591             location.position_source = ULP_LOCATION_IS_FROM_ZPP;
1592 
1593             mAdapter.getUlpProxy()->reportPosition(location,
1594                                                    locationExtended,
1595                                                    LOC_SESS_SUCCESS,
1596                                                    techMask);
1597         }
1598     };
1599 
1600     sendMsg(new MsgGetZpp(*this, *mLocApi));
1601 }
1602 
1603 bool
hasNiNotifyCallback(LocationAPI * client)1604 GnssAdapter::hasNiNotifyCallback(LocationAPI* client)
1605 {
1606     auto it = mClientData.find(client);
1607     return (it != mClientData.end() && it->second.gnssNiCb);
1608 }
1609 
1610 void
gnssNiResponseCommand(LocationAPI * client,uint32_t id,GnssNiResponse response)1611 GnssAdapter::gnssNiResponseCommand(LocationAPI* client,
1612                                    uint32_t id,
1613                                    GnssNiResponse response)
1614 {
1615     LOC_LOGD("%s]: client %p id %u response %u", __func__, client, id, response);
1616 
1617     struct MsgGnssNiResponse : public LocMsg {
1618         GnssAdapter& mAdapter;
1619         LocationAPI* mClient;
1620         uint32_t mSessionId;
1621         GnssNiResponse mResponse;
1622         inline MsgGnssNiResponse(GnssAdapter& adapter,
1623                                  LocationAPI* client,
1624                                  uint32_t sessionId,
1625                                  GnssNiResponse response) :
1626             LocMsg(),
1627             mAdapter(adapter),
1628             mClient(client),
1629             mSessionId(sessionId),
1630             mResponse(response) {}
1631         inline virtual void proc() const {
1632             NiData& niData = mAdapter.getNiData();
1633             LocationError err = LOCATION_ERROR_SUCCESS;
1634             if (!mAdapter.hasNiNotifyCallback(mClient)) {
1635                 err = LOCATION_ERROR_ID_UNKNOWN;
1636             } else {
1637                 NiSession* pSession = NULL;
1638                 if (mSessionId == niData.sessionEs.reqID &&
1639                     NULL != niData.sessionEs.rawRequest) {
1640                     pSession = &niData.sessionEs;
1641                     // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
1642                     if (mResponse == GNSS_NI_RESPONSE_ACCEPT &&
1643                         NULL != niData.session.rawRequest) {
1644                             pthread_mutex_lock(&niData.session.tLock);
1645                             niData.session.resp = GNSS_NI_RESPONSE_IGNORE;
1646                             niData.session.respRecvd = true;
1647                             pthread_cond_signal(&niData.session.tCond);
1648                             pthread_mutex_unlock(&niData.session.tLock);
1649                     }
1650                 } else if (mSessionId == niData.session.reqID &&
1651                     NULL != niData.session.rawRequest) {
1652                     pSession = &niData.session;
1653                 }
1654 
1655                 if (pSession) {
1656                     LOC_LOGI("%s]: gnssNiResponseCommand: send user mResponse %u for id %u",
1657                              __func__, mResponse, mSessionId);
1658                     pthread_mutex_lock(&pSession->tLock);
1659                     pSession->resp = mResponse;
1660                     pSession->respRecvd = true;
1661                     pthread_cond_signal(&pSession->tCond);
1662                     pthread_mutex_unlock(&pSession->tLock);
1663                 } else {
1664                     err = LOCATION_ERROR_ID_UNKNOWN;
1665                     LOC_LOGE("%s]: gnssNiResponseCommand: id %u not an active session",
1666                              __func__, mSessionId);
1667                 }
1668             }
1669             mAdapter.reportResponse(mClient, err, mSessionId);
1670         }
1671     };
1672 
1673     sendMsg(new MsgGnssNiResponse(*this, client, id, response));
1674 
1675 }
1676 
1677 void
gnssNiResponseCommand(GnssNiResponse response,void * rawRequest)1678 GnssAdapter::gnssNiResponseCommand(GnssNiResponse response, void* rawRequest)
1679 {
1680     LOC_LOGD("%s]: response %u", __func__, response);
1681 
1682     struct MsgGnssNiResponse : public LocMsg {
1683         LocApiBase& mApi;
1684         const GnssNiResponse mResponse;
1685         const void* mPayload;
1686         inline MsgGnssNiResponse(LocApiBase& api,
1687                                  const GnssNiResponse response,
1688                                  const void* rawRequest) :
1689             LocMsg(),
1690             mApi(api),
1691             mResponse(response),
1692             mPayload(rawRequest) {}
1693         inline virtual ~MsgGnssNiResponse() {
1694             // this is a bit weird since mPayload is not
1695             // allocated by this class.  But there is no better way.
1696             // mPayload actually won't be NULL here.
1697             free((void*)mPayload);
1698         }
1699         inline virtual void proc() const {
1700             mApi.informNiResponse(mResponse, mPayload);
1701         }
1702     };
1703 
1704     sendMsg(new MsgGnssNiResponse(*mLocApi, response, rawRequest));
1705 
1706 }
1707 
1708 uint32_t
enableCommand(LocationTechnologyType techType)1709 GnssAdapter::enableCommand(LocationTechnologyType techType)
1710 {
1711     uint32_t sessionId = generateSessionId();
1712     LOC_LOGD("%s]: id %u techType %u", __func__, sessionId, techType);
1713 
1714     struct MsgEnableGnss : public LocMsg {
1715         GnssAdapter& mAdapter;
1716         LocApiBase& mApi;
1717         ContextBase& mContext;
1718         uint32_t mSessionId;
1719         LocationTechnologyType mTechType;
1720         inline MsgEnableGnss(GnssAdapter& adapter,
1721                              LocApiBase& api,
1722                              ContextBase& context,
1723                              uint32_t sessionId,
1724                              LocationTechnologyType techType) :
1725             LocMsg(),
1726             mAdapter(adapter),
1727             mApi(api),
1728             mContext(context),
1729             mSessionId(sessionId),
1730             mTechType(techType) {}
1731         inline virtual void proc() const {
1732             LocationError err = LOCATION_ERROR_SUCCESS;
1733             uint32_t powerVoteId = mAdapter.getPowerVoteId();
1734             if (mTechType != LOCATION_TECHNOLOGY_TYPE_GNSS) {
1735                 err = LOCATION_ERROR_INVALID_PARAMETER;
1736             } else if (powerVoteId > 0) {
1737                 err = LOCATION_ERROR_ALREADY_STARTED;
1738             } else {
1739                 mContext.modemPowerVote(true);
1740                 mAdapter.setPowerVoteId(mSessionId);
1741                 mApi.setGpsLock(GNSS_CONFIG_GPS_LOCK_NONE);
1742             }
1743             mAdapter.reportResponse(err, mSessionId);
1744         }
1745     };
1746 
1747     if (mContext != NULL) {
1748         sendMsg(new MsgEnableGnss(*this, *mLocApi, *mContext, sessionId, techType));
1749     } else {
1750         LOC_LOGE("%s]: Context is NULL", __func__);
1751     }
1752 
1753     return sessionId;
1754 }
1755 
1756 void
disableCommand(uint32_t id)1757 GnssAdapter::disableCommand(uint32_t id)
1758 {
1759     LOC_LOGD("%s]: id %u", __func__, id);
1760 
1761     struct MsgDisableGnss : public LocMsg {
1762         GnssAdapter& mAdapter;
1763         LocApiBase& mApi;
1764         ContextBase& mContext;
1765         uint32_t mSessionId;
1766         inline MsgDisableGnss(GnssAdapter& adapter,
1767                              LocApiBase& api,
1768                              ContextBase& context,
1769                              uint32_t sessionId) :
1770             LocMsg(),
1771             mAdapter(adapter),
1772             mApi(api),
1773             mContext(context),
1774             mSessionId(sessionId) {}
1775         inline virtual void proc() const {
1776             LocationError err = LOCATION_ERROR_SUCCESS;
1777             uint32_t powerVoteId = mAdapter.getPowerVoteId();
1778             if (powerVoteId != mSessionId) {
1779                 err = LOCATION_ERROR_ID_UNKNOWN;
1780             } else {
1781                 mContext.modemPowerVote(false);
1782                 mAdapter.setPowerVoteId(0);
1783                 mApi.setGpsLock(mAdapter.convertGpsLock(ContextBase::mGps_conf.GPS_LOCK));
1784             }
1785             mAdapter.reportResponse(err, mSessionId);
1786         }
1787     };
1788 
1789     if (mContext != NULL) {
1790         sendMsg(new MsgDisableGnss(*this, *mLocApi, *mContext, id));
1791     }
1792 
1793 }
1794 
1795 void
reportPositionEvent(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask,bool fromUlp)1796 GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation,
1797                                  const GpsLocationExtended& locationExtended,
1798                                  enum loc_sess_status status,
1799                                  LocPosTechMask techMask,
1800                                  bool fromUlp)
1801 {
1802     LOC_LOGD("%s]: fromUlp %u status %u", __func__, fromUlp, status);
1803 
1804     // if this event is not called from ULP, then try to call into ULP and return if successfull
1805     if (!fromUlp) {
1806         if (mUlpProxy->reportPosition(ulpLocation, locationExtended,
1807                                  status, techMask)) {
1808             return;
1809         }
1810     }
1811 
1812     struct MsgReportPosition : public LocMsg {
1813         GnssAdapter& mAdapter;
1814         const UlpLocation mUlpLocation;
1815         const GpsLocationExtended mLocationExtended;
1816         loc_sess_status mStatus;
1817         LocPosTechMask mTechMask;
1818         inline MsgReportPosition(GnssAdapter& adapter,
1819                                  const UlpLocation& ulpLocation,
1820                                  const GpsLocationExtended& locationExtended,
1821                                  loc_sess_status status,
1822                                  LocPosTechMask techMask) :
1823             LocMsg(),
1824             mAdapter(adapter),
1825             mUlpLocation(ulpLocation),
1826             mLocationExtended(locationExtended),
1827             mStatus(status),
1828             mTechMask(techMask) {}
1829         inline virtual void proc() const {
1830             // extract bug report info - this returns true if consumed by systemstatus
1831             SystemStatus* s = LocDualContext::getSystemStatus();
1832             if ((nullptr != s) && (LOC_SESS_SUCCESS == mStatus)){
1833                 s->eventPosition(mUlpLocation, mLocationExtended);
1834             }
1835             mAdapter.reportPosition(mUlpLocation, mLocationExtended, mStatus, mTechMask);
1836         }
1837     };
1838 
1839     sendMsg(new MsgReportPosition(*this, ulpLocation, locationExtended, status, techMask));
1840 }
1841 
1842 void
reportPosition(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask)1843 GnssAdapter::reportPosition(const UlpLocation& ulpLocation,
1844                             const GpsLocationExtended& locationExtended,
1845                             enum loc_sess_status status,
1846                             LocPosTechMask techMask)
1847 {
1848     bool reported = false;
1849     // what's in the if is... (line by line)
1850     // 1. this is a final fix; and
1851     //   1.1 it is a Satellite fix; or
1852     //   1.2 it is a sensor fix
1853     // 2. (must be intermediate fix... implicit)
1854     //   2.1 we accepte intermediate; and
1855     //   2.2 it is NOT the case that
1856     //   2.2.1 there is inaccuracy; and
1857     //   2.2.2 we care about inaccuracy; and
1858     //   2.2.3 the inaccuracy exceeds our tolerance
1859     if ((LOC_SESS_SUCCESS == status &&
1860               ((LOC_POS_TECH_MASK_SATELLITE |
1861                 LOC_POS_TECH_MASK_SENSORS   |
1862                 LOC_POS_TECH_MASK_HYBRID) &
1863                techMask)) ||
1864              (LOC_SESS_INTERMEDIATE == ContextBase::mGps_conf.INTERMEDIATE_POS &&
1865               !((ulpLocation.gpsLocation.flags &
1866                  LOC_GPS_LOCATION_HAS_ACCURACY) &&
1867                 (ContextBase::mGps_conf.ACCURACY_THRES != 0) &&
1868                 (ulpLocation.gpsLocation.accuracy >
1869                  ContextBase::mGps_conf.ACCURACY_THRES)))) {
1870         if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA) {
1871             mGnssSvIdUsedInPosAvail = true;
1872             mGnssSvIdUsedInPosition = locationExtended.gnss_sv_used_ids;
1873         }
1874         for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
1875             if (nullptr != it->second.trackingCb) {
1876                 Location location = {};
1877                 convertLocation(location, ulpLocation.gpsLocation, locationExtended, techMask);
1878                 it->second.trackingCb(location);
1879             }
1880             if (nullptr != it->second.gnssLocationInfoCb) {
1881                 GnssLocationInfoNotification locationInfo = {};
1882                 convertLocationInfo(locationInfo, locationExtended);
1883                 it->second.gnssLocationInfoCb(locationInfo);
1884             }
1885         }
1886         reported = true;
1887     } else {
1888         LOC_LOGI("%s: not reported. Status: %d, techMask: %d, flags %d, accuracy %f",
1889                 __func__, (int)status, (int)techMask, (int)ulpLocation.gpsLocation.flags,
1890                 (float)ulpLocation.gpsLocation.accuracy);
1891     }
1892 
1893     if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) {
1894         uint8_t generate_nmea = (reported && status != LOC_SESS_FAILURE);
1895         std::vector<std::string> nmeaArraystr;
1896         loc_nmea_generate_pos(ulpLocation, locationExtended, generate_nmea, nmeaArraystr);
1897         for (auto sentence : nmeaArraystr) {
1898             reportNmea(sentence.c_str(), sentence.length());
1899         }
1900     }
1901 
1902     // Free the allocated memory for rawData
1903     UlpLocation* gp = (UlpLocation*)&(ulpLocation);
1904     if (gp != NULL && gp->rawData != NULL)
1905     {
1906         delete (char*)gp->rawData;
1907         gp->rawData = NULL;
1908         gp->rawDataSize = 0;
1909     }
1910 }
1911 
1912 void
reportSvEvent(const GnssSvNotification & svNotify,bool fromUlp)1913 GnssAdapter::reportSvEvent(const GnssSvNotification& svNotify,
1914                            bool fromUlp)
1915 {
1916     LOC_LOGD("%s]: fromUlp %u", __func__, fromUlp);
1917 
1918     // if this event is not called from ULP, then try to call into ULP and return if successfull
1919     if (!fromUlp) {
1920         if (mUlpProxy->reportSv(svNotify)) {
1921             return;
1922         }
1923     }
1924 
1925     struct MsgReportSv : public LocMsg {
1926         GnssAdapter& mAdapter;
1927         const GnssSvNotification mSvNotify;
1928         inline MsgReportSv(GnssAdapter& adapter,
1929                            const GnssSvNotification& svNotify) :
1930             LocMsg(),
1931             mAdapter(adapter),
1932             mSvNotify(svNotify) {}
1933         inline virtual void proc() const {
1934             mAdapter.reportSv((GnssSvNotification&)mSvNotify);
1935         }
1936     };
1937 
1938     sendMsg(new MsgReportSv(*this, svNotify));
1939 }
1940 
1941 void
reportSv(GnssSvNotification & svNotify)1942 GnssAdapter::reportSv(GnssSvNotification& svNotify)
1943 {
1944     int numSv = svNotify.count;
1945     int16_t gnssSvId = 0;
1946     uint64_t svUsedIdMask = 0;
1947     for (int i=0; i < numSv; i++) {
1948         svUsedIdMask = 0;
1949         gnssSvId = svNotify.gnssSvs[i].svId;
1950         switch (svNotify.gnssSvs[i].type) {
1951             case GNSS_SV_TYPE_GPS:
1952                 if (mGnssSvIdUsedInPosAvail) {
1953                     svUsedIdMask = mGnssSvIdUsedInPosition.gps_sv_used_ids_mask;
1954                 }
1955                 break;
1956             case GNSS_SV_TYPE_GLONASS:
1957                 if (mGnssSvIdUsedInPosAvail) {
1958                     svUsedIdMask = mGnssSvIdUsedInPosition.glo_sv_used_ids_mask;
1959                 }
1960                 break;
1961             case GNSS_SV_TYPE_BEIDOU:
1962                 if (mGnssSvIdUsedInPosAvail) {
1963                     svUsedIdMask = mGnssSvIdUsedInPosition.bds_sv_used_ids_mask;
1964                 }
1965                 break;
1966             case GNSS_SV_TYPE_GALILEO:
1967                 if (mGnssSvIdUsedInPosAvail) {
1968                     svUsedIdMask = mGnssSvIdUsedInPosition.gal_sv_used_ids_mask;
1969                 }
1970                 break;
1971             case GNSS_SV_TYPE_QZSS:
1972                 if (mGnssSvIdUsedInPosAvail) {
1973                     svUsedIdMask = mGnssSvIdUsedInPosition.qzss_sv_used_ids_mask;
1974                 }
1975                 // QZSS SV id's need to reported as it is to framework, since
1976                 // framework expects it as it is. See GnssStatus.java.
1977                 // SV id passed to here by LocApi is 1-based.
1978                 svNotify.gnssSvs[i].svId += (QZSS_SV_PRN_MIN - 1);
1979                 break;
1980             default:
1981                 svUsedIdMask = 0;
1982                 break;
1983         }
1984 
1985         // If SV ID was used in previous position fix, then set USED_IN_FIX
1986         // flag, else clear the USED_IN_FIX flag.
1987         if (svUsedIdMask & (1 << (gnssSvId - 1))) {
1988             svNotify.gnssSvs[i].gnssSvOptionsMask |= GNSS_SV_OPTIONS_USED_IN_FIX_BIT;
1989         }
1990     }
1991 
1992     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
1993         if (nullptr != it->second.gnssSvCb) {
1994             it->second.gnssSvCb(svNotify);
1995         }
1996     }
1997 
1998     if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) {
1999         std::vector<std::string> nmeaArraystr;
2000         loc_nmea_generate_sv(svNotify, nmeaArraystr);
2001         for (auto sentence : nmeaArraystr) {
2002             reportNmea(sentence.c_str(), sentence.length());
2003         }
2004     }
2005 
2006     mGnssSvIdUsedInPosAvail = false;
2007 }
2008 
2009 void
reportNmeaEvent(const char * nmea,size_t length,bool fromUlp)2010 GnssAdapter::reportNmeaEvent(const char* nmea, size_t length, bool fromUlp)
2011 {
2012     // if this event is not called from ULP, then try to call into ULP and return if successfull
2013     if (!fromUlp && !loc_nmea_is_debug(nmea, length)) {
2014         if (mUlpProxy->reportNmea(nmea, length)) {
2015             return;
2016         }
2017     }
2018 
2019     struct MsgReportNmea : public LocMsg {
2020         GnssAdapter& mAdapter;
2021         const char* mNmea;
2022         size_t mLength;
2023         inline MsgReportNmea(GnssAdapter& adapter,
2024                              const char* nmea,
2025                              size_t length) :
2026             LocMsg(),
2027             mAdapter(adapter),
2028             mNmea(new char[length+1]),
2029             mLength(length) {
2030                 strlcpy((char*)mNmea, nmea, length+1);
2031             }
2032         inline virtual ~MsgReportNmea()
2033         {
2034             delete[] mNmea;
2035         }
2036         inline virtual void proc() const {
2037             // extract bug report info - this returns true if consumed by systemstatus
2038             bool ret = false;
2039             SystemStatus* s = LocDualContext::getSystemStatus();
2040             if (nullptr != s) {
2041                 ret = s->setNmeaString(mNmea, mLength);
2042             }
2043             if (false == ret) {
2044                 // forward NMEA message to upper layer
2045                 mAdapter.reportNmea(mNmea, mLength);
2046             }
2047         }
2048     };
2049 
2050     sendMsg(new MsgReportNmea(*this, nmea, length));
2051 }
2052 
2053 void
reportNmea(const char * nmea,size_t length)2054 GnssAdapter::reportNmea(const char* nmea, size_t length)
2055 {
2056     GnssNmeaNotification nmeaNotification = {};
2057     nmeaNotification.size = sizeof(GnssNmeaNotification);
2058 
2059     struct timeval tv;
2060     gettimeofday(&tv, (struct timezone *) NULL);
2061     int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
2062     nmeaNotification.timestamp = now;
2063     nmeaNotification.nmea = nmea;
2064     nmeaNotification.length = length;
2065 
2066     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2067         if (nullptr != it->second.gnssNmeaCb) {
2068             it->second.gnssNmeaCb(nmeaNotification);
2069         }
2070     }
2071 }
2072 
2073 bool
requestNiNotifyEvent(const GnssNiNotification & notify,const void * data)2074 GnssAdapter::requestNiNotifyEvent(const GnssNiNotification &notify, const void* data)
2075 {
2076     LOC_LOGI("%s]: notif_type: %d, timeout: %d, default_resp: %d"
2077              "requestor_id: %s (encoding: %d) text: %s text (encoding: %d) extras: %s",
2078              __func__, notify.type, notify.timeout, notify.timeoutResponse,
2079              notify.requestor, notify.requestorEncoding,
2080              notify.message, notify.messageEncoding, notify.extras);
2081 
2082     struct MsgReportNiNotify : public LocMsg {
2083         GnssAdapter& mAdapter;
2084         const GnssNiNotification mNotify;
2085         const void* mData;
2086         inline MsgReportNiNotify(GnssAdapter& adapter,
2087                                  const GnssNiNotification& notify,
2088                                  const void* data) :
2089             LocMsg(),
2090             mAdapter(adapter),
2091             mNotify(notify),
2092             mData(data) {}
2093         inline virtual void proc() const {
2094             mAdapter.requestNiNotify(mNotify, mData);
2095         }
2096     };
2097 
2098     sendMsg(new MsgReportNiNotify(*this, notify, data));
2099 
2100     return true;
2101 }
2102 
niThreadProc(void * args)2103 static void* niThreadProc(void *args)
2104 {
2105     NiSession* pSession = (NiSession*)args;
2106     int rc = 0;          /* return code from pthread calls */
2107 
2108     struct timeval present_time;
2109     struct timespec expire_time;
2110 
2111     pthread_mutex_lock(&pSession->tLock);
2112     /* Calculate absolute expire time */
2113     gettimeofday(&present_time, NULL);
2114     expire_time.tv_sec  = present_time.tv_sec + pSession->respTimeLeft;
2115     expire_time.tv_nsec = present_time.tv_usec * 1000;
2116     LOC_LOGD("%s]: time out set for abs time %ld with delay %d sec",
2117              __func__, (long)expire_time.tv_sec, pSession->respTimeLeft);
2118 
2119     while (!pSession->respRecvd) {
2120         rc = pthread_cond_timedwait(&pSession->tCond,
2121                                     &pSession->tLock,
2122                                     &expire_time);
2123         if (rc == ETIMEDOUT) {
2124             pSession->resp = GNSS_NI_RESPONSE_NO_RESPONSE;
2125             LOC_LOGD("%s]: time out after valting for specified time. Ret Val %d",
2126                      __func__, rc);
2127             break;
2128         }
2129     }
2130     LOC_LOGD("%s]: Java layer has sent us a user response and return value from "
2131              "pthread_cond_timedwait = %d pSession->resp is %u", __func__, rc, pSession->resp);
2132     pSession->respRecvd = false; /* Reset the user response flag for the next session*/
2133 
2134     // adding this check to support modem restart, in which case, we need the thread
2135     // to exit without calling sending data. We made sure that rawRequest is NULL in
2136     // loc_eng_ni_reset_on_engine_restart()
2137     GnssAdapter* adapter = pSession->adapter;
2138     GnssNiResponse resp;
2139     void* rawRequest = NULL;
2140     bool sendResponse = false;
2141 
2142     if (NULL != pSession->rawRequest) {
2143         if (pSession->resp != GNSS_NI_RESPONSE_IGNORE) {
2144             resp = pSession->resp;
2145             rawRequest = pSession->rawRequest;
2146             sendResponse = true;
2147         } else {
2148             free(pSession->rawRequest);
2149         }
2150         pSession->rawRequest = NULL;
2151     }
2152     pthread_mutex_unlock(&pSession->tLock);
2153 
2154     pSession->respTimeLeft = 0;
2155     pSession->reqID = 0;
2156 
2157     if (sendResponse) {
2158         adapter->gnssNiResponseCommand(resp, rawRequest);
2159     }
2160 
2161     return NULL;
2162 }
2163 
2164 bool
requestNiNotify(const GnssNiNotification & notify,const void * data)2165 GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data)
2166 {
2167     NiSession* pSession = NULL;
2168     gnssNiCallback gnssNiCb = nullptr;
2169 
2170     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2171         if (nullptr != it->second.gnssNiCb) {
2172             gnssNiCb = it->second.gnssNiCb;
2173             break;
2174         }
2175     }
2176     if (nullptr == gnssNiCb) {
2177         EXIT_LOG(%s, "no clients with gnssNiCb.");
2178         return false;
2179     }
2180 
2181     if (notify.type == GNSS_NI_TYPE_EMERGENCY_SUPL) {
2182         if (NULL != mNiData.sessionEs.rawRequest) {
2183             LOC_LOGI("%s]: supl es NI in progress, new supl es NI ignored, type: %d",
2184                      __func__, notify.type);
2185             if (NULL != data) {
2186                 free((void*)data);
2187             }
2188         } else {
2189             pSession = &mNiData.sessionEs;
2190         }
2191     } else {
2192         if (NULL != mNiData.session.rawRequest ||
2193             NULL != mNiData.sessionEs.rawRequest) {
2194             LOC_LOGI("%s]: supl NI in progress, new supl NI ignored, type: %d",
2195                      __func__, notify.type);
2196             if (NULL != data) {
2197                 free((void*)data);
2198             }
2199         } else {
2200             pSession = &mNiData.session;
2201         }
2202     }
2203 
2204     if (pSession) {
2205         /* Save request */
2206         pSession->rawRequest = (void*)data;
2207         pSession->reqID = ++mNiData.reqIDCounter;
2208         pSession->adapter = this;
2209 
2210         int sessionId = pSession->reqID;
2211 
2212         /* For robustness, spawn a thread at this point to timeout to clear up the notification
2213          * status, even though the OEM layer in java does not do so.
2214          **/
2215         pSession->respTimeLeft =
2216              5 + (notify.timeout != 0 ? notify.timeout : LOC_NI_NO_RESPONSE_TIME);
2217 
2218         int rc = 0;
2219         rc = pthread_create(&pSession->thread, NULL, niThreadProc, pSession);
2220         if (rc) {
2221             LOC_LOGE("%s]: Loc NI thread is not created.", __func__);
2222         }
2223         rc = pthread_detach(pSession->thread);
2224         if (rc) {
2225             LOC_LOGE("%s]: Loc NI thread is not detached.", __func__);
2226         }
2227 
2228         if (nullptr != gnssNiCb) {
2229             gnssNiCb(sessionId, notify);
2230         }
2231     }
2232 
2233     return true;
2234 }
2235 
2236 void
reportGnssMeasurementDataEvent(const GnssMeasurementsNotification & measurementsNotify)2237 GnssAdapter::reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& measurementsNotify)
2238 {
2239     LOC_LOGD("%s]: ", __func__);
2240 
2241     struct MsgReportGnssMeasurementData : public LocMsg {
2242         GnssAdapter& mAdapter;
2243         const GnssMeasurementsNotification mMeasurementsNotify;
2244         inline MsgReportGnssMeasurementData(GnssAdapter& adapter,
2245                                            const GnssMeasurementsNotification& measurementsNotify) :
2246             LocMsg(),
2247             mAdapter(adapter),
2248             mMeasurementsNotify(measurementsNotify) {}
2249         inline virtual void proc() const {
2250             mAdapter.reportGnssMeasurementData(mMeasurementsNotify);
2251         }
2252     };
2253 
2254     sendMsg(new MsgReportGnssMeasurementData(*this, measurementsNotify));
2255 }
2256 
2257 void
reportGnssMeasurementData(const GnssMeasurementsNotification & measurementsNotify)2258 GnssAdapter::reportGnssMeasurementData(const GnssMeasurementsNotification& measurementsNotify)
2259 {
2260     for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2261         if (nullptr != it->second.gnssMeasurementsCb) {
2262             it->second.gnssMeasurementsCb(measurementsNotify);
2263         }
2264     }
2265 }
2266 
2267 void
reportSvMeasurementEvent(GnssSvMeasurementSet & svMeasurementSet)2268 GnssAdapter::reportSvMeasurementEvent(GnssSvMeasurementSet &svMeasurementSet)
2269 {
2270     LOC_LOGD("%s]: ", __func__);
2271 
2272     // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary.
2273     mUlpProxy->reportSvMeasurement(svMeasurementSet);
2274 }
2275 
2276 void
reportSvPolynomialEvent(GnssSvPolynomial & svPolynomial)2277 GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial)
2278 {
2279     LOC_LOGD("%s]: ", __func__);
2280 
2281     // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary.
2282     mUlpProxy->reportSvPolynomial(svPolynomial);
2283 }
2284 
2285 /* INIT LOC AGPS MANAGER */
initAgpsCommand(void * statusV4Cb)2286 void GnssAdapter::initAgpsCommand(void* statusV4Cb){
2287 
2288     LOC_LOGI("GnssAdapter::initAgpsCommand");
2289 
2290     /* Set ATL open/close callbacks */
2291     AgpsAtlOpenStatusCb atlOpenStatusCb =
2292             [this](int handle, int isSuccess, char* apn,
2293                     AGpsBearerType bearerType, AGpsExtType agpsType) {
2294 
2295                 mLocApi->atlOpenStatus(
2296                         handle, isSuccess, apn, bearerType, agpsType);
2297             };
2298     AgpsAtlCloseStatusCb atlCloseStatusCb =
2299             [this](int handle, int isSuccess) {
2300 
2301                 mLocApi->atlCloseStatus(handle, isSuccess);
2302             };
2303 
2304     /* Register DS Client APIs */
2305     AgpsDSClientInitFn dsClientInitFn =
2306             [this](bool isDueToSSR) {
2307 
2308                 return mLocApi->initDataServiceClient(isDueToSSR);
2309             };
2310 
2311     AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn =
2312             [this] {
2313 
2314                 return mLocApi->openAndStartDataCall();
2315             };
2316 
2317     AgpsDSClientStopDataCallFn dsClientStopDataCallFn =
2318             [this] {
2319 
2320                 mLocApi->stopDataCall();
2321             };
2322 
2323     AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn =
2324             [this] {
2325 
2326                 mLocApi->closeDataCall();
2327             };
2328 
2329     AgpsDSClientReleaseFn dsClientReleaseFn =
2330             [this] {
2331 
2332                 mLocApi->releaseDataServiceClient();
2333             };
2334 
2335     /* Send Msg function */
2336     SendMsgToAdapterMsgQueueFn sendMsgFn =
2337             [this](LocMsg* msg) {
2338 
2339                 sendMsg(msg);
2340             };
2341 
2342     /* Message to initialize AGPS module */
2343     struct AgpsMsgInit: public LocMsg {
2344 
2345         AgpsManager* mAgpsManager;
2346 
2347         AgpsFrameworkInterface::AgnssStatusIpV4Cb mFrameworkStatusV4Cb;
2348 
2349         AgpsAtlOpenStatusCb mAtlOpenStatusCb;
2350         AgpsAtlCloseStatusCb mAtlCloseStatusCb;
2351 
2352         AgpsDSClientInitFn mDSClientInitFn;
2353         AgpsDSClientOpenAndStartDataCallFn mDSClientOpenAndStartDataCallFn;
2354         AgpsDSClientStopDataCallFn mDSClientStopDataCallFn;
2355         AgpsDSClientCloseDataCallFn mDSClientCloseDataCallFn;
2356         AgpsDSClientReleaseFn mDSClientReleaseFn;
2357 
2358         SendMsgToAdapterMsgQueueFn mSendMsgFn;
2359         GnssAdapter& mAdapter;
2360 
2361         inline AgpsMsgInit(AgpsManager* agpsManager,
2362                 AgpsFrameworkInterface::AgnssStatusIpV4Cb frameworkStatusV4Cb,
2363                 AgpsAtlOpenStatusCb atlOpenStatusCb,
2364                 AgpsAtlCloseStatusCb atlCloseStatusCb,
2365                 AgpsDSClientInitFn dsClientInitFn,
2366                 AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn,
2367                 AgpsDSClientStopDataCallFn dsClientStopDataCallFn,
2368                 AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn,
2369                 AgpsDSClientReleaseFn dsClientReleaseFn,
2370                 SendMsgToAdapterMsgQueueFn sendMsgFn,
2371                 GnssAdapter& adapter) :
2372                 LocMsg(), mAgpsManager(agpsManager), mFrameworkStatusV4Cb(
2373                         frameworkStatusV4Cb), mAtlOpenStatusCb(atlOpenStatusCb), mAtlCloseStatusCb(
2374                         atlCloseStatusCb), mDSClientInitFn(dsClientInitFn), mDSClientOpenAndStartDataCallFn(
2375                         dsClientOpenAndStartDataCallFn), mDSClientStopDataCallFn(
2376                         dsClientStopDataCallFn), mDSClientCloseDataCallFn(
2377                         dsClientCloseDataCallFn), mDSClientReleaseFn(
2378                         dsClientReleaseFn), mSendMsgFn(sendMsgFn),
2379                         mAdapter(adapter) {
2380 
2381             LOC_LOGV("AgpsMsgInit");
2382         }
2383 
2384         inline virtual void proc() const {
2385 
2386             LOC_LOGV("AgpsMsgInit::proc()");
2387 
2388             mAgpsManager->registerCallbacks(mFrameworkStatusV4Cb, mAtlOpenStatusCb,
2389                     mAtlCloseStatusCb, mDSClientInitFn,
2390                     mDSClientOpenAndStartDataCallFn, mDSClientStopDataCallFn,
2391                     mDSClientCloseDataCallFn, mDSClientReleaseFn, mSendMsgFn);
2392 
2393             mAgpsManager->createAgpsStateMachines();
2394 
2395             /* Register for AGPS event mask */
2396             mAdapter.updateEvtMask(LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST,
2397                                    LOC_REGISTRATION_MASK_ENABLED);
2398         }
2399     };
2400 
2401     /* Send message to initialize AGPS Manager */
2402     sendMsg(new AgpsMsgInit(
2403                 &mAgpsManager,
2404                 (AgpsFrameworkInterface::AgnssStatusIpV4Cb)statusV4Cb,
2405                 atlOpenStatusCb, atlCloseStatusCb,
2406                 dsClientInitFn, dsClientOpenAndStartDataCallFn,
2407                 dsClientStopDataCallFn, dsClientCloseDataCallFn,
2408                 dsClientReleaseFn,
2409                 sendMsgFn,
2410                 *this));
2411 }
2412 
2413 /* GnssAdapter::requestATL
2414  * Method triggered in QMI thread as part of handling below message:
2415  * eQMI_LOC_SERVER_REQUEST_OPEN_V02
2416  * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
2417  * eQMI_LOC_WWAN_TYPE_INTERNET_V02
2418  * eQMI_LOC_WWAN_TYPE_AGNSS_V02 */
requestATL(int connHandle,LocAGpsType agpsType)2419 bool GnssAdapter::requestATL(int connHandle, LocAGpsType agpsType){
2420 
2421     LOC_LOGI("GnssAdapter::requestATL");
2422 
2423     sendMsg( new AgpsMsgRequestATL(
2424              &mAgpsManager, connHandle, (AGpsExtType)agpsType));
2425 
2426     return true;
2427 }
2428 
2429 /* GnssAdapter::requestSuplES
2430  * Method triggered in QMI thread as part of handling below message:
2431  * eQMI_LOC_SERVER_REQUEST_OPEN_V02
2432  * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
2433  * eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02 */
requestSuplES(int connHandle)2434 bool GnssAdapter::requestSuplES(int connHandle){
2435 
2436     LOC_LOGI("GnssAdapter::requestSuplES");
2437 
2438     sendMsg( new AgpsMsgRequestATL(
2439              &mAgpsManager, connHandle, LOC_AGPS_TYPE_SUPL_ES));
2440 
2441     return true;
2442 }
2443 
2444 /* GnssAdapter::releaseATL
2445  * Method triggered in QMI thread as part of handling below message:
2446  * eQMI_LOC_SERVER_REQUEST_CLOSE_V02
2447  * Triggers teardown of an existing AGPS call */
releaseATL(int connHandle)2448 bool GnssAdapter::releaseATL(int connHandle){
2449 
2450     LOC_LOGI("GnssAdapter::releaseATL");
2451 
2452     /* Release SUPL/INTERNET/SUPL_ES ATL */
2453     struct AgpsMsgReleaseATL: public LocMsg {
2454 
2455         AgpsManager* mAgpsManager;
2456         int mConnHandle;
2457 
2458         inline AgpsMsgReleaseATL(AgpsManager* agpsManager, int connHandle) :
2459                 LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle) {
2460 
2461             LOC_LOGV("AgpsMsgReleaseATL");
2462         }
2463 
2464         inline virtual void proc() const {
2465 
2466             LOC_LOGV("AgpsMsgReleaseATL::proc()");
2467             mAgpsManager->releaseATL(mConnHandle);
2468         }
2469     };
2470 
2471     sendMsg( new AgpsMsgReleaseATL(&mAgpsManager, connHandle));
2472 
2473     return true;
2474 }
2475 
2476 /* GnssAdapter::reportDataCallOpened
2477  * DS Client data call opened successfully.
2478  * Send message to AGPS Manager to handle. */
reportDataCallOpened()2479 bool GnssAdapter::reportDataCallOpened(){
2480 
2481     LOC_LOGI("GnssAdapter::reportDataCallOpened");
2482 
2483     struct AgpsMsgSuplEsOpened: public LocMsg {
2484 
2485         AgpsManager* mAgpsManager;
2486 
2487         inline AgpsMsgSuplEsOpened(AgpsManager* agpsManager) :
2488                 LocMsg(), mAgpsManager(agpsManager) {
2489 
2490             LOC_LOGV("AgpsMsgSuplEsOpened");
2491         }
2492 
2493         inline virtual void proc() const {
2494 
2495             LOC_LOGV("AgpsMsgSuplEsOpened::proc()");
2496             mAgpsManager->reportDataCallOpened();
2497         }
2498     };
2499 
2500     sendMsg( new AgpsMsgSuplEsOpened(&mAgpsManager));
2501 
2502     return true;
2503 }
2504 
2505 /* GnssAdapter::reportDataCallClosed
2506  * DS Client data call closed.
2507  * Send message to AGPS Manager to handle. */
reportDataCallClosed()2508 bool GnssAdapter::reportDataCallClosed(){
2509 
2510     LOC_LOGI("GnssAdapter::reportDataCallClosed");
2511 
2512     struct AgpsMsgSuplEsClosed: public LocMsg {
2513 
2514         AgpsManager* mAgpsManager;
2515 
2516         inline AgpsMsgSuplEsClosed(AgpsManager* agpsManager) :
2517                 LocMsg(), mAgpsManager(agpsManager) {
2518 
2519             LOC_LOGV("AgpsMsgSuplEsClosed");
2520         }
2521 
2522         inline virtual void proc() const {
2523 
2524             LOC_LOGV("AgpsMsgSuplEsClosed::proc()");
2525             mAgpsManager->reportDataCallClosed();
2526         }
2527     };
2528 
2529     sendMsg( new AgpsMsgSuplEsClosed(&mAgpsManager));
2530 
2531     return true;
2532 }
2533 
dataConnOpenCommand(AGpsExtType agpsType,const char * apnName,int apnLen,LocApnIpType ipType)2534 void GnssAdapter::dataConnOpenCommand(
2535         AGpsExtType agpsType,
2536         const char* apnName, int apnLen, LocApnIpType ipType){
2537 
2538     LOC_LOGI("GnssAdapter::frameworkDataConnOpen");
2539 
2540     struct AgpsMsgAtlOpenSuccess: public LocMsg {
2541 
2542         AgpsManager* mAgpsManager;
2543         AGpsExtType mAgpsType;
2544         char* mApnName;
2545         int mApnLen;
2546         LocApnIpType mIpType;
2547 
2548         inline AgpsMsgAtlOpenSuccess(AgpsManager* agpsManager, AGpsExtType agpsType,
2549                 const char* apnName, int apnLen, LocApnIpType ipType) :
2550                 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType), mApnName(
2551                         new char[apnLen + 1]), mApnLen(apnLen), mIpType(ipType) {
2552 
2553             LOC_LOGV("AgpsMsgAtlOpenSuccess");
2554             memcpy(mApnName, apnName, apnLen);
2555             mApnName[apnLen] = 0;
2556         }
2557 
2558         inline ~AgpsMsgAtlOpenSuccess() {
2559             delete[] mApnName;
2560         }
2561 
2562         inline virtual void proc() const {
2563 
2564             LOC_LOGV("AgpsMsgAtlOpenSuccess::proc()");
2565             mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, mApnLen,
2566                     mIpType);
2567         }
2568     };
2569 
2570     sendMsg( new AgpsMsgAtlOpenSuccess(
2571             &mAgpsManager, (AGpsExtType)agpsType, apnName, apnLen, ipType));
2572 }
2573 
dataConnClosedCommand(AGpsExtType agpsType)2574 void GnssAdapter::dataConnClosedCommand(AGpsExtType agpsType){
2575 
2576     LOC_LOGI("GnssAdapter::frameworkDataConnClosed");
2577 
2578     struct AgpsMsgAtlClosed: public LocMsg {
2579 
2580         AgpsManager* mAgpsManager;
2581         AGpsExtType mAgpsType;
2582 
2583         inline AgpsMsgAtlClosed(AgpsManager* agpsManager, AGpsExtType agpsType) :
2584                 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
2585 
2586             LOC_LOGV("AgpsMsgAtlClosed");
2587         }
2588 
2589         inline virtual void proc() const {
2590 
2591             LOC_LOGV("AgpsMsgAtlClosed::proc()");
2592             mAgpsManager->reportAtlClosed(mAgpsType);
2593         }
2594     };
2595 
2596     sendMsg( new AgpsMsgAtlClosed(&mAgpsManager, (AGpsExtType)agpsType));
2597 }
2598 
dataConnFailedCommand(AGpsExtType agpsType)2599 void GnssAdapter::dataConnFailedCommand(AGpsExtType agpsType){
2600 
2601     LOC_LOGI("GnssAdapter::frameworkDataConnFailed");
2602 
2603     struct AgpsMsgAtlOpenFailed: public LocMsg {
2604 
2605         AgpsManager* mAgpsManager;
2606         AGpsExtType mAgpsType;
2607 
2608         inline AgpsMsgAtlOpenFailed(AgpsManager* agpsManager, AGpsExtType agpsType) :
2609                 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
2610 
2611             LOC_LOGV("AgpsMsgAtlOpenFailed");
2612         }
2613 
2614         inline virtual void proc() const {
2615 
2616             LOC_LOGV("AgpsMsgAtlOpenFailed::proc()");
2617             mAgpsManager->reportAtlOpenFailed(mAgpsType);
2618         }
2619     };
2620 
2621     sendMsg( new AgpsMsgAtlOpenFailed(&mAgpsManager, (AGpsExtType)agpsType));
2622 }
2623 
convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo> & out,const GnssSvType & in_constellation,const SystemStatusReports & in)2624 void GnssAdapter::convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo>& out,
2625                                        const GnssSvType& in_constellation,
2626                                        const SystemStatusReports& in)
2627 {
2628     uint64_t sv_mask = 0ULL;
2629     uint32_t svid_min = 0;
2630     uint32_t svid_num = 0;
2631     uint32_t svid_idx = 0;
2632 
2633     uint64_t eph_health_good_mask = 0ULL;
2634     uint64_t eph_health_bad_mask = 0ULL;
2635     uint64_t server_perdiction_available_mask = 0ULL;
2636     float server_perdiction_age = 0.0f;
2637 
2638     // set constellationi based parameters
2639     switch (in_constellation) {
2640         case GNSS_SV_TYPE_GPS:
2641             svid_min = GNSS_BUGREPORT_GPS_MIN;
2642             svid_num = GPS_NUM;
2643             svid_idx = 0;
2644             if (!in.mSvHealth.empty()) {
2645                 eph_health_good_mask = in.mSvHealth.back().mGpsGoodMask;
2646                 eph_health_bad_mask  = in.mSvHealth.back().mGpsBadMask;
2647             }
2648             if (!in.mXtra.empty()) {
2649                 server_perdiction_available_mask = in.mXtra.back().mGpsXtraValid;
2650                 server_perdiction_age = (float)(in.mXtra.back().mGpsXtraAge);
2651             }
2652             break;
2653         case GNSS_SV_TYPE_GLONASS:
2654             svid_min = GNSS_BUGREPORT_GLO_MIN;
2655             svid_num = GLO_NUM;
2656             svid_idx = GPS_NUM;
2657             if (!in.mSvHealth.empty()) {
2658                 eph_health_good_mask = in.mSvHealth.back().mGloGoodMask;
2659                 eph_health_bad_mask  = in.mSvHealth.back().mGloBadMask;
2660             }
2661             if (!in.mXtra.empty()) {
2662                 server_perdiction_available_mask = in.mXtra.back().mGloXtraValid;
2663                 server_perdiction_age = (float)(in.mXtra.back().mGloXtraAge);
2664             }
2665             break;
2666         case GNSS_SV_TYPE_QZSS:
2667             svid_min = GNSS_BUGREPORT_QZSS_MIN;
2668             svid_num = QZSS_NUM;
2669             svid_idx = GPS_NUM+GLO_NUM+BDS_NUM+GAL_NUM;
2670             if (!in.mSvHealth.empty()) {
2671                 eph_health_good_mask = in.mSvHealth.back().mQzssGoodMask;
2672                 eph_health_bad_mask  = in.mSvHealth.back().mQzssBadMask;
2673             }
2674             if (!in.mXtra.empty()) {
2675                 server_perdiction_available_mask = in.mXtra.back().mQzssXtraValid;
2676                 server_perdiction_age = (float)(in.mXtra.back().mQzssXtraAge);
2677             }
2678             break;
2679         case GNSS_SV_TYPE_BEIDOU:
2680             svid_min = GNSS_BUGREPORT_BDS_MIN;
2681             svid_num = BDS_NUM;
2682             svid_idx = GPS_NUM+GLO_NUM;
2683             if (!in.mSvHealth.empty()) {
2684                 eph_health_good_mask = in.mSvHealth.back().mBdsGoodMask;
2685                 eph_health_bad_mask  = in.mSvHealth.back().mBdsBadMask;
2686             }
2687             if (!in.mXtra.empty()) {
2688                 server_perdiction_available_mask = in.mXtra.back().mBdsXtraValid;
2689                 server_perdiction_age = (float)(in.mXtra.back().mBdsXtraAge);
2690             }
2691             break;
2692         case GNSS_SV_TYPE_GALILEO:
2693             svid_min = GNSS_BUGREPORT_GAL_MIN;
2694             svid_num = GAL_NUM;
2695             svid_idx = GPS_NUM+GLO_NUM+BDS_NUM;
2696             if (!in.mSvHealth.empty()) {
2697                 eph_health_good_mask = in.mSvHealth.back().mGalGoodMask;
2698                 eph_health_bad_mask  = in.mSvHealth.back().mGalBadMask;
2699             }
2700             if (!in.mXtra.empty()) {
2701                 server_perdiction_available_mask = in.mXtra.back().mGalXtraValid;
2702                 server_perdiction_age = (float)(in.mXtra.back().mGalXtraAge);
2703             }
2704             break;
2705         default:
2706             return;
2707     }
2708 
2709     // extract each sv info from systemstatus report
2710     for(uint32_t i=0; i<svid_num; i++) {
2711 
2712         GnssDebugSatelliteInfo s = {};
2713         s.size = sizeof(s);
2714         s.svid = i + svid_min;
2715         s.constellation = in_constellation;
2716 
2717         if (!in.mNavData.empty()) {
2718             s.mEphemerisType   = in.mNavData.back().mNav[svid_idx+i].mType;
2719             s.mEphemerisSource = in.mNavData.back().mNav[svid_idx+i].mSource;
2720         }
2721         else {
2722             s.mEphemerisType   = GNSS_EPH_TYPE_UNKNOWN;
2723             s.mEphemerisSource = GNSS_EPH_SOURCE_UNKNOWN;
2724         }
2725 
2726         sv_mask = 0x1ULL << i;
2727         if (eph_health_good_mask & sv_mask) {
2728             s.mEphemerisHealth = GNSS_EPH_HEALTH_GOOD;
2729         }
2730         else if (eph_health_bad_mask & sv_mask) {
2731             s.mEphemerisHealth = GNSS_EPH_HEALTH_BAD;
2732         }
2733         else {
2734             s.mEphemerisHealth = GNSS_EPH_HEALTH_UNKNOWN;
2735         }
2736 
2737         if (!in.mNavData.empty()) {
2738             s.ephemerisAgeSeconds =
2739                 (float)(in.mNavData.back().mNav[svid_idx+i].mAgeSec);
2740         }
2741         else {
2742             s.ephemerisAgeSeconds = 0.0f;
2743         }
2744 
2745         if (server_perdiction_available_mask & sv_mask) {
2746             s.serverPredictionIsAvailable = true;
2747         }
2748         else {
2749             s.serverPredictionIsAvailable = false;
2750         }
2751 
2752         s.serverPredictionAgeSeconds = server_perdiction_age;
2753         out.push_back(s);
2754     }
2755 
2756     return;
2757 }
2758 
getDebugReport(GnssDebugReport & r)2759 bool GnssAdapter::getDebugReport(GnssDebugReport& r)
2760 {
2761     LOC_LOGD("%s]: ", __func__);
2762 
2763     SystemStatus* systemstatus = LocDualContext::getSystemStatus();
2764     if (nullptr == systemstatus) {
2765         return false;
2766     }
2767 
2768     SystemStatusReports reports = {};
2769     systemstatus->getReport(reports, true);
2770 
2771     r.size = sizeof(r);
2772 
2773     // location block
2774     r.mLocation.size = sizeof(r.mLocation);
2775     if(!reports.mLocation.empty() && reports.mLocation.back().mValid) {
2776         r.mLocation.mValid = true;
2777         r.mLocation.mLocation.latitude =
2778             reports.mLocation.back().mLocation.gpsLocation.latitude;
2779         r.mLocation.mLocation.longitude =
2780             reports.mLocation.back().mLocation.gpsLocation.longitude;
2781         r.mLocation.mLocation.altitude =
2782             reports.mLocation.back().mLocation.gpsLocation.altitude;
2783         r.mLocation.mLocation.speed =
2784             (double)(reports.mLocation.back().mLocation.gpsLocation.speed);
2785         r.mLocation.mLocation.bearing =
2786             (double)(reports.mLocation.back().mLocation.gpsLocation.bearing);
2787         r.mLocation.mLocation.accuracy =
2788             (double)(reports.mLocation.back().mLocation.gpsLocation.accuracy);
2789 
2790         r.mLocation.verticalAccuracyMeters =
2791             reports.mLocation.back().mLocationEx.vert_unc;
2792         r.mLocation.speedAccuracyMetersPerSecond =
2793             reports.mLocation.back().mLocationEx.speed_unc;
2794         r.mLocation.bearingAccuracyDegrees =
2795             reports.mLocation.back().mLocationEx.bearing_unc;
2796 
2797         r.mLocation.mUtcReported =
2798             reports.mLocation.back().mUtcReported;
2799     }
2800     else if(!reports.mBestPosition.empty() && reports.mBestPosition.back().mValid) {
2801         r.mLocation.mValid = true;
2802         r.mLocation.mLocation.latitude =
2803                 (double)(reports.mBestPosition.back().mBestLat) * RAD2DEG;
2804         r.mLocation.mLocation.longitude =
2805                 (double)(reports.mBestPosition.back().mBestLon) * RAD2DEG;
2806         r.mLocation.mLocation.altitude = reports.mBestPosition.back().mBestAlt;
2807         r.mLocation.mUtcReported = reports.mBestPosition.back().mUtcReported;
2808     }
2809     else {
2810         r.mLocation.mValid = false;
2811     }
2812 
2813     if (r.mLocation.mValid) {
2814         LOC_LOGV("getDebugReport - lat=%f lon=%f alt=%f speed=%f",
2815             r.mLocation.mLocation.latitude,
2816             r.mLocation.mLocation.longitude,
2817             r.mLocation.mLocation.altitude,
2818             r.mLocation.mLocation.speed);
2819     }
2820 
2821     // time block
2822     r.mTime.size = sizeof(r.mTime);
2823     if(!reports.mTimeAndClock.empty() && reports.mTimeAndClock.back().mTimeValid) {
2824         r.mTime.mValid = true;
2825         r.mTime.timeEstimate =
2826             (((int64_t)(reports.mTimeAndClock.back().mGpsWeek)*7 +
2827                         GNSS_UTC_TIME_OFFSET)*24*60*60 -
2828               (int64_t)(reports.mTimeAndClock.back().mLeapSeconds))*1000ULL +
2829               (int64_t)(reports.mTimeAndClock.back().mGpsTowMs);
2830 
2831         r.mTime.timeUncertaintyNs =
2832             (float)((reports.mTimeAndClock.back().mTimeUnc +
2833                      reports.mTimeAndClock.back().mLeapSecUnc)*1000);
2834         r.mTime.frequencyUncertaintyNsPerSec =
2835             (float)(reports.mTimeAndClock.back().mClockFreqBiasUnc);
2836         LOC_LOGV("getDebugReport - timeestimate=%ld unc=%f frequnc=%f",
2837                 r.mTime.timeEstimate,
2838                 r.mTime.timeUncertaintyNs, r.mTime.frequencyUncertaintyNsPerSec);
2839     }
2840     else {
2841         r.mTime.mValid = false;
2842     }
2843 
2844     // satellite info block
2845     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GPS, reports);
2846     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GLONASS, reports);
2847     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_QZSS, reports);
2848     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_BEIDOU, reports);
2849     convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GALILEO, reports);
2850     LOC_LOGV("getDebugReport - satellite=%lu", r.mSatelliteInfo.size());
2851 
2852     return true;
2853 }