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
This commit is contained in:
gomo
2018-12-12 16:49:39 -08:00
parent 6fa14abad3
commit 226b7b7775
16 changed files with 1439 additions and 57 deletions

View File

@@ -2532,6 +2532,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();
@@ -2768,8 +2843,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);

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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(

View File

@@ -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.

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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;
@@ -2593,6 +2594,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) {

View File

@@ -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
@@ -1596,20 +1596,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() {

View File

@@ -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);
}

View File

@@ -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<>();

View File

@@ -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[] = {