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 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 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 109 void GeofenceAPIClient::geofencePause(uint32_t geofence_id) 110 { 111 LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id); 112 locAPIPauseGeofences(1, &geofence_id); 113 } 114 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 126 void GeofenceAPIClient::geofenceRemove(uint32_t geofence_id) 127 { 128 LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id); 129 locAPIRemoveGeofences(1, &geofence_id); 130 } 131 132 void GeofenceAPIClient::geofenceRemoveAll() 133 { 134 LOC_LOGD("%s]", __FUNCTION__); 135 // TODO locAPIRemoveAllGeofences(); 136 } 137 138 // callbacks 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 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 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 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 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 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