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 #ifndef LOCATION_API_CLINET_BASE_H 30 #define LOCATION_API_CLINET_BASE_H 31 32 #include <stdint.h> 33 #include <stdlib.h> 34 #include <pthread.h> 35 #include <queue> 36 #include <map> 37 38 #include "LocationAPI.h" 39 40 enum SESSION_MODE { 41 SESSION_MODE_NONE = 0, 42 SESSION_MODE_ON_FULL, 43 SESSION_MODE_ON_FIX, 44 SESSION_MODE_ON_TRIP_COMPLETED 45 }; 46 47 enum REQUEST_TYPE { 48 REQUEST_TRACKING = 0, 49 REQUEST_SESSION, 50 REQUEST_GEOFENCE, 51 REQUEST_NIRESPONSE, 52 REQUEST_MAX, 53 }; 54 55 enum CTRL_REQUEST_TYPE { 56 CTRL_REQUEST_DELETEAIDINGDATA = 0, 57 CTRL_REQUEST_CONTROL, 58 CTRL_REQUEST_CONFIG, 59 CTRL_REQUEST_MAX, 60 }; 61 62 class LocationAPIClientBase; 63 64 class LocationAPIRequest { 65 public: 66 LocationAPIRequest() {} 67 virtual ~LocationAPIRequest() {} 68 virtual void onResponse(LocationError /*error*/, uint32_t /*id*/) {} 69 virtual void onCollectiveResponse( 70 size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {} 71 }; 72 73 class RequestQueue { 74 public: 75 RequestQueue(): mSession(0) { 76 } 77 virtual ~RequestQueue() { 78 reset(0); 79 } 80 void inline setSession(uint32_t session) { mSession = session; } 81 void reset(uint32_t session) { 82 LocationAPIRequest* request = nullptr; 83 while (!mQueue.empty()) { 84 request = mQueue.front(); 85 mQueue.pop(); 86 delete request; 87 } 88 mSession = session; 89 } 90 void push(LocationAPIRequest* request) { 91 mQueue.push(request); 92 } 93 LocationAPIRequest* pop() { 94 LocationAPIRequest* request = nullptr; 95 if (!mQueue.empty()) { 96 request = mQueue.front(); 97 mQueue.pop(); 98 } 99 return request; 100 } 101 uint32_t getSession() { return mSession; } 102 private: 103 uint32_t mSession; 104 std::queue<LocationAPIRequest*> mQueue; 105 }; 106 107 class LocationAPIControlClient { 108 public: 109 LocationAPIControlClient(); 110 virtual ~LocationAPIControlClient(); 111 LocationAPIControlClient(const LocationAPIControlClient&) = delete; 112 LocationAPIControlClient& operator=(const LocationAPIControlClient&) = delete; 113 114 LocationAPIRequest* getRequestBySession(uint32_t session); 115 116 // LocationControlAPI 117 uint32_t locAPIGnssDeleteAidingData(GnssAidingData& data); 118 uint32_t locAPIEnable(LocationTechnologyType techType); 119 void locAPIDisable(); 120 uint32_t locAPIGnssUpdateConfig(GnssConfig config); 121 122 // callbacks 123 void onCtrlResponseCb(LocationError error, uint32_t id); 124 void onCtrlCollectiveResponseCb(size_t count, LocationError* errors, uint32_t* ids); 125 126 inline virtual void onGnssDeleteAidingDataCb(LocationError /*error*/) {} 127 inline virtual void onEnableCb(LocationError /*error*/) {} 128 inline virtual void onDisableCb(LocationError /*error*/) {} 129 inline virtual void onGnssUpdateConfigCb( 130 size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {} 131 132 class GnssDeleteAidingDataRequest : public LocationAPIRequest { 133 public: 134 GnssDeleteAidingDataRequest(LocationAPIControlClient& API) : mAPI(API) {} 135 inline void onResponse(LocationError error, uint32_t /*id*/) { 136 mAPI.onGnssDeleteAidingDataCb(error); 137 } 138 LocationAPIControlClient& mAPI; 139 }; 140 141 class EnableRequest : public LocationAPIRequest { 142 public: 143 EnableRequest(LocationAPIControlClient& API) : mAPI(API) {} 144 inline void onResponse(LocationError error, uint32_t /*id*/) { 145 mAPI.onEnableCb(error); 146 } 147 LocationAPIControlClient& mAPI; 148 }; 149 150 class DisableRequest : public LocationAPIRequest { 151 public: 152 DisableRequest(LocationAPIControlClient& API) : mAPI(API) {} 153 inline void onResponse(LocationError error, uint32_t /*id*/) { 154 mAPI.onDisableCb(error); 155 } 156 LocationAPIControlClient& mAPI; 157 }; 158 159 class GnssUpdateConfigRequest : public LocationAPIRequest { 160 public: 161 GnssUpdateConfigRequest(LocationAPIControlClient& API) : mAPI(API) {} 162 inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* ids) { 163 mAPI.onGnssUpdateConfigCb(count, errors, ids); 164 } 165 LocationAPIControlClient& mAPI; 166 }; 167 168 private: 169 pthread_mutex_t mMutex; 170 LocationControlAPI* mLocationControlAPI; 171 RequestQueue mRequestQueues[CTRL_REQUEST_MAX]; 172 bool mEnabled; 173 GnssConfig mConfig; 174 }; 175 176 class LocationAPIClientBase { 177 public: 178 LocationAPIClientBase(); 179 virtual ~LocationAPIClientBase(); 180 LocationAPIClientBase(const LocationAPIClientBase&) = delete; 181 LocationAPIClientBase& operator=(const LocationAPIClientBase&) = delete; 182 183 void locAPISetCallbacks(LocationCallbacks& locationCallbacks); 184 void removeSession(uint32_t session); 185 LocationAPIRequest* getRequestBySession(uint32_t session); 186 187 // LocationAPI 188 uint32_t locAPIStartTracking(LocationOptions& options); 189 void locAPIStopTracking(); 190 void locAPIUpdateTrackingOptions(LocationOptions& options); 191 192 int32_t locAPIGetBatchSize(); 193 uint32_t locAPIStartSession(uint32_t id, uint32_t sessionMode, 194 LocationOptions& options); 195 uint32_t locAPIStopSession(uint32_t id); 196 uint32_t locAPIUpdateSessionOptions(uint32_t id, uint32_t sessionMode, 197 LocationOptions& options); 198 void locAPIGetBatchedLocations(uint32_t id, size_t count); 199 200 uint32_t locAPIAddGeofences(size_t count, uint32_t* ids, 201 GeofenceOption* options, GeofenceInfo* data); 202 void locAPIRemoveGeofences(size_t count, uint32_t* ids); 203 void locAPIModifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options); 204 void locAPIPauseGeofences(size_t count, uint32_t* ids); 205 void locAPIResumeGeofences(size_t count, uint32_t* ids, GeofenceBreachTypeMask* mask); 206 void locAPIRemoveAllGeofences(); 207 208 void locAPIGnssNiResponse(uint32_t id, GnssNiResponse response); 209 210 // callbacks 211 void onResponseCb(LocationError error, uint32_t id); 212 void onCollectiveResponseCb(size_t count, LocationError* errors, uint32_t* ids); 213 214 void beforeGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification); 215 216 inline virtual void onCapabilitiesCb(LocationCapabilitiesMask /*capabilitiesMask*/) {} 217 inline virtual void onGnssNmeaCb(GnssNmeaNotification /*gnssNmeaNotification*/) {} 218 inline virtual void onGnssMeasurementsCb( 219 GnssMeasurementsNotification /*gnssMeasurementsNotification*/) {} 220 221 inline virtual void onTrackingCb(Location /*location*/) {} 222 inline virtual void onGnssSvCb(GnssSvNotification /*gnssSvNotification*/) {} 223 inline virtual void onStartTrackingCb(LocationError /*error*/) {} 224 inline virtual void onStopTrackingCb(LocationError /*error*/) {} 225 inline virtual void onUpdateTrackingOptionsCb(LocationError /*error*/) {} 226 227 inline virtual void onGnssLocationInfoCb( 228 GnssLocationInfoNotification /*gnssLocationInfoNotification*/) {} 229 230 inline virtual void onBatchingCb(size_t /*count*/, Location* /*location*/, 231 BatchingOptions /*batchingOptions*/) {} 232 inline virtual void onBatchingStatusCb(BatchingStatusInfo /*batchingStatus*/, 233 std::list<uint32_t> &/*listOfCompletedTrips*/) {} 234 void beforeBatchingStatusCb(BatchingStatusInfo batchStatus, 235 std::list<uint32_t> & tripCompletedList); 236 inline virtual void onStartBatchingCb(LocationError /*error*/) {} 237 inline virtual void onStopBatchingCb(LocationError /*error*/) {} 238 inline virtual void onUpdateBatchingOptionsCb(LocationError /*error*/) {} 239 inline virtual void onGetBatchedLocationsCb(LocationError /*error*/) {} 240 241 inline virtual void onGeofenceBreachCb( 242 GeofenceBreachNotification /*geofenceBreachNotification*/) {} 243 inline virtual void onGeofenceStatusCb( 244 GeofenceStatusNotification /*geofenceStatusNotification*/) {} 245 inline virtual void onAddGeofencesCb( 246 size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {} 247 inline virtual void onRemoveGeofencesCb( 248 size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {} 249 inline virtual void onModifyGeofencesCb( 250 size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {} 251 inline virtual void onPauseGeofencesCb( 252 size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {} 253 inline virtual void onResumeGeofencesCb( 254 size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {} 255 256 inline virtual void onGnssNiCb(uint32_t /*id*/, GnssNiNotification /*gnssNiNotification*/) {} 257 inline virtual void onGnssNiResponseCb(LocationError /*error*/) {} 258 259 private: 260 // private inner classes 261 typedef struct { 262 uint32_t id; 263 uint32_t trackingSession; 264 uint32_t batchingSession; 265 uint32_t sessionMode; 266 } SessionEntity; 267 268 template<typename T> 269 class BiDict { 270 public: 271 BiDict() { 272 pthread_mutex_init(&mBiDictMutex, nullptr); 273 } 274 virtual ~BiDict() { 275 pthread_mutex_destroy(&mBiDictMutex); 276 } 277 bool hasId(uint32_t id) { 278 pthread_mutex_lock(&mBiDictMutex); 279 bool ret = (mForwardMap.find(id) != mForwardMap.end()); 280 pthread_mutex_unlock(&mBiDictMutex); 281 return ret; 282 } 283 bool hasSession(uint32_t session) { 284 pthread_mutex_lock(&mBiDictMutex); 285 bool ret = (mBackwardMap.find(session) != mBackwardMap.end()); 286 pthread_mutex_unlock(&mBiDictMutex); 287 return ret; 288 } 289 void set(uint32_t id, uint32_t session, T& ext) { 290 pthread_mutex_lock(&mBiDictMutex); 291 mForwardMap[id] = session; 292 mBackwardMap[session] = id; 293 mExtMap[session] = ext; 294 pthread_mutex_unlock(&mBiDictMutex); 295 } 296 void clear() { 297 pthread_mutex_lock(&mBiDictMutex); 298 mForwardMap.clear(); 299 mBackwardMap.clear(); 300 mExtMap.clear(); 301 pthread_mutex_unlock(&mBiDictMutex); 302 } 303 void rmById(uint32_t id) { 304 pthread_mutex_lock(&mBiDictMutex); 305 mBackwardMap.erase(mForwardMap[id]); 306 mExtMap.erase(mForwardMap[id]); 307 mForwardMap.erase(id); 308 pthread_mutex_unlock(&mBiDictMutex); 309 } 310 void rmBySession(uint32_t session) { 311 pthread_mutex_lock(&mBiDictMutex); 312 mForwardMap.erase(mBackwardMap[session]); 313 mBackwardMap.erase(session); 314 mExtMap.erase(session); 315 pthread_mutex_unlock(&mBiDictMutex); 316 } 317 uint32_t getId(uint32_t session) { 318 pthread_mutex_lock(&mBiDictMutex); 319 uint32_t ret = 0; 320 auto it = mBackwardMap.find(session); 321 if (it != mBackwardMap.end()) { 322 ret = it->second; 323 } 324 pthread_mutex_unlock(&mBiDictMutex); 325 return ret; 326 } 327 uint32_t getSession(uint32_t id) { 328 pthread_mutex_lock(&mBiDictMutex); 329 uint32_t ret = 0; 330 auto it = mForwardMap.find(id); 331 if (it != mForwardMap.end()) { 332 ret = it->second; 333 } 334 pthread_mutex_unlock(&mBiDictMutex); 335 return ret; 336 } 337 T getExtById(uint32_t id) { 338 pthread_mutex_lock(&mBiDictMutex); 339 T ret; 340 memset(&ret, 0, sizeof(T)); 341 uint32_t session = mForwardMap[id]; 342 if (session > 0) { 343 auto it = mExtMap.find(session); 344 if (it != mExtMap.end()) { 345 ret = it->second; 346 } 347 } 348 pthread_mutex_unlock(&mBiDictMutex); 349 return ret; 350 } 351 T getExtBySession(uint32_t session) { 352 pthread_mutex_lock(&mBiDictMutex); 353 T ret; 354 memset(&ret, 0, sizeof(T)); 355 auto it = mExtMap.find(session); 356 if (it != mExtMap.end()) { 357 ret = it->second; 358 } 359 pthread_mutex_unlock(&mBiDictMutex); 360 return ret; 361 } 362 std::vector<uint32_t> getAllSessions() { 363 std::vector<uint32_t> ret; 364 pthread_mutex_lock(&mBiDictMutex); 365 for (auto it = mBackwardMap.begin(); it != mBackwardMap.end(); it++) { 366 ret.push_back(it->first); 367 } 368 pthread_mutex_unlock(&mBiDictMutex); 369 return ret; 370 } 371 private: 372 pthread_mutex_t mBiDictMutex; 373 // mForwarMap mapping id->session 374 std::map<uint32_t, uint32_t> mForwardMap; 375 // mBackwardMap mapping session->id 376 std::map<uint32_t, uint32_t> mBackwardMap; 377 // mExtMap mapping session->ext 378 std::map<uint32_t, T> mExtMap; 379 }; 380 381 class StartTrackingRequest : public LocationAPIRequest { 382 public: 383 StartTrackingRequest(LocationAPIClientBase& API) : mAPI(API) {} 384 inline void onResponse(LocationError error, uint32_t /*id*/) { 385 mAPI.onStartTrackingCb(error); 386 } 387 LocationAPIClientBase& mAPI; 388 }; 389 390 class StopTrackingRequest : public LocationAPIRequest { 391 public: 392 StopTrackingRequest(LocationAPIClientBase& API) : mAPI(API) {} 393 inline void onResponse(LocationError error, uint32_t id) { 394 mAPI.onStopTrackingCb(error); 395 if (error == LOCATION_ERROR_SUCCESS) { 396 mAPI.removeSession(id); 397 } 398 } 399 LocationAPIClientBase& mAPI; 400 }; 401 402 class UpdateTrackingOptionsRequest : public LocationAPIRequest { 403 public: 404 UpdateTrackingOptionsRequest(LocationAPIClientBase& API) : mAPI(API) {} 405 inline void onResponse(LocationError error, uint32_t /*id*/) { 406 mAPI.onUpdateTrackingOptionsCb(error); 407 } 408 LocationAPIClientBase& mAPI; 409 }; 410 411 class StartBatchingRequest : public LocationAPIRequest { 412 public: 413 StartBatchingRequest(LocationAPIClientBase& API) : mAPI(API) {} 414 inline void onResponse(LocationError error, uint32_t /*id*/) { 415 mAPI.onStartBatchingCb(error); 416 } 417 LocationAPIClientBase& mAPI; 418 }; 419 420 class StopBatchingRequest : public LocationAPIRequest { 421 public: 422 StopBatchingRequest(LocationAPIClientBase& API) : mAPI(API) {} 423 inline void onResponse(LocationError error, uint32_t id) { 424 mAPI.onStopBatchingCb(error); 425 if (error == LOCATION_ERROR_SUCCESS) { 426 mAPI.removeSession(id); 427 } 428 } 429 LocationAPIClientBase& mAPI; 430 }; 431 432 class UpdateBatchingOptionsRequest : public LocationAPIRequest { 433 public: 434 UpdateBatchingOptionsRequest(LocationAPIClientBase& API) : mAPI(API) {} 435 inline void onResponse(LocationError error, uint32_t /*id*/) { 436 mAPI.onUpdateBatchingOptionsCb(error); 437 } 438 LocationAPIClientBase& mAPI; 439 }; 440 441 class GetBatchedLocationsRequest : public LocationAPIRequest { 442 public: 443 GetBatchedLocationsRequest(LocationAPIClientBase& API) : mAPI(API) {} 444 inline void onResponse(LocationError error, uint32_t /*id*/) { 445 mAPI.onGetBatchedLocationsCb(error); 446 } 447 LocationAPIClientBase& mAPI; 448 }; 449 450 class AddGeofencesRequest : public LocationAPIRequest { 451 public: 452 AddGeofencesRequest(LocationAPIClientBase& API) : mAPI(API) {} 453 inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) { 454 uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count); 455 for (size_t i = 0; i < count; i++) { 456 ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]); 457 } 458 mAPI.onAddGeofencesCb(count, errors, ids); 459 free(ids); 460 } 461 LocationAPIClientBase& mAPI; 462 }; 463 464 class RemoveGeofencesRequest : public LocationAPIRequest { 465 public: 466 RemoveGeofencesRequest(LocationAPIClientBase& API) : mAPI(API) {} 467 inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) { 468 uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count); 469 for (size_t i = 0; i < count; i++) { 470 ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]); 471 mAPI.mGeofenceBiDict.rmBySession(sessions[i]); 472 } 473 mAPI.onRemoveGeofencesCb(count, errors, ids); 474 free(ids); 475 } 476 LocationAPIClientBase& mAPI; 477 }; 478 479 class ModifyGeofencesRequest : public LocationAPIRequest { 480 public: 481 ModifyGeofencesRequest(LocationAPIClientBase& API) : mAPI(API) {} 482 inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) { 483 uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count); 484 for (size_t i = 0; i < count; i++) { 485 ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]); 486 } 487 mAPI.onModifyGeofencesCb(count, errors, ids); 488 free(ids); 489 } 490 LocationAPIClientBase& mAPI; 491 }; 492 493 class PauseGeofencesRequest : public LocationAPIRequest { 494 public: 495 PauseGeofencesRequest(LocationAPIClientBase& API) : mAPI(API) {} 496 inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) { 497 uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count); 498 for (size_t i = 0; i < count; i++) { 499 ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]); 500 } 501 mAPI.onPauseGeofencesCb(count, errors, ids); 502 free(ids); 503 } 504 LocationAPIClientBase& mAPI; 505 }; 506 507 class ResumeGeofencesRequest : public LocationAPIRequest { 508 public: 509 ResumeGeofencesRequest(LocationAPIClientBase& API) : mAPI(API) {} 510 inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) { 511 uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count); 512 for (size_t i = 0; i < count; i++) { 513 ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]); 514 } 515 mAPI.onResumeGeofencesCb(count, errors, ids); 516 free(ids); 517 } 518 LocationAPIClientBase& mAPI; 519 }; 520 521 class GnssNiResponseRequest : public LocationAPIRequest { 522 public: 523 GnssNiResponseRequest(LocationAPIClientBase& API) : mAPI(API) {} 524 inline void onResponse(LocationError error, uint32_t /*id*/) { 525 mAPI.onGnssNiResponseCb(error); 526 } 527 LocationAPIClientBase& mAPI; 528 }; 529 530 private: 531 pthread_mutex_t mMutex; 532 533 geofenceBreachCallback mGeofenceBreachCallback; 534 batchingStatusCallback mBatchingStatusCallback; 535 536 LocationAPI* mLocationAPI; 537 538 RequestQueue mRequestQueues[REQUEST_MAX]; 539 BiDict<GeofenceBreachTypeMask> mGeofenceBiDict; 540 BiDict<SessionEntity> mSessionBiDict; 541 int32_t mBatchSize; 542 bool mTracking; 543 }; 544 545 #endif /* LOCATION_API_CLINET_BASE_H */ 546