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_GeofenceApiClient"
32 
33 #include <log_util.h>
34 #include <loc_cfg.h>
35 
36 #include "LocationUtil.h"
37 #include "GeofenceAPIClient.h"
38 
39 namespace android {
40 namespace hardware {
41 namespace gnss {
42 namespace V1_0 {
43 namespace implementation {
44 
45 
GeofenceAPIClient(const sp<IGnssGeofenceCallback> & callback)46 GeofenceAPIClient::GeofenceAPIClient(const sp<IGnssGeofenceCallback>& callback) :
47     LocationAPIClientBase(),
48     mGnssGeofencingCbIface(callback)
49 {
50     LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);
51 
52     LocationCallbacks locationCallbacks;
53     locationCallbacks.size = sizeof(LocationCallbacks);
54 
55     locationCallbacks.trackingCb = nullptr;
56     locationCallbacks.batchingCb = nullptr;
57 
58     locationCallbacks.geofenceBreachCb = nullptr;
59     if (mGnssGeofencingCbIface != nullptr) {
60         locationCallbacks.geofenceBreachCb =
61             [this](GeofenceBreachNotification geofenceBreachNotification) {
62                 onGeofenceBreachCb(geofenceBreachNotification);
63             };
64 
65         locationCallbacks.geofenceStatusCb =
66             [this](GeofenceStatusNotification geofenceStatusNotification) {
67                 onGeofenceStatusCb(geofenceStatusNotification);
68             };
69     }
70 
71     locationCallbacks.gnssLocationInfoCb = nullptr;
72     locationCallbacks.gnssNiCb = nullptr;
73     locationCallbacks.gnssSvCb = nullptr;
74     locationCallbacks.gnssNmeaCb = nullptr;
75     locationCallbacks.gnssMeasurementsCb = nullptr;
76 
77     locAPISetCallbacks(locationCallbacks);
78 }
79 
geofenceAdd(uint32_t geofence_id,double latitude,double longitude,double radius_meters,int32_t last_transition,int32_t monitor_transitions,uint32_t notification_responsiveness_ms,uint32_t unknown_timer_ms)80 void GeofenceAPIClient::geofenceAdd(uint32_t geofence_id, double latitude, double longitude,
81         double radius_meters, int32_t last_transition, int32_t monitor_transitions,
82         uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms)
83 {
84     LOC_LOGD("%s]: (%d %f %f %f %d %d %d %d)", __FUNCTION__,
85             geofence_id, latitude, longitude, radius_meters,
86             last_transition, monitor_transitions, notification_responsiveness_ms, unknown_timer_ms);
87 
88     GeofenceOption options;
89     memset(&options, 0, sizeof(GeofenceOption));
90     options.size = sizeof(GeofenceOption);
91     if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED)
92         options.breachTypeMask |= GEOFENCE_BREACH_ENTER_BIT;
93     if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED)
94         options.breachTypeMask |=  GEOFENCE_BREACH_EXIT_BIT;
95     options.responsiveness = notification_responsiveness_ms;
96 
97     GeofenceInfo data;
98     data.size = sizeof(GeofenceInfo);
99     data.latitude = latitude;
100     data.longitude = longitude;
101     data.radius = radius_meters;
102 
103     LocationError err = (LocationError)locAPIAddGeofences(1, &geofence_id, &options, &data);
104     if (LOCATION_ERROR_SUCCESS != err) {
105         onAddGeofencesCb(1, &err, &geofence_id);
106     }
107 }
108 
geofencePause(uint32_t geofence_id)109 void GeofenceAPIClient::geofencePause(uint32_t geofence_id)
110 {
111     LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id);
112     locAPIPauseGeofences(1, &geofence_id);
113 }
114 
geofenceResume(uint32_t geofence_id,int32_t monitor_transitions)115 void GeofenceAPIClient::geofenceResume(uint32_t geofence_id, int32_t monitor_transitions)
116 {
117     LOC_LOGD("%s]: (%d %d)", __FUNCTION__, geofence_id, monitor_transitions);
118     GeofenceBreachTypeMask mask = 0;
119     if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED)
120         mask |= GEOFENCE_BREACH_ENTER_BIT;
121     if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED)
122         mask |=  GEOFENCE_BREACH_EXIT_BIT;
123     locAPIResumeGeofences(1, &geofence_id, &mask);
124 }
125 
geofenceRemove(uint32_t geofence_id)126 void GeofenceAPIClient::geofenceRemove(uint32_t geofence_id)
127 {
128     LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id);
129     locAPIRemoveGeofences(1, &geofence_id);
130 }
131 
geofenceRemoveAll()132 void GeofenceAPIClient::geofenceRemoveAll()
133 {
134     LOC_LOGD("%s]", __FUNCTION__);
135     // TODO locAPIRemoveAllGeofences();
136 }
137 
138 // callbacks
onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification)139 void GeofenceAPIClient::onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification)
140 {
141     LOC_LOGD("%s]: (%zu)", __FUNCTION__, geofenceBreachNotification.count);
142     if (mGnssGeofencingCbIface != nullptr) {
143         for (size_t i = 0; i < geofenceBreachNotification.count; i++) {
144             GnssLocation gnssLocation;
145             convertGnssLocation(geofenceBreachNotification.location, gnssLocation);
146 
147             IGnssGeofenceCallback::GeofenceTransition transition;
148             if (geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER)
149                 transition = IGnssGeofenceCallback::GeofenceTransition::ENTERED;
150             else if (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT)
151                 transition = IGnssGeofenceCallback::GeofenceTransition::EXITED;
152             else {
153                 // continue with other breach if transition is
154                 // nether GPS_GEOFENCE_ENTERED nor GPS_GEOFENCE_EXITED
155                 continue;
156             }
157 
158             auto r = mGnssGeofencingCbIface->gnssGeofenceTransitionCb(
159                     geofenceBreachNotification.ids[i], gnssLocation, transition,
160                     static_cast<GnssUtcTime>(geofenceBreachNotification.timestamp));
161             if (!r.isOk()) {
162                 LOC_LOGE("%s] Error from gnssGeofenceTransitionCb description=%s",
163                     __func__, r.description().c_str());
164             }
165         }
166     }
167 }
168 
onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification)169 void GeofenceAPIClient::onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification)
170 {
171     LOC_LOGD("%s]: (%d)", __FUNCTION__, geofenceStatusNotification.available);
172     if (mGnssGeofencingCbIface != nullptr) {
173         IGnssGeofenceCallback::GeofenceAvailability status =
174             IGnssGeofenceCallback::GeofenceAvailability::UNAVAILABLE;
175         if (geofenceStatusNotification.available == GEOFENCE_STATUS_AVAILABILE_YES) {
176             status = IGnssGeofenceCallback::GeofenceAvailability::AVAILABLE;
177         }
178         GnssLocation gnssLocation;
179         memset(&gnssLocation, 0, sizeof(GnssLocation));
180         auto r = mGnssGeofencingCbIface->gnssGeofenceStatusCb(status, gnssLocation);
181         if (!r.isOk()) {
182             LOC_LOGE("%s] Error from gnssGeofenceStatusCb description=%s",
183                 __func__, r.description().c_str());
184         }
185     }
186 }
187 
onAddGeofencesCb(size_t count,LocationError * errors,uint32_t * ids)188 void GeofenceAPIClient::onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
189 {
190     LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
191     if (mGnssGeofencingCbIface != nullptr) {
192         for (size_t i = 0; i < count; i++) {
193             IGnssGeofenceCallback::GeofenceStatus status =
194                 IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
195             if (errors[i] == LOCATION_ERROR_SUCCESS)
196                 status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
197             else if (errors[i] == LOCATION_ERROR_ID_EXISTS)
198                 status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_EXISTS;
199             auto r = mGnssGeofencingCbIface->gnssGeofenceAddCb(ids[i], status);
200             if (!r.isOk()) {
201                 LOC_LOGE("%s] Error from gnssGeofenceAddCb description=%s",
202                     __func__, r.description().c_str());
203             }
204         }
205     }
206 }
207 
onRemoveGeofencesCb(size_t count,LocationError * errors,uint32_t * ids)208 void GeofenceAPIClient::onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
209 {
210     LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
211     if (mGnssGeofencingCbIface != nullptr) {
212         for (size_t i = 0; i < count; i++) {
213             IGnssGeofenceCallback::GeofenceStatus status =
214                 IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
215             if (errors[i] == LOCATION_ERROR_SUCCESS)
216                 status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
217             else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
218                 status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN;
219             auto r = mGnssGeofencingCbIface->gnssGeofenceRemoveCb(ids[i], status);
220             if (!r.isOk()) {
221                 LOC_LOGE("%s] Error from gnssGeofenceRemoveCb description=%s",
222                     __func__, r.description().c_str());
223             }
224         }
225     }
226 }
227 
onPauseGeofencesCb(size_t count,LocationError * errors,uint32_t * ids)228 void GeofenceAPIClient::onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
229 {
230     LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
231     if (mGnssGeofencingCbIface != nullptr) {
232         for (size_t i = 0; i < count; i++) {
233             IGnssGeofenceCallback::GeofenceStatus status =
234                 IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
235             if (errors[i] == LOCATION_ERROR_SUCCESS)
236                 status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
237             else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
238                 status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN;
239             auto r = mGnssGeofencingCbIface->gnssGeofencePauseCb(ids[i], status);
240             if (!r.isOk()) {
241                 LOC_LOGE("%s] Error from gnssGeofencePauseCb description=%s",
242                     __func__, r.description().c_str());
243             }
244         }
245     }
246 }
247 
onResumeGeofencesCb(size_t count,LocationError * errors,uint32_t * ids)248 void GeofenceAPIClient::onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids)
249 {
250     LOC_LOGD("%s]: (%zu)", __FUNCTION__, count);
251     if (mGnssGeofencingCbIface != nullptr) {
252         for (size_t i = 0; i < count; i++) {
253             IGnssGeofenceCallback::GeofenceStatus status =
254                 IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC;
255             if (errors[i] == LOCATION_ERROR_SUCCESS)
256                 status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS;
257             else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN)
258                 status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN;
259             auto r = mGnssGeofencingCbIface->gnssGeofenceResumeCb(ids[i], status);
260             if (!r.isOk()) {
261                 LOC_LOGE("%s] Error from gnssGeofenceResumeCb description=%s",
262                     __func__, r.description().c_str());
263             }
264         }
265     }
266 }
267 
268 }  // namespace implementation
269 }  // namespace V1_0
270 }  // namespace gnss
271 }  // namespace hardware
272 }  // namespace android
273