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