1 /*
2  * Copyright (C) 2018 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.IntRange;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.SystemApi;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 
27 import com.android.internal.util.Preconditions;
28 
29 /**
30  * A container with measurement corrections for a single visible satellite
31  *
32  * @hide
33  */
34 @SystemApi
35 public final class GnssSingleSatCorrection implements Parcelable {
36 
37     /**
38      * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
39      * #mProbSatIsLos}.
40      *
41      * @hide
42      */
43     public static final int HAS_PROB_SAT_IS_LOS_MASK = 1 << 0;
44 
45     /**
46      * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
47      * #mExcessPathLengthMeters}.
48      *
49      * @hide
50      */
51     public static final int HAS_EXCESS_PATH_LENGTH_MASK = 1 << 1;
52 
53     /**
54      * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
55      * #mExcessPathLengthUncertaintyMeters}.
56      *
57      * @hide
58      */
59     public static final int HAS_EXCESS_PATH_LENGTH_UNC_MASK = 1 << 2;
60 
61     /**
62      * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
63      * #mReflectingPlane}.
64      *
65      * @hide
66      */
67     public static final int HAS_REFLECTING_PLANE_MASK = 1 << 3;
68 
69     /** A bitmask of fields present in this object (see HAS_* constants defined above) */
70     private final int mSingleSatCorrectionFlags;
71 
72     /** Defines the constellation of the given satellite as defined in {@link GnssStatus}. */
73     @GnssStatus.ConstellationType
74     private final int mConstellationType;
75 
76     /**
77      * Satellite vehicle ID number
78      *
79      * <p>Interpretation depends on {@link GnssStatus#getSvid(int)}.
80      */
81     @IntRange(from = 0)
82     private final int mSatId;
83 
84     /**
85      * Carrier frequency of the signal to be corrected, for example it can be the GPS center
86      * frequency for L1 = 1,575,420,000 Hz, varying GLO channels, etc.
87      *
88      * <p>For an L1, L5 receiver tracking a satellite on L1 and L5 at the same time, two correction
89      * objects will be reported for this same satellite, in one of the correction objects, all the
90      * values related to L1 will be filled, and in the other all of the values related to L5 will be
91      * filled.
92      */
93     @FloatRange(from = 0.0f,  fromInclusive = false)
94     private final float mCarrierFrequencyHz;
95 
96     /**
97      * The probability that the satellite is estimated to be in Line-of-Sight condition at the given
98      * location.
99      */
100     @FloatRange(from = 0.0f, to = 1.0f)
101     private final float mProbSatIsLos;
102 
103     /**
104      * Excess path length to be subtracted from pseudorange before using it in calculating location.
105      */
106     @FloatRange(from = 0.0f)
107     private final float mExcessPathLengthMeters;
108 
109     /** Error estimate (1-sigma) for the Excess path length estimate */
110     @FloatRange(from = 0.0f)
111     private final float mExcessPathLengthUncertaintyMeters;
112 
113     /**
114      * Defines the reflecting plane location and azimuth information
115      *
116      * <p>The flag HAS_REFLECTING_PLANE will be used to set this value to invalid if the satellite
117      * signal goes through multiple reflections or if reflection plane serving is not supported.
118      */
119     @Nullable
120     private final GnssReflectingPlane mReflectingPlane;
121 
GnssSingleSatCorrection(Builder builder)122     private GnssSingleSatCorrection(Builder builder) {
123         mSingleSatCorrectionFlags = builder.mSingleSatCorrectionFlags;
124         mSatId = builder.mSatId;
125         mConstellationType = builder.mConstellationType;
126         mCarrierFrequencyHz = builder.mCarrierFrequencyHz;
127         mProbSatIsLos = builder.mProbSatIsLos;
128         mExcessPathLengthMeters = builder.mExcessPathLengthMeters;
129         mExcessPathLengthUncertaintyMeters = builder.mExcessPathLengthUncertaintyMeters;
130         mReflectingPlane = builder.mReflectingPlane;
131     }
132 
133     /**
134      * Gets a bitmask of fields present in this object
135      *
136      * @hide
137      */
getSingleSatelliteCorrectionFlags()138     public int getSingleSatelliteCorrectionFlags() {
139         return mSingleSatCorrectionFlags;
140     }
141 
142     /**
143      * Gets the constellation type.
144      *
145      * <p>The return value is one of those constants with {@code CONSTELLATION_} prefix in {@link
146      * GnssStatus}.
147      */
148     @GnssStatus.ConstellationType
getConstellationType()149     public int getConstellationType() {
150         return mConstellationType;
151     }
152 
153     /**
154      * Gets the satellite ID.
155      *
156      * <p>Interpretation depends on {@link #getConstellationType()}. See {@link
157      * GnssStatus#getSvid(int)}.
158      */
159     @IntRange(from = 0)
getSatelliteId()160     public int getSatelliteId() {
161         return mSatId;
162     }
163 
164     /**
165      * Gets the carrier frequency of the tracked signal.
166      *
167      * <p>For example it can be the GPS central frequency for L1 = 1575.45 MHz, or L2 = 1227.60 MHz,
168      * L5 = 1176.45 MHz, varying GLO channels, etc.
169      *
170      * <p>For an L1, L5 receiver tracking a satellite on L1 and L5 at the same time, two correction
171      * objects will be reported for this same satellite, in one of the correction objects, all the
172      * values related to L1 will be filled, and in the other all of the values related to L5 will be
173      * filled.
174      *
175      * @return the carrier frequency of the signal tracked in Hz.
176      */
177     @FloatRange(from = 0.0f,  fromInclusive = false)
getCarrierFrequencyHz()178     public float getCarrierFrequencyHz() {
179         return mCarrierFrequencyHz;
180     }
181 
182     /**
183      * Returns the probability that the satellite is in line-of-sight condition at the given
184      * location.
185      */
186     @FloatRange(from = 0.0f, to = 1.0f)
getProbabilityLineOfSight()187     public float getProbabilityLineOfSight() {
188         return mProbSatIsLos;
189     }
190 
191     /**
192      * Returns the Excess path length to be subtracted from pseudorange before using it in
193      * calculating location.
194      */
195     @FloatRange(from = 0.0f)
getExcessPathLengthMeters()196     public float getExcessPathLengthMeters() {
197         return mExcessPathLengthMeters;
198     }
199 
200     /** Returns the error estimate (1-sigma) for the Excess path length estimate */
201     @FloatRange(from = 0.0f)
getExcessPathLengthUncertaintyMeters()202     public float getExcessPathLengthUncertaintyMeters() {
203         return mExcessPathLengthUncertaintyMeters;
204     }
205 
206     /**
207      * Returns the reflecting plane characteristics at which the signal has bounced
208      *
209      * <p>The flag HAS_REFLECTING_PLANE will be used to set this value to invalid if the satellite
210      * signal goes through multiple reflections or if reflection plane serving is not supported
211      */
212     @Nullable
getReflectingPlane()213     public GnssReflectingPlane getReflectingPlane() {
214         return mReflectingPlane;
215     }
216 
217     /** Returns {@code true} if {@link #getProbabilityLineOfSight()} is valid. */
hasValidSatelliteLineOfSight()218     public boolean hasValidSatelliteLineOfSight() {
219         return (mSingleSatCorrectionFlags & HAS_PROB_SAT_IS_LOS_MASK) != 0;
220     }
221 
222     /** Returns {@code true} if {@link #getExcessPathLengthMeters()} is valid. */
hasExcessPathLength()223     public boolean hasExcessPathLength() {
224         return (mSingleSatCorrectionFlags & HAS_EXCESS_PATH_LENGTH_MASK) != 0;
225     }
226 
227     /** Returns {@code true} if {@link #getExcessPathLengthUncertaintyMeters()} is valid. */
hasExcessPathLengthUncertainty()228     public boolean hasExcessPathLengthUncertainty() {
229         return (mSingleSatCorrectionFlags & HAS_EXCESS_PATH_LENGTH_UNC_MASK) != 0;
230     }
231 
232     /** Returns {@code true} if {@link #getReflectingPlane()} is valid. */
hasReflectingPlane()233     public boolean hasReflectingPlane() {
234         return (mSingleSatCorrectionFlags & HAS_REFLECTING_PLANE_MASK) != 0;
235     }
236 
237     @Override
describeContents()238     public int describeContents() {
239         return 0;
240     }
241 
242     public static final Creator<GnssSingleSatCorrection> CREATOR =
243             new Creator<GnssSingleSatCorrection>() {
244                 @Override
245                 @NonNull
246                 public GnssSingleSatCorrection createFromParcel(@NonNull Parcel parcel) {
247                     int mSingleSatCorrectionFlags = parcel.readInt();
248                     boolean hasReflectingPlane =
249                             (mSingleSatCorrectionFlags & HAS_REFLECTING_PLANE_MASK) != 0;
250                     final GnssSingleSatCorrection.Builder singleSatCorrectionBuilder =
251                             new Builder()
252                                     .setConstellationType(parcel.readInt())
253                                     .setSatelliteId(parcel.readInt())
254                                     .setCarrierFrequencyHz(parcel.readFloat())
255                                     .setProbabilityLineOfSight(parcel.readFloat())
256                                     .setExcessPathLengthMeters(parcel.readFloat())
257                                     .setExcessPathLengthUncertaintyMeters(parcel.readFloat());
258                     if (hasReflectingPlane) {
259                         singleSatCorrectionBuilder.setReflectingPlane(
260                                 GnssReflectingPlane.CREATOR.createFromParcel(parcel));
261                     }
262                     return singleSatCorrectionBuilder.build();
263                 }
264 
265                 @Override
266                 public GnssSingleSatCorrection[] newArray(int i) {
267                     return new GnssSingleSatCorrection[i];
268                 }
269             };
270 
271     @NonNull
272     @Override
toString()273     public String toString() {
274         final String format = "   %-29s = %s\n";
275         StringBuilder builder = new StringBuilder("GnssSingleSatCorrection:\n");
276         builder.append(
277                 String.format(format, "SingleSatCorrectionFlags = ", mSingleSatCorrectionFlags));
278         builder.append(String.format(format, "ConstellationType = ", mConstellationType));
279         builder.append(String.format(format, "SatId = ", mSatId));
280         builder.append(String.format(format, "CarrierFrequencyHz = ", mCarrierFrequencyHz));
281         builder.append(String.format(format, "ProbSatIsLos = ", mProbSatIsLos));
282         builder.append(String.format(format, "ExcessPathLengthMeters = ", mExcessPathLengthMeters));
283         builder.append(
284                 String.format(
285                         format,
286                         "ExcessPathLengthUncertaintyMeters = ",
287                         mExcessPathLengthUncertaintyMeters));
288         if (hasReflectingPlane()) {
289             builder.append(String.format(format, "ReflectingPlane = ", mReflectingPlane));
290         }
291         return builder.toString();
292     }
293 
294     @Override
writeToParcel(@onNull Parcel parcel, int flags)295     public void writeToParcel(@NonNull Parcel parcel, int flags) {
296         parcel.writeInt(mSingleSatCorrectionFlags);
297         parcel.writeInt(mConstellationType);
298         parcel.writeInt(mSatId);
299         parcel.writeFloat(mCarrierFrequencyHz);
300         parcel.writeFloat(mProbSatIsLos);
301         parcel.writeFloat(mExcessPathLengthMeters);
302         parcel.writeFloat(mExcessPathLengthUncertaintyMeters);
303         if (hasReflectingPlane()) {
304             mReflectingPlane.writeToParcel(parcel, flags);
305         }
306     }
307 
308     /** Builder for {@link GnssSingleSatCorrection} */
309     public static final class Builder {
310 
311         /**
312          * For documentation of below fields, see corresponding fields in {@link
313          * GnssSingleSatCorrection}.
314          */
315         private int mSingleSatCorrectionFlags;
316 
317         private int mConstellationType;
318         private int mSatId;
319         private float mCarrierFrequencyHz;
320         private float mProbSatIsLos;
321         private float mExcessPathLengthMeters;
322         private float mExcessPathLengthUncertaintyMeters;
323         @Nullable
324         private GnssReflectingPlane mReflectingPlane;
325 
326         /** Sets the constellation type. */
setConstellationType( @nssStatus.ConstellationType int constellationType)327         @NonNull public Builder setConstellationType(
328                 @GnssStatus.ConstellationType int constellationType) {
329             mConstellationType = constellationType;
330             return this;
331         }
332 
333         /** Sets the Satellite ID defined in the ICD of the given constellation. */
setSatelliteId(@ntRangefrom = 0) int satId)334         @NonNull public Builder setSatelliteId(@IntRange(from = 0) int satId) {
335             mSatId = satId;
336             return this;
337         }
338 
339         /** Sets the Carrier frequency in Hz. */
setCarrierFrequencyHz( @loatRangefrom = 0.0f, fromInclusive = false) float carrierFrequencyHz)340         @NonNull public Builder setCarrierFrequencyHz(
341                 @FloatRange(from = 0.0f,  fromInclusive = false) float carrierFrequencyHz) {
342             mCarrierFrequencyHz = carrierFrequencyHz;
343             return this;
344         }
345 
346         /**
347          * Sets the line-of-sight probability of the satellite at the given location in the range
348          * between 0 and 1.
349          */
setProbabilityLineOfSight( @loatRangefrom = 0.0f, to = 1.0f) float probSatIsLos)350         @NonNull public Builder setProbabilityLineOfSight(
351                 @FloatRange(from = 0.0f, to = 1.0f) float probSatIsLos) {
352             Preconditions.checkArgumentInRange(
353                     probSatIsLos, 0, 1, "probSatIsLos should be between 0 and 1.");
354             mProbSatIsLos = probSatIsLos;
355             mSingleSatCorrectionFlags =
356                     (byte) (mSingleSatCorrectionFlags | HAS_PROB_SAT_IS_LOS_MASK);
357             return this;
358         }
359 
360         /**
361          * Sets the Excess path length to be subtracted from pseudorange before using it in
362          * calculating location.
363          */
setExcessPathLengthMeters( @loatRangefrom = 0.0f) float excessPathLengthMeters)364         @NonNull public Builder setExcessPathLengthMeters(
365                 @FloatRange(from = 0.0f) float excessPathLengthMeters) {
366             mExcessPathLengthMeters = excessPathLengthMeters;
367             mSingleSatCorrectionFlags =
368                     (byte) (mSingleSatCorrectionFlags | HAS_EXCESS_PATH_LENGTH_MASK);
369             return this;
370         }
371 
372         /** Sets the error estimate (1-sigma) for the Excess path length estimate */
setExcessPathLengthUncertaintyMeters( @loatRangefrom = 0.0f) float excessPathLengthUncertaintyMeters)373         @NonNull public Builder setExcessPathLengthUncertaintyMeters(
374                 @FloatRange(from = 0.0f) float excessPathLengthUncertaintyMeters) {
375             mExcessPathLengthUncertaintyMeters = excessPathLengthUncertaintyMeters;
376             mSingleSatCorrectionFlags =
377                     (byte) (mSingleSatCorrectionFlags | HAS_EXCESS_PATH_LENGTH_UNC_MASK);
378             return this;
379         }
380 
381         /** Sets the reflecting plane information */
setReflectingPlane(@ullable GnssReflectingPlane reflectingPlane)382         @NonNull public Builder setReflectingPlane(@Nullable GnssReflectingPlane reflectingPlane) {
383             mReflectingPlane = reflectingPlane;
384             if (reflectingPlane != null) {
385                 mSingleSatCorrectionFlags =
386                         (byte) (mSingleSatCorrectionFlags | HAS_REFLECTING_PLANE_MASK);
387             } else {
388                 mSingleSatCorrectionFlags =
389                         (byte) (mSingleSatCorrectionFlags & ~HAS_REFLECTING_PLANE_MASK);
390             }
391             return this;
392         }
393 
394         /** Builds a {@link GnssSingleSatCorrection} instance as specified by this builder. */
build()395         @NonNull public GnssSingleSatCorrection build() {
396             return new GnssSingleSatCorrection(this);
397         }
398     }
399 }
400