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