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 import java.util.ArrayList;
30 import java.util.Collections;
31 import java.util.List;
32 
33 /**
34  * A class representing a GNSS measurement corrections for all used GNSS satellites at the location
35  * and time specified
36  *
37  * @hide
38  */
39 @SystemApi
40 public final class GnssMeasurementCorrections implements Parcelable {
41 
42     /** Represents latitude in degrees at which the corrections are computed. */
43     @FloatRange(from = -90.0f, to = 90.0f)
44     private final double mLatitudeDegrees;
45     /** Represents longitude in degrees at which the corrections are computed. */
46     @FloatRange(from = -180.0f, to = 180.0f)
47     private final double mLongitudeDegrees;
48     /**
49      * Represents altitude in meters above the WGS 84 reference ellipsoid at which the corrections
50      * are computed.
51      */
52     @FloatRange(from = -1000.0, to = 10000.0f)
53     private final double mAltitudeMeters;
54     /**
55      * Represents the horizontal uncertainty (68% confidence) in meters on the device position at
56      * which the corrections are provided.
57      *
58      * <p> This value is useful for example to judge how accurate the provided corrections are.
59      */
60     @FloatRange(from = 0.0f)
61     private final double mHorizontalPositionUncertaintyMeters;
62     /**
63      * Represents the vertical uncertainty (68% confidence) in meters on the device position at
64      * which the corrections are provided.
65      *
66      * <p> This value is useful for example to judge how accurate the provided corrections are.
67      */
68     @FloatRange(from = 0.0f)
69     private final double mVerticalPositionUncertaintyMeters;
70 
71     /** Time Of Applicability, GPS time of week in nanoseconds. */
72     @IntRange(from = 0)
73     private final long mToaGpsNanosecondsOfWeek;
74 
75     /**
76      * A set of {@link GnssSingleSatCorrection} each containing measurement corrections for a
77      * satellite in view.
78      */
79     @NonNull
80     private final List<GnssSingleSatCorrection> mSingleSatCorrectionList;
81 
82     /**
83      * Indicates whether the environment bearing is available.
84      */
85     private final boolean mHasEnvironmentBearing;
86 
87     /**
88      * Environment bearing in degrees clockwise from true north, in the direction of user motion.
89      * Environment bearing is provided when it is known with high probability that velocity is
90      * aligned with an environment feature (such as edge of a building, or road).
91      */
92     @FloatRange(from = 0.0f, to = 360.0f)
93     private final float mEnvironmentBearingDegrees;
94 
95     /**
96      * Environment bearing uncertainty in degrees.
97      */
98     @FloatRange(from = 0.0f, to = 180.0f)
99     private final float mEnvironmentBearingUncertaintyDegrees;
100 
GnssMeasurementCorrections(Builder builder)101     private GnssMeasurementCorrections(Builder builder) {
102         mLatitudeDegrees = builder.mLatitudeDegrees;
103         mLongitudeDegrees = builder.mLongitudeDegrees;
104         mAltitudeMeters = builder.mAltitudeMeters;
105         mHorizontalPositionUncertaintyMeters = builder.mHorizontalPositionUncertaintyMeters;
106         mVerticalPositionUncertaintyMeters = builder.mVerticalPositionUncertaintyMeters;
107         mToaGpsNanosecondsOfWeek = builder.mToaGpsNanosecondsOfWeek;
108         final List<GnssSingleSatCorrection> singleSatCorrList =  builder.mSingleSatCorrectionList;
109         Preconditions.checkArgument(singleSatCorrList != null && !singleSatCorrList.isEmpty());
110         mSingleSatCorrectionList = Collections.unmodifiableList(new ArrayList<>(singleSatCorrList));
111         mHasEnvironmentBearing = builder.mEnvironmentBearingIsSet
112                 && builder.mEnvironmentBearingUncertaintyIsSet;
113         mEnvironmentBearingDegrees = builder.mEnvironmentBearingDegrees;
114         mEnvironmentBearingUncertaintyDegrees = builder.mEnvironmentBearingUncertaintyDegrees;
115     }
116 
117     /** Gets the latitude in degrees at which the corrections are computed. */
118     @FloatRange(from = -90.0f, to = 90.0f)
getLatitudeDegrees()119     public double getLatitudeDegrees() {
120         return mLatitudeDegrees;
121     }
122 
123     /** Gets the longitude in degrees at which the corrections are computed. */
124     @FloatRange(from = -180.0f, to = 180.0f)
getLongitudeDegrees()125     public double getLongitudeDegrees() {
126         return mLongitudeDegrees;
127     }
128 
129     /**
130      * Gets the altitude in meters above the WGS 84 reference ellipsoid at which the corrections are
131      * computed.
132      */
133     @FloatRange(from = -1000.0f, to = 10000.0f)
getAltitudeMeters()134     public double getAltitudeMeters() {
135         return mAltitudeMeters;
136     }
137 
138     /**
139      * Gets the horizontal uncertainty (68% confidence) in meters on the device position at
140      * which the corrections are provided.
141      */
142     @FloatRange(from = 0.0f)
getHorizontalPositionUncertaintyMeters()143     public double getHorizontalPositionUncertaintyMeters() {
144         return mHorizontalPositionUncertaintyMeters;
145     }
146 
147     /**
148      * Gets the vertical uncertainty (68% confidence) in meters on the device position at
149      * which the corrections are provided.
150      */
151     @FloatRange(from = 0.0f)
getVerticalPositionUncertaintyMeters()152     public double getVerticalPositionUncertaintyMeters() {
153         return mVerticalPositionUncertaintyMeters;
154     }
155 
156     /** Gets the time of applicability, GPS time of week in nanoseconds. */
157     @IntRange(from = 0)
getToaGpsNanosecondsOfWeek()158     public long getToaGpsNanosecondsOfWeek() {
159         return mToaGpsNanosecondsOfWeek;
160     }
161 
162     /**
163      * Gets a set of {@link GnssSingleSatCorrection} each containing measurement corrections for a
164      * satellite in view
165      */
166     @NonNull
getSingleSatelliteCorrectionList()167     public List<GnssSingleSatCorrection> getSingleSatelliteCorrectionList() {
168         return mSingleSatCorrectionList;
169     }
170 
171     /**
172      * If true, environment bearing will be available.
173      */
hasEnvironmentBearing()174     public boolean hasEnvironmentBearing() {
175         return mHasEnvironmentBearing;
176     }
177 
178     /**
179      * Gets the environment bearing in degrees clockwise from true north, in the direction of user
180      * motion. Environment bearing is provided when it is known with high probability that
181      * velocity is aligned with an environment feature (such as edge of a building, or road).
182      *
183      * {@link #hasEnvironmentBearing} should be called to check the environment bearing is available
184      * before calling this method. The value is undefined if {@link #hasEnvironmentBearing} returns
185      * false.
186      */
187     @FloatRange(from = 0.0f, to = 360.0f)
getEnvironmentBearingDegrees()188     public float getEnvironmentBearingDegrees() {
189         return mEnvironmentBearingDegrees;
190     }
191 
192     /**
193      * Gets the environment bearing uncertainty in degrees. It represents the standard deviation of
194      * the physical structure in the circle of position uncertainty. The uncertainty can take values
195      * between 0 and 180 degrees. The {@link #hasEnvironmentBearing} becomes false as the
196      * uncertainty value passes a predefined threshold depending on the physical structure around
197      * the user.
198      *
199      * {@link #hasEnvironmentBearing} should be called to check the environment bearing is available
200      * before calling this method. The value is undefined if {@link #hasEnvironmentBearing} returns
201      * false.
202      */
203     @FloatRange(from = 0.0f, to = 180.0f)
getEnvironmentBearingUncertaintyDegrees()204     public float getEnvironmentBearingUncertaintyDegrees() {
205         return mEnvironmentBearingUncertaintyDegrees;
206     }
207 
208     @Override
describeContents()209     public int describeContents() {
210         return 0;
211     }
212 
213     public static final Creator<GnssMeasurementCorrections> CREATOR =
214             new Creator<GnssMeasurementCorrections>() {
215                 @Override
216                 @NonNull
217                 public GnssMeasurementCorrections createFromParcel(@NonNull Parcel parcel) {
218                     final GnssMeasurementCorrections.Builder gnssMeasurementCorrectons =
219                             new Builder()
220                                     .setLatitudeDegrees(parcel.readDouble())
221                                     .setLongitudeDegrees(parcel.readDouble())
222                                     .setAltitudeMeters(parcel.readDouble())
223                                     .setHorizontalPositionUncertaintyMeters(parcel.readDouble())
224                                     .setVerticalPositionUncertaintyMeters(parcel.readDouble())
225                                     .setToaGpsNanosecondsOfWeek(parcel.readLong());
226                     List<GnssSingleSatCorrection> singleSatCorrectionList = new ArrayList<>();
227                     parcel.readTypedList(singleSatCorrectionList, GnssSingleSatCorrection.CREATOR);
228                     gnssMeasurementCorrectons.setSingleSatelliteCorrectionList(
229                             singleSatCorrectionList);
230                     boolean hasEnvironmentBearing = parcel.readBoolean();
231                     if (hasEnvironmentBearing) {
232                         gnssMeasurementCorrectons.setEnvironmentBearingDegrees(parcel.readFloat());
233                         gnssMeasurementCorrectons.setEnvironmentBearingUncertaintyDegrees(
234                                 parcel.readFloat());
235                     }
236                     return gnssMeasurementCorrectons.build();
237                 }
238 
239                 @Override
240                 public GnssMeasurementCorrections[] newArray(int i) {
241                     return new GnssMeasurementCorrections[i];
242                 }
243             };
244 
245     @NonNull
246     @Override
toString()247     public String toString() {
248         final String format = "   %-29s = %s\n";
249         StringBuilder builder = new StringBuilder("GnssMeasurementCorrections:\n");
250         builder.append(String.format(format, "LatitudeDegrees = ", mLatitudeDegrees));
251         builder.append(String.format(format, "LongitudeDegrees = ", mLongitudeDegrees));
252         builder.append(String.format(format, "AltitudeMeters = ", mAltitudeMeters));
253         builder.append(String.format(format, "HorizontalPositionUncertaintyMeters = ",
254                 mHorizontalPositionUncertaintyMeters));
255         builder.append(String.format(format, "VerticalPositionUncertaintyMeters = ",
256                 mVerticalPositionUncertaintyMeters));
257         builder.append(
258                 String.format(format, "ToaGpsNanosecondsOfWeek = ", mToaGpsNanosecondsOfWeek));
259         builder.append(
260                 String.format(format, "mSingleSatCorrectionList = ", mSingleSatCorrectionList));
261         builder.append(
262                 String.format(format, "HasEnvironmentBearing = ", mHasEnvironmentBearing));
263         builder.append(
264                 String.format(format, "EnvironmentBearingDegrees = ",
265                         mEnvironmentBearingDegrees));
266         builder.append(
267                 String.format(format, "EnvironmentBearingUncertaintyDegrees = ",
268                 mEnvironmentBearingUncertaintyDegrees));
269         return builder.toString();
270     }
271 
272     @Override
writeToParcel(@onNull Parcel parcel, int flags)273     public void writeToParcel(@NonNull Parcel parcel, int flags) {
274         parcel.writeDouble(mLatitudeDegrees);
275         parcel.writeDouble(mLongitudeDegrees);
276         parcel.writeDouble(mAltitudeMeters);
277         parcel.writeDouble(mHorizontalPositionUncertaintyMeters);
278         parcel.writeDouble(mVerticalPositionUncertaintyMeters);
279         parcel.writeLong(mToaGpsNanosecondsOfWeek);
280         parcel.writeTypedList(mSingleSatCorrectionList);
281         parcel.writeBoolean(mHasEnvironmentBearing);
282         if (mHasEnvironmentBearing) {
283             parcel.writeFloat(mEnvironmentBearingDegrees);
284             parcel.writeFloat(mEnvironmentBearingUncertaintyDegrees);
285         }
286     }
287 
288     /** Builder for {@link GnssMeasurementCorrections} */
289     public static final class Builder {
290         /**
291          * For documentation of below fields, see corresponding fields in {@link
292          * GnssMeasurementCorrections}.
293          */
294         private double mLatitudeDegrees;
295         private double mLongitudeDegrees;
296         private double mAltitudeMeters;
297         private double mHorizontalPositionUncertaintyMeters;
298         private double mVerticalPositionUncertaintyMeters;
299         private long mToaGpsNanosecondsOfWeek;
300         @Nullable private List<GnssSingleSatCorrection> mSingleSatCorrectionList;
301         private float mEnvironmentBearingDegrees;
302         private boolean mEnvironmentBearingIsSet = false;
303         private float mEnvironmentBearingUncertaintyDegrees;
304         private boolean mEnvironmentBearingUncertaintyIsSet = false;
305 
306         /** Sets the latitude in degrees at which the corrections are computed. */
setLatitudeDegrees( @loatRangefrom = -90.0f, to = 90.0f) double latitudeDegrees)307         @NonNull public Builder setLatitudeDegrees(
308                 @FloatRange(from = -90.0f, to = 90.0f) double latitudeDegrees) {
309             mLatitudeDegrees = latitudeDegrees;
310             return this;
311         }
312 
313         /** Sets the longitude in degrees at which the corrections are computed. */
setLongitudeDegrees( @loatRangefrom = -180.0f, to = 180.0f) double longitudeDegrees)314         @NonNull public Builder setLongitudeDegrees(
315                 @FloatRange(from = -180.0f, to = 180.0f) double longitudeDegrees) {
316             mLongitudeDegrees = longitudeDegrees;
317             return this;
318         }
319 
320         /**
321          * Sets the altitude in meters above the WGS 84 reference ellipsoid at which the corrections
322          * are computed.
323          */
setAltitudeMeters( @loatRangefrom = -1000.0f, to = 10000.0f) double altitudeMeters)324         @NonNull public Builder setAltitudeMeters(
325                 @FloatRange(from = -1000.0f, to = 10000.0f) double altitudeMeters) {
326             mAltitudeMeters = altitudeMeters;
327             return this;
328         }
329 
330 
331         /**
332          * Sets the horizontal uncertainty (68% confidence) in meters on the device position at
333          * which the corrections are provided.
334          */
setHorizontalPositionUncertaintyMeters( @loatRangefrom = 0.0f) double horizontalPositionUncertaintyMeters)335         @NonNull public Builder setHorizontalPositionUncertaintyMeters(
336                 @FloatRange(from = 0.0f) double horizontalPositionUncertaintyMeters) {
337             mHorizontalPositionUncertaintyMeters = horizontalPositionUncertaintyMeters;
338             return this;
339         }
340 
341         /**
342          * Sets the vertical uncertainty (68% confidence) in meters on the device position at which
343          * the corrections are provided.
344          */
setVerticalPositionUncertaintyMeters( @loatRangefrom = 0.0f) double verticalPositionUncertaintyMeters)345         @NonNull public Builder setVerticalPositionUncertaintyMeters(
346                 @FloatRange(from = 0.0f) double verticalPositionUncertaintyMeters) {
347             mVerticalPositionUncertaintyMeters = verticalPositionUncertaintyMeters;
348             return this;
349         }
350 
351         /** Sets the time of applicability, GPS time of week in nanoseconds. */
setToaGpsNanosecondsOfWeek( @ntRangefrom = 0) long toaGpsNanosecondsOfWeek)352         @NonNull public Builder setToaGpsNanosecondsOfWeek(
353                 @IntRange(from = 0) long toaGpsNanosecondsOfWeek) {
354             mToaGpsNanosecondsOfWeek = toaGpsNanosecondsOfWeek;
355             return this;
356         }
357 
358         /**
359          * Sets a the list of {@link GnssSingleSatCorrection} containing measurement corrections for
360          * a satellite in view
361          */
setSingleSatelliteCorrectionList( @onNull List<GnssSingleSatCorrection> singleSatCorrectionList)362         @NonNull public Builder setSingleSatelliteCorrectionList(
363                 @NonNull List<GnssSingleSatCorrection> singleSatCorrectionList) {
364             mSingleSatCorrectionList = singleSatCorrectionList;
365             return this;
366         }
367 
368         /**
369          * Sets the environment bearing in degrees clockwise from true north, in the direction of
370          * user motion. Environment bearing is provided when it is known with high probability
371          * that velocity is aligned with an environment feature (such as edge of a building, or
372          * road).
373          *
374          * Both the bearing and uncertainty must be set for the environment bearing to be valid.
375          */
setEnvironmentBearingDegrees( @loatRangefrom = 0.0f, to = 360.0f) float environmentBearingDegrees)376         @NonNull public Builder setEnvironmentBearingDegrees(
377                 @FloatRange(from = 0.0f, to = 360.0f)
378                         float environmentBearingDegrees) {
379             mEnvironmentBearingDegrees = environmentBearingDegrees;
380             mEnvironmentBearingIsSet = true;
381             return this;
382         }
383 
384         /**
385          * Sets the environment bearing uncertainty in degrees.
386          *
387          * Both the bearing and uncertainty must be set for the environment bearing to be valid.
388          */
setEnvironmentBearingUncertaintyDegrees( @loatRangefrom = 0.0f, to = 180.0f) float environmentBearingUncertaintyDegrees)389         @NonNull public Builder setEnvironmentBearingUncertaintyDegrees(
390                 @FloatRange(from = 0.0f, to = 180.0f)
391                         float environmentBearingUncertaintyDegrees) {
392             mEnvironmentBearingUncertaintyDegrees = environmentBearingUncertaintyDegrees;
393             mEnvironmentBearingUncertaintyIsSet = true;
394             return this;
395         }
396 
397         /** Builds a {@link GnssMeasurementCorrections} instance as specified by this builder. */
build()398         @NonNull public GnssMeasurementCorrections build() {
399             if (mEnvironmentBearingIsSet ^ mEnvironmentBearingUncertaintyIsSet) {
400                 throw new IllegalStateException("Both environment bearing and environment bearing "
401                         + "uncertainty must be set.");
402             }
403             return new GnssMeasurementCorrections(this);
404         }
405     }
406 }
407