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