1/* Copyright (c) 2011-2014, 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#define LOG_NDDEBUG 0
30#define LOG_TAG "LocSvc_EngAdapter"
31
32#include <LocEngAdapter.h>
33#include "loc_eng_msg.h"
34#include "loc_log.h"
35
36using namespace loc_core;
37
38LocInternalAdapter::LocInternalAdapter(LocEngAdapter* adapter) :
39    LocAdapterBase(adapter->getMsgTask()),
40    mLocEngAdapter(adapter)
41{
42}
43void LocInternalAdapter::setPositionModeInt(LocPosMode& posMode) {
44    sendMsg(new LocEngPositionMode(mLocEngAdapter, posMode));
45}
46void LocInternalAdapter::startFixInt() {
47    sendMsg(new LocEngStartFix(mLocEngAdapter));
48}
49void LocInternalAdapter::stopFixInt() {
50    sendMsg(new LocEngStopFix(mLocEngAdapter));
51}
52void LocInternalAdapter::getZppInt() {
53    sendMsg(new LocEngGetZpp(mLocEngAdapter));
54}
55
56LocEngAdapter::LocEngAdapter(LOC_API_ADAPTER_EVENT_MASK_T mask,
57                             void* owner, ContextBase* context,
58                             MsgTask::tCreate tCreator) :
59    LocAdapterBase(mask,
60                   //Get the AFW context if VzW context has not already been intialized in
61                   //loc_ext
62                   context == NULL?
63                   LocDualContext::getLocFgContext(tCreator,
64                                                   LocDualContext::mLocationHalName)
65                   :context),
66    mOwner(owner), mInternalAdapter(new LocInternalAdapter(this)),
67    mUlp(new UlpProxyBase()), mNavigating(false),
68    mSupportsAgpsRequests(false),
69    mSupportsPositionInjection(false),
70    mSupportsTimeInjection(false),
71    mPowerVote(0)
72{
73    memset(&mFixCriteria, 0, sizeof(mFixCriteria));
74    mFixCriteria.mode = LOC_POSITION_MODE_INVALID;
75    LOC_LOGD("LocEngAdapter created");
76}
77
78inline
79LocEngAdapter::~LocEngAdapter()
80{
81    delete mInternalAdapter;
82    LOC_LOGV("LocEngAdapter deleted");
83}
84
85void LocInternalAdapter::setUlpProxy(UlpProxyBase* ulp) {
86    struct LocSetUlpProxy : public LocMsg {
87        LocAdapterBase* mAdapter;
88        UlpProxyBase* mUlp;
89        inline LocSetUlpProxy(LocAdapterBase* adapter, UlpProxyBase* ulp) :
90            LocMsg(), mAdapter(adapter), mUlp(ulp) {
91        }
92        virtual void proc() const {
93            LOC_LOGV("%s] ulp %p adapter %p", __func__,
94                     mUlp, mAdapter);
95            mAdapter->setUlpProxy(mUlp);
96        }
97    };
98
99    sendMsg(new LocSetUlpProxy(mLocEngAdapter, ulp));
100}
101
102void LocEngAdapter::setUlpProxy(UlpProxyBase* ulp)
103{
104    if (ulp == mUlp) {
105        //This takes care of the case when double initalization happens
106        //and we get the same object back for UlpProxyBase . Do nothing
107        return;
108    }
109
110    LOC_LOGV("%s] %p", __func__, ulp);
111    if (NULL == ulp) {
112        LOC_LOGE("%s:%d]: ulp pointer is NULL", __func__, __LINE__);
113        ulp = new UlpProxyBase();
114    }
115
116    if (LOC_POSITION_MODE_INVALID != mUlp->mPosMode.mode) {
117        // need to send this mode and start msg to ULP
118        ulp->sendFixMode(mUlp->mPosMode);
119    }
120
121    if(mUlp->mFixSet) {
122        ulp->sendStartFix();
123    }
124
125    delete mUlp;
126    mUlp = ulp;
127}
128
129int LocEngAdapter::setGpsLockMsg(LOC_GPS_LOCK_MASK lockMask)
130{
131    struct LocEngAdapterGpsLock : public LocMsg {
132        LocEngAdapter* mAdapter;
133        LOC_GPS_LOCK_MASK mLockMask;
134        inline LocEngAdapterGpsLock(LocEngAdapter* adapter, LOC_GPS_LOCK_MASK lockMask) :
135            LocMsg(), mAdapter(adapter), mLockMask(lockMask)
136        {
137            locallog();
138        }
139        inline virtual void proc() const {
140            mAdapter->setGpsLock(mLockMask);
141        }
142        inline  void locallog() const {
143            LOC_LOGV("LocEngAdapterGpsLock - mLockMask: %x", mLockMask);
144        }
145        inline virtual void log() const {
146            locallog();
147        }
148    };
149    sendMsg(new LocEngAdapterGpsLock(this, lockMask));
150    return 0;
151}
152
153void LocEngAdapter::requestPowerVote()
154{
155    if (getPowerVoteRight()) {
156        /* Power voting without engine lock:
157         * 101: vote down, 102-104 - vote up
158         * These codes are used not to confuse with actual engine lock
159         * functionality, that can't be used in SSR scenario, as it
160         * conflicts with initialization sequence.
161         */
162        bool powerUp = getPowerVote();
163        LOC_LOGV("LocEngAdapterVotePower - Vote Power: %d", (int)powerUp);
164        setGpsLock(powerUp ? 103 : 101);
165    }
166}
167
168void LocInternalAdapter::reportPosition(UlpLocation &location,
169                                        GpsLocationExtended &locationExtended,
170                                        void* locationExt,
171                                        enum loc_sess_status status,
172                                        LocPosTechMask loc_technology_mask)
173{
174    sendMsg(new LocEngReportPosition(mLocEngAdapter,
175                                     location,
176                                     locationExtended,
177                                     locationExt,
178                                     status,
179                                     loc_technology_mask));
180}
181
182
183void LocEngAdapter::reportPosition(UlpLocation &location,
184                                   GpsLocationExtended &locationExtended,
185                                   void* locationExt,
186                                   enum loc_sess_status status,
187                                   LocPosTechMask loc_technology_mask)
188{
189    if (! mUlp->reportPosition(location,
190                               locationExtended,
191                               locationExt,
192                               status,
193                               loc_technology_mask )) {
194        mInternalAdapter->reportPosition(location,
195                                         locationExtended,
196                                         locationExt,
197                                         status,
198                                         loc_technology_mask);
199    }
200}
201
202void LocInternalAdapter::reportSv(GpsSvStatus &svStatus,
203                                  GpsLocationExtended &locationExtended,
204                                  void* svExt){
205    sendMsg(new LocEngReportSv(mLocEngAdapter, svStatus,
206                               locationExtended, svExt));
207}
208
209void LocEngAdapter::reportSv(GpsSvStatus &svStatus,
210                             GpsLocationExtended &locationExtended,
211                             void* svExt)
212{
213
214    // We want to send SV info to ULP to help it in determining GNSS
215    // signal strength ULP will forward the SV reports to HAL without
216    // any modifications
217    if (! mUlp->reportSv(svStatus, locationExtended, svExt)) {
218        mInternalAdapter->reportSv(svStatus, locationExtended, svExt);
219    }
220}
221
222void LocEngAdapter::setInSession(bool inSession)
223{
224    mNavigating = inSession;
225    mLocApi->setInSession(inSession);
226    if (!mNavigating) {
227        mFixCriteria.mode = LOC_POSITION_MODE_INVALID;
228    }
229}
230
231void LocInternalAdapter::reportStatus(GpsStatusValue status)
232{
233    sendMsg(new LocEngReportStatus(mLocEngAdapter, status));
234}
235
236void LocEngAdapter::reportStatus(GpsStatusValue status)
237{
238    if (!mUlp->reportStatus(status)) {
239        mInternalAdapter->reportStatus(status);
240    }
241}
242
243inline
244void LocEngAdapter::reportNmea(const char* nmea, int length)
245{
246    sendMsg(new LocEngReportNmea(mOwner, nmea, length));
247}
248
249inline
250bool LocEngAdapter::reportXtraServer(const char* url1,
251                                        const char* url2,
252                                        const char* url3,
253                                        const int maxlength)
254{
255    if (mSupportsAgpsRequests) {
256        sendMsg(new LocEngReportXtraServer(mOwner, url1,
257                                           url2, url3, maxlength));
258    }
259    return mSupportsAgpsRequests;
260}
261
262inline
263bool LocEngAdapter::requestATL(int connHandle, AGpsType agps_type)
264{
265    if (mSupportsAgpsRequests) {
266        sendMsg(new LocEngRequestATL(mOwner,
267                                     connHandle, agps_type));
268    }
269    return mSupportsAgpsRequests;
270}
271
272inline
273bool LocEngAdapter::releaseATL(int connHandle)
274{
275    if (mSupportsAgpsRequests) {
276        sendMsg(new LocEngReleaseATL(mOwner, connHandle));
277    }
278    return mSupportsAgpsRequests;
279}
280
281inline
282bool LocEngAdapter::requestXtraData()
283{
284    if (mSupportsAgpsRequests) {
285        sendMsg(new LocEngRequestXtra(mOwner));
286    }
287    return mSupportsAgpsRequests;
288}
289
290inline
291bool LocEngAdapter::requestTime()
292{
293    if (mSupportsAgpsRequests) {
294        sendMsg(new LocEngRequestTime(mOwner));
295    }
296    return mSupportsAgpsRequests;
297}
298
299inline
300bool LocEngAdapter::requestNiNotify(GpsNiNotification &notif, const void* data)
301{
302    if (mSupportsAgpsRequests) {
303        notif.size = sizeof(notif);
304        notif.timeout = LOC_NI_NO_RESPONSE_TIME;
305
306        sendMsg(new LocEngRequestNi(mOwner, notif, data));
307    }
308    return mSupportsAgpsRequests;
309}
310
311inline
312bool LocEngAdapter::requestSuplES(int connHandle)
313{
314    if (mSupportsAgpsRequests)
315        sendMsg(new LocEngRequestSuplEs(mOwner, connHandle));
316    return mSupportsAgpsRequests;
317}
318
319inline
320bool LocEngAdapter::reportDataCallOpened()
321{
322    if(mSupportsAgpsRequests)
323        sendMsg(new LocEngSuplEsOpened(mOwner));
324    return mSupportsAgpsRequests;
325}
326
327inline
328bool LocEngAdapter::reportDataCallClosed()
329{
330    if(mSupportsAgpsRequests)
331        sendMsg(new LocEngSuplEsClosed(mOwner));
332    return mSupportsAgpsRequests;
333}
334
335inline
336void LocEngAdapter::handleEngineDownEvent()
337{
338    sendMsg(new LocEngDown(mOwner));
339}
340
341inline
342void LocEngAdapter::handleEngineUpEvent()
343{
344    sendMsg(new LocEngUp(mOwner));
345}
346
347enum loc_api_adapter_err LocEngAdapter::setTime(GpsUtcTime time,
348                                                int64_t timeReference,
349                                                int uncertainty)
350{
351    loc_api_adapter_err result = LOC_API_ADAPTER_ERR_SUCCESS;
352
353    LOC_LOGD("%s:%d]: mSupportsTimeInjection is %d",
354             __func__, __LINE__, mSupportsTimeInjection);
355
356    if (mSupportsTimeInjection) {
357        LOC_LOGD("%s:%d]: Injecting time", __func__, __LINE__);
358        result = mLocApi->setTime(time, timeReference, uncertainty);
359    } else {
360        mSupportsTimeInjection = true;
361    }
362    return result;
363}
364
365enum loc_api_adapter_err LocEngAdapter::setXtraVersionCheck(int check)
366{
367    enum loc_api_adapter_err ret;
368    ENTRY_LOG();
369    enum xtra_version_check eCheck;
370    switch (check) {
371    case 0:
372        eCheck = DISABLED;
373        break;
374    case 1:
375        eCheck = AUTO;
376        break;
377    case 2:
378        eCheck = XTRA2;
379        break;
380    case 3:
381        eCheck = XTRA3;
382        break;
383    default:
384        eCheck = DISABLED;
385    }
386    ret = mLocApi->setXtraVersionCheck(eCheck);
387    EXIT_LOG(%d, ret);
388    return ret;
389}
390
391void LocEngAdapter::reportGpsMeasurementData(GpsData &gpsMeasurementData)
392{
393    sendMsg(new LocEngReportGpsMeasurement(mOwner,
394                                           gpsMeasurementData));
395}
396
397/*
398  Update Registration Mask
399 */
400void LocEngAdapter::updateRegistrationMask(LOC_API_ADAPTER_EVENT_MASK_T event,
401                                           loc_registration_mask_status isEnabled)
402{
403    LOC_LOGD("entering %s", __func__);
404    int result = LOC_API_ADAPTER_ERR_FAILURE;
405    result = mLocApi->updateRegistrationMask(event, isEnabled);
406    if (result == LOC_API_ADAPTER_ERR_SUCCESS) {
407        LOC_LOGD("%s] update registration mask succeed.", __func__);
408    } else {
409        LOC_LOGE("%s] update registration mask failed.", __func__);
410    }
411}
412
413/*
414  Set Gnss Constellation Config
415 */
416bool LocEngAdapter::gnssConstellationConfig()
417{
418    LOC_LOGD("entering %s", __func__);
419    bool result = false;
420    result = mLocApi->gnssConstellationConfig();
421    return result;
422}
423