1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.location; 18 19 import android.annotation.FloatRange; 20 import android.annotation.NonNull; 21 import android.annotation.SystemApi; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 25 import com.android.internal.util.Preconditions; 26 27 import java.util.Arrays; 28 import java.util.Objects; 29 30 /** 31 * Contains info about the correlation output of incoming GNSS signal and a local copy of 32 * its corresponding spreading code at a given frequency offset. 33 * 34 * @hide 35 */ 36 @SystemApi 37 public final class CorrelationVector implements Parcelable { 38 39 private final double mSamplingWidthMeters; 40 private final double mSamplingStartMeters; 41 private final double mFrequencyOffsetMetersPerSecond; 42 @NonNull private final int[] mMagnitude; 43 44 /** 45 * Returns the space between correlation samples in meters. 46 */ 47 @FloatRange(from = 0.0f, fromInclusive = false) getSamplingWidthMeters()48 public double getSamplingWidthMeters() { 49 return mSamplingWidthMeters; 50 } 51 52 /** 53 * Returns the offset of the first sampling bin in meters. 54 * 55 * <p>The following sampling bins are located at positive offsets from this value as follows: 56 * samplingStartMeters, samplingStartMeters + samplingWidthMeters, ... , samplingStartMeters + 57 * (magnitude.size-1) * samplingWidthMeters. 58 * 59 */ 60 @FloatRange(from = 0.0f) getSamplingStartMeters()61 public double getSamplingStartMeters() { 62 return mSamplingStartMeters; 63 } 64 65 /** 66 * Returns the frequency offset from reported pseudorange rate for this CorrelationVector. 67 */ 68 @FloatRange(from = 0.0f) getFrequencyOffsetMetersPerSecond()69 public double getFrequencyOffsetMetersPerSecond() { 70 return mFrequencyOffsetMetersPerSecond; 71 } 72 73 /** 74 * Returns the data array representing normalized correlation magnitude values. 75 * 76 * <p>The data are normalized correlation magnitude values from -1 to 1, the reported value must 77 * be encoded as signed 16 bit integer where 1 is represented by 32767 and -1 is represented 78 * by -32768. 79 * 80 * <p>The values are quantized using a 16bit integer to save on the data size since the array 81 * contains real data and it might grow. 82 * 83 */ 84 @NonNull getMagnitude()85 public int[] getMagnitude() { 86 return mMagnitude.clone(); 87 } 88 CorrelationVector(Builder builder)89 private CorrelationVector(Builder builder) { 90 Preconditions.checkNotNull(builder.mMagnitude, "Magnitude array must not be null"); 91 Preconditions.checkArgumentPositive(builder.mMagnitude.length, 92 "Magnitude array must have non-zero length"); 93 Preconditions.checkArgument(builder.mFrequencyOffsetMetersPerSecond >= 0.0, 94 "FrequencyOffsetMetersPerSecond must be non-negative (greater than or equal to 0)"); 95 Preconditions.checkArgument(builder.mSamplingWidthMeters > 0.0, 96 "SamplingWidthMeters must be positive (greater than 0)"); 97 mMagnitude = builder.mMagnitude; 98 mFrequencyOffsetMetersPerSecond = builder.mFrequencyOffsetMetersPerSecond; 99 mSamplingWidthMeters = builder.mSamplingWidthMeters; 100 mSamplingStartMeters = builder.mSamplingStartMeters; 101 } 102 CorrelationVector(Parcel in)103 private CorrelationVector(Parcel in) { 104 mSamplingWidthMeters = in.readDouble(); 105 mSamplingStartMeters = in.readDouble(); 106 mFrequencyOffsetMetersPerSecond = in.readDouble(); 107 mMagnitude = new int[in.readInt()]; 108 in.readIntArray(mMagnitude); 109 } 110 111 /* 112 * Method definitions to support Parcelable operations. 113 */ 114 public static final @NonNull Parcelable.Creator<CorrelationVector> CREATOR = 115 new Parcelable.Creator<CorrelationVector>() { 116 @Override 117 public CorrelationVector createFromParcel(Parcel parcel) { 118 return new CorrelationVector(parcel); 119 } 120 121 @Override 122 public CorrelationVector[] newArray(int size) { 123 return new CorrelationVector[size]; 124 } 125 }; 126 127 @Override describeContents()128 public int describeContents() { 129 return 0; 130 } 131 132 @NonNull 133 @Override toString()134 public String toString() { 135 return "CorrelationVector{" 136 + "FrequencyOffsetMetersPerSecond=" + mFrequencyOffsetMetersPerSecond 137 + ", SamplingWidthMeters=" + mSamplingWidthMeters 138 + ", SamplingStartMeters=" + mSamplingStartMeters 139 + ", Magnitude=" + Arrays.toString(mMagnitude) 140 + '}'; 141 } 142 143 @Override writeToParcel(@onNull Parcel dest, int flags)144 public void writeToParcel(@NonNull Parcel dest, int flags) { 145 dest.writeDouble(mSamplingWidthMeters); 146 dest.writeDouble(mSamplingStartMeters); 147 dest.writeDouble(mFrequencyOffsetMetersPerSecond); 148 dest.writeInt(mMagnitude.length); 149 dest.writeIntArray(mMagnitude); 150 } 151 152 /** 153 * Returns true if this {@link CorrelationVector} is equivalent to the given object. 154 * Returns false otherwise. 155 */ 156 @Override equals(Object object)157 public boolean equals(Object object) { 158 if (object == this) { 159 return true; 160 } 161 if (!(object instanceof CorrelationVector)) { 162 return false; 163 } 164 CorrelationVector c = (CorrelationVector) object; 165 return Arrays.equals(mMagnitude, c.getMagnitude()) 166 && Double.compare(mSamplingWidthMeters, c.getSamplingWidthMeters()) == 0 167 && Double.compare(mSamplingStartMeters, c.getSamplingStartMeters()) == 0 168 && Double.compare(mFrequencyOffsetMetersPerSecond, 169 c.getFrequencyOffsetMetersPerSecond()) == 0; 170 } 171 172 @Override hashCode()173 public int hashCode() { 174 return Objects.hash(mSamplingWidthMeters, mSamplingStartMeters, 175 mFrequencyOffsetMetersPerSecond, Arrays.hashCode(mMagnitude)); 176 } 177 178 /** 179 * Builder class for CorrelationVector. 180 */ 181 public static final class Builder { 182 183 private double mSamplingWidthMeters; 184 private double mSamplingStartMeters; 185 private double mFrequencyOffsetMetersPerSecond; 186 @NonNull private int[] mMagnitude; 187 188 /** Sets the space between correlation samples in meters. */ 189 @NonNull setSamplingWidthMeters( @loatRangefrom = 0.0f, fromInclusive = false) double samplingWidthMeters)190 public Builder setSamplingWidthMeters( 191 @FloatRange(from = 0.0f, fromInclusive = false) double samplingWidthMeters) { 192 mSamplingWidthMeters = samplingWidthMeters; 193 return this; 194 } 195 196 /** Sets the offset of the first sampling bin in meters. */ 197 @NonNull setSamplingStartMeters(@loatRangefrom = 0.0f) double samplingStartMeters)198 public Builder setSamplingStartMeters(@FloatRange(from = 0.0f) double samplingStartMeters) { 199 mSamplingStartMeters = samplingStartMeters; 200 return this; 201 } 202 203 /** Sets the frequency offset from reported pseudorange rate for this CorrelationVector */ 204 @NonNull setFrequencyOffsetMetersPerSecond( @loatRangefrom = 0.0f) double frequencyOffsetMetersPerSecond)205 public Builder setFrequencyOffsetMetersPerSecond( 206 @FloatRange(from = 0.0f) double frequencyOffsetMetersPerSecond) { 207 mFrequencyOffsetMetersPerSecond = frequencyOffsetMetersPerSecond; 208 return this; 209 } 210 211 /** Sets the data array representing normalized correlation magnitude values. */ 212 @NonNull setMagnitude(@onNull int[] magnitude)213 public Builder setMagnitude(@NonNull int[] magnitude) { 214 mMagnitude = magnitude; 215 return this; 216 } 217 218 /** 219 * Build CorrelationVector object. 220 * 221 * @return instance of CorrelationVector 222 */ 223 @NonNull build()224 public CorrelationVector build() { 225 return new CorrelationVector(this); 226 } 227 } 228 } 229