| /* | |
| * Copyright (C) 2024 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| package android.location; | |
| import android.annotation.FlaggedApi; | |
| import android.annotation.FloatRange; | |
| import android.annotation.IntRange; | |
| import android.annotation.NonNull; | |
| import android.annotation.SystemApi; | |
| import android.location.GlonassSatelliteEphemeris.GlonassHealthStatus; | |
| import android.location.flags.Flags; | |
| import android.os.Parcel; | |
| import android.os.Parcelable; | |
| import com.android.internal.util.Preconditions; | |
| import java.util.ArrayList; | |
| import java.util.Collections; | |
| import java.util.List; | |
| /** | |
| * A class contains Glonass almanac data. | |
| * | |
| * <p>This is defined in Glonass ICD v5.1 section 4.5. | |
| * | |
| * @hide | |
| */ | |
| @FlaggedApi(Flags.FLAG_GNSS_ASSISTANCE_INTERFACE) | |
| @SystemApi | |
| public final class GlonassAlmanac implements Parcelable { | |
| /** Almanac issue date in milliseconds (UTC) */ | |
| private final long mIssueDateMillis; | |
| /** List of GlonassSatelliteAlmanacs. */ | |
| @NonNull private final List<GlonassSatelliteAlmanac> mSatelliteAlmanacs; | |
| /** | |
| * Constructor for GlonassAlmanac. | |
| * | |
| * @param issueDateMillis The almanac issue date in milliseconds (UTC). | |
| * @param satelliteAlmanacs The list of GlonassSatelliteAlmanac. | |
| */ | |
| public GlonassAlmanac( | |
| @IntRange(from = 0) long issueDateMillis, | |
| @NonNull List<GlonassSatelliteAlmanac> satelliteAlmanacs) { | |
| Preconditions.checkArgument(issueDateMillis >= 0); | |
| Preconditions.checkNotNull(satelliteAlmanacs, "satelliteAlmanacs cannot be null"); | |
| mIssueDateMillis = issueDateMillis; | |
| mSatelliteAlmanacs = Collections.unmodifiableList(new ArrayList<>(satelliteAlmanacs)); | |
| } | |
| /** Returns the almanac issue date in milliseconds (UTC). */ | |
| @IntRange(from = 0) | |
| public long getIssueDateMillis() { | |
| return mIssueDateMillis; | |
| } | |
| /** Returns the list of GlonassSatelliteAlmanacs. */ | |
| @NonNull | |
| public List<GlonassSatelliteAlmanac> getSatelliteAlmanacs() { | |
| return mSatelliteAlmanacs; | |
| } | |
| @Override | |
| public int describeContents() { | |
| return 0; | |
| } | |
| @Override | |
| public void writeToParcel(@NonNull Parcel dest, int flags) { | |
| dest.writeLong(mIssueDateMillis); | |
| dest.writeTypedList(mSatelliteAlmanacs); | |
| } | |
| public static final @NonNull Parcelable.Creator<GlonassAlmanac> CREATOR = | |
| new Parcelable.Creator<GlonassAlmanac>() { | |
| @Override | |
| public GlonassAlmanac createFromParcel(@NonNull Parcel in) { | |
| long issueDateMillis = in.readLong(); | |
| List<GlonassSatelliteAlmanac> satelliteAlmanacs = new ArrayList<>(); | |
| in.readTypedList(satelliteAlmanacs, GlonassSatelliteAlmanac.CREATOR); | |
| return new GlonassAlmanac(issueDateMillis, satelliteAlmanacs); | |
| } | |
| @Override | |
| public GlonassAlmanac[] newArray(int size) { | |
| return new GlonassAlmanac[size]; | |
| } | |
| }; | |
| @Override | |
| @NonNull | |
| public String toString() { | |
| StringBuilder builder = new StringBuilder("GlonassAlmanac["); | |
| builder.append("issueDateMillis = ").append(mIssueDateMillis); | |
| builder.append(", satelliteAlmanacs = ").append(mSatelliteAlmanacs); | |
| builder.append("]"); | |
| return builder.toString(); | |
| } | |
| /** | |
| * A class contains Glonass satellite almanac data. | |
| * | |
| * <p>This is defined in Glonass ICD v5.1 section 4.5. | |
| */ | |
| public static final class GlonassSatelliteAlmanac implements Parcelable { | |
| /** Slot number. */ | |
| private final int mSlotNumber; | |
| /** Satellite health status. */ | |
| private final @GlonassHealthStatus int mHealthState; | |
| /** Frequency channel number. */ | |
| private final int mFrequencyChannelNumber; | |
| /** Calendar day number within the four-year period beginning since the leap year. */ | |
| private final int mCalendarDayNumber; | |
| /** Flag to indicates if the satellite is a GLONASS-M satellite. */ | |
| private final boolean mGlonassM; | |
| /** Coarse value of satellite time correction to GLONASS time in seconds. */ | |
| private final double mTau; | |
| /** Time of first ascending node passage of satellite in seconds. */ | |
| private final double mTLambda; | |
| /** Longitude of the first ascending node in semi-circles. */ | |
| private final double mLambda; | |
| /** Correction to the mean value of inclination in semi-circles. */ | |
| private final double mDeltaI; | |
| /** Correction to the mean value of the draconian period in seconds per orbital period */ | |
| private final double mDeltaT; | |
| /** Rate of change of draconian period in seconds per orbital period squared. */ | |
| private final double mDeltaTDot; | |
| /** Eccentricity. */ | |
| private final double mEccentricity; | |
| /** Argument of perigee in semi-circles. */ | |
| private final double mOmega; | |
| private GlonassSatelliteAlmanac(Builder builder) { | |
| // Allow slotNumber beyond the range to support potential future extensibility. | |
| Preconditions.checkArgument(builder.mSlotNumber >= 1); | |
| // Allow healthState beyond the range to support potential future extensibility. | |
| Preconditions.checkArgument(builder.mHealthState >= 0); | |
| Preconditions.checkArgumentInRange( | |
| builder.mFrequencyChannelNumber, -7, 6, "FrequencyChannelNumber"); | |
| Preconditions.checkArgumentInRange( | |
| builder.mCalendarDayNumber, 1, 1461, "CalendarDayNumber"); | |
| Preconditions.checkArgumentInRange(builder.mTau, -1.9e-3f, 1.9e-3f, "Tau"); | |
| Preconditions.checkArgumentInRange(builder.mTLambda, 0.0f, 44100.0f, "TLambda"); | |
| Preconditions.checkArgumentInRange(builder.mLambda, -1.0f, 1.0f, "Lambda"); | |
| Preconditions.checkArgumentInRange(builder.mDeltaI, -0.067f, 0.067f, "DeltaI"); | |
| Preconditions.checkArgumentInRange(builder.mDeltaT, -3600.0f, 3600.0f, "DeltaT"); | |
| Preconditions.checkArgumentInRange(builder.mDeltaTDot, -0.004f, 0.004f, "DeltaTDot"); | |
| Preconditions.checkArgumentInRange(builder.mEccentricity, 0.0f, 0.03f, "Eccentricity"); | |
| Preconditions.checkArgumentInRange(builder.mOmega, -1.0f, 1.0f, "Omega"); | |
| mSlotNumber = builder.mSlotNumber; | |
| mHealthState = builder.mHealthState; | |
| mFrequencyChannelNumber = builder.mFrequencyChannelNumber; | |
| mCalendarDayNumber = builder.mCalendarDayNumber; | |
| mGlonassM = builder.mGlonassM; | |
| mTau = builder.mTau; | |
| mTLambda = builder.mTLambda; | |
| mLambda = builder.mLambda; | |
| mDeltaI = builder.mDeltaI; | |
| mDeltaT = builder.mDeltaT; | |
| mDeltaTDot = builder.mDeltaTDot; | |
| mEccentricity = builder.mEccentricity; | |
| mOmega = builder.mOmega; | |
| } | |
| /** Returns the slot number. */ | |
| @IntRange(from = 1, to = 25) | |
| public int getSlotNumber() { | |
| return mSlotNumber; | |
| } | |
| /** Returns the satellite health status. */ | |
| public @GlonassHealthStatus int getHealthState() { | |
| return mHealthState; | |
| } | |
| /** Returns the frequency channel number. */ | |
| @IntRange(from = -7, to = 6) | |
| public int getFrequencyChannelNumber() { | |
| return mFrequencyChannelNumber; | |
| } | |
| /** | |
| * Returns the calendar day number within the four-year period beginning since the leap | |
| * year. | |
| */ | |
| @IntRange(from = 1, to = 1461) | |
| public int getCalendarDayNumber() { | |
| return mCalendarDayNumber; | |
| } | |
| /** Returns true if the satellite is a GLONASS-M satellite, false otherwise. */ | |
| public boolean isGlonassM() { | |
| return mGlonassM; | |
| } | |
| /** Returns the coarse value of satellite time correction to GLONASS time in seconds. */ | |
| @FloatRange(from = -1.9e-3f, to = 1.9e-3f) | |
| public double getTau() { | |
| return mTau; | |
| } | |
| /** Returns the time of first ascending node passage of satellite in seconds. */ | |
| @FloatRange(from = 0.0f, to = 44100.0f) | |
| public double getTLambda() { | |
| return mTLambda; | |
| } | |
| /** Returns the longitude of the first ascending node in semi-circles. */ | |
| @FloatRange(from = -1.0f, to = 1.0f) | |
| public double getLambda() { | |
| return mLambda; | |
| } | |
| /** Returns the correction to the mean value of inclination in semi-circles. */ | |
| @FloatRange(from = -0.067f, to = 0.067f) | |
| public double getDeltaI() { | |
| return mDeltaI; | |
| } | |
| /** | |
| * Returns the correction to the mean value of the draconian period in seconds per orbital | |
| * period | |
| */ | |
| @FloatRange(from = -3600.0f, to = 3600.0f) | |
| public double getDeltaT() { | |
| return mDeltaT; | |
| } | |
| /** Returns the rate of change of draconian period in seconds per orbital period squared. */ | |
| @FloatRange(from = -0.004f, to = 0.004f) | |
| public double getDeltaTDot() { | |
| return mDeltaTDot; | |
| } | |
| /** Returns the eccentricity. */ | |
| @FloatRange(from = 0.0f, to = 0.03f) | |
| public double getEccentricity() { | |
| return mEccentricity; | |
| } | |
| /** Returns the Argument of perigee in semi-circles. */ | |
| @FloatRange(from = -1.0f, to = 1.0f) | |
| public double getOmega() { | |
| return mOmega; | |
| } | |
| @Override | |
| public int describeContents() { | |
| return 0; | |
| } | |
| @Override | |
| public void writeToParcel(@NonNull Parcel dest, int flags) { | |
| dest.writeInt(mSlotNumber); | |
| dest.writeInt(mHealthState); | |
| dest.writeInt(mFrequencyChannelNumber); | |
| dest.writeInt(mCalendarDayNumber); | |
| dest.writeBoolean(mGlonassM); | |
| dest.writeDouble(mTau); | |
| dest.writeDouble(mTLambda); | |
| dest.writeDouble(mLambda); | |
| dest.writeDouble(mDeltaI); | |
| dest.writeDouble(mDeltaT); | |
| dest.writeDouble(mDeltaTDot); | |
| dest.writeDouble(mEccentricity); | |
| dest.writeDouble(mOmega); | |
| } | |
| public static final @NonNull Parcelable.Creator<GlonassSatelliteAlmanac> CREATOR = | |
| new Parcelable.Creator<GlonassSatelliteAlmanac>() { | |
| @Override | |
| public GlonassSatelliteAlmanac createFromParcel(@NonNull Parcel source) { | |
| return new GlonassSatelliteAlmanac.Builder() | |
| .setSlotNumber(source.readInt()) | |
| .setHealthState(source.readInt()) | |
| .setFrequencyChannelNumber(source.readInt()) | |
| .setCalendarDayNumber(source.readInt()) | |
| .setGlonassM(source.readBoolean()) | |
| .setTau(source.readDouble()) | |
| .setTLambda(source.readDouble()) | |
| .setLambda(source.readDouble()) | |
| .setDeltaI(source.readDouble()) | |
| .setDeltaT(source.readDouble()) | |
| .setDeltaTDot(source.readDouble()) | |
| .setEccentricity(source.readDouble()) | |
| .setOmega(source.readDouble()) | |
| .build(); | |
| } | |
| @Override | |
| public GlonassSatelliteAlmanac[] newArray(int size) { | |
| return new GlonassSatelliteAlmanac[size]; | |
| } | |
| }; | |
| @Override | |
| @NonNull | |
| public String toString() { | |
| StringBuilder builder = new StringBuilder("GlonassSatelliteAlmanac["); | |
| builder.append("slotNumber = ").append(mSlotNumber); | |
| builder.append(", healthState = ").append(mHealthState); | |
| builder.append(", frequencyChannelNumber = ").append(mFrequencyChannelNumber); | |
| builder.append(", calendarDayNumber = ").append(mCalendarDayNumber); | |
| builder.append(", glonassM = ").append(mGlonassM); | |
| builder.append(", tau = ").append(mTau); | |
| builder.append(", tLambda = ").append(mTLambda); | |
| builder.append(", lambda = ").append(mLambda); | |
| builder.append(", deltaI = ").append(mDeltaI); | |
| builder.append(", deltaT = ").append(mDeltaT); | |
| builder.append(", deltaTDot = ").append(mDeltaTDot); | |
| builder.append(", eccentricity = ").append(mEccentricity); | |
| builder.append(", omega = ").append(mOmega); | |
| builder.append("]"); | |
| return builder.toString(); | |
| } | |
| /** Builder for {@link GlonassSatelliteAlmanac}. */ | |
| public static final class Builder { | |
| private int mSlotNumber; | |
| private int mHealthState; | |
| private int mFrequencyChannelNumber; | |
| private int mCalendarDayNumber; | |
| private boolean mGlonassM; | |
| private double mTau; | |
| private double mTLambda; | |
| private double mLambda; | |
| private double mDeltaI; | |
| private double mDeltaT; | |
| private double mDeltaTDot; | |
| private double mEccentricity; | |
| private double mOmega; | |
| /** Sets the slot number. */ | |
| @NonNull | |
| public Builder setSlotNumber(@IntRange(from = 1, to = 25) int slotNumber) { | |
| mSlotNumber = slotNumber; | |
| return this; | |
| } | |
| /** Sets the satellite health status. */ | |
| @NonNull | |
| public Builder setHealthState(@GlonassHealthStatus int healthState) { | |
| mHealthState = healthState; | |
| return this; | |
| } | |
| /** Sets the frequency channel number. */ | |
| @NonNull | |
| public Builder setFrequencyChannelNumber( | |
| @IntRange(from = -7, to = 6) int frequencyChannelNumber) { | |
| mFrequencyChannelNumber = frequencyChannelNumber; | |
| return this; | |
| } | |
| /** | |
| * Sets the calendar day number within the four-year period beginning since the leap | |
| * year. | |
| */ | |
| @NonNull | |
| public Builder setCalendarDayNumber( | |
| @IntRange(from = 1, to = 1461) int calendarDayNumber) { | |
| mCalendarDayNumber = calendarDayNumber; | |
| return this; | |
| } | |
| /** Sets to true if the satellite is a GLONASS-M satellite, false otherwise. */ | |
| @NonNull | |
| public Builder setGlonassM(boolean isGlonassM) { | |
| this.mGlonassM = isGlonassM; | |
| return this; | |
| } | |
| /** Sets the coarse value of satellite time correction to GLONASS time in seconds. */ | |
| @NonNull | |
| public Builder setTau(@FloatRange(from = -1.9e-3f, to = 1.9e-3f) double tau) { | |
| mTau = tau; | |
| return this; | |
| } | |
| /** Sets the time of first ascending node passage of satellite in seconds. */ | |
| @NonNull | |
| public Builder setTLambda(@FloatRange(from = 0.0f, to = 44100.0f) double tLambda) { | |
| mTLambda = tLambda; | |
| return this; | |
| } | |
| /** Sets the longitude of the first ascending node in semi-circles. */ | |
| @NonNull | |
| public Builder setLambda(@FloatRange(from = -1.0f, to = 1.0f) double lambda) { | |
| mLambda = lambda; | |
| return this; | |
| } | |
| /** Sets the correction to the mean value of inclination in semi-circles. */ | |
| @NonNull | |
| public Builder setDeltaI(@FloatRange(from = -0.067f, to = 0.067f) double deltaI) { | |
| mDeltaI = deltaI; | |
| return this; | |
| } | |
| /** | |
| * Sets the correction to the mean value of the draconian period in seconds per orbital | |
| * period. | |
| */ | |
| @NonNull | |
| public Builder setDeltaT(@FloatRange(from = -3600.0f, to = 3600.0f) double deltaT) { | |
| mDeltaT = deltaT; | |
| return this; | |
| } | |
| /** | |
| * Sets the rate of change of draconian period in seconds per orbital period squared. | |
| */ | |
| @NonNull | |
| public Builder setDeltaTDot(@FloatRange(from = -0.004f, to = 0.004f) double deltaTDot) { | |
| mDeltaTDot = deltaTDot; | |
| return this; | |
| } | |
| /** Sets the eccentricity. */ | |
| @NonNull | |
| public Builder setEccentricity( | |
| @FloatRange(from = 0.0f, to = 0.03f) double eccentricity) { | |
| mEccentricity = eccentricity; | |
| return this; | |
| } | |
| /** Sets the Argument of perigee in semi-circles. */ | |
| @NonNull | |
| public Builder setOmega(@FloatRange(from = -1.0f, to = 1.0f) double omega) { | |
| mOmega = omega; | |
| return this; | |
| } | |
| /** Builds a {@link GlonassSatelliteAlmanac}. */ | |
| @NonNull | |
| public GlonassSatelliteAlmanac build() { | |
| return new GlonassSatelliteAlmanac(this); | |
| } | |
| } | |
| } | |
| } |