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