1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "GnssHal_GnssGeofencing" 18 19 #include "GnssGeofencing.h" 20 #include <GnssUtils.h> 21 22 namespace android { 23 namespace hardware { 24 namespace gnss { 25 namespace V1_0 { 26 namespace implementation { 27 28 std::vector<std::unique_ptr<ThreadFuncArgs>> GnssGeofencing::sThreadFuncArgsList; 29 sp<IGnssGeofenceCallback> GnssGeofencing::mGnssGeofencingCbIface = nullptr; 30 bool GnssGeofencing::sInterfaceExists = false; 31 32 GpsGeofenceCallbacks GnssGeofencing::sGnssGfCb = { 33 .geofence_transition_callback = gnssGfTransitionCb, 34 .geofence_status_callback = gnssGfStatusCb, 35 .geofence_add_callback = gnssGfAddCb, 36 .geofence_remove_callback = gnssGfRemoveCb, 37 .geofence_pause_callback = gnssGfPauseCb, 38 .geofence_resume_callback = gnssGfResumeCb, 39 .create_thread_cb = createThreadCb 40 }; 41 42 GnssGeofencing::GnssGeofencing(const GpsGeofencingInterface* gpsGeofencingIface) 43 : mGnssGeofencingIface(gpsGeofencingIface) { 44 /* Error out if an instance of the interface already exists. */ 45 LOG_ALWAYS_FATAL_IF(sInterfaceExists); 46 sInterfaceExists = true; 47 } 48 49 GnssGeofencing::~GnssGeofencing() { 50 sThreadFuncArgsList.clear(); 51 sInterfaceExists = false; 52 } 53 void GnssGeofencing::gnssGfTransitionCb(int32_t geofenceId, 54 GpsLocation* location, 55 int32_t transition, 56 GpsUtcTime timestamp) { 57 if (mGnssGeofencingCbIface == nullptr) { 58 ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__); 59 return; 60 } 61 62 if (location == nullptr) { 63 ALOGE("%s : Invalid location from GNSS HAL", __func__); 64 return; 65 } 66 67 GnssLocation gnssLocation = convertToGnssLocation(location); 68 auto ret = mGnssGeofencingCbIface->gnssGeofenceTransitionCb( 69 geofenceId, 70 gnssLocation, 71 static_cast<IGnssGeofenceCallback::GeofenceTransition>(transition), 72 timestamp); 73 if (!ret.isOk()) { 74 ALOGE("%s: Unable to invoke callback", __func__); 75 } 76 } 77 78 void GnssGeofencing::gnssGfStatusCb(int32_t status, GpsLocation* location) { 79 if (mGnssGeofencingCbIface == nullptr) { 80 ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__); 81 return; 82 } 83 84 GnssLocation gnssLocation; 85 86 if (location != nullptr) { 87 gnssLocation = convertToGnssLocation(location); 88 } else { 89 gnssLocation = {}; 90 } 91 92 auto ret = mGnssGeofencingCbIface->gnssGeofenceStatusCb( 93 static_cast<IGnssGeofenceCallback::GeofenceAvailability>(status), gnssLocation); 94 if (!ret.isOk()) { 95 ALOGE("%s: Unable to invoke callback", __func__); 96 } 97 } 98 99 void GnssGeofencing::gnssGfAddCb(int32_t geofenceId, int32_t status) { 100 if (mGnssGeofencingCbIface == nullptr) { 101 ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__); 102 return; 103 } 104 105 auto ret = mGnssGeofencingCbIface->gnssGeofenceAddCb( 106 geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status)); 107 if (!ret.isOk()) { 108 ALOGE("%s: Unable to invoke callback", __func__); 109 } 110 } 111 112 void GnssGeofencing::gnssGfRemoveCb(int32_t geofenceId, int32_t status) { 113 if (mGnssGeofencingCbIface == nullptr) { 114 ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__); 115 return; 116 } 117 118 auto ret = mGnssGeofencingCbIface->gnssGeofenceRemoveCb( 119 geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status)); 120 if (!ret.isOk()) { 121 ALOGE("%s: Unable to invoke callback", __func__); 122 } 123 } 124 125 void GnssGeofencing::gnssGfPauseCb(int32_t geofenceId, int32_t status) { 126 if (mGnssGeofencingCbIface == nullptr) { 127 ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__); 128 return; 129 } 130 131 auto ret = mGnssGeofencingCbIface->gnssGeofencePauseCb( 132 geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status)); 133 if (!ret.isOk()) { 134 ALOGE("%s: Unable to invoke callback", __func__); 135 } 136 } 137 138 void GnssGeofencing::gnssGfResumeCb(int32_t geofenceId, int32_t status) { 139 if (mGnssGeofencingCbIface == nullptr) { 140 ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__); 141 return; 142 } 143 144 auto ret = mGnssGeofencingCbIface->gnssGeofenceResumeCb( 145 geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status)); 146 if (!ret.isOk()) { 147 ALOGE("%s: Unable to invoke callback", __func__); 148 } 149 } 150 151 pthread_t GnssGeofencing::createThreadCb(const char* name, void (*start)(void*), void* arg) { 152 return createPthread(name, start, arg, &sThreadFuncArgsList); 153 } 154 155 // Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow. 156 Return<void> GnssGeofencing::setCallback(const sp<IGnssGeofenceCallback>& callback) { 157 mGnssGeofencingCbIface = callback; 158 159 if (mGnssGeofencingIface == nullptr) { 160 ALOGE("%s: GnssGeofencing interface is not available", __func__); 161 } else { 162 mGnssGeofencingIface->init(&sGnssGfCb); 163 } 164 165 return Void(); 166 } 167 168 Return<void> GnssGeofencing::addGeofence( 169 int32_t geofenceId, 170 double latitudeDegrees, 171 double longitudeDegrees, 172 double radiusMeters, 173 IGnssGeofenceCallback::GeofenceTransition lastTransition, 174 int32_t monitorTransitions, 175 uint32_t notificationResponsivenessMs, 176 uint32_t unknownTimerMs) { 177 if (mGnssGeofencingIface == nullptr) { 178 ALOGE("%s: GnssGeofencing interface is not available", __func__); 179 return Void(); 180 } else { 181 mGnssGeofencingIface->add_geofence_area( 182 geofenceId, 183 latitudeDegrees, 184 longitudeDegrees, 185 radiusMeters, 186 static_cast<int32_t>(lastTransition), 187 monitorTransitions, 188 notificationResponsivenessMs, 189 unknownTimerMs); 190 } 191 return Void(); 192 } 193 194 Return<void> GnssGeofencing::pauseGeofence(int32_t geofenceId) { 195 if (mGnssGeofencingIface == nullptr) { 196 ALOGE("%s: GnssGeofencing interface is not available", __func__); 197 } else { 198 mGnssGeofencingIface->pause_geofence(geofenceId); 199 } 200 return Void(); 201 } 202 203 Return<void> GnssGeofencing::resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) { 204 if (mGnssGeofencingIface == nullptr) { 205 ALOGE("%s: GnssGeofencing interface is not available", __func__); 206 } else { 207 mGnssGeofencingIface->resume_geofence(geofenceId, monitorTransitions); 208 } 209 return Void(); 210 } 211 212 Return<void> GnssGeofencing::removeGeofence(int32_t geofenceId) { 213 if (mGnssGeofencingIface == nullptr) { 214 ALOGE("%s: GnssGeofencing interface is not available", __func__); 215 } else { 216 mGnssGeofencingIface->remove_geofence_area(geofenceId); 217 } 218 return Void(); 219 } 220 221 } // namespace implementation 222 } // namespace V1_0 223 } // namespace gnss 224 } // namespace hardware 225 } // namespace android 226