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 };
45 
46 enum REQUEST_TYPE {
47     REQUEST_TRACKING = 0,
48     REQUEST_BATCHING,
49     REQUEST_GEOFENCE,
50     REQUEST_NIRESPONSE,
51     REQUEST_DELETEAIDINGDATA,
52     REQUEST_CONTROL,
53     REQUEST_MAX,
54 };
55 
56 class LocationAPIClientBase
57 {
58 public:
59     LocationAPIClientBase();
60     virtual ~LocationAPIClientBase();
61     LocationAPIClientBase(const LocationAPIClientBase&) = delete;
62     LocationAPIClientBase& operator=(const LocationAPIClientBase&) = delete;
63 
64     void locAPISetCallbacks(LocationCallbacks& locationCallbacks);
65 
66     // LocationAPI
67     uint32_t locAPIStartTracking(LocationOptions& options);
68     void locAPIStopTracking();
69     void locAPIUpdateTrackingOptions(LocationOptions& options);
70 
71     int32_t locAPIGetBatchSize();
72     uint32_t locAPIStartSession(uint32_t id, uint32_t sessionMode,
73             LocationOptions& options);
74     uint32_t locAPIStopSession(uint32_t id);
75     uint32_t locAPIUpdateSessionOptions(uint32_t id, uint32_t sessionMode,
76             LocationOptions& options);
77     void locAPIGetBatchedLocations(size_t count);
78 
79     uint32_t locAPIAddGeofences(size_t count, uint32_t* ids,
80             GeofenceOption* options, GeofenceInfo* data);
81     void locAPIRemoveGeofences(size_t count, uint32_t* ids);
82     void locAPIModifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options);
83     void locAPIPauseGeofences(size_t count, uint32_t* ids);
84     void locAPIResumeGeofences(size_t count, uint32_t* ids, GeofenceBreachTypeMask* mask);
85     void locAPIRemoveAllGeofences();
86 
87     void locAPIGnssNiResponse(uint32_t id, GnssNiResponse response);
88     uint32_t locAPIGnssDeleteAidingData(GnssAidingData& data);
89 
90     uint32_t locAPIEnable(LocationTechnologyType techType);
91     void locAPIDisable();
92     uint32_t locAPIGnssUpdateConfig(GnssConfig config);
93 
94     // callbacks
95     void onResponseCb(LocationError error, uint32_t id);
96     void onCollectiveResponseCb(size_t count, LocationError* errors, uint32_t* ids);
97 
98     void onCtrlResponseCb(LocationError error, uint32_t id);
99     void onCtrlCollectiveResponseCb(size_t count, LocationError* errors, uint32_t* ids);
100 
101     void beforeGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification);
102 
onCapabilitiesCb(LocationCapabilitiesMask)103     inline virtual void onCapabilitiesCb(LocationCapabilitiesMask /*capabilitiesMask*/) {}
onGnssNmeaCb(GnssNmeaNotification)104     inline virtual void onGnssNmeaCb(GnssNmeaNotification /*gnssNmeaNotification*/) {}
onGnssMeasurementsCb(GnssMeasurementsNotification)105     inline virtual void onGnssMeasurementsCb(
106             GnssMeasurementsNotification /*gnssMeasurementsNotification*/) {}
107 
onTrackingCb(Location)108     inline virtual void onTrackingCb(Location /*location*/) {}
onGnssSvCb(GnssSvNotification)109     inline virtual void onGnssSvCb(GnssSvNotification /*gnssSvNotification*/) {}
onStartTrackingCb(LocationError)110     inline virtual void onStartTrackingCb(LocationError /*error*/) {}
onStopTrackingCb(LocationError)111     inline virtual void onStopTrackingCb(LocationError /*error*/) {}
onUpdateTrackingOptionsCb(LocationError)112     inline virtual void onUpdateTrackingOptionsCb(LocationError /*error*/) {}
113 
onGnssLocationInfoCb(GnssLocationInfoNotification)114     inline virtual void onGnssLocationInfoCb(
115             GnssLocationInfoNotification /*gnssLocationInfoNotification*/) {}
116 
onBatchingCb(size_t,Location *)117     inline virtual void onBatchingCb(size_t /*count*/, Location* /*location*/) {}
onStartBatchingCb(LocationError)118     inline virtual void onStartBatchingCb(LocationError /*error*/) {}
onStopBatchingCb(LocationError)119     inline virtual void onStopBatchingCb(LocationError /*error*/) {}
onUpdateBatchingOptionsCb(LocationError)120     inline virtual void onUpdateBatchingOptionsCb(LocationError /*error*/) {}
onGetBatchedLocationsCb(LocationError)121     inline virtual void onGetBatchedLocationsCb(LocationError /*error*/) {}
122 
onGeofenceBreachCb(GeofenceBreachNotification)123     inline virtual void onGeofenceBreachCb(
124             GeofenceBreachNotification /*geofenceBreachNotification*/) {}
onGeofenceStatusCb(GeofenceStatusNotification)125     inline virtual void onGeofenceStatusCb(
126             GeofenceStatusNotification /*geofenceStatusNotification*/) {}
onAddGeofencesCb(size_t,LocationError *,uint32_t *)127     inline virtual void onAddGeofencesCb(
128             size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
onRemoveGeofencesCb(size_t,LocationError *,uint32_t *)129     inline virtual void onRemoveGeofencesCb(
130             size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
onModifyGeofencesCb(size_t,LocationError *,uint32_t *)131     inline virtual void onModifyGeofencesCb(
132             size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
onPauseGeofencesCb(size_t,LocationError *,uint32_t *)133     inline virtual void onPauseGeofencesCb(
134             size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
onResumeGeofencesCb(size_t,LocationError *,uint32_t *)135     inline virtual void onResumeGeofencesCb(
136             size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
137 
onGnssNiCb(uint32_t,GnssNiNotification)138     inline virtual void onGnssNiCb(uint32_t /*id*/, GnssNiNotification /*gnssNiNotification*/) {}
onGnssNiResponseCb(LocationError)139     inline virtual void onGnssNiResponseCb(LocationError /*error*/) {}
onGnssDeleteAidingDataCb(LocationError)140     inline virtual void onGnssDeleteAidingDataCb(LocationError /*error*/) {}
141 
onEnableCb(LocationError)142     inline virtual void onEnableCb(LocationError /*error*/) {}
onDisableCb(LocationError)143     inline virtual void onDisableCb(LocationError /*error*/) {}
onGnssUpdateConfigCb(size_t,LocationError *,uint32_t *)144     inline virtual void onGnssUpdateConfigCb(
145             size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
146 
147 private:
148     // private inner classes
149     typedef struct {
150         uint32_t id;
151         uint32_t trackingSession;
152         uint32_t batchingSession;
153         uint32_t sessionMode;
154     } SessionEntity;
155 
156     class BiDict {
157     public:
BiDict()158         BiDict() {
159             pthread_mutex_init(&mBiDictMutex, nullptr);
160         }
~BiDict()161         ~BiDict() {
162             pthread_mutex_destroy(&mBiDictMutex);
163         }
hasId(uint32_t id)164         bool hasId(uint32_t id) {
165             pthread_mutex_lock(&mBiDictMutex);
166             bool ret = (mForwardMap.find(id) != mForwardMap.end());
167             pthread_mutex_unlock(&mBiDictMutex);
168             return ret;
169         }
set(uint32_t id,uint32_t session,uint32_t type)170         void set(uint32_t id, uint32_t session, uint32_t type) {
171             pthread_mutex_lock(&mBiDictMutex);
172             mForwardMap[id] = session;
173             mBackwardMap[session] = id;
174             mTypeMap[session] = type;
175             pthread_mutex_unlock(&mBiDictMutex);
176         }
clear()177         void clear() {
178             pthread_mutex_lock(&mBiDictMutex);
179             mForwardMap.clear();
180             mBackwardMap.clear();
181             mTypeMap.clear();
182             pthread_mutex_unlock(&mBiDictMutex);
183         }
rmById(uint32_t id)184         void rmById(uint32_t id) {
185             pthread_mutex_lock(&mBiDictMutex);
186             mBackwardMap.erase(mForwardMap[id]);
187             mTypeMap.erase(mForwardMap[id]);
188             mForwardMap.erase(id);
189             pthread_mutex_unlock(&mBiDictMutex);
190         }
rmBySession(uint32_t session)191         void rmBySession(uint32_t session) {
192             pthread_mutex_lock(&mBiDictMutex);
193             mForwardMap.erase(mBackwardMap[session]);
194             mBackwardMap.erase(session);
195             mTypeMap.erase(session);
196             pthread_mutex_unlock(&mBiDictMutex);
197         }
getId(uint32_t session)198         uint32_t getId(uint32_t session) {
199             pthread_mutex_lock(&mBiDictMutex);
200             uint32_t ret = mBackwardMap[session];
201             pthread_mutex_unlock(&mBiDictMutex);
202             return ret;
203         }
getSession(uint32_t id)204         uint32_t getSession(uint32_t id) {
205             pthread_mutex_lock(&mBiDictMutex);
206             uint32_t ret = mForwardMap[id];
207             pthread_mutex_unlock(&mBiDictMutex);
208             return ret;
209         }
getType(uint32_t session)210         uint32_t getType(uint32_t session) {
211             pthread_mutex_lock(&mBiDictMutex);
212             uint32_t ret = mTypeMap[session];
213             pthread_mutex_unlock(&mBiDictMutex);
214             return ret;
215         }
getAllSessions()216         std::vector<uint32_t> getAllSessions() {
217             std::vector<uint32_t> ret;
218             pthread_mutex_lock(&mBiDictMutex);
219             for (auto it = mBackwardMap.begin(); it != mBackwardMap.end(); it++) {
220                 ret.push_back(it->first);
221             }
222             pthread_mutex_unlock(&mBiDictMutex);
223             return ret;
224         }
225     private:
226         pthread_mutex_t mBiDictMutex;
227         // mForwarMap mapping id->session
228         std::map<uint32_t, uint32_t> mForwardMap;
229         // mBackwardMap mapping session->id
230         std::map<uint32_t, uint32_t> mBackwardMap;
231         // mTypeMap mapping session->type
232         std::map<uint32_t, uint32_t> mTypeMap;
233     };
234 
235     class LocationAPIRequest {
236     public:
LocationAPIRequest(LocationAPIClientBase & API)237         LocationAPIRequest(LocationAPIClientBase& API) : mAPI(API) {}
~LocationAPIRequest()238         virtual ~LocationAPIRequest() {}
onResponse(LocationError)239         virtual void onResponse(LocationError /*error*/) {};
onCollectiveResponse(size_t,LocationError *,uint32_t *)240         virtual void onCollectiveResponse(
241                 size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {};
242         LocationAPIClientBase& mAPI;
243     };
244 
245     class StartTrackingRequest : public LocationAPIRequest {
246     public:
StartTrackingRequest(LocationAPIClientBase & API)247         StartTrackingRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
onResponse(LocationError error)248         inline void onResponse(LocationError error) {
249             mAPI.onStartTrackingCb(error);
250         }
251     };
252 
253     class StopTrackingRequest : public LocationAPIRequest {
254     public:
StopTrackingRequest(LocationAPIClientBase & API)255         StopTrackingRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
onResponse(LocationError error)256         inline void onResponse(LocationError error) {
257             mAPI.onStopTrackingCb(error);
258         }
259     };
260 
261     class UpdateTrackingOptionsRequest : public LocationAPIRequest {
262     public:
UpdateTrackingOptionsRequest(LocationAPIClientBase & API)263         UpdateTrackingOptionsRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
onResponse(LocationError error)264         inline void onResponse(LocationError error) {
265             mAPI.onUpdateTrackingOptionsCb(error);
266         }
267     };
268 
269     class StartBatchingRequest : public LocationAPIRequest {
270     public:
StartBatchingRequest(LocationAPIClientBase & API)271         StartBatchingRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
onResponse(LocationError error)272         inline void onResponse(LocationError error) {
273             mAPI.onStartBatchingCb(error);
274         }
275     };
276 
277     class StopBatchingRequest : public LocationAPIRequest {
278     public:
StopBatchingRequest(LocationAPIClientBase & API)279         StopBatchingRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
onResponse(LocationError error)280         inline void onResponse(LocationError error) {
281             mAPI.onStopBatchingCb(error);
282         }
283     };
284 
285     class UpdateBatchingOptionsRequest : public LocationAPIRequest {
286     public:
UpdateBatchingOptionsRequest(LocationAPIClientBase & API)287         UpdateBatchingOptionsRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
onResponse(LocationError error)288         inline void onResponse(LocationError error) {
289             mAPI.onUpdateBatchingOptionsCb(error);
290         }
291     };
292 
293     class GetBatchedLocationsRequest : public LocationAPIRequest {
294     public:
GetBatchedLocationsRequest(LocationAPIClientBase & API)295         GetBatchedLocationsRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
onResponse(LocationError error)296         inline void onResponse(LocationError error) {
297             mAPI.onGetBatchedLocationsCb(error);
298         }
299     };
300 
301     class AddGeofencesRequest : public LocationAPIRequest {
302     public:
AddGeofencesRequest(LocationAPIClientBase & API)303         AddGeofencesRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
onCollectiveResponse(size_t count,LocationError * errors,uint32_t * sessions)304         inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) {
305             uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count);
306             for (size_t i = 0; i < count; i++) {
307                 ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]);
308             }
309             mAPI.onAddGeofencesCb(count, errors, ids);
310             free(ids);
311         }
312     };
313 
314     class RemoveGeofencesRequest : public LocationAPIRequest {
315     public:
RemoveGeofencesRequest(LocationAPIClientBase & API)316         RemoveGeofencesRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
onCollectiveResponse(size_t count,LocationError * errors,uint32_t * sessions)317         inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) {
318             uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count);
319             for (size_t i = 0; i < count; i++) {
320                 ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]);
321                 mAPI.mGeofenceBiDict.rmBySession(sessions[i]);
322             }
323             mAPI.onRemoveGeofencesCb(count, errors, ids);
324             free(ids);
325         }
326     };
327 
328     class ModifyGeofencesRequest : public LocationAPIRequest {
329     public:
ModifyGeofencesRequest(LocationAPIClientBase & API)330         ModifyGeofencesRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
onCollectiveResponse(size_t count,LocationError * errors,uint32_t * sessions)331         inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) {
332             uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count);
333             for (size_t i = 0; i < count; i++) {
334                 ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]);
335             }
336             mAPI.onModifyGeofencesCb(count, errors, ids);
337             free(ids);
338         }
339     };
340 
341     class PauseGeofencesRequest : public LocationAPIRequest {
342     public:
PauseGeofencesRequest(LocationAPIClientBase & API)343         PauseGeofencesRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
onCollectiveResponse(size_t count,LocationError * errors,uint32_t * sessions)344         inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) {
345             uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count);
346             for (size_t i = 0; i < count; i++) {
347                 ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]);
348             }
349             mAPI.onPauseGeofencesCb(count, errors, ids);
350             free(ids);
351         }
352     };
353 
354     class ResumeGeofencesRequest : public LocationAPIRequest {
355     public:
ResumeGeofencesRequest(LocationAPIClientBase & API)356         ResumeGeofencesRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
onCollectiveResponse(size_t count,LocationError * errors,uint32_t * sessions)357         inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) {
358             uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count);
359             for (size_t i = 0; i < count; i++) {
360                 ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]);
361             }
362             mAPI.onResumeGeofencesCb(count, errors, ids);
363             free(ids);
364         }
365     };
366 
367     class GnssNiResponseRequest : public LocationAPIRequest {
368     public:
GnssNiResponseRequest(LocationAPIClientBase & API)369         GnssNiResponseRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
onResponse(LocationError error)370         inline void onResponse(LocationError error) {
371             mAPI.onGnssNiResponseCb(error);
372         }
373     };
374 
375     class GnssDeleteAidingDataRequest : public LocationAPIRequest {
376     public:
GnssDeleteAidingDataRequest(LocationAPIClientBase & API)377         GnssDeleteAidingDataRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
onResponse(LocationError error)378         inline void onResponse(LocationError error) {
379             mAPI.onGnssDeleteAidingDataCb(error);
380         }
381     };
382 
383     class EnableRequest : public LocationAPIRequest {
384     public:
EnableRequest(LocationAPIClientBase & API)385         EnableRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
onResponse(LocationError error)386         inline void onResponse(LocationError error) {
387             mAPI.onEnableCb(error);
388         }
389     };
390 
391     class DisableRequest : public LocationAPIRequest {
392     public:
DisableRequest(LocationAPIClientBase & API)393         DisableRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
onResponse(LocationError error)394         inline void onResponse(LocationError error) {
395             mAPI.onDisableCb(error);
396         }
397     };
398 
399     class GnssUpdateConfigRequest : public LocationAPIRequest {
400     public:
GnssUpdateConfigRequest(LocationAPIClientBase & API)401         GnssUpdateConfigRequest(LocationAPIClientBase& API) : LocationAPIRequest(API) {}
onCollectiveResponse(size_t count,LocationError * errors,uint32_t * ids)402         inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* ids) {
403             mAPI.onGnssUpdateConfigCb(count, errors, ids);
404         }
405     };
406 
407     class RequestQueue {
408     public:
RequestQueue(uint32_t session)409         RequestQueue(uint32_t session): mSession(session) {
410         }
~RequestQueue()411         ~RequestQueue() {
412             LocationAPIRequest* request = nullptr;
413             while (!mQueue.empty()) {
414                 request = mQueue.front();
415                 mQueue.pop();
416                 delete request;
417             }
418         }
push(LocationAPIRequest * request)419         void push(LocationAPIRequest* request) {
420             mQueue.push(request);
421         }
pop()422         LocationAPIRequest* pop() {
423             LocationAPIRequest* request = nullptr;
424             if (!mQueue.empty()) {
425                 request = mQueue.front();
426                 mQueue.pop();
427             }
428             return request;
429         }
getSession()430         uint32_t getSession() { return mSession; }
431     private:
432         uint32_t mSession;
433         std::queue<LocationAPIRequest*> mQueue;
434     };
435 
436     LocationAPIRequest* getRequestBySession(uint32_t session);
437     LocationAPIRequest* getGeofencesRequest();
438 
439 private:
440     pthread_mutex_t mMutex;
441 
442     trackingCallback mTrackingCallback;
443     batchingCallback mBatchingCallback;
444     geofenceBreachCallback mGeofenceBreachCallback;
445 
446     LocationAPI* mLocationAPI;
447     LocationControlAPI* mLocationControlAPI;
448 
449     BiDict mGeofenceBiDict;
450     RequestQueue* mRequestQueues[REQUEST_MAX];
451     std::map<uint32_t, SessionEntity> mSessionMap;
452     int32_t mBatchSize;
453 
454     GnssConfig mConfig;
455 };
456 
457 #endif /* LOCATION_API_CLINET_BASE_H */
458