code:
/* Copyright (c) 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.
 *
 */

#define LOG_NDEBUG 0
#define LOG_TAG "LocSvc_MeasurementAPIClient"

#include <log_util.h>
#include <loc_cfg.h>
#include <inttypes.h>

#include "LocationUtil.h"
#include "MeasurementAPIClient.h"
#include <loc_misc_utils.h>

namespace android {
namespace hardware {
namespace gnss {
namespace V2_0 {
namespace implementation {

using ::android::hardware::gnss::V1_0::IGnssMeasurement;
using ::android::hardware::gnss::V2_0::IGnssMeasurementCallback;

static void convertGnssData(GnssMeasurementsNotification& in,
        V1_0::IGnssMeasurementCallback::GnssData& out);
static void convertGnssData_1_1(GnssMeasurementsNotification& in,
        V1_1::IGnssMeasurementCallback::GnssData& out);
static void convertGnssData_2_0(GnssMeasurementsNotification& in,
        V2_0::IGnssMeasurementCallback::GnssData& out);
static void convertGnssMeasurement(GnssMeasurementsData& in,
        V1_0::IGnssMeasurementCallback::GnssMeasurement& out);
static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out);
static void convertGnssMeasurementsCodeType(GnssMeasurementsCodeType& in,
        ::android::hardware::hidl_string& out);
static void convertElapsedRealtimeNanos(GnssMeasurementsNotification& in,
        ::android::hardware::gnss::V2_0::ElapsedRealtime& elapsedRealtimeNanos);

MeasurementAPIClient::MeasurementAPIClient() :
    mGnssMeasurementCbIface(nullptr),
    mGnssMeasurementCbIface_1_1(nullptr),
    mGnssMeasurementCbIface_2_0(nullptr),
    mTracking(false)
{
    LOC_LOGD("%s]: ()", __FUNCTION__);
}

MeasurementAPIClient::~MeasurementAPIClient()
{
    LOC_LOGD("%s]: ()", __FUNCTION__);
}

void MeasurementAPIClient::clearInterfaces()
{
    mGnssMeasurementCbIface = nullptr;
    mGnssMeasurementCbIface_1_1 = nullptr;
    mGnssMeasurementCbIface_2_0 = nullptr;
}

// for GpsInterface
Return<IGnssMeasurement::GnssMeasurementStatus>
MeasurementAPIClient::measurementSetCallback(const sp<V1_0::IGnssMeasurementCallback>& callback)
{
    LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback);

    mMutex.lock();
    clearInterfaces();
    mGnssMeasurementCbIface = callback;
    mMutex.unlock();

    return startTracking();
}

Return<IGnssMeasurement::GnssMeasurementStatus>
MeasurementAPIClient::measurementSetCallback_1_1(
        const sp<V1_1::IGnssMeasurementCallback>& callback,
        GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
{
    LOC_LOGD("%s]: (%p) (powermode: %d) (tbm: %d)",
            __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement);

    mMutex.lock();
    clearInterfaces();
    mGnssMeasurementCbIface_1_1 = callback;
    mMutex.unlock();

    return startTracking(powerMode, timeBetweenMeasurement);
}

Return<IGnssMeasurement::GnssMeasurementStatus>
MeasurementAPIClient::measurementSetCallback_2_0(
    const sp<V2_0::IGnssMeasurementCallback>& callback,
    GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
{
    LOC_LOGD("%s]: (%p) (powermode: %d) (tbm: %d)",
        __FUNCTION__, &callback, (int)powerMode, timeBetweenMeasurement);

    mMutex.lock();
    clearInterfaces();
    mGnssMeasurementCbIface_2_0 = callback;
    mMutex.unlock();

    return startTracking(powerMode, timeBetweenMeasurement);
}

Return<IGnssMeasurement::GnssMeasurementStatus>
MeasurementAPIClient::startTracking(
        GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
{
    LocationCallbacks locationCallbacks;
    memset(&locationCallbacks, 0, sizeof(LocationCallbacks));
    locationCallbacks.size = sizeof(LocationCallbacks);

    locationCallbacks.trackingCb = nullptr;
    locationCallbacks.batchingCb = nullptr;
    locationCallbacks.geofenceBreachCb = nullptr;
    locationCallbacks.geofenceStatusCb = nullptr;
    locationCallbacks.gnssLocationInfoCb = nullptr;
    locationCallbacks.gnssNiCb = nullptr;
    locationCallbacks.gnssSvCb = nullptr;
    locationCallbacks.gnssNmeaCb = nullptr;

    locationCallbacks.gnssMeasurementsCb = nullptr;
    if (mGnssMeasurementCbIface_2_0 != nullptr ||
        mGnssMeasurementCbIface_1_1 != nullptr ||
        mGnssMeasurementCbIface != nullptr) {
        locationCallbacks.gnssMeasurementsCb =
            [this](GnssMeasurementsNotification gnssMeasurementsNotification) {
                onGnssMeasurementsCb(gnssMeasurementsNotification);
            };
    }

    locAPISetCallbacks(locationCallbacks);

    TrackingOptions options = {};
    memset(&options, 0, sizeof(TrackingOptions));
    options.size = sizeof(TrackingOptions);
    options.minInterval = 1000;
    options.mode = GNSS_SUPL_MODE_STANDALONE;
    if (GNSS_POWER_MODE_INVALID != powerMode) {
        options.powerMode = powerMode;
        options.tbm = timeBetweenMeasurement;
    }

    mTracking = true;
    LOC_LOGD("%s]: start tracking session", __FUNCTION__);
    locAPIStartTracking(options);
    return IGnssMeasurement::GnssMeasurementStatus::SUCCESS;
}

// for GpsMeasurementInterface
void MeasurementAPIClient::measurementClose() {
    LOC_LOGD("%s]: ()", __FUNCTION__);
    mTracking = false;
    locAPIStopTracking();
}

// callbacks
void MeasurementAPIClient::onGnssMeasurementsCb(
        GnssMeasurementsNotification gnssMeasurementsNotification)
{
    LOC_LOGD("%s]: (count: %u active: %d)",
            __FUNCTION__, gnssMeasurementsNotification.count, mTracking);
    if (mTracking) {
        mMutex.lock();
        sp<V1_0::IGnssMeasurementCallback> gnssMeasurementCbIface = nullptr;
        sp<V1_1::IGnssMeasurementCallback> gnssMeasurementCbIface_1_1 = nullptr;
        sp<V2_0::IGnssMeasurementCallback> gnssMeasurementCbIface_2_0 = nullptr;
        if (mGnssMeasurementCbIface_2_0 != nullptr) {
            gnssMeasurementCbIface_2_0 = mGnssMeasurementCbIface_2_0;
        } else if (mGnssMeasurementCbIface_1_1 != nullptr) {
            gnssMeasurementCbIface_1_1 = mGnssMeasurementCbIface_1_1;
        } else if (mGnssMeasurementCbIface != nullptr) {
            gnssMeasurementCbIface = mGnssMeasurementCbIface;
        }
        mMutex.unlock();

        if (gnssMeasurementCbIface_2_0 != nullptr) {
            V2_0::IGnssMeasurementCallback::GnssData gnssData;
            convertGnssData_2_0(gnssMeasurementsNotification, gnssData);
            auto r = gnssMeasurementCbIface_2_0->gnssMeasurementCb_2_0(gnssData);
            if (!r.isOk()) {
                LOC_LOGE("%s] Error from gnssMeasurementCb description=%s",
                    __func__, r.description().c_str());
            }
        } else if (gnssMeasurementCbIface_1_1 != nullptr) {
            V1_1::IGnssMeasurementCallback::GnssData gnssData;
            convertGnssData_1_1(gnssMeasurementsNotification, gnssData);
            auto r = gnssMeasurementCbIface_1_1->gnssMeasurementCb(gnssData);
            if (!r.isOk()) {
                LOC_LOGE("%s] Error from gnssMeasurementCb description=%s",
                    __func__, r.description().c_str());
            }
        } else if (gnssMeasurementCbIface != nullptr) {
            V1_0::IGnssMeasurementCallback::GnssData gnssData;
            convertGnssData(gnssMeasurementsNotification, gnssData);
            auto r = gnssMeasurementCbIface->GnssMeasurementCb(gnssData);
            if (!r.isOk()) {
                LOC_LOGE("%s] Error from GnssMeasurementCb description=%s",
                    __func__, r.description().c_str());
            }
        }
    }
}

static void convertGnssMeasurement(GnssMeasurementsData& in,
        V1_0::IGnssMeasurementCallback::GnssMeasurement& out)
{
    memset(&out, 0, sizeof(out));
    if (in.flags & GNSS_MEASUREMENTS_DATA_SIGNAL_TO_NOISE_RATIO_BIT)
        out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_SNR;
    if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT)
        out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_FREQUENCY;
    if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_CYCLES_BIT)
        out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_CYCLES;
    if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_BIT)
        out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE;
    if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_UNCERTAINTY_BIT)
        out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY;
    if (in.flags & GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT)
        out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL;
    convertGnssSvid(in, out.svid);
    convertGnssConstellationType(in.svType, out.constellation);
    out.timeOffsetNs = in.timeOffsetNs;
    if (in.stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT)
        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK;
    if (in.stateMask & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT)
        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC;
    if (in.stateMask & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT)
        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC;
    if (in.stateMask & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT)
        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED;
    if (in.stateMask & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT)
        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS;
    if (in.stateMask & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT)
        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC;
    if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT)
        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC;
    if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT)
        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED;
    if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT)
        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC;
    if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT)
        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC;
    if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT)
        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK;
    if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT)
        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK;
    if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT)
        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC;
    if (in.stateMask &  GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT)
        out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC;
    out.receivedSvTimeInNs = in.receivedSvTimeNs;
    out.receivedSvTimeUncertaintyInNs = in.receivedSvTimeUncertaintyNs;
    out.cN0DbHz = in.carrierToNoiseDbHz;
    out.pseudorangeRateMps = in.pseudorangeRateMps;
    out.pseudorangeRateUncertaintyMps = in.pseudorangeRateUncertaintyMps;
    if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
        out.accumulatedDeltaRangeState |=
            IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
    if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
        out.accumulatedDeltaRangeState |=
            IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET;
    if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT)
        out.accumulatedDeltaRangeState |=
            IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP;
    out.accumulatedDeltaRangeM = in.adrMeters;
    out.accumulatedDeltaRangeUncertaintyM = in.adrUncertaintyMeters;
    out.carrierFrequencyHz = in.carrierFrequencyHz;
    out.carrierCycles = in.carrierCycles;
    out.carrierPhase = in.carrierPhase;
    out.carrierPhaseUncertainty = in.carrierPhaseUncertainty;
    uint8_t indicator =
        static_cast<uint8_t>(IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN);
    if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_PRESENT)
        indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_PRESENT;
    if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_NOT_PRESENT)
        indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATIOR_NOT_PRESENT;
    out.multipathIndicator =
        static_cast<IGnssMeasurementCallback::GnssMultipathIndicator>(indicator);
    out.snrDb = in.signalToNoiseRatioDb;
    out.agcLevelDb = in.agcLevelDb;
}

static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out)
{
    memset(&out, 0, sizeof(out));
    if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT)
        out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_LEAP_SECOND;
    if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_UNCERTAINTY_BIT)
        out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_TIME_UNCERTAINTY;
    if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT)
        out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_FULL_BIAS;
    if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT)
        out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS;
    if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT)
        out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS_UNCERTAINTY;
    if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT)
        out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT;
    if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT)
        out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT_UNCERTAINTY;
    out.leapSecond = in.leapSecond;
    out.timeNs = in.timeNs;
    out.timeUncertaintyNs = in.timeUncertaintyNs;
    out.fullBiasNs = in.fullBiasNs;
    out.biasNs = in.biasNs;
    out.biasUncertaintyNs = in.biasUncertaintyNs;
    out.driftNsps = in.driftNsps;
    out.driftUncertaintyNsps = in.driftUncertaintyNsps;
    out.hwClockDiscontinuityCount = in.hwClockDiscontinuityCount;
}

static void convertGnssData(GnssMeasurementsNotification& in,
        V1_0::IGnssMeasurementCallback::GnssData& out)
{
    memset(&out, 0, sizeof(out));
    out.measurementCount = in.count;
    if (out.measurementCount > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) {
        LOC_LOGW("%s]: Too many measurement %u. Clamps to %d.",
                __FUNCTION__,  out.measurementCount, V1_0::GnssMax::SVS_COUNT);
        out.measurementCount = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT);
    }
    for (size_t i = 0; i < out.measurementCount; i++) {
        convertGnssMeasurement(in.measurements[i], out.measurements[i]);
    }
    convertGnssClock(in.clock, out.clock);
}

static void convertGnssData_1_1(GnssMeasurementsNotification& in,
        V1_1::IGnssMeasurementCallback::GnssData& out)
{
    memset(&out, 0, sizeof(out));
    out.measurements.resize(in.count);
    for (size_t i = 0; i < in.count; i++) {
        convertGnssMeasurement(in.measurements[i], out.measurements[i].v1_0);
        if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
            out.measurements[i].accumulatedDeltaRangeState |=
            IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
        if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
            out.measurements[i].accumulatedDeltaRangeState |=
            IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET;
        if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT)
            out.measurements[i].accumulatedDeltaRangeState |=
            IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP;
        if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_HALF_CYCLE_RESOLVED_BIT)
            out.measurements[i].accumulatedDeltaRangeState |=
            IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_HALF_CYCLE_RESOLVED;
    }
    convertGnssClock(in.clock, out.clock);
}

static void convertGnssData_2_0(GnssMeasurementsNotification& in,
        V2_0::IGnssMeasurementCallback::GnssData& out)
{
    memset(&out, 0, sizeof(out));
    out.measurements.resize(in.count);
    for (size_t i = 0; i < in.count; i++) {
        convertGnssMeasurement(in.measurements[i], out.measurements[i].v1_1.v1_0);
        convertGnssConstellationType(in.measurements[i].svType, out.measurements[i].constellation);
        convertGnssMeasurementsCodeType(in.measurements[i].codeType, out.measurements[i].codeType);
        if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT)
            out.measurements[i].v1_1.accumulatedDeltaRangeState |=
            IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID;
        if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT)
            out.measurements[i].v1_1.accumulatedDeltaRangeState |=
            IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET;
        if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT)
            out.measurements[i].v1_1.accumulatedDeltaRangeState |=
            IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP;
        if (in.measurements[i].adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_HALF_CYCLE_RESOLVED_BIT)
            out.measurements[i].v1_1.accumulatedDeltaRangeState |=
            IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_HALF_CYCLE_RESOLVED;
        if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT)
            out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK;
        if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT)
            out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC;
        if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT)
            out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC;
        if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT)
            out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED;
        if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT)
            out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS;
        if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT)
            out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC;
        if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT)
            out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC;
        if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT)
            out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED;
        if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT)
            out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC;
        if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT)
            out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC;
        if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT)
            out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK;
        if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT)
            out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK;
        if (in.measurements[i].stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT)
            out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC;
        if (in.measurements[i].stateMask &  GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT)
            out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC;
        if (in.measurements[i].stateMask &  GNSS_MEASUREMENTS_STATE_TOW_KNOWN_BIT)
            out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_KNOWN;
        if (in.measurements[i].stateMask &  GNSS_MEASUREMENTS_STATE_GLO_TOD_KNOWN_BIT)
            out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_KNOWN;
        if (in.measurements[i].stateMask &  GNSS_MEASUREMENTS_STATE_2ND_CODE_LOCK_BIT)
            out.measurements[i].state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_2ND_CODE_LOCK;
    }
    convertGnssClock(in.clock, out.clock);
    convertElapsedRealtimeNanos(in, out.elapsedRealtime);
}

static void convertElapsedRealtimeNanos(GnssMeasurementsNotification& in,
        ::android::hardware::gnss::V2_0::ElapsedRealtime& elapsedRealtime)
{
    if (in.clock.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_ELAPSED_REAL_TIME_BIT) {
        elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS;
        elapsedRealtime.timestampNs = in.clock.elapsedRealTime;
        elapsedRealtime.flags |= V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS;
        elapsedRealtime.timeUncertaintyNs = in.clock.elapsedRealTimeUnc;
        LOC_LOGd("elapsedRealtime.timestampNs=%" PRIi64 ""
                 " elapsedRealtime.timeUncertaintyNs=%" PRIi64 " elapsedRealtime.flags=0x%X",
                 elapsedRealtime.timestampNs,
                 elapsedRealtime.timeUncertaintyNs, elapsedRealtime.flags);
    }
}

static void convertGnssMeasurementsCodeType(GnssMeasurementsCodeType& in,
        ::android::hardware::hidl_string& out)
{
    switch(in) {
        case GNSS_MEASUREMENTS_CODE_TYPE_A:
            out = "A";
            break;
        case GNSS_MEASUREMENTS_CODE_TYPE_B:
            out = "B";
            break;
        case GNSS_MEASUREMENTS_CODE_TYPE_C:
            out = "C";
            break;
        case GNSS_MEASUREMENTS_CODE_TYPE_I:
            out = "I";
            break;
        case GNSS_MEASUREMENTS_CODE_TYPE_L:
            out = "L";
            break;
        case GNSS_MEASUREMENTS_CODE_TYPE_M:
            out = "M";
            break;
        case GNSS_MEASUREMENTS_CODE_TYPE_P:
            out = "P";
            break;
        case GNSS_MEASUREMENTS_CODE_TYPE_Q:
            out = "Q";
            break;
        case GNSS_MEASUREMENTS_CODE_TYPE_S:
            out = "S";
            break;
        case GNSS_MEASUREMENTS_CODE_TYPE_W:
            out = "W";
            break;
        case GNSS_MEASUREMENTS_CODE_TYPE_X:
            out = "X";
            break;
        case GNSS_MEASUREMENTS_CODE_TYPE_Y:
            out = "Y";
            break;
        case GNSS_MEASUREMENTS_CODE_TYPE_Z:
            out = "Z";
            break;
        case GNSS_MEASUREMENTS_CODE_TYPE_N:
            out = "N";
            break;
        default:
            out = "UNKNOWN";
    }
}

}  // namespace implementation
}  // namespace V2_0
}  // namespace gnss
}  // namespace hardware
}  // namespace android


code:
/* Copyright (c) 2017-2019, 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 MEASUREMENT_API_CLINET_H
#define MEASUREMENT_API_CLINET_H

#include <mutex>
#include <android/hardware/gnss/2.0/IGnssMeasurement.h>
//#include <android/hardware/gnss/1.1/IGnssMeasurementCallback.h>
#include <LocationAPIClientBase.h>
#include <hidl/Status.h>
#include <gps_extended_c.h>

namespace android {
namespace hardware {
namespace gnss {
namespace V2_0 {
namespace implementation {

using ::android::sp;

class MeasurementAPIClient : public LocationAPIClientBase
{
public:
    MeasurementAPIClient();
    MeasurementAPIClient(const MeasurementAPIClient&) = delete;
    MeasurementAPIClient& operator=(const MeasurementAPIClient&) = delete;

    // for GpsMeasurementInterface
    Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback(
            const sp<V1_0::IGnssMeasurementCallback>& callback);
    Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback_1_1(
            const sp<V1_1::IGnssMeasurementCallback>& callback,
            GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
            uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
    Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback_2_0(
            const sp<V2_0::IGnssMeasurementCallback>& callback,
            GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
            uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);
    void measurementClose();
    Return<IGnssMeasurement::GnssMeasurementStatus> startTracking(
            GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID,
            uint32_t timeBetweenMeasurement = GPS_DEFAULT_FIX_INTERVAL_MS);

    // callbacks we are interested in
    void onGnssMeasurementsCb(GnssMeasurementsNotification gnssMeasurementsNotification) final;

private:
    virtual ~MeasurementAPIClient();

    std::mutex mMutex;
    sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface;
    sp<V1_1::IGnssMeasurementCallback> mGnssMeasurementCbIface_1_1;
    sp<V2_0::IGnssMeasurementCallback> mGnssMeasurementCbIface_2_0;
    bool mTracking;
    void clearInterfaces();
};

}  // namespace implementation
}  // namespace V2_0
}  // namespace gnss
}  // namespace hardware
}  // namespace android
#endif // MEASUREMENT_API_CLINET_H

license: unknown


code:
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Not a Contribution
 */
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "android.hardware.gnss@2.0-service-qti"

#include <android/hardware/gnss/2.0/IGnss.h>
#include <hidl/LegacySupport.h>
#include "loc_cfg.h"
#include "loc_misc_utils.h"

extern "C" {
#include "vndfwk-detect.h"
}

#ifdef ARCH_ARM_32
#define DEFAULT_HW_BINDER_MEM_SIZE 65536
#endif

using android::hardware::gnss::V2_0::IGnss;

using android::hardware::configureRpcThreadpool;
using android::hardware::registerPassthroughServiceImplementation;
using android::hardware::joinRpcThreadpool;

using android::status_t;
using android::OK;

typedef int vendorEnhancedServiceMain(int /* argc */, char* /* argv */ []);

int main() {

    ALOGI("%s", __FUNCTION__);

    int vendorInfo = getVendorEnhancedInfo();
    bool vendorEnhanced = ( 1 == vendorInfo || 3 == vendorInfo );
    setVendorEnhanced(vendorEnhanced);

#ifdef ARCH_ARM_32
    android::hardware::ProcessState::initWithMmapSize((size_t)(DEFAULT_HW_BINDER_MEM_SIZE));
#endif
    configureRpcThreadpool(1, true);
    status_t status;

    status = registerPassthroughServiceImplementation<IGnss>();
    if (status == OK) {
    #ifdef LOC_HIDL_VERSION
        #define VENDOR_ENHANCED_LIB "vendor.qti.gnss@" LOC_HIDL_VERSION "-service.so"

        void* libHandle = NULL;
        vendorEnhancedServiceMain* vendorEnhancedMainMethod = (vendorEnhancedServiceMain*)
                dlGetSymFromLib(libHandle, VENDOR_ENHANCED_LIB, "main");
        if (NULL != vendorEnhancedMainMethod) {
            (*vendorEnhancedMainMethod)(0, NULL);
        }
    #else
        ALOGI("LOC_HIDL_VERSION not defined.");
    #endif
        joinRpcThreadpool();
    } else {
        ALOGE("Error while registering IGnss 2.0 service: %d", status);
    }

    return 0;
}


code:
/*
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 * Not a Contribution
 */
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "LocSvc_AGnssInterface"

#include <log_util.h>
#include "Gnss.h"
#include "AGnss.h"

namespace android {
namespace hardware {
namespace gnss {
namespace V2_1 {
namespace implementation {

static AGnss* spAGnss = nullptr;

AGnss::AGnss(Gnss* gnss) : mGnss(gnss), mType(LOC_AGPS_TYPE_INVALID) {
    spAGnss = this;
}

AGnss::~AGnss() {
    spAGnss = nullptr;
}

void AGnss::agnssStatusIpV4Cb(AGnssExtStatusIpV4 status) {
    if (nullptr != spAGnss) {
        spAGnss->statusCb(status.type, status.status);
    }
}

void AGnss::statusCb(AGpsExtType type, LocAGpsStatusValue status) {

    V2_0::IAGnssCallback::AGnssType  aType;
    IAGnssCallback::AGnssStatusValue aStatus;

    // cache the AGps Type
    mType = type;

    switch (type) {
    case LOC_AGPS_TYPE_SUPL:
        aType = IAGnssCallback::AGnssType::SUPL;
        break;
    case LOC_AGPS_TYPE_SUPL_ES:
        aType = IAGnssCallback::AGnssType::SUPL_EIMS;
        break;
    default:
        LOC_LOGE("invalid type: %d", type);
        return;
    }

    switch (status) {
    case LOC_GPS_REQUEST_AGPS_DATA_CONN:
        aStatus = IAGnssCallback::AGnssStatusValue::REQUEST_AGNSS_DATA_CONN;
        break;
    case LOC_GPS_RELEASE_AGPS_DATA_CONN:
        aStatus = IAGnssCallback::AGnssStatusValue::RELEASE_AGNSS_DATA_CONN;
        break;
    case LOC_GPS_AGPS_DATA_CONNECTED:
        aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONNECTED;
        break;
    case LOC_GPS_AGPS_DATA_CONN_DONE:
        aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_DONE;
        break;
    case LOC_GPS_AGPS_DATA_CONN_FAILED:
        aStatus = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_FAILED;
        break;
    default:
        LOC_LOGE("invalid status: %d", status);
        return;
    }

    if (mAGnssCbIface != nullptr) {
        auto r = mAGnssCbIface->agnssStatusCb(aType, aStatus);
        if (!r.isOk()) {
            LOC_LOGw("Error invoking AGNSS status cb %s", r.description().c_str());
        }
    }
    else {
        LOC_LOGw("setCallback has not been called yet");
    }
}

Return<void> AGnss::setCallback(const sp<V2_0::IAGnssCallback>& callback) {

    if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
        LOC_LOGE("Null GNSS interface");
        return Void();
    }

    // Save the interface
    mAGnssCbIface = callback;

    AgpsCbInfo cbInfo = {};
    cbInfo.statusV4Cb = (void*)agnssStatusIpV4Cb;
    cbInfo.atlType = AGPS_ATL_TYPE_SUPL | AGPS_ATL_TYPE_SUPL_ES;

    mGnss->getGnssInterface()->agpsInit(cbInfo);
    return Void();
}

Return<bool> AGnss::dataConnClosed() {

    if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
        LOC_LOGE("Null GNSS interface");
        return false;
    }

    mGnss->getGnssInterface()->agpsDataConnClosed(LOC_AGPS_TYPE_SUPL);
    return true;
}

Return<bool> AGnss::dataConnFailed() {

    if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
        LOC_LOGE("Null GNSS interface");
        return false;
    }

    mGnss->getGnssInterface()->agpsDataConnFailed(LOC_AGPS_TYPE_SUPL);
    return true;
}

Return<bool> AGnss::dataConnOpen(uint64_t /*networkHandle*/, const hidl_string& apn,
        V2_0::IAGnss::ApnIpType apnIpType) {

    if (mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
        LOC_LOGE("Null GNSS interface");
        return false;
    }

    std::string apnString(apn.c_str());
    // During Emergency SUPL, an apn name of "sos" means that no
    // apn was found, like in the simless case, so apn is cleared
    if (LOC_AGPS_TYPE_SUPL_ES == mType && "sos" == apnString) {
        LOC_LOGD("dataConnOpen APN name = [sos] cleared");
        apnString.clear();
    }

    LOC_LOGD("dataConnOpen APN name = [%s]", apnString.c_str());

    AGpsBearerType bearerType;
    switch (apnIpType) {
    case IAGnss::ApnIpType::IPV4:
        bearerType = AGPS_APN_BEARER_IPV4;
        break;
    case IAGnss::ApnIpType::IPV6:
        bearerType = AGPS_APN_BEARER_IPV6;
        break;
    case IAGnss::ApnIpType::IPV4V6:
        bearerType = AGPS_APN_BEARER_IPV4V6;
        break;
    default:
        bearerType = AGPS_APN_BEARER_IPV4;
        break;
    }

    mGnss->getGnssInterface()->agpsDataConnOpen(
        LOC_AGPS_TYPE_SUPL, apnString.c_str(), apnString.size(), (int)bearerType);
    return true;
}

Return<bool> AGnss::setServer(V2_0::IAGnssCallback::AGnssType type,
                              const hidl_string& hostname,
                              int32_t port) {
    if (mGnss == nullptr) {
        LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
        return false;
    }

    GnssConfig config;
    memset(&config, 0, sizeof(GnssConfig));
    config.size = sizeof(GnssConfig);
    config.flags = GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
    config.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
    if (type == IAGnssCallback::AGnssType::SUPL) {
        config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL;
    } else if (type == IAGnssCallback::AGnssType::C2K) {
        config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_C2K;
    } else if (type == IAGnssCallback::AGnssType::SUPL_EIMS) {
        config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL_EIMS;
    } else if (type == IAGnssCallback::AGnssType::SUPL_IMS) {
        config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL_IMS;
    } else {
        LOC_LOGE("%s]: invalid AGnssType: %d", __FUNCTION__, static_cast<uint8_t>(type));
        return false;
    }
    config.assistanceServer.hostName = strdup(hostname.c_str());
    config.assistanceServer.port = port;
    return mGnss->updateConfiguration(config);
}

}  // namespace implementation
}  // namespace V2_1
}  // namespace gnss
}  // namespace hardware
}  // namespace android


code:
/*
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 * Not a Contribution
 */
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H
#define ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H

#include <android/hardware/gnss/2.0/IAGnss.h>
#include <hidl/Status.h>
#include <gps_extended_c.h>

namespace android {
namespace hardware {
namespace gnss {
namespace V2_1 {
namespace implementation {

using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
using ::android::sp;
using ::android::hardware::gnss::V2_0::IAGnssCallback;

struct Gnss;
struct AGnss : public V2_0::IAGnss {

    AGnss(Gnss* gnss);
    ~AGnss();
    /*
     * Methods from ::android::hardware::gnss::V2_0::IAGnss interface follow.
     * These declarations were generated from IAGnss.hal.
     */
    Return<void> setCallback(const sp<V2_0::IAGnssCallback>& callback) override;

    Return<bool> dataConnClosed() override;

    Return<bool> dataConnFailed() override;

    Return<bool> dataConnOpen(uint64_t networkHandle, const hidl_string& apn,
            V2_0::IAGnss::ApnIpType apnIpType) override;

    Return<bool> setServer(V2_0::IAGnssCallback::AGnssType type,
                         const hidl_string& hostname, int32_t port) override;

    void statusCb(AGpsExtType type, LocAGpsStatusValue status);

    /* Data call setup callback passed down to GNSS HAL implementation */
    static void agnssStatusIpV4Cb(AGnssExtStatusIpV4 status);

 private:
    Gnss* mGnss = nullptr;
    sp<V2_0::IAGnssCallback> mAGnssCbIface = nullptr;

    AGpsExtType mType;
};

}  // namespace implementation
}  // namespace V2_1
}  // namespace gnss
}  // namespace hardware
}  // namespace android

#endif  // ANDROID_HARDWARE_GNSS_V2_0_AGNSS_H


code:
/*
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 * Not a Contribution
 */
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "LocSvc__AGnssRilInterface"

#include <log_util.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sstream>
#include <string>
#include "Gnss.h"
#include "AGnssRil.h"
#include <DataItemConcreteTypesBase.h>

typedef void* (getLocationInterface)();

namespace android {
namespace hardware {
namespace gnss {
namespace V2_1 {
namespace implementation {

AGnssRil::AGnssRil(Gnss* gnss) : mGnss(gnss) {
    ENTRY_LOG_CALLFLOW();
}

AGnssRil::~AGnssRil() {
    ENTRY_LOG_CALLFLOW();
}

Return<bool> AGnssRil::updateNetworkState(bool connected, NetworkType type, bool /*roaming*/) {
    ENTRY_LOG_CALLFLOW();
    // Extra NetworkTypes not available in IAgnssRil enums
    const int NetworkType_BLUETOOTH = 7;
    const int NetworkType_ETHERNET = 9;
    const int NetworkType_PROXY = 16;
    std::string apn("");

    // for XTRA
    if (nullptr != mGnss && ( nullptr != mGnss->getGnssInterface() )) {
        int8_t typeout = loc_core::TYPE_UNKNOWN;
        switch(type)
        {
            case IAGnssRil::NetworkType::MOBILE:
                typeout = loc_core::TYPE_MOBILE;
                break;
            case IAGnssRil::NetworkType::WIFI:
                typeout = loc_core::TYPE_WIFI;
                break;
            case IAGnssRil::NetworkType::MMS:
                typeout = loc_core::TYPE_MMS;
                break;
            case IAGnssRil::NetworkType::SUPL:
                typeout = loc_core::TYPE_SUPL;
                break;
            case IAGnssRil::NetworkType::DUN:
                typeout = loc_core::TYPE_DUN;
                break;
            case IAGnssRil::NetworkType::HIPRI:
                typeout = loc_core::TYPE_HIPRI;
                break;
            case IAGnssRil::NetworkType::WIMAX:
                typeout = loc_core::TYPE_WIMAX;
                break;
            default:
                {
                    int networkType = (int) type;
                    // Handling network types not available in IAgnssRil
                    switch(networkType)
                    {
                        case NetworkType_BLUETOOTH:
                            typeout = loc_core::TYPE_BLUETOOTH;
                            break;
                        case NetworkType_ETHERNET:
                            typeout = loc_core::TYPE_ETHERNET;
                            break;
                        case NetworkType_PROXY:
                            typeout = loc_core::TYPE_PROXY;
                            break;
                        default:
                            typeout = loc_core::TYPE_UNKNOWN;
                    }
                }
                break;
        }
        mGnss->getGnssInterface()->updateConnectionStatus(connected, typeout, false, 0, apn);
    }
    return true;
}
Return<bool> AGnssRil::updateNetworkState_2_0(const V2_0::IAGnssRil::NetworkAttributes& attributes) {
    ENTRY_LOG_CALLFLOW();
    std::string apn = attributes.apn;
    if (nullptr != mGnss && (nullptr != mGnss->getGnssInterface())) {
        int8_t typeout = loc_core::TYPE_UNKNOWN;
        bool roaming = false;
        if (attributes.capabilities & IAGnssRil::NetworkCapability::NOT_METERED) {
            typeout = loc_core::TYPE_WIFI;
        } else {
            typeout = loc_core::TYPE_MOBILE;
        }
        if (attributes.capabilities & IAGnssRil::NetworkCapability::NOT_ROAMING) {
            roaming = false;
        }
        LOC_LOGd("apn string received is: %s", apn.c_str());
        mGnss->getGnssInterface()->updateConnectionStatus(attributes.isConnected,
                typeout, roaming, (NetworkHandle) attributes.networkHandle, apn);
    }
    return true;
}

}  // namespace implementation
}  // namespace V2_1
}  // namespace gnss
}  // namespace hardware
}  // namespace android


code:
/*
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 * Not a Contribution
 */
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_
#define ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_

#include <android/hardware/gnss/2.0/IAGnssRil.h>
#include <hidl/Status.h>
#include <location_interface.h>

namespace android {
namespace hardware {
namespace gnss {
namespace V2_1 {
namespace implementation {

using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
using ::android::sp;

struct Gnss;
/*
 * Extended interface for AGNSS RIL support. An Assisted GNSS Radio Interface Layer interface
 * allows the GNSS chipset to request radio interface layer information from Android platform.
 * Examples of such information are reference location, unique subscriber ID, phone number string
 * and network availability changes. Also contains wrapper methods to allow methods from
 * IAGnssiRilCallback interface to be passed into the conventional implementation of the GNSS HAL.
 */
struct AGnssRil : public V2_0::IAGnssRil {
    AGnssRil(Gnss* gnss);
    ~AGnssRil();

    /*
     * Methods from ::android::hardware::gnss::V1_0::IAGnssRil follow.
     * These declarations were generated from IAGnssRil.hal.
     */
    Return<void> setCallback(const sp<V1_0::IAGnssRilCallback>& /*callback*/) override {
        return Void();
    }
    Return<void> setRefLocation(const V1_0::IAGnssRil::AGnssRefLocation& /*agnssReflocation*/) override {
        return Void();
    }
    Return<bool> setSetId(V1_0::IAGnssRil::SetIDType /*type*/, const hidl_string& /*setid*/) override {
        return false;
    }
    Return<bool> updateNetworkAvailability(bool /*available*/,
                                    const hidl_string& /*apn*/) override {
        return false;
    }
    Return<bool> updateNetworkState(bool connected, V1_0::IAGnssRil::NetworkType type, bool roaming) override;

    // Methods from ::android::hardware::gnss::V2_0::IAGnssRil follow
    Return<bool> updateNetworkState_2_0(const V2_0::IAGnssRil::NetworkAttributes& attributes) override;

 private:
    Gnss* mGnss = nullptr;
};

}  // namespace implementation
}  // namespace V2_1
}  // namespace gnss
}  // namespace hardware
}  // namespace android

#endif  // ANDROID_HARDWARE_GNSS_V2_0_AGNSSRIL_H_


code:
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := android.hardware.gnss@2.1-impl-qti
# activate the following line for debug purposes only, comment out for production
#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SRC_FILES := \
    AGnss.cpp \
    Gnss.cpp \
    AGnssRil.cpp \
    GnssMeasurement.cpp \
    GnssConfiguration.cpp \
    GnssBatching.cpp \
    GnssGeofencing.cpp \
    GnssNi.cpp \
    GnssDebug.cpp \
    GnssAntennaInfo.cpp \
    MeasurementCorrections.cpp \
    GnssVisibilityControl.cpp

LOCAL_SRC_FILES += \
    location_api/GnssAPIClient.cpp \
    location_api/MeasurementAPIClient.cpp \
    location_api/GeofenceAPIClient.cpp \
    location_api/BatchingAPIClient.cpp \
    location_api/LocationUtil.cpp \

ifeq ($(GNSS_HIDL_LEGACY_MEASURMENTS),true)
LOCAL_CFLAGS += \
     -DGNSS_HIDL_LEGACY_MEASURMENTS
endif

LOCAL_C_INCLUDES:= \
    $(LOCAL_PATH)/location_api

LOCAL_HEADER_LIBRARIES := \
    libgps.utils_headers \
    libloc_core_headers \
    libloc_pla_headers \
    liblocation_api_headers \
    liblocbatterylistener_headers

LOCAL_SHARED_LIBRARIES := \
    liblog \
    libhidlbase \
    libcutils \
    libutils \
    android.hardware.gnss@1.0 \
    android.hardware.gnss@1.1 \
    android.hardware.gnss@2.0 \
    android.hardware.gnss@2.1 \
    android.hardware.gnss.measurement_corrections@1.0 \
    android.hardware.gnss.measurement_corrections@1.1 \
    android.hardware.gnss.visibility_control@1.0 \
    android.hardware.health@1.0 \
    android.hardware.health@2.0 \
    android.hardware.health@2.1 \
    android.hardware.power@1.2 \
    libbase

LOCAL_SHARED_LIBRARIES += \
    libloc_core \
    libgps.utils \
    libdl \
    liblocation_api \

LOCAL_CFLAGS += $(GNSS_CFLAGS)
LOCAL_STATIC_LIBRARIES := liblocbatterylistener
LOCAL_STATIC_LIBRARIES += libhealthhalutils
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := android.hardware.gnss@2.1-service-qti

# activate the following line for debug purposes only, comment out for production
#LOCAL_SANITIZE_DIAG += $(GNSS_SANITIZE_DIAG)
LOCAL_VINTF_FRAGMENTS := android.hardware.gnss@2.1-service-qti.xml
LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_INIT_RC := android.hardware.gnss@2.1-service-qti.rc
LOCAL_SRC_FILES := \
    service.cpp \

LOCAL_HEADER_LIBRARIES := \
    libgps.utils_headers \
    libloc_core_headers \
    libloc_pla_headers \
    liblocation_api_headers

LOCAL_SHARED_LIBRARIES := \
    liblog \
    libcutils \
    libdl \
    libbase \
    libutils \
    libgps.utils \
    libqti_vndfwk_detect \

LOCAL_SHARED_LIBRARIES += \
    libhidlbase \
    android.hardware.gnss@1.0 \
    android.hardware.gnss@1.1 \
    android.hardware.gnss@2.0 \
    android.hardware.gnss@2.1 \

LOCAL_CFLAGS += $(GNSS_CFLAGS)

ifneq ($(LOC_HIDL_VERSION),)
LOCAL_CFLAGS += -DLOC_HIDL_VERSION='"$(LOC_HIDL_VERSION)"'
endif

include $(BUILD_EXECUTABLE)


code:
/*
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 * Not a Contribution
 */
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2_0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2_0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "LocSvc_GnssInterface"
#define LOG_NDEBUG 0

#include <fstream>
#include <log_util.h>
#include <dlfcn.h>
#include <cutils/properties.h>
#include "Gnss.h"
#include "LocationUtil.h"
#include "battery_listener.h"
#include "loc_misc_utils.h"

typedef const GnssInterface* (getLocationInterface)();

#define IMAGES_INFO_FILE "/sys/devices/soc0/images"
#define DELIMITER ";"

namespace android {
namespace hardware {
namespace gnss {
namespace V2_1 {
namespace implementation {

using ::android::hardware::gnss::visibility_control::V1_0::implementation::GnssVisibilityControl;
using ::android::hardware::gnss::measurement_corrections::V1_1::
        implementation::MeasurementCorrections;
static sp<Gnss> sGnss;
static std::string getVersionString() {
    static std::string version;
    if (!version.empty())
        return version;

    char value[PROPERTY_VALUE_MAX] = {0};
    property_get("ro.hardware", value, "unknown");
    version.append(value).append(DELIMITER);

    std::ifstream in(IMAGES_INFO_FILE);
    std::string s;
    while(getline(in, s)) {
        std::size_t found = s.find("CRM:");
        if (std::string::npos == found) {
            continue;
        }

        // skip over space characters after "CRM:"
        const char* substr = s.c_str();
        found += 4;
        while (0 != substr[found] && isspace(substr[found])) {
            found++;
        }
        if (s.find("11:") != found) {
            continue;
        }
        s.erase(0, found + 3);

        found = s.find_first_of("\r\n");
        if (std::string::npos != found) {
            s.erase(s.begin() + found, s.end());
        }
        version.append(s).append(DELIMITER);
    }
    return version;
}

void Gnss::GnssDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) {
    LOC_LOGE("%s] service died. cookie: %llu, who: %p",
            __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
    if (mGnss != nullptr) {
        mGnss->getGnssInterface()->resetNetworkInfo();
        mGnss->cleanup();
    }
}

void location_on_battery_status_changed(bool charging) {
    LOC_LOGd("battery status changed to %s charging", charging ? "" : "not");
    if (sGnss != nullptr) {
        sGnss->getGnssInterface()->updateBatteryStatus(charging);
    }
}
Gnss::Gnss() {
    ENTRY_LOG_CALLFLOW();
    sGnss = this;
    // initilize gnss interface at first in case needing notify battery status
    sGnss->getGnssInterface()->initialize();
    // register health client to listen on battery change
    loc_extn_battery_properties_listener_init(location_on_battery_status_changed);
    // clear pending GnssConfig
    memset(&mPendingConfig, 0, sizeof(GnssConfig));
    mGnssDeathRecipient = new GnssDeathRecipient(this);
}

Gnss::~Gnss() {
    ENTRY_LOG_CALLFLOW();
    if (mApi != nullptr) {
        mApi->destroy();
        mApi = nullptr;
    }
    sGnss = nullptr;
}

GnssAPIClient* Gnss::getApi() {
    if (mApi != nullptr) {
        return mApi;
    }

    if (mGnssCbIface_2_1 != nullptr) {
        mApi = new GnssAPIClient(mGnssCbIface_2_1);
    } else if (mGnssCbIface_2_0 != nullptr) {
        mApi = new GnssAPIClient(mGnssCbIface_2_0);
    } else if (mGnssCbIface_1_1 != nullptr) {
        mApi = new GnssAPIClient(mGnssCbIface_1_1, mGnssNiCbIface);
    } else if (mGnssCbIface != nullptr) {
        mApi = new GnssAPIClient(mGnssCbIface, mGnssNiCbIface);
    } else {
        LOC_LOGW("%s] GnssAPIClient is not ready", __FUNCTION__);
        return mApi;
    }

    if (mPendingConfig.size == sizeof(GnssConfig)) {
        // we have pending GnssConfig
        mApi->gnssConfigurationUpdate(mPendingConfig);
        // clear size to invalid mPendingConfig
        mPendingConfig.size = 0;
        if (mPendingConfig.assistanceServer.hostName != nullptr) {
            free((void*)mPendingConfig.assistanceServer.hostName);
        }
    }

    return mApi;
}

const GnssInterface* Gnss::getGnssInterface() {
    static bool getGnssInterfaceFailed = false;
    if (mGnssInterface == nullptr && !getGnssInterfaceFailed) {
        void * libHandle = nullptr;
        getLocationInterface* getter = (getLocationInterface*)
                dlGetSymFromLib(libHandle, "libgnss.so", "getGnssInterface");
        if (NULL == getter) {
            getGnssInterfaceFailed = true;
        } else {
            mGnssInterface = (GnssInterface*)(*getter)();
        }
    }
    return mGnssInterface;
}

Return<bool> Gnss::setCallback(const sp<V1_0::IGnssCallback>& callback)  {
    ENTRY_LOG_CALLFLOW();

    // In case where previous call to setCallback_1_1/setCallback_2_0/setCallback_2_1, then
    // we need to cleanup these interfaces/callbacks here since we no longer
    // do so in cleanup() function to keep callbacks around after cleanup()
    if (mApi != nullptr) {
        mApi->gnssUpdateCallbacks_2_0(nullptr);
        mApi->gnssUpdateCallbacks_2_1(nullptr);
    }
    if (mGnssCbIface_1_1 != nullptr) {
        mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
        mGnssCbIface_1_1 = nullptr;
    }
    if (mGnssCbIface_2_0 != nullptr) {
        mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
        mGnssCbIface_2_0 = nullptr;
    }
    if (mGnssCbIface_2_1 != nullptr) {
        mGnssCbIface_2_1->unlinkToDeath(mGnssDeathRecipient);
        mGnssCbIface_2_1 = nullptr;
    }

    if (mGnssCbIface != nullptr) {
        mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
    }
    mGnssCbIface = callback;
    if (mGnssCbIface != nullptr) {
        mGnssCbIface->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
    }

    GnssAPIClient* api = getApi();
    if (api != nullptr) {
        api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
        api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
        api->requestCapabilities();
    }
    return true;
}

Return<bool> Gnss::setGnssNiCb(const sp<IGnssNiCallback>& callback) {
    ENTRY_LOG_CALLFLOW();
    mGnssNiCbIface = callback;
    GnssAPIClient* api = getApi();
    if (api != nullptr) {
        api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface);
    }
    return true;
}

Return<bool> Gnss::updateConfiguration(GnssConfig& gnssConfig) {
    ENTRY_LOG_CALLFLOW();
    GnssAPIClient* api = getApi();
    if (api) {
        api->gnssConfigurationUpdate(gnssConfig);
    } else if (gnssConfig.flags != 0) {
        // api is not ready yet, update mPendingConfig with gnssConfig
        mPendingConfig.size = sizeof(GnssConfig);

        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT;
            mPendingConfig.gpsLock = gnssConfig.gpsLock;
        }
        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT;
            mPendingConfig.suplVersion = gnssConfig.suplVersion;
        }
        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT;
            mPendingConfig.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer);
            mPendingConfig.assistanceServer.type = gnssConfig.assistanceServer.type;
            if (mPendingConfig.assistanceServer.hostName != nullptr) {
                free((void*)mPendingConfig.assistanceServer.hostName);
                mPendingConfig.assistanceServer.hostName =
                    strdup(gnssConfig.assistanceServer.hostName);
            }
            mPendingConfig.assistanceServer.port = gnssConfig.assistanceServer.port;
        }
        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT;
            mPendingConfig.lppProfileMask = gnssConfig.lppProfileMask;
        }
        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT;
            mPendingConfig.lppeControlPlaneMask = gnssConfig.lppeControlPlaneMask;
        }
        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT;
            mPendingConfig.lppeUserPlaneMask = gnssConfig.lppeUserPlaneMask;
        }
        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT;
            mPendingConfig.aGlonassPositionProtocolMask = gnssConfig.aGlonassPositionProtocolMask;
        }
        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT;
            mPendingConfig.emergencyPdnForEmergencySupl = gnssConfig.emergencyPdnForEmergencySupl;
        }
        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT;
            mPendingConfig.suplEmergencyServices = gnssConfig.suplEmergencyServices;
        }
        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_MODE_BIT;
            mPendingConfig.suplModeMask = gnssConfig.suplModeMask;
        }
        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) {
            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT;
            mPendingConfig.blacklistedSvIds = gnssConfig.blacklistedSvIds;
        }
        if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT) {
            mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EMERGENCY_EXTENSION_SECONDS_BIT;
            mPendingConfig.emergencyExtensionSeconds = gnssConfig.emergencyExtensionSeconds;
        }
    }
    return true;
}

Return<bool> Gnss::start()  {
    ENTRY_LOG_CALLFLOW();
    bool retVal = false;
    GnssAPIClient* api = getApi();
    if (api) {
        retVal = api->gnssStart();
    }
    return retVal;
}

Return<bool> Gnss::stop()  {
    ENTRY_LOG_CALLFLOW();
    bool retVal = false;
    GnssAPIClient* api = getApi();
    if (api) {
        retVal = api->gnssStop();
    }
    return retVal;
}

Return<void> Gnss::cleanup()  {
    ENTRY_LOG_CALLFLOW();

    if (mApi != nullptr) {
        mApi->gnssStop();
        mApi->gnssDisable();
    }

    return Void();
}

Return<bool> Gnss::injectLocation(double latitudeDegrees,
                                  double longitudeDegrees,
                                  float accuracyMeters)  {
    ENTRY_LOG_CALLFLOW();
    const GnssInterface* gnssInterface = getGnssInterface();
    if (nullptr != gnssInterface) {
        gnssInterface->injectLocation(latitudeDegrees, longitudeDegrees, accuracyMeters);
        return true;
    } else {
        return false;
    }
}

Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
                              int32_t uncertaintyMs) {
    return true;
}

Return<void> Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags)  {
    ENTRY_LOG_CALLFLOW();
    GnssAPIClient* api = getApi();
    if (api) {
        api->gnssDeleteAidingData(aidingDataFlags);
    }
    return Void();
}

Return<bool> Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode mode,
                                   V1_0::IGnss::GnssPositionRecurrence recurrence,
                                   uint32_t minIntervalMs,
                                   uint32_t preferredAccuracyMeters,
                                   uint32_t preferredTimeMs)  {
    ENTRY_LOG_CALLFLOW();
    bool retVal = false;
    GnssAPIClient* api = getApi();
    if (api) {
        retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
                preferredAccuracyMeters, preferredTimeMs);
    }
    return retVal;
}

Return<sp<V1_0::IAGnss>> Gnss::getExtensionAGnss()  {
    ENTRY_LOG_CALLFLOW();
    // deprecated function. Must return nullptr to pass VTS
    return nullptr;
}

Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi()  {
    ENTRY_LOG_CALLFLOW();
    // deprecated function. Must return nullptr to pass VTS
    return nullptr;
}

Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
    ENTRY_LOG_CALLFLOW();
    if (mGnssMeasurement == nullptr) {
        mGnssMeasurement = new GnssMeasurement();
    }
    return mGnssMeasurement;
}

Return<sp<V1_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration()  {
    ENTRY_LOG_CALLFLOW();
    if (mGnssConfig == nullptr) {
        mGnssConfig = new GnssConfiguration(this);
    }
    return mGnssConfig;
}

Return<sp<V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing()  {
    ENTRY_LOG_CALLFLOW();
    if (mGnssGeofencingIface == nullptr) {
        mGnssGeofencingIface = new GnssGeofencing();
    }
    return mGnssGeofencingIface;
}

Return<sp<V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching()  {
    ENTRY_LOG_CALLFLOW();
    if (mGnssBatching == nullptr) {
        mGnssBatching = new GnssBatching();
    }
    return mGnssBatching;
}

Return<sp<V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
    ENTRY_LOG_CALLFLOW();
    if (mGnssDebug == nullptr) {
        mGnssDebug = new GnssDebug(this);
    }
    return mGnssDebug;
}

Return<sp<V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
    ENTRY_LOG_CALLFLOW();
    if (mGnssRil == nullptr) {
        mGnssRil = new AGnssRil(this);
    }
    return mGnssRil;
}

// Methods from ::android::hardware::gnss::V1_1::IGnss follow.
Return<bool> Gnss::setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) {
    ENTRY_LOG_CALLFLOW();
    auto r = callback->gnssNameCb(getVersionString());
    if (!r.isOk()) {
        LOC_LOGE("%s] Error from gnssNameCb description=%s",
                __func__, r.description().c_str());
    }

    // In case where previous call to setCallback/setCallback_2_0/setCallback_2_1, then
    // we need to cleanup these interfaces/callbacks here since we no longer
    // do so in cleanup() function to keep callbacks around after cleanup()
    if (mApi != nullptr) {
        mApi->gnssUpdateCallbacks_2_0(nullptr);
        mApi->gnssUpdateCallbacks_2_1(nullptr);
    }
    if (mGnssCbIface != nullptr) {
        mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
        mGnssCbIface = nullptr;
    }
    if (mGnssCbIface_2_0 != nullptr) {
        mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
        mGnssCbIface_2_0 = nullptr;
    }
    if (mGnssCbIface_2_1 != nullptr) {
        mGnssCbIface_2_1->unlinkToDeath(mGnssDeathRecipient);
        mGnssCbIface_2_1 = nullptr;
    }

    if (mGnssCbIface_1_1 != nullptr) {
        mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
    }
    mGnssCbIface_1_1 = callback;
    if (mGnssCbIface_1_1 != nullptr) {
        mGnssCbIface_1_1->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
    }

    const GnssInterface* gnssInterface = getGnssInterface();
    if (nullptr != gnssInterface) {
        OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
            odcpiRequestCb(odcpiRequest);
        };
        gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
    }

    GnssAPIClient* api = getApi();
    if (api != nullptr) {
        api->gnssUpdateCallbacks(mGnssCbIface_1_1, mGnssNiCbIface);
        api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
        api->requestCapabilities();
    }

    return true;
}

Return<bool> Gnss::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
        V1_0::IGnss::GnssPositionRecurrence recurrence,
        uint32_t minIntervalMs,
        uint32_t preferredAccuracyMeters,
        uint32_t preferredTimeMs,
        bool lowPowerMode) {
    ENTRY_LOG_CALLFLOW();
    bool retVal = false;
    GnssAPIClient* api = getApi();
    if (api) {
        GnssPowerMode powerMode = lowPowerMode?
                GNSS_POWER_MODE_M4 : GNSS_POWER_MODE_M2;
        retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
                preferredAccuracyMeters, preferredTimeMs, powerMode, minIntervalMs);
    }
    return retVal;
}

Return<sp<V1_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_1_1() {
    ENTRY_LOG_CALLFLOW();
#ifdef GNSS_HIDL_LEGACY_MEASURMENTS
    return nullptr;
#else
    if (mGnssMeasurement == nullptr)
        mGnssMeasurement = new GnssMeasurement();
    return mGnssMeasurement;
#endif
}

Return<sp<V1_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_1_1() {
    ENTRY_LOG_CALLFLOW();
    if (mGnssConfig == nullptr)
        mGnssConfig = new GnssConfiguration(this);
    return mGnssConfig;
}

Return<bool> Gnss::injectBestLocation(const GnssLocation& gnssLocation) {
    ENTRY_LOG_CALLFLOW();
    const GnssInterface* gnssInterface = getGnssInterface();
    if (nullptr != gnssInterface) {
        Location location = {};
        convertGnssLocation(gnssLocation, location);
        gnssInterface->odcpiInject(location);
    }
    return true;
}

void Gnss::odcpiRequestCb(const OdcpiRequestInfo& request) {
    ENTRY_LOG_CALLFLOW();
    if (ODCPI_REQUEST_TYPE_STOP == request.type) {
        return;
    }
    if (mGnssCbIface_2_1 != nullptr) {
        // For emergency mode, request DBH (Device based hybrid) location
        // Mark Independent from GNSS flag to false.
        if (ODCPI_REQUEST_TYPE_START == request.type) {
            LOC_LOGd("gnssRequestLocationCb_2_1 isUserEmergency = %d", request.isEmergencyMode);
            auto r = mGnssCbIface_2_1->gnssRequestLocationCb_2_0(!request.isEmergencyMode,
                                                                 request.isEmergencyMode);
            if (!r.isOk()) {
                LOC_LOGe("Error invoking gnssRequestLocationCb_2_0 %s", r.description().c_str());
            }
        } else {
            LOC_LOGv("Unsupported ODCPI request type: %d", request.type);
        }
    } else if (mGnssCbIface_2_0 != nullptr) {
        // For emergency mode, request DBH (Device based hybrid) location
        // Mark Independent from GNSS flag to false.
        if (ODCPI_REQUEST_TYPE_START == request.type) {
            LOC_LOGd("gnssRequestLocationCb_2_0 isUserEmergency = %d", request.isEmergencyMode);
            auto r = mGnssCbIface_2_0->gnssRequestLocationCb_2_0(!request.isEmergencyMode,
                                                                 request.isEmergencyMode);
            if (!r.isOk()) {
                LOC_LOGe("Error invoking gnssRequestLocationCb_2_0 %s", r.description().c_str());
            }
        } else {
            LOC_LOGv("Unsupported ODCPI request type: %d", request.type);
        }
    } else if (mGnssCbIface_1_1 != nullptr) {
        // For emergency mode, request DBH (Device based hybrid) location
        // Mark Independent from GNSS flag to false.
        if (ODCPI_REQUEST_TYPE_START == request.type) {
            auto r = mGnssCbIface_1_1->gnssRequestLocationCb(!request.isEmergencyMode);
            if (!r.isOk()) {
                LOC_LOGe("Error invoking gnssRequestLocationCb %s", r.description().c_str());
            }
        } else {
            LOC_LOGv("Unsupported ODCPI request type: %d", request.type);
        }
    } else {
        LOC_LOGe("ODCPI request not supported.");
    }
}

// Methods from ::android::hardware::gnss::V2_0::IGnss follow.
Return<bool> Gnss::setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) {
    ENTRY_LOG_CALLFLOW();
    auto r = callback->gnssNameCb(getVersionString());
    if (!r.isOk()) {
        LOC_LOGE("%s] Error from gnssNameCb description=%s",
                __func__, r.description().c_str());
    }

    // In case where previous call to setCallback/setCallback_1_1/setCallback_2_1, then
    // we need to cleanup these interfaces/callbacks here since we no longer
    // do so in cleanup() function to keep callbacks around after cleanup()
    if (mApi != nullptr) {
        mApi->gnssUpdateCallbacks(nullptr, nullptr);
        mApi->gnssUpdateCallbacks_2_1(nullptr);
    }
    mGnssNiCbIface = nullptr;
    if (mGnssCbIface != nullptr) {
        mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
        mGnssCbIface = nullptr;
    }
    if (mGnssCbIface_1_1 != nullptr) {
        mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
        mGnssCbIface_1_1 = nullptr;
    }
    if (mGnssCbIface_2_1 != nullptr) {
        mGnssCbIface_2_1->unlinkToDeath(mGnssDeathRecipient);
        mGnssCbIface_2_1 = nullptr;
    }

    if (mGnssCbIface_2_0 != nullptr) {
        mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
    }
    mGnssCbIface_2_0 = callback;
    if (mGnssCbIface_2_0 != nullptr) {
        mGnssCbIface_2_0->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
    }

    const GnssInterface* gnssInterface = getGnssInterface();
    if (nullptr != gnssInterface) {
        OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
            odcpiRequestCb(odcpiRequest);
        };
        gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
    }

    GnssAPIClient* api = getApi();
    if (api != nullptr) {
        api->gnssUpdateCallbacks_2_0(mGnssCbIface_2_0);
        api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
        api->requestCapabilities();
    }

    return true;
}

Return<sp<V2_0::IAGnss>> Gnss::getExtensionAGnss_2_0() {
    ENTRY_LOG_CALLFLOW();
    if (mAGnssIface_2_0 == nullptr) {
        mAGnssIface_2_0 = new AGnss(this);
    }
    return mAGnssIface_2_0;
}
Return<sp<V2_0::IAGnssRil>> Gnss::getExtensionAGnssRil_2_0() {

    if (mGnssRil == nullptr) {
        mGnssRil = new AGnssRil(this);
    }
    return mGnssRil;
}

Return<sp<V2_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_0() {
    ENTRY_LOG_CALLFLOW();
    if (mGnssConfig == nullptr) {
        mGnssConfig = new GnssConfiguration(this);
    }
    return mGnssConfig;
}
Return<sp<V2_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_0() {
    ENTRY_LOG_CALLFLOW();
#ifdef GNSS_HIDL_LEGACY_MEASURMENTS
    return nullptr;
#else
    if (mGnssMeasurement == nullptr)
        mGnssMeasurement = new GnssMeasurement();
    return mGnssMeasurement;
#endif
}

Return<sp<IMeasurementCorrectionsV1_0>>
        Gnss::getExtensionMeasurementCorrections() {
    ENTRY_LOG_CALLFLOW();
    if (mGnssMeasCorr == nullptr) {
        mGnssMeasCorr = new MeasurementCorrections(this);
    }
    return mGnssMeasCorr;
}

Return<sp<IMeasurementCorrectionsV1_1>>
        Gnss::getExtensionMeasurementCorrections_1_1() {
    ENTRY_LOG_CALLFLOW();
    if (mGnssMeasCorr == nullptr) {
        mGnssMeasCorr = new MeasurementCorrections(this);
    }
    return mGnssMeasCorr;
}

Return<sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl>>
        Gnss::getExtensionVisibilityControl() {
    ENTRY_LOG_CALLFLOW();
    if (mVisibCtrl == nullptr) {
        mVisibCtrl = new GnssVisibilityControl(this);
    }
    return mVisibCtrl;
}

Return<bool> Gnss::injectBestLocation_2_0(const V2_0::GnssLocation& gnssLocation) {
    ENTRY_LOG_CALLFLOW();
    const GnssInterface* gnssInterface = getGnssInterface();
    if (nullptr != gnssInterface) {
        Location location = {};
        convertGnssLocation(gnssLocation, location);
        gnssInterface->odcpiInject(location);
    }
    return true;
}

Return<sp<V2_0::IGnssDebug>> Gnss::getExtensionGnssDebug_2_0() {
    ENTRY_LOG_CALLFLOW();
    if (mGnssDebug == nullptr) {
        mGnssDebug = new GnssDebug(this);
    }
    return mGnssDebug;
}

Return<sp<V2_0::IGnssBatching>> Gnss::getExtensionGnssBatching_2_0() {
    return nullptr;
}

// Methods from ::android::hardware::gnss::V2_1::IGnss follow.
Return<bool> Gnss::setCallback_2_1(const sp<V2_1::IGnssCallback>& callback) {
    ENTRY_LOG_CALLFLOW();
    auto r = callback->gnssNameCb(getVersionString());
    if (!r.isOk()) {
        LOC_LOGE("%s] Error from gnssNameCb description=%s",
                __func__, r.description().c_str());
    }

    // In case where previous call to setCallback/setCallback_1_1/setCallback_2_0, then
    // we need to cleanup these interfaces/callbacks here since we no longer
    // do so in cleanup() function to keep callbacks around after cleanup()
    if (mApi != nullptr) {
        mApi->gnssUpdateCallbacks(nullptr, nullptr);
        mApi->gnssUpdateCallbacks_2_0(nullptr);
    }
    mGnssNiCbIface = nullptr;
    if (mGnssCbIface != nullptr) {
        mGnssCbIface->unlinkToDeath(mGnssDeathRecipient);
        mGnssCbIface = nullptr;
    }
    if (mGnssCbIface_1_1 != nullptr) {
        mGnssCbIface_1_1->unlinkToDeath(mGnssDeathRecipient);
        mGnssCbIface_1_1 = nullptr;
    }
    if (mGnssCbIface_2_0 != nullptr) {
        mGnssCbIface_2_0->unlinkToDeath(mGnssDeathRecipient);
        mGnssCbIface_2_0 = nullptr;
    }
    if (mGnssCbIface_2_1 != nullptr) {
        mGnssCbIface_2_1->unlinkToDeath(mGnssDeathRecipient);
    }
    mGnssCbIface_2_1 = callback;
    if (mGnssCbIface_2_1 != nullptr) {
        mGnssCbIface_2_1->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/);
    }

    const GnssInterface* gnssInterface = getGnssInterface();
    if (gnssInterface != nullptr) {
        OdcpiRequestCallback cb = [this](const OdcpiRequestInfo& odcpiRequest) {
            odcpiRequestCb(odcpiRequest);
        };
        gnssInterface->odcpiInit(cb, OdcpiPrioritytype::ODCPI_HANDLER_PRIORITY_LOW);
    }

    GnssAPIClient* api = getApi();
    if (api != nullptr) {
        api->gnssUpdateCallbacks_2_1(mGnssCbIface_2_1);
        api->gnssEnable(LOCATION_TECHNOLOGY_TYPE_GNSS);
        api->requestCapabilities();
    }

    return true;
}
Return<sp<V2_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_1() {
    ENTRY_LOG_CALLFLOW();
    if (mGnssMeasurement == nullptr) {
        mGnssMeasurement = new GnssMeasurement();
    }
    return mGnssMeasurement;
}
Return<sp<V2_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_1() {
    ENTRY_LOG_CALLFLOW();
    if (mGnssConfig == nullptr) {
        mGnssConfig = new GnssConfiguration(this);
    }
    return mGnssConfig;
}

Return<sp<V2_1::IGnssAntennaInfo>> Gnss::getExtensionGnssAntennaInfo() {
    ENTRY_LOG_CALLFLOW();
    if (mGnssAntennaInfo == nullptr) {
        mGnssAntennaInfo = new GnssAntennaInfo(this);
    }
    return mGnssAntennaInfo;
}

V1_0::IGnss* HIDL_FETCH_IGnss(const char* hal) {
    ENTRY_LOG_CALLFLOW();
    V1_0::IGnss* iface = nullptr;
    iface = new Gnss();
    if (iface == nullptr) {
        LOC_LOGE("%s]: failed to get %s", __FUNCTION__, hal);
    }
    return iface;
}

}  // namespace implementation
}  // namespace V2_1
}  // namespace gnss
}  // namespace hardware
}  // namespace android


code:
/*
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 * Not a Contribution
 */
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2_0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2_0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_HARDWARE_GNSS_V2_1_GNSS_H
#define ANDROID_HARDWARE_GNSS_V2_1_GNSS_H

#include <AGnss.h>
#include <AGnssRil.h>
#include <GnssConfiguration.h>
#include <GnssMeasurement.h>
#include <GnssBatching.h>
#include <GnssGeofencing.h>
#include <GnssNi.h>
#include <GnssDebug.h>
#include <GnssAntennaInfo.h>

#include <android/hardware/gnss/2.1/IGnss.h>
#include <android/hardware/gnss/measurement_corrections/1.1/IMeasurementCorrections.h>
#include <MeasurementCorrections.h>
#include <GnssVisibilityControl.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>

#include "GnssAPIClient.h"

namespace android {
namespace hardware {
namespace gnss {
namespace V2_1 {
namespace implementation {

using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;
using ::android::hardware::gnss::V1_0::GnssLocation;
using IMeasurementCorrectionsV1_0 =
        ::android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
using IMeasurementCorrectionsV1_1 =
        ::android::hardware::gnss::measurement_corrections::V1_1::IMeasurementCorrections;
using ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl;

struct Gnss : public IGnss {
    Gnss();
    ~Gnss();

    /*
     * Methods from ::android::hardware::gnss::V1_0::IGnss follow.
     * These declarations were generated from Gnss.hal.
     */
    Return<bool> setCallback(const sp<V1_0::IGnssCallback>& callback)  override;
    Return<bool> start()  override;
    Return<bool> stop()  override;
    Return<void> cleanup()  override;
    Return<bool> injectLocation(double latitudeDegrees,
                                double longitudeDegrees,
                                float accuracyMeters)  override;
    Return<bool> injectTime(int64_t timeMs,
                            int64_t timeReferenceMs,
                            int32_t uncertaintyMs) override;
    Return<void> deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags)  override;
    Return<bool> setPositionMode(V1_0::IGnss::GnssPositionMode mode,
                                 V1_0::IGnss::GnssPositionRecurrence recurrence,
                                 uint32_t minIntervalMs,
                                 uint32_t preferredAccuracyMeters,
                                 uint32_t preferredTimeMs)  override;
    Return<sp<V1_0::IAGnss>> getExtensionAGnss() override;
    Return<sp<V1_0::IGnssNi>> getExtensionGnssNi() override;
    Return<sp<V1_0::IGnssMeasurement>> getExtensionGnssMeasurement() override;
    Return<sp<V1_0::IGnssConfiguration>> getExtensionGnssConfiguration() override;
    Return<sp<V1_0::IGnssGeofencing>> getExtensionGnssGeofencing() override;
    Return<sp<V1_0::IGnssBatching>> getExtensionGnssBatching() override;

    Return<sp<V1_0::IAGnssRil>> getExtensionAGnssRil() override;

    inline Return<sp<V1_0::IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override {
        return nullptr;
    }

    inline Return<sp<V1_0::IGnssXtra>> getExtensionXtra() override {
        return nullptr;
    }

    Return<sp<V1_0::IGnssDebug>> getExtensionGnssDebug() override;

    // Methods from ::android::hardware::gnss::V1_1::IGnss follow.
    Return<bool> setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) override;
    Return<bool> setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
            V1_0::IGnss::GnssPositionRecurrence recurrence,
            uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
            uint32_t preferredTimeMs, bool lowPowerMode) override;
    Return<sp<V1_1::IGnssMeasurement>> getExtensionGnssMeasurement_1_1() override;
    Return<sp<V1_1::IGnssConfiguration>> getExtensionGnssConfiguration_1_1() override;
    Return<bool> injectBestLocation(const GnssLocation& location) override;

    // Methods from ::android::hardware::gnss::V2_0::IGnss follow.
    Return<bool> setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) override;
    Return<sp<V2_0::IAGnss>> getExtensionAGnss_2_0() override;
    Return<sp<V2_0::IAGnssRil>> getExtensionAGnssRil_2_0() override;

    Return<sp<V2_0::IGnssConfiguration>> getExtensionGnssConfiguration_2_0() override;
    Return<sp<IMeasurementCorrectionsV1_0>> getExtensionMeasurementCorrections() override;
    Return<sp<IMeasurementCorrectionsV1_1>> getExtensionMeasurementCorrections_1_1() override;
    Return<sp<V2_0::IGnssMeasurement>> getExtensionGnssMeasurement_2_0() override;

    Return<bool> injectBestLocation_2_0(
            const ::android::hardware::gnss::V2_0::GnssLocation& location) override;

    Return<sp<V2_0::IGnssBatching>> getExtensionGnssBatching_2_0() override;
    Return<sp<V2_0::IGnssDebug>> getExtensionGnssDebug_2_0() override;
    Return<sp<::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl>>
            getExtensionVisibilityControl() override;

    // Methods from ::android::hardware::gnss::V2_1::IGnss follow.
    Return<bool> setCallback_2_1(const sp<V2_1::IGnssCallback>& callback) override;
    Return<sp<V2_1::IGnssMeasurement>> getExtensionGnssMeasurement_2_1() override;
    Return<sp<V2_1::IGnssConfiguration>> getExtensionGnssConfiguration_2_1() override;
    Return<sp<V2_1::IGnssAntennaInfo>> getExtensionGnssAntennaInfo() override;

    // These methods are not part of the IGnss base class.
    GnssAPIClient* getApi();
    Return<bool> setGnssNiCb(const sp<IGnssNiCallback>& niCb);
    Return<bool> updateConfiguration(GnssConfig& gnssConfig);
    const GnssInterface* getGnssInterface();

    // Callback for ODCPI request
    void odcpiRequestCb(const OdcpiRequestInfo& request);

 private:
    struct GnssDeathRecipient : hidl_death_recipient {
        GnssDeathRecipient(sp<Gnss> gnss) : mGnss(gnss) {
        }
        ~GnssDeathRecipient() = default;
        virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
        sp<Gnss> mGnss;
    };

 private:
    sp<GnssDeathRecipient> mGnssDeathRecipient = nullptr;

    sp<V1_0::IGnssNi> mGnssNi = nullptr;
    sp<V1_0::IGnssGeofencing> mGnssGeofencingIface = nullptr;
    sp<V1_0::IAGnss> mAGnssIface = nullptr;
    sp<V1_0::IGnssCallback> mGnssCbIface = nullptr;
    sp<V1_0::IGnssNiCallback> mGnssNiCbIface = nullptr;
    sp<V1_1::IGnssCallback> mGnssCbIface_1_1 = nullptr;
    sp<V2_0::IAGnss> mAGnssIface_2_0 = nullptr;
    sp<V2_0::IAGnssRil> mGnssRil = nullptr;
    sp<V2_0::IGnssBatching> mGnssBatching = nullptr;
    sp<V2_0::IGnssDebug> mGnssDebug = nullptr;
    sp<V2_0::IGnssCallback> mGnssCbIface_2_0 = nullptr;
    sp<V2_1::IGnssCallback> mGnssCbIface_2_1 = nullptr;
    sp<V2_1::IGnssMeasurement> mGnssMeasurement = nullptr;
    sp<V2_1::IGnssConfiguration> mGnssConfig = nullptr;
    sp<V2_1::IGnssAntennaInfo> mGnssAntennaInfo = nullptr;
    sp<IMeasurementCorrectionsV1_1> mGnssMeasCorr = nullptr;
    sp<IGnssVisibilityControl> mVisibCtrl = nullptr;

    GnssAPIClient* mApi = nullptr;
    GnssConfig mPendingConfig;
    const GnssInterface* mGnssInterface = nullptr;
};

extern "C" V1_0::IGnss* HIDL_FETCH_IGnss(const char* name);

}  // namespace implementation
}  // namespace V2_1
}  // namespace gnss
}  // namespace hardware
}  // namespace android

#endif  // ANDROID_HARDWARE_GNSS_V2_1_GNSS_H


code:
/*
 * Copyright (c) 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_GnssAntennaInfoInterface"

#include <log_util.h>
#include "Gnss.h"
#include "GnssAntennaInfo.h"
#include <android/hardware/gnss/1.0/types.h>

namespace android {
namespace hardware {
namespace gnss {
namespace V2_1 {
namespace implementation {

static GnssAntennaInfo* spGnssAntennaInfo = nullptr;

static void convertGnssAntennaInfo(std::vector<GnssAntennaInformation>& in,
        hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& antennaInfos);

void GnssAntennaInfo::GnssAntennaInfoDeathRecipient::serviceDied(uint64_t cookie,
                                                                 const wp<IBase>& who) {
    LOC_LOGE("%s] service died. cookie: %llu, who: %p",
            __FUNCTION__, static_cast<unsigned long long>(cookie), &who);
    // we do nothing here
    // Gnss::GnssDeathRecipient will stop the session
    // However, we need to inform the adapter that the service has died
    if (nullptr == spGnssAntennaInfo) {
        LOC_LOGE("%s]: spGnssAntennaInfo is nullptr", __FUNCTION__);
        return;
    }
    if (nullptr == spGnssAntennaInfo->mGnss) {
        LOC_LOGE("%s]: spGnssAntennaInfo->mGnss is nullptr", __FUNCTION__);
        return;
    }

    spGnssAntennaInfo->mGnss->getGnssInterface()->antennaInfoClose();
}

static void convertGnssAntennaInfo(std::vector<GnssAntennaInformation>& in,
        hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& out) {

    uint32_t vecSize, numberOfRows, numberOfColumns;
    vecSize = in.size();
    out.resize(vecSize);
    for (uint32_t i = 0; i < vecSize; i++) {
        out[i].carrierFrequencyMHz = in[i].carrierFrequencyMHz;
        out[i].phaseCenterOffsetCoordinateMillimeters.x =
                in[i].phaseCenterOffsetCoordinateMillimeters.x;
        out[i].phaseCenterOffsetCoordinateMillimeters.xUncertainty =
                in[i].phaseCenterOffsetCoordinateMillimeters.xUncertainty;
        out[i].phaseCenterOffsetCoordinateMillimeters.y =
                in[i].phaseCenterOffsetCoordinateMillimeters.y;
        out[i].phaseCenterOffsetCoordinateMillimeters.yUncertainty =
                in[i].phaseCenterOffsetCoordinateMillimeters.yUncertainty;
        out[i].phaseCenterOffsetCoordinateMillimeters.z =
                in[i].phaseCenterOffsetCoordinateMillimeters.z;
        out[i].phaseCenterOffsetCoordinateMillimeters.zUncertainty =
                in[i].phaseCenterOffsetCoordinateMillimeters.zUncertainty;

        numberOfRows = in[i].phaseCenterVariationCorrectionMillimeters.size();
        out[i].phaseCenterVariationCorrectionMillimeters.resize(numberOfRows);
        for (uint32_t j = 0; j < numberOfRows; j++) {
            numberOfColumns = in[i].phaseCenterVariationCorrectionMillimeters[j].size();
            out[i].phaseCenterVariationCorrectionMillimeters[j].row.resize(numberOfColumns);
            for (uint32_t k = 0; k < numberOfColumns; k++) {
                out[i].phaseCenterVariationCorrectionMillimeters[j].row[k] =
                        in[i].phaseCenterVariationCorrectionMillimeters[j][k];
            }
        }

        numberOfRows = in[i].phaseCenterVariationCorrectionUncertaintyMillimeters.size();
        out[i].phaseCenterVariationCorrectionUncertaintyMillimeters.resize(numberOfRows);
        for (uint32_t j = 0; j < numberOfRows; j++) {
            numberOfColumns = in[i].phaseCenterVariationCorrectionUncertaintyMillimeters[j].size();
            out[i].phaseCenterVariationCorrectionUncertaintyMillimeters[j].
                    row.resize(numberOfColumns);
            for (uint32_t k = 0; k < numberOfColumns; k++) {
                out[i].phaseCenterVariationCorrectionUncertaintyMillimeters[j].row[k] =
                        in[i].phaseCenterVariationCorrectionUncertaintyMillimeters[j][k];
            }
        }

        numberOfRows = in[i].signalGainCorrectionDbi.size();
        out[i].signalGainCorrectionDbi.resize(numberOfRows);
        for (uint32_t j = 0; j < numberOfRows; j++) {
            numberOfColumns = in[i].signalGainCorrectionDbi[j].size();
            out[i].signalGainCorrectionDbi[j].row.resize(numberOfColumns);
            for (uint32_t k = 0; k < numberOfColumns; k++) {
                out[i].signalGainCorrectionDbi[j].row[k] = in[i].signalGainCorrectionDbi[j][k];
            }
        }

        numberOfRows = in[i].signalGainCorrectionUncertaintyDbi.size();
        out[i].signalGainCorrectionUncertaintyDbi.resize(numberOfRows);
        for (uint32_t j = 0; j < numberOfRows; j++) {
            numberOfColumns = in[i].signalGainCorrectionUncertaintyDbi[j].size();
            out[i].signalGainCorrectionUncertaintyDbi[j].row.resize(numberOfColumns);
            for (uint32_t k = 0; k < numberOfColumns; k++) {
                out[i].signalGainCorrectionUncertaintyDbi[j].row[k] =
                        in[i].signalGainCorrectionUncertaintyDbi[j][k];
            }
        }
    }
}

GnssAntennaInfo::GnssAntennaInfo(Gnss* gnss) : mGnss(gnss) {
    mGnssAntennaInfoDeathRecipient = new GnssAntennaInfoDeathRecipient(this);
    spGnssAntennaInfo = this;
}

GnssAntennaInfo::~GnssAntennaInfo() {
    spGnssAntennaInfo = nullptr;
}

// Methods from ::android::hardware::gnss::V2_1::IGnssAntennaInfo follow.
Return<GnssAntennaInfo::GnssAntennaInfoStatus>
        GnssAntennaInfo::setCallback(const sp<IGnssAntennaInfoCallback>& callback)  {
    uint32_t retValue;
    if (mGnss == nullptr) {
        LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
        return GnssAntennaInfoStatus::ERROR_GENERIC;
    }

    mGnssAntennaInfoCbIface = callback;
    retValue = mGnss->getGnssInterface()->antennaInfoInit(aiGnssAntennaInfoCb);

    switch (retValue) {
    case ANTENNA_INFO_SUCCESS: return GnssAntennaInfoStatus::SUCCESS;
    case ANTENNA_INFO_ERROR_ALREADY_INIT: return GnssAntennaInfoStatus::ERROR_ALREADY_INIT;
    case ANTENNA_INFO_ERROR_GENERIC:
    default: return GnssAntennaInfoStatus::ERROR_GENERIC;
    }
}

Return<void> GnssAntennaInfo::close(void)  {
    if (mGnss == nullptr) {
        LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__);
        return Void();
    }

    mGnss->getGnssInterface()->antennaInfoClose();

    return Void();
}

void GnssAntennaInfo::aiGnssAntennaInfoCb
        (std::vector<GnssAntennaInformation> gnssAntennaInformations) {
    if (nullptr != spGnssAntennaInfo) {
        spGnssAntennaInfo->gnssAntennaInfoCb(gnssAntennaInformations);
    }
}

void GnssAntennaInfo::gnssAntennaInfoCb
        (std::vector<GnssAntennaInformation> gnssAntennaInformations) {

    if (mGnssAntennaInfoCbIface != nullptr) {
        hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo> antennaInfos;

        // Convert from one structure to another
        convertGnssAntennaInfo(gnssAntennaInformations, antennaInfos);

        auto r = mGnssAntennaInfoCbIface->gnssAntennaInfoCb(antennaInfos);
        if (!r.isOk()) {
            LOC_LOGw("Error antenna info cb %s", r.description().c_str());
        }
    } else {
        LOC_LOGw("setCallback has not been called yet");
    }
}

}  // namespace implementation
}  // namespace V2_1
}  // namespace gnss
}  // namespace hardware
}  // namespace android


code:
/*
 * Copyright (c) 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 ANDROID_HARDWARE_GNSS_V2_1_GNSSANTENNAINFO_H
#define ANDROID_HARDWARE_GNSS_V2_1_GNSSANTENNAINFO_H

#include <android/hardware/gnss/2.1/IGnssAntennaInfo.h>
#include <hidl/Status.h>

namespace android {
namespace hardware {
namespace gnss {
namespace V2_1 {
namespace implementation {

using ::android::hardware::gnss::V2_1::IGnssAntennaInfo;
using ::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
using ::android::sp;

struct Gnss;
struct GnssAntennaInfo : public IGnssAntennaInfo {
    GnssAntennaInfo(Gnss* gnss);
    ~GnssAntennaInfo();

    /*
     * Methods from ::android::hardware::gnss::V1_1::IGnssAntennaInfo follow.
     * These declarations were generated from IGnssAntennaInfo.hal.
     */
    Return<GnssAntennaInfoStatus>
            setCallback(const sp<IGnssAntennaInfoCallback>& callback) override;
    Return<void> close(void) override;

    void gnssAntennaInfoCb(std::vector<GnssAntennaInformation> gnssAntennaInformations);

    static void aiGnssAntennaInfoCb(std::vector<GnssAntennaInformation> gnssAntennaInformations);

 private:
    struct GnssAntennaInfoDeathRecipient : hidl_death_recipient {
        GnssAntennaInfoDeathRecipient(sp<GnssAntennaInfo> gnssAntennaInfo) :
                mGnssAntennaInfo(gnssAntennaInfo) {
        }
        ~GnssAntennaInfoDeathRecipient() = default;
        virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
        sp<GnssAntennaInfo> mGnssAntennaInfo;
    };

 private:
    sp<GnssAntennaInfoDeathRecipient> mGnssAntennaInfoDeathRecipient = nullptr;
    sp<IGnssAntennaInfoCallback> mGnssAntennaInfoCbIface = nullptr;
    Gnss* mGnss = nullptr;
};

}  // namespace implementation
}  // namespace V2_1
}  // namespace gnss
}  // namespace hardware
}  // namespace android

#endif  // ANDROID_HARDWARE_GNSS_V2_1_GNSSANTENNAINFO_H