diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2018-12-21 06:34:19 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2018-12-21 06:34:19 +0000 |
commit | 7a01a914779b79b4b58fbe60abce62f4fab53fbf (patch) | |
tree | ac03a01fef35fb2ba4d891bd62deab01a394e1cf | |
parent | 36db4ebbb3d754a728c1e6f72850731365b15895 (diff) | |
parent | 226b7b7775dd1009ab5504fc1aec17db34f24a2e (diff) |
Merge "Bluesky Android Q Platform Changes"
16 files changed, 1439 insertions, 57 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index 3aa7cc7a1bdb..5ccb7bb2e9ae 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -2577,6 +2577,81 @@ package android.location { method public void onLocationBatch(java.util.List<android.location.Location>); } + public final class GnssMeasurementCorrections implements android.os.Parcelable { + method public int describeContents(); + method public double getAltitudeMeters(); + method public double getLatitudeDegrees(); + method public double getLongitudeDegrees(); + method public java.util.List<android.location.GnssSingleSatCorrection> getSingleSatCorrectionList(); + method public long getToaGpsNanosecondsOfWeek(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementCorrections> CREATOR; + } + + public static class GnssMeasurementCorrections.Builder { + ctor public GnssMeasurementCorrections.Builder(); + method public android.location.GnssMeasurementCorrections build(); + method public android.location.GnssMeasurementCorrections.Builder setAltitudeMeters(double); + method public android.location.GnssMeasurementCorrections.Builder setLatitudeDegrees(double); + method public android.location.GnssMeasurementCorrections.Builder setLongitudeDegrees(double); + method public android.location.GnssMeasurementCorrections.Builder setSingleSatCorrectionList(java.util.List<android.location.GnssSingleSatCorrection>); + method public android.location.GnssMeasurementCorrections.Builder setToaGpsNanosecondsOfWeek(long); + } + + public final class GnssReflectingPlane implements android.os.Parcelable { + method public int describeContents(); + method public double getAltitudeMeters(); + method public double getAzimuthDegrees(); + method public double getLatitudeDegrees(); + method public double getLongitudeDegrees(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.location.GnssReflectingPlane> CREATOR; + } + + public static class GnssReflectingPlane.Builder { + ctor public GnssReflectingPlane.Builder(); + method public android.location.GnssReflectingPlane build(); + method public android.location.GnssReflectingPlane.Builder setAltitudeMeters(double); + method public android.location.GnssReflectingPlane.Builder setAzimuthDegrees(double); + method public android.location.GnssReflectingPlane.Builder setLatitudeDegrees(double); + method public android.location.GnssReflectingPlane.Builder setLongitudeDegrees(double); + } + + public final class GnssSingleSatCorrection implements android.os.Parcelable { + method public int describeContents(); + method public float getCarrierFrequencyHz(); + method public int getConstellationType(); + method public float getExcessPathLengthMeters(); + method public float getExcessPathLengthUncertaintyMeters(); + method public android.location.GnssReflectingPlane getReflectingPlane(); + method public int getSatId(); + method public int getSingleSatCorrectionFlags(); + method public boolean hasExcessPathLength(); + method public boolean hasExcessPathLengthUncertainty(); + method public boolean hasReflectingPlane(); + method public boolean hasSatelliteLineOfSight(); + method public boolean isSatelliteLineOfSight(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.location.GnssSingleSatCorrection> CREATOR; + field public static final int HAS_EXCESS_PATH_LENGTH_MASK = 2; // 0x2 + field public static final int HAS_EXCESS_PATH_LENGTH_UNC_MASK = 4; // 0x4 + field public static final int HAS_REFLECTING_PLANE_MASK = 8; // 0x8 + field public static final int HAS_SAT_IS_LOS_MASK = 1; // 0x1 + } + + public static class GnssSingleSatCorrection.Builder { + ctor public GnssSingleSatCorrection.Builder(); + method public android.location.GnssSingleSatCorrection build(); + method public android.location.GnssSingleSatCorrection.Builder setCarrierFrequencyHz(float); + method public android.location.GnssSingleSatCorrection.Builder setConstellationType(int); + method public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthMeters(float); + method public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthUncertaintyMeters(float); + method public android.location.GnssSingleSatCorrection.Builder setReflectingPlane(android.location.GnssReflectingPlane); + method public android.location.GnssSingleSatCorrection.Builder setSatId(int); + method public android.location.GnssSingleSatCorrection.Builder setSatIsLos(boolean); + method public android.location.GnssSingleSatCorrection.Builder setSingleSatCorrectionFlags(int); + } + public class GpsClock implements android.os.Parcelable { method public int describeContents(); method public double getBiasInNs(); @@ -2813,8 +2888,10 @@ package android.location { method public deprecated boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener); method public void flushGnssBatch(); method public int getGnssBatchSize(); + method public int getGnssCapabilities(); method public java.lang.String getLocationControllerExtraPackage(); method public java.lang.String getNetworkProviderPackage(); + method public void injectGnssMeasurementCorrections(android.location.GnssMeasurementCorrections); method public boolean isLocationControllerExtraPackageEnabled(); method public boolean isLocationEnabledForUser(android.os.UserHandle); method public boolean isProviderEnabledForUser(java.lang.String, android.os.UserHandle); diff --git a/location/java/android/location/GnssMeasurementCallbackTransport.java b/location/java/android/location/GnssMeasurementCallbackTransport.java index 21f63068084e..1188b13b7841 100644 --- a/location/java/android/location/GnssMeasurementCallbackTransport.java +++ b/location/java/android/location/GnssMeasurementCallbackTransport.java @@ -19,6 +19,8 @@ package android.location; import android.content.Context; import android.os.RemoteException; +import com.android.internal.util.Preconditions; + /** * A handler class to manage transport callbacks for {@link GnssMeasurementsEvent.Callback}. * @@ -26,12 +28,13 @@ import android.os.RemoteException; */ class GnssMeasurementCallbackTransport extends LocalListenerHelper<GnssMeasurementsEvent.Callback> { + private static final String TAG = "GnssMeasCbTransport"; private final ILocationManager mLocationManager; private final IGnssMeasurementsListener mListenerTransport = new ListenerTransport(); public GnssMeasurementCallbackTransport(Context context, ILocationManager locationManager) { - super(context, "GnssMeasurementListenerTransport"); + super(context, TAG); mLocationManager = locationManager; } @@ -47,17 +50,34 @@ class GnssMeasurementCallbackTransport mLocationManager.removeGnssMeasurementsListener(mListenerTransport); } + /** + * Injects GNSS measurement corrections into the GNSS chipset. + * + * @param measurementCorrections a {@link GnssMeasurementCorrections} object with the GNSS + * measurement corrections to be injected into the GNSS chipset. + */ + protected void injectGnssMeasurementCorrections( + GnssMeasurementCorrections measurementCorrections) throws RemoteException { + Preconditions.checkNotNull(measurementCorrections); + mLocationManager.injectGnssMeasurementCorrections( + measurementCorrections, getContext().getPackageName()); + } + + protected int getGnssCapabilities() throws RemoteException { + return mLocationManager.getGnssCapabilities(getContext().getPackageName()); + } + private class ListenerTransport extends IGnssMeasurementsListener.Stub { @Override public void onGnssMeasurementsReceived(final GnssMeasurementsEvent event) { ListenerOperation<GnssMeasurementsEvent.Callback> operation = new ListenerOperation<GnssMeasurementsEvent.Callback>() { - @Override - public void execute(GnssMeasurementsEvent.Callback callback) - throws RemoteException { - callback.onGnssMeasurementsReceived(event); - } - }; + @Override + public void execute(GnssMeasurementsEvent.Callback callback) + throws RemoteException { + callback.onGnssMeasurementsReceived(event); + } + }; foreach(operation); } diff --git a/location/java/android/location/GnssMeasurementCorrections.aidl b/location/java/android/location/GnssMeasurementCorrections.aidl new file mode 100644 index 000000000000..b05eb5455c82 --- /dev/null +++ b/location/java/android/location/GnssMeasurementCorrections.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 208 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 GnssMeasurementCorrections; diff --git a/location/java/android/location/GnssMeasurementCorrections.java b/location/java/android/location/GnssMeasurementCorrections.java new file mode 100644 index 000000000000..b81bf908053c --- /dev/null +++ b/location/java/android/location/GnssMeasurementCorrections.java @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2018 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.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * A class representing a GNSS measurement corrections for all used GNSS satellites at the location + * and time specified + * + * @hide + */ +@SystemApi +public final class GnssMeasurementCorrections implements Parcelable { + + /** Represents latitude in degrees at which the corrections are computed. */ + private double mLatitudeDegrees; + /** Represents longitude in degrees at which the corrections are computed. */ + private double mLongitudeDegrees; + /** + * Represents altitude in meters above the WGS 84 reference ellipsoid at which the corrections + * are computed. + */ + private double mAltitudeMeters; + + /** Time Of Applicability, GPS time of week */ + private long mToaGpsNanosecondsOfWeek; + + /** + * A set of {@link GnssSingleSatCorrection} each containing measurement corrections for a + * satellite in view + */ + private @Nullable List<GnssSingleSatCorrection> mSingleSatCorrectionList; + + private GnssMeasurementCorrections(Builder builder) { + mLatitudeDegrees = builder.mLatitudeDegrees; + mLongitudeDegrees = builder.mLongitudeDegrees; + mAltitudeMeters = builder.mAltitudeMeters; + mToaGpsNanosecondsOfWeek = builder.mToaGpsNanosecondsOfWeek; + mSingleSatCorrectionList = + builder.mSingleSatCorrectionList == null + ? null + : Collections.unmodifiableList( + new ArrayList<>(builder.mSingleSatCorrectionList)); + } + + /** Gets the latitude in degrees at which the corrections are computed. */ + public double getLatitudeDegrees() { + return mLatitudeDegrees; + } + + /** Gets the longitude in degrees at which the corrections are computed. */ + public double getLongitudeDegrees() { + return mLongitudeDegrees; + } + + /** + * Gets the altitude in meters above the WGS 84 reference ellipsoid at which the corrections are + * computed. + */ + public double getAltitudeMeters() { + return mAltitudeMeters; + } + + /** Gets the time of applicability, GPS time of week in nanoseconds. */ + public long getToaGpsNanosecondsOfWeek() { + return mToaGpsNanosecondsOfWeek; + } + + /** + * Gets a set of {@link GnssSingleSatCorrection} each containing measurement corrections for a + * satellite in view + */ + public @Nullable List<GnssSingleSatCorrection> getSingleSatCorrectionList() { + return mSingleSatCorrectionList; + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator<GnssMeasurementCorrections> CREATOR = + new Creator<GnssMeasurementCorrections>() { + @Override + public GnssMeasurementCorrections createFromParcel(Parcel parcel) { + GnssMeasurementCorrections.Builder gnssMeasurementCorrectons = + new Builder() + .setLatitudeDegrees(parcel.readDouble()) + .setLongitudeDegrees(parcel.readDouble()) + .setAltitudeMeters(parcel.readDouble()) + .setToaGpsNanosecondsOfWeek(parcel.readLong()); + List<GnssSingleSatCorrection> singleSatCorrectionList = new ArrayList<>(); + parcel.readTypedList(singleSatCorrectionList, GnssSingleSatCorrection.CREATOR); + gnssMeasurementCorrectons.setSingleSatCorrectionList( + singleSatCorrectionList.isEmpty() ? null : singleSatCorrectionList); + return gnssMeasurementCorrectons.build(); + } + + @Override + public GnssMeasurementCorrections[] newArray(int i) { + return new GnssMeasurementCorrections[i]; + } + }; + + @Override + public String toString() { + final String format = " %-29s = %s\n"; + StringBuilder builder = new StringBuilder("GnssMeasurementCorrections:\n"); + builder.append(String.format(format, "LatitudeDegrees = ", mLatitudeDegrees)); + builder.append(String.format(format, "LongitudeDegrees = ", mLongitudeDegrees)); + builder.append(String.format(format, "AltitudeMeters = ", mAltitudeMeters)); + builder.append( + String.format(format, "ToaGpsNanosecondsOfWeek = ", mToaGpsNanosecondsOfWeek)); + builder.append( + String.format(format, "mSingleSatCorrectionList = ", mSingleSatCorrectionList)); + return builder.toString(); + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeDouble(mLatitudeDegrees); + parcel.writeDouble(mLongitudeDegrees); + parcel.writeDouble(mAltitudeMeters); + parcel.writeLong(mToaGpsNanosecondsOfWeek); + parcel.writeTypedList(mSingleSatCorrectionList); + } + + /** Builder for {@link GnssMeasurementCorrections} */ + public static class Builder { + /** + * For documentation of below fields, see corresponding fields in {@link + * GnssMeasurementCorrections}. + */ + private double mLatitudeDegrees; + + private double mLongitudeDegrees; + private double mAltitudeMeters; + private long mToaGpsNanosecondsOfWeek; + private List<GnssSingleSatCorrection> mSingleSatCorrectionList; + + /** Sets the latitude in degrees at which the corrections are computed. */ + public Builder setLatitudeDegrees(double latitudeDegrees) { + mLatitudeDegrees = latitudeDegrees; + return this; + } + + /** Sets the longitude in degrees at which the corrections are computed. */ + public Builder setLongitudeDegrees(double longitudeDegrees) { + mLongitudeDegrees = longitudeDegrees; + return this; + } + + /** + * Sets the altitude in meters above the WGS 84 reference ellipsoid at which the corrections + * are computed. + */ + public Builder setAltitudeMeters(double altitudeMeters) { + mAltitudeMeters = altitudeMeters; + return this; + } + + /** Sets the time of applicability, GPS time of week in nanoseconds. */ + public Builder setToaGpsNanosecondsOfWeek(long toaGpsNanosecondsOfWeek) { + mToaGpsNanosecondsOfWeek = toaGpsNanosecondsOfWeek; + return this; + } + + /** + * Sets a the list of {@link GnssSingleSatCorrection} containing measurement corrections for + * a satellite in view + */ + public Builder setSingleSatCorrectionList( + @Nullable List<GnssSingleSatCorrection> singleSatCorrectionList) { + if (singleSatCorrectionList == null) { + mSingleSatCorrectionList = null; + } else { + mSingleSatCorrectionList = + Collections.unmodifiableList(new ArrayList<>(singleSatCorrectionList)); + } + return this; + } + + /** Builds a {@link GnssMeasurementCorrections} instance as specified by this builder. */ + public GnssMeasurementCorrections build() { + return new GnssMeasurementCorrections(this); + } + } +} diff --git a/location/java/android/location/GnssReflectingPlane.java b/location/java/android/location/GnssReflectingPlane.java new file mode 100644 index 000000000000..64b37524e37f --- /dev/null +++ b/location/java/android/location/GnssReflectingPlane.java @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2018 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.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Holds the characteristics of the reflecting plane that a satellite signal has bounced from. + * + * @hide + */ +@SystemApi +public final class GnssReflectingPlane implements Parcelable { + + /** Represents latitude in degrees of the reflecting plane */ + private double mLatitudeDegrees; + /** Represents longitude in degrees of the reflecting plane. */ + private double mLongitudeDegrees; + /** + * Represents altitude in meters above the WGS 84 reference ellipsoid of the reflection point in + * the plane + */ + private double mAltitudeMeters; + + /** Represents azimuth clockwise from north of the reflecting plane in degrees. */ + private double mAzimuthDegrees; + + private GnssReflectingPlane(Builder builder) { + mLatitudeDegrees = builder.mLatitudeDegrees; + mLongitudeDegrees = builder.mLongitudeDegrees; + mAltitudeMeters = builder.mAltitudeMeters; + mAzimuthDegrees = builder.mAzimuthDegrees; + } + + /** Gets the latitude in degrees of the reflecting plane. */ + public double getLatitudeDegrees() { + return mLatitudeDegrees; + } + + /** Gets the longitude in degrees of the reflecting plane. */ + public double getLongitudeDegrees() { + return mLongitudeDegrees; + } + + /** + * Gets the altitude in meters above the WGS 84 reference ellipsoid of the reflecting point + * within the plane + */ + public double getAltitudeMeters() { + return mAltitudeMeters; + } + + /** Gets the azimuth clockwise from north of the reflecting plane in degrees. */ + public double getAzimuthDegrees() { + return mAzimuthDegrees; + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator<GnssReflectingPlane> CREATOR = + new Creator<GnssReflectingPlane>() { + @Override + public GnssReflectingPlane createFromParcel(Parcel parcel) { + GnssReflectingPlane reflectingPlane = + new Builder() + .setLatitudeDegrees(parcel.readDouble()) + .setLongitudeDegrees(parcel.readDouble()) + .setAltitudeMeters(parcel.readDouble()) + .setAzimuthDegrees(parcel.readDouble()) + .build(); + return reflectingPlane; + } + + @Override + public GnssReflectingPlane[] newArray(int i) { + return new GnssReflectingPlane[i]; + } + }; + + @Override + public String toString() { + final String format = " %-29s = %s\n"; + StringBuilder builder = new StringBuilder("ReflectingPlane:\n"); + builder.append(String.format(format, "LatitudeDegrees = ", mLatitudeDegrees)); + builder.append(String.format(format, "LongitudeDegrees = ", mLongitudeDegrees)); + builder.append(String.format(format, "AltitudeMeters = ", mAltitudeMeters)); + builder.append(String.format(format, "AzimuthDegrees = ", mAzimuthDegrees)); + return builder.toString(); + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeDouble(mLatitudeDegrees); + parcel.writeDouble(mLongitudeDegrees); + parcel.writeDouble(mAltitudeMeters); + parcel.writeDouble(mAzimuthDegrees); + } + + /** Builder for {@link GnssReflectingPlane} */ + public static class Builder { + /** For documentation, see corresponding fields in {@link GnssReflectingPlane}. */ + private double mLatitudeDegrees; + + private double mLongitudeDegrees; + private double mAltitudeMeters; + private double mAzimuthDegrees; + + /** Sets the latitude in degrees of the reflecting plane. */ + public Builder setLatitudeDegrees(double latitudeDegrees) { + mLatitudeDegrees = latitudeDegrees; + return this; + } + + /** Sets the longitude in degrees of the reflecting plane. */ + public Builder setLongitudeDegrees(double longitudeDegrees) { + mLongitudeDegrees = longitudeDegrees; + return this; + } + + /** + * Sets the altitude in meters above the WGS 84 reference ellipsoid of the reflecting point + * within the plane + */ + public Builder setAltitudeMeters(double altitudeMeters) { + mAltitudeMeters = altitudeMeters; + return this; + } + + /** Sets the azimuth clockwise from north of the reflecting plane in degrees. */ + public Builder setAzimuthDegrees(double azimuthDegrees) { + mAzimuthDegrees = azimuthDegrees; + return this; + } + + /** Builds a {@link GnssReflectingPlane} object as specified by this builder. */ + public GnssReflectingPlane build() { + return new GnssReflectingPlane(this); + } + } +} diff --git a/location/java/android/location/GnssSingleSatCorrection.java b/location/java/android/location/GnssSingleSatCorrection.java new file mode 100644 index 000000000000..6c757f949f19 --- /dev/null +++ b/location/java/android/location/GnssSingleSatCorrection.java @@ -0,0 +1,346 @@ +/* + * Copyright (C) 2018 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.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * A container with measurement corrections for a single visible satellite + * + * @hide + */ +@SystemApi +public final class GnssSingleSatCorrection implements Parcelable { + + /** + * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link + * #mSatIsLos}. + */ + public static final int HAS_SAT_IS_LOS_MASK = 1 << 0; + + /** + * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link + * #mExcessPathLengthMeters}. + */ + public static final int HAS_EXCESS_PATH_LENGTH_MASK = 1 << 1; + + /** + * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link + * #mExcessPathLengthUncertaintyMeters}. + */ + public static final int HAS_EXCESS_PATH_LENGTH_UNC_MASK = 1 << 2; + + /** + * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link + * #mReflectingPlane}. + */ + public static final int HAS_REFLECTING_PLANE_MASK = 1 << 3; + + /** A bitmask of fields present in this object (see HAS_* constants defined above) */ + private int mSingleSatCorrectionFlags; + + /** Defines the constellation of the given satellite as defined in {@link GnssStatus}. */ + private int mConstellationType; + + /** + * Satellite vehicle ID number + * + * <p>Interpretation depends on {@link GnssStatus#getSvid(int)}. + */ + private int mSatId; + + /** + * Carrier frequency of the signal to be corrected, for example it can be the GPS center + * frequency for L1 = 1,575,420,000 Hz, varying GLO channels, etc. + * + * <p>For an L1, L5 receiver tracking a satellite on L1 and L5 at the same time, two correction + * objects will be reported for this same satellite, in one of the correction objects, all the + * values related to L1 will be filled, and in the other all of the values related to L5 will be + * filled. + */ + private float mCarrierFrequencyHz; + + /** + * True if the satellite is estimated to be in Line-of-Sight condition at the given location. + */ + private boolean mSatIsLos; + + /** + * Excess path length to be subtracted from pseudorange before using it in calculating location. + */ + private float mExcessPathLengthMeters; + + /** Error estimate (1-sigma) for the Excess path length estimate */ + private float mExcessPathLengthUncertaintyMeters; + + /** + * Defines the reflecting plane location and azimuth information + * + * <p>The flag HAS_REFLECTING_PLANE will be used to set this value to invalid if the satellite + * signal goes through multiple reflections or if reflection plane serving is not supported. + */ + private @Nullable GnssReflectingPlane mReflectingPlane; + + private GnssSingleSatCorrection(Builder builder) { + mSingleSatCorrectionFlags = builder.mSingleSatCorrectionFlags; + mSatId = builder.mSatId; + mConstellationType = builder.mConstellationType; + mCarrierFrequencyHz = builder.mCarrierFrequencyHz; + mSatIsLos = builder.mSatIsLos; + mExcessPathLengthMeters = builder.mExcessPathLengthMeters; + mExcessPathLengthUncertaintyMeters = builder.mExcessPathLengthUncertaintyMeters; + mReflectingPlane = builder.mReflectingPlane; + } + + /** Gets a bitmask of fields present in this object */ + public int getSingleSatCorrectionFlags() { + return mSingleSatCorrectionFlags; + } + + /** + * Gets the constellation type. + * + * <p>The return value is one of those constants with {@code CONSTELLATION_} prefix in {@link + * GnssStatus}. + */ + @GnssStatus.ConstellationType + public int getConstellationType() { + return mConstellationType; + } + + /** + * Gets the satellite ID. + * + * <p>Interpretation depends on {@link #getConstellationType()}. See {@link + * GnssStatus#getSvid(int)}. + */ + public int getSatId() { + return mSatId; + } + + /** + * Gets the carrier frequency of the tracked signal. + * + * <p>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. + * + * <p>For an L1, L5 receiver tracking a satellite on L1 and L5 at the same time, two correction + * objects will be reported for this same satellite, in one of the correction objects, all the + * values related to L1 will be filled, and in the other all of the values related to L5 will be + * filled. + * + * @return the carrier frequency of the signal tracked in Hz. + */ + public float getCarrierFrequencyHz() { + return mCarrierFrequencyHz; + } + + /** True if the satellite is line-of-sight */ + public boolean isSatelliteLineOfSight() { + return mSatIsLos; + } + + /** + * Returns the Excess path length to be subtracted from pseudorange before using it in + * calculating location. + */ + public float getExcessPathLengthMeters() { + return mExcessPathLengthMeters; + } + + /** Returns the error estimate (1-sigma) for the Excess path length estimate */ + public float getExcessPathLengthUncertaintyMeters() { + return mExcessPathLengthUncertaintyMeters; + } + + /** + * Returns the reflecting plane characteristics at which the signal has bounced + * + * <p>The flag HAS_REFLECTING_PLANE will be used to set this value to invalid if the satellite + * signal goes through multiple reflections or if reflection plane serving is not supported + */ + public @Nullable GnssReflectingPlane getReflectingPlane() { + return mReflectingPlane; + } + + /** Returns {@code true} if {@link #isSatelliteLineOfSight()} is valid. */ + public boolean hasSatelliteLineOfSight() { + return (mSingleSatCorrectionFlags & HAS_SAT_IS_LOS_MASK) != 0; + } + + /** Returns {@code true} if {@link #getExcessPathLengthMeters()} is valid. */ + public boolean hasExcessPathLength() { + return (mSingleSatCorrectionFlags & HAS_EXCESS_PATH_LENGTH_MASK) != 0; + } + + /** Returns {@code true} if {@link #getExcessPathLengthUncertaintyMeters()} is valid. */ + public boolean hasExcessPathLengthUncertainty() { + return (mSingleSatCorrectionFlags & HAS_EXCESS_PATH_LENGTH_UNC_MASK) != 0; + } + + /** Returns {@code true} if {@link #getReflectingPlane()} is valid. */ + public boolean hasReflectingPlane() { + return (mSingleSatCorrectionFlags & HAS_REFLECTING_PLANE_MASK) != 0; + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator<GnssSingleSatCorrection> CREATOR = + new Creator<GnssSingleSatCorrection>() { + @Override + public GnssSingleSatCorrection createFromParcel(Parcel parcel) { + GnssSingleSatCorrection singleSatCorrection = + new Builder() + .setSingleSatCorrectionFlags(parcel.readInt()) + .setConstellationType(parcel.readInt()) + .setSatId(parcel.readInt()) + .setCarrierFrequencyHz(parcel.readFloat()) + .setSatIsLos(parcel.readBoolean()) + .setExcessPathLengthMeters(parcel.readFloat()) + .setExcessPathLengthUncertaintyMeters(parcel.readFloat()) + .setReflectingPlane( + GnssReflectingPlane.CREATOR.createFromParcel(parcel)) + .build(); + return singleSatCorrection; + } + + @Override + public GnssSingleSatCorrection[] newArray(int i) { + return new GnssSingleSatCorrection[i]; + } + }; + + @Override + public String toString() { + final String format = " %-29s = %s\n"; + StringBuilder builder = new StringBuilder("GnssSingleSatCorrection:\n"); + builder.append( + String.format(format, "SingleSatCorrectionFlags = ", mSingleSatCorrectionFlags)); + builder.append(String.format(format, "ConstellationType = ", mConstellationType)); + builder.append(String.format(format, "SatId = ", mSatId)); + builder.append(String.format(format, "CarrierFrequencyHz = ", mCarrierFrequencyHz)); + builder.append(String.format(format, "SatIsLos = ", mSatIsLos)); + builder.append(String.format(format, "ExcessPathLengthMeters = ", mExcessPathLengthMeters)); + builder.append( + String.format( + format, + "ExcessPathLengthUncertaintyMeters = ", + mExcessPathLengthUncertaintyMeters)); + builder.append(String.format(format, "ReflectingPlane = ", mReflectingPlane)); + return builder.toString(); + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeInt(mSingleSatCorrectionFlags); + parcel.writeInt(mConstellationType); + parcel.writeInt(mSatId); + parcel.writeFloat(mCarrierFrequencyHz); + parcel.writeBoolean(mSatIsLos); + parcel.writeFloat(mExcessPathLengthMeters); + parcel.writeFloat(mExcessPathLengthUncertaintyMeters); + mReflectingPlane.writeToParcel(parcel, flags); + } + + /** Builder for {@link GnssSingleSatCorrection} */ + public static class Builder { + + /** + * For documentation of below fields, see corresponding fields in {@link + * GnssSingleSatCorrection}. + */ + private int mSingleSatCorrectionFlags; + + private int mConstellationType; + private int mSatId; + private float mCarrierFrequencyHz; + private boolean mSatIsLos; + private float mExcessPathLengthMeters; + private float mExcessPathLengthUncertaintyMeters; + private GnssReflectingPlane mReflectingPlane; + + /** Sets a bitmask of fields present in this object */ + public Builder setSingleSatCorrectionFlags(int singleSatCorrectionFlags) { + mSingleSatCorrectionFlags = singleSatCorrectionFlags; + return this; + } + + /** Sets the constellation type. */ + public Builder setConstellationType(int constellationType) { + mConstellationType = constellationType; + return this; + } + + /** Sets the Satellite ID. */ + public Builder setSatId(int satId) { + mSatId = satId; + return this; + } + + /** Sets the Carrier frequency in Hz. */ + public Builder setCarrierFrequencyHz(float carrierFrequencyHz) { + mCarrierFrequencyHz = carrierFrequencyHz; + return this; + } + + /** Sets the line=of-sight state of the satellite */ + public Builder setSatIsLos(boolean satIsLos) { + mSatIsLos = satIsLos; + mSingleSatCorrectionFlags = (byte) (mSingleSatCorrectionFlags | HAS_SAT_IS_LOS_MASK); + return this; + } + + /** + * Sets the Excess path length to be subtracted from pseudorange before using it in + * calculating location. + */ + public Builder setExcessPathLengthMeters(float excessPathLengthMeters) { + mExcessPathLengthMeters = excessPathLengthMeters; + mSingleSatCorrectionFlags = + (byte) (mSingleSatCorrectionFlags | HAS_EXCESS_PATH_LENGTH_MASK); + return this; + } + + /** Sets the error estimate (1-sigma) for the Excess path length estimate */ + public Builder setExcessPathLengthUncertaintyMeters( + float excessPathLengthUncertaintyMeters) { + mExcessPathLengthUncertaintyMeters = excessPathLengthUncertaintyMeters; + mSingleSatCorrectionFlags = + (byte) (mSingleSatCorrectionFlags | HAS_EXCESS_PATH_LENGTH_UNC_MASK); + return this; + } + + /** Sets the reflecting plane information */ + public Builder setReflectingPlane(GnssReflectingPlane reflectingPlane) { + mReflectingPlane = reflectingPlane; + mSingleSatCorrectionFlags = + (byte) (mSingleSatCorrectionFlags | HAS_REFLECTING_PLANE_MASK); + return this; + } + + /** Builds a {@link GnssSingleSatCorrection} instance as specified by this builder. */ + public GnssSingleSatCorrection build() { + return new GnssSingleSatCorrection(this); + } + } +} diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index 05d49e592747..bdc84da57799 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -21,6 +21,7 @@ import android.location.Address; import android.location.Criteria; import android.location.GeocoderParams; import android.location.Geofence; +import android.location.GnssMeasurementCorrections; import android.location.IBatchedLocationCallback; import android.location.IGnssMeasurementsListener; import android.location.IGnssStatusListener; @@ -63,6 +64,9 @@ interface ILocationManager boolean sendNiResponse(int notifId, int userResponse); boolean addGnssMeasurementsListener(in IGnssMeasurementsListener listener, in String packageName); + void injectGnssMeasurementCorrections(in GnssMeasurementCorrections corrections, + in String packageName); + int getGnssCapabilities(in String packageName); void removeGnssMeasurementsListener(in IGnssMeasurementsListener listener); boolean addGnssNavigationMessageListener( diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 1cd3d86a0c27..040e4f9f1bd0 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -22,6 +22,7 @@ import static android.Manifest.permission.LOCATION_HARDWARE; import static android.Manifest.permission.WRITE_SECURE_SETTINGS; import android.Manifest; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresFeature; import android.annotation.RequiresPermission; @@ -2079,17 +2080,54 @@ public class LocationManager { } /** - * No-op method to keep backward-compatibility. - * Don't use it. Use {@link #unregisterGnssMeasurementsCallback} instead. + * Injects GNSS measurement corrections into the GNSS chipset. + * + * @param measurementCorrections a {@link GnssMeasurementCorrections} object with the GNSS + * measurement corrections to be injected into the GNSS chipset. + * @hide + */ + @SystemApi + @RequiresPermission(ACCESS_FINE_LOCATION) + public void injectGnssMeasurementCorrections( + @NonNull GnssMeasurementCorrections measurementCorrections) { + try { + mGnssMeasurementCallbackTransport.injectGnssMeasurementCorrections( + measurementCorrections); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns an integer with flags representing the capabilities of the GNSS chipset. + * + * @hide + */ + @SystemApi + /** + * Returns the integer capability flags of the GNSS chipset as defined in {@code + * IGnssCallback.hal} + */ + public int getGnssCapabilities() { + try { + return mGnssMeasurementCallbackTransport.getGnssCapabilities(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * No-op method to keep backward-compatibility. Don't use it. Use {@link + * #unregisterGnssMeasurementsCallback} instead. + * * @hide * @deprecated use {@link #unregisterGnssMeasurementsCallback(GnssMeasurementsEvent.Callback)} - * instead. + * instead. */ @Deprecated @SystemApi @SuppressLint("Doclava125") - public void removeGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) { - } + public void removeGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {} /** * Unregisters a GPS Measurement callback. diff --git a/location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java b/location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java new file mode 100644 index 000000000000..c18d58f9a704 --- /dev/null +++ b/location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2018 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.os.Parcel; + +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.List; + +/** Unit tests for {@link GnssMeasurementCorrections}. */ +public class GnssMeasurementCorrectionsTest extends TestCase { + public void testDescribeContents() { + GnssMeasurementCorrections measurementCorrections = + new GnssMeasurementCorrections.Builder().build(); + measurementCorrections.describeContents(); + } + + public void testWriteToParcel() { + GnssMeasurementCorrections.Builder measurementCorrections = + new GnssMeasurementCorrections.Builder(); + setTestValues(measurementCorrections); + Parcel parcel = Parcel.obtain(); + measurementCorrections.build().writeToParcel(parcel, 0); + parcel.setDataPosition(0); + GnssMeasurementCorrections newMeasurementCorrection = + GnssMeasurementCorrections.CREATOR.createFromParcel(parcel); + verifyTestValues(newMeasurementCorrection); + parcel.recycle(); + } + + private static void verifyTestValues(GnssMeasurementCorrections measurementCorrections) { + assertEquals(37.386051, measurementCorrections.getLatitudeDegrees()); + assertEquals(-122.083855, measurementCorrections.getLongitudeDegrees()); + assertEquals(32.0, measurementCorrections.getAltitudeMeters()); + assertEquals(604000000000000L, measurementCorrections.getToaGpsNanosecondsOfWeek()); + + GnssSingleSatCorrection singleSatCorrection = + measurementCorrections.getSingleSatCorrectionList().get(0); + GnssSingleSatCorrectionsTest.verifyTestValues(singleSatCorrection); + + singleSatCorrection = measurementCorrections.getSingleSatCorrectionList().get(1); + assertEquals(15, singleSatCorrection.getSingleSatCorrectionFlags()); + assertEquals(GnssStatus.CONSTELLATION_GPS, singleSatCorrection.getConstellationType()); + assertEquals(11, singleSatCorrection.getSatId()); + assertEquals(1575430000f, singleSatCorrection.getCarrierFrequencyHz()); + assertEquals(false, singleSatCorrection.isSatelliteLineOfSight()); + assertEquals(50.0f, singleSatCorrection.getExcessPathLengthMeters()); + assertEquals(55.0f, singleSatCorrection.getExcessPathLengthUncertaintyMeters()); + GnssReflectingPlane reflectingPlane = singleSatCorrection.getReflectingPlane(); + assertEquals(37.386054, reflectingPlane.getLatitudeDegrees()); + assertEquals(-122.083855, reflectingPlane.getLongitudeDegrees()); + assertEquals(120.0, reflectingPlane.getAltitudeMeters()); + assertEquals(153.0, reflectingPlane.getAzimuthDegrees()); + } + + private static void setTestValues(GnssMeasurementCorrections.Builder measurementCorrections) { + measurementCorrections + .setLatitudeDegrees(37.386051) + .setLongitudeDegrees(-122.083855) + .setAltitudeMeters(32) + .setToaGpsNanosecondsOfWeek(604000000000000L); + List<GnssSingleSatCorrection> singleSatCorrectionList = new ArrayList<>(); + singleSatCorrectionList.add(GnssSingleSatCorrectionsTest.generateTestSingleSatCorrection()); + singleSatCorrectionList.add(generateTestSingleSatCorrection()); + measurementCorrections.setSingleSatCorrectionList(singleSatCorrectionList); + } + + private static GnssSingleSatCorrection generateTestSingleSatCorrection() { + GnssSingleSatCorrection.Builder singleSatCorrection = new GnssSingleSatCorrection.Builder(); + singleSatCorrection + .setSingleSatCorrectionFlags(8) + .setConstellationType(GnssStatus.CONSTELLATION_GPS) + .setSatId(11) + .setCarrierFrequencyHz(1575430000f) + .setSatIsLos(false) + .setExcessPathLengthMeters(50.0f) + .setExcessPathLengthUncertaintyMeters(55.0f) + .setReflectingPlane(generateTestReflectingPlane()); + return singleSatCorrection.build(); + } + + private static GnssReflectingPlane generateTestReflectingPlane() { + GnssReflectingPlane.Builder reflectingPlane = + new GnssReflectingPlane.Builder() + .setLatitudeDegrees(37.386054) + .setLongitudeDegrees(-122.083855) + .setAltitudeMeters(120.0) + .setAzimuthDegrees(153); + return reflectingPlane.build(); + } +} diff --git a/location/tests/locationtests/src/android/location/GnssReflectingPlaneTest.java b/location/tests/locationtests/src/android/location/GnssReflectingPlaneTest.java new file mode 100644 index 000000000000..d7a3378e5a12 --- /dev/null +++ b/location/tests/locationtests/src/android/location/GnssReflectingPlaneTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2018 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.os.Parcel; + +import junit.framework.TestCase; + +/** Unit tests for {@link GnssReflectingPlane}. */ +public class GnssReflectingPlaneTest extends TestCase { + public void testDescribeContents() { + GnssReflectingPlane reflectingPlane = new GnssReflectingPlane.Builder().build(); + reflectingPlane.describeContents(); + } + + public void testWriteToParcel() { + GnssReflectingPlane.Builder reflectingPlane = new GnssReflectingPlane.Builder(); + setTestValues(reflectingPlane); + Parcel parcel = Parcel.obtain(); + reflectingPlane.build().writeToParcel(parcel, 0); + parcel.setDataPosition(0); + GnssReflectingPlane newReflectingPlane = + GnssReflectingPlane.CREATOR.createFromParcel(parcel); + verifyTestValues(newReflectingPlane); + parcel.recycle(); + } + + public static void verifyTestValues(GnssReflectingPlane reflectingPlane) { + assertEquals(37.386052, reflectingPlane.getLatitudeDegrees()); + assertEquals(-122.083853, reflectingPlane.getLongitudeDegrees()); + assertEquals(100.0, reflectingPlane.getAltitudeMeters()); + assertEquals(123.0, reflectingPlane.getAzimuthDegrees()); + } + + private static void setTestValues(GnssReflectingPlane.Builder reflectingPlane) { + GnssReflectingPlane refPlane = generateTestReflectingPlane(); + reflectingPlane + .setLatitudeDegrees(refPlane.getLatitudeDegrees()) + .setLongitudeDegrees(refPlane.getLongitudeDegrees()) + .setAltitudeMeters(refPlane.getAltitudeMeters()) + .setAzimuthDegrees(refPlane.getAzimuthDegrees()); + } + + public static GnssReflectingPlane generateTestReflectingPlane() { + GnssReflectingPlane.Builder reflectingPlane = + new GnssReflectingPlane.Builder() + .setLatitudeDegrees(37.386052) + .setLongitudeDegrees(-122.083853) + .setAltitudeMeters(100.0) + .setAzimuthDegrees(123.0); + return reflectingPlane.build(); + } +} diff --git a/location/tests/locationtests/src/android/location/GnssSingleSatCorrectionsTest.java b/location/tests/locationtests/src/android/location/GnssSingleSatCorrectionsTest.java new file mode 100644 index 000000000000..2e54ae463595 --- /dev/null +++ b/location/tests/locationtests/src/android/location/GnssSingleSatCorrectionsTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2018 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.os.Parcel; + +import junit.framework.TestCase; + +/** Unit tests for {@link GnssSingleSatCorrection}. */ +public class GnssSingleSatCorrectionsTest extends TestCase { + public void testDescribeContents() { + GnssSingleSatCorrection singleSatCorrection = new GnssSingleSatCorrection.Builder().build(); + singleSatCorrection.describeContents(); + } + + public void testWriteToParcel() { + GnssSingleSatCorrection.Builder singleSatCorrection = new GnssSingleSatCorrection.Builder(); + setTestValues(singleSatCorrection); + Parcel parcel = Parcel.obtain(); + singleSatCorrection.build().writeToParcel(parcel, 0); + parcel.setDataPosition(0); + GnssSingleSatCorrection newSingleSatCorrection = + GnssSingleSatCorrection.CREATOR.createFromParcel(parcel); + verifyTestValues(newSingleSatCorrection); + parcel.recycle(); + } + + public static void verifyTestValues(GnssSingleSatCorrection singleSatCorrection) { + assertEquals(15, singleSatCorrection.getSingleSatCorrectionFlags()); + assertEquals(GnssStatus.CONSTELLATION_GALILEO, singleSatCorrection.getConstellationType()); + assertEquals(12, singleSatCorrection.getSatId()); + assertEquals(1575420000f, singleSatCorrection.getCarrierFrequencyHz()); + assertEquals(true, singleSatCorrection.isSatelliteLineOfSight()); + assertEquals(10.0f, singleSatCorrection.getExcessPathLengthMeters()); + assertEquals(5.0f, singleSatCorrection.getExcessPathLengthUncertaintyMeters()); + GnssReflectingPlane reflectingPlane = singleSatCorrection.getReflectingPlane(); + GnssReflectingPlaneTest.verifyTestValues(reflectingPlane); + } + + private static void setTestValues(GnssSingleSatCorrection.Builder singleSatCorrection) { + GnssSingleSatCorrection singleSatCorr = generateTestSingleSatCorrection(); + singleSatCorrection + .setSingleSatCorrectionFlags(singleSatCorr.getSingleSatCorrectionFlags()) + .setConstellationType(singleSatCorr.getConstellationType()) + .setSatId(singleSatCorr.getSatId()) + .setCarrierFrequencyHz(singleSatCorr.getCarrierFrequencyHz()) + .setSatIsLos(singleSatCorr.isSatelliteLineOfSight()) + .setExcessPathLengthMeters(singleSatCorr.getExcessPathLengthMeters()) + .setExcessPathLengthUncertaintyMeters( + singleSatCorr.getExcessPathLengthUncertaintyMeters()) + .setReflectingPlane(singleSatCorr.getReflectingPlane()); + } + + public static GnssSingleSatCorrection generateTestSingleSatCorrection() { + GnssSingleSatCorrection.Builder singleSatCorrection = + new GnssSingleSatCorrection.Builder() + .setSingleSatCorrectionFlags(15) + .setConstellationType(GnssStatus.CONSTELLATION_GALILEO) + .setSatId(12) + .setCarrierFrequencyHz(1575420000f) + .setSatIsLos(true) + .setExcessPathLengthMeters(10.0f) + .setExcessPathLengthUncertaintyMeters(5.0f) + .setReflectingPlane(GnssReflectingPlaneTest.generateTestReflectingPlane()); + return singleSatCorrection.build(); + } +} diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index d33b61757141..2346cfc07a83 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -47,6 +47,7 @@ import android.location.Address; import android.location.Criteria; import android.location.GeocoderParams; import android.location.Geofence; +import android.location.GnssMeasurementCorrections; import android.location.IBatchedLocationCallback; import android.location.IGnssMeasurementsListener; import android.location.IGnssNavigationMessageListener; @@ -2594,6 +2595,30 @@ public class LocationManagerService extends ILocationManager.Stub { } @Override + public void injectGnssMeasurementCorrections( + GnssMeasurementCorrections measurementCorrections, String packageName) { + mContext.enforceCallingPermission( + android.Manifest.permission.LOCATION_HARDWARE, + "Location Hardware permission not granted to inject GNSS measurement corrections."); + if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) { + mGnssMeasurementsProvider.injectGnssMeasurementCorrections(measurementCorrections); + } else { + Slog.e(TAG, "Can not inject GNSS corrections due to no permission."); + } + } + + @Override + public int getGnssCapabilities(String packageName) { + mContext.enforceCallingPermission( + android.Manifest.permission.LOCATION_HARDWARE, + "Location Hardware permission not granted to obrain GNSS chipset capabilities."); + if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) { + return -1; + } + return mGnssMeasurementsProvider.getGnssCapabilities(); + } + + @Override public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) { if (mGnssMeasurementsProvider == null) { return; diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java index 0f060fe09318..9c6cb20b88b6 100644 --- a/services/core/java/com/android/server/location/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/GnssLocationProvider.java @@ -170,7 +170,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008; private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010; private static final int GPS_CAPABILITY_GEOFENCING = 0x0000020; - private static final int GPS_CAPABILITY_MEASUREMENTS = 0x0000040; + public static final int GPS_CAPABILITY_MEASUREMENTS = 0x0000040; private static final int GPS_CAPABILITY_NAV_MESSAGES = 0x0000080; // The AGPS SUPL mode @@ -1607,20 +1607,20 @@ public class GnssLocationProvider extends AbstractLocationProvider implements @NativeEntryPoint private void setEngineCapabilities(final int capabilities) { // send to handler thread for fast native return, and in-order handling - mHandler.post(() -> { - mEngineCapabilities = capabilities; + mHandler.post( + () -> { + mEngineCapabilities = capabilities; - if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) { - mNtpTimeHelper.enablePeriodicTimeInjection(); - requestUtcTime(); - } + if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) { + mNtpTimeHelper.enablePeriodicTimeInjection(); + requestUtcTime(); + } - mGnssMeasurementsProvider.onCapabilitiesUpdated(hasCapability( - GPS_CAPABILITY_MEASUREMENTS)); - mGnssNavigationMessageProvider.onCapabilitiesUpdated(hasCapability( - GPS_CAPABILITY_NAV_MESSAGES)); - restartRequests(); - }); + mGnssMeasurementsProvider.onCapabilitiesUpdated(capabilities); + mGnssNavigationMessageProvider.onCapabilitiesUpdated( + hasCapability(GPS_CAPABILITY_NAV_MESSAGES)); + restartRequests(); + }); } private void restartRequests() { diff --git a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java index 3e2ba87a033e..77dee8241bea 100644 --- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java +++ b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java @@ -17,6 +17,7 @@ package com.android.server.location; import android.content.Context; +import android.location.GnssMeasurementCorrections; import android.location.GnssMeasurementsEvent; import android.location.IGnssMeasurementsListener; import android.os.Handler; @@ -27,14 +28,13 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; /** - * An base implementation for GPS measurements provider. - * It abstracts out the responsibility of handling listeners, while still allowing technology - * specific implementations to be built. + * An base implementation for GPS measurements provider. It abstracts out the responsibility of + * handling listeners, while still allowing technology specific implementations to be built. * * @hide */ -public abstract class GnssMeasurementsProvider extends - RemoteListenerHelper<IGnssMeasurementsListener> { +public abstract class GnssMeasurementsProvider + extends RemoteListenerHelper<IGnssMeasurementsListener> { private static final String TAG = "GnssMeasurementsProvider"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); @@ -42,19 +42,19 @@ public abstract class GnssMeasurementsProvider extends private boolean mIsCollectionStarted; private boolean mEnableFullTracking; + private int mGnssEngineCapabilities; protected GnssMeasurementsProvider(Context context, Handler handler) { this(context, handler, new GnssMeasurementProviderNative()); } @VisibleForTesting - GnssMeasurementsProvider(Context context, Handler handler, - GnssMeasurementProviderNative aNative) { + GnssMeasurementsProvider( + Context context, Handler handler, GnssMeasurementProviderNative aNative) { super(context, handler, TAG); mNative = aNative; } - // TODO(b/37460011): Use this with death recovery logic. void resumeIfStarted() { if (DEBUG) { Log.d(TAG, "resumeIfStarted"); @@ -87,6 +87,25 @@ public abstract class GnssMeasurementsProvider extends } } + /** + * Injects GNSS measurement corrections into the GNSS chipset. + * + * @param measurementCorrections a {@link GnssMeasurementCorrections} object with the GNSS + * measurement corrections to be injected into the GNSS chipset. + */ + public void injectGnssMeasurementCorrections( + GnssMeasurementCorrections measurementCorrections) { + mHandler.post( + new Runnable() { + @Override + public void run() { + if (!mNative.injectGnssMeasurementCorrections(measurementCorrections)) { + Log.e(TAG, "Failure in injecting GNSS corrections."); + } + } + }); + } + @Override protected void unregisterFromService() { boolean stopped = mNative.stopMeasurementCollection(); @@ -96,20 +115,31 @@ public abstract class GnssMeasurementsProvider extends } public void onMeasurementsAvailable(final GnssMeasurementsEvent event) { - foreach((IGnssMeasurementsListener listener, int uid, String packageName) -> { - if (!hasPermission(uid, packageName)) { - logPermissionDisabledEventNotReported(TAG, packageName, "GNSS measurements"); - return; - } - listener.onGnssMeasurementsReceived(event); - }); + foreach( + (IGnssMeasurementsListener listener, int uid, String packageName) -> { + if (!hasPermission(uid, packageName)) { + logPermissionDisabledEventNotReported( + TAG, packageName, "GNSS measurements"); + return; + } + listener.onGnssMeasurementsReceived(event); + }); } - public void onCapabilitiesUpdated(boolean isGnssMeasurementsSupported) { + /** Updates the framework about the capabilities of the GNSS chipset */ + public void onCapabilitiesUpdated(int capabilities) { + mGnssEngineCapabilities = capabilities; + boolean isGnssMeasurementsSupported = + (capabilities & GnssLocationProvider.GPS_CAPABILITY_MEASUREMENTS) != 0; setSupported(isGnssMeasurementsSupported); updateResult(); } + /** Obtains the GNSS engine capabilities. */ + public int getGnssCapabilities() { + return mGnssEngineCapabilities; + } + public void onGpsEnabledChanged() { tryUpdateRegistrationWithService(); updateResult(); @@ -170,6 +200,11 @@ public abstract class GnssMeasurementsProvider extends public boolean stopMeasurementCollection() { return native_stop_measurement_collection(); } + + public boolean injectGnssMeasurementCorrections( + GnssMeasurementCorrections measurementCorrections) { + return native_inject_gnss_measurement_corrections(measurementCorrections); + } } private static native boolean native_is_measurement_supported(); @@ -177,4 +212,7 @@ public abstract class GnssMeasurementsProvider extends private static native boolean native_start_measurement_collection(boolean enableFullTracking); private static native boolean native_stop_measurement_collection(); + + private static native boolean native_inject_gnss_measurement_corrections( + GnssMeasurementCorrections measurementCorrections); } diff --git a/services/core/java/com/android/server/location/RemoteListenerHelper.java b/services/core/java/com/android/server/location/RemoteListenerHelper.java index 37d43fc1da69..e69b2ec28ebc 100644 --- a/services/core/java/com/android/server/location/RemoteListenerHelper.java +++ b/services/core/java/com/android/server/location/RemoteListenerHelper.java @@ -43,7 +43,7 @@ abstract class RemoteListenerHelper<TListener extends IInterface> { protected static final int RESULT_UNKNOWN = 5; protected static final int RESULT_NOT_ALLOWED = 6; - private final Handler mHandler; + protected final Handler mHandler; private final String mTag; private final Map<IBinder, LinkedListener> mListenerMap = new HashMap<>(); diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp index 58fd30e225c1..729aed171ab1 100644 --- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp @@ -25,6 +25,7 @@ #include <android/hardware/gnss/1.0/IGnssMeasurement.h> #include <android/hardware/gnss/1.1/IGnssMeasurement.h> #include <android/hardware/gnss/2.0/IGnssMeasurement.h> +#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h> #include <nativehelper/JNIHelp.h> #include "jni.h" #include "hardware_legacy/power.h" @@ -68,6 +69,25 @@ static jmethodID method_reportMeasurementData; static jmethodID method_reportNavigationMessages; static jmethodID method_reportLocationBatch; static jmethodID method_reportGnssServiceDied; +static jmethodID method_correctionsGetLatitudeDegrees; +static jmethodID method_correctionsGetLongitudeDegrees; +static jmethodID method_correctionsGetAltitudeMeters; +static jmethodID method_correctionsGetToaGpsNanosecondsOfWeek; +static jmethodID method_correctionsGetSingleSatCorrectionList; +static jmethodID method_listSize; +static jmethodID method_correctionListGet; +static jmethodID method_correctionSatFlags; +static jmethodID method_correctionSatConstType; +static jmethodID method_correctionSatId; +static jmethodID method_correctionSatCarrierFreq; +static jmethodID method_correctionSatIsLos; +static jmethodID method_correctionSatEpl; +static jmethodID method_correctionSatEplUnc; +static jmethodID method_correctionSatRefPlane; +static jmethodID method_correctionPlaneLatDeg; +static jmethodID method_correctionPlaneLngDeg; +static jmethodID method_correctionPlaneAltDeg; +static jmethodID method_correctionPlaneAzimDeg; /* * Save a pointer to JavaVm to attach/detach threads executing @@ -105,7 +125,10 @@ using android::hardware::gnss::V1_0::IGnssNiCallback; using android::hardware::gnss::V1_0::IGnssXtra; using android::hardware::gnss::V1_0::IGnssXtraCallback; -using android::hardware::gnss::V1_1::IGnssCallback; +using android::hardware::gnss::V2_0::IGnssCallback; +using android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections; +using android::hardware::gnss::measurement_corrections::V1_0::SingleSatCorrection; +using android::hardware::gnss::measurement_corrections::V1_0::ReflectingPlane; using android::hidl::base::V1_0::IBase; @@ -123,6 +146,9 @@ using IGnssMeasurementCallback_V2_0 = android::hardware::gnss::V2_0::IGnssMeasur using IAGnssRil_V1_0 = android::hardware::gnss::V1_0::IAGnssRil; using IAGnssRil_V2_0 = android::hardware::gnss::V2_0::IAGnssRil; +using IMeasurementCorrections = + android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections; + struct GnssDeathRecipient : virtual public hidl_death_recipient { // hidl_death_recipient interface @@ -155,6 +181,11 @@ sp<IGnssMeasurement_V1_0> gnssMeasurementIface = nullptr; sp<IGnssMeasurement_V1_1> gnssMeasurementIface_V1_1 = nullptr; sp<IGnssMeasurement_V2_0> gnssMeasurementIface_V2_0 = nullptr; sp<IGnssNavigationMessage> gnssNavigationMessageIface = nullptr; +sp<IMeasurementCorrections> gnssCorrectionsIface = nullptr; +// This boolean is needed to ensure that Gnsss Measurement Corrections related method are only +// initalized when needed which will be few devices initially +bool firstGnssMeasurementCorrectionInjected = false; + #define WAKE_LOCK_NAME "GPS" @@ -415,6 +446,8 @@ struct GnssCallback : public IGnssCallback { // New in 1.1 Return<void> gnssNameCb(const android::hardware::hidl_string& name) override; + Return<void> gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override; + // TODO(b/73306084): Reconsider allocation cost vs threadsafety on these statics static const char* sNmeaString; static size_t sNmeaStringLength; @@ -537,6 +570,10 @@ Return<void> GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) { return Void(); } +Return<void> GnssCallback::gnssSetCapabilitiesCb_2_0(uint32_t capabilities) { + return GnssCallback::gnssSetCapabilitesCb(capabilities); +} + Return<void> GnssCallback::gnssAcquireWakelockCb() { acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); return Void(); @@ -1283,6 +1320,12 @@ static void android_location_GnssLocationProvider_init_once(JNIEnv* env, jclass if (gnssHal_V2_0 != nullptr) { // TODO(b/119638366): getExtensionGnssMeasurement_1_1 from gnssHal_V2_0 auto gnssMeasurement = gnssHal_V2_0->getExtensionGnssMeasurement_2_0(); + auto gnssCorrections = gnssHal_V2_0->getExtensionMeasurementCorrections(); + if (!gnssCorrections.isOk()) { + ALOGD("Unable to get a handle to GnssMeasurementCorrections interface"); + } else { + gnssCorrectionsIface = gnssCorrections; + } if (!gnssMeasurement.isOk()) { ALOGD("Unable to get a handle to GnssMeasurement_V2_0"); } else { @@ -1386,11 +1429,14 @@ static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject sp<IGnssCallback> gnssCbIface = new GnssCallback(); Return<bool> result = false; - if (gnssHal_V1_1 != nullptr) { + if (gnssHal_V2_0 != nullptr) { + result = gnssHal_V2_0->setCallback_2_0(gnssCbIface); + } else if (gnssHal_V1_1 != nullptr) { result = gnssHal_V1_1->setCallback_1_1(gnssCbIface); } else { result = gnssHal->setCallback(gnssCbIface); } + if (!result.isOk() || !result) { ALOGE("SetCallback for Gnss Interface fails\n"); return JNI_FALSE; @@ -1933,6 +1979,150 @@ static jboolean android_location_GnssMeasurementsProvider_stop_measurement_colle return boolToJbool(result.isOk()); } +static jboolean android_location_GnssMeasurementsProvider_inject_gnss_measurement_corrections( + JNIEnv* env, + jobject obj /* clazz*/, + jobject correctionsObj) { + + if (gnssCorrectionsIface == nullptr) { + ALOGW("Trying to inject GNSS corrections on a chipset that does not support them."); + return JNI_FALSE; + } + if (firstGnssMeasurementCorrectionInjected == false) { + jclass measCorrClass = env->GetObjectClass(correctionsObj); + method_correctionsGetLatitudeDegrees = env->GetMethodID( + measCorrClass,"getLatitudeDegrees", "()D"); + + method_correctionsGetLongitudeDegrees = env->GetMethodID( + measCorrClass, "getLongitudeDegrees", "()D"); + + method_correctionsGetAltitudeMeters = env->GetMethodID( + measCorrClass, "getAltitudeMeters", "()D"); + + method_correctionsGetToaGpsNanosecondsOfWeek = env->GetMethodID( + measCorrClass, "getToaGpsNanosecondsOfWeek", "()J"); + + method_correctionsGetSingleSatCorrectionList = env->GetMethodID( + measCorrClass, "getSingleSatCorrectionList", "()Ljava.util.List;"); + } + + jdouble latitudeDegreesCorr = env->CallDoubleMethod( + correctionsObj, method_correctionsGetLatitudeDegrees); + jdouble longitudeDegreesCorr = env->CallDoubleMethod( + correctionsObj, method_correctionsGetLongitudeDegrees); + jdouble altitudeDegreesCorr = env->CallDoubleMethod( + correctionsObj, method_correctionsGetAltitudeMeters); + jlong toaGpsNanosOfWeek = env->CallLongMethod( + correctionsObj, method_correctionsGetToaGpsNanosecondsOfWeek); + jobject singleSatCorrectionList = env->CallObjectMethod(correctionsObj, + method_correctionsGetSingleSatCorrectionList); + + if (firstGnssMeasurementCorrectionInjected == false) { + jclass corrListClass = env->GetObjectClass(singleSatCorrectionList); + method_listSize = env->GetMethodID(corrListClass, "size", "()I"); + method_correctionListGet = env->GetMethodID( + corrListClass, "get", "(I)Landroid/location/GnssSingleSatCorrection;"); + } + + auto len = (singleSatCorrectionList == nullptr) + ? 0 + : env->CallIntMethod(singleSatCorrectionList, method_listSize); + hidl_vec<SingleSatCorrection> list(len); + + for (uint16_t i = 0; i < len; ++i) { + jobject singleSatCorrectionObj = env->CallObjectMethod( + singleSatCorrectionList, method_correctionListGet, i); + + if (firstGnssMeasurementCorrectionInjected == false) { + jclass singleSatCorrClass = env->GetObjectClass(singleSatCorrectionObj); + method_correctionSatFlags = env->GetMethodID( + singleSatCorrClass, "getSingleSatCorrectionFlags", "()I"); + method_correctionSatConstType = env->GetMethodID( + singleSatCorrClass, "getConstellationType", "()I"); + method_correctionSatId= env->GetMethodID( + singleSatCorrClass, "getSatId", "()I"); + method_correctionSatCarrierFreq = env->GetMethodID( + singleSatCorrClass, "getCarrierFrequencyHz", "()F"); + method_correctionSatIsLos = env->GetMethodID( + singleSatCorrClass,"getSatIsLos", "()Z"); + method_correctionSatEpl = env->GetMethodID( + singleSatCorrClass, "getExcessPathLengthMeters", "()F"); + method_correctionSatEplUnc = env->GetMethodID( + singleSatCorrClass, "getExcessPathLengthUncertaintyMeters", "()F"); + method_correctionSatRefPlane = env->GetMethodID( + singleSatCorrClass, "getReflectingPlane", + "()Landroid/location/GnssReflectingPlane;"); + } + + jint correctionFlags = + env->CallIntMethod(singleSatCorrectionObj, method_correctionSatFlags); + jint constType = env->CallIntMethod(singleSatCorrectionObj, + method_correctionSatConstType); + jint satId = + env->CallIntMethod(singleSatCorrectionObj, method_correctionSatId); + jfloat carrierFreqHz = env->CallFloatMethod( + singleSatCorrectionObj, method_correctionSatCarrierFreq); + jboolean satIsLos = env->CallBooleanMethod(singleSatCorrectionObj, + method_correctionSatIsLos); + jfloat eplMeters = + env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEpl); + jfloat eplUncMeters = env->CallFloatMethod(singleSatCorrectionObj, + method_correctionSatEplUnc); + jobject reflectingPlaneObj = env->CallObjectMethod( + singleSatCorrectionObj, method_correctionSatRefPlane); + + if (firstGnssMeasurementCorrectionInjected == false) { + jclass refPlaneClass = env->GetObjectClass(reflectingPlaneObj); + method_correctionPlaneLatDeg = env->GetMethodID( + refPlaneClass, "getLatitudeDegrees", "()D"); + method_correctionPlaneLngDeg = env->GetMethodID( + refPlaneClass, "getLongitudeDegrees", "()D"); + method_correctionPlaneAltDeg = env->GetMethodID( + refPlaneClass, "getAltitudeMeters", "()D"); + method_correctionPlaneAzimDeg = env->GetMethodID( + refPlaneClass, "getAzimuthDegrees", "()D"); + } + + jdouble latitudeDegreesRefPlane = env->CallDoubleMethod( + reflectingPlaneObj, method_correctionPlaneLatDeg); + jdouble longitudeDegreesRefPlane = env->CallDoubleMethod( + reflectingPlaneObj, method_correctionPlaneLngDeg); + jdouble altitudeDegreesRefPlane = env->CallDoubleMethod( + reflectingPlaneObj, method_correctionPlaneAltDeg); + jdouble azimuthDegreeRefPlane = env->CallDoubleMethod( + reflectingPlaneObj, method_correctionPlaneAzimDeg); + ReflectingPlane reflectingPlane = { + .latitudeDegrees = latitudeDegreesRefPlane, + .longitudeDegrees = longitudeDegreesRefPlane, + .altitudeMeters = altitudeDegreesRefPlane, + .azimuthDegrees = azimuthDegreeRefPlane, + }; + + SingleSatCorrection singleSatCorrection = { + .singleSatCorrectionFlags = static_cast<uint16_t>(correctionFlags), + .constellation = static_cast<GnssConstellationType>(constType), + .svid = static_cast<uint16_t>(satId), + .carrierFrequencyHz = carrierFreqHz, + .satIsLos = static_cast<bool>(satIsLos), + .excessPathLengthMeters = eplMeters, + .excessPathLengthUncertaintyMeters = eplUncMeters, + .reflectingPlane = reflectingPlane, + }; + list[i] = singleSatCorrection; + } + MeasurementCorrections measurementCorrections = { + .latitudeDegrees = latitudeDegreesCorr, + .longitudeDegrees = longitudeDegreesCorr, + .altitudeMeters = altitudeDegreesCorr, + .toaGpsNanosecondsOfWeek = static_cast<uint64_t>(toaGpsNanosOfWeek), + .satCorrections = list, + }; + + gnssCorrectionsIface->setCorrections(measurementCorrections); + firstGnssMeasurementCorrectionInjected = true; + return JNI_TRUE; +} + static jboolean android_location_GnssNavigationMessageProvider_is_navigation_message_supported( JNIEnv* env, jclass clazz) { @@ -2310,19 +2500,20 @@ static const JNINativeMethod sGeofenceMethods[] = { }; static const JNINativeMethod sMeasurementMethods[] = { - /* name, signature, funcPtr */ - {"native_is_measurement_supported", - "()Z", - reinterpret_cast<void *>( - android_location_GnssMeasurementsProvider_is_measurement_supported)}, - {"native_start_measurement_collection", - "(Z)Z", - reinterpret_cast<void *>( - android_location_GnssMeasurementsProvider_start_measurement_collection)}, - {"native_stop_measurement_collection", - "()Z", - reinterpret_cast<void *>( - android_location_GnssMeasurementsProvider_stop_measurement_collection)}, + /* name, signature, funcPtr */ + {"native_is_measurement_supported", "()Z", + reinterpret_cast<void*>( + android_location_GnssMeasurementsProvider_is_measurement_supported)}, + {"native_start_measurement_collection", "(Z)Z", + reinterpret_cast<void*>( + android_location_GnssMeasurementsProvider_start_measurement_collection)}, + {"native_stop_measurement_collection", "()Z", + reinterpret_cast<void*>( + android_location_GnssMeasurementsProvider_stop_measurement_collection)}, + {"native_inject_gnss_measurement_corrections", + "(Landroid/location/GnssMeasurementCorrections;)Z", + reinterpret_cast<void*>( + android_location_GnssMeasurementsProvider_inject_gnss_measurement_corrections)}, }; static const JNINativeMethod sNavigationMessageMethods[] = { |