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 mGnssGeofencingCbIface->gnssGeofenceTransitionCb( 159 geofenceBreachNotification.ids[i], gnssLocation, transition, 160 static_cast<GnssUtcTime>(geofenceBreachNotification.timestamp)); 161 } 162 } 163 } 164 165 void GeofenceAPIClient::onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification) 166 { 167 LOC_LOGD("%s]: (%d)", __FUNCTION__, geofenceStatusNotification.available); 168 if (mGnssGeofencingCbIface != nullptr) { 169 IGnssGeofenceCallback::GeofenceAvailability status = 170 IGnssGeofenceCallback::GeofenceAvailability::UNAVAILABLE; 171 if (geofenceStatusNotification.available == GEOFENCE_STATUS_AVAILABILE_YES) { 172 status = IGnssGeofenceCallback::GeofenceAvailability::AVAILABLE; 173 } 174 GnssLocation gnssLocation; 175 memset(&gnssLocation, 0, sizeof(GnssLocation)); 176 mGnssGeofencingCbIface->gnssGeofenceStatusCb(status, gnssLocation); 177 } 178 } 179 180 void GeofenceAPIClient::onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) 181 { 182 LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); 183 if (mGnssGeofencingCbIface != nullptr) { 184 for (size_t i = 0; i < count; i++) { 185 IGnssGeofenceCallback::GeofenceStatus status = 186 IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; 187 if (errors[i] == LOCATION_ERROR_SUCCESS) 188 status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; 189 else if (errors[i] == LOCATION_ERROR_ID_EXISTS) 190 status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_EXISTS; 191 mGnssGeofencingCbIface->gnssGeofenceAddCb(ids[i], status); 192 } 193 } 194 } 195 196 void GeofenceAPIClient::onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) 197 { 198 LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); 199 if (mGnssGeofencingCbIface != nullptr) { 200 for (size_t i = 0; i < count; i++) { 201 IGnssGeofenceCallback::GeofenceStatus status = 202 IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; 203 if (errors[i] == LOCATION_ERROR_SUCCESS) 204 status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; 205 else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) 206 status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; 207 mGnssGeofencingCbIface->gnssGeofenceRemoveCb(ids[i], status); 208 } 209 } 210 } 211 212 void GeofenceAPIClient::onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) 213 { 214 LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); 215 if (mGnssGeofencingCbIface != nullptr) { 216 for (size_t i = 0; i < count; i++) { 217 IGnssGeofenceCallback::GeofenceStatus status = 218 IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; 219 if (errors[i] == LOCATION_ERROR_SUCCESS) 220 status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; 221 else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) 222 status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; 223 mGnssGeofencingCbIface->gnssGeofencePauseCb(ids[i], status); 224 } 225 } 226 } 227 228 void GeofenceAPIClient::onResumeGeofencesCb(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 mGnssGeofencingCbIface->gnssGeofenceResumeCb(ids[i], status); 240 } 241 } 242 } 243 244 } // namespace implementation 245 } // namespace V1_0 246 } // namespace gnss 247 } // namespace hardware 248 } // namespace android 249