From af90af79315d30ce62131bc43a828b57bade78ba Mon Sep 17 00:00:00 2001 From: Yu-Han Yang Date: Wed, 29 Dec 2021 15:58:42 -0800 Subject: [PATCH] Add GnssAutomaticGainControl to GnssMeasurementsEvent (frameworks/base) AgcLevelDb has been a subfield of GnssMeasurement. However, GnssMeasurement is only reported by the chipset when there is GNSS signal. For example, in deep indoor, or when there is strong jamming signal, no GnssMeasurement can be reported, and thus no AGC value can be reported. To resolve that, we are adding this GnssAgc to GnssMeasurementsEvent directly, so that the client can get AGC values even without GNSS signal (i.e., without GnssMeasurement). Bug: 206670536 Test: atest GnssAutomaticGainControlTest atest GnssMeasurementsEventTest Change-Id: I97c7ec98b6e8cc977c6e879b52a8cf75c355ae33 --- core/api/current.txt | 32 ++- core/api/test-current.txt | 6 +- .../location/GnssAutomaticGainControl.aidl | 19 ++ .../location/GnssAutomaticGainControl.java | 215 ++++++++++++++++++ .../android/location/GnssMeasurement.java | 8 + .../location/GnssMeasurementsEvent.java | 167 ++++++++++---- .../core/jni/gnss/GnssMeasurementCallback.cpp | 127 ++++++++++- .../core/jni/gnss/GnssMeasurementCallback.h | 6 +- 8 files changed, 515 insertions(+), 65 deletions(-) create mode 100644 location/java/android/location/GnssAutomaticGainControl.aidl create mode 100644 location/java/android/location/GnssAutomaticGainControl.java diff --git a/core/api/current.txt b/core/api/current.txt index a0f6500276902..77e1a4ff63d39 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -20140,6 +20140,24 @@ package android.location { field @NonNull public static final android.os.Parcelable.Creator CREATOR; } + public final class GnssAutomaticGainControl implements android.os.Parcelable { + method public int describeContents(); + method @IntRange(from=0) public long getCarrierFrequencyHz(); + method public int getConstellationType(); + method @FloatRange(from=0xffffd8f0, to=10000) public double getLevelDb(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public static final class GnssAutomaticGainControl.Builder { + ctor public GnssAutomaticGainControl.Builder(); + ctor public GnssAutomaticGainControl.Builder(@NonNull android.location.GnssAutomaticGainControl); + method @NonNull public android.location.GnssAutomaticGainControl build(); + method @NonNull public android.location.GnssAutomaticGainControl.Builder setCarrierFrequencyHz(@IntRange(from=0) long); + method @NonNull public android.location.GnssAutomaticGainControl.Builder setConstellationType(int); + method @NonNull public android.location.GnssAutomaticGainControl.Builder setLevelDb(@FloatRange(from=0xffffd8f0, to=10000) double); + } + public final class GnssCapabilities implements android.os.Parcelable { method public int describeContents(); method public boolean hasAntennaInfo(); @@ -20196,7 +20214,7 @@ package android.location { method public double getAccumulatedDeltaRangeMeters(); method public int getAccumulatedDeltaRangeState(); method public double getAccumulatedDeltaRangeUncertaintyMeters(); - method public double getAutomaticGainControlLevelDb(); + method @Deprecated public double getAutomaticGainControlLevelDb(); method @FloatRange(from=0, to=63) public double getBasebandCn0DbHz(); method @Deprecated public long getCarrierCycles(); method public float getCarrierFrequencyHz(); @@ -20218,7 +20236,7 @@ package android.location { method public int getState(); method public int getSvid(); method public double getTimeOffsetNanos(); - method public boolean hasAutomaticGainControlLevelDb(); + method @Deprecated public boolean hasAutomaticGainControlLevelDb(); method public boolean hasBasebandCn0DbHz(); method @Deprecated public boolean hasCarrierCycles(); method public boolean hasCarrierFrequencyHz(); @@ -20280,11 +20298,21 @@ package android.location { public final class GnssMeasurementsEvent implements android.os.Parcelable { method public int describeContents(); method @NonNull public android.location.GnssClock getClock(); + method @NonNull public java.util.Collection getGnssAutomaticGainControls(); method @NonNull public java.util.Collection getMeasurements(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator CREATOR; } + public static final class GnssMeasurementsEvent.Builder { + ctor public GnssMeasurementsEvent.Builder(); + ctor public GnssMeasurementsEvent.Builder(@NonNull android.location.GnssMeasurementsEvent); + method @NonNull public android.location.GnssMeasurementsEvent build(); + method @NonNull public android.location.GnssMeasurementsEvent.Builder setClock(@NonNull android.location.GnssClock); + method @NonNull public android.location.GnssMeasurementsEvent.Builder setGnssAutomaticGainControls(@NonNull java.util.Collection); + method @NonNull public android.location.GnssMeasurementsEvent.Builder setMeasurements(@NonNull java.util.Collection); + } + public abstract static class GnssMeasurementsEvent.Callback { ctor public GnssMeasurementsEvent.Callback(); method public void onGnssMeasurementsReceived(android.location.GnssMeasurementsEvent); diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 66250fcebe926..75bafa9051206 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -1319,7 +1319,7 @@ package android.location { method public void setAccumulatedDeltaRangeMeters(double); method public void setAccumulatedDeltaRangeState(int); method public void setAccumulatedDeltaRangeUncertaintyMeters(double); - method public void setAutomaticGainControlLevelInDb(double); + method @Deprecated public void setAutomaticGainControlLevelInDb(double); method public void setBasebandCn0DbHz(double); method @Deprecated public void setCarrierCycles(long); method public void setCarrierFrequencyHz(float); @@ -1346,10 +1346,6 @@ package android.location { field public static final int ADR_STATE_ALL = 31; // 0x1f } - public final class GnssMeasurementsEvent implements android.os.Parcelable { - ctor public GnssMeasurementsEvent(android.location.GnssClock, android.location.GnssMeasurement[]); - } - public final class GnssNavigationMessage implements android.os.Parcelable { ctor public GnssNavigationMessage(); method public void reset(); diff --git a/location/java/android/location/GnssAutomaticGainControl.aidl b/location/java/android/location/GnssAutomaticGainControl.aidl new file mode 100644 index 0000000000000..8298cb7110645 --- /dev/null +++ b/location/java/android/location/GnssAutomaticGainControl.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2022 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. + */ + +package android.location; + +parcelable GnssAutomaticGainControl; diff --git a/location/java/android/location/GnssAutomaticGainControl.java b/location/java/android/location/GnssAutomaticGainControl.java new file mode 100644 index 0000000000000..e4f7304a8c9db --- /dev/null +++ b/location/java/android/location/GnssAutomaticGainControl.java @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2022 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. + */ + +package android.location; + +import android.annotation.FloatRange; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.util.Preconditions; + +import java.util.Objects; + +/** + * A class that contains GNSS Automatic Gain Control (AGC) information. + * + *

AGC acts as a variable gain amplifier adjusting the power of the incoming signal. The AGC + * level may be used to indicate potential interference. Higher gain (and/or lower input power) + * shall be output as a positive number. Hence in cases of strong jamming, in the band of this + * signal, this value will go more negative. This value must be consistent given the same level + * of the incoming signal power. + * + *

Note: Different hardware designs (e.g. antenna, pre-amplification, or other RF HW + * components) may also affect the typical output of this value on any given hardware design + * in an open sky test - the important aspect of this output is that changes in this value are + * indicative of changes on input signal power in the frequency band for this measurement. + */ +public final class GnssAutomaticGainControl implements Parcelable { + private final double mLevelDb; + private final int mConstellationType; + private final long mCarrierFrequencyHz; + + /** + * Creates a {@link GnssAutomaticGainControl} with a full list of parameters. + */ + private GnssAutomaticGainControl(double levelDb, int constellationType, + long carrierFrequencyHz) { + mLevelDb = levelDb; + mConstellationType = constellationType; + mCarrierFrequencyHz = carrierFrequencyHz; + } + + /** + * Gets the Automatic Gain Control level in dB. + */ + @FloatRange(from = -10000, to = 10000) + public double getLevelDb() { + return mLevelDb; + } + + /** + * Gets the constellation type. + * + *

The return value is one of those constants with {@code CONSTELLATION_} prefix in + * {@link GnssStatus}. + */ + @GnssStatus.ConstellationType + public int getConstellationType() { + return mConstellationType; + } + + /** + * Gets the carrier frequency of the tracked signal. + * + *

For example it can be the GPS central frequency for L1 = 1575.45 MHz, or L2 = 1227.60 MHz, + * L5 = 1176.45 MHz, varying GLO channels, etc. + * + * @return the carrier frequency of the signal tracked in Hz. + */ + @IntRange(from = 0) + public long getCarrierFrequencyHz() { + return mCarrierFrequencyHz; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel parcel, int flag) { + parcel.writeDouble(mLevelDb); + parcel.writeInt(mConstellationType); + parcel.writeLong(mCarrierFrequencyHz); + } + + @NonNull + public static final Creator CREATOR = + new Creator() { + @Override + @NonNull + public GnssAutomaticGainControl createFromParcel(@NonNull Parcel parcel) { + return new GnssAutomaticGainControl(parcel.readDouble(), parcel.readInt(), + parcel.readLong()); + } + + @Override + public GnssAutomaticGainControl[] newArray(int i) { + return new GnssAutomaticGainControl[i]; + } + }; + + @NonNull + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + s.append("GnssAutomaticGainControl["); + s.append("Level=").append(mLevelDb).append(" dB"); + s.append(" Constellation=").append( + GnssStatus.constellationTypeToString(mConstellationType)); + s.append(" CarrierFrequency=").append(mCarrierFrequencyHz).append(" Hz"); + s.append(']'); + return s.toString(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof GnssAutomaticGainControl)) { + return false; + } + + GnssAutomaticGainControl other = (GnssAutomaticGainControl) obj; + if (Double.compare(mLevelDb, other.mLevelDb) + != 0) { + return false; + } + if (mConstellationType != other.mConstellationType) { + return false; + } + if (mCarrierFrequencyHz != other.mCarrierFrequencyHz) { + return false; + } + return true; + } + + @Override + public int hashCode() { + return Objects.hash(mLevelDb, mConstellationType, mCarrierFrequencyHz); + } + + /** Builder for {@link GnssAutomaticGainControl} */ + public static final class Builder { + private double mLevelDb; + private int mConstellationType; + private long mCarrierFrequencyHz; + + /** + * Constructs a {@link GnssAutomaticGainControl.Builder} instance. + */ + public Builder() { + } + + /** + * Constructs a {@link GnssAutomaticGainControl.Builder} instance by copying a + * {@link GnssAutomaticGainControl}. + */ + public Builder(@NonNull GnssAutomaticGainControl agc) { + mLevelDb = agc.getLevelDb(); + mConstellationType = agc.getConstellationType(); + mCarrierFrequencyHz = agc.getCarrierFrequencyHz(); + } + + /** + * Sets the Automatic Gain Control level in dB. + */ + @NonNull + public Builder setLevelDb(@FloatRange(from = -10000, to = 10000) double levelDb) { + Preconditions.checkArgument(levelDb >= -10000 && levelDb <= 10000); + mLevelDb = levelDb; + return this; + } + + /** + * Sets the constellation type. + */ + @NonNull + public Builder setConstellationType(@GnssStatus.ConstellationType int constellationType) { + mConstellationType = constellationType; + return this; + } + + /** + * Sets the Carrier frequency in Hz. + */ + @NonNull public Builder setCarrierFrequencyHz(@IntRange(from = 0) long carrierFrequencyHz) { + Preconditions.checkArgumentNonnegative(carrierFrequencyHz); + mCarrierFrequencyHz = carrierFrequencyHz; + return this; + } + + /** Builds a {@link GnssAutomaticGainControl} instance as specified by this builder. */ + @NonNull + public GnssAutomaticGainControl build() { + return new GnssAutomaticGainControl(mLevelDb, mConstellationType, mCarrierFrequencyHz); + } + } +} diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java index ecdd4b616e0fd..cdfa02c8b28f5 100644 --- a/location/java/android/location/GnssMeasurement.java +++ b/location/java/android/location/GnssMeasurement.java @@ -1381,7 +1381,10 @@ public final class GnssMeasurement implements Parcelable { /** * Returns {@code true} if {@link #getAutomaticGainControlLevelDb()} is available, * {@code false} otherwise. + * + * @deprecated Use {@link GnssMeasurementsEvent#getGnssAutomaticGainControls()} instead. */ + @Deprecated public boolean hasAutomaticGainControlLevelDb() { return isFlagSet(HAS_AUTOMATIC_GAIN_CONTROL); } @@ -1401,7 +1404,10 @@ public final class GnssMeasurement implements Parcelable { * indicative of changes on input signal power in the frequency band for this measurement. * *

The value is only available if {@link #hasAutomaticGainControlLevelDb()} is {@code true} + * + * @deprecated Use {@link GnssMeasurementsEvent#getGnssAutomaticGainControls()} instead. */ + @Deprecated public double getAutomaticGainControlLevelDb() { return mAutomaticGainControlLevelInDb; } @@ -1409,7 +1415,9 @@ public final class GnssMeasurement implements Parcelable { /** * Sets the Automatic Gain Control level in dB. * @hide + * @deprecated Use {@link GnssMeasurementsEvent.Builder#setGnssAutomaticGainControls()} instead. */ + @Deprecated @TestApi public void setAutomaticGainControlLevelInDb(double agcLevelDb) { setFlag(HAS_AUTOMATIC_GAIN_CONTROL); diff --git a/location/java/android/location/GnssMeasurementsEvent.java b/location/java/android/location/GnssMeasurementsEvent.java index a07a64acb6e66..075ddebc859fe 100644 --- a/location/java/android/location/GnssMeasurementsEvent.java +++ b/location/java/android/location/GnssMeasurementsEvent.java @@ -18,16 +18,19 @@ package android.location; import android.annotation.IntDef; import android.annotation.NonNull; -import android.annotation.TestApi; +import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; +import com.android.internal.util.Preconditions; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.security.InvalidParameterException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.List; /** * A class implementing a container for data associated with a measurement event. @@ -35,7 +38,8 @@ import java.util.Collections; */ public final class GnssMeasurementsEvent implements Parcelable { private final GnssClock mClock; - private final Collection mReadOnlyMeasurements; + private final List mMeasurements; + private final List mGnssAgcs; /** * Used for receiving GNSS satellite measurements from the GNSS engine. @@ -116,20 +120,13 @@ public final class GnssMeasurementsEvent implements Parcelable { } /** - * @hide + * Create a {@link GnssMeasurementsEvent} instance with a full list of parameters. */ - @TestApi - public GnssMeasurementsEvent(GnssClock clock, GnssMeasurement[] measurements) { - if (clock == null) { - throw new InvalidParameterException("Parameter 'clock' must not be null."); - } - if (measurements == null || measurements.length == 0) { - mReadOnlyMeasurements = Collections.emptyList(); - } else { - Collection measurementCollection = Arrays.asList(measurements); - mReadOnlyMeasurements = Collections.unmodifiableCollection(measurementCollection); - } - + private GnssMeasurementsEvent(@NonNull GnssClock clock, + @NonNull List measurements, + @NonNull List agcs) { + mMeasurements = measurements; + mGnssAgcs = agcs; mClock = clock; } @@ -143,26 +140,31 @@ public final class GnssMeasurementsEvent implements Parcelable { } /** - * Gets a read-only collection of measurements associated with the current event. + * Gets the collection of measurements associated with the current event. */ @NonNull public Collection getMeasurements() { - return mReadOnlyMeasurements; + return mMeasurements; + } + + /** + * Gets the collection of {@link GnssAutomaticGainControl} associated with the + * current event. + */ + @NonNull + public Collection getGnssAutomaticGainControls() { + return mGnssAgcs; } public static final @android.annotation.NonNull Creator CREATOR = new Creator() { @Override public GnssMeasurementsEvent createFromParcel(Parcel in) { - ClassLoader classLoader = getClass().getClassLoader(); - - GnssClock clock = in.readParcelable(classLoader); - - int measurementsLength = in.readInt(); - GnssMeasurement[] measurementsArray = new GnssMeasurement[measurementsLength]; - in.readTypedArray(measurementsArray, GnssMeasurement.CREATOR); - - return new GnssMeasurementsEvent(clock, measurementsArray); + GnssClock clock = in.readParcelable(getClass().getClassLoader()); + List measurements = in.createTypedArrayList(GnssMeasurement.CREATOR); + List agcs = in.createTypedArrayList( + GnssAutomaticGainControl.CREATOR); + return new GnssMeasurementsEvent(clock, measurements, agcs); } @Override @@ -179,28 +181,105 @@ public final class GnssMeasurementsEvent implements Parcelable { @Override public void writeToParcel(Parcel parcel, int flags) { parcel.writeParcelable(mClock, flags); - - int measurementsCount = mReadOnlyMeasurements.size(); - GnssMeasurement[] measurementsArray = - mReadOnlyMeasurements.toArray(new GnssMeasurement[measurementsCount]); - parcel.writeInt(measurementsArray.length); - parcel.writeTypedArray(measurementsArray, flags); + parcel.writeTypedList(mMeasurements); + parcel.writeTypedList(mGnssAgcs); } @Override public String toString() { - StringBuilder builder = new StringBuilder("[ GnssMeasurementsEvent:\n\n"); - - builder.append(mClock.toString()); - builder.append("\n"); - - for (GnssMeasurement measurement : mReadOnlyMeasurements) { - builder.append(measurement.toString()); - builder.append("\n"); - } - + StringBuilder builder = new StringBuilder("GnssMeasurementsEvent["); + builder.append(mClock); + builder.append(' ').append(mMeasurements.toString()); + builder.append(' ').append(mGnssAgcs.toString()); builder.append("]"); - return builder.toString(); } + + /** Builder for {@link GnssMeasurementsEvent} */ + public static final class Builder { + private GnssClock mClock; + private List mMeasurements; + private List mGnssAgcs; + + /** + * Constructs a {@link GnssMeasurementsEvent.Builder} instance. + */ + public Builder() { + mClock = new GnssClock(); + mMeasurements = new ArrayList<>(); + mGnssAgcs = new ArrayList<>(); + } + + /** + * Constructs a {@link GnssMeasurementsEvent.Builder} instance by copying a + * {@link GnssMeasurementsEvent}. + */ + public Builder(@NonNull GnssMeasurementsEvent event) { + mClock = event.getClock(); + mMeasurements = (List) event.getMeasurements(); + mGnssAgcs = (List) event.getGnssAutomaticGainControls(); + } + + /** + * Sets the {@link GnssClock}. + */ + @NonNull + public Builder setClock(@NonNull GnssClock clock) { + Preconditions.checkNotNull(clock); + mClock = clock; + return this; + } + + /** + * Sets the collection of {@link GnssMeasurement}. + * + * This API exists for JNI since it is easier for JNI to work with an array than a + * collection. + * @hide + */ + @NonNull + public Builder setMeasurements(@Nullable GnssMeasurement... measurements) { + mMeasurements = measurements == null ? Collections.emptyList() : Arrays.asList( + measurements); + return this; + } + + /** + * Sets the collection of {@link GnssMeasurement}. + */ + @NonNull + public Builder setMeasurements(@NonNull Collection measurements) { + mMeasurements = new ArrayList<>(measurements); + return this; + } + + /** + * Sets the collection of {@link GnssAutomaticGainControl}. + * + * This API exists for JNI since it is easier for JNI to work with an array than a + * collection. + * @hide + */ + @NonNull + public Builder setGnssAutomaticGainControls(@Nullable GnssAutomaticGainControl... agcs) { + mGnssAgcs = agcs == null ? Collections.emptyList() : Arrays.asList(agcs); + return this; + } + + /** + * Sets the collection of {@link GnssAutomaticGainControl}. + */ + @NonNull + public Builder setGnssAutomaticGainControls( + @NonNull Collection agcs) { + mGnssAgcs = new ArrayList<>(agcs); + return this; + } + + /** Builds a {@link GnssMeasurementsEvent} instance as specified by this builder. */ + @NonNull + public GnssMeasurementsEvent build() { + return new GnssMeasurementsEvent(mClock, mMeasurements, mGnssAgcs); + } + } } diff --git a/services/core/jni/gnss/GnssMeasurementCallback.cpp b/services/core/jni/gnss/GnssMeasurementCallback.cpp index 34ae4690e0ea3..5a7cee9db5bb6 100644 --- a/services/core/jni/gnss/GnssMeasurementCallback.cpp +++ b/services/core/jni/gnss/GnssMeasurementCallback.cpp @@ -27,12 +27,16 @@ 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; @@ -47,7 +51,16 @@ jmethodID method_correlationVectorBuilderSetFrequencyOffsetMetersPerSecond; jmethodID method_correlationVectorBuilderSetMagnitude; jmethodID method_correlationVectorBuilderSetSamplingStartMeters; jmethodID method_correlationVectorBuilderSetSamplingWidthMeters; -jmethodID method_gnssMeasurementsEventCtor; +jmethodID method_gnssAgcBuilderCtor; +jmethodID method_gnssAgcBuilderSetLevelDb; +jmethodID method_gnssAgcBuilderSetConstellationType; +jmethodID method_gnssAgcBuilderSetCarrierFrequencyHz; +jmethodID method_gnssAgcBuilderBuild; +jmethodID method_gnssMeasurementsEventBuilderCtor; +jmethodID method_gnssMeasurementsEventBuilderSetClock; +jmethodID method_gnssMeasurementsEventBuilderSetMeasurements; +jmethodID method_gnssMeasurementsEventBuilderSetGnssAutomaticGainControls; +jmethodID method_gnssMeasurementsEventBuilderBuild; jmethodID method_gnssMeasurementsSetCorrelationVectors; jmethodID method_gnssMeasurementsSetSatellitePvt; jmethodID method_gnssClockCtor; @@ -69,12 +82,55 @@ jmethodID method_clockInfo; 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); - method_gnssMeasurementsEventCtor = - env->GetMethodID(class_gnssMeasurementsEvent, "", - "(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V"); + 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_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"); @@ -152,14 +208,25 @@ void GnssMeasurement_class_init_once(JNIEnv* env, jclass& clazz) { } void setMeasurementData(JNIEnv* env, jobject& callbacksObj, jobject clock, - jobjectArray measurementArray) { - jobject gnssMeasurementsEvent = - env->NewObject(class_gnssMeasurementsEvent, method_gnssMeasurementsEventCtor, clock, - measurementArray); + jobjectArray measurementArray, jobjectArray gnssAgcArray) { + jobject gnssMeasurementsEventBuilderObject = + env->NewObject(class_gnssMeasurementsEventBuilder, + method_gnssMeasurementsEventBuilderCtor); + env->CallObjectMethod(gnssMeasurementsEventBuilderObject, + method_gnssMeasurementsEventBuilderSetClock, clock); + env->CallObjectMethod(gnssMeasurementsEventBuilderObject, + method_gnssMeasurementsEventBuilderSetMeasurements, measurementArray); + env->CallObjectMethod(gnssMeasurementsEventBuilderObject, + method_gnssMeasurementsEventBuilderSetGnssAutomaticGainControls, + gnssAgcArray); + jobject gnssMeasurementsEventObject = + env->CallObjectMethod(gnssMeasurementsEventBuilderObject, + method_gnssMeasurementsEventBuilderBuild); - env->CallVoidMethod(callbacksObj, method_reportMeasurementData, gnssMeasurementsEvent); + env->CallVoidMethod(callbacksObj, method_reportMeasurementData, gnssMeasurementsEventObject); checkAndClearExceptionFromCallback(env, __FUNCTION__); - env->DeleteLocalRef(gnssMeasurementsEvent); + env->DeleteLocalRef(gnssMeasurementsEventBuilderObject); + env->DeleteLocalRef(gnssMeasurementsEventObject); } template @@ -289,9 +356,13 @@ void GnssMeasurementCallbackAidl::translateAndSetGnssData(const GnssData& data) JavaObject gnssClockJavaObject(env, class_gnssClock, method_gnssClockCtor); translateGnssClock(env, data, gnssClockJavaObject); jobject clock = gnssClockJavaObject.get(); - jobjectArray measurementArray = translateAllGnssMeasurements(env, data.measurements); - setMeasurementData(env, mCallbacksObj, clock, measurementArray); + + jobjectArray gnssAgcArray = nullptr; + if (data.gnssAgcs.has_value()) { + gnssAgcArray = translateAllGnssAgcs(env, data.gnssAgcs.value()); + } + setMeasurementData(env, mCallbacksObj, clock, measurementArray, gnssAgcArray); env->DeleteLocalRef(clock); env->DeleteLocalRef(measurementArray); @@ -436,6 +507,38 @@ jobjectArray GnssMeasurementCallbackAidl::translateAllGnssMeasurements( 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) { + if (!agcs[i].has_value()) { + continue; + } + const GnssAgc& gnssAgc = agcs[i].value(); + + jobject agcBuilderObject = env->NewObject(class_gnssAgcBuilder, method_gnssAgcBuilderCtor); + env->CallObjectMethod(agcBuilderObject, method_gnssAgcBuilderSetLevelDb, + gnssAgc.agcLevelDb); + env->CallObjectMethod(agcBuilderObject, method_gnssAgcBuilderSetConstellationType, + (int)gnssAgc.constellation); + env->CallObjectMethod(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); diff --git a/services/core/jni/gnss/GnssMeasurementCallback.h b/services/core/jni/gnss/GnssMeasurementCallback.h index 32200fdf904e9..9b346312db38d 100644 --- a/services/core/jni/gnss/GnssMeasurementCallback.h +++ b/services/core/jni/gnss/GnssMeasurementCallback.h @@ -48,7 +48,7 @@ extern jmethodID method_reportMeasurementData; void GnssMeasurement_class_init_once(JNIEnv* env, jclass& clazz); void setMeasurementData(JNIEnv* env, jobject& callbacksObj, jobject clock, - jobjectArray measurementArray); + jobjectArray measurementArray, jobjectArray gnssAgcArray); class GnssMeasurementCallbackAidl : public hardware::gnss::BnGnssMeasurementCallback { public: @@ -62,6 +62,8 @@ private: jobjectArray translateAllGnssMeasurements( JNIEnv* env, const std::vector& measurements); + jobjectArray translateAllGnssAgcs( + JNIEnv* env, const std::vector>& agcs); void translateAndSetGnssData(const hardware::gnss::GnssData& data); @@ -139,7 +141,7 @@ void GnssMeasurementCallbackHidl::translateAndSetGnssData(const T& data) { size_t count = getMeasurementCount(data); jobjectArray measurementArray = translateAllGnssMeasurements(env, data.measurements.data(), count); - setMeasurementData(env, mCallbacksObj, clock, measurementArray); + setMeasurementData(env, mCallbacksObj, clock, measurementArray, nullptr); env->DeleteLocalRef(clock); env->DeleteLocalRef(measurementArray);