Files
hardware_interfaces/gnss/1.0/default/GnssMeasurement.cpp
Wyatt Riley 2525d9e579 Setting clock flags for GPS clock
Full bias nanosecond flag is now set correctly for
legacy GpsData (vs. modern GnssData) implementations
of gps.h measurements, going through default GNSS
HAL implementation.

Change-Id: Iec8f03994b6d9e509221e1323b54dc997319fccc
Fixes: 64482271
Test: Before/after on device with GnssLogger
2017-08-25 07:02:58 -07:00

261 lines
10 KiB
C++

/*
* 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 "GnssHAL_GnssMeasurementInterface"
#include "GnssMeasurement.h"
namespace android {
namespace hardware {
namespace gnss {
namespace V1_0 {
namespace implementation {
sp<IGnssMeasurementCallback> GnssMeasurement::sGnssMeasureCbIface = nullptr;
GpsMeasurementCallbacks GnssMeasurement::sGnssMeasurementCbs = {
.size = sizeof(GpsMeasurementCallbacks),
.measurement_callback = gpsMeasurementCb,
.gnss_measurement_callback = gnssMeasurementCb
};
GnssMeasurement::GnssMeasurement(const GpsMeasurementInterface* gpsMeasurementIface)
: mGnssMeasureIface(gpsMeasurementIface) {}
void GnssMeasurement::gnssMeasurementCb(LegacyGnssData* legacyGnssData) {
if (sGnssMeasureCbIface == nullptr) {
ALOGE("%s: GNSSMeasurement Callback Interface configured incorrectly", __func__);
return;
}
if (legacyGnssData == nullptr) {
ALOGE("%s: Invalid GnssData from GNSS HAL", __func__);
return;
}
IGnssMeasurementCallback::GnssData gnssData;
gnssData.measurementCount = std::min(legacyGnssData->measurement_count,
static_cast<size_t>(GnssMax::SVS_COUNT));
for (size_t i = 0; i < gnssData.measurementCount; i++) {
auto entry = legacyGnssData->measurements[i];
auto state = static_cast<GnssMeasurementState>(entry.state);
if (state & IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED) {
state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_KNOWN;
}
if (state & IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED) {
state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_KNOWN;
}
gnssData.measurements[i] = {
.flags = entry.flags,
.svid = entry.svid,
.constellation = static_cast<GnssConstellationType>(entry.constellation),
.timeOffsetNs = entry.time_offset_ns,
.state = state,
.receivedSvTimeInNs = entry.received_sv_time_in_ns,
.receivedSvTimeUncertaintyInNs = entry.received_sv_time_uncertainty_in_ns,
.cN0DbHz = entry.c_n0_dbhz,
.pseudorangeRateMps = entry.pseudorange_rate_mps,
.pseudorangeRateUncertaintyMps = entry.pseudorange_rate_uncertainty_mps,
.accumulatedDeltaRangeState = entry.accumulated_delta_range_state,
.accumulatedDeltaRangeM = entry.accumulated_delta_range_m,
.accumulatedDeltaRangeUncertaintyM = entry.accumulated_delta_range_uncertainty_m,
.carrierFrequencyHz = entry.carrier_frequency_hz,
.carrierCycles = entry.carrier_cycles,
.carrierPhase = entry.carrier_phase,
.carrierPhaseUncertainty = entry.carrier_phase_uncertainty,
.multipathIndicator = static_cast<IGnssMeasurementCallback::GnssMultipathIndicator>(
entry.multipath_indicator),
.snrDb = entry.snr_db
};
}
auto clockVal = legacyGnssData->clock;
gnssData.clock = {
.gnssClockFlags = clockVal.flags,
.leapSecond = clockVal.leap_second,
.timeNs = clockVal.time_ns,
.timeUncertaintyNs = clockVal.time_uncertainty_ns,
.fullBiasNs = clockVal.full_bias_ns,
.biasNs = clockVal.bias_ns,
.biasUncertaintyNs = clockVal.bias_uncertainty_ns,
.driftNsps = clockVal.drift_nsps,
.driftUncertaintyNsps = clockVal.drift_uncertainty_nsps,
.hwClockDiscontinuityCount = clockVal.hw_clock_discontinuity_count
};
auto ret = sGnssMeasureCbIface->GnssMeasurementCb(gnssData);
if (!ret.isOk()) {
ALOGE("%s: Unable to invoke callback", __func__);
}
}
/*
* The code in the following method has been moved here from GnssLocationProvider.
* It converts GpsData to GnssData. This code is no longer required in
* GnssLocationProvider since GpsData is deprecated and no longer part of the
* GNSS interface.
*/
void GnssMeasurement::gpsMeasurementCb(GpsData* gpsData) {
if (sGnssMeasureCbIface == nullptr) {
ALOGE("%s: GNSSMeasurement Callback Interface configured incorrectly", __func__);
return;
}
if (gpsData == nullptr) {
ALOGE("%s: Invalid GpsData from GNSS HAL", __func__);
return;
}
IGnssMeasurementCallback::GnssData gnssData;
gnssData.measurementCount = std::min(gpsData->measurement_count,
static_cast<size_t>(GnssMax::SVS_COUNT));
for (size_t i = 0; i < gnssData.measurementCount; i++) {
auto entry = gpsData->measurements[i];
gnssData.measurements[i].flags = entry.flags;
gnssData.measurements[i].svid = static_cast<int32_t>(entry.prn);
if (entry.prn >= 1 && entry.prn <= 32) {
gnssData.measurements[i].constellation = GnssConstellationType::GPS;
} else {
gnssData.measurements[i].constellation =
GnssConstellationType::UNKNOWN;
}
gnssData.measurements[i].timeOffsetNs = entry.time_offset_ns;
gnssData.measurements[i].state = entry.state;
gnssData.measurements[i].receivedSvTimeInNs = entry.received_gps_tow_ns;
gnssData.measurements[i].receivedSvTimeUncertaintyInNs =
entry.received_gps_tow_uncertainty_ns;
gnssData.measurements[i].cN0DbHz = entry.c_n0_dbhz;
gnssData.measurements[i].pseudorangeRateMps = entry.pseudorange_rate_mps;
gnssData.measurements[i].pseudorangeRateUncertaintyMps =
entry.pseudorange_rate_uncertainty_mps;
gnssData.measurements[i].accumulatedDeltaRangeState =
entry.accumulated_delta_range_state;
gnssData.measurements[i].accumulatedDeltaRangeM =
entry.accumulated_delta_range_m;
gnssData.measurements[i].accumulatedDeltaRangeUncertaintyM =
entry.accumulated_delta_range_uncertainty_m;
if (entry.flags & GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY) {
gnssData.measurements[i].carrierFrequencyHz = entry.carrier_frequency_hz;
} else {
gnssData.measurements[i].carrierFrequencyHz = 0;
}
if (entry.flags & GNSS_MEASUREMENT_HAS_CARRIER_PHASE) {
gnssData.measurements[i].carrierPhase = entry.carrier_phase;
} else {
gnssData.measurements[i].carrierPhase = 0;
}
if (entry.flags & GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY) {
gnssData.measurements[i].carrierPhaseUncertainty = entry.carrier_phase_uncertainty;
} else {
gnssData.measurements[i].carrierPhaseUncertainty = 0;
}
gnssData.measurements[i].multipathIndicator =
static_cast<IGnssMeasurementCallback::GnssMultipathIndicator>(
entry.multipath_indicator);
if (entry.flags & GNSS_MEASUREMENT_HAS_SNR) {
gnssData.measurements[i].snrDb = entry.snr_db;
} else {
gnssData.measurements[i].snrDb = 0;
}
}
auto clockVal = gpsData->clock;
static uint32_t discontinuity_count_to_handle_old_clock_type = 0;
gnssData.clock.leapSecond = clockVal.leap_second;
/*
* GnssClock only supports the more effective HW_CLOCK type, so type
* handling and documentation complexity has been removed. To convert the
* old GPS_CLOCK types (active only in a limited number of older devices),
* the GPS time information is handled as an always discontinuous HW clock,
* with the GPS time information put into the full_bias_ns instead - so that
* time_ns - full_bias_ns = local estimate of GPS time. Additionally, the
* sign of full_bias_ns and bias_ns has flipped between GpsClock &
* GnssClock, so that is also handled below.
*/
switch (clockVal.type) {
case GPS_CLOCK_TYPE_UNKNOWN:
// Clock type unsupported.
ALOGE("Unknown clock type provided.");
break;
case GPS_CLOCK_TYPE_LOCAL_HW_TIME:
// Already local hardware time. No need to do anything.
break;
case GPS_CLOCK_TYPE_GPS_TIME:
// GPS time, need to convert.
clockVal.flags |= GPS_CLOCK_HAS_FULL_BIAS;
clockVal.full_bias_ns = clockVal.time_ns;
clockVal.time_ns = 0;
gnssData.clock.hwClockDiscontinuityCount =
discontinuity_count_to_handle_old_clock_type++;
break;
}
gnssData.clock.timeNs = clockVal.time_ns;
gnssData.clock.timeUncertaintyNs = clockVal.time_uncertainty_ns;
/*
* Definition of sign for full_bias_ns & bias_ns has been changed since N,
* so flip signs here.
*/
gnssData.clock.fullBiasNs = -(clockVal.full_bias_ns);
gnssData.clock.biasNs = -(clockVal.bias_ns);
gnssData.clock.biasUncertaintyNs = clockVal.bias_uncertainty_ns;
gnssData.clock.driftNsps = clockVal.drift_nsps;
gnssData.clock.driftUncertaintyNsps = clockVal.drift_uncertainty_nsps;
gnssData.clock.gnssClockFlags = clockVal.flags;
auto ret = sGnssMeasureCbIface->GnssMeasurementCb(gnssData);
if (!ret.isOk()) {
ALOGE("%s: Unable to invoke callback", __func__);
}
}
// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
Return<GnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback(
const sp<IGnssMeasurementCallback>& callback) {
if (mGnssMeasureIface == nullptr) {
ALOGE("%s: GnssMeasure interface is unavailable", __func__);
return GnssMeasurementStatus::ERROR_GENERIC;
}
sGnssMeasureCbIface = callback;
return static_cast<GnssMeasurement::GnssMeasurementStatus>(
mGnssMeasureIface->init(&sGnssMeasurementCbs));
}
Return<void> GnssMeasurement::close() {
if (mGnssMeasureIface == nullptr) {
ALOGE("%s: GnssMeasure interface is unavailable", __func__);
} else {
mGnssMeasureIface->close();
}
return Void();
}
} // namespace implementation
} // namespace V1_0
} // namespace gnss
} // namespace hardware
} // namespace android