793 lines
26 KiB
C++
793 lines
26 KiB
C++
/* Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above
|
|
* copyright notice, this list of conditions and the following
|
|
* disclaimer in the documentation and/or other materials provided
|
|
* with the distribution.
|
|
* * Neither the name of The Linux Foundation nor the names of its
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
|
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
|
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#define LOG_TAG "LocSvc_LocationQapi"
|
|
|
|
#include <loc_pla.h>
|
|
#include "log_util.h"
|
|
#include "loc_cfg.h"
|
|
#include "LocationClientApi.h"
|
|
#include "qapi_location.h"
|
|
#include <pthread.h>
|
|
#include <vector>
|
|
#include <string.h>
|
|
#include <LocTimer.h>
|
|
|
|
using namespace std;
|
|
using namespace loc_util;
|
|
using namespace location_client;
|
|
using Runnable = std::function<void()>;
|
|
|
|
class QapiTimer : public LocTimer {
|
|
public:
|
|
QapiTimer() : LocTimer(), mStarted(false) {}
|
|
inline ~QapiTimer() { stop(); }
|
|
inline void set(const time_t waitTimeMs, const Runnable& runable) {
|
|
mWaitTimeInMs = waitTimeMs;
|
|
mRunnable = runable;
|
|
}
|
|
inline void start() {
|
|
mStarted = true;
|
|
LocTimer::start(mWaitTimeInMs, false);
|
|
}
|
|
inline void start(const time_t waitTimeSec) {
|
|
mWaitTimeInMs = waitTimeSec * 1000;
|
|
start();
|
|
}
|
|
inline void stop() {
|
|
if (mStarted) {
|
|
LocTimer::stop();
|
|
mStarted = false;
|
|
}
|
|
}
|
|
inline void restart() { stop(); start(); }
|
|
inline void restart(const time_t waitTimeSec) { stop(); start(waitTimeSec); }
|
|
inline bool isStarted() { return mStarted; }
|
|
|
|
private:
|
|
// Override
|
|
inline virtual void timeOutCallback() override {
|
|
mStarted = false;
|
|
mRunnable();
|
|
}
|
|
|
|
private:
|
|
time_t mWaitTimeInMs;
|
|
Runnable mRunnable;
|
|
bool mStarted;
|
|
|
|
};
|
|
|
|
static pthread_mutex_t qMutex;
|
|
static bool qMutexInitDone = false;
|
|
static LocationClientApi* pLocClientApi = nullptr;
|
|
static LocationClientApi* pLocPassiveClientApi = nullptr;
|
|
static QapiTimer mTimer;
|
|
qapi_Location_Callbacks_t qLocationCallbacks;
|
|
static qapi_Location_t qCacheLocation;
|
|
static QapiTimer mPassiveTimer;
|
|
|
|
static qapi_Location_Error_t get_qapi_error(LocationResponse err)
|
|
{
|
|
switch (err)
|
|
{
|
|
case LOCATION_RESPONSE_SUCCESS: return QAPI_LOCATION_ERROR_SUCCESS;
|
|
case LOCATION_RESPONSE_UNKOWN_FAILURE: return QAPI_LOCATION_ERROR_GENERAL_FAILURE;
|
|
case LOCATION_RESPONSE_NOT_SUPPORTED: return QAPI_LOCATION_ERROR_NOT_SUPPORTED;
|
|
default: return QAPI_LOCATION_ERROR_GENERAL_FAILURE;
|
|
}
|
|
}
|
|
|
|
static int32_t copy_to_user_space_buffer(
|
|
uint8_t* user_space_buffer,
|
|
uint32_t user_space_buffer_size,
|
|
uint8_t* data_ptr,
|
|
uint32_t data_size,
|
|
uint32_t offset) {
|
|
|
|
if (offset >= user_space_buffer_size) {
|
|
LOC_LOGe("Invalid offset %d, buffer size %d",
|
|
offset, user_space_buffer_size);
|
|
return -1;
|
|
}
|
|
|
|
memcpy((user_space_buffer + offset), data_ptr, data_size);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void print_qLocation_array(qapi_Location_t* qLocationArray, uint32_t length) {
|
|
|
|
for (uint32_t i = 0; i < length; i++) {
|
|
LOC_LOGv("LAT: %d.%d LON: %d.%d ALT: %d.%d ALT_MSL: %d.%d",
|
|
(int)qLocationArray[i].latitude,
|
|
(abs((int)(qLocationArray[i].latitude * 100000))) % 100000,
|
|
(int)qLocationArray[i].longitude,
|
|
(abs((int)(qLocationArray[i].longitude * 100000))) % 100000,
|
|
(int)qLocationArray[i].altitude,
|
|
(abs((int)(qLocationArray[i].altitude * 100))) % 100,
|
|
(int)qLocationArray[i].altitudeMeanSeaLevel,
|
|
(abs((int)(qLocationArray[i].altitudeMeanSeaLevel * 100))) % 100);
|
|
|
|
LOC_LOGv("SPEED: %d.%d BEAR: %d.%d TIME: 0x%x%x FLAGS: %u",
|
|
(int)qLocationArray[i].speed,
|
|
(abs((int)(qLocationArray[i].speed * 100))) % 100,
|
|
(int)qLocationArray[i].bearing,
|
|
(abs((int)(qLocationArray[i].bearing * 100))) % 100,
|
|
(int)(qLocationArray[i].timestamp >> 32),
|
|
(int)qLocationArray[i].timestamp, qLocationArray[i].flags);
|
|
|
|
LOC_LOGv("ACC: %d.%d VERT_ACC: %d.%d SPEED_ACC: %d.%d BEAR_ACC: %d.%d",
|
|
(int)qLocationArray[i].accuracy,
|
|
(abs((int)(qLocationArray[i].accuracy * 100))) % 100,
|
|
(int)qLocationArray[i].verticalAccuracy,
|
|
(abs((int)(qLocationArray[i].verticalAccuracy * 100))) % 100,
|
|
(int)qLocationArray[i].speedAccuracy,
|
|
(abs((int)(qLocationArray[i].speedAccuracy * 100))) % 100,
|
|
(int)qLocationArray[i].bearingAccuracy,
|
|
(abs((int)(qLocationArray[i].bearingAccuracy * 100))) % 100);
|
|
}
|
|
}
|
|
|
|
static void print_qGnssData(qapi_Gnss_Data_t* qGnssData) {
|
|
|
|
LOC_LOGv("JAMMER_GPS: %u JAMMER_GLONASS: %u",
|
|
qGnssData->jammerInd[QAPI_GNSS_SV_TYPE_GPS],
|
|
qGnssData->jammerInd[QAPI_GNSS_SV_TYPE_GLONASS]);
|
|
|
|
LOC_LOGv("JAMMER_BEIDOU: %u JAMMER_GALILEO: %u",
|
|
qGnssData->jammerInd[QAPI_GNSS_SV_TYPE_BEIDOU],
|
|
qGnssData->jammerInd[QAPI_GNSS_SV_TYPE_GALILEO]);
|
|
}
|
|
|
|
static void location_capabilities_callback(
|
|
LocationCapabilitiesMask capsMask)
|
|
{
|
|
LOC_LOGv("location_capabilities_callback!");
|
|
|
|
qLocationCallbacks.capabilitiesCb(
|
|
(qapi_Location_Capabilities_Mask_t)capsMask);
|
|
}
|
|
|
|
static void location_response_callback(
|
|
LocationResponse err)
|
|
{
|
|
qapi_Location_Error_t qErr;
|
|
|
|
qErr = get_qapi_error(err);
|
|
LOC_LOGv("location_response_callback!");
|
|
|
|
// hard-code id to 0 for now
|
|
uint32_t id = 0;
|
|
qLocationCallbacks.responseCb(qErr, id);
|
|
}
|
|
|
|
static void location_collective_response_callback(
|
|
vector<std::pair<Geofence, LocationResponse>>& responses)
|
|
{
|
|
qapi_Location_Error_t* qLocationErrorArray = NULL;
|
|
|
|
// hard-coded
|
|
qLocationErrorArray = new qapi_Location_Error_t[5];
|
|
uint32_t* ids = new uint32_t[5];
|
|
|
|
for (int i = 0; i < 5; i++) {
|
|
qLocationErrorArray[i] = QAPI_LOCATION_ERROR_SUCCESS;
|
|
}
|
|
|
|
LOC_LOGd("Invoking Collective Response Cb");
|
|
qLocationCallbacks.collectiveResponseCb(
|
|
5, qLocationErrorArray, ids);
|
|
|
|
delete[] qLocationErrorArray;
|
|
delete[] ids;
|
|
}
|
|
|
|
static void location_tracking_callback(
|
|
Location location)
|
|
{
|
|
qapi_Location_t qLocation = {};
|
|
bool bIsSingleShot = false;
|
|
|
|
// first check if location is valid
|
|
if (0 == location.flags) {
|
|
LOC_LOGd("Ignore invalid location");
|
|
return;
|
|
}
|
|
|
|
if (mTimer.isStarted()) {
|
|
LOC_LOGd("Timer was started, meaning this is singleshot");
|
|
if (nullptr != pLocClientApi) {
|
|
LOC_LOGd("Stop singleshot session");
|
|
pLocClientApi->stopPositionSession();
|
|
}
|
|
LOC_LOGd("Stop singleshot timer");
|
|
mTimer.stop();
|
|
bIsSingleShot = true;
|
|
}
|
|
qLocation.size = sizeof(qapi_Location_t);
|
|
qLocation.timestamp = location.timestamp;
|
|
qLocation.latitude = location.latitude;
|
|
qLocation.longitude = location.longitude;
|
|
qLocation.altitude = location.altitude;
|
|
// TODO
|
|
// qLocation.altitudeMeanSeaLevel = location.altitudeMeanSeaLevel;
|
|
qLocation.speed = location.speed;
|
|
qLocation.bearing = location.bearing;
|
|
qLocation.accuracy = location.horizontalAccuracy;
|
|
qLocation.flags = location.flags;
|
|
qLocation.flags &= ~QAPI_LOCATION_HAS_ALTITUDE_MSL_BIT;
|
|
qLocation.verticalAccuracy = location.verticalAccuracy;
|
|
qLocation.speedAccuracy = location.speedAccuracy;
|
|
qLocation.bearingAccuracy = location.bearingAccuracy;
|
|
|
|
print_qLocation_array(&qLocation, 1);
|
|
if (bIsSingleShot) {
|
|
LOC_LOGd("Invoking Singleshot Callback");
|
|
if (qLocationCallbacks.singleShotCb) {
|
|
qLocationCallbacks.singleShotCb(qLocation, QAPI_LOCATION_ERROR_SUCCESS);
|
|
} else {
|
|
LOC_LOGe("No singleshot cb registered");
|
|
}
|
|
} else {
|
|
LOC_LOGd("Invoking Tracking Callback");
|
|
if (qLocationCallbacks.trackingCb) {
|
|
qLocationCallbacks.trackingCb(qLocation);
|
|
}
|
|
else {
|
|
LOC_LOGe("No tracking cb registered");
|
|
}
|
|
}
|
|
}
|
|
|
|
static void gnss_location_tracking_callback(
|
|
GnssLocation gnsslocation)
|
|
{
|
|
qapi_Location_t qLocation = {};
|
|
bool bIsSingleShot = false;
|
|
|
|
// first check if location is valid
|
|
if (0 == gnsslocation.flags) {
|
|
LOC_LOGd("Ignore invalid location");
|
|
return;
|
|
}
|
|
|
|
if (mTimer.isStarted()) {
|
|
LOC_LOGd("Timer was started, meaning this is singleshot");
|
|
if (nullptr != pLocClientApi) {
|
|
LOC_LOGd("Stop singleshot session");
|
|
pLocClientApi->stopPositionSession();
|
|
}
|
|
LOC_LOGd("Stop singleshot timer");
|
|
mTimer.stop();
|
|
bIsSingleShot = true;
|
|
}
|
|
qLocation.size = sizeof(qapi_Location_t);
|
|
qLocation.timestamp = gnsslocation.timestamp;
|
|
qLocation.latitude = gnsslocation.latitude;
|
|
qLocation.longitude = gnsslocation.longitude;
|
|
qLocation.altitude = gnsslocation.altitude;
|
|
qLocation.altitudeMeanSeaLevel = gnsslocation.altitudeMeanSeaLevel;
|
|
qLocation.speed = gnsslocation.speed;
|
|
qLocation.bearing = gnsslocation.bearing;
|
|
qLocation.accuracy = gnsslocation.horizontalAccuracy;
|
|
qLocation.flags = gnsslocation.flags;
|
|
if (gnsslocation.gnssInfoFlags & GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT) {
|
|
qLocation.flags |= QAPI_LOCATION_HAS_ALTITUDE_MSL_BIT;
|
|
}
|
|
qLocation.verticalAccuracy = gnsslocation.verticalAccuracy;
|
|
qLocation.speedAccuracy = gnsslocation.speedAccuracy;
|
|
qLocation.bearingAccuracy = gnsslocation.bearingAccuracy;
|
|
|
|
print_qLocation_array(&qLocation, 1);
|
|
if (bIsSingleShot) {
|
|
LOC_LOGd("Invoking Singleshot Callback");
|
|
if (qLocationCallbacks.singleShotCb) {
|
|
qLocationCallbacks.singleShotCb(qLocation, QAPI_LOCATION_ERROR_SUCCESS);
|
|
} else {
|
|
LOC_LOGe("No singleshot cb registered");
|
|
}
|
|
} else {
|
|
LOC_LOGd("Invoking Tracking Callback");
|
|
if (qLocationCallbacks.trackingCb) {
|
|
qLocationCallbacks.trackingCb(qLocation);
|
|
}
|
|
else {
|
|
LOC_LOGe("No tracking cb registered");
|
|
}
|
|
}
|
|
}
|
|
|
|
static void loc_passive_capabilities_callback(
|
|
LocationCapabilitiesMask capsMask)
|
|
{
|
|
LOC_LOGv("loc_passive_capabilities_callback!");
|
|
}
|
|
|
|
static void loc_passive_tracking_callback(
|
|
GnssLocation gnsslocation)
|
|
{
|
|
qCacheLocation.size = sizeof(qapi_Location_t);
|
|
qCacheLocation.timestamp = gnsslocation.timestamp;
|
|
qCacheLocation.latitude = gnsslocation.latitude;
|
|
qCacheLocation.longitude = gnsslocation.longitude;
|
|
qCacheLocation.altitude = gnsslocation.altitude;
|
|
qCacheLocation.altitudeMeanSeaLevel = gnsslocation.altitudeMeanSeaLevel;
|
|
qCacheLocation.speed = gnsslocation.speed;
|
|
qCacheLocation.bearing = gnsslocation.bearing;
|
|
qCacheLocation.accuracy = gnsslocation.horizontalAccuracy;
|
|
qCacheLocation.flags = gnsslocation.flags;
|
|
if (gnsslocation.gnssInfoFlags & GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT) {
|
|
qCacheLocation.flags |= QAPI_LOCATION_HAS_ALTITUDE_MSL_BIT;
|
|
}
|
|
qCacheLocation.flags |= QAPI_LOCATION_IS_BEST_AVAIL_POS_BIT;
|
|
qCacheLocation.verticalAccuracy = gnsslocation.verticalAccuracy;
|
|
qCacheLocation.speedAccuracy = gnsslocation.speedAccuracy;
|
|
qCacheLocation.bearingAccuracy = gnsslocation.bearingAccuracy;
|
|
|
|
print_qLocation_array(&qCacheLocation, 1);
|
|
}
|
|
|
|
static void loc_passive_response_callback(
|
|
LocationResponse err)
|
|
{
|
|
LOC_LOGv("loc_passive_response_callback!");
|
|
}
|
|
|
|
struct MyClientCallbacks {
|
|
CapabilitiesCb capabilitycb;
|
|
ResponseCb responsecb;
|
|
CollectiveResponseCb collectivecb;
|
|
LocationCb locationcb;
|
|
};
|
|
|
|
static MyClientCallbacks gLocationCallbacks = {
|
|
location_capabilities_callback,
|
|
location_response_callback,
|
|
location_collective_response_callback,
|
|
location_tracking_callback,
|
|
};
|
|
|
|
#define LOC_PATH_QAPI_CONF_STR "/etc/qapi.conf"
|
|
|
|
const char LOC_PATH_QAPI_CONF[] = LOC_PATH_QAPI_CONF_STR;
|
|
static uint32_t gDebug = 0;
|
|
static uint32_t gSingleshotTimeout = 0;
|
|
|
|
static const loc_param_s_type gConfigTable[] =
|
|
{
|
|
{ "DEBUG_LEVEL", &gDebug, NULL, 'n' }
|
|
};
|
|
|
|
static const loc_param_s_type gQapiConfigTable[] =
|
|
{
|
|
{ "SINGLESHOT_TIMEOUT", &gSingleshotTimeout, NULL, 'n' }
|
|
};
|
|
|
|
/* Parameters we need in a configuration file specifically for QAPI:
|
|
SINGLESHOT_TIMEOUT
|
|
*/
|
|
|
|
extern "C" {
|
|
qapi_Location_Error_t qapi_Loc_Init(
|
|
qapi_loc_client_id* pClientId,
|
|
const qapi_Location_Callbacks_t* pCallbacks)
|
|
{
|
|
qapi_Location_Error_t retVal =
|
|
QAPI_LOCATION_ERROR_SUCCESS;
|
|
|
|
// read configuration file
|
|
UTIL_READ_CONF(LOC_PATH_GPS_CONF, gConfigTable);
|
|
LOC_LOGd("gDebug=%u LOC_PATH_GPS_CONF=%s", gDebug, LOC_PATH_GPS_CONF);
|
|
|
|
UTIL_READ_CONF(LOC_PATH_QAPI_CONF, gQapiConfigTable);
|
|
LOC_LOGd("gSingleshotTimeout=%u LOC_PATH_QAPI_CONF=%s", gSingleshotTimeout, LOC_PATH_QAPI_CONF);
|
|
|
|
MyClientCallbacks locationCallbacks = gLocationCallbacks;
|
|
|
|
LOC_LOGd("qapi_Loc_Init! pCallbacks %p"
|
|
"cap %p res %p col %p trk %p",
|
|
pCallbacks,
|
|
pCallbacks->capabilitiesCb,
|
|
pCallbacks->responseCb,
|
|
pCallbacks->collectiveResponseCb,
|
|
pCallbacks->trackingCb);
|
|
|
|
LOC_LOGd("qapi_Loc_Init! pCallbacks %p"
|
|
"bat %p gf %p ss %p gd %p",
|
|
pCallbacks,
|
|
pCallbacks->batchingCb,
|
|
pCallbacks->geofenceBreachCb,
|
|
pCallbacks->singleShotCb,
|
|
pCallbacks->gnssDataCb);
|
|
|
|
if (!qMutexInitDone)
|
|
{
|
|
pthread_mutex_init(&qMutex, NULL);
|
|
qMutexInitDone = true;
|
|
}
|
|
|
|
/* Input sanity */
|
|
if (NULL == pCallbacks->capabilitiesCb ||
|
|
NULL == pCallbacks->responseCb ||
|
|
NULL == pCallbacks->collectiveResponseCb)
|
|
{
|
|
return QAPI_LOCATION_ERROR_CALLBACK_MISSING;
|
|
}
|
|
/* Don't register callbacks not provided by client */
|
|
if (NULL == pCallbacks->trackingCb) {
|
|
locationCallbacks.locationcb = NULL;
|
|
}
|
|
pthread_mutex_lock(&qMutex);
|
|
|
|
do
|
|
{
|
|
qLocationCallbacks = *pCallbacks;
|
|
if (nullptr == pLocClientApi) {
|
|
pLocClientApi = new LocationClientApi(
|
|
location_capabilities_callback);
|
|
retVal = QAPI_LOCATION_ERROR_SUCCESS;
|
|
} else {
|
|
retVal = QAPI_LOCATION_ERROR_ALREADY_STARTED;
|
|
}
|
|
/* Start passive listener here in order to be able to satisfy
|
|
qapi_Loc_Get_Best_Available_Position call */
|
|
|
|
if (nullptr == pLocPassiveClientApi) {
|
|
pLocPassiveClientApi = new LocationClientApi(
|
|
loc_passive_capabilities_callback);
|
|
retVal = QAPI_LOCATION_ERROR_SUCCESS;
|
|
bool ret;
|
|
memset(&qCacheLocation, 0, sizeof(qCacheLocation));
|
|
qCacheLocation.flags |= QAPI_LOCATION_IS_BEST_AVAIL_POS_BIT;
|
|
|
|
GnssReportCbs gnnsReportCbs;
|
|
memset(&gnnsReportCbs, 0, sizeof(gnnsReportCbs));
|
|
gnnsReportCbs.gnssLocationCallback = loc_passive_tracking_callback;
|
|
|
|
ret = pLocPassiveClientApi->startPositionSession(
|
|
0, // both 0 means passive listener
|
|
gnnsReportCbs,
|
|
loc_passive_response_callback);
|
|
if (!ret) {
|
|
retVal = QAPI_LOCATION_ERROR_GENERAL_FAILURE;
|
|
}
|
|
} else {
|
|
retVal = QAPI_LOCATION_ERROR_ALREADY_STARTED;
|
|
}
|
|
|
|
*pClientId = 0;
|
|
} while (0);
|
|
pthread_mutex_unlock(&qMutex);
|
|
return retVal;
|
|
}
|
|
|
|
qapi_Location_Error_t qapi_Loc_Deinit(
|
|
qapi_loc_client_id clientId)
|
|
{
|
|
qapi_Location_Error_t retVal =
|
|
QAPI_LOCATION_ERROR_ID_UNKNOWN;
|
|
|
|
LOC_LOGd("gDebug=%u LOC_PATH_GPS_CONF=%s", gDebug, LOC_PATH_GPS_CONF);
|
|
LOC_LOGd("qapi_Loc_Deinit client %d", clientId);
|
|
|
|
pthread_mutex_lock(&qMutex);
|
|
if (nullptr != pLocClientApi) {
|
|
delete pLocClientApi;
|
|
pLocClientApi = nullptr;
|
|
retVal = QAPI_LOCATION_ERROR_SUCCESS;
|
|
}
|
|
pthread_mutex_unlock(&qMutex);
|
|
return retVal;
|
|
}
|
|
|
|
qapi_Location_Error_t qapi_Loc_Set_User_Buffer(
|
|
qapi_loc_client_id clientId,
|
|
uint8_t* pUserBuffer,
|
|
size_t bufferSize)
|
|
{
|
|
return QAPI_LOCATION_ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
qapi_Location_Error_t qapi_Loc_Start_Tracking(
|
|
qapi_loc_client_id clientId,
|
|
const qapi_Location_Options_t* pOptions,
|
|
uint32_t* pSessionId)
|
|
{
|
|
qapi_Location_Error_t retVal =
|
|
QAPI_LOCATION_ERROR_SUCCESS;
|
|
|
|
LOC_LOGd("qapi_Loc_Start_Tracking! pOptions=%p pSessionId=%p clientId=%d",
|
|
pOptions, pSessionId, clientId);
|
|
|
|
pthread_mutex_lock(&qMutex);
|
|
do {
|
|
if (NULL == pOptions)
|
|
{
|
|
LOC_LOGe("pOptions NULL");
|
|
retVal = QAPI_LOCATION_ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
LOC_LOGd("qapi_Loc_Start_Tracking! minInterval=%d minDistance=%d",
|
|
pOptions->minInterval,
|
|
pOptions->minDistance);
|
|
|
|
if (nullptr != pLocClientApi) {
|
|
bool ret;
|
|
ret = pLocClientApi->startPositionSession(
|
|
pOptions->minInterval,
|
|
pOptions->minDistance,
|
|
location_tracking_callback,
|
|
location_response_callback);
|
|
if (!ret) {
|
|
retVal = QAPI_LOCATION_ERROR_GENERAL_FAILURE;
|
|
}
|
|
} else {
|
|
retVal = QAPI_LOCATION_ERROR_GENERAL_FAILURE;
|
|
}
|
|
} while (0);
|
|
*pSessionId = 1;
|
|
pthread_mutex_unlock(&qMutex);
|
|
return retVal;
|
|
}
|
|
|
|
qapi_Location_Error_t qapi_Loc_Stop_Tracking(
|
|
qapi_loc_client_id clientId,
|
|
uint32_t sessionId)
|
|
{
|
|
qapi_Location_Error_t retVal =
|
|
QAPI_LOCATION_ERROR_SUCCESS;
|
|
|
|
LOC_LOGv("qapi_Loc_Stop_Tracking! clientId %d, sessionId %d",
|
|
clientId, sessionId);
|
|
|
|
pthread_mutex_lock(&qMutex);
|
|
|
|
if (nullptr != pLocClientApi) {
|
|
pLocClientApi->stopPositionSession();
|
|
} else {
|
|
retVal = QAPI_LOCATION_ERROR_GENERAL_FAILURE;
|
|
}
|
|
pthread_mutex_unlock(&qMutex);
|
|
return retVal;
|
|
}
|
|
|
|
qapi_Location_Error_t qapi_Loc_Update_Tracking_Options(
|
|
qapi_loc_client_id clientId,
|
|
uint32_t sessionId,
|
|
const qapi_Location_Options_t* pOptions)
|
|
{
|
|
return QAPI_LOCATION_ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
qapi_Location_Error_t qapi_Loc_Start_Batching(
|
|
qapi_loc_client_id clientId,
|
|
const qapi_Location_Options_t* pOptions,
|
|
uint32_t* pSessionId)
|
|
{
|
|
return QAPI_LOCATION_ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
qapi_Location_Error_t qapi_Loc_Stop_Batching(
|
|
qapi_loc_client_id clientId,
|
|
uint32_t sessionId)
|
|
{
|
|
return QAPI_LOCATION_ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
qapi_Location_Error_t qapi_Loc_Update_Batching_Options(
|
|
qapi_loc_client_id clientId,
|
|
uint32_t sessionId,
|
|
const qapi_Location_Options_t* pOptions)
|
|
{
|
|
return QAPI_LOCATION_ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
qapi_Location_Error_t qapi_Loc_Get_Batched_Locations(
|
|
qapi_loc_client_id clientId,
|
|
uint32_t sessionId,
|
|
size_t count)
|
|
{
|
|
return QAPI_LOCATION_ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
qapi_Location_Error_t qapi_Loc_Add_Geofences(
|
|
qapi_loc_client_id clientId,
|
|
size_t count,
|
|
const qapi_Geofence_Option_t* pOptions,
|
|
const qapi_Geofence_Info_t* pInfo,
|
|
uint32_t** pIdArray)
|
|
{
|
|
return QAPI_LOCATION_ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
qapi_Location_Error_t qapi_Loc_Remove_Geofences(
|
|
qapi_loc_client_id clientId,
|
|
size_t count,
|
|
const uint32_t* pIDs)
|
|
{
|
|
return QAPI_LOCATION_ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
qapi_Location_Error_t qapi_Loc_Modify_Geofences(
|
|
qapi_loc_client_id clientId,
|
|
size_t count,
|
|
const uint32_t* pIDs,
|
|
const qapi_Geofence_Option_t* options)
|
|
{
|
|
return QAPI_LOCATION_ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
qapi_Location_Error_t qapi_Loc_Pause_Geofences(
|
|
qapi_loc_client_id clientId,
|
|
size_t count,
|
|
const uint32_t* pIDs)
|
|
{
|
|
return QAPI_LOCATION_ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
qapi_Location_Error_t qapi_Loc_Resume_Geofences(
|
|
qapi_loc_client_id clientId,
|
|
size_t count,
|
|
const uint32_t* pIDs)
|
|
{
|
|
return QAPI_LOCATION_ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
qapi_Location_Error_t qapi_Loc_Get_Single_Shot(
|
|
qapi_loc_client_id clientId,
|
|
qapi_Location_Power_Level_t powerLevel,
|
|
uint32_t* pSessionId)
|
|
{
|
|
qapi_Location_Error_t retVal =
|
|
QAPI_LOCATION_ERROR_SUCCESS;
|
|
bool bFound = false;
|
|
qapi_Location_Options_t options;
|
|
|
|
LOC_LOGd("qapi_Loc_Get_Single_Shot! pSessionId=%p clientId=%d",
|
|
pSessionId, clientId);
|
|
|
|
pthread_mutex_lock(&qMutex);
|
|
do {
|
|
if (QAPI_LOCATION_POWER_HIGH != powerLevel &&
|
|
QAPI_LOCATION_POWER_LOW != powerLevel)
|
|
{
|
|
LOC_LOGe("powerLevel is invalid");
|
|
retVal = QAPI_LOCATION_ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
LOC_LOGd("qapi_Loc_Get_Single_Shot! powerLevel=%d",
|
|
powerLevel);
|
|
|
|
GnssReportCbs gnnsReportCbs;
|
|
memset(&gnnsReportCbs, 0, sizeof(gnnsReportCbs));
|
|
gnnsReportCbs.gnssLocationCallback = gnss_location_tracking_callback;
|
|
|
|
if (nullptr != pLocClientApi) {
|
|
bool ret;
|
|
ret = pLocClientApi->startPositionSession(
|
|
1000,
|
|
gnnsReportCbs,
|
|
location_response_callback);
|
|
if (!ret) {
|
|
retVal = QAPI_LOCATION_ERROR_GENERAL_FAILURE;
|
|
} else {
|
|
Runnable timerRunnable = [pLocClientApi] {
|
|
pLocClientApi->stopPositionSession();
|
|
if (qLocationCallbacks.singleShotCb) {
|
|
qapi_Location_t qLocation;
|
|
qLocationCallbacks.singleShotCb(qLocation, QAPI_LOCATION_ERROR_TIMEOUT);
|
|
} else {
|
|
LOC_LOGe("No singleshot cb registered");
|
|
}
|
|
};
|
|
mTimer.set(gSingleshotTimeout, timerRunnable);
|
|
mTimer.start();
|
|
}
|
|
} else {
|
|
retVal = QAPI_LOCATION_ERROR_GENERAL_FAILURE;
|
|
}
|
|
} while (0);
|
|
*pSessionId = 1;
|
|
pthread_mutex_unlock(&qMutex);
|
|
return retVal;
|
|
}
|
|
|
|
qapi_Location_Error_t qapi_Loc_Cancel_Single_Shot(
|
|
qapi_loc_client_id clientId,
|
|
uint32_t sessionId)
|
|
{
|
|
qapi_Location_Error_t retVal =
|
|
QAPI_LOCATION_ERROR_SUCCESS;
|
|
|
|
LOC_LOGv("qapi_Loc_Cancel_Single_Shot! clientId %d, sessionId %d",
|
|
clientId, sessionId);
|
|
|
|
pthread_mutex_lock(&qMutex);
|
|
if (mTimer.isStarted()) {
|
|
LOC_LOGd("Timer was started, singleshot session in progress");
|
|
if (nullptr != pLocClientApi) {
|
|
LOC_LOGd("Stop singleshot session");
|
|
pLocClientApi->stopPositionSession();
|
|
}
|
|
LOC_LOGd("Stop singleshot timer");
|
|
mTimer.stop();
|
|
} else {
|
|
LOC_LOGd("No singleshot session in progress!");
|
|
}
|
|
pthread_mutex_unlock(&qMutex);
|
|
return retVal;
|
|
}
|
|
|
|
qapi_Location_Error_t qapi_Loc_Start_Get_Gnss_Data(
|
|
qapi_loc_client_id clientId,
|
|
uint32_t* pSessionId)
|
|
{
|
|
return QAPI_LOCATION_ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
qapi_Location_Error_t qapi_Loc_Stop_Get_Gnss_Data(
|
|
qapi_loc_client_id clientId,
|
|
uint32_t sessionId)
|
|
{
|
|
return QAPI_LOCATION_ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
qapi_Location_Error_t qapi_Loc_Get_Best_Available_Position(
|
|
qapi_loc_client_id clientId,
|
|
uint32_t* pSessionId)
|
|
{
|
|
qapi_Location_Error_t retVal = QAPI_LOCATION_ERROR_SUCCESS;
|
|
|
|
LOC_LOGv("qapi_Loc_Get_Best_Available_Position! clientId %d", clientId);
|
|
pthread_mutex_lock(&qMutex);
|
|
do {
|
|
if (nullptr != pLocClientApi) {
|
|
Runnable timerRunnable = [] {
|
|
if (qLocationCallbacks.singleShotCb) {
|
|
qLocationCallbacks.singleShotCb(qCacheLocation, QAPI_LOCATION_ERROR_SUCCESS);
|
|
} else {
|
|
LOC_LOGe("No singleshot cb registered");
|
|
}
|
|
};
|
|
mPassiveTimer.set(500, timerRunnable);
|
|
mPassiveTimer.start();
|
|
|
|
} else {
|
|
retVal = QAPI_LOCATION_ERROR_GENERAL_FAILURE;
|
|
}
|
|
} while (0);
|
|
|
|
pthread_mutex_unlock(&qMutex);
|
|
return retVal;
|
|
}
|
|
|
|
} /* extern "C" */
|