Bluesky Android Q Platform Changes
- Changes to C++ HAL and GNSS Location Provder Code to inject
corrections to chipset
- Changes to JNI bridge to translate the Java corrections to C++
- Changes to JAVA side of the bridge: GnssLocationProvider.cpp to pipe
the corrections through the JNI
- Build the Locaiton Manager First Party APIs and methods
- Build needed Java containers: GnssMeasuremetCorrections.java,
GnssSingleSatCorrections.java and ReflectingPlane.java
- Build the Parcelables to send all our Java objects through processes
- Build piping methods in CallbackTransport.java,
LocationMangerservice.java, etc to pass the data in both direcions
- update API docs: current.txt and system-current.txt
Bug: 111441283
Test: Existing tests pass.
Change-Id: I8650fea21c69c8f31ba9cabe63d4a6676ffe38d7
diff --git a/api/system-current.txt b/api/system-current.txt
index 7d890c6..53e4e08 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2532,6 +2532,81 @@
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();
@@ -2768,8 +2843,10 @@
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 21f6306..1188b13b 100644
--- a/location/java/android/location/GnssMeasurementCallbackTransport.java
+++ b/location/java/android/location/GnssMeasurementCallbackTransport.java
@@ -19,6 +19,8 @@
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 @@
*/
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 @@
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 0000000..b05eb54
--- /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 0000000..b81bf90
--- /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 0000000..64b3752
--- /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 0000000..6c757f9
--- /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 05d49e5..bdc84da 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -21,6 +21,7 @@
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 @@
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 1cd3d86..040e4f9 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -22,6 +22,7 @@
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 @@
}
/**
- * 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 0000000..c18d58f
--- /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 0000000..d7a3378
--- /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 0000000..2e54ae4
--- /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 d33b617..2346cfc 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.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 @@
}
@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 29e1878..73bdd41 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 @@
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
@@ -1596,20 +1596,20 @@
@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 3e2ba87..77dee82 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 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 @@
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 @@
}
}
+ /**
+ * 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 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 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 @@
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 37d43fc..e69b2ec 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 @@
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 58fd30e..729aed1 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_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::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 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_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 @@
// 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();
}
+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 @@
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 @@
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 @@
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 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[] = {