/* * Copyright (C) 2020 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 "GnssMeasCbJni" #include "GnssMeasurementCallback.h" namespace android::gnss { using binder::Status; using hardware::gnss::CorrelationVector; using hardware::gnss::ElapsedRealtime; using hardware::gnss::GnssClock; using hardware::gnss::GnssData; using hardware::gnss::GnssMeasurement; using hardware::gnss::SatellitePvt; using GnssAgc = hardware::gnss::GnssData::GnssAgc; namespace { jclass class_arrayList; jclass class_clockInfo; jclass class_correlationVectorBuilder; jclass class_gnssAgc; jclass class_gnssAgcBuilder; jclass class_gnssMeasurementsEvent; jclass class_gnssMeasurementsEventBuilder; jclass class_gnssMeasurement; jclass class_gnssClock; jclass class_positionEcef; jclass class_satellitePvtBuilder; jclass class_velocityEcef; jmethodID method_arrayListAdd; jmethodID method_arrayListCtor; jmethodID method_correlationVectorBuilderBuild; jmethodID method_correlationVectorBuilderCtor; jmethodID method_correlationVectorBuilderSetFrequencyOffsetMetersPerSecond; jmethodID method_correlationVectorBuilderSetMagnitude; jmethodID method_correlationVectorBuilderSetSamplingStartMeters; jmethodID method_correlationVectorBuilderSetSamplingWidthMeters; jmethodID method_gnssAgcBuilderCtor; jmethodID method_gnssAgcBuilderSetLevelDb; jmethodID method_gnssAgcBuilderSetConstellationType; jmethodID method_gnssAgcBuilderSetCarrierFrequencyHz; jmethodID method_gnssAgcBuilderBuild; jmethodID method_gnssMeasurementsEventBuilderCtor; jmethodID method_gnssMeasurementsEventBuilderSetClock; jmethodID method_gnssMeasurementsEventBuilderSetIsFullTracking; jmethodID method_gnssMeasurementsEventBuilderSetMeasurements; jmethodID method_gnssMeasurementsEventBuilderSetGnssAutomaticGainControls; jmethodID method_gnssMeasurementsEventBuilderBuild; jmethodID method_gnssMeasurementsSetCorrelationVectors; jmethodID method_gnssMeasurementsSetSatellitePvt; jmethodID method_gnssClockCtor; jmethodID method_gnssMeasurementCtor; jmethodID method_reportMeasurementData; jmethodID method_satellitePvtBuilderBuild; jmethodID method_satellitePvtBuilderCtor; jmethodID method_satellitePvtBuilderSetPositionEcef; jmethodID method_satellitePvtBuilderSetVelocityEcef; jmethodID method_satellitePvtBuilderSetClockInfo; jmethodID method_satellitePvtBuilderSetIonoDelayMeters; jmethodID method_satellitePvtBuilderSetTropoDelayMeters; jmethodID method_satellitePvtBuilderSetTimeOfClock; jmethodID method_satellitePvtBuilderSetTimeOfEphemeris; jmethodID method_satellitePvtBuilderSetIssueOfDataClock; jmethodID method_satellitePvtBuilderSetIssueOfDataEphemeris; jmethodID method_satellitePvtBuilderSetEphemerisSource; jmethodID method_positionEcef; jmethodID method_velocityEcef; jmethodID method_clockInfo; } // anonymous namespace void GnssMeasurement_class_init_once(JNIEnv* env, jclass& clazz) { method_reportMeasurementData = env->GetMethodID(clazz, "reportMeasurementData", "(Landroid/location/GnssMeasurementsEvent;)V"); // Initialize GnssMeasurement related classes and methods jclass gnssMeasurementsEventClass = env->FindClass("android/location/GnssMeasurementsEvent"); class_gnssMeasurementsEvent = (jclass)env->NewGlobalRef(gnssMeasurementsEventClass); jclass gnssMeasurementsEventBuilderClass = env->FindClass("android/location/GnssMeasurementsEvent$Builder"); class_gnssMeasurementsEventBuilder = (jclass)env->NewGlobalRef(gnssMeasurementsEventBuilderClass); method_gnssMeasurementsEventBuilderCtor = env->GetMethodID(class_gnssMeasurementsEventBuilder, "", "()V"); method_gnssMeasurementsEventBuilderSetClock = env->GetMethodID(class_gnssMeasurementsEventBuilder, "setClock", "(Landroid/location/GnssClock;)" "Landroid/location/GnssMeasurementsEvent$Builder;"); method_gnssMeasurementsEventBuilderSetMeasurements = env->GetMethodID(class_gnssMeasurementsEventBuilder, "setMeasurements", "([Landroid/location/GnssMeasurement;)" "Landroid/location/GnssMeasurementsEvent$Builder;"); method_gnssMeasurementsEventBuilderSetGnssAutomaticGainControls = env->GetMethodID(class_gnssMeasurementsEventBuilder, "setGnssAutomaticGainControls", "([Landroid/location/GnssAutomaticGainControl;)" "Landroid/location/GnssMeasurementsEvent$Builder;"); method_gnssMeasurementsEventBuilderSetIsFullTracking = env->GetMethodID(class_gnssMeasurementsEventBuilder, "setIsFullTracking", "(Z)" "Landroid/location/GnssMeasurementsEvent$Builder;"); method_gnssMeasurementsEventBuilderBuild = env->GetMethodID(class_gnssMeasurementsEventBuilder, "build", "()Landroid/location/GnssMeasurementsEvent;"); // Initialize GnssAgc related classes and methods jclass gnssAgcClass = env->FindClass("android/location/GnssAutomaticGainControl"); class_gnssAgc = (jclass)env->NewGlobalRef(gnssAgcClass); jclass gnssAgcBuilderClass = env->FindClass("android/location/GnssAutomaticGainControl$Builder"); class_gnssAgcBuilder = (jclass)env->NewGlobalRef(gnssAgcBuilderClass); method_gnssAgcBuilderCtor = env->GetMethodID(class_gnssAgcBuilder, "", "()V"); method_gnssAgcBuilderSetLevelDb = env->GetMethodID(class_gnssAgcBuilder, "setLevelDb", "(D)" "Landroid/location/GnssAutomaticGainControl$Builder;"); method_gnssAgcBuilderSetConstellationType = env->GetMethodID(class_gnssAgcBuilder, "setConstellationType", "(I)" "Landroid/location/GnssAutomaticGainControl$Builder;"); method_gnssAgcBuilderSetCarrierFrequencyHz = env->GetMethodID(class_gnssAgcBuilder, "setCarrierFrequencyHz", "(J)" "Landroid/location/GnssAutomaticGainControl$Builder;"); method_gnssAgcBuilderBuild = env->GetMethodID(class_gnssAgcBuilder, "build", "()Landroid/location/GnssAutomaticGainControl;"); // Initialize GnssMeasurement related classes and methods jclass gnssMeasurementClass = env->FindClass("android/location/GnssMeasurement"); class_gnssMeasurement = (jclass)env->NewGlobalRef(gnssMeasurementClass); method_gnssMeasurementCtor = env->GetMethodID(class_gnssMeasurement, "", "()V"); method_gnssMeasurementsSetSatellitePvt = env->GetMethodID(class_gnssMeasurement, "setSatellitePvt", "(Landroid/location/SatellitePvt;)V"); method_gnssMeasurementsSetCorrelationVectors = env->GetMethodID(class_gnssMeasurement, "setCorrelationVectors", "(Ljava/util/Collection;)V"); jclass gnssClockClass = env->FindClass("android/location/GnssClock"); class_gnssClock = (jclass)env->NewGlobalRef(gnssClockClass); method_gnssClockCtor = env->GetMethodID(class_gnssClock, "", "()V"); jclass satellitePvtBuilder = env->FindClass("android/location/SatellitePvt$Builder"); class_satellitePvtBuilder = (jclass)env->NewGlobalRef(satellitePvtBuilder); method_satellitePvtBuilderCtor = env->GetMethodID(class_satellitePvtBuilder, "", "()V"); method_satellitePvtBuilderSetPositionEcef = env->GetMethodID(class_satellitePvtBuilder, "setPositionEcef", "(Landroid/location/SatellitePvt$PositionEcef;)" "Landroid/location/SatellitePvt$Builder;"); method_satellitePvtBuilderSetVelocityEcef = env->GetMethodID(class_satellitePvtBuilder, "setVelocityEcef", "(Landroid/location/SatellitePvt$VelocityEcef;)" "Landroid/location/SatellitePvt$Builder;"); method_satellitePvtBuilderSetClockInfo = env->GetMethodID(class_satellitePvtBuilder, "setClockInfo", "(Landroid/location/SatellitePvt$ClockInfo;)" "Landroid/location/SatellitePvt$Builder;"); method_satellitePvtBuilderSetIonoDelayMeters = env->GetMethodID(class_satellitePvtBuilder, "setIonoDelayMeters", "(D)Landroid/location/SatellitePvt$Builder;"); method_satellitePvtBuilderSetTropoDelayMeters = env->GetMethodID(class_satellitePvtBuilder, "setTropoDelayMeters", "(D)Landroid/location/SatellitePvt$Builder;"); method_satellitePvtBuilderSetTimeOfClock = env->GetMethodID(class_satellitePvtBuilder, "setTimeOfClockSeconds", "(J)Landroid/location/SatellitePvt$Builder;"); method_satellitePvtBuilderSetTimeOfEphemeris = env->GetMethodID(class_satellitePvtBuilder, "setTimeOfEphemerisSeconds", "(J)Landroid/location/SatellitePvt$Builder;"); method_satellitePvtBuilderSetIssueOfDataClock = env->GetMethodID(class_satellitePvtBuilder, "setIssueOfDataClock", "(I)Landroid/location/SatellitePvt$Builder;"); method_satellitePvtBuilderSetIssueOfDataEphemeris = env->GetMethodID(class_satellitePvtBuilder, "setIssueOfDataEphemeris", "(I)Landroid/location/SatellitePvt$Builder;"); method_satellitePvtBuilderSetEphemerisSource = env->GetMethodID(class_satellitePvtBuilder, "setEphemerisSource", "(I)Landroid/location/SatellitePvt$Builder;"); method_satellitePvtBuilderBuild = env->GetMethodID(class_satellitePvtBuilder, "build", "()Landroid/location/SatellitePvt;"); jclass positionEcefClass = env->FindClass("android/location/SatellitePvt$PositionEcef"); class_positionEcef = (jclass)env->NewGlobalRef(positionEcefClass); method_positionEcef = env->GetMethodID(class_positionEcef, "", "(DDDD)V"); jclass velocityEcefClass = env->FindClass("android/location/SatellitePvt$VelocityEcef"); class_velocityEcef = (jclass)env->NewGlobalRef(velocityEcefClass); method_velocityEcef = env->GetMethodID(class_velocityEcef, "", "(DDDD)V"); jclass clockInfoClass = env->FindClass("android/location/SatellitePvt$ClockInfo"); class_clockInfo = (jclass)env->NewGlobalRef(clockInfoClass); method_clockInfo = env->GetMethodID(class_clockInfo, "", "(DDD)V"); jclass correlationVectorBuilder = env->FindClass("android/location/CorrelationVector$Builder"); class_correlationVectorBuilder = (jclass)env->NewGlobalRef(correlationVectorBuilder); method_correlationVectorBuilderCtor = env->GetMethodID(class_correlationVectorBuilder, "", "()V"); method_correlationVectorBuilderSetMagnitude = env->GetMethodID(class_correlationVectorBuilder, "setMagnitude", "([I)Landroid/location/CorrelationVector$Builder;"); method_correlationVectorBuilderSetFrequencyOffsetMetersPerSecond = env->GetMethodID(class_correlationVectorBuilder, "setFrequencyOffsetMetersPerSecond", "(D)Landroid/location/CorrelationVector$Builder;"); method_correlationVectorBuilderSetSamplingStartMeters = env->GetMethodID(class_correlationVectorBuilder, "setSamplingStartMeters", "(D)Landroid/location/CorrelationVector$Builder;"); method_correlationVectorBuilderSetSamplingWidthMeters = env->GetMethodID(class_correlationVectorBuilder, "setSamplingWidthMeters", "(D)Landroid/location/CorrelationVector$Builder;"); method_correlationVectorBuilderBuild = env->GetMethodID(class_correlationVectorBuilder, "build", "()Landroid/location/CorrelationVector;"); jclass arrayListClass = env->FindClass("java/util/ArrayList"); class_arrayList = (jclass)env->NewGlobalRef(arrayListClass); method_arrayListCtor = env->GetMethodID(class_arrayList, "", "()V"); method_arrayListAdd = env->GetMethodID(class_arrayList, "add", "(Ljava/lang/Object;)Z"); } void setMeasurementData(JNIEnv* env, jobject& callbacksObj, jobject clock, jobjectArray measurementArray, jobjectArray gnssAgcArray, bool hasIsFullTracking, jboolean isFullTracking) { jobject gnssMeasurementsEventBuilderObject = env->NewObject(class_gnssMeasurementsEventBuilder, method_gnssMeasurementsEventBuilderCtor); callObjectMethodIgnoringResult(env, gnssMeasurementsEventBuilderObject, method_gnssMeasurementsEventBuilderSetClock, clock); callObjectMethodIgnoringResult(env, gnssMeasurementsEventBuilderObject, method_gnssMeasurementsEventBuilderSetMeasurements, measurementArray); callObjectMethodIgnoringResult(env, gnssMeasurementsEventBuilderObject, method_gnssMeasurementsEventBuilderSetGnssAutomaticGainControls, gnssAgcArray); if (hasIsFullTracking) { callObjectMethodIgnoringResult(env, gnssMeasurementsEventBuilderObject, method_gnssMeasurementsEventBuilderSetIsFullTracking, isFullTracking); } jobject gnssMeasurementsEventObject = env->CallObjectMethod(gnssMeasurementsEventBuilderObject, method_gnssMeasurementsEventBuilderBuild); env->CallVoidMethod(callbacksObj, method_reportMeasurementData, gnssMeasurementsEventObject); checkAndClearExceptionFromCallback(env, __FUNCTION__); env->DeleteLocalRef(gnssMeasurementsEventBuilderObject); env->DeleteLocalRef(gnssMeasurementsEventObject); } template void setMeasurementFields_V1_0(const T_Measurement& measurement, JavaObject& object) { uint32_t flags = static_cast(measurement.flags); SET(Svid, static_cast(measurement.svid)); SET(TimeOffsetNanos, measurement.timeOffsetNs); SET(State, static_cast(measurement.state)); SET(ReceivedSvTimeNanos, measurement.receivedSvTimeInNs); SET(ReceivedSvTimeUncertaintyNanos, measurement.receivedSvTimeUncertaintyInNs); SET(PseudorangeRateMetersPerSecond, measurement.pseudorangeRateMps); SET(PseudorangeRateUncertaintyMetersPerSecond, measurement.pseudorangeRateUncertaintyMps); SET(AccumulatedDeltaRangeState, (static_cast(measurement.accumulatedDeltaRangeState) & ~ADR_STATE_HALF_CYCLE_REPORTED)); // Half Cycle state not reported from Hardware in V1_0 SET(AccumulatedDeltaRangeMeters, measurement.accumulatedDeltaRangeM); SET(AccumulatedDeltaRangeUncertaintyMeters, measurement.accumulatedDeltaRangeUncertaintyM); // Intentionally not copying deprecated fields of carrierCycles, // carrierPhase, carrierPhaseUncertainty SET(MultipathIndicator, static_cast(measurement.multipathIndicator)); if (flags & static_cast(T_Flags::HAS_SNR)) { SET(SnrInDb, measurement.snrDb); } if (flags & static_cast(T_Flags::HAS_AUTOMATIC_GAIN_CONTROL)) { SET(AutomaticGainControlLevelInDb, measurement.agcLevelDb); } } template void setMeasurementFields_V2_1(const T_Measurement& measurement, JavaObject& object) { SET(BasebandCn0DbHz, measurement.basebandCN0DbHz); if (measurement.flags & T_Flags::HAS_FULL_ISB) { SET(FullInterSignalBiasNanos, measurement.fullInterSignalBiasNs); } if (measurement.flags & T_Flags::HAS_FULL_ISB_UNCERTAINTY) { SET(FullInterSignalBiasUncertaintyNanos, measurement.fullInterSignalBiasUncertaintyNs); } if (measurement.flags & T_Flags::HAS_SATELLITE_ISB) { SET(SatelliteInterSignalBiasNanos, measurement.satelliteInterSignalBiasNs); } if (measurement.flags & T_Flags::HAS_SATELLITE_ISB_UNCERTAINTY) { SET(SatelliteInterSignalBiasUncertaintyNanos, measurement.satelliteInterSignalBiasUncertaintyNs); } } template void setClockFields_V1_0(const T_Clock& clock, JavaObject& object) { uint32_t flags = static_cast(clock.gnssClockFlags); if (flags & static_cast(T_Flags::HAS_LEAP_SECOND)) { SET(LeapSecond, static_cast(clock.leapSecond)); } if (flags & static_cast(T_Flags::HAS_TIME_UNCERTAINTY)) { SET(TimeUncertaintyNanos, clock.timeUncertaintyNs); } if (flags & static_cast(T_Flags::HAS_FULL_BIAS)) { SET(FullBiasNanos, clock.fullBiasNs); } if (flags & static_cast(T_Flags::HAS_BIAS)) { SET(BiasNanos, clock.biasNs); } if (flags & static_cast(T_Flags::HAS_BIAS_UNCERTAINTY)) { SET(BiasUncertaintyNanos, clock.biasUncertaintyNs); } if (flags & static_cast(T_Flags::HAS_DRIFT)) { SET(DriftNanosPerSecond, clock.driftNsps); } if (flags & static_cast(T_Flags::HAS_DRIFT_UNCERTAINTY)) { SET(DriftUncertaintyNanosPerSecond, clock.driftUncertaintyNsps); } SET(TimeNanos, clock.timeNs); SET(HardwareClockDiscontinuityCount, clock.hwClockDiscontinuityCount); } template void setClockFields_V2_1(const T_Clock& clock, JavaObject& object) { JNIEnv* env = getJniEnv(); SET(ReferenceConstellationTypeForIsb, static_cast(clock.referenceSignalTypeForIsb.constellation)); SET(ReferenceCarrierFrequencyHzForIsb, clock.referenceSignalTypeForIsb.carrierFrequencyHz); jstring referenceCodeTypeForIsb = env->NewStringUTF(clock.referenceSignalTypeForIsb.codeType.c_str()); SET(ReferenceCodeTypeForIsb, referenceCodeTypeForIsb); env->DeleteLocalRef(referenceCodeTypeForIsb); } template void setElapsedRealtimeFields(const T_ElapsedRealtime& elapsedRealtime, JavaObject& object) { uint32_t flags = static_cast(elapsedRealtime.flags); if (flags & T_Flags::HAS_TIMESTAMP_NS) { SET(ElapsedRealtimeNanos, static_cast(elapsedRealtime.timestampNs)); } if (flags & T_Flags::HAS_TIME_UNCERTAINTY_NS) { SET(ElapsedRealtimeUncertaintyNanos, static_cast(elapsedRealtime.timeUncertaintyNs)); } } // Implementation of GnssMeasurementCallbackAidl class. Status GnssMeasurementCallbackAidl::gnssMeasurementCb(const GnssData& data) { ALOGD("%s", __func__); translateAndSetGnssData(data); return Status::ok(); } void GnssMeasurementCallbackAidl::translateAndSetGnssData(const GnssData& data) { JNIEnv* env = getJniEnv(); JavaObject gnssClockJavaObject(env, class_gnssClock, method_gnssClockCtor); translateGnssClock(env, data, gnssClockJavaObject); jobject clock = gnssClockJavaObject.get(); jobjectArray measurementArray = translateAllGnssMeasurements(env, data.measurements); jobjectArray gnssAgcArray = nullptr; gnssAgcArray = translateAllGnssAgcs(env, data.gnssAgcs); if (interfaceVersion >= 3) { setMeasurementData(env, mCallbacksObj, clock, measurementArray, gnssAgcArray, /*hasIsFullTracking=*/true, data.isFullTracking); } else { setMeasurementData(env, mCallbacksObj, clock, measurementArray, gnssAgcArray, /*hasIsFullTracking=*/false, /*isFullTracking=*/JNI_FALSE); } env->DeleteLocalRef(clock); env->DeleteLocalRef(measurementArray); env->DeleteLocalRef(gnssAgcArray); } void GnssMeasurementCallbackAidl::translateSingleGnssMeasurement(JNIEnv* env, const GnssMeasurement& measurement, JavaObject& object) { setMeasurementFields_V1_0(measurement, object); setMeasurementFields_V2_1(measurement, object); SET(Cn0DbHz, measurement.antennaCN0DbHz); SET(ConstellationType, static_cast(measurement.signalType.constellation)); // Half cycle state is reported in the AIDL version of GnssMeasurement SET(AccumulatedDeltaRangeState, (static_cast(measurement.accumulatedDeltaRangeState) | ADR_STATE_HALF_CYCLE_REPORTED)); if (measurement.flags & static_cast(GnssMeasurement::HAS_CARRIER_FREQUENCY)) { SET(CarrierFrequencyHz, static_cast(measurement.signalType.carrierFrequencyHz)); } if (measurement.flags & static_cast(GnssMeasurement::HAS_SATELLITE_PVT)) { const SatellitePvt& satellitePvt = measurement.satellitePvt; uint16_t satFlags = static_cast(satellitePvt.flags); jobject positionEcef = nullptr; jobject velocityEcef = nullptr; jobject clockInfo = nullptr; jobject satellitePvtBuilderObject = env->NewObject(class_satellitePvtBuilder, method_satellitePvtBuilderCtor); if (satFlags & SatellitePvt::HAS_POSITION_VELOCITY_CLOCK_INFO) { positionEcef = env->NewObject(class_positionEcef, method_positionEcef, satellitePvt.satPosEcef.posXMeters, satellitePvt.satPosEcef.posYMeters, satellitePvt.satPosEcef.posZMeters, satellitePvt.satPosEcef.ureMeters); velocityEcef = env->NewObject(class_velocityEcef, method_velocityEcef, satellitePvt.satVelEcef.velXMps, satellitePvt.satVelEcef.velYMps, satellitePvt.satVelEcef.velZMps, satellitePvt.satVelEcef.ureRateMps); clockInfo = env->NewObject(class_clockInfo, method_clockInfo, satellitePvt.satClockInfo.satHardwareCodeBiasMeters, satellitePvt.satClockInfo.satTimeCorrectionMeters, satellitePvt.satClockInfo.satClkDriftMps); callObjectMethodIgnoringResult(env, satellitePvtBuilderObject, method_satellitePvtBuilderSetPositionEcef, positionEcef); callObjectMethodIgnoringResult(env, satellitePvtBuilderObject, method_satellitePvtBuilderSetVelocityEcef, velocityEcef); callObjectMethodIgnoringResult(env, satellitePvtBuilderObject, method_satellitePvtBuilderSetClockInfo, clockInfo); } if (satFlags & SatellitePvt::HAS_IONO) { callObjectMethodIgnoringResult(env, satellitePvtBuilderObject, method_satellitePvtBuilderSetIonoDelayMeters, satellitePvt.ionoDelayMeters); } if (satFlags & SatellitePvt::HAS_TROPO) { callObjectMethodIgnoringResult(env, satellitePvtBuilderObject, method_satellitePvtBuilderSetTropoDelayMeters, satellitePvt.tropoDelayMeters); } if (interfaceVersion >= 2) { callObjectMethodIgnoringResult(env, satellitePvtBuilderObject, method_satellitePvtBuilderSetTimeOfClock, satellitePvt.timeOfClockSeconds); callObjectMethodIgnoringResult(env, satellitePvtBuilderObject, method_satellitePvtBuilderSetTimeOfEphemeris, satellitePvt.timeOfEphemerisSeconds); callObjectMethodIgnoringResult(env, satellitePvtBuilderObject, method_satellitePvtBuilderSetIssueOfDataClock, satellitePvt.issueOfDataClock); callObjectMethodIgnoringResult(env, satellitePvtBuilderObject, method_satellitePvtBuilderSetIssueOfDataEphemeris, satellitePvt.issueOfDataEphemeris); callObjectMethodIgnoringResult(env, satellitePvtBuilderObject, method_satellitePvtBuilderSetEphemerisSource, static_cast(satellitePvt.ephemerisSource)); } jobject satellitePvtObject = env->CallObjectMethod(satellitePvtBuilderObject, method_satellitePvtBuilderBuild); env->CallVoidMethod(object.get(), method_gnssMeasurementsSetSatellitePvt, satellitePvtObject); env->DeleteLocalRef(positionEcef); env->DeleteLocalRef(velocityEcef); env->DeleteLocalRef(clockInfo); env->DeleteLocalRef(satellitePvtBuilderObject); env->DeleteLocalRef(satellitePvtObject); } if (measurement.flags & static_cast(GnssMeasurement::HAS_CORRELATION_VECTOR)) { jobject correlationVectorList = env->NewObject(class_arrayList, method_arrayListCtor); for (uint16_t i = 0; i < measurement.correlationVectors.size(); ++i) { const CorrelationVector& correlationVector = measurement.correlationVectors[i]; const std::vector& magnitudeVector = correlationVector.magnitude; jsize numMagnitude = magnitudeVector.size(); jintArray magnitudeArray = env->NewIntArray(numMagnitude); env->SetIntArrayRegion(magnitudeArray, 0, numMagnitude, reinterpret_cast(magnitudeVector.data())); jobject correlationVectorBuilderObject = env->NewObject(class_correlationVectorBuilder, method_correlationVectorBuilderCtor); callObjectMethodIgnoringResult(env, correlationVectorBuilderObject, method_correlationVectorBuilderSetMagnitude, magnitudeArray); callObjectMethodIgnoringResult( env, correlationVectorBuilderObject, method_correlationVectorBuilderSetFrequencyOffsetMetersPerSecond, correlationVector.frequencyOffsetMps); callObjectMethodIgnoringResult(env, correlationVectorBuilderObject, method_correlationVectorBuilderSetSamplingStartMeters, correlationVector.samplingStartM); callObjectMethodIgnoringResult(env, correlationVectorBuilderObject, method_correlationVectorBuilderSetSamplingWidthMeters, correlationVector.samplingWidthM); jobject correlationVectorObject = env->CallObjectMethod(correlationVectorBuilderObject, method_correlationVectorBuilderBuild); env->CallBooleanMethod(correlationVectorList, method_arrayListAdd, correlationVectorObject); env->DeleteLocalRef(magnitudeArray); env->DeleteLocalRef(correlationVectorBuilderObject); env->DeleteLocalRef(correlationVectorObject); } env->CallVoidMethod(object.get(), method_gnssMeasurementsSetCorrelationVectors, correlationVectorList); env->DeleteLocalRef(correlationVectorList); } jstring codeType = env->NewStringUTF(measurement.signalType.codeType.c_str()); SET(CodeType, codeType); env->DeleteLocalRef(codeType); } jobjectArray GnssMeasurementCallbackAidl::translateAllGnssMeasurements( JNIEnv* env, const std::vector& measurements) { if (measurements.size() == 0) { return nullptr; } jobjectArray gnssMeasurementArray = env->NewObjectArray(measurements.size(), class_gnssMeasurement, nullptr /* initialElement */); for (uint16_t i = 0; i < measurements.size(); ++i) { JavaObject object(env, class_gnssMeasurement, method_gnssMeasurementCtor); translateSingleGnssMeasurement(env, measurements[i], object); jobject gnssMeasurement = object.get(); env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement); env->DeleteLocalRef(gnssMeasurement); } return gnssMeasurementArray; } jobjectArray GnssMeasurementCallbackAidl::translateAllGnssAgcs(JNIEnv* env, const std::vector& agcs) { if (agcs.size() == 0) { return nullptr; } jobjectArray gnssAgcArray = env->NewObjectArray(agcs.size(), class_gnssAgc, nullptr /* initialElement */); for (uint16_t i = 0; i < agcs.size(); ++i) { const GnssAgc& gnssAgc = agcs[i]; jobject agcBuilderObject = env->NewObject(class_gnssAgcBuilder, method_gnssAgcBuilderCtor); callObjectMethodIgnoringResult(env, agcBuilderObject, method_gnssAgcBuilderSetLevelDb, gnssAgc.agcLevelDb); callObjectMethodIgnoringResult(env, agcBuilderObject, method_gnssAgcBuilderSetConstellationType, (int)gnssAgc.constellation); callObjectMethodIgnoringResult(env, agcBuilderObject, method_gnssAgcBuilderSetCarrierFrequencyHz, gnssAgc.carrierFrequencyHz); jobject agcObject = env->CallObjectMethod(agcBuilderObject, method_gnssAgcBuilderBuild); env->SetObjectArrayElement(gnssAgcArray, i, agcObject); env->DeleteLocalRef(agcBuilderObject); env->DeleteLocalRef(agcObject); } return gnssAgcArray; } void GnssMeasurementCallbackAidl::translateGnssClock(JNIEnv* env, const GnssData& data, JavaObject& object) { setElapsedRealtimeFields(data.elapsedRealtime, object); setClockFields_V1_0(data.clock, object); setClockFields_V2_1(data.clock, object); } // Implementation of GnssMeasurementCallbackHidl class. hardware::Return GnssMeasurementCallbackHidl::gnssMeasurementCb_2_1( const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssData& data) { translateAndSetGnssData(data); return hardware::Void(); } hardware::Return GnssMeasurementCallbackHidl::gnssMeasurementCb_2_0( const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssData& data) { translateAndSetGnssData(data); return hardware::Void(); } hardware::Return GnssMeasurementCallbackHidl::gnssMeasurementCb( const hardware::gnss::V1_1::IGnssMeasurementCallback::GnssData& data) { translateAndSetGnssData(data); return hardware::Void(); } hardware::Return GnssMeasurementCallbackHidl::GnssMeasurementCb( const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData& data) { translateAndSetGnssData(data); return hardware::Void(); } template <> size_t GnssMeasurementCallbackHidl::getMeasurementCount< hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData>( const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData& data) { return data.measurementCount; } // Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement"); template <> void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement< hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement>( const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement& measurement, JavaObject& object) { setMeasurementFields_V1_0(measurement, object); SET(ConstellationType, static_cast(measurement.constellation)); SET(Cn0DbHz, measurement.cN0DbHz); if (measurement.flags & static_cast(GnssMeasurementFlags::HAS_CARRIER_FREQUENCY)) { SET(CarrierFrequencyHz, measurement.carrierFrequencyHz); } } // Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement"); template <> void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement< hardware::gnss::V1_1::IGnssMeasurementCallback::GnssMeasurement>( const hardware::gnss::V1_1::IGnssMeasurementCallback::GnssMeasurement& measurement_V1_1, JavaObject& object) { translateSingleGnssMeasurement(measurement_V1_1.v1_0, object); // Half cycle state is reported in HIDL v1.1 or newer. SET(AccumulatedDeltaRangeState, (static_cast(measurement_V1_1.accumulatedDeltaRangeState) | ADR_STATE_HALF_CYCLE_REPORTED)); } // Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement"); template <> void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement< hardware::gnss::V2_0::IGnssMeasurementCallback::GnssMeasurement>( const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssMeasurement& measurement_V2_0, JavaObject& object) { JNIEnv* env = getJniEnv(); translateSingleGnssMeasurement(measurement_V2_0.v1_1, object); jstring codeType = env->NewStringUTF(measurement_V2_0.codeType.c_str()); SET(CodeType, codeType); // Overwrite with v2_0.state since V2_0.v1_1.v1_0.state is deprecated. SET(State, static_cast(measurement_V2_0.state)); // Overwrite with v2_0.constellation since V2_0.v1_1.v1_0.constellation is deprecated. SET(ConstellationType, static_cast(measurement_V2_0.constellation)); if (codeType) { env->DeleteLocalRef(codeType); } } // Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement"); template <> void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement< hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement>( const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement& measurement_V2_1, JavaObject& object) { translateSingleGnssMeasurement(measurement_V2_1.v2_0, object); setMeasurementFields_V2_1(measurement_V2_1, object); } template <> void GnssMeasurementCallbackHidl::translateGnssClock( const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssClock& clock, JavaObject& object) { setClockFields_V1_0(clock, object); } template <> void GnssMeasurementCallbackHidl::translateGnssClock( const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssClock& clock, JavaObject& object) { setClockFields_V2_1(clock, object); translateGnssClock(clock.v1_0, object); } template <> void GnssMeasurementCallbackHidl::translateGnssClock( const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssData& data, JavaObject& object) { setElapsedRealtimeFields(data.elapsedRealtime, object); translateGnssClock(data.clock, object); } template <> void GnssMeasurementCallbackHidl::translateGnssClock( const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssData& data, JavaObject& object) { auto elapsedRealtime = data.elapsedRealtime; uint16_t flags = static_cast(elapsedRealtime.flags); if (flags & hardware::gnss::V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) { SET(ElapsedRealtimeNanos, static_cast(elapsedRealtime.timestampNs)); } if (flags & hardware::gnss::V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS) { SET(ElapsedRealtimeUncertaintyNanos, static_cast(elapsedRealtime.timeUncertaintyNs)); } translateGnssClock(data.clock, object); } } // namespace android::gnss