1/* Copyright (c) 2011-2015, 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 <sys/stat.h>
33#include <errno.h>
34#include <ctype.h>
35#include <cutils/properties.h>
36#include <LocEngAdapter.h>
37#include "loc_eng_msg.h"
38#include "loc_log.h"
39
40#define CHIPSET_SERIAL_NUMBER_MAX_LEN 16
41#define USER_AGENT_MAX_LEN 512
42
43using namespace loc_core;
44
45LocInternalAdapter::LocInternalAdapter(LocEngAdapter* adapter) :
46    LocAdapterBase(adapter->getMsgTask()),
47    mLocEngAdapter(adapter)
48{
49}
50void LocInternalAdapter::setPositionModeInt(LocPosMode& posMode) {
51    sendMsg(new LocEngPositionMode(mLocEngAdapter, posMode));
52}
53void LocInternalAdapter::startFixInt() {
54    sendMsg(new LocEngStartFix(mLocEngAdapter));
55}
56void LocInternalAdapter::stopFixInt() {
57    sendMsg(new LocEngStopFix(mLocEngAdapter));
58}
59void LocInternalAdapter::getZppInt() {
60    sendMsg(new LocEngGetZpp(mLocEngAdapter));
61}
62
63LocEngAdapter::LocEngAdapter(LOC_API_ADAPTER_EVENT_MASK_T mask,
64                             void* owner, ContextBase* context,
65                             LocThread::tCreate tCreator) :
66    LocAdapterBase(mask,
67                   //Get the AFW context if VzW context has not already been intialized in
68                   //loc_ext
69                   context == NULL?
70                   LocDualContext::getLocFgContext(tCreator,
71                                                   NULL,
72                                                   LocDualContext::mLocationHalName,
73                                                   false)
74                   :context),
75    mOwner(owner), mInternalAdapter(new LocInternalAdapter(this)),
76    mUlp(new UlpProxyBase()), mNavigating(false),
77    mSupportsAgpsRequests(false),
78    mSupportsPositionInjection(false),
79    mSupportsTimeInjection(false),
80    mPowerVote(0)
81{
82    memset(&mFixCriteria, 0, sizeof(mFixCriteria));
83    mFixCriteria.mode = LOC_POSITION_MODE_INVALID;
84    LOC_LOGD("LocEngAdapter created");
85}
86
87inline
88LocEngAdapter::~LocEngAdapter()
89{
90    delete mInternalAdapter;
91    LOC_LOGV("LocEngAdapter deleted");
92}
93
94void LocEngAdapter::setXtraUserAgent() {
95    struct LocSetXtraUserAgent : public LocMsg {
96        const ContextBase* const mContext;
97        inline LocSetXtraUserAgent(ContextBase* context) :
98            LocMsg(), mContext(context) {
99        }
100        virtual void proc() const {
101            char release[PROPERTY_VALUE_MAX];
102            char manufacture[PROPERTY_VALUE_MAX];
103            char model[PROPERTY_VALUE_MAX];
104            char board[PROPERTY_VALUE_MAX];
105            char brand[PROPERTY_VALUE_MAX];
106            char chipsetsn[CHIPSET_SERIAL_NUMBER_MAX_LEN];
107            char userAgent[USER_AGENT_MAX_LEN];
108            const char defVal[] = "-";
109
110            property_get("ro.build.version.release", release,     defVal);
111            property_get("ro.product.manufacturer",  manufacture, defVal);
112            property_get("ro.product.model", model,   defVal);
113            property_get("ro.product.board", board,   defVal);
114            property_get("ro.product.brand", brand,   defVal);
115            getChipsetSerialNo(chipsetsn, sizeof(chipsetsn), defVal);
116
117            encodeInPlace(release, PROPERTY_VALUE_MAX);
118            encodeInPlace(manufacture, PROPERTY_VALUE_MAX);
119            encodeInPlace(model, PROPERTY_VALUE_MAX);
120            encodeInPlace(board, PROPERTY_VALUE_MAX);
121            encodeInPlace(brand, PROPERTY_VALUE_MAX);
122
123            snprintf(userAgent, sizeof(userAgent), "A/%s/%s/%s/%s/-/QCX3/s%u/-/%s/-/%s/-/-/-",
124                     release, manufacture, model, board,
125                     mContext->getIzatDevId(), chipsetsn, brand);
126
127            for (int i = 0; i < sizeof(userAgent) && userAgent[i]; i++) {
128                if (' ' == userAgent[i]) userAgent[i] = '#';
129            }
130
131            saveUserAgentString(userAgent, strlen(userAgent));
132            LOC_LOGV("%s] UserAgent %s", __func__, userAgent);
133        }
134
135        void saveUserAgentString(const char* data, const int len) const {
136            const char XTRA_FOLDER[] = "/data/misc/location/xtra";
137            const char USER_AGENT_FILE[] = "/data/misc/location/xtra/useragent.txt";
138
139            if (data == NULL || len < 1) {
140                LOC_LOGE("%s:%d]: invalid input data = %p len = %d", __func__, __LINE__, data, len);
141                return;
142            }
143
144            struct stat s;
145            int err = stat(XTRA_FOLDER, &s);
146            if (err < 0) {
147                if (ENOENT == errno) {
148                    if (mkdir(XTRA_FOLDER, 0700) < 0) {
149                        LOC_LOGE("%s:%d]: make XTRA_FOLDER failed", __func__, __LINE__);
150                        return;
151                    }
152                } else {
153                    LOC_LOGE("%s:%d]: XTRA_FOLDER invalid", __func__, __LINE__);
154                    return;
155                }
156            }
157
158            FILE* file = fopen(USER_AGENT_FILE, "wt");
159            if (file == NULL) {
160                LOC_LOGE("%s:%d]: open USER_AGENT_FILE failed", __func__, __LINE__);
161                return;
162            }
163
164            size_t written = fwrite(data, 1, len, file);
165            fclose(file);
166            file = NULL;
167
168            // set file permission
169            chmod(USER_AGENT_FILE, 0600);
170
171            if (written != len) {
172                LOC_LOGE("%s:%d]: write USER_AGENT_FILE failed", __func__, __LINE__);
173            }
174        }
175
176        void getChipsetSerialNo(char buf[], int buflen, const char def[]) const {
177            const char SOC_SERIAL_NUMBER[] = "/sys/devices/soc0/serial_number";
178
179            FILE* file = fopen(SOC_SERIAL_NUMBER, "rt");
180            if (file == NULL) {
181                // use default upon unreadable file
182                strlcpy(buf, def, buflen);
183
184            } else {
185                size_t size = fread(buf, 1, buflen - 1, file);
186                if (size == 0) {
187                   // use default upon empty file
188                   strlcpy(buf, def, buflen);
189
190                } else {
191                   buf[size] = '\0';
192                }
193
194                fclose(file);
195
196                // remove trailing spaces
197                size_t len = strlen(buf);
198                while (--len >= 0 && isspace(buf[len])) {
199                    buf[len] = '\0';
200                }
201            }
202
203            return;
204        }
205
206        /**
207         *  encode the given string value such that all separator characters ('/','+','|','%')
208         *  in the string are repaced by their corresponding encodings (%2F","%2B","%7C", "%25")
209         */
210        static void encodeInPlace(char value[], const int size) {
211            char buffer[size];
212
213            struct ENCODE {
214                const char ch;
215                const char *code;
216            };
217
218            const ENCODE encodings[] = { {'/', "%2F"}, {'+', "%2B"}, {'|', "%7C",}, {'%', "%25"} };
219            const int nencodings = (int)sizeof(encodings) / sizeof(encodings[0]);
220
221            int inpos = 0, outpos = 0;
222            while(value[inpos] != '\0' && outpos < size - 1) {
223                // check if escaped character
224                int escchar = 0;
225                while(escchar < nencodings && encodings[escchar].ch != value[inpos]) {
226                    escchar++;
227                }
228
229                if (escchar == nencodings) {
230                    // non escaped character
231                    buffer[outpos++] = value[inpos++];
232                    continue;
233                }
234
235                // escaped character
236                int codepos = 0;
237                #define NUM_CHARS_IN_CODE 3
238
239                if (outpos + NUM_CHARS_IN_CODE >= size) {
240                    // skip last character if there is insufficient space
241                    break;
242                }
243
244                while(outpos < size - 1 && codepos < NUM_CHARS_IN_CODE) {
245                    buffer[outpos++] = encodings[escchar].code[codepos++];
246                }
247                inpos++;
248            }
249
250            // copy to ouput
251            value[outpos] = '\0';
252            while(--outpos >= 0) {
253                value[outpos] = buffer[outpos];
254            }
255        }
256    };
257
258    sendMsg(new LocSetXtraUserAgent(mContext));
259}
260
261void LocInternalAdapter::setUlpProxy(UlpProxyBase* ulp) {
262    struct LocSetUlpProxy : public LocMsg {
263        LocAdapterBase* mAdapter;
264        UlpProxyBase* mUlp;
265        inline LocSetUlpProxy(LocAdapterBase* adapter, UlpProxyBase* ulp) :
266            LocMsg(), mAdapter(adapter), mUlp(ulp) {
267        }
268        virtual void proc() const {
269            LOC_LOGV("%s] ulp %p adapter %p", __func__,
270                     mUlp, mAdapter);
271            mAdapter->setUlpProxy(mUlp);
272        }
273    };
274
275    sendMsg(new LocSetUlpProxy(mLocEngAdapter, ulp));
276}
277
278void LocEngAdapter::setUlpProxy(UlpProxyBase* ulp)
279{
280    if (ulp == mUlp) {
281        //This takes care of the case when double initalization happens
282        //and we get the same object back for UlpProxyBase . Do nothing
283        return;
284    }
285
286    LOC_LOGV("%s] %p", __func__, ulp);
287    if (NULL == ulp) {
288        LOC_LOGE("%s:%d]: ulp pointer is NULL", __func__, __LINE__);
289        ulp = new UlpProxyBase();
290    }
291
292    if (LOC_POSITION_MODE_INVALID != mUlp->mPosMode.mode) {
293        // need to send this mode and start msg to ULP
294        ulp->sendFixMode(mUlp->mPosMode);
295    }
296
297    if(mUlp->mFixSet) {
298        ulp->sendStartFix();
299    }
300
301    delete mUlp;
302    mUlp = ulp;
303}
304
305int LocEngAdapter::setGpsLockMsg(LOC_GPS_LOCK_MASK lockMask)
306{
307    struct LocEngAdapterGpsLock : public LocMsg {
308        LocEngAdapter* mAdapter;
309        LOC_GPS_LOCK_MASK mLockMask;
310        inline LocEngAdapterGpsLock(LocEngAdapter* adapter, LOC_GPS_LOCK_MASK lockMask) :
311            LocMsg(), mAdapter(adapter), mLockMask(lockMask)
312        {
313            locallog();
314        }
315        inline virtual void proc() const {
316            mAdapter->setGpsLock(mLockMask);
317        }
318        inline  void locallog() const {
319            LOC_LOGV("LocEngAdapterGpsLock - mLockMask: %x", mLockMask);
320        }
321        inline virtual void log() const {
322            locallog();
323        }
324    };
325    sendMsg(new LocEngAdapterGpsLock(this, lockMask));
326    return 0;
327}
328
329void LocEngAdapter::requestPowerVote()
330{
331    if (getPowerVoteRight()) {
332        /* Power voting without engine lock:
333         * 101: vote down, 102-104 - vote up
334         * These codes are used not to confuse with actual engine lock
335         * functionality, that can't be used in SSR scenario, as it
336         * conflicts with initialization sequence.
337         */
338        bool powerUp = getPowerVote();
339        LOC_LOGV("LocEngAdapterVotePower - Vote Power: %d", (int)powerUp);
340        setGpsLock(powerUp ? 103 : 101);
341    }
342}
343
344void LocInternalAdapter::reportPosition(UlpLocation &location,
345                                        GpsLocationExtended &locationExtended,
346                                        void* locationExt,
347                                        enum loc_sess_status status,
348                                        LocPosTechMask loc_technology_mask)
349{
350    sendMsg(new LocEngReportPosition(mLocEngAdapter,
351                                     location,
352                                     locationExtended,
353                                     locationExt,
354                                     status,
355                                     loc_technology_mask));
356}
357
358
359void LocEngAdapter::reportPosition(UlpLocation &location,
360                                   GpsLocationExtended &locationExtended,
361                                   void* locationExt,
362                                   enum loc_sess_status status,
363                                   LocPosTechMask loc_technology_mask)
364{
365    if (! mUlp->reportPosition(location,
366                               locationExtended,
367                               locationExt,
368                               status,
369                               loc_technology_mask )) {
370        mInternalAdapter->reportPosition(location,
371                                         locationExtended,
372                                         locationExt,
373                                         status,
374                                         loc_technology_mask);
375    }
376}
377
378void LocInternalAdapter::reportSv(QtiGnssSvStatus &svStatus,
379                                  GpsLocationExtended &locationExtended,
380                                  void* svExt){
381    sendMsg(new LocEngReportSv(mLocEngAdapter, svStatus,
382                               locationExtended, svExt));
383}
384
385void LocEngAdapter::reportSv(QtiGnssSvStatus &svStatus,
386                             GpsLocationExtended &locationExtended,
387                             void* svExt)
388{
389
390    // We want to send SV info to ULP to help it in determining GNSS
391    // signal strength ULP will forward the SV reports to HAL without
392    // any modifications
393    if (! mUlp->reportSv(svStatus, locationExtended, svExt)) {
394        mInternalAdapter->reportSv(svStatus, locationExtended, svExt);
395    }
396}
397
398void LocEngAdapter::setInSession(bool inSession)
399{
400    mNavigating = inSession;
401    mLocApi->setInSession(inSession);
402    if (!mNavigating) {
403        mFixCriteria.mode = LOC_POSITION_MODE_INVALID;
404    }
405}
406
407void LocInternalAdapter::reportStatus(GpsStatusValue status)
408{
409    sendMsg(new LocEngReportStatus(mLocEngAdapter, status));
410}
411
412void LocEngAdapter::reportStatus(GpsStatusValue status)
413{
414    if (!mUlp->reportStatus(status)) {
415        mInternalAdapter->reportStatus(status);
416    }
417}
418
419inline
420void LocEngAdapter::reportNmea(const char* nmea, int length)
421{
422    sendMsg(new LocEngReportNmea(mOwner, nmea, length));
423}
424
425inline
426bool LocEngAdapter::reportXtraServer(const char* url1,
427                                        const char* url2,
428                                        const char* url3,
429                                        const int maxlength)
430{
431    if (mSupportsAgpsRequests) {
432        sendMsg(new LocEngReportXtraServer(mOwner, url1,
433                                           url2, url3, maxlength));
434    }
435    return mSupportsAgpsRequests;
436}
437
438inline
439bool LocEngAdapter::requestATL(int connHandle, AGpsType agps_type)
440{
441    if (mSupportsAgpsRequests) {
442        sendMsg(new LocEngRequestATL(mOwner,
443                                     connHandle, agps_type));
444    }
445    return mSupportsAgpsRequests;
446}
447
448inline
449bool LocEngAdapter::releaseATL(int connHandle)
450{
451    if (mSupportsAgpsRequests) {
452        sendMsg(new LocEngReleaseATL(mOwner, connHandle));
453    }
454    return mSupportsAgpsRequests;
455}
456
457inline
458bool LocEngAdapter::requestXtraData()
459{
460    if (mSupportsAgpsRequests) {
461        sendMsg(new LocEngRequestXtra(mOwner));
462    }
463    return mSupportsAgpsRequests;
464}
465
466inline
467bool LocEngAdapter::requestTime()
468{
469    if (mSupportsAgpsRequests) {
470        sendMsg(new LocEngRequestTime(mOwner));
471    }
472    return mSupportsAgpsRequests;
473}
474
475inline
476bool LocEngAdapter::requestNiNotify(GpsNiNotification &notif, const void* data)
477{
478    if (mSupportsAgpsRequests) {
479        notif.size = sizeof(notif);
480        notif.timeout = LOC_NI_NO_RESPONSE_TIME;
481
482        sendMsg(new LocEngRequestNi(mOwner, notif, data));
483    }
484    return mSupportsAgpsRequests;
485}
486
487inline
488bool LocEngAdapter::requestSuplES(int connHandle)
489{
490    if (mSupportsAgpsRequests)
491        sendMsg(new LocEngRequestSuplEs(mOwner, connHandle));
492    return mSupportsAgpsRequests;
493}
494
495inline
496bool LocEngAdapter::reportDataCallOpened()
497{
498    if(mSupportsAgpsRequests)
499        sendMsg(new LocEngSuplEsOpened(mOwner));
500    return mSupportsAgpsRequests;
501}
502
503inline
504bool LocEngAdapter::reportDataCallClosed()
505{
506    if(mSupportsAgpsRequests)
507        sendMsg(new LocEngSuplEsClosed(mOwner));
508    return mSupportsAgpsRequests;
509}
510
511inline
512void LocEngAdapter::handleEngineDownEvent()
513{
514    sendMsg(new LocEngDown(mOwner));
515}
516
517inline
518void LocEngAdapter::handleEngineUpEvent()
519{
520    sendMsg(new LocEngUp(mOwner));
521}
522
523enum loc_api_adapter_err LocEngAdapter::setTime(GpsUtcTime time,
524                                                int64_t timeReference,
525                                                int uncertainty)
526{
527    loc_api_adapter_err result = LOC_API_ADAPTER_ERR_SUCCESS;
528
529    LOC_LOGD("%s:%d]: mSupportsTimeInjection is %d",
530             __func__, __LINE__, mSupportsTimeInjection);
531
532    if (mSupportsTimeInjection) {
533        LOC_LOGD("%s:%d]: Injecting time", __func__, __LINE__);
534        result = mLocApi->setTime(time, timeReference, uncertainty);
535    } else {
536        mSupportsTimeInjection = true;
537    }
538    return result;
539}
540
541enum loc_api_adapter_err LocEngAdapter::setXtraVersionCheck(int check)
542{
543    enum loc_api_adapter_err ret;
544    ENTRY_LOG();
545    enum xtra_version_check eCheck;
546    switch (check) {
547    case 0:
548        eCheck = DISABLED;
549        break;
550    case 1:
551        eCheck = AUTO;
552        break;
553    case 2:
554        eCheck = XTRA2;
555        break;
556    case 3:
557        eCheck = XTRA3;
558        break;
559    default:
560        eCheck = DISABLED;
561    }
562    ret = mLocApi->setXtraVersionCheck(eCheck);
563    EXIT_LOG(%d, ret);
564    return ret;
565}
566
567void LocEngAdapter::reportGpsMeasurementData(GpsData &gpsMeasurementData)
568{
569    sendMsg(new LocEngReportGpsMeasurement(mOwner,
570                                           gpsMeasurementData));
571}
572
573/*
574  Update Registration Mask
575 */
576void LocEngAdapter::updateRegistrationMask(LOC_API_ADAPTER_EVENT_MASK_T event,
577                                           loc_registration_mask_status isEnabled)
578{
579    LOC_LOGD("entering %s", __func__);
580    int result = LOC_API_ADAPTER_ERR_FAILURE;
581    result = mLocApi->updateRegistrationMask(event, isEnabled);
582    if (result == LOC_API_ADAPTER_ERR_SUCCESS) {
583        LOC_LOGD("%s] update registration mask succeed.", __func__);
584    } else {
585        LOC_LOGE("%s] update registration mask failed.", __func__);
586    }
587}
588
589/*
590  Set Gnss Constellation Config
591 */
592bool LocEngAdapter::gnssConstellationConfig()
593{
594    LOC_LOGD("entering %s", __func__);
595    bool result = false;
596    result = mLocApi->gnssConstellationConfig();
597    return result;
598}
599