code:
/* Copyright (c) 2011-2014, 2016-2021 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_NDEBUG 0 //Define to enable LOGV
#define LOG_TAG "LocSvc_LocApiBase"

#include <dlfcn.h>
#include <inttypes.h>
#include <gps_extended_c.h>
#include <LocApiBase.h>
#include <LocAdapterBase.h>
#include <log_util.h>
#include <LocContext.h>
#include <loc_misc_utils.h>

namespace loc_core {

#define TO_ALL_LOCADAPTERS(call) TO_ALL_ADAPTERS(mLocAdapters, (call))
#define TO_1ST_HANDLING_LOCADAPTERS(call) TO_1ST_HANDLING_ADAPTER(mLocAdapters, (call))

int hexcode(char *hexstring, int string_size,
            const char *data, int data_size)
{
   int i;
   for (i = 0; i < data_size; i++)
   {
      char ch = data[i];
      if (i*2 + 3 <= string_size)
      {
         snprintf(&hexstring[i*2], 3, "%02X", ch);
      }
      else {
         break;
      }
   }
   return i;
}

int decodeAddress(char *addr_string, int string_size,
                   const char *data, int data_size)
{
    const char addr_prefix = 0x91;
    int i, idxOutput = 0;

    if (!data || !addr_string) { return 0; }

    if (data[0] != addr_prefix)
    {
        LOC_LOGW("decodeAddress: address prefix is not 0x%x but 0x%x", addr_prefix, data[0]);
        addr_string[0] = '\0';
        return 0; // prefix not correct
    }

    for (i = 1; i < data_size; i++)
    {
        unsigned char ch = data[i], low = ch & 0x0F, hi = ch >> 4;
        if (low <= 9 && idxOutput < string_size - 1) { addr_string[idxOutput++] = low + '0'; }
        if (hi <= 9 && idxOutput < string_size - 1) { addr_string[idxOutput++] = hi + '0'; }
    }

    addr_string[idxOutput] = '\0'; // Terminates the string

    return idxOutput;
}

struct LocSsrMsg : public LocMsg {
    LocApiBase* mLocApi;
    inline LocSsrMsg(LocApiBase* locApi) :
        LocMsg(), mLocApi(locApi)
    {
        locallog();
    }
    inline virtual void proc() const {
        mLocApi->close();
        if (LOC_API_ADAPTER_ERR_SUCCESS == mLocApi->open(mLocApi->getEvtMask())) {
            // Notify adapters that engine up after SSR
            mLocApi->handleEngineUpEvent();
        }
    }
    inline void locallog() const {
        LOC_LOGV("LocSsrMsg");
    }
    inline virtual void log() const {
        locallog();
    }
};

struct LocOpenMsg : public LocMsg {
    LocApiBase* mLocApi;
    LocAdapterBase* mAdapter;
    inline LocOpenMsg(LocApiBase* locApi, LocAdapterBase* adapter = nullptr) :
            LocMsg(), mLocApi(locApi), mAdapter(adapter)
    {
        locallog();
    }
    inline virtual void proc() const {
        if (LOC_API_ADAPTER_ERR_SUCCESS == mLocApi->open(mLocApi->getEvtMask()) &&
            nullptr != mAdapter) {
            mAdapter->handleEngineUpEvent();
        }
    }
    inline void locallog() const {
        LOC_LOGv("LocOpen Mask: %" PRIx64 "\n", mLocApi->getEvtMask());
    }
    inline virtual void log() const {
        locallog();
    }
};

struct LocCloseMsg : public LocMsg {
    LocApiBase* mLocApi;
    inline LocCloseMsg(LocApiBase* locApi) :
        LocMsg(), mLocApi(locApi)
    {
        locallog();
    }
    inline virtual void proc() const {
        mLocApi->close();
    }
    inline void locallog() const {
    }
    inline virtual void log() const {
        locallog();
    }
};

MsgTask* LocApiBase::mMsgTask = nullptr;
volatile int32_t LocApiBase::mMsgTaskRefCount = 0;

LocApiBase::LocApiBase(LOC_API_ADAPTER_EVENT_MASK_T excludedMask,
                       ContextBase* context) :
    mContext(context),
    mMask(0), mExcludedMask(excludedMask)
{
    memset(mLocAdapters, 0, sizeof(mLocAdapters));

    android_atomic_inc(&mMsgTaskRefCount);
    if (nullptr == mMsgTask) {
        mMsgTask = new MsgTask("LocApiMsgTask");
    }
}

LOC_API_ADAPTER_EVENT_MASK_T LocApiBase::getEvtMask()
{
    LOC_API_ADAPTER_EVENT_MASK_T mask = 0;

    TO_ALL_LOCADAPTERS(mask |= mLocAdapters[i]->getEvtMask());

    return mask & ~mExcludedMask;
}

bool LocApiBase::isMaster()
{
    bool isMaster = false;

    for (int i = 0;
            !isMaster && i < MAX_ADAPTERS && NULL != mLocAdapters[i];
            i++) {
        isMaster |= mLocAdapters[i]->isAdapterMaster();
    }
    return isMaster;
}

bool LocApiBase::isInSession()
{
    bool inSession = false;

    for (int i = 0;
         !inSession && i < MAX_ADAPTERS && NULL != mLocAdapters[i];
         i++) {
        inSession = mLocAdapters[i]->isInSession();
    }

    return inSession;
}

bool LocApiBase::needReport(const UlpLocation& ulpLocation,
                            enum loc_sess_status status,
                            LocPosTechMask techMask)
{
    bool reported = false;

    if (LOC_SESS_SUCCESS == status) {
        // this is a final fix
        LocPosTechMask mask =
            LOC_POS_TECH_MASK_SATELLITE | LOC_POS_TECH_MASK_SENSORS | LOC_POS_TECH_MASK_HYBRID;
        // it is a Satellite fix or a sensor fix
        reported = (mask & techMask);
    }
    else if (LOC_SESS_INTERMEDIATE == status &&
        LOC_SESS_INTERMEDIATE == ContextBase::mGps_conf.INTERMEDIATE_POS) {
        // this is a intermediate fix and we accept intermediate

        // it is NOT the case that
        // there is inaccuracy; and
        // we care about inaccuracy; and
        // the inaccuracy exceeds our tolerance
        reported = !((ulpLocation.gpsLocation.flags & LOC_GPS_LOCATION_HAS_ACCURACY) &&
            (ContextBase::mGps_conf.ACCURACY_THRES != 0) &&
            (ulpLocation.gpsLocation.accuracy > ContextBase::mGps_conf.ACCURACY_THRES));
    }

    return reported;
}

void LocApiBase::addAdapter(LocAdapterBase* adapter)
{
    for (int i = 0; i < MAX_ADAPTERS && mLocAdapters[i] != adapter; i++) {
        if (mLocAdapters[i] == NULL) {
            mLocAdapters[i] = adapter;
            sendMsg(new LocOpenMsg(this,  adapter));
            break;
        }
    }
}

void LocApiBase::removeAdapter(LocAdapterBase* adapter)
{
    for (int i = 0;
         i < MAX_ADAPTERS && NULL != mLocAdapters[i];
         i++) {
        if (mLocAdapters[i] == adapter) {
            mLocAdapters[i] = NULL;

            // shift the rest of the adapters up so that the pointers
            // in the array do not have holes.  This should be more
            // performant, because the array maintenance is much much
            // less frequent than event handlings, which need to linear
            // search all the adapters
            int j = i;
            while (++i < MAX_ADAPTERS && mLocAdapters[i] != NULL);

            // i would be MAX_ADAPTERS or point to a NULL
            i--;
            // i now should point to a none NULL adapter within valid
            // range although i could be equal to j, but it won't hurt.
            // No need to check it, as it gains nothing.
            mLocAdapters[j] = mLocAdapters[i];
            // this makes sure that we exit the for loop
            mLocAdapters[i] = NULL;

            // if we have an empty list of adapters
            if (0 == i) {
                sendMsg(new LocCloseMsg(this));
            } else {
                // else we need to remove the bit
                sendMsg(new LocOpenMsg(this));
            }
        }
    }
}

void LocApiBase::updateEvtMask()
{
    sendMsg(new LocOpenMsg(this));
}

void LocApiBase::updateNmeaMask(uint32_t mask)
{
    struct LocSetNmeaMsg : public LocMsg {
        LocApiBase* mLocApi;
        uint32_t mMask;
        inline LocSetNmeaMsg(LocApiBase* locApi, uint32_t mask) :
            LocMsg(), mLocApi(locApi), mMask(mask)
        {
            locallog();
        }
        inline virtual void proc() const {
            mLocApi->setNMEATypesSync(mMask);
        }
        inline void locallog() const {
            LOC_LOGv("LocSyncNmea NmeaMask: %" PRIx32 "\n", mMask);
        }
        inline virtual void log() const {
            locallog();
        }
    };

    sendMsg(new LocSetNmeaMsg(this, mask));
}

void LocApiBase::handleEngineUpEvent()
{
    // loop through adapters, and deliver to all adapters.
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->handleEngineUpEvent());
}

void LocApiBase::handleEngineDownEvent()
{    // This will take care of renegotiating the loc handle
    sendMsg(new LocSsrMsg(this));

    // loop through adapters, and deliver to all adapters.
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->handleEngineDownEvent());
}

void LocApiBase::reportPosition(UlpLocation& location,
                                GpsLocationExtended& locationExtended,
                                enum loc_sess_status status,
                                LocPosTechMask loc_technology_mask,
                                GnssDataNotification* pDataNotify,
                                int msInWeek)
{
    // print the location info before delivering
    LOC_LOGD("flags: %d\n  source: %d\n  latitude: %f\n  longitude: %f\n  "
             "altitude: %f\n  speed: %f\n  bearing: %f\n  accuracy: %f\n  "
             "timestamp: %" PRId64 "\n"
             "Session status: %d\n Technology mask: %u\n "
             "SV used in fix (gps/glo/bds/gal/qzss) : \
             (0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 ")",
             location.gpsLocation.flags, location.position_source,
             location.gpsLocation.latitude, location.gpsLocation.longitude,
             location.gpsLocation.altitude, location.gpsLocation.speed,
             location.gpsLocation.bearing, location.gpsLocation.accuracy,
             location.gpsLocation.timestamp, status, loc_technology_mask,
             locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask,
             locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask,
             locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask,
             locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask,
             locationExtended.gnss_sv_used_ids.qzss_sv_used_ids_mask,
             locationExtended.gnss_sv_used_ids.navic_sv_used_ids_mask);
    // loop through adapters, and deliver to all adapters.
    TO_ALL_LOCADAPTERS(
        mLocAdapters[i]->reportPositionEvent(location, locationExtended,
                                             status, loc_technology_mask,
                                             pDataNotify, msInWeek)
    );
}

void LocApiBase::reportWwanZppFix(LocGpsLocation &zppLoc)
{
    // loop through adapters, and deliver to the first handling adapter.
    TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportWwanZppFix(zppLoc));
}

void LocApiBase::reportZppBestAvailableFix(LocGpsLocation &zppLoc,
        GpsLocationExtended &location_extended, LocPosTechMask tech_mask)
{
    // loop through adapters, and deliver to the first handling adapter.
    TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportZppBestAvailableFix(zppLoc,
            location_extended, tech_mask));
}

void LocApiBase::requestOdcpi(OdcpiRequestInfo& request)
{
    // loop through adapters, and deliver to the first handling adapter.
    TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestOdcpiEvent(request));
}

void LocApiBase::reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot)
{
    // loop through adapters, and deliver to the first handling adapter.
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssEngEnergyConsumedEvent(
            energyConsumedSinceFirstBoot));
}

void LocApiBase::reportDeleteAidingDataEvent(GnssAidingData& aidingData) {
    // loop through adapters, and deliver to the first handling adapter.
    TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportDeleteAidingDataEvent(aidingData));
}

void LocApiBase::reportKlobucharIonoModel(GnssKlobucharIonoModel & ionoModel) {
    // loop through adapters, and deliver to the first handling adapter.
    TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportKlobucharIonoModelEvent(ionoModel));
}

void LocApiBase::reportGnssAdditionalSystemInfo(GnssAdditionalSystemInfo& additionalSystemInfo) {
    // loop through adapters, and deliver to the first handling adapter.
    TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportGnssAdditionalSystemInfoEvent(
            additionalSystemInfo));
}

void LocApiBase::sendNfwNotification(GnssNfwNotification& notification)
{
    // loop through adapters, and deliver to the first handling adapter.
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportNfwNotificationEvent(notification));

}

void LocApiBase::reportSv(GnssSvNotification& svNotify)
{
    const char* constellationString[] = { "Unknown", "GPS", "SBAS", "GLONASS",
        "QZSS", "BEIDOU", "GALILEO", "NAVIC" };

    // print the SV info before delivering
    LOC_LOGV("num sv: %u\n"
        "      sv: constellation svid         cN0  basebandCN0"
        "    elevation    azimuth    flags",
        svNotify.count);
    for (size_t i = 0; i < svNotify.count && i < GNSS_SV_MAX; i++) {
        if (svNotify.gnssSvs[i].type >
            sizeof(constellationString) / sizeof(constellationString[0]) - 1) {
            svNotify.gnssSvs[i].type = GNSS_SV_TYPE_UNKNOWN;
        }
        // Display what we report to clients
        LOC_LOGV("   %03zu: %*s  %02d    %f    %f    %f    %f    %f    0x%02X 0x%2X",
            i,
            13,
            constellationString[svNotify.gnssSvs[i].type],
            svNotify.gnssSvs[i].svId,
            svNotify.gnssSvs[i].cN0Dbhz,
            svNotify.gnssSvs[i].basebandCarrierToNoiseDbHz,
            svNotify.gnssSvs[i].elevation,
            svNotify.gnssSvs[i].azimuth,
            svNotify.gnssSvs[i].carrierFrequencyHz,
            svNotify.gnssSvs[i].gnssSvOptionsMask,
            svNotify.gnssSvs[i].gnssSignalTypeMask);
    }
    // loop through adapters, and deliver to all adapters.
    TO_ALL_LOCADAPTERS(
        mLocAdapters[i]->reportSvEvent(svNotify)
        );
}

void LocApiBase::reportSvPolynomial(GnssSvPolynomial &svPolynomial)
{
    // loop through adapters, and deliver to all adapters.
    TO_ALL_LOCADAPTERS(
        mLocAdapters[i]->reportSvPolynomialEvent(svPolynomial)
    );
}

void LocApiBase::reportSvEphemeris(GnssSvEphemerisReport & svEphemeris)
{
    // loop through adapters, and deliver to all adapters.
    TO_ALL_LOCADAPTERS(
        mLocAdapters[i]->reportSvEphemerisEvent(svEphemeris)
    );
}

void LocApiBase::reportStatus(LocGpsStatusValue status)
{
    // loop through adapters, and deliver to all adapters.
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportStatus(status));
}

void LocApiBase::reportData(GnssDataNotification& dataNotify, int msInWeek)
{
    // loop through adapters, and deliver to all adapters.
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportDataEvent(dataNotify, msInWeek));
}

void LocApiBase::reportNmea(const char* nmea, int length)
{
    // loop through adapters, and deliver to all adapters.
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportNmeaEvent(nmea, length));
}

void LocApiBase::reportXtraServer(const char* url1, const char* url2,
                                  const char* url3, const int maxlength)
{
    // loop through adapters, and deliver to the first handling adapter.
    TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportXtraServer(url1, url2, url3, maxlength));

}

void LocApiBase::reportLocationSystemInfo(const LocationSystemInfo& locationSystemInfo)
{
    // loop through adapters, and deliver to all adapters.
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportLocationSystemInfoEvent(locationSystemInfo));
}

void LocApiBase::reportQwesCapabilities
(
    const std::unordered_map<LocationQwesFeatureType, bool> &featureMap
)
{
    // loop through adapters, and deliver to all adapters.
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportQwesCapabilities(featureMap));
}
void LocApiBase::requestXtraData()
{
    // loop through adapters, and deliver to the first handling adapter.
    TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestXtraData());
}

void LocApiBase::requestTime()
{
    // loop through adapters, and deliver to the first handling adapter.
    TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestTime());
}

void LocApiBase::requestLocation()
{
    // loop through adapters, and deliver to the first handling adapter.
    TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestLocation());
}

void LocApiBase::requestATL(int connHandle, LocAGpsType agps_type,
                            LocApnTypeMask apn_type_mask)
{
    // loop through adapters, and deliver to the first handling adapter.
    TO_1ST_HANDLING_LOCADAPTERS(
            mLocAdapters[i]->requestATL(connHandle, agps_type, apn_type_mask));
}

void LocApiBase::releaseATL(int connHandle)
{
    // loop through adapters, and deliver to the first handling adapter.
    TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->releaseATL(connHandle));
}

void LocApiBase::requestNiNotify(GnssNiNotification &notify, const void* data,
                                 const LocInEmergency emergencyState)
{
    // loop through adapters, and deliver to the first handling adapter.
    TO_1ST_HANDLING_LOCADAPTERS(
            mLocAdapters[i]->requestNiNotifyEvent(notify,
                                                  data,
                                                  emergencyState));
}

void* LocApiBase :: getSibling()
    DEFAULT_IMPL(NULL)

LocApiProxyBase* LocApiBase :: getLocApiProxy()
    DEFAULT_IMPL(NULL)

void LocApiBase::reportGnssMeasurements(GnssMeasurements& gnssMeasurements, int msInWeek)
{
    // loop through adapters, and deliver to all adapters.
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssMeasurementsEvent(gnssMeasurements, msInWeek));
}

void LocApiBase::reportGnssSvIdConfig(const GnssSvIdConfig& config)
{
    // Print the config
    LOC_LOGv("gloBlacklistSvMask: %" PRIu64 ", bdsBlacklistSvMask: %" PRIu64 ",\n"
             "qzssBlacklistSvMask: %" PRIu64 ", galBlacklistSvMask: %" PRIu64 ",\n"
              "navicBlacklistSvMask: %" PRIu64,
             config.gloBlacklistSvMask, config.bdsBlacklistSvMask,
             config.qzssBlacklistSvMask, config.galBlacklistSvMask, config.navicBlacklistSvMask);

    // Loop through adapters, and deliver to all adapters.
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssSvIdConfigEvent(config));
}

void LocApiBase::reportGnssSvTypeConfig(const GnssSvTypeConfig& config)
{
    // Print the config
    LOC_LOGv("blacklistedMask: %" PRIu64 ", enabledMask: %" PRIu64,
             config.blacklistedSvTypesMask, config.enabledSvTypesMask);

    // Loop through adapters, and deliver to all adapters.
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssSvTypeConfigEvent(config));
}

void LocApiBase::geofenceBreach(size_t count, uint32_t* hwIds, Location& location,
                                GeofenceBreachType breachType, uint64_t timestamp)
{
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->geofenceBreachEvent(count, hwIds, location, breachType,
                                                            timestamp));
}

void LocApiBase::geofenceStatus(GeofenceStatusAvailable available)
{
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->geofenceStatusEvent(available));
}

void LocApiBase::reportDBTPosition(UlpLocation &location, GpsLocationExtended &locationExtended,
                                   enum loc_sess_status status, LocPosTechMask loc_technology_mask)
{
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportPositionEvent(location, locationExtended, status,
                                                            loc_technology_mask));
}

void LocApiBase::reportLocations(Location* locations, size_t count, BatchingMode batchingMode)
{
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportLocationsEvent(locations, count, batchingMode));
}

void LocApiBase::reportCompletedTrips(uint32_t accumulated_distance)
{
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportCompletedTripsEvent(accumulated_distance));
}

void LocApiBase::handleBatchStatusEvent(BatchingStatus batchStatus)
{
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportBatchStatusChangeEvent(batchStatus));
}

void LocApiBase::reportGnssConfig(uint32_t sessionId, const GnssConfig& gnssConfig)
{
    // loop through adapters, and deliver to the first handling adapter.
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssConfigEvent(sessionId, gnssConfig));
}

void LocApiBase::reportLatencyInfo(GnssLatencyInfo& gnssLatencyInfo)
{
    // loop through adapters, and deliver to the first handling adapter.
    TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportLatencyInfoEvent(gnssLatencyInfo));
}

enum loc_api_adapter_err LocApiBase::
   open(LOC_API_ADAPTER_EVENT_MASK_T /*mask*/)
DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS)

enum loc_api_adapter_err LocApiBase::
    close()
DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS)

void LocApiBase::startFix(const LocPosMode& /*posMode*/, LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::stopFix(LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::
    deleteAidingData(const GnssAidingData& /*data*/, LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::
    injectPosition(double /*latitude*/, double /*longitude*/, float /*accuracy*/,
                   bool /*onDemandCpi*/)
DEFAULT_IMPL()

void LocApiBase::
    injectPosition(const Location& /*location*/, bool /*onDemandCpi*/)
DEFAULT_IMPL()

void LocApiBase::
    injectPosition(const GnssLocationInfoNotification & /*locationInfo*/, bool /*onDemandCpi*/)
DEFAULT_IMPL()

void LocApiBase::
    setTime(LocGpsUtcTime /*time*/, int64_t /*timeReference*/, int /*uncertainty*/)
DEFAULT_IMPL()

void LocApiBase::
   atlOpenStatus(int /*handle*/, int /*is_succ*/, char* /*apn*/, uint32_t /*apnLen*/,
                 AGpsBearerType /*bear*/, LocAGpsType /*agpsType*/,
                 LocApnTypeMask /*mask*/)
DEFAULT_IMPL()

void LocApiBase::
    atlCloseStatus(int /*handle*/, int /*is_succ*/)
DEFAULT_IMPL()

LocationError LocApiBase::
    setServerSync(const char* /*url*/, int /*len*/, LocServerType /*type*/)
DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)

LocationError LocApiBase::
    setServerSync(unsigned int /*ip*/, int /*port*/, LocServerType /*type*/)
DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)

void LocApiBase::
    informNiResponse(GnssNiResponse /*userResponse*/, const void* /*passThroughData*/)
DEFAULT_IMPL()

LocationError LocApiBase::
    setSUPLVersionSync(GnssConfigSuplVersion /*version*/)
DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)

enum loc_api_adapter_err LocApiBase::
    setNMEATypesSync (uint32_t /*typesMask*/)
DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS)

LocationError LocApiBase::
    setLPPConfigSync(GnssConfigLppProfileMask /*profileMask*/)
DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)

enum loc_api_adapter_err LocApiBase::
    setSensorPropertiesSync(bool /*gyroBiasVarianceRandomWalk_valid*/,
                        float /*gyroBiasVarianceRandomWalk*/,
                        bool /*accelBiasVarianceRandomWalk_valid*/,
                        float /*accelBiasVarianceRandomWalk*/,
                        bool /*angleBiasVarianceRandomWalk_valid*/,
                        float /*angleBiasVarianceRandomWalk*/,
                        bool /*rateBiasVarianceRandomWalk_valid*/,
                        float /*rateBiasVarianceRandomWalk*/,
                        bool /*velocityBiasVarianceRandomWalk_valid*/,
                        float /*velocityBiasVarianceRandomWalk*/)
DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS)

enum loc_api_adapter_err LocApiBase::
    setSensorPerfControlConfigSync(int /*controlMode*/,
                               int /*accelSamplesPerBatch*/,
                               int /*accelBatchesPerSec*/,
                               int /*gyroSamplesPerBatch*/,
                               int /*gyroBatchesPerSec*/,
                               int /*accelSamplesPerBatchHigh*/,
                               int /*accelBatchesPerSecHigh*/,
                               int /*gyroSamplesPerBatchHigh*/,
                               int /*gyroBatchesPerSecHigh*/,
                               int /*algorithmConfig*/)
DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS)

LocationError LocApiBase::
    setAGLONASSProtocolSync(GnssConfigAGlonassPositionProtocolMask /*aGlonassProtocol*/)
DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)

LocationError LocApiBase::
    setLPPeProtocolCpSync(GnssConfigLppeControlPlaneMask /*lppeCP*/)
DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)

LocationError LocApiBase::
    setLPPeProtocolUpSync(GnssConfigLppeUserPlaneMask /*lppeUP*/)
DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)

GnssConfigSuplVersion LocApiBase::convertSuplVersion(const uint32_t /*suplVersion*/)
DEFAULT_IMPL(GNSS_CONFIG_SUPL_VERSION_1_0_0)

GnssConfigLppeControlPlaneMask LocApiBase::convertLppeCp(const uint32_t /*lppeControlPlaneMask*/)
DEFAULT_IMPL(0)

GnssConfigLppeUserPlaneMask LocApiBase::convertLppeUp(const uint32_t /*lppeUserPlaneMask*/)
DEFAULT_IMPL(0)

LocationError LocApiBase::setEmergencyExtensionWindowSync(
        const uint32_t /*emergencyExtensionSeconds*/)
DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)

void LocApiBase::setMeasurementCorrections(
        const GnssMeasurementCorrections& /*gnssMeasurementCorrections*/)
DEFAULT_IMPL()

void LocApiBase::
   getWwanZppFix()
DEFAULT_IMPL()

void LocApiBase::
   getBestAvailableZppFix()
DEFAULT_IMPL()

LocationError LocApiBase::
    setGpsLockSync(GnssConfigGpsLock /*lock*/)
DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)

void LocApiBase::
    requestForAidingData(GnssAidingDataSvMask /*svDataMask*/)
DEFAULT_IMPL()

LocationError LocApiBase::
    setXtraVersionCheckSync(uint32_t /*check*/)
DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)

LocationError LocApiBase::setBlacklistSvSync(const GnssSvIdConfig& /*config*/)
DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)

void LocApiBase::setBlacklistSv(const GnssSvIdConfig& /*config*/,
                                LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::getBlacklistSv()
DEFAULT_IMPL()

void LocApiBase::setConstellationControl(const GnssSvTypeConfig& /*config*/,
                                         LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::getConstellationControl()
DEFAULT_IMPL()

void LocApiBase::resetConstellationControl(LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::
    setConstrainedTuncMode(bool /*enabled*/,
                           float /*tuncConstraint*/,
                           uint32_t /*energyBudget*/,
                           LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::
    setPositionAssistedClockEstimatorMode(bool /*enabled*/,
                                          LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::getGnssEnergyConsumed()
DEFAULT_IMPL()

void LocApiBase::addGeofence(uint32_t /*clientId*/, const GeofenceOption& /*options*/,
        const GeofenceInfo& /*info*/,
        LocApiResponseData<LocApiGeofenceData>* /*adapterResponseData*/)
DEFAULT_IMPL()

void LocApiBase::removeGeofence(uint32_t /*hwId*/, uint32_t /*clientId*/,
        LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::pauseGeofence(uint32_t /*hwId*/, uint32_t /*clientId*/,
        LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::resumeGeofence(uint32_t /*hwId*/, uint32_t /*clientId*/,
        LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::modifyGeofence(uint32_t /*hwId*/, uint32_t /*clientId*/,
         const GeofenceOption& /*options*/, LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::startTimeBasedTracking(const TrackingOptions& /*options*/,
        LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::stopTimeBasedTracking(LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::startDistanceBasedTracking(uint32_t /*sessionId*/,
        const LocationOptions& /*options*/, LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::stopDistanceBasedTracking(uint32_t /*sessionId*/,
        LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::startBatching(uint32_t /*sessionId*/, const LocationOptions& /*options*/,
        uint32_t /*accuracy*/, uint32_t /*timeout*/, LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::stopBatching(uint32_t /*sessionId*/, LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

LocationError LocApiBase::startOutdoorTripBatchingSync(uint32_t /*tripDistance*/,
        uint32_t /*tripTbf*/, uint32_t /*timeout*/)
DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)

void LocApiBase::startOutdoorTripBatching(uint32_t /*tripDistance*/, uint32_t /*tripTbf*/,
        uint32_t /*timeout*/, LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::reStartOutdoorTripBatching(uint32_t /*ongoingTripDistance*/,
        uint32_t /*ongoingTripInterval*/, uint32_t /*batchingTimeout,*/,
        LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

LocationError LocApiBase::stopOutdoorTripBatchingSync(bool /*deallocBatchBuffer*/)
DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)

void LocApiBase::stopOutdoorTripBatching(bool /*deallocBatchBuffer*/,
        LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

LocationError LocApiBase::getBatchedLocationsSync(size_t /*count*/)
DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)

void LocApiBase::getBatchedLocations(size_t /*count*/, LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

LocationError LocApiBase::getBatchedTripLocationsSync(size_t /*count*/,
        uint32_t /*accumulatedDistance*/)
DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)

void LocApiBase::getBatchedTripLocations(size_t /*count*/, uint32_t /*accumulatedDistance*/,
        LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

LocationError LocApiBase::queryAccumulatedTripDistanceSync(uint32_t& /*accumulated_trip_distance*/,
        uint32_t& /*numOfBatchedPositions*/)
DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)

void LocApiBase::queryAccumulatedTripDistance(
        LocApiResponseData<LocApiBatchData>* /*adapterResponseData*/)
DEFAULT_IMPL()

void LocApiBase::setBatchSize(size_t /*size*/)
DEFAULT_IMPL()

void LocApiBase::setTripBatchSize(size_t /*size*/)
DEFAULT_IMPL()

void LocApiBase::addToCallQueue(LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::updateSystemPowerState(PowerStateType /*powerState*/)
DEFAULT_IMPL()

void LocApiBase::
    configRobustLocation(bool /*enabled*/,
                         bool /*enableForE911*/,
                         LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::
    getRobustLocationConfig(uint32_t sessionId, LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::
    configMinGpsWeek(uint16_t minGpsWeek,
                     LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::
    getMinGpsWeek(uint32_t sessionId, LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

LocationError LocApiBase::
    setParameterSync(const GnssConfig& gnssConfig)
DEFAULT_IMPL(LOCATION_ERROR_SUCCESS)

void LocApiBase::
    getParameter(uint32_t sessionId, GnssConfigFlagsMask flags, LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::
    configConstellationMultiBand(const GnssSvTypeConfig& secondaryBandConfig,
                                 LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

void LocApiBase::
    getConstellationMultiBandConfig(uint32_t sessionId, LocApiResponse* /*adapterResponse*/)
DEFAULT_IMPL()

int64_t ElapsedRealtimeEstimator::getElapsedRealtimeEstimateNanos(int64_t curDataTimeNanos,
            bool isCurDataTimeTrustable, int64_t tbf) {
    //The algorithm works follow below steps:
    //When isCurDataTimeTrustable is meet (means Modem timestamp is already stable),
    //1, Wait for mFixTimeStablizationThreshold fixes; While waiting for modem time
    //   stable, we set the traveltime to a default value;
    //2, When the mFixTimeStablizationThreshold fix comes, we think now the mode time
    //   is already stable, calculate the initial AP-Modem clock diff(mCurrentClockDiff)
    //   using formula:
    //   mCurrentClockDiff = currentTimeNanos - locationTimeNanos - currentTravelTimeNanos
    //3, since then, when the nth fix comes,
    //   3.1 First update mCurrentClockDiff using below formula:
    //        mCurrentClockDiff = mCurrentClockDiff + (currentTimeNanos - sinceBootTimeNanos)
    //                - (mPrevUtcTimeNanos - mPrevBootTimeNanos)
    //   3.2 Calculate currentTravelTimeNanos:
    //        currentTravelTimeNanos = currentTimeNanos - locationTimeNanos - mCurrentClockDiff
    //4, It is possible that locationTimeNanos will jump,
    //   reset mFixTimeStablizationThreshold to default value, jump to step 2 to continue.

    int64_t currentTravelTimeNanos = mInitialTravelTime;
    struct timespec currentTime;
    int64_t sinceBootTimeNanos;
    if (getCurrentTime(currentTime, sinceBootTimeNanos)) {
        if (isCurDataTimeTrustable) {
            if (tbf > 0 && tbf != curDataTimeNanos - mPrevDataTimeNanos) {
                mFixTimeStablizationThreshold = 5;
            }
            int64_t currentTimeNanos = (int64_t)currentTime.tv_sec*1000000000 + currentTime.tv_nsec;
            LOC_LOGd("sinceBootTimeNanos:%" PRIi64 " currentTimeNanos:%" PRIi64 ""
                     " locationTimeNanos:%" PRIi64 "",
                     sinceBootTimeNanos, currentTimeNanos, curDataTimeNanos);
            if (mFixTimeStablizationThreshold == 0) {
                currentTravelTimeNanos = mInitialTravelTime;
                mCurrentClockDiff = currentTimeNanos - curDataTimeNanos - currentTravelTimeNanos;
            } else if (mFixTimeStablizationThreshold < 0) {
                mCurrentClockDiff = mCurrentClockDiff + (currentTimeNanos - sinceBootTimeNanos)
                        - (mPrevUtcTimeNanos - mPrevBootTimeNanos);
                currentTravelTimeNanos = currentTimeNanos - curDataTimeNanos - mCurrentClockDiff;
            }

            mPrevUtcTimeNanos = currentTimeNanos;
            mPrevBootTimeNanos = sinceBootTimeNanos;
            mPrevDataTimeNanos = curDataTimeNanos;
            mFixTimeStablizationThreshold--;
        }
    } else {
        return -1;
    }
    LOC_LOGd("Estimated travel time: %" PRIi64 "", currentTravelTimeNanos);
    return (sinceBootTimeNanos - currentTravelTimeNanos);
}

void ElapsedRealtimeEstimator::reset() {
    mCurrentClockDiff = 0;
    mPrevDataTimeNanos = 0;
    mPrevUtcTimeNanos = 0;
    mPrevBootTimeNanos = 0;
    mFixTimeStablizationThreshold = 5;
}

int64_t ElapsedRealtimeEstimator::getElapsedRealtimeQtimer(int64_t qtimerTicksAtOrigin) {
    struct timespec currentTime;
    int64_t sinceBootTimeNanos;
    int64_t elapsedRealTimeNanos;

    if (getCurrentTime(currentTime, sinceBootTimeNanos)) {
       uint64_t qtimerDiff = 0;
       uint64_t qTimerTickCount = getQTimerTickCount();
       if (qTimerTickCount >= qtimerTicksAtOrigin) {
           qtimerDiff = qTimerTickCount - qtimerTicksAtOrigin;
       }
       LOC_LOGd("sinceBootTimeNanos:%" PRIi64 " qtimerTicksAtOrigin=%" PRIi64 ""
                " qTimerTickCount=%" PRIi64 " qtimerDiff=%" PRIi64 "",
                sinceBootTimeNanos, qtimerTicksAtOrigin, qTimerTickCount, qtimerDiff);
       uint64_t qTimerDiffNanos = qTimerTicksToNanos(double(qtimerDiff));

       /* If the time difference between Qtimer on modem side and Qtimer on AP side
          is greater than one second we assume this is a dual-SoC device such as
          Kona and will try to get Qtimer on modem side and on AP side and
          will adjust our difference accordingly */
       if (qTimerDiffNanos > 1000000000) {
           uint64_t qtimerDelta = getQTimerDeltaNanos();
           if (qTimerDiffNanos >= qtimerDelta) {
               qTimerDiffNanos -= qtimerDelta;
           }
       }

       LOC_LOGd("Qtimer travel time: %" PRIi64 "", qTimerDiffNanos);
       if (sinceBootTimeNanos >= qTimerDiffNanos) {
           elapsedRealTimeNanos = sinceBootTimeNanos - qTimerDiffNanos;
       } else {
           elapsedRealTimeNanos = -1;
       }
    } else {
        elapsedRealTimeNanos = -1;
    }
    return elapsedRealTimeNanos;
}

bool ElapsedRealtimeEstimator::getCurrentTime(
        struct timespec& currentTime, int64_t& sinceBootTimeNanos)
{
    struct timespec sinceBootTime;
    struct timespec sinceBootTimeTest;
    bool clockGetTimeSuccess = false;
    const uint32_t MAX_TIME_DELTA_VALUE_NANOS = 10000;
    const uint32_t MAX_GET_TIME_COUNT = 20;
    /* Attempt to get CLOCK_REALTIME and CLOCK_BOOTIME in succession without an interruption
    or context switch (for up to MAX_GET_TIME_COUNT times) to avoid errors in the calculation */
    for (uint32_t i = 0; i < MAX_GET_TIME_COUNT; i++) {
        if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTime) != 0) {
            break;
        };
        if (clock_gettime(CLOCK_REALTIME, &currentTime) != 0) {
            break;
        }
        if (clock_gettime(CLOCK_BOOTTIME, &sinceBootTimeTest) != 0) {
            break;
        };
        sinceBootTimeNanos = (int64_t)sinceBootTime.tv_sec * 1000000000 + sinceBootTime.tv_nsec;
        int64_t sinceBootTimeTestNanos =
            (int64_t)sinceBootTimeTest.tv_sec * 1000000000 + sinceBootTimeTest.tv_nsec;
        int64_t sinceBootTimeDeltaNanos = sinceBootTimeTestNanos - sinceBootTimeNanos;

        /* sinceBootTime and sinceBootTimeTest should have a close value if there was no
        interruption or context switch between clock_gettime for CLOCK_BOOTIME and
        clock_gettime for CLOCK_REALTIME */
        if (sinceBootTimeDeltaNanos < MAX_TIME_DELTA_VALUE_NANOS) {
            clockGetTimeSuccess = true;
            break;
        } else {
            LOC_LOGd("Delta:%" PRIi64 "ns time too large, retry number #%u...",
                     sinceBootTimeDeltaNanos, i + 1);
        }
    }
    return clockGetTimeSuccess;
}
} // namespace loc_core


code:
/* Copyright (c) 2011-2014, 2016-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.
 *
 */
#ifndef LOC_API_BASE_H
#define LOC_API_BASE_H

#include <stddef.h>
#include <ctype.h>
#include <gps_extended.h>
#include <LocationAPI.h>
#include <MsgTask.h>
#include <LocSharedLock.h>
#include <log_util.h>
#ifdef NO_UNORDERED_SET_OR_MAP
    #include <map>
#else
    #include <unordered_map>
#endif
#include <inttypes.h>
#include <functional>

using namespace loc_util;

namespace loc_core {

class ContextBase;
struct LocApiResponse;
template <typename> struct LocApiResponseData;

int hexcode(char *hexstring, int string_size,
            const char *data, int data_size);
int decodeAddress(char *addr_string, int string_size,
                  const char *data, int data_size);

#define MAX_ADAPTERS          10
#define MAX_FEATURE_LENGTH    100

#define TO_ALL_ADAPTERS(adapters, call)                                \
    for (int i = 0; i < MAX_ADAPTERS && NULL != (adapters)[i]; i++) {  \
        call;                                                          \
    }

#define TO_1ST_HANDLING_ADAPTER(adapters, call)                              \
    for (int i = 0; i <MAX_ADAPTERS && NULL != (adapters)[i] && !(call); i++);

class LocAdapterBase;
struct LocSsrMsg;
struct LocOpenMsg;

typedef struct
{
    uint32_t accumulatedDistance;
    uint32_t numOfBatchedPositions;
} LocApiBatchData;

typedef struct
{
    uint32_t hwId;
} LocApiGeofenceData;

struct LocApiMsg: LocMsg {
    private:
        std::function<void ()> mProcImpl;
        inline virtual void proc() const {
            mProcImpl();
        }
    public:
        inline LocApiMsg(std::function<void ()> procImpl ) :
                         mProcImpl(procImpl) {}
};

class LocApiProxyBase {
public:
    inline LocApiProxyBase() {}
    inline virtual ~LocApiProxyBase() {}
    inline virtual void* getSibling2() { return NULL; }
    inline virtual double getGloRfLoss(uint32_t left,
            uint32_t center, uint32_t right, uint8_t gloFrequency) { return 0.0; }
};

class LocApiBase {
    friend struct LocSsrMsg;
    //LocOpenMsg calls open() which makes it necessary to declare
    //it as a friend
    friend struct LocOpenMsg;
    friend struct LocCloseMsg;
    friend struct LocKillMsg;
    friend class ContextBase;
    static MsgTask* mMsgTask;
    static volatile int32_t mMsgTaskRefCount;
    LocAdapterBase* mLocAdapters[MAX_ADAPTERS];

protected:
    ContextBase *mContext;
    virtual enum loc_api_adapter_err
        open(LOC_API_ADAPTER_EVENT_MASK_T mask);
    virtual enum loc_api_adapter_err
        close();
    LOC_API_ADAPTER_EVENT_MASK_T getEvtMask();
    LOC_API_ADAPTER_EVENT_MASK_T mMask;
    uint32_t mNmeaMask;
    LocApiBase(LOC_API_ADAPTER_EVENT_MASK_T excludedMask,
               ContextBase* context = NULL);
    inline virtual ~LocApiBase() {
        android_atomic_dec(&mMsgTaskRefCount);
        if (nullptr != mMsgTask && 0 == mMsgTaskRefCount) {
            delete mMsgTask;
            mMsgTask = nullptr;
        }
    }
    bool isInSession();
    const LOC_API_ADAPTER_EVENT_MASK_T mExcludedMask;
    bool isMaster();

public:
    inline void sendMsg(const LocMsg* msg) const {
        if (nullptr != mMsgTask) {
            mMsgTask->sendMsg(msg);
        }
    }
    inline void destroy() {
        close();
        struct LocKillMsg : public LocMsg {
            LocApiBase* mLocApi;
            inline LocKillMsg(LocApiBase* locApi) : LocMsg(), mLocApi(locApi) {}
            inline virtual void proc() const {
                delete mLocApi;
            }
        };
        sendMsg(new LocKillMsg(this));
    }

    static bool needReport(const UlpLocation& ulpLocation,
                           enum loc_sess_status status,
                           LocPosTechMask techMask);

    void addAdapter(LocAdapterBase* adapter);
    void removeAdapter(LocAdapterBase* adapter);

    // upward calls
    void handleEngineUpEvent();
    void handleEngineDownEvent();
    void reportPosition(UlpLocation& location,
                        GpsLocationExtended& locationExtended,
                        enum loc_sess_status status,
                        LocPosTechMask loc_technology_mask =
                                  LOC_POS_TECH_MASK_DEFAULT,
                        GnssDataNotification* pDataNotify = nullptr,
                        int msInWeek = -1);
    void reportSv(GnssSvNotification& svNotify);
    void reportSvPolynomial(GnssSvPolynomial &svPolynomial);
    void reportSvEphemeris(GnssSvEphemerisReport &svEphemeris);
    void reportStatus(LocGpsStatusValue status);
    void reportNmea(const char* nmea, int length);
    void reportData(GnssDataNotification& dataNotify, int msInWeek);
    void reportXtraServer(const char* url1, const char* url2,
                          const char* url3, const int maxlength);
    void reportLocationSystemInfo(const LocationSystemInfo& locationSystemInfo);
    void requestXtraData();
    void requestTime();
    void requestLocation();
    void requestATL(int connHandle, LocAGpsType agps_type, LocApnTypeMask apn_type_mask);
    void releaseATL(int connHandle);
    void requestNiNotify(GnssNiNotification &notify, const void* data,
                         const LocInEmergency emergencyState);
    void reportGnssMeasurements(GnssMeasurements& gnssMeasurements, int msInWeek);
    void reportWwanZppFix(LocGpsLocation &zppLoc);
    void reportZppBestAvailableFix(LocGpsLocation &zppLoc, GpsLocationExtended &location_extended,
            LocPosTechMask tech_mask);
    void reportGnssSvIdConfig(const GnssSvIdConfig& config);
    void reportGnssSvTypeConfig(const GnssSvTypeConfig& config);
    void requestOdcpi(OdcpiRequestInfo& request);
    void reportGnssEngEnergyConsumedEvent(uint64_t energyConsumedSinceFirstBoot);
    void reportDeleteAidingDataEvent(GnssAidingData& aidingData);
    void reportKlobucharIonoModel(GnssKlobucharIonoModel& ionoModel);
    void reportGnssAdditionalSystemInfo(GnssAdditionalSystemInfo& additionalSystemInfo);
    void sendNfwNotification(GnssNfwNotification& notification);
    void reportGnssConfig(uint32_t sessionId, const GnssConfig& gnssConfig);
    void reportLatencyInfo(GnssLatencyInfo& gnssLatencyInfo);
    void reportQwesCapabilities
    (
        const std::unordered_map<LocationQwesFeatureType, bool> &featureMap
    );

    void geofenceBreach(size_t count, uint32_t* hwIds, Location& location,
            GeofenceBreachType breachType, uint64_t timestamp);
    void geofenceStatus(GeofenceStatusAvailable available);
    void reportDBTPosition(UlpLocation &location,
                           GpsLocationExtended &locationExtended,
                           enum loc_sess_status status,
                           LocPosTechMask loc_technology_mask);
    void reportLocations(Location* locations, size_t count, BatchingMode batchingMode);
    void reportCompletedTrips(uint32_t accumulated_distance);
    void handleBatchStatusEvent(BatchingStatus batchStatus);

    // downward calls
    virtual void* getSibling();
    virtual LocApiProxyBase* getLocApiProxy();
    virtual void startFix(const LocPosMode& fixCriteria, LocApiResponse* adapterResponse);
    virtual void stopFix(LocApiResponse* adapterResponse);
    virtual void deleteAidingData(const GnssAidingData& data, LocApiResponse* adapterResponse);
    virtual void injectPosition(double latitude, double longitude, float accuracy,
            bool onDemandCpi);
    virtual void injectPosition(const GnssLocationInfoNotification &locationInfo,
            bool onDemandCpi=false);
    virtual void injectPosition(const Location& location, bool onDemandCpi);
    virtual void setTime(LocGpsUtcTime time, int64_t timeReference, int uncertainty);
    virtual void atlOpenStatus(int handle, int is_succ, char* apn, uint32_t apnLen,
            AGpsBearerType bear, LocAGpsType agpsType, LocApnTypeMask mask);
    virtual void atlCloseStatus(int handle, int is_succ);
    virtual LocationError setServerSync(const char* url, int len, LocServerType type);
    virtual LocationError setServerSync(unsigned int ip, int port, LocServerType type);
    virtual void informNiResponse(GnssNiResponse userResponse, const void* passThroughData);
    virtual LocationError setSUPLVersionSync(GnssConfigSuplVersion version);
    virtual enum loc_api_adapter_err setNMEATypesSync(uint32_t typesMask);
    virtual LocationError setLPPConfigSync(GnssConfigLppProfileMask profileMask);
    virtual enum loc_api_adapter_err setSensorPropertiesSync(
            bool gyroBiasVarianceRandomWalk_valid, float gyroBiasVarianceRandomWalk,
            bool accelBiasVarianceRandomWalk_valid, float accelBiasVarianceRandomWalk,
            bool angleBiasVarianceRandomWalk_valid, float angleBiasVarianceRandomWalk,
            bool rateBiasVarianceRandomWalk_valid, float rateBiasVarianceRandomWalk,
            bool velocityBiasVarianceRandomWalk_valid, float velocityBiasVarianceRandomWalk);
    virtual enum loc_api_adapter_err setSensorPerfControlConfigSync(int controlMode,
            int accelSamplesPerBatch, int accelBatchesPerSec, int gyroSamplesPerBatch,
            int gyroBatchesPerSec, int accelSamplesPerBatchHigh, int accelBatchesPerSecHigh,
            int gyroSamplesPerBatchHigh, int gyroBatchesPerSecHigh, int algorithmConfig);
    virtual LocationError
            setAGLONASSProtocolSync(GnssConfigAGlonassPositionProtocolMask aGlonassProtocol);
    virtual LocationError setLPPeProtocolCpSync(GnssConfigLppeControlPlaneMask lppeCP);
    virtual LocationError setLPPeProtocolUpSync(GnssConfigLppeUserPlaneMask lppeUP);
    virtual GnssConfigSuplVersion convertSuplVersion(const uint32_t suplVersion);
    virtual GnssConfigLppeControlPlaneMask convertLppeCp(const uint32_t lppeControlPlaneMask);
    virtual GnssConfigLppeUserPlaneMask convertLppeUp(const uint32_t lppeUserPlaneMask);
    virtual LocationError setEmergencyExtensionWindowSync(const uint32_t emergencyExtensionSeconds);
    virtual void setMeasurementCorrections(
            const GnssMeasurementCorrections& gnssMeasurementCorrections);

    virtual void getWwanZppFix();
    virtual void getBestAvailableZppFix();
    virtual LocationError setGpsLockSync(GnssConfigGpsLock lock);
    virtual void requestForAidingData(GnssAidingDataSvMask svDataMask);
    virtual LocationError setXtraVersionCheckSync(uint32_t check);
    /* Requests for SV/Constellation Control */
    virtual LocationError setBlacklistSvSync(const GnssSvIdConfig& config);
    virtual void setBlacklistSv(const GnssSvIdConfig& config,
                                LocApiResponse *adapterResponse=nullptr);
    virtual void getBlacklistSv();
    virtual void setConstellationControl(const GnssSvTypeConfig& config,
                                         LocApiResponse *adapterResponse=nullptr);
    virtual void getConstellationControl();
    virtual void resetConstellationControl(LocApiResponse *adapterResponse=nullptr);

    virtual void setConstrainedTuncMode(bool enabled,
                                        float tuncConstraint,
                                        uint32_t energyBudget,
                                        LocApiResponse* adapterResponse=nullptr);
    virtual void setPositionAssistedClockEstimatorMode(bool enabled,
                                                       LocApiResponse* adapterResponse=nullptr);
    virtual void getGnssEnergyConsumed();

    virtual void addGeofence(uint32_t clientId, const GeofenceOption& options,
            const GeofenceInfo& info, LocApiResponseData<LocApiGeofenceData>* adapterResponseData);
    virtual void removeGeofence(uint32_t hwId, uint32_t clientId, LocApiResponse* adapterResponse);
    virtual void pauseGeofence(uint32_t hwId, uint32_t clientId, LocApiResponse* adapterResponse);
    virtual void resumeGeofence(uint32_t hwId, uint32_t clientId, LocApiResponse* adapterResponse);
    virtual void modifyGeofence(uint32_t hwId, uint32_t clientId, const GeofenceOption& options,
             LocApiResponse* adapterResponse);

    virtual void startTimeBasedTracking(const TrackingOptions& options,
             LocApiResponse* adapterResponse);
    virtual void stopTimeBasedTracking(LocApiResponse* adapterResponse);
    virtual void startDistanceBasedTracking(uint32_t sessionId, const LocationOptions& options,
             LocApiResponse* adapterResponse);
    virtual void stopDistanceBasedTracking(uint32_t sessionId,
             LocApiResponse* adapterResponse = nullptr);
    virtual void startBatching(uint32_t sessionId, const LocationOptions& options,
            uint32_t accuracy, uint32_t timeout, LocApiResponse* adapterResponse);
    virtual void stopBatching(uint32_t sessionId, LocApiResponse* adapterResponse);
    virtual LocationError startOutdoorTripBatchingSync(uint32_t tripDistance,
            uint32_t tripTbf, uint32_t timeout);
    virtual void startOutdoorTripBatching(uint32_t tripDistance,
            uint32_t tripTbf, uint32_t timeout, LocApiResponse* adapterResponse);
    virtual void reStartOutdoorTripBatching(uint32_t ongoingTripDistance,
            uint32_t ongoingTripInterval, uint32_t batchingTimeout,
            LocApiResponse* adapterResponse);
    virtual LocationError stopOutdoorTripBatchingSync(bool deallocBatchBuffer = true);
    virtual void stopOutdoorTripBatching(bool deallocBatchBuffer = true,
            LocApiResponse* adapterResponse = nullptr);
    virtual LocationError getBatchedLocationsSync(size_t count);
    virtual void getBatchedLocations(size_t count, LocApiResponse* adapterResponse);
    virtual LocationError getBatchedTripLocationsSync(size_t count, uint32_t accumulatedDistance);
    virtual void getBatchedTripLocations(size_t count, uint32_t accumulatedDistance,
            LocApiResponse* adapterResponse);
    virtual LocationError queryAccumulatedTripDistanceSync(uint32_t &accumulated_trip_distance,
            uint32_t &numOfBatchedPositions);
    virtual void queryAccumulatedTripDistance(
            LocApiResponseData<LocApiBatchData>* adapterResponseData);
    virtual void setBatchSize(size_t size);
    virtual void setTripBatchSize(size_t size);
    virtual void addToCallQueue(LocApiResponse* adapterResponse);

    void updateEvtMask();
    void updateNmeaMask(uint32_t mask);

    virtual void updateSystemPowerState(PowerStateType systemPowerState);

    virtual void configRobustLocation(bool enable, bool enableForE911,
                                      LocApiResponse* adapterResponse=nullptr);
    virtual void getRobustLocationConfig(uint32_t sessionId, LocApiResponse* adapterResponse);
    virtual void configMinGpsWeek(uint16_t minGpsWeek,
                                  LocApiResponse* adapterResponse=nullptr);
    virtual void getMinGpsWeek(uint32_t sessionId, LocApiResponse* adapterResponse);

    virtual LocationError setParameterSync(const GnssConfig & gnssConfig);
    virtual void getParameter(uint32_t sessionId, GnssConfigFlagsMask flags,
                              LocApiResponse* adapterResponse=nullptr);

    virtual void configConstellationMultiBand(const GnssSvTypeConfig& secondaryBandConfig,
                                              LocApiResponse* adapterResponse=nullptr);
    virtual void getConstellationMultiBandConfig(uint32_t sessionId,
                                        LocApiResponse* adapterResponse=nullptr);
};

class ElapsedRealtimeEstimator {
private:
    int64_t mCurrentClockDiff;
    int64_t mPrevUtcTimeNanos;
    int64_t mPrevBootTimeNanos;
    int64_t mFixTimeStablizationThreshold;
    int64_t mInitialTravelTime;
    int64_t mPrevDataTimeNanos;
public:

    ElapsedRealtimeEstimator(int64_t travelTimeNanosEstimate):
            mInitialTravelTime(travelTimeNanosEstimate) {reset();}
    int64_t getElapsedRealtimeEstimateNanos(int64_t curDataTimeNanos,
            bool isCurDataTimeTrustable, int64_t tbf);
    inline int64_t getElapsedRealtimeUncNanos() { return 5000000;}
    void reset();

    static int64_t getElapsedRealtimeQtimer(int64_t qtimerTicksAtOrigin);
    static bool getCurrentTime(struct timespec& currentTime, int64_t& sinceBootTimeNanos);
};

typedef LocApiBase* (getLocApi_t)(LOC_API_ADAPTER_EVENT_MASK_T exMask,
                                  ContextBase *context);

} // namespace loc_core

#endif //LOC_API_BASE_H

license: unknown


code:
/* Copyright (c) 2011-2014, 2016-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_NDEBUG 0
#define LOG_TAG "LocSvc_Ctx"

#include <cutils/sched_policy.h>
#include <unistd.h>
#include <LocContext.h>
#include <msg_q.h>
#include <log_util.h>
#include <loc_log.h>

namespace loc_core {

const MsgTask* LocContext::mMsgTask = NULL;
ContextBase* LocContext::mContext = NULL;
// the name must be shorter than 15 chars
const char* LocContext::mLocationHalName = "Loc_hal_worker";
#ifndef USE_GLIB
const char* LocContext::mLBSLibName = "liblbs_core.so";
#else
const char* LocContext::mLBSLibName = "liblbs_core.so.1";
#endif

pthread_mutex_t LocContext::mGetLocContextMutex = PTHREAD_MUTEX_INITIALIZER;

const MsgTask* LocContext::getMsgTask(const char* name)
{
    if (NULL == mMsgTask) {
        mMsgTask = new MsgTask(name);
    }
    return mMsgTask;
}

ContextBase* LocContext::getLocContext(const char* name)
{
    pthread_mutex_lock(&LocContext::mGetLocContextMutex);
    LOC_LOGD("%s:%d]: querying ContextBase with tCreator", __func__, __LINE__);
    if (NULL == mContext) {
        LOC_LOGD("%s:%d]: creating msgTask with tCreator", __func__, __LINE__);
        const MsgTask* msgTask = getMsgTask(name);
        mContext = new LocContext(msgTask);
    }
    pthread_mutex_unlock(&LocContext::mGetLocContextMutex);

    return mContext;
}

void LocContext :: injectFeatureConfig(ContextBase *curContext)
{
    LOC_LOGD("%s:%d]: Calling LBSProxy (%p) to inject feature config",
             __func__, __LINE__, ((LocContext *)curContext)->mLBSProxy);
    ((LocContext *)curContext)->mLBSProxy->injectFeatureConfig(curContext);
}

LocContext::LocContext(const MsgTask* msgTask) :
    ContextBase(msgTask, 0, mLBSLibName)
{
}

}


code:
/* Copyright (c) 2011-2014, 2017-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.
 *
 */
#ifndef __LOC_CONTEXT__
#define __LOC_CONTEXT__

#include <stdbool.h>
#include <ctype.h>
#include <dlfcn.h>
#include <ContextBase.h>

namespace loc_core {

class LocContext : public ContextBase {
    static const MsgTask* mMsgTask;
    static ContextBase* mContext;
    static const MsgTask* getMsgTask(const char* name);
    static pthread_mutex_t mGetLocContextMutex;

protected:
    LocContext(const MsgTask* msgTask);
    inline virtual ~LocContext() {}

public:
    static const char* mLBSLibName;
    static const char* mLocationHalName;

    static ContextBase* getLocContext(const char* name);

    static void injectFeatureConfig(ContextBase *context);
};

}

#endif //__LOC_CONTEXT__