LocationAPIClientBase.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969
  1. /* Copyright (c) 2017, 2020-2021 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. #define LOG_NDEBUG 0
  29. #define LOG_TAG "LocSvc_APIClientBase"
  30. #include <loc_pla.h>
  31. #include <log_util.h>
  32. #include <inttypes.h>
  33. #include <loc_cfg.h>
  34. #include "LocationAPIClientBase.h"
  35. #define GEOFENCE_SESSION_ID 0xFFFFFFFF
  36. #define CONFIG_SESSION_ID 0xFFFFFFFF
  37. // LocationAPIControlClient
  38. LocationAPIControlClient::LocationAPIControlClient() :
  39. mEnabled(false)
  40. {
  41. pthread_mutex_init(&mMutex, nullptr);
  42. for (int i = 0; i < CTRL_REQUEST_MAX; i++) {
  43. mRequestQueues[i].reset((uint32_t)0);
  44. }
  45. LocationControlCallbacks locationControlCallbacks;
  46. locationControlCallbacks.size = sizeof(LocationControlCallbacks);
  47. locationControlCallbacks.responseCb =
  48. [this](LocationError error, uint32_t id) {
  49. onCtrlResponseCb(error, id);
  50. };
  51. locationControlCallbacks.collectiveResponseCb =
  52. [this](size_t count, LocationError* errors, uint32_t* ids) {
  53. onCtrlCollectiveResponseCb(count, errors, ids);
  54. };
  55. mLocationControlAPI = LocationControlAPI::createInstance(locationControlCallbacks);
  56. }
  57. LocationAPIControlClient::~LocationAPIControlClient()
  58. {
  59. pthread_mutex_lock(&mMutex);
  60. if (mLocationControlAPI) {
  61. mLocationControlAPI->destroy();
  62. mLocationControlAPI = nullptr;
  63. }
  64. for (int i = 0; i < CTRL_REQUEST_MAX; i++) {
  65. mRequestQueues[i].reset((uint32_t)0);
  66. }
  67. pthread_mutex_unlock(&mMutex);
  68. pthread_mutex_destroy(&mMutex);
  69. }
  70. uint32_t LocationAPIControlClient::locAPIGnssDeleteAidingData(GnssAidingData& data)
  71. {
  72. uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
  73. pthread_mutex_lock(&mMutex);
  74. if (mLocationControlAPI) {
  75. uint32_t session = mLocationControlAPI->gnssDeleteAidingData(data);
  76. LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session);
  77. mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].reset(session);
  78. mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].push(new GnssDeleteAidingDataRequest(*this));
  79. retVal = LOCATION_ERROR_SUCCESS;
  80. }
  81. pthread_mutex_unlock(&mMutex);
  82. return retVal;
  83. }
  84. uint32_t LocationAPIControlClient::locAPIEnable(LocationTechnologyType techType)
  85. {
  86. uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
  87. pthread_mutex_lock(&mMutex);
  88. if (mEnabled) {
  89. // just return success if already enabled
  90. retVal = LOCATION_ERROR_SUCCESS;
  91. } else if (mLocationControlAPI) {
  92. uint32_t session = mLocationControlAPI->enable(techType);
  93. LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session);
  94. mRequestQueues[CTRL_REQUEST_CONTROL].reset(session);
  95. mRequestQueues[CTRL_REQUEST_CONTROL].push(new EnableRequest(*this));
  96. retVal = LOCATION_ERROR_SUCCESS;
  97. mEnabled = true;
  98. } else {
  99. LOC_LOGE("%s:%d] failed.", __FUNCTION__, __LINE__);
  100. }
  101. pthread_mutex_unlock(&mMutex);
  102. return retVal;
  103. }
  104. void LocationAPIControlClient::locAPIDisable()
  105. {
  106. pthread_mutex_lock(&mMutex);
  107. if (mEnabled && mLocationControlAPI) {
  108. uint32_t session = 0;
  109. session = mRequestQueues[CTRL_REQUEST_CONTROL].getSession();
  110. if (session > 0) {
  111. mRequestQueues[CTRL_REQUEST_CONTROL].push(new DisableRequest(*this));
  112. mLocationControlAPI->disable(session);
  113. mEnabled = false;
  114. } else {
  115. LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session);
  116. }
  117. }
  118. pthread_mutex_unlock(&mMutex);
  119. }
  120. uint32_t LocationAPIControlClient::locAPIGnssUpdateConfig(GnssConfig config)
  121. {
  122. uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
  123. pthread_mutex_lock(&mMutex);
  124. if (mLocationControlAPI) {
  125. uint32_t* idArray = mLocationControlAPI->gnssUpdateConfig(config);
  126. LOC_LOGv("gnssUpdateConfig return array: %p", idArray);
  127. if (nullptr != idArray) {
  128. if (nullptr != mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].getSessionArrayPtr()) {
  129. mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].reset(idArray);
  130. }
  131. mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].push(new GnssUpdateConfigRequest(*this));
  132. retVal = LOCATION_ERROR_SUCCESS;
  133. delete [] idArray;
  134. }
  135. }
  136. pthread_mutex_unlock(&mMutex);
  137. return retVal;
  138. }
  139. uint32_t LocationAPIControlClient::locAPIGnssGetConfig(GnssConfigFlagsMask mask)
  140. {
  141. uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
  142. pthread_mutex_lock(&mMutex);
  143. if (mLocationControlAPI) {
  144. uint32_t* idArray = mLocationControlAPI->gnssGetConfig(mask);
  145. LOC_LOGv("gnssGetConfig return array: %p", idArray);
  146. if (nullptr != idArray) {
  147. if (nullptr != mRequestQueues[CTRL_REQUEST_CONFIG_GET].getSessionArrayPtr()) {
  148. mRequestQueues[CTRL_REQUEST_CONFIG_GET].reset(idArray);
  149. }
  150. mRequestQueues[CTRL_REQUEST_CONFIG_GET].push(new GnssGetConfigRequest(*this));
  151. retVal = LOCATION_ERROR_SUCCESS;
  152. delete [] idArray;
  153. }
  154. }
  155. pthread_mutex_unlock(&mMutex);
  156. return retVal;
  157. }
  158. void LocationAPIControlClient::onCtrlResponseCb(LocationError error, uint32_t id)
  159. {
  160. if (error != LOCATION_ERROR_SUCCESS) {
  161. LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, error, id);
  162. } else {
  163. LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, error, id);
  164. }
  165. LocationAPIRequest* request = getRequestBySession(id);
  166. if (request) {
  167. request->onResponse(error, id);
  168. delete request;
  169. }
  170. }
  171. void LocationAPIControlClient::onCtrlCollectiveResponseCb(
  172. size_t count, LocationError* errors, uint32_t* ids)
  173. {
  174. for (size_t i = 0; i < count; i++) {
  175. if (errors[i] != LOCATION_ERROR_SUCCESS) {
  176. LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, errors[i], ids[i]);
  177. } else {
  178. LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, errors[i], ids[i]);
  179. }
  180. }
  181. LocationAPIRequest* request = getRequestBySessionArrayPtr(ids);
  182. if (request) {
  183. request->onCollectiveResponse(count, errors, ids);
  184. delete request;
  185. }
  186. }
  187. LocationAPIRequest* LocationAPIControlClient::getRequestBySession(uint32_t session)
  188. {
  189. pthread_mutex_lock(&mMutex);
  190. LocationAPIRequest* request = nullptr;
  191. if (mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].getSession() == session) {
  192. request = mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].pop();
  193. } else if (mRequestQueues[CTRL_REQUEST_CONTROL].getSession() == session) {
  194. request = mRequestQueues[CTRL_REQUEST_CONTROL].pop();
  195. }
  196. pthread_mutex_unlock(&mMutex);
  197. return request;
  198. }
  199. LocationAPIRequest*
  200. LocationAPIControlClient::getRequestBySessionArrayPtr(
  201. uint32_t* sessionArrayPtr)
  202. {
  203. pthread_mutex_lock(&mMutex);
  204. LocationAPIRequest* request = nullptr;
  205. if (mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].getSessionArrayPtr() == sessionArrayPtr) {
  206. request = mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].pop();
  207. } else if (mRequestQueues[CTRL_REQUEST_CONFIG_GET].getSessionArrayPtr() == sessionArrayPtr) {
  208. request = mRequestQueues[CTRL_REQUEST_CONFIG_GET].pop();
  209. }
  210. pthread_mutex_unlock(&mMutex);
  211. return request;
  212. }
  213. // LocationAPIClientBase
  214. LocationAPIClientBase::LocationAPIClientBase() :
  215. mGeofenceBreachCallback(nullptr),
  216. mBatchingStatusCallback(nullptr),
  217. mLocationAPI(nullptr),
  218. mBatchSize(-1),
  219. mTracking(false)
  220. {
  221. // use recursive mutex, in case callback come from the same thread
  222. pthread_mutexattr_t attr;
  223. pthread_mutexattr_init(&attr);
  224. pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  225. pthread_mutex_init(&mMutex, &attr);
  226. for (int i = 0; i < REQUEST_MAX; i++) {
  227. mRequestQueues[i].reset((uint32_t)0);
  228. }
  229. }
  230. void LocationAPIClientBase::locAPISetCallbacks(LocationCallbacks& locationCallbacks)
  231. {
  232. pthread_mutex_lock(&mMutex);
  233. if (locationCallbacks.geofenceBreachCb != nullptr) {
  234. mGeofenceBreachCallback = locationCallbacks.geofenceBreachCb;
  235. locationCallbacks.geofenceBreachCb =
  236. [this](GeofenceBreachNotification geofenceBreachNotification) {
  237. beforeGeofenceBreachCb(geofenceBreachNotification);
  238. };
  239. }
  240. locationCallbacks.capabilitiesCb =
  241. [this](LocationCapabilitiesMask capabilitiesMask) {
  242. onCapabilitiesCb(capabilitiesMask);
  243. };
  244. locationCallbacks.responseCb = [this](LocationError error, uint32_t id) {
  245. onResponseCb(error, id);
  246. };
  247. locationCallbacks.collectiveResponseCb =
  248. [this](size_t count, LocationError* errors, uint32_t* ids) {
  249. onCollectiveResponseCb(count, errors, ids);
  250. };
  251. if (locationCallbacks.batchingStatusCb != nullptr) {
  252. mBatchingStatusCallback = locationCallbacks.batchingStatusCb;
  253. locationCallbacks.batchingStatusCb =
  254. [this](BatchingStatusInfo batchStatus, std::list<uint32_t> & tripCompletedList) {
  255. beforeBatchingStatusCb(batchStatus, tripCompletedList);
  256. };
  257. }
  258. if (mLocationAPI == nullptr ) {
  259. mLocationAPI = LocationAPI::createInstance(locationCallbacks);
  260. } else {
  261. mLocationAPI->updateCallbacks(locationCallbacks);
  262. }
  263. pthread_mutex_unlock(&mMutex);
  264. }
  265. void LocationAPIClientBase::destroy()
  266. {
  267. LOC_LOGD("LocationAPIClientBase::destroy()");
  268. pthread_mutex_lock(&mMutex);
  269. mGeofenceBreachCallback = nullptr;
  270. for (int i = 0; i < REQUEST_MAX; i++) {
  271. mRequestQueues[i].reset((uint32_t)0);
  272. }
  273. LocationAPI* localHandle = nullptr;
  274. if (nullptr != mLocationAPI) {
  275. localHandle = mLocationAPI;
  276. mLocationAPI = nullptr;
  277. }
  278. pthread_mutex_unlock(&mMutex);
  279. // Invoking destroy has the possibility of destroy complete callback
  280. // being invoked right away in the same context, hence no instance
  281. // member must be accessed after the destroy call.
  282. if (nullptr != localHandle) {
  283. localHandle->destroy([this]() {onLocationApiDestroyCompleteCb();});
  284. }
  285. }
  286. LocationAPIClientBase::~LocationAPIClientBase()
  287. {
  288. pthread_mutex_destroy(&mMutex);
  289. }
  290. void LocationAPIClientBase::onLocationApiDestroyCompleteCb()
  291. {
  292. LOC_LOGD("LocationAPIClientBase::onLocationApiDestroyCompleteCb()");
  293. delete this;
  294. }
  295. uint32_t LocationAPIClientBase::locAPIStartTracking(TrackingOptions& options)
  296. {
  297. uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
  298. pthread_mutex_lock(&mMutex);
  299. if (mLocationAPI) {
  300. if (mTracking) {
  301. LOC_LOGW("%s:%d] Existing tracking session present", __FUNCTION__, __LINE__);
  302. } else {
  303. uint32_t session = mLocationAPI->startTracking(options);
  304. LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session);
  305. // onResponseCb might be called from other thread immediately after
  306. // startTracking returns, so we are not going to unlock mutex
  307. // until StartTrackingRequest is pushed into mRequestQueues[REQUEST_TRACKING]
  308. mRequestQueues[REQUEST_TRACKING].reset(session);
  309. mRequestQueues[REQUEST_TRACKING].push(new StartTrackingRequest(*this));
  310. mTracking = true;
  311. }
  312. retVal = LOCATION_ERROR_SUCCESS;
  313. }
  314. pthread_mutex_unlock(&mMutex);
  315. return retVal;
  316. }
  317. void LocationAPIClientBase::locAPIStopTracking()
  318. {
  319. pthread_mutex_lock(&mMutex);
  320. if (mLocationAPI) {
  321. uint32_t session = 0;
  322. session = mRequestQueues[REQUEST_TRACKING].getSession();
  323. if (session > 0) {
  324. mRequestQueues[REQUEST_TRACKING].push(new StopTrackingRequest(*this));
  325. mLocationAPI->stopTracking(session);
  326. mTracking = false;
  327. } else {
  328. LOC_LOGD("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session);
  329. }
  330. }
  331. pthread_mutex_unlock(&mMutex);
  332. }
  333. void LocationAPIClientBase::locAPIUpdateTrackingOptions(TrackingOptions& options)
  334. {
  335. pthread_mutex_lock(&mMutex);
  336. if (mLocationAPI) {
  337. uint32_t session = 0;
  338. session = mRequestQueues[REQUEST_TRACKING].getSession();
  339. if (session > 0) {
  340. mRequestQueues[REQUEST_TRACKING].push(new UpdateTrackingOptionsRequest(*this));
  341. mLocationAPI->updateTrackingOptions(session, options);
  342. } else {
  343. LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session);
  344. }
  345. }
  346. pthread_mutex_unlock(&mMutex);
  347. }
  348. int32_t LocationAPIClientBase::locAPIGetBatchSize()
  349. {
  350. if (mBatchSize == -1) {
  351. const loc_param_s_type batching_conf_param_table[] =
  352. {
  353. {"BATCH_SIZE", &mBatchSize, nullptr, 'n'},
  354. };
  355. UTIL_READ_CONF(LOC_PATH_BATCHING_CONF, batching_conf_param_table);
  356. if (mBatchSize < 0) {
  357. // set mBatchSize to 0 if we got an illegal value from config file
  358. mBatchSize = 0;
  359. }
  360. }
  361. return mBatchSize;
  362. }
  363. uint32_t LocationAPIClientBase::locAPIStartSession(
  364. uint32_t id, uint32_t sessionMode, TrackingOptions&& options)
  365. {
  366. uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
  367. pthread_mutex_lock(&mMutex);
  368. if (mLocationAPI) {
  369. if (mSessionBiDict.hasId(id)) {
  370. LOC_LOGE("%s:%d] session %d has already started.", __FUNCTION__, __LINE__, id);
  371. retVal = LOCATION_ERROR_ALREADY_STARTED;
  372. } else {
  373. uint32_t trackingSession = 0;
  374. uint32_t batchingSession = 0;
  375. if (sessionMode == SESSION_MODE_ON_FIX) {
  376. trackingSession = mLocationAPI->startTracking(options);
  377. LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, trackingSession);
  378. mRequestQueues[REQUEST_SESSION].push(new StartTrackingRequest(*this));
  379. } else {
  380. // Fill in the batch mode
  381. BatchingOptions batchOptions = {};
  382. batchOptions.size = sizeof(BatchingOptions);
  383. switch (sessionMode) {
  384. case SESSION_MODE_ON_FULL:
  385. batchOptions.batchingMode = BATCHING_MODE_ROUTINE;
  386. break;
  387. case SESSION_MODE_ON_TRIP_COMPLETED:
  388. batchOptions.batchingMode = BATCHING_MODE_TRIP;
  389. break;
  390. default:
  391. batchOptions.batchingMode = BATCHING_MODE_NO_AUTO_REPORT;
  392. break;
  393. }
  394. // Populate location option values
  395. batchOptions.minDistance = options.minDistance;
  396. batchOptions.minInterval = options.minInterval;
  397. batchOptions.mode = options.mode;
  398. batchingSession = mLocationAPI->startBatching(batchOptions);
  399. LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, batchingSession);
  400. mRequestQueues[REQUEST_SESSION].setSession(batchingSession);
  401. mRequestQueues[REQUEST_SESSION].push(new StartBatchingRequest(*this));
  402. }
  403. uint32_t session = ((sessionMode != SESSION_MODE_ON_FIX) ?
  404. batchingSession : trackingSession);
  405. SessionEntity entity;
  406. entity.id = id;
  407. entity.trackingSession = trackingSession;
  408. entity.batchingSession = batchingSession;
  409. entity.sessionMode = sessionMode;
  410. mSessionBiDict.set(id, session, entity);
  411. retVal = LOCATION_ERROR_SUCCESS;
  412. }
  413. }
  414. pthread_mutex_unlock(&mMutex);
  415. return retVal;
  416. }
  417. uint32_t LocationAPIClientBase::locAPIStopSession(uint32_t id)
  418. {
  419. uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
  420. pthread_mutex_lock(&mMutex);
  421. if (mLocationAPI) {
  422. if (mSessionBiDict.hasId(id)) {
  423. SessionEntity entity = mSessionBiDict.getExtById(id);
  424. uint32_t trackingSession = entity.trackingSession;
  425. uint32_t batchingSession = entity.batchingSession;
  426. uint32_t sMode = entity.sessionMode;
  427. if (sMode == SESSION_MODE_ON_FIX) {
  428. mRequestQueues[REQUEST_SESSION].push(new StopTrackingRequest(*this));
  429. mLocationAPI->stopTracking(trackingSession);
  430. } else {
  431. mRequestQueues[REQUEST_SESSION].push(new StopBatchingRequest(*this));
  432. mLocationAPI->stopBatching(batchingSession);
  433. }
  434. retVal = LOCATION_ERROR_SUCCESS;
  435. } else {
  436. retVal = LOCATION_ERROR_ID_UNKNOWN;
  437. LOC_LOGE("%s:%d] session %d is not exist.", __FUNCTION__, __LINE__, id);
  438. }
  439. }
  440. pthread_mutex_unlock(&mMutex);
  441. return retVal;
  442. }
  443. uint32_t LocationAPIClientBase::locAPIUpdateSessionOptions(
  444. uint32_t id, uint32_t sessionMode, TrackingOptions&& options)
  445. {
  446. uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
  447. pthread_mutex_lock(&mMutex);
  448. if (mLocationAPI) {
  449. if (mSessionBiDict.hasId(id)) {
  450. SessionEntity entity = mSessionBiDict.getExtById(id);
  451. uint32_t trackingSession = entity.trackingSession;
  452. uint32_t batchingSession = entity.batchingSession;
  453. uint32_t sMode = entity.sessionMode;
  454. if (sessionMode == SESSION_MODE_ON_FIX) {
  455. // we only add an UpdateTrackingOptionsRequest to mRequestQueues[REQUEST_SESSION],
  456. // even if this update request will stop batching and then start tracking.
  457. mRequestQueues[REQUEST_SESSION].push(new UpdateTrackingOptionsRequest(*this));
  458. if (sMode == SESSION_MODE_ON_FIX) {
  459. mLocationAPI->updateTrackingOptions(trackingSession, options);
  460. } else {
  461. // stop batching
  462. // batchingSession will be removed from mSessionBiDict soon,
  463. // so we don't need to add a new request to mRequestQueues[REQUEST_SESSION].
  464. mLocationAPI->stopBatching(batchingSession);
  465. batchingSession = 0;
  466. mRequestQueues[REQUEST_SESSION].setSession(batchingSession);
  467. // start tracking
  468. trackingSession = mLocationAPI->startTracking(options);
  469. LOC_LOGI("%s:%d] start new session: %d",
  470. __FUNCTION__, __LINE__, trackingSession);
  471. }
  472. } else {
  473. // we only add an UpdateBatchingOptionsRequest to mRequestQueues[REQUEST_SESSION],
  474. // even if this update request will stop tracking and then start batching.
  475. mRequestQueues[REQUEST_SESSION].push(new UpdateBatchingOptionsRequest(*this));
  476. BatchingOptions batchOptions = {};
  477. batchOptions.size = sizeof(BatchingOptions);
  478. switch (sessionMode) {
  479. case SESSION_MODE_ON_FULL:
  480. batchOptions.batchingMode = BATCHING_MODE_ROUTINE;
  481. break;
  482. case SESSION_MODE_ON_TRIP_COMPLETED:
  483. batchOptions.batchingMode = BATCHING_MODE_TRIP;
  484. break;
  485. default:
  486. batchOptions.batchingMode = BATCHING_MODE_NO_AUTO_REPORT;
  487. break;
  488. }
  489. if (sMode == SESSION_MODE_ON_FIX) {
  490. // stop tracking
  491. // trackingSession will be removed from mSessionBiDict soon,
  492. // so we don't need to add a new request to mRequestQueues[REQUEST_SESSION].
  493. mLocationAPI->stopTracking(trackingSession);
  494. trackingSession = 0;
  495. // Populate location option values
  496. batchOptions.minDistance = options.minDistance;
  497. batchOptions.minInterval = options.minInterval;
  498. batchOptions.mode = options.mode;
  499. // start batching
  500. batchingSession = mLocationAPI->startBatching(batchOptions);
  501. LOC_LOGI("%s:%d] start new session: %d",
  502. __FUNCTION__, __LINE__, batchingSession);
  503. mRequestQueues[REQUEST_SESSION].setSession(batchingSession);
  504. } else {
  505. mLocationAPI->updateBatchingOptions(batchingSession, batchOptions);
  506. }
  507. }
  508. uint32_t session = ((sessionMode != SESSION_MODE_ON_FIX) ?
  509. batchingSession : trackingSession);
  510. entity.trackingSession = trackingSession;
  511. entity.batchingSession = batchingSession;
  512. entity.sessionMode = sessionMode;
  513. // remove the old values from mSessionBiDict before we add a new one.
  514. mSessionBiDict.rmById(id);
  515. mSessionBiDict.set(id, session, entity);
  516. retVal = LOCATION_ERROR_SUCCESS;
  517. } else {
  518. retVal = LOCATION_ERROR_ID_UNKNOWN;
  519. LOC_LOGE("%s:%d] session %d is not exist.", __FUNCTION__, __LINE__, id);
  520. }
  521. }
  522. pthread_mutex_unlock(&mMutex);
  523. return retVal;
  524. }
  525. uint32_t LocationAPIClientBase::locAPIGetBatchedLocations(uint32_t id, size_t count)
  526. {
  527. uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
  528. pthread_mutex_lock(&mMutex);
  529. if (mLocationAPI) {
  530. if (mSessionBiDict.hasId(id)) {
  531. SessionEntity entity = mSessionBiDict.getExtById(id);
  532. if (entity.sessionMode != SESSION_MODE_ON_FIX) {
  533. uint32_t batchingSession = entity.batchingSession;
  534. mRequestQueues[REQUEST_SESSION].push(new GetBatchedLocationsRequest(*this));
  535. mLocationAPI->getBatchedLocations(batchingSession, count);
  536. retVal = LOCATION_ERROR_SUCCESS;
  537. } else {
  538. LOC_LOGE("%s:%d] Unsupported for session id: %d, mode is SESSION_MODE_ON_FIX",
  539. __FUNCTION__, __LINE__, id);
  540. retVal = LOCATION_ERROR_NOT_SUPPORTED;
  541. }
  542. } else {
  543. retVal = LOCATION_ERROR_ID_UNKNOWN;
  544. LOC_LOGd("unknown session id: %d, might flush() a stopped session", id);
  545. }
  546. }
  547. pthread_mutex_unlock(&mMutex);
  548. return retVal;
  549. }
  550. uint32_t LocationAPIClientBase::locAPIAddGeofences(
  551. size_t count, uint32_t* ids, GeofenceOption* options, GeofenceInfo* data)
  552. {
  553. uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
  554. pthread_mutex_lock(&mMutex);
  555. if (mLocationAPI) {
  556. if (mRequestQueues[REQUEST_GEOFENCE].getSession() != GEOFENCE_SESSION_ID) {
  557. mRequestQueues[REQUEST_GEOFENCE].reset(GEOFENCE_SESSION_ID);
  558. }
  559. uint32_t* sessions = mLocationAPI->addGeofences(count, options, data);
  560. if (sessions) {
  561. LOC_LOGI("%s:%d] start new sessions: %p", __FUNCTION__, __LINE__, sessions);
  562. mRequestQueues[REQUEST_GEOFENCE].push(new AddGeofencesRequest(*this));
  563. for (size_t i = 0; i < count; i++) {
  564. mGeofenceBiDict.set(ids[i], sessions[i], options[i].breachTypeMask);
  565. }
  566. retVal = LOCATION_ERROR_SUCCESS;
  567. }
  568. }
  569. pthread_mutex_unlock(&mMutex);
  570. return retVal;
  571. }
  572. void LocationAPIClientBase::locAPIRemoveGeofences(size_t count, uint32_t* ids)
  573. {
  574. pthread_mutex_lock(&mMutex);
  575. if (mLocationAPI) {
  576. uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
  577. if (sessions == NULL) {
  578. LOC_LOGE("%s:%d] Failed to allocate %zu bytes !",
  579. __FUNCTION__, __LINE__, sizeof(uint32_t) * count);
  580. pthread_mutex_unlock(&mMutex);
  581. return;
  582. }
  583. if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
  584. BiDict<GeofenceBreachTypeMask>* removedGeofenceBiDict =
  585. new BiDict<GeofenceBreachTypeMask>();
  586. size_t j = 0;
  587. for (size_t i = 0; i < count; i++) {
  588. sessions[j] = mGeofenceBiDict.getSession(ids[i]);
  589. if (sessions[j] > 0) {
  590. GeofenceBreachTypeMask type = mGeofenceBiDict.getExtBySession(sessions[j]);
  591. mGeofenceBiDict.rmBySession(sessions[j]);
  592. removedGeofenceBiDict->set(ids[i], sessions[j], type);
  593. j++;
  594. }
  595. }
  596. if (j > 0) {
  597. mRequestQueues[REQUEST_GEOFENCE].push(new RemoveGeofencesRequest(*this,
  598. removedGeofenceBiDict));
  599. mLocationAPI->removeGeofences(j, sessions);
  600. } else {
  601. delete(removedGeofenceBiDict);
  602. }
  603. } else {
  604. LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
  605. mRequestQueues[REQUEST_GEOFENCE].getSession());
  606. }
  607. free(sessions);
  608. }
  609. pthread_mutex_unlock(&mMutex);
  610. }
  611. void LocationAPIClientBase::locAPIModifyGeofences(
  612. size_t count, uint32_t* ids, GeofenceOption* options)
  613. {
  614. pthread_mutex_lock(&mMutex);
  615. if (mLocationAPI) {
  616. uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
  617. if (sessions == NULL) {
  618. LOC_LOGE("%s:%d] Failed to allocate %zu bytes !",
  619. __FUNCTION__, __LINE__, sizeof(uint32_t) * count);
  620. pthread_mutex_unlock(&mMutex);
  621. return;
  622. }
  623. if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
  624. size_t j = 0;
  625. for (size_t i = 0; i < count; i++) {
  626. sessions[j] = mGeofenceBiDict.getSession(ids[i]);
  627. if (sessions[j] > 0) {
  628. mGeofenceBiDict.set(ids[i], sessions[j], options[i].breachTypeMask);
  629. j++;
  630. }
  631. }
  632. if (j > 0) {
  633. mRequestQueues[REQUEST_GEOFENCE].push(new ModifyGeofencesRequest(*this));
  634. mLocationAPI->modifyGeofences(j, sessions, options);
  635. }
  636. } else {
  637. LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
  638. mRequestQueues[REQUEST_GEOFENCE].getSession());
  639. }
  640. free(sessions);
  641. }
  642. pthread_mutex_unlock(&mMutex);
  643. }
  644. void LocationAPIClientBase::locAPIPauseGeofences(size_t count, uint32_t* ids)
  645. {
  646. pthread_mutex_lock(&mMutex);
  647. if (mLocationAPI) {
  648. uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
  649. if (sessions == NULL) {
  650. LOC_LOGE("%s:%d] Failed to allocate %zu bytes !",
  651. __FUNCTION__, __LINE__, sizeof(uint32_t) * count);
  652. pthread_mutex_unlock(&mMutex);
  653. return;
  654. }
  655. if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
  656. size_t j = 0;
  657. for (size_t i = 0; i < count; i++) {
  658. sessions[j] = mGeofenceBiDict.getSession(ids[i]);
  659. if (sessions[j] > 0) {
  660. j++;
  661. }
  662. }
  663. if (j > 0) {
  664. mRequestQueues[REQUEST_GEOFENCE].push(new PauseGeofencesRequest(*this));
  665. mLocationAPI->pauseGeofences(j, sessions);
  666. }
  667. } else {
  668. LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
  669. mRequestQueues[REQUEST_GEOFENCE].getSession());
  670. }
  671. free(sessions);
  672. }
  673. pthread_mutex_unlock(&mMutex);
  674. }
  675. void LocationAPIClientBase::locAPIResumeGeofences(
  676. size_t count, uint32_t* ids, GeofenceBreachTypeMask* mask)
  677. {
  678. pthread_mutex_lock(&mMutex);
  679. if (mLocationAPI) {
  680. uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
  681. if (sessions == NULL) {
  682. LOC_LOGE("%s:%d] Failed to allocate %zu bytes !",
  683. __FUNCTION__, __LINE__, sizeof(uint32_t) * count);
  684. pthread_mutex_unlock(&mMutex);
  685. return;
  686. }
  687. if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
  688. size_t j = 0;
  689. for (size_t i = 0; i < count; i++) {
  690. sessions[j] = mGeofenceBiDict.getSession(ids[i]);
  691. if (sessions[j] > 0) {
  692. if (mask) {
  693. mGeofenceBiDict.set(ids[i], sessions[j], mask[i]);
  694. }
  695. j++;
  696. }
  697. }
  698. if (j > 0) {
  699. mRequestQueues[REQUEST_GEOFENCE].push(new ResumeGeofencesRequest(*this));
  700. mLocationAPI->resumeGeofences(j, sessions);
  701. }
  702. } else {
  703. LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
  704. mRequestQueues[REQUEST_GEOFENCE].getSession());
  705. }
  706. free(sessions);
  707. }
  708. pthread_mutex_unlock(&mMutex);
  709. }
  710. void LocationAPIClientBase::locAPIRemoveAllGeofences()
  711. {
  712. std::vector<uint32_t> idsVec = mGeofenceBiDict.getAllIds();
  713. if (idsVec.size() > 0) {
  714. locAPIRemoveGeofences(idsVec.size(), &idsVec[0]);
  715. }
  716. }
  717. void LocationAPIClientBase::locAPIGnssNiResponse(uint32_t id, GnssNiResponse response)
  718. {
  719. pthread_mutex_lock(&mMutex);
  720. if (mLocationAPI) {
  721. uint32_t session = id;
  722. mLocationAPI->gnssNiResponse(id, response);
  723. LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session);
  724. mRequestQueues[REQUEST_NIRESPONSE].reset(session);
  725. mRequestQueues[REQUEST_NIRESPONSE].push(new GnssNiResponseRequest(*this));
  726. }
  727. pthread_mutex_unlock(&mMutex);
  728. }
  729. void LocationAPIClientBase::beforeGeofenceBreachCb(
  730. GeofenceBreachNotification geofenceBreachNotification)
  731. {
  732. uint32_t* ids = (uint32_t*)malloc(sizeof(uint32_t) * geofenceBreachNotification.count);
  733. uint32_t* backup = geofenceBreachNotification.ids;
  734. size_t n = geofenceBreachNotification.count;
  735. geofenceBreachCallback genfenceCallback = nullptr;
  736. if (ids == NULL) {
  737. LOC_LOGE("%s:%d] Failed to alloc %zu bytes",
  738. __FUNCTION__, __LINE__,
  739. sizeof(uint32_t) * geofenceBreachNotification.count);
  740. return;
  741. }
  742. pthread_mutex_lock(&mMutex);
  743. if (mGeofenceBreachCallback != nullptr) {
  744. size_t count = 0;
  745. for (size_t i = 0; i < n; i++) {
  746. uint32_t id = mGeofenceBiDict.getId(geofenceBreachNotification.ids[i]);
  747. GeofenceBreachTypeMask type =
  748. mGeofenceBiDict.getExtBySession(geofenceBreachNotification.ids[i]);
  749. // if type == 0, we will not head into the fllowing block anyway.
  750. // so we don't need to check id and type
  751. if ((geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER &&
  752. (type & GEOFENCE_BREACH_ENTER_BIT)) ||
  753. (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT &&
  754. (type & GEOFENCE_BREACH_EXIT_BIT))
  755. ) {
  756. ids[count] = id;
  757. count++;
  758. }
  759. }
  760. geofenceBreachNotification.count = count;
  761. geofenceBreachNotification.ids = ids;
  762. genfenceCallback = mGeofenceBreachCallback;
  763. }
  764. pthread_mutex_unlock(&mMutex);
  765. if (genfenceCallback != nullptr) {
  766. genfenceCallback(geofenceBreachNotification);
  767. }
  768. // restore ids
  769. geofenceBreachNotification.ids = backup;
  770. geofenceBreachNotification.count = n;
  771. free(ids);
  772. }
  773. void LocationAPIClientBase::beforeBatchingStatusCb(BatchingStatusInfo batchStatus,
  774. std::list<uint32_t> & tripCompletedList) {
  775. // map the trip ids to the client ids
  776. std::list<uint32_t> tripCompletedClientIdList;
  777. tripCompletedClientIdList.clear();
  778. if (batchStatus.batchingStatus == BATCHING_STATUS_TRIP_COMPLETED) {
  779. for (auto itt = tripCompletedList.begin(); itt != tripCompletedList.end(); itt++) {
  780. if (mSessionBiDict.hasSession(*itt)) {
  781. SessionEntity sessEntity = mSessionBiDict.getExtBySession(*itt);
  782. if (sessEntity.sessionMode == SESSION_MODE_ON_TRIP_COMPLETED) {
  783. tripCompletedClientIdList.push_back(sessEntity.id);
  784. mSessionBiDict.rmBySession(*itt);
  785. }
  786. }
  787. }
  788. }
  789. mBatchingStatusCallback(batchStatus, tripCompletedClientIdList);
  790. }
  791. void LocationAPIClientBase::onResponseCb(LocationError error, uint32_t id)
  792. {
  793. if (error != LOCATION_ERROR_SUCCESS) {
  794. LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, error, id);
  795. } else {
  796. LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, error, id);
  797. }
  798. LocationAPIRequest* request = getRequestBySession(id);
  799. if (request) {
  800. request->onResponse(error, id);
  801. delete request;
  802. }
  803. }
  804. void LocationAPIClientBase::onCollectiveResponseCb(
  805. size_t count, LocationError* errors, uint32_t* ids)
  806. {
  807. for (size_t i = 0; i < count; i++) {
  808. if (errors[i] != LOCATION_ERROR_SUCCESS) {
  809. LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, errors[i], ids[i]);
  810. } else {
  811. LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, errors[i], ids[i]);
  812. }
  813. }
  814. LocationAPIRequest* request = nullptr;
  815. pthread_mutex_lock(&mMutex);
  816. if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
  817. request = mRequestQueues[REQUEST_GEOFENCE].pop();
  818. }
  819. pthread_mutex_unlock(&mMutex);
  820. if (request) {
  821. request->onCollectiveResponse(count, errors, ids);
  822. delete request;
  823. }
  824. }
  825. void LocationAPIClientBase::removeSession(uint32_t session) {
  826. if (mSessionBiDict.hasSession(session)) {
  827. mSessionBiDict.rmBySession(session);
  828. }
  829. }
  830. LocationAPIRequest* LocationAPIClientBase::getRequestBySession(uint32_t session)
  831. {
  832. pthread_mutex_lock(&mMutex);
  833. LocationAPIRequest* request = nullptr;
  834. for (int i = 0; i < REQUEST_MAX; i++) {
  835. if (i != REQUEST_GEOFENCE &&
  836. i != REQUEST_SESSION &&
  837. mRequestQueues[i].getSession() == session) {
  838. request = mRequestQueues[i].pop();
  839. break;
  840. }
  841. }
  842. if (request == nullptr) {
  843. // Can't find a request with correct session,
  844. // try to find it from mSessionBiDict
  845. if (mSessionBiDict.hasSession(session)) {
  846. request = mRequestQueues[REQUEST_SESSION].pop();
  847. }
  848. }
  849. pthread_mutex_unlock(&mMutex);
  850. return request;
  851. }