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
30#define LOG_NDDEBUG 0
31#define LOG_TAG "LocSvc_GnssAPIClient"
32
33#include <log_util.h>
34#include <loc_cfg.h>
35
36#include "LocationUtil.h"
37#include "GnssAPIClient.h"
38
39namespace android {
40namespace hardware {
41namespace gnss {
42namespace V1_0 {
43namespace implementation {
44
45static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out);
46
47GnssAPIClient::GnssAPIClient(const sp<IGnssCallback>& gpsCb,
48    const sp<IGnssNiCallback>& niCb) :
49    LocationAPIClientBase(),
50    mGnssCbIface(nullptr),
51    mGnssNiCbIface(nullptr),
52    mLocationCapabilitiesMask(0)
53{
54    LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
55
56    // set default LocationOptions.
57    memset(&mLocationOptions, 0, sizeof(LocationOptions));
58    mLocationOptions.size = sizeof(LocationOptions);
59    mLocationOptions.minInterval = 1000;
60    mLocationOptions.minDistance = 0;
61    mLocationOptions.mode = GNSS_SUPL_MODE_STANDALONE;
62
63    gnssUpdateCallbacks(gpsCb, niCb);
64}
65
66GnssAPIClient::~GnssAPIClient()
67{
68    LOC_LOGD("%s]: ()", __FUNCTION__);
69}
70
71// for GpsInterface
72void GnssAPIClient::gnssUpdateCallbacks(const sp<IGnssCallback>& gpsCb,
73    const sp<IGnssNiCallback>& niCb)
74{
75    LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb);
76
77    mGnssCbIface = gpsCb;
78    mGnssNiCbIface = niCb;
79
80    LocationCallbacks locationCallbacks;
81    locationCallbacks.size = sizeof(LocationCallbacks);
82
83    locationCallbacks.trackingCb = nullptr;
84    if (mGnssCbIface != nullptr) {
85        locationCallbacks.trackingCb = [this](Location location) {
86            onTrackingCb(location);
87        };
88    }
89
90    locationCallbacks.batchingCb = nullptr;
91    locationCallbacks.geofenceBreachCb = nullptr;
92    locationCallbacks.geofenceStatusCb = nullptr;
93    locationCallbacks.gnssLocationInfoCb = nullptr;
94
95    locationCallbacks.gnssNiCb = nullptr;
96    if (mGnssNiCbIface != nullptr) {
97        locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotification) {
98            onGnssNiCb(id, gnssNiNotification);
99        };
100    }
101
102    locationCallbacks.gnssSvCb = nullptr;
103    if (mGnssCbIface != nullptr) {
104        locationCallbacks.gnssSvCb = [this](GnssSvNotification gnssSvNotification) {
105            onGnssSvCb(gnssSvNotification);
106        };
107    }
108
109    locationCallbacks.gnssNmeaCb = nullptr;
110    if (mGnssCbIface != nullptr) {
111        locationCallbacks.gnssNmeaCb = [this](GnssNmeaNotification gnssNmeaNotification) {
112            onGnssNmeaCb(gnssNmeaNotification);
113        };
114    }
115
116    locationCallbacks.gnssMeasurementsCb = nullptr;
117
118    locAPISetCallbacks(locationCallbacks);
119}
120
121bool GnssAPIClient::gnssStart()
122{
123    LOC_LOGD("%s]: ()", __FUNCTION__);
124    bool retVal = true;
125    locAPIStartTracking(mLocationOptions);
126    return retVal;
127}
128
129bool GnssAPIClient::gnssStop()
130{
131    LOC_LOGD("%s]: ()", __FUNCTION__);
132    bool retVal = true;
133    locAPIStopTracking();
134    return retVal;
135}
136
137void GnssAPIClient::gnssDeleteAidingData(IGnss::GnssAidingData aidingDataFlags)
138{
139    LOC_LOGD("%s]: (%02hx)", __FUNCTION__, aidingDataFlags);
140    GnssAidingData data;
141    memset(&data, 0, sizeof (GnssAidingData));
142    data.sv.svTypeMask = GNSS_AIDING_DATA_SV_TYPE_GPS |
143        GNSS_AIDING_DATA_SV_TYPE_GLONASS |
144        GNSS_AIDING_DATA_SV_TYPE_QZSS |
145        GNSS_AIDING_DATA_SV_TYPE_BEIDOU |
146        GNSS_AIDING_DATA_SV_TYPE_GALILEO;
147
148    if (aidingDataFlags == IGnss::GnssAidingData::DELETE_ALL)
149        data.deleteAll = true;
150    else {
151        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_EPHEMERIS)
152            data.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS;
153        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_ALMANAC)
154            data.sv.svMask |= GNSS_AIDING_DATA_SV_ALMANAC;
155        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_POSITION)
156            data.common.mask |= GNSS_AIDING_DATA_COMMON_POSITION;
157        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_TIME)
158            data.common.mask |= GNSS_AIDING_DATA_COMMON_TIME;
159        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_IONO)
160            data.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE;
161        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_UTC)
162            data.common.mask |= GNSS_AIDING_DATA_COMMON_UTC;
163        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_HEALTH)
164            data.sv.svMask |= GNSS_AIDING_DATA_SV_HEALTH;
165        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVDIR)
166            data.sv.svMask |= GNSS_AIDING_DATA_SV_DIRECTION;
167        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVSTEER)
168            data.sv.svMask |= GNSS_AIDING_DATA_SV_STEER;
169        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SADATA)
170            data.sv.svMask |= GNSS_AIDING_DATA_SV_SA_DATA;
171        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_RTI)
172            data.common.mask |= GNSS_AIDING_DATA_COMMON_RTI;
173        if (aidingDataFlags & IGnss::GnssAidingData::DELETE_CELLDB_INFO)
174            data.common.mask |= GNSS_AIDING_DATA_COMMON_CELLDB;
175    }
176    locAPIGnssDeleteAidingData(data);
177}
178
179bool GnssAPIClient::gnssSetPositionMode(IGnss::GnssPositionMode mode,
180        IGnss::GnssPositionRecurrence recurrence, uint32_t minIntervalMs,
181        uint32_t preferredAccuracyMeters, uint32_t preferredTimeMs)
182{
183    LOC_LOGD("%s]: (%d %d %d %d %d)", __FUNCTION__,
184            (int)mode, recurrence, minIntervalMs, preferredAccuracyMeters, preferredTimeMs);
185    bool retVal = true;
186    memset(&mLocationOptions, 0, sizeof(LocationOptions));
187    mLocationOptions.size = sizeof(LocationOptions);
188    mLocationOptions.minInterval = minIntervalMs;
189    mLocationOptions.minDistance = preferredAccuracyMeters;
190    if (mode == IGnss::GnssPositionMode::STANDALONE)
191        mLocationOptions.mode = GNSS_SUPL_MODE_STANDALONE;
192    else if (mode == IGnss::GnssPositionMode::MS_BASED)
193        mLocationOptions.mode = GNSS_SUPL_MODE_MSB;
194    else if (mode ==  IGnss::GnssPositionMode::MS_ASSISTED)
195        mLocationOptions.mode = GNSS_SUPL_MODE_MSA;
196    return retVal;
197}
198
199// for GpsNiInterface
200void GnssAPIClient::gnssNiRespond(int32_t notifId,
201        IGnssNiCallback::GnssUserResponseType userResponse)
202{
203    LOC_LOGD("%s]: (%d %d)", __FUNCTION__, notifId, static_cast<int>(userResponse));
204    GnssNiResponse data = GNSS_NI_RESPONSE_IGNORE;
205    if (userResponse == IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT)
206        data = GNSS_NI_RESPONSE_ACCEPT;
207    else if (userResponse == IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY)
208        data = GNSS_NI_RESPONSE_DENY;
209    else if (userResponse == IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP)
210        data = GNSS_NI_RESPONSE_NO_RESPONSE;
211    locAPIGnssNiResponse(notifId, data);
212}
213
214// for GnssConfigurationInterface
215void GnssAPIClient::gnssConfigurationUpdate(const GnssConfig& gnssConfig)
216{
217    LOC_LOGD("%s]: (%02x)", __FUNCTION__, gnssConfig.flags);
218    locAPIGnssUpdateConfig(gnssConfig);
219}
220
221// callbacks
222void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask)
223{
224    LOC_LOGD("%s]: (%02x)", __FUNCTION__, capabilitiesMask);
225    mLocationCapabilitiesMask = capabilitiesMask;
226    if (mGnssCbIface != nullptr) {
227        uint32_t data = 0;
228        if ((capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT) ||
229                (capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT) ||
230                (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT) ||
231                (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT))
232            data |= IGnssCallback::Capabilities::SCHEDULING;
233        if (capabilitiesMask & LOCATION_CAPABILITIES_GEOFENCE_BIT)
234            data |= IGnssCallback::Capabilities::GEOFENCING;
235        if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT)
236            data |= IGnssCallback::Capabilities::MEASUREMENTS;
237        if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSB_BIT)
238            data |= IGnssCallback::Capabilities::MSB;
239        if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSA_BIT)
240            data |= IGnssCallback::Capabilities::MSA;
241        mGnssCbIface->gnssSetCapabilitesCb(data);
242    }
243    if (mGnssCbIface != nullptr) {
244        IGnssCallback::GnssSystemInfo gnssInfo;
245        gnssInfo.yearOfHw = 2015;
246        if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) {
247            gnssInfo.yearOfHw = 2017;
248        }
249        LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw);
250        mGnssCbIface->gnssSetSystemInfoCb(gnssInfo);
251    }
252}
253
254void GnssAPIClient::onTrackingCb(Location location)
255{
256    LOC_LOGD("%s]: (flags: %02x)", __FUNCTION__, location.flags);
257    if (mGnssCbIface != nullptr) {
258        GnssLocation gnssLocation;
259        convertGnssLocation(location, gnssLocation);
260        mGnssCbIface->gnssLocationCb(gnssLocation);
261    }
262}
263
264void GnssAPIClient::onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification)
265{
266    LOC_LOGD("%s]: (id: %d)", __FUNCTION__, id);
267
268    if (mGnssNiCbIface == nullptr) {
269        LOC_LOGE("%s]: mGnssNiCbIface is nullptr", __FUNCTION__);
270        return;
271    }
272
273    IGnssNiCallback::GnssNiNotification notificationGnss;
274
275    notificationGnss.notificationId = id;
276
277    if (gnssNiNotification.type == GNSS_NI_TYPE_VOICE)
278        notificationGnss.niType = IGnssNiCallback::GnssNiType::VOICE;
279    else if (gnssNiNotification.type == GNSS_NI_TYPE_SUPL)
280        notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_SUPL;
281    else if (gnssNiNotification.type == GNSS_NI_TYPE_CONTROL_PLANE)
282        notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_CTRL_PLANE;
283    // GNSS_NI_TYPE_EMERGENCY_SUPL not supported
284
285    if (gnssNiNotification.options == GNSS_NI_OPTIONS_NOTIFICATION)
286        notificationGnss.notifyFlags =
287            static_cast<uint32_t>(IGnssNiCallback::GnssNiNotifyFlags::NEED_NOTIFY);
288    else if (gnssNiNotification.options == GNSS_NI_OPTIONS_VERIFICATION)
289        notificationGnss.notifyFlags =
290            static_cast<uint32_t>(IGnssNiCallback::GnssNiNotifyFlags::NEED_VERIFY);
291    else if (gnssNiNotification.options == GNSS_NI_OPTIONS_PRIVACY_OVERRIDE)
292        notificationGnss.notifyFlags =
293            static_cast<uint32_t>(IGnssNiCallback::GnssNiNotifyFlags::PRIVACY_OVERRIDE);
294
295    notificationGnss.timeoutSec = gnssNiNotification.timeout;
296
297    if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_ACCEPT)
298        notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT;
299    else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_DENY)
300        notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY;
301    else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_NO_RESPONSE ||
302            gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_IGNORE)
303        notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP;
304
305    notificationGnss.requestorId = gnssNiNotification.requestor;
306
307    notificationGnss.notificationMessage = gnssNiNotification.message;
308
309    if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_NONE)
310        notificationGnss.requestorIdEncoding =
311            IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
312    else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
313        notificationGnss.requestorIdEncoding =
314            IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
315    else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
316        notificationGnss.requestorIdEncoding =
317            IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
318    else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
319        notificationGnss.requestorIdEncoding =
320            IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
321
322    if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_NONE)
323        notificationGnss.notificationIdEncoding =
324            IGnssNiCallback::GnssNiEncodingType::ENC_NONE;
325    else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT)
326        notificationGnss.notificationIdEncoding =
327            IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT;
328    else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UTF8)
329        notificationGnss.notificationIdEncoding =
330            IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8;
331    else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UCS2)
332        notificationGnss.notificationIdEncoding =
333            IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2;
334
335    mGnssNiCbIface->niNotifyCb(notificationGnss);
336}
337
338void GnssAPIClient::onGnssSvCb(GnssSvNotification gnssSvNotification)
339{
340    LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, gnssSvNotification.count);
341    if (mGnssCbIface != nullptr) {
342        IGnssCallback::GnssSvStatus svStatus;
343        convertGnssSvStatus(gnssSvNotification, svStatus);
344        mGnssCbIface->gnssSvStatusCb(svStatus);
345    }
346}
347
348void GnssAPIClient::onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification)
349{
350    if (mGnssCbIface != nullptr) {
351        android::hardware::hidl_string nmeaString;
352        nmeaString.setToExternal(gnssNmeaNotification.nmea, gnssNmeaNotification.length);
353        mGnssCbIface->gnssNmeaCb(static_cast<GnssUtcTime>(gnssNmeaNotification.timestamp),
354                nmeaString);
355    }
356}
357
358void GnssAPIClient::onStartTrackingCb(LocationError error)
359{
360    LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
361    if (error == LOCATION_ERROR_SUCCESS && mGnssCbIface != nullptr) {
362        mGnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON);
363        mGnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
364    }
365}
366
367void GnssAPIClient::onStopTrackingCb(LocationError error)
368{
369    LOC_LOGD("%s]: (%d)", __FUNCTION__, error);
370    if (error == LOCATION_ERROR_SUCCESS && mGnssCbIface != nullptr) {
371        mGnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END);
372        mGnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON);
373    }
374}
375
376static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out)
377{
378    memset(&out, 0, sizeof(IGnssCallback::GnssSvStatus));
379    out.numSvs = in.count;
380    if (out.numSvs > static_cast<uint32_t>(GnssMax::SVS_COUNT)) {
381        LOC_LOGW("%s]: Too many satellites %zd. Clamps to %d.",
382                __FUNCTION__,  out.numSvs, GnssMax::SVS_COUNT);
383        out.numSvs = static_cast<uint32_t>(GnssMax::SVS_COUNT);
384    }
385    for (size_t i = 0; i < out.numSvs; i++) {
386        IGnssCallback::GnssSvInfo& info = out.gnssSvList[i];
387        info.svid = in.gnssSvs[i].svId;
388        convertGnssConstellationType(in.gnssSvs[i].type, info.constellation);
389        info.cN0Dbhz = in.gnssSvs[i].cN0Dbhz;
390        info.elevationDegrees = in.gnssSvs[i].elevation;
391        info.azimuthDegrees = in.gnssSvs[i].azimuth;
392        info.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
393        if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT)
394            info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
395        if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT)
396            info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
397        if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)
398            info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
399    }
400}
401
402}  // namespace implementation
403}  // namespace V1_0
404}  // namespace gnss
405}  // namespace hardware
406}  // namespace android
407