| /* |
| * 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, "<init>", "()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, "<init>", "()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, "<init>", "()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, "<init>", "()V"); |
| |
| jclass satellitePvtBuilder = env->FindClass("android/location/SatellitePvt$Builder"); |
| class_satellitePvtBuilder = (jclass)env->NewGlobalRef(satellitePvtBuilder); |
| method_satellitePvtBuilderCtor = env->GetMethodID(class_satellitePvtBuilder, "<init>", "()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, "<init>", "(DDDD)V"); |
| |
| jclass velocityEcefClass = env->FindClass("android/location/SatellitePvt$VelocityEcef"); |
| class_velocityEcef = (jclass)env->NewGlobalRef(velocityEcefClass); |
| method_velocityEcef = env->GetMethodID(class_velocityEcef, "<init>", "(DDDD)V"); |
| |
| jclass clockInfoClass = env->FindClass("android/location/SatellitePvt$ClockInfo"); |
| class_clockInfo = (jclass)env->NewGlobalRef(clockInfoClass); |
| method_clockInfo = env->GetMethodID(class_clockInfo, "<init>", "(DDD)V"); |
| |
| jclass correlationVectorBuilder = env->FindClass("android/location/CorrelationVector$Builder"); |
| class_correlationVectorBuilder = (jclass)env->NewGlobalRef(correlationVectorBuilder); |
| method_correlationVectorBuilderCtor = |
| env->GetMethodID(class_correlationVectorBuilder, "<init>", "()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, "<init>", "()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 <class T_Measurement, class T_Flags> |
| void setMeasurementFields_V1_0(const T_Measurement& measurement, JavaObject& object) { |
| uint32_t flags = static_cast<uint32_t>(measurement.flags); |
| |
| SET(Svid, static_cast<int32_t>(measurement.svid)); |
| SET(TimeOffsetNanos, measurement.timeOffsetNs); |
| SET(State, static_cast<int32_t>(measurement.state)); |
| SET(ReceivedSvTimeNanos, measurement.receivedSvTimeInNs); |
| SET(ReceivedSvTimeUncertaintyNanos, measurement.receivedSvTimeUncertaintyInNs); |
| SET(PseudorangeRateMetersPerSecond, measurement.pseudorangeRateMps); |
| SET(PseudorangeRateUncertaintyMetersPerSecond, measurement.pseudorangeRateUncertaintyMps); |
| SET(AccumulatedDeltaRangeState, |
| (static_cast<int32_t>(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<int32_t>(measurement.multipathIndicator)); |
| |
| if (flags & static_cast<uint32_t>(T_Flags::HAS_SNR)) { |
| SET(SnrInDb, measurement.snrDb); |
| } |
| |
| if (flags & static_cast<uint32_t>(T_Flags::HAS_AUTOMATIC_GAIN_CONTROL)) { |
| SET(AutomaticGainControlLevelInDb, measurement.agcLevelDb); |
| } |
| } |
| |
| template <class T_Measurement, class T_Flags> |
| 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 <class T_Clock, class T_Flags> |
| void setClockFields_V1_0(const T_Clock& clock, JavaObject& object) { |
| uint32_t flags = static_cast<uint32_t>(clock.gnssClockFlags); |
| if (flags & static_cast<uint32_t>(T_Flags::HAS_LEAP_SECOND)) { |
| SET(LeapSecond, static_cast<int32_t>(clock.leapSecond)); |
| } |
| |
| if (flags & static_cast<uint32_t>(T_Flags::HAS_TIME_UNCERTAINTY)) { |
| SET(TimeUncertaintyNanos, clock.timeUncertaintyNs); |
| } |
| |
| if (flags & static_cast<uint32_t>(T_Flags::HAS_FULL_BIAS)) { |
| SET(FullBiasNanos, clock.fullBiasNs); |
| } |
| |
| if (flags & static_cast<uint32_t>(T_Flags::HAS_BIAS)) { |
| SET(BiasNanos, clock.biasNs); |
| } |
| |
| if (flags & static_cast<uint32_t>(T_Flags::HAS_BIAS_UNCERTAINTY)) { |
| SET(BiasUncertaintyNanos, clock.biasUncertaintyNs); |
| } |
| |
| if (flags & static_cast<uint32_t>(T_Flags::HAS_DRIFT)) { |
| SET(DriftNanosPerSecond, clock.driftNsps); |
| } |
| |
| if (flags & static_cast<uint32_t>(T_Flags::HAS_DRIFT_UNCERTAINTY)) { |
| SET(DriftUncertaintyNanosPerSecond, clock.driftUncertaintyNsps); |
| } |
| |
| SET(TimeNanos, clock.timeNs); |
| SET(HardwareClockDiscontinuityCount, clock.hwClockDiscontinuityCount); |
| } |
| |
| template <class T_Clock, class T_Flags> |
| void setClockFields_V2_1(const T_Clock& clock, JavaObject& object) { |
| JNIEnv* env = getJniEnv(); |
| SET(ReferenceConstellationTypeForIsb, |
| static_cast<int32_t>(clock.referenceSignalTypeForIsb.constellation)); |
| SET(ReferenceCarrierFrequencyHzForIsb, clock.referenceSignalTypeForIsb.carrierFrequencyHz); |
| |
| jstring referenceCodeTypeForIsb = |
| env->NewStringUTF(clock.referenceSignalTypeForIsb.codeType.c_str()); |
| SET(ReferenceCodeTypeForIsb, referenceCodeTypeForIsb); |
| env->DeleteLocalRef(referenceCodeTypeForIsb); |
| } |
| |
| template <class T_ElapsedRealtime, class T_Flags> |
| void setElapsedRealtimeFields(const T_ElapsedRealtime& elapsedRealtime, JavaObject& object) { |
| uint32_t flags = static_cast<uint32_t>(elapsedRealtime.flags); |
| if (flags & T_Flags::HAS_TIMESTAMP_NS) { |
| SET(ElapsedRealtimeNanos, static_cast<uint64_t>(elapsedRealtime.timestampNs)); |
| } |
| if (flags & T_Flags::HAS_TIME_UNCERTAINTY_NS) { |
| SET(ElapsedRealtimeUncertaintyNanos, |
| static_cast<double>(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 (this->getInterfaceVersion() >= 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<GnssMeasurement, GnssMeasurement>(measurement, object); |
| setMeasurementFields_V2_1<GnssMeasurement, GnssMeasurement>(measurement, object); |
| |
| SET(Cn0DbHz, measurement.antennaCN0DbHz); |
| SET(ConstellationType, static_cast<int32_t>(measurement.signalType.constellation)); |
| // Half cycle state is reported in the AIDL version of GnssMeasurement |
| SET(AccumulatedDeltaRangeState, |
| (static_cast<int32_t>(measurement.accumulatedDeltaRangeState) | |
| ADR_STATE_HALF_CYCLE_REPORTED)); |
| |
| if (measurement.flags & static_cast<uint32_t>(GnssMeasurement::HAS_CARRIER_FREQUENCY)) { |
| SET(CarrierFrequencyHz, static_cast<float>(measurement.signalType.carrierFrequencyHz)); |
| } |
| |
| if (measurement.flags & static_cast<uint32_t>(GnssMeasurement::HAS_SATELLITE_PVT)) { |
| const SatellitePvt& satellitePvt = measurement.satellitePvt; |
| uint16_t satFlags = static_cast<uint16_t>(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 (this->getInterfaceVersion() >= 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<int>(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<uint32_t>(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<int32_t>& magnitudeVector = correlationVector.magnitude; |
| |
| jsize numMagnitude = magnitudeVector.size(); |
| jintArray magnitudeArray = env->NewIntArray(numMagnitude); |
| env->SetIntArrayRegion(magnitudeArray, 0, numMagnitude, |
| reinterpret_cast<const jint*>(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<GnssMeasurement>& 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<GnssAgc>& 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<ElapsedRealtime, ElapsedRealtime>(data.elapsedRealtime, object); |
| setClockFields_V1_0<GnssClock, GnssClock>(data.clock, object); |
| setClockFields_V2_1<GnssClock, GnssClock>(data.clock, object); |
| } |
| |
| // Implementation of GnssMeasurementCallbackHidl class. |
| |
| hardware::Return<void> GnssMeasurementCallbackHidl::gnssMeasurementCb_2_1( |
| const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssData& data) { |
| translateAndSetGnssData(data); |
| return hardware::Void(); |
| } |
| |
| hardware::Return<void> GnssMeasurementCallbackHidl::gnssMeasurementCb_2_0( |
| const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssData& data) { |
| translateAndSetGnssData(data); |
| return hardware::Void(); |
| } |
| |
| hardware::Return<void> GnssMeasurementCallbackHidl::gnssMeasurementCb( |
| const hardware::gnss::V1_1::IGnssMeasurementCallback::GnssData& data) { |
| translateAndSetGnssData(data); |
| return hardware::Void(); |
| } |
| |
| hardware::Return<void> 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<hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement, |
| GnssMeasurementFlags>(measurement, object); |
| |
| SET(ConstellationType, static_cast<int32_t>(measurement.constellation)); |
| SET(Cn0DbHz, measurement.cN0DbHz); |
| if (measurement.flags & static_cast<uint32_t>(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<int32_t>(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<int32_t>(measurement_V2_0.state)); |
| |
| // Overwrite with v2_0.constellation since V2_0.v1_1.v1_0.constellation is deprecated. |
| SET(ConstellationType, static_cast<int32_t>(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<hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement, |
| GnssMeasurementFlags>(measurement_V2_1, object); |
| } |
| |
| template <> |
| void GnssMeasurementCallbackHidl::translateGnssClock( |
| const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssClock& clock, |
| JavaObject& object) { |
| setClockFields_V1_0<hardware::gnss::V1_0::IGnssMeasurementCallback::GnssClock, |
| GnssClockFlags>(clock, object); |
| } |
| |
| template <> |
| void GnssMeasurementCallbackHidl::translateGnssClock( |
| const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssClock& clock, |
| JavaObject& object) { |
| setClockFields_V2_1<hardware::gnss::V2_1::IGnssMeasurementCallback::GnssClock, |
| GnssClockFlags>(clock, object); |
| translateGnssClock(clock.v1_0, object); |
| } |
| |
| template <> |
| void GnssMeasurementCallbackHidl::translateGnssClock( |
| const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssData& data, JavaObject& object) { |
| setElapsedRealtimeFields<hardware::gnss::V2_0::ElapsedRealtime, |
| hardware::gnss::V2_0::ElapsedRealtimeFlags>(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<uint16_t>(elapsedRealtime.flags); |
| if (flags & hardware::gnss::V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) { |
| SET(ElapsedRealtimeNanos, static_cast<uint64_t>(elapsedRealtime.timestampNs)); |
| } |
| if (flags & hardware::gnss::V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS) { |
| SET(ElapsedRealtimeUncertaintyNanos, |
| static_cast<double>(elapsedRealtime.timeUncertaintyNs)); |
| } |
| translateGnssClock(data.clock, object); |
| } |
| |
| } // namespace android::gnss |