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