1 /* 2 * Copyright (C) 2024 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.FlaggedApi; 20 import android.annotation.FloatRange; 21 import android.annotation.IntRange; 22 import android.annotation.NonNull; 23 import android.annotation.SystemApi; 24 import android.location.GlonassSatelliteEphemeris.GlonassHealthStatus; 25 import android.location.flags.Flags; 26 import android.os.Parcel; 27 import android.os.Parcelable; 28 29 import com.android.internal.util.Preconditions; 30 31 import java.util.ArrayList; 32 import java.util.Collections; 33 import java.util.List; 34 35 /** 36 * A class contains Glonass almanac data. 37 * 38 * <p>This is defined in Glonass ICD v5.1 section 4.5. 39 * 40 * @hide 41 */ 42 @FlaggedApi(Flags.FLAG_GNSS_ASSISTANCE_INTERFACE) 43 @SystemApi 44 public final class GlonassAlmanac implements Parcelable { 45 46 /** Almanac issue date in milliseconds (UTC) */ 47 private final long mIssueDateMillis; 48 49 /** List of GlonassSatelliteAlmanacs. */ 50 @NonNull private final List<GlonassSatelliteAlmanac> mSatelliteAlmanacs; 51 52 /** 53 * Constructor for GlonassAlmanac. 54 * 55 * @param issueDateMillis The almanac issue date in milliseconds (UTC). 56 * @param satelliteAlmanacs The list of GlonassSatelliteAlmanac. 57 */ GlonassAlmanac( @ntRangefrom = 0) long issueDateMillis, @NonNull List<GlonassSatelliteAlmanac> satelliteAlmanacs)58 public GlonassAlmanac( 59 @IntRange(from = 0) long issueDateMillis, 60 @NonNull List<GlonassSatelliteAlmanac> satelliteAlmanacs) { 61 Preconditions.checkArgument(issueDateMillis >= 0); 62 Preconditions.checkNotNull(satelliteAlmanacs, "satelliteAlmanacs cannot be null"); 63 mIssueDateMillis = issueDateMillis; 64 mSatelliteAlmanacs = Collections.unmodifiableList(new ArrayList<>(satelliteAlmanacs)); 65 } 66 67 /** Returns the almanac issue date in milliseconds (UTC). */ 68 @IntRange(from = 0) getIssueDateMillis()69 public long getIssueDateMillis() { 70 return mIssueDateMillis; 71 } 72 73 /** Returns the list of GlonassSatelliteAlmanacs. */ 74 @NonNull getSatelliteAlmanacs()75 public List<GlonassSatelliteAlmanac> getSatelliteAlmanacs() { 76 return mSatelliteAlmanacs; 77 } 78 79 @Override describeContents()80 public int describeContents() { 81 return 0; 82 } 83 84 @Override writeToParcel(@onNull Parcel dest, int flags)85 public void writeToParcel(@NonNull Parcel dest, int flags) { 86 dest.writeLong(mIssueDateMillis); 87 dest.writeTypedList(mSatelliteAlmanacs); 88 } 89 90 public static final @NonNull Parcelable.Creator<GlonassAlmanac> CREATOR = 91 new Parcelable.Creator<GlonassAlmanac>() { 92 @Override 93 public GlonassAlmanac createFromParcel(@NonNull Parcel in) { 94 long issueDateMillis = in.readLong(); 95 List<GlonassSatelliteAlmanac> satelliteAlmanacs = new ArrayList<>(); 96 in.readTypedList(satelliteAlmanacs, GlonassSatelliteAlmanac.CREATOR); 97 return new GlonassAlmanac(issueDateMillis, satelliteAlmanacs); 98 } 99 100 @Override 101 public GlonassAlmanac[] newArray(int size) { 102 return new GlonassAlmanac[size]; 103 } 104 }; 105 106 @Override 107 @NonNull toString()108 public String toString() { 109 StringBuilder builder = new StringBuilder("GlonassAlmanac["); 110 builder.append("issueDateMillis = ").append(mIssueDateMillis); 111 builder.append(", satelliteAlmanacs = ").append(mSatelliteAlmanacs); 112 builder.append("]"); 113 return builder.toString(); 114 } 115 116 /** 117 * A class contains Glonass satellite almanac data. 118 * 119 * <p>This is defined in Glonass ICD v5.1 section 4.5. 120 */ 121 public static final class GlonassSatelliteAlmanac implements Parcelable { 122 /** Slot number. */ 123 private final int mSlotNumber; 124 125 /** Satellite health status. */ 126 private final @GlonassHealthStatus int mHealthState; 127 128 /** Frequency channel number. */ 129 private final int mFrequencyChannelNumber; 130 131 /** Calendar day number within the four-year period beginning since the leap year. */ 132 private final int mCalendarDayNumber; 133 134 /** Flag to indicates if the satellite is a GLONASS-M satellitee. */ 135 private final boolean mGlonassM; 136 137 /** Coarse value of satellite time correction to GLONASS time in seconds. */ 138 private final double mTau; 139 140 /** Time of first ascending node passage of satellite in seconds. */ 141 private final double mTLambda; 142 143 /** Longitude of the first ascending node in semi-circles. */ 144 private final double mLambda; 145 146 /** Correction to the mean value of inclination in semi-circles. */ 147 private final double mDeltaI; 148 149 /** Correction to the mean value of the draconian period in seconds per orbital period */ 150 private final double mDeltaT; 151 152 /** Rate of change of draconian period in seconds per orbital period squared. */ 153 private final double mDeltaTDot; 154 155 /** Eccentricity. */ 156 private final double mEccentricity; 157 158 /** Argument of perigee in semi-circles. */ 159 private final double mOmega; 160 GlonassSatelliteAlmanac(Builder builder)161 private GlonassSatelliteAlmanac(Builder builder) { 162 // Allow slotNumber beyond the range to support potential future extensibility. 163 Preconditions.checkArgument(builder.mSlotNumber >= 1); 164 // Allow healthState beyond the range to support potential future extensibility. 165 Preconditions.checkArgument(builder.mHealthState >= 0); 166 Preconditions.checkArgumentInRange( 167 builder.mFrequencyChannelNumber, 0, 31, "FrequencyChannelNumber"); 168 Preconditions.checkArgumentInRange( 169 builder.mCalendarDayNumber, 1, 1461, "CalendarDayNumber"); 170 Preconditions.checkArgumentInRange(builder.mTau, -1.9e-3f, 1.9e-3f, "Tau"); 171 Preconditions.checkArgumentInRange(builder.mTLambda, 0.0f, 44100.0f, "TLambda"); 172 Preconditions.checkArgumentInRange(builder.mLambda, -1.0f, 1.0f, "Lambda"); 173 Preconditions.checkArgumentInRange(builder.mDeltaI, -0.067f, 0.067f, "DeltaI"); 174 Preconditions.checkArgumentInRange(builder.mDeltaT, -3600.0f, 3600.0f, "DeltaT"); 175 Preconditions.checkArgumentInRange(builder.mDeltaTDot, -0.004f, 0.004f, "DeltaTDot"); 176 Preconditions.checkArgumentInRange(builder.mEccentricity, 0.0f, 0.03f, "Eccentricity"); 177 Preconditions.checkArgumentInRange(builder.mOmega, -1.0f, 1.0f, "Omega"); 178 mSlotNumber = builder.mSlotNumber; 179 mHealthState = builder.mHealthState; 180 mFrequencyChannelNumber = builder.mFrequencyChannelNumber; 181 mCalendarDayNumber = builder.mCalendarDayNumber; 182 mGlonassM = builder.mGlonassM; 183 mTau = builder.mTau; 184 mTLambda = builder.mTLambda; 185 mLambda = builder.mLambda; 186 mDeltaI = builder.mDeltaI; 187 mDeltaT = builder.mDeltaT; 188 mDeltaTDot = builder.mDeltaTDot; 189 mEccentricity = builder.mEccentricity; 190 mOmega = builder.mOmega; 191 } 192 193 /** Returns the slot number. */ 194 @IntRange(from = 1, to = 25) getSlotNumber()195 public int getSlotNumber() { 196 return mSlotNumber; 197 } 198 199 /** Returns the satellite health status. */ getHealthState()200 public @GlonassHealthStatus int getHealthState() { 201 return mHealthState; 202 } 203 204 /** Returns the frequency channel number. */ 205 @IntRange(from = 0, to = 31) getFrequencyChannelNumber()206 public int getFrequencyChannelNumber() { 207 return mFrequencyChannelNumber; 208 } 209 210 /** 211 * Returns the calendar day number within the four-year period beginning since the leap 212 * year. 213 */ 214 @IntRange(from = 1, to = 1461) getCalendarDayNumber()215 public int getCalendarDayNumber() { 216 return mCalendarDayNumber; 217 } 218 219 /** Returns true if the satellite is a GLONASS-M satellitee, false otherwise. */ isGlonassM()220 public boolean isGlonassM() { 221 return mGlonassM; 222 } 223 224 /** Returns the coarse value of satellite time correction to GLONASS time in seconds. */ 225 @FloatRange(from = -1.9e-3f, to = 1.9e-3f) getTau()226 public double getTau() { 227 return mTau; 228 } 229 230 /** Returns the time of first ascending node passage of satellite in seconds. */ 231 @FloatRange(from = 0.0f, to = 44100.0f) getTLambda()232 public double getTLambda() { 233 return mTLambda; 234 } 235 236 /** Returns the longitude of the first ascending node in semi-circles. */ 237 @FloatRange(from = -1.0f, to = 1.0f) getLambda()238 public double getLambda() { 239 return mLambda; 240 } 241 242 /** Returns the correction to the mean value of inclination in semi-circles. */ 243 @FloatRange(from = -0.067f, to = 0.067f) getDeltaI()244 public double getDeltaI() { 245 return mDeltaI; 246 } 247 248 /** 249 * Returns the correction to the mean value of the draconian period in seconds per orbital 250 * period 251 */ 252 @FloatRange(from = -3600.0f, to = 3600.0f) getDeltaT()253 public double getDeltaT() { 254 return mDeltaT; 255 } 256 257 /** Returns the rate of change of draconian period in seconds per orbital period squared. */ 258 @FloatRange(from = -0.004f, to = 0.004f) getDeltaTDot()259 public double getDeltaTDot() { 260 return mDeltaTDot; 261 } 262 263 /** Returns the eccentricity. */ 264 @FloatRange(from = 0.0f, to = 0.03f) getEccentricity()265 public double getEccentricity() { 266 return mEccentricity; 267 } 268 269 /** Returns the Argument of perigee in semi-circles. */ 270 @FloatRange(from = -1.0f, to = 1.0f) getOmega()271 public double getOmega() { 272 return mOmega; 273 } 274 275 @Override describeContents()276 public int describeContents() { 277 return 0; 278 } 279 280 @Override writeToParcel(@onNull Parcel dest, int flags)281 public void writeToParcel(@NonNull Parcel dest, int flags) { 282 dest.writeInt(mSlotNumber); 283 dest.writeInt(mHealthState); 284 dest.writeInt(mFrequencyChannelNumber); 285 dest.writeInt(mCalendarDayNumber); 286 dest.writeBoolean(mGlonassM); 287 dest.writeDouble(mTau); 288 dest.writeDouble(mTLambda); 289 dest.writeDouble(mLambda); 290 dest.writeDouble(mDeltaI); 291 dest.writeDouble(mDeltaT); 292 dest.writeDouble(mDeltaTDot); 293 dest.writeDouble(mEccentricity); 294 dest.writeDouble(mOmega); 295 } 296 297 public static final @NonNull Parcelable.Creator<GlonassSatelliteAlmanac> CREATOR = 298 new Parcelable.Creator<GlonassSatelliteAlmanac>() { 299 @Override 300 public GlonassSatelliteAlmanac createFromParcel(@NonNull Parcel source) { 301 return new GlonassSatelliteAlmanac.Builder() 302 .setSlotNumber(source.readInt()) 303 .setHealthState(source.readInt()) 304 .setFrequencyChannelNumber(source.readInt()) 305 .setCalendarDayNumber(source.readInt()) 306 .setGlonassM(source.readBoolean()) 307 .setTau(source.readDouble()) 308 .setTLambda(source.readDouble()) 309 .setLambda(source.readDouble()) 310 .setDeltaI(source.readDouble()) 311 .setDeltaT(source.readDouble()) 312 .setDeltaTDot(source.readDouble()) 313 .setEccentricity(source.readDouble()) 314 .setOmega(source.readDouble()) 315 .build(); 316 } 317 318 @Override 319 public GlonassSatelliteAlmanac[] newArray(int size) { 320 return new GlonassSatelliteAlmanac[size]; 321 } 322 }; 323 324 @Override 325 @NonNull toString()326 public String toString() { 327 StringBuilder builder = new StringBuilder("GlonassSatelliteAlmanac["); 328 builder.append("slotNumber = ").append(mSlotNumber); 329 builder.append(", healthState = ").append(mHealthState); 330 builder.append(", frequencyChannelNumber = ").append(mFrequencyChannelNumber); 331 builder.append(", calendarDayNumber = ").append(mCalendarDayNumber); 332 builder.append(", glonassM = ").append(mGlonassM); 333 builder.append(", tau = ").append(mTau); 334 builder.append(", tLambda = ").append(mTLambda); 335 builder.append(", lambda = ").append(mLambda); 336 builder.append(", deltaI = ").append(mDeltaI); 337 builder.append(", deltaT = ").append(mDeltaT); 338 builder.append(", deltaTDot = ").append(mDeltaTDot); 339 builder.append(", eccentricity = ").append(mEccentricity); 340 builder.append(", omega = ").append(mOmega); 341 builder.append("]"); 342 return builder.toString(); 343 } 344 345 /** Builder for {@link GlonassSatelliteAlmanac}. */ 346 public static final class Builder { 347 private int mSlotNumber; 348 private int mHealthState; 349 private int mFrequencyChannelNumber; 350 private int mCalendarDayNumber; 351 private boolean mGlonassM; 352 private double mTau; 353 private double mTLambda; 354 private double mLambda; 355 private double mDeltaI; 356 private double mDeltaT; 357 private double mDeltaTDot; 358 private double mEccentricity; 359 private double mOmega; 360 361 /** Sets the slot number. */ 362 @NonNull setSlotNumber(@ntRangefrom = 1, to = 25) int slotNumber)363 public Builder setSlotNumber(@IntRange(from = 1, to = 25) int slotNumber) { 364 mSlotNumber = slotNumber; 365 return this; 366 } 367 368 /** Sets the satellite health status. */ 369 @NonNull setHealthState(@lonassHealthStatus int healthState)370 public Builder setHealthState(@GlonassHealthStatus int healthState) { 371 mHealthState = healthState; 372 return this; 373 } 374 375 /** Sets the frequency channel number. */ 376 @NonNull setFrequencyChannelNumber( @ntRangefrom = 0, to = 31) int frequencyChannelNumber)377 public Builder setFrequencyChannelNumber( 378 @IntRange(from = 0, to = 31) int frequencyChannelNumber) { 379 mFrequencyChannelNumber = frequencyChannelNumber; 380 return this; 381 } 382 383 /** 384 * Sets the calendar day number within the four-year period beginning since the leap 385 * year. 386 */ 387 @NonNull setCalendarDayNumber( @ntRangefrom = 1, to = 1461) int calendarDayNumber)388 public Builder setCalendarDayNumber( 389 @IntRange(from = 1, to = 1461) int calendarDayNumber) { 390 mCalendarDayNumber = calendarDayNumber; 391 return this; 392 } 393 394 /** Sets to true if the satellite is a GLONASS-M satellitee, false otherwise. */ 395 @NonNull setGlonassM(boolean isGlonassM)396 public Builder setGlonassM(boolean isGlonassM) { 397 this.mGlonassM = isGlonassM; 398 return this; 399 } 400 401 /** Sets the coarse value of satellite time correction to GLONASS time in seconds. */ 402 @NonNull setTau(@loatRangefrom = -1.9e-3f, to = 1.9e-3f) double tau)403 public Builder setTau(@FloatRange(from = -1.9e-3f, to = 1.9e-3f) double tau) { 404 mTau = tau; 405 return this; 406 } 407 408 /** Sets the time of first ascending node passage of satellite in seconds. */ 409 @NonNull setTLambda(@loatRangefrom = 0.0f, to = 44100.0f) double tLambda)410 public Builder setTLambda(@FloatRange(from = 0.0f, to = 44100.0f) double tLambda) { 411 mTLambda = tLambda; 412 return this; 413 } 414 415 /** Sets the longitude of the first ascending node in semi-circles. */ 416 @NonNull setLambda(@loatRangefrom = -1.0f, to = 1.0f) double lambda)417 public Builder setLambda(@FloatRange(from = -1.0f, to = 1.0f) double lambda) { 418 mLambda = lambda; 419 return this; 420 } 421 422 /** Sets the correction to the mean value of inclination in semi-circles. */ 423 @NonNull setDeltaI(@loatRangefrom = -0.067f, to = 0.067f) double deltaI)424 public Builder setDeltaI(@FloatRange(from = -0.067f, to = 0.067f) double deltaI) { 425 mDeltaI = deltaI; 426 return this; 427 } 428 429 /** 430 * Sets the correction to the mean value of the draconian period in seconds per orbital 431 * period. 432 */ 433 @NonNull setDeltaT(@loatRangefrom = -3600.0f, to = 3600.0f) double deltaT)434 public Builder setDeltaT(@FloatRange(from = -3600.0f, to = 3600.0f) double deltaT) { 435 mDeltaT = deltaT; 436 return this; 437 } 438 439 /** 440 * Sets the rate of change of draconian period in seconds per orbital period squared. 441 */ 442 @NonNull setDeltaTDot(@loatRangefrom = -0.004f, to = 0.004f) double deltaTDot)443 public Builder setDeltaTDot(@FloatRange(from = -0.004f, to = 0.004f) double deltaTDot) { 444 mDeltaTDot = deltaTDot; 445 return this; 446 } 447 448 /** Sets the eccentricity. */ 449 @NonNull setEccentricity( @loatRangefrom = 0.0f, to = 0.03f) double eccentricity)450 public Builder setEccentricity( 451 @FloatRange(from = 0.0f, to = 0.03f) double eccentricity) { 452 mEccentricity = eccentricity; 453 return this; 454 } 455 456 /** Sets the Argument of perigee in semi-circles. */ 457 @NonNull setOmega(@loatRangefrom = -1.0f, to = 1.0f) double omega)458 public Builder setOmega(@FloatRange(from = -1.0f, to = 1.0f) double omega) { 459 mOmega = omega; 460 return this; 461 } 462 463 /** Builds a {@link GlonassSatelliteAlmanac}. */ 464 @NonNull build()465 public GlonassSatelliteAlmanac build() { 466 return new GlonassSatelliteAlmanac(this); 467 } 468 } 469 } 470 } 471