From daffd228199ed35d890dae22b440ea1c66eadf4e Mon Sep 17 00:00:00 2001 From: Shinru Han Date: Mon, 21 Dec 2020 21:11:33 +0800 Subject: Add CorrelationVector AIDL (framework/base) Test: on cuttlefish Bug: 171516016 Change-Id: Ib214c52701e0d0139083e8e3bb3c5862d29da48a --- .../java/android/location/CorrelationVector.java | 228 +++++++++++++++++++++ .../java/android/location/GnssCapabilities.java | 30 ++- .../java/android/location/GnssMeasurement.java | 83 ++++++++ .../android/location/GnssMeasurementRequest.java | 50 ++++- .../java/android/location/LocationManager.java | 4 +- 5 files changed, 388 insertions(+), 7 deletions(-) create mode 100644 location/java/android/location/CorrelationVector.java (limited to 'location/java') diff --git a/location/java/android/location/CorrelationVector.java b/location/java/android/location/CorrelationVector.java new file mode 100644 index 000000000000..eca35dd69362 --- /dev/null +++ b/location/java/android/location/CorrelationVector.java @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.location; + +import android.annotation.FloatRange; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.util.Preconditions; + +import java.util.Arrays; +import java.util.Objects; + +/** + * Contains info about the correlation output of incoming GNSS signal and a local copy of + * its corresponding spreading code at a given frequency offset. + * + * @hide + */ +@SystemApi +public final class CorrelationVector implements Parcelable { + + private final double mSamplingWidthMeters; + private final double mSamplingStartMeters; + private final int mFrequencyOffsetMetersPerSecond; + @NonNull private final int[] mMagnitude; + + /** + * Returns the space between correlation samples in meters. + */ + @FloatRange(from = 0.0f, fromInclusive = false) + public double getSamplingWidthMeters() { + return mSamplingWidthMeters; + } + + /** + * Returns the offset of the first sampling bin in meters. + * + *

The following sampling bins are located at positive offsets from this value as follows: + * samplingStartMeters, samplingStartMeters + samplingWidthMeters, ... , samplingStartMeters + + * (magnitude.size-1) * samplingWidthMeters. + * + */ + @FloatRange(from = 0.0f) + public double getSamplingStartMeters() { + return mSamplingStartMeters; + } + + /** + * Returns the frequency offset from reported pseudorange rate for this CorrelationVector. + */ + @IntRange(from = 0) + public int getFrequencyOffsetMetersPerSecond() { + return mFrequencyOffsetMetersPerSecond; + } + + /** + * Returns the data array representing normalized correlation magnitude values. + * + *

The data are normalized correlation magnitude values from -1 to 1, the reported value must + * be encoded as signed 16 bit integer where 1 is represented by 32767 and -1 is represented + * by -32768. + * + */ + @NonNull + public int[] getMagnitude() { + return mMagnitude.clone(); + } + + private CorrelationVector(Builder builder) { + Preconditions.checkNotNull(builder.mMagnitude, "Magnitude array must not be null"); + Preconditions.checkArgumentPositive(builder.mMagnitude.length, + "Magnitude array must have non-zero length"); + Preconditions.checkArgumentNonNegative(builder.mFrequencyOffsetMetersPerSecond, + "FrequencyOffsetMetersPerSecond must be non-negative (greater than or equal to 0)"); + Preconditions.checkArgument(builder.mSamplingWidthMeters > 0.0, + "SamplingWidthMeters must be positive (greater than 0)"); + Preconditions.checkArgument(builder.mSamplingStartMeters >= 0.0, + "SamplingStartMeters must be non-negative (greater than or equal to 0)"); + mMagnitude = builder.mMagnitude; + mFrequencyOffsetMetersPerSecond = builder.mFrequencyOffsetMetersPerSecond; + mSamplingWidthMeters = builder.mSamplingWidthMeters; + mSamplingStartMeters = builder.mSamplingStartMeters; + } + + private CorrelationVector(Parcel in) { + mSamplingWidthMeters = in.readDouble(); + mSamplingStartMeters = in.readDouble(); + mFrequencyOffsetMetersPerSecond = in.readInt(); + mMagnitude = new int[in.readInt()]; + in.readIntArray(mMagnitude); + } + + /* + * Method definitions to support Parcelable operations. + */ + public static final @NonNull Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public CorrelationVector createFromParcel(Parcel parcel) { + return new CorrelationVector(parcel); + } + + @Override + public CorrelationVector[] newArray(int size) { + return new CorrelationVector[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @NonNull + @Override + public String toString() { + return "CorrelationVector{" + + "FrequencyOffsetMetersPerSecond=" + mFrequencyOffsetMetersPerSecond + + ", SamplingWidthMeters=" + mSamplingWidthMeters + + ", SamplingStartMeters=" + mSamplingStartMeters + + ", Magnitude=" + Arrays.toString(mMagnitude) + + '}'; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeDouble(mSamplingWidthMeters); + dest.writeDouble(mSamplingStartMeters); + dest.writeInt(mFrequencyOffsetMetersPerSecond); + dest.writeInt(mMagnitude.length); + dest.writeIntArray(mMagnitude); + } + + /** + * Returns true if this {@link CorrelationVector} is equivalent to the given object. + * Returns false otherwise. + */ + @Override + public boolean equals(Object object) { + if (object == this) { + return true; + } + if (!(object instanceof CorrelationVector)) { + return false; + } + CorrelationVector c = (CorrelationVector) object; + return Arrays.equals(mMagnitude, c.getMagnitude()) + && Double.compare(mSamplingWidthMeters, c.getSamplingWidthMeters()) == 0 + && Double.compare(mSamplingStartMeters, c.getSamplingStartMeters()) == 0 + && Integer.compare(mFrequencyOffsetMetersPerSecond, + c.getFrequencyOffsetMetersPerSecond()) == 0; + } + + @Override + public int hashCode() { + return Objects.hash(mSamplingWidthMeters, mSamplingStartMeters, + mFrequencyOffsetMetersPerSecond, Arrays.hashCode(mMagnitude)); + } + + /** + * Builder class for CorrelationVector. + */ + public static final class Builder { + + private double mSamplingWidthMeters; + private double mSamplingStartMeters; + private int mFrequencyOffsetMetersPerSecond; + @NonNull private int[] mMagnitude; + + /** Sets the space between correlation samples in meters. */ + @NonNull + public Builder setSamplingWidthMeters( + @FloatRange(from = 0.0f, fromInclusive = false) double samplingWidthMeters) { + mSamplingWidthMeters = samplingWidthMeters; + return this; + } + + /** Sets the offset of the first sampling bin in meters. */ + @NonNull + public Builder setSamplingStartMeters(@FloatRange(from = 0.0f) double samplingStartMeters) { + mSamplingStartMeters = samplingStartMeters; + return this; + } + + /** Sets the frequency offset from reported pseudorange rate for this CorrelationVector */ + @NonNull + public Builder setFrequencyOffsetMetersPerSecond( + @IntRange(from = 0) int frequencyOffsetMetersPerSecond) { + mFrequencyOffsetMetersPerSecond = frequencyOffsetMetersPerSecond; + return this; + } + + /** Sets the data array representing normalized correlation magnitude values. */ + @NonNull + public Builder setMagnitude(@NonNull int[] magnitude) { + mMagnitude = magnitude; + return this; + } + + /** + * Build CorrelationVector object. + * + * @return instance of CorrelationVector + */ + @NonNull + public CorrelationVector build() { + return new CorrelationVector(this); + } + } +} diff --git a/location/java/android/location/GnssCapabilities.java b/location/java/android/location/GnssCapabilities.java index b650a9fd0416..a5e28158ab78 100644 --- a/location/java/android/location/GnssCapabilities.java +++ b/location/java/android/location/GnssCapabilities.java @@ -58,6 +58,8 @@ public final class GnssCapabilities implements Parcelable { /** @hide */ public static final int TOP_HAL_CAPABILITY_ANTENNA_INFO = 2048; /** @hide */ + public static final int TOP_HAL_CAPABILITY_CORRELATION_VECTOR = 4096; + /** @hide */ public static final int TOP_HAL_CAPABILITY_SATELLITE_PVT = 8192; /** @hide */ @@ -67,7 +69,8 @@ public final class GnssCapabilities implements Parcelable { TOP_HAL_CAPABILITY_MEASUREMENTS, TOP_HAL_CAPABILITY_NAV_MESSAGES, TOP_HAL_CAPABILITY_LOW_POWER_MODE, TOP_HAL_CAPABILITY_SATELLITE_BLOCKLIST, TOP_HAL_CAPABILITY_MEASUREMENT_CORRECTIONS, TOP_HAL_CAPABILITY_ANTENNA_INFO, - TOP_HAL_CAPABILITY_SATELLITE_PVT}) + TOP_HAL_CAPABILITY_CORRELATION_VECTOR, TOP_HAL_CAPABILITY_SATELLITE_PVT}) + @Retention(RetentionPolicy.SOURCE) public @interface TopHalCapabilityFlags {} @@ -336,6 +339,17 @@ public final class GnssCapabilities implements Parcelable { return (mTopFlags & TOP_HAL_CAPABILITY_ANTENNA_INFO) != 0; } + /** + * Returns {@code true} if GNSS chipset supports correlation vectors as part of measurements + * outputs, {@code false} otherwise. + * + * @hide + */ + @SystemApi + public boolean hasMeasurementCorrelationVectors() { + return (mTopFlags & TOP_HAL_CAPABILITY_CORRELATION_VECTOR) != 0; + } + /** * Returns {@code true} if GNSS chipset supports line-of-sight satellite identification * measurement corrections, {@code false} otherwise. @@ -533,6 +547,9 @@ public final class GnssCapabilities implements Parcelable { if (hasAntennaInfo()) { builder.append("ANTENNA_INFO "); } + if (hasMeasurementCorrelationVectors()) { + builder.append("MEASUREMENT_CORRELATION_VECTORS "); + } if (hasMeasurementCorrectionsLosSats()) { builder.append("LOS_SATS "); } @@ -719,6 +736,17 @@ public final class GnssCapabilities implements Parcelable { return this; } + /** + * Sets correlation vector capability. + * + * @hide + */ + @SystemApi + public @NonNull Builder setHasMeasurementCorrelationVectors(boolean capable) { + mTopFlags = setFlag(mTopFlags, TOP_HAL_CAPABILITY_CORRELATION_VECTOR, capable); + return this; + } + /** * Sets measurement corrections line-of-sight satellites capabilitity. * diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java index 5509a6c65614..c3615fed3a0e 100644 --- a/location/java/android/location/GnssMeasurement.java +++ b/location/java/android/location/GnssMeasurement.java @@ -38,6 +38,9 @@ import android.os.Parcelable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; /** * A class representing a GNSS satellite measurement, containing raw and computed information. @@ -70,6 +73,7 @@ public final class GnssMeasurement implements Parcelable { private double mSatelliteInterSignalBiasNanos; private double mSatelliteInterSignalBiasUncertaintyNanos; @Nullable private SatellitePvt mSatellitePvt; + @Nullable private Collection mReadOnlyCorrelationVectors; // The following enumerations must be in sync with the values declared in GNSS HAL. @@ -77,6 +81,7 @@ public final class GnssMeasurement implements Parcelable { private static final int HAS_CODE_TYPE = (1 << 14); private static final int HAS_BASEBAND_CN0 = (1 << 15); private static final int HAS_SATELLITE_PVT = (1 << 20); + private static final int HAS_CORRELATION_VECTOR = (1 << 21); /** * The status of the multipath indicator. @@ -279,6 +284,7 @@ public final class GnssMeasurement implements Parcelable { mSatelliteInterSignalBiasUncertaintyNanos = measurement.mSatelliteInterSignalBiasUncertaintyNanos; mSatellitePvt = measurement.mSatellitePvt; + mReadOnlyCorrelationVectors = measurement.mReadOnlyCorrelationVectors; } /** @@ -1712,6 +1718,7 @@ public final class GnssMeasurement implements Parcelable { * *

The value is only available if {@link #hasSatellitePvt()} is * {@code true}. + * * @hide */ @Nullable @@ -1745,6 +1752,58 @@ public final class GnssMeasurement implements Parcelable { resetFlag(HAS_SATELLITE_PVT); } + /** + * Returns {@code true} if {@link #getCorrelationVectors()} is available, + * {@code false} otherwise. + * + * @hide + */ + @SystemApi + public boolean hasCorrelationVectors() { + return isFlagSet(HAS_CORRELATION_VECTOR); + } + + /** + * Gets read-only collection of CorrelationVector with each CorrelationVector corresponding to a + * frequency offset. + * + *

To represent correlation values over a 2D spaces (delay and frequency), a + * CorrelationVector is required per frequency offset, and each CorrelationVector contains + * correlation values at equally spaced spatial offsets. + * + * @hide + */ + @Nullable + @SystemApi + public Collection getCorrelationVectors() { + return mReadOnlyCorrelationVectors; + } + + /** + * Sets the CorrelationVectors. + * + * @hide + */ + @TestApi + public void setCorrelationVectors(@Nullable Collection correlationVectors) { + if (correlationVectors == null || correlationVectors.isEmpty()) { + resetCorrelationVectors(); + } else { + setFlag(HAS_CORRELATION_VECTOR); + mReadOnlyCorrelationVectors = Collections.unmodifiableCollection(correlationVectors); + } + } + + /** + * Resets the CorrelationVectors. + * + * @hide + */ + @TestApi + public void resetCorrelationVectors() { + resetFlag(HAS_CORRELATION_VECTOR); + mReadOnlyCorrelationVectors = null; + } public static final @NonNull Creator CREATOR = new Creator() { @Override @@ -1781,6 +1840,15 @@ public final class GnssMeasurement implements Parcelable { ClassLoader classLoader = getClass().getClassLoader(); gnssMeasurement.mSatellitePvt = parcel.readParcelable(classLoader); } + if (gnssMeasurement.hasCorrelationVectors()) { + CorrelationVector[] correlationVectorsArray = + new CorrelationVector[parcel.readInt()]; + parcel.readTypedArray(correlationVectorsArray, CorrelationVector.CREATOR); + Collection corrVecCollection = + Arrays.asList(correlationVectorsArray); + gnssMeasurement.mReadOnlyCorrelationVectors = + Collections.unmodifiableCollection(corrVecCollection); + } return gnssMeasurement; } @@ -1821,6 +1889,13 @@ public final class GnssMeasurement implements Parcelable { if (hasSatellitePvt()) { parcel.writeParcelable(mSatellitePvt, flags); } + if (hasCorrelationVectors()) { + int correlationVectorCount = mReadOnlyCorrelationVectors.size(); + CorrelationVector[] correlationVectorArray = + mReadOnlyCorrelationVectors.toArray(new CorrelationVector[correlationVectorCount]); + parcel.writeInt(correlationVectorArray.length); + parcel.writeTypedArray(correlationVectorArray, flags); + } } @Override @@ -1928,6 +2003,13 @@ public final class GnssMeasurement implements Parcelable { builder.append(mSatellitePvt.toString()); } + if (hasCorrelationVectors()) { + for (CorrelationVector correlationVector : mReadOnlyCorrelationVectors) { + builder.append(correlationVector.toString()); + builder.append("\n"); + } + } + return builder.toString(); } @@ -1958,6 +2040,7 @@ public final class GnssMeasurement implements Parcelable { resetSatelliteInterSignalBiasNanos(); resetSatelliteInterSignalBiasUncertaintyNanos(); resetSatellitePvt(); + resetCorrelationVectors(); } private void setFlag(int flag) { diff --git a/location/java/android/location/GnssMeasurementRequest.java b/location/java/android/location/GnssMeasurementRequest.java index 613f5918b708..f509252e7542 100644 --- a/location/java/android/location/GnssMeasurementRequest.java +++ b/location/java/android/location/GnssMeasurementRequest.java @@ -17,20 +17,38 @@ package android.location; import android.annotation.NonNull; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; +import java.util.Objects; + /** * This class contains extra parameters to pass in a GNSS measurement request. */ public final class GnssMeasurementRequest implements Parcelable { + private final boolean mCorrelationVectorOutputsEnabled; private final boolean mFullTracking; /** * Creates a {@link GnssMeasurementRequest} with a full list of parameters. */ - private GnssMeasurementRequest(boolean fullTracking) { + private GnssMeasurementRequest(boolean fullTracking, boolean correlationVectorOutputsEnabled) { mFullTracking = fullTracking; + mCorrelationVectorOutputsEnabled = correlationVectorOutputsEnabled; + } + + /** + * Represents whether to enable correlation vector outputs. + * + *

If true, enable correlation vectors as part of the raw GNSS measurements outputs. + * If false, disable correlation vectors. + * + * @hide + */ + @SystemApi + public boolean isCorrelationVectorOutputsEnabled() { + return mCorrelationVectorOutputsEnabled; } /** @@ -56,7 +74,7 @@ public final class GnssMeasurementRequest implements Parcelable { @Override @NonNull public GnssMeasurementRequest createFromParcel(@NonNull Parcel parcel) { - return new GnssMeasurementRequest(parcel.readBoolean()); + return new GnssMeasurementRequest(parcel.readBoolean(), parcel.readBoolean()); } @Override @@ -68,6 +86,7 @@ public final class GnssMeasurementRequest implements Parcelable { @Override public void writeToParcel(@NonNull Parcel parcel, int flags) { parcel.writeBoolean(mFullTracking); + parcel.writeBoolean(mCorrelationVectorOutputsEnabled); } @NonNull @@ -78,6 +97,9 @@ public final class GnssMeasurementRequest implements Parcelable { if (mFullTracking) { s.append("FullTracking"); } + if (mCorrelationVectorOutputsEnabled) { + s.append(", CorrelationVectorOutPuts"); + } s.append(']'); return s.toString(); } @@ -90,13 +112,15 @@ public final class GnssMeasurementRequest implements Parcelable { GnssMeasurementRequest other = (GnssMeasurementRequest) obj; if (mFullTracking != other.mFullTracking) return false; - + if (mCorrelationVectorOutputsEnabled != other.mCorrelationVectorOutputsEnabled) { + return false; + } return true; } @Override public int hashCode() { - return mFullTracking ? 1 : 0; + return Objects.hash(mFullTracking, mCorrelationVectorOutputsEnabled); } @Override @@ -106,6 +130,7 @@ public final class GnssMeasurementRequest implements Parcelable { /** Builder for {@link GnssMeasurementRequest} */ public static final class Builder { + private boolean mCorrelationVectorOutputsEnabled; private boolean mFullTracking; /** @@ -118,9 +143,24 @@ public final class GnssMeasurementRequest implements Parcelable { * Constructs a {@link Builder} instance by copying a {@link GnssMeasurementRequest}. */ public Builder(@NonNull GnssMeasurementRequest request) { + mCorrelationVectorOutputsEnabled = request.isCorrelationVectorOutputsEnabled(); mFullTracking = request.isFullTracking(); } + /** + * Set the value of whether to enable correlation vector outputs, which is false by default. + * + *

If true, enable correlation vectors as part of the raw GNSS measurements outputs. + * If false, disable correlation vectors. + * + * @hide + */ + @SystemApi + @NonNull public Builder setCorrelationVectorOutputsEnabled(boolean value) { + mCorrelationVectorOutputsEnabled = value; + return this; + } + /** * Set the value of whether to enable full GNSS tracking, which is false by default. * @@ -146,7 +186,7 @@ public final class GnssMeasurementRequest implements Parcelable { /** Builds a {@link GnssMeasurementRequest} instance as specified by this builder. */ @NonNull public GnssMeasurementRequest build() { - return new GnssMeasurementRequest(mFullTracking); + return new GnssMeasurementRequest(mFullTracking, mCorrelationVectorOutputsEnabled); } } } diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 2dc9eb44236f..0ce1ad0d9380 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -3171,7 +3171,9 @@ public class LocationManager { for (GnssMeasurementRequest request : requests) { if (request.isFullTracking()) { builder.setFullTracking(true); - break; + } + if (request.isCorrelationVectorOutputsEnabled()) { + builder.setCorrelationVectorOutputsEnabled(true); } } -- cgit v1.2.3-59-g8ed1b