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