blob: c16ad91f130a0c46be12e6a162ecbeed11ce66bf [file] [log] [blame]
/*
* 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.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 almanac parameters for GPS, QZSS, Galileo, Beidou.
*
* <p>For Beidou, this is defined in BDS-SIS-ICD-B1I-3.0 section 5.2.4.15.
*
* <p>For GPS, this is defined in IS-GPS-200 section 20.3.3.5.1.2.
*
* <p>For QZSS, this is defined in IS-QZSS-PNT section 4.1.2.6.
*
* <p>For Galileo, this is defined in Galileo-OS-SIS-ICD-v2.1 section 5.1.10.
*
* @hide
*/
@FlaggedApi(Flags.FLAG_GNSS_ASSISTANCE_INTERFACE)
@SystemApi
public final class GnssAlmanac implements Parcelable {
/**
* Almanac issue date in milliseconds (UTC).
*
* <p>This is unused for GPS/QZSS/Baidou.
*/
private final long mIssueDateMillis;
/**
* Almanac issue of data.
*
* <p>This is unused for GPS/QZSS/Baidou.
*/
private final int mIoda;
/**
* Almanac reference week number.
*
* <p>For GPS and QZSS, this is GPS week number (modulo 1024).
*
* <p>For Beidou, this is Baidou week number (modulo 8192).
*
* <p>For Galileo, this is modulo 4 representation of the Galileo week number.
*/
private final int mWeekNumber;
/** Almanac reference time in seconds. */
private final int mToaSeconds;
/**
* Flag to indicate if the satelliteAlmanacs contains complete GNSS
* constellation indicated by svid.
*/
private final boolean mCompleteAlmanacProvided;
/** The list of GnssSatelliteAlmanacs. */
@NonNull private final List<GnssSatelliteAlmanac> mGnssSatelliteAlmanacs;
private GnssAlmanac(Builder builder) {
Preconditions.checkArgument(builder.mIssueDateMillis >= 0);
Preconditions.checkArgument(builder.mIoda >= 0);
Preconditions.checkArgument(builder.mWeekNumber >= 0);
Preconditions.checkArgumentInRange(builder.mToaSeconds, 0, 604800, "ToaSeconds");
Preconditions.checkNotNull(
builder.mGnssSatelliteAlmanacs, "GnssSatelliteAlmanacs cannot be null");
mIssueDateMillis = builder.mIssueDateMillis;
mIoda = builder.mIoda;
mWeekNumber = builder.mWeekNumber;
mToaSeconds = builder.mToaSeconds;
mCompleteAlmanacProvided = builder.mCompleteAlmanacProvided;
mGnssSatelliteAlmanacs =
Collections.unmodifiableList(new ArrayList<>(builder.mGnssSatelliteAlmanacs));
}
/** Returns the almanac issue date in milliseconds (UTC). */
@IntRange(from = 0)
public long getIssueDateMillis() {
return mIssueDateMillis;
}
/** Returns the almanac issue of data. */
@IntRange(from = 0)
public int getIoda() {
return mIoda;
}
/**
* Returns the almanac reference week number.
*
* <p>For GPS and QZSS, this is GPS week number (modulo 1024).
*
* <p>For Beidou, this is Baidou week number (modulo 8192).
*
* <p>For Galileo, this is modulo 4 representation of the Galileo week number.
*/
@IntRange(from = 0)
public int getWeekNumber() {
return mWeekNumber;
}
/** Returns the almanac reference time in seconds. */
@IntRange(from = 0, to = 604800)
public int getToaSeconds() {
return mToaSeconds;
}
/**
* Returns the flag to indicate if the satelliteAlmanacs contains complete GNSS
* constellation indicated by svid.
*/
public boolean isCompleteAlmanacProvided() {
return mCompleteAlmanacProvided;
}
/** Returns the list of GnssSatelliteAlmanacs. */
@NonNull
public List<GnssSatelliteAlmanac> getGnssSatelliteAlmanacs() {
return mGnssSatelliteAlmanacs;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeLong(mIssueDateMillis);
dest.writeInt(mIoda);
dest.writeInt(mWeekNumber);
dest.writeInt(mToaSeconds);
dest.writeBoolean(mCompleteAlmanacProvided);
dest.writeTypedList(mGnssSatelliteAlmanacs);
}
public static final @NonNull Creator<GnssAlmanac> CREATOR =
new Creator<GnssAlmanac>() {
@Override
public GnssAlmanac createFromParcel(Parcel in) {
GnssAlmanac.Builder gnssAlmanac = new GnssAlmanac.Builder();
gnssAlmanac.setIssueDateMillis(in.readLong());
gnssAlmanac.setIoda(in.readInt());
gnssAlmanac.setWeekNumber(in.readInt());
gnssAlmanac.setToaSeconds(in.readInt());
gnssAlmanac.setCompleteAlmanacProvided(in.readBoolean());
List<GnssSatelliteAlmanac> satelliteAlmanacs = new ArrayList<>();
in.readTypedList(satelliteAlmanacs, GnssSatelliteAlmanac.CREATOR);
gnssAlmanac.setGnssSatelliteAlmanacs(satelliteAlmanacs);
return gnssAlmanac.build();
}
@Override
public GnssAlmanac[] newArray(int size) {
return new GnssAlmanac[size];
}
};
@Override
public String toString() {
StringBuilder builder = new StringBuilder("GnssAlmanac[");
builder.append("issueDateMillis=").append(mIssueDateMillis);
builder.append(", ioda=").append(mIoda);
builder.append(", weekNumber=").append(mWeekNumber);
builder.append(", toaSeconds=").append(mToaSeconds);
builder.append(", completeAlmanacProvided=").append(mCompleteAlmanacProvided);
builder.append(", satelliteAlmanacs=").append(mGnssSatelliteAlmanacs);
builder.append("]");
return builder.toString();
}
/** Builder for {@link GnssAlmanac}. */
public static final class Builder {
private long mIssueDateMillis;
private int mIoda;
private int mWeekNumber;
private int mToaSeconds;
private boolean mCompleteAlmanacProvided;
private List<GnssSatelliteAlmanac> mGnssSatelliteAlmanacs;
/** Sets the almanac issue date in milliseconds (UTC). */
@NonNull
public Builder setIssueDateMillis(@IntRange(from = 0) long issueDateMillis) {
mIssueDateMillis = issueDateMillis;
return this;
}
/** Sets the almanac issue of data. */
@NonNull
public Builder setIoda(@IntRange(from = 0) int ioda) {
mIoda = ioda;
return this;
}
/**
* Sets the almanac reference week number.
*
* <p>For GPS and QZSS, this is GPS week number (modulo 1024).
*
* <p>For Beidou, this is Baidou week number (modulo 8192).
*
* <p>For Galileo, this is modulo 4 representation of the Galileo week number.
*/
@NonNull
public Builder setWeekNumber(@IntRange(from = 0) int weekNumber) {
mWeekNumber = weekNumber;
return this;
}
/** Sets the almanac reference time in seconds. */
@NonNull
public Builder setToaSeconds(@IntRange(from = 0, to = 604800) int toaSeconds) {
mToaSeconds = toaSeconds;
return this;
}
/**
* Sets to true if the satelliteAlmanacs contains complete GNSS
* constellation indicated by svid, false otherwise.
*/
@NonNull
public Builder setCompleteAlmanacProvided(boolean isCompleteAlmanacProvided) {
this.mCompleteAlmanacProvided = isCompleteAlmanacProvided;
return this;
}
/** Sets the list of GnssSatelliteAlmanacs. */
@NonNull
public Builder setGnssSatelliteAlmanacs(
@NonNull List<GnssSatelliteAlmanac> gnssSatelliteAlmanacs) {
mGnssSatelliteAlmanacs = gnssSatelliteAlmanacs;
return this;
}
/** Builds a {@link GnssAlmanac} instance as specified by this builder. */
@NonNull
public GnssAlmanac build() {
return new GnssAlmanac(this);
}
}
/**
* A class contains almanac parameters for GPS, QZSS, Galileo, Beidou.
*
* <p>For Beidou, this is defined in BDS-SIS-ICD-B1I-3.0 section 5.2.4.15.
*
* <p>For GPS, this is defined in IS-GPS-200 section 20.3.3.5.1.2.
*
* <p>For QZSS, this is defined in IS-QZSS-PNT section 4.1.2.6.
*
* <p>For Galileo, this is defined in Galileo-OS-SIS-ICD-v2.1 section 5.1.10.
*/
public static final class GnssSatelliteAlmanac implements Parcelable {
/** The PRN or satellite ID number for the GNSS satellite. */
private final int mSvid;
/**
* Satellite health information.
*
* <p>For GPS, this is satellite subframe 4 and 5, page 25 6-bit health code as defined in
* IS-GPS-200 Table 20-VIII expressed in integer form.
*
* <p>For QZSS, this is the 5-bit health code as defined in IS-QZSS-PNT, Table 4.1.2-5-2
* expressed in integer form.
*
* <p>For Beidou, this is 1-bit health information. (0=healthy, 1=unhealthy).
*
* <p>For Galileo, this is 6-bit health, bit 0 and 1 is for E5a, bit 2 and 3 is for E5b, bit
* 4 and 5 is for E1b.
*/
private final int mSvHealth;
/** Eccentricity. */
private final double mEccentricity;
/**
* Inclination in semi-circles.
*
* <p>For GPS and Galileo, this is the difference between the inclination angle at reference
* time and the nominal inclination in semi-circles.
*
* <p>For Beidou and QZSS, this is the inclination angle at reference time in semi-circles.
*/
private final double mInclination;
/** Argument of perigee in semi-circles. */
private final double mOmega;
/** Longitude of ascending node of orbital plane at weekly epoch in semi-circles. */
private final double mOmega0;
/** Rate of right ascension in semi-circles per second. */
private final double mOmegaDot;
/**
* Square root of semi-major axis in square root of meters.
*
* <p>For Galileo, this is the difference with respect to the square root of the nominal
* semi-major axis in square root of meters.
*/
private final double mRootA;
/** Mean anomaly at reference time in semi-circles. */
private final double mM0;
/** Satellite clock time bias correction coefficient in seconds. */
private final double mAf0;
/** Satellite clock time drift correction coefficient in seconds per second. */
private final double mAf1;
private GnssSatelliteAlmanac(Builder builder) {
Preconditions.checkArgument(builder.mSvid > 0);
Preconditions.checkArgument(builder.mSvHealth >= 0);
Preconditions.checkArgument(builder.mEccentricity >= 0.0f);
Preconditions.checkArgumentInRange(builder.mInclination, -1.0f, 1.0f, "Inclination");
Preconditions.checkArgumentInRange(builder.mOmega, -1.0f, 1.0f, "Omega");
Preconditions.checkArgumentInRange(builder.mOmega0, -1.0f, 1.0f, "Omega0");
Preconditions.checkArgumentInRange(builder.mOmegaDot, -1.0f, 1.0f, "OmegaDot");
Preconditions.checkArgumentInRange(builder.mRootA, 0.0f, 8192.0f, "RootA");
Preconditions.checkArgumentInRange(builder.mM0, -1.0f, 1.0f, "M0");
Preconditions.checkArgumentInRange(builder.mAf0, -0.0625f, 0.0625f, "Af0");
Preconditions.checkArgumentInRange(builder.mAf1, -1.5e-8f, 1.5e-8f, "Af1");
mSvid = builder.mSvid;
mSvHealth = builder.mSvHealth;
mEccentricity = builder.mEccentricity;
mInclination = builder.mInclination;
mOmega = builder.mOmega;
mOmega0 = builder.mOmega0;
mOmegaDot = builder.mOmegaDot;
mRootA = builder.mRootA;
mM0 = builder.mM0;
mAf0 = builder.mAf0;
mAf1 = builder.mAf1;
}
/** Returns the PRN or satellite ID number of the GNSS satellite. */
@IntRange(from = 1)
public int getSvid() {
return mSvid;
}
/**
* Returns the satellite health information.
*
* <p>For GPS, this is satellite subframe 4 and 5, page 25 6-bit health code as defined in
* IS-GPS-200 Table 20-VIII expressed in integer form.
*
* <p>For QZSS, this is the 5-bit health code as defined in IS-QZSS-PNT, Table 4.1.2-5-2
* expressed in integer form.
*
* <p>For Beidou, this is 1-bit health information. (0=healthy, 1=unhealthy).
*
* <p>For Galileo, this is 6-bit health, bit 0 and 1 is for E5a, bit 2 and 3 is for E5b,
* bit 4 and 5 is for E1b.
*/
@IntRange(from = 0)
public int getSvHealth() {
return mSvHealth;
}
/** Returns the eccentricity. */
@FloatRange(from = 0.0f)
public double getEccentricity() {
return mEccentricity;
}
/**
* Returns the inclination in semi-circles.
*
* <p>For GPS and Galileo, this is the difference between the inclination angle at reference
* time and the nominal inclination in semi-circles.
*
* <p>For Beidou and QZSS, this is the inclination angle at reference time in semi-circles.
*/
@FloatRange(from = -1.0f, to = 1.0f)
public double getInclination() {
return mInclination;
}
/** Returns the argument of perigee in semi-circles. */
@FloatRange(from = -1.0f, to = 1.0f)
public double getOmega() {
return mOmega;
}
/**
* Returns the longitude of ascending node of orbital plane at weekly epoch in semi-circles.
*/
@FloatRange(from = -1.0f, to = 1.0f)
public double getOmega0() {
return mOmega0;
}
/** Returns the rate of right ascension in semi-circles per second. */
@FloatRange(from = -1.0f, to = 1.0f)
public double getOmegaDot() {
return mOmegaDot;
}
/**
* Returns the square root of semi-major axis in square root of meters.
*
* <p>For Galileo, this is the difference with respect to the square root of the nominal
* semi-major axis in square root of meters.
*/
@FloatRange(from = 0.0f, to = 8192.0f)
public double getRootA() {
return mRootA;
}
/** Returns the mean anomaly at reference time in semi-circles. */
@FloatRange(from = -1.0f, to = 1.0f)
public double getM0() {
return mM0;
}
/** Returns the satellite clock time bias correction coefficient in seconds. */
@FloatRange(from = -0.0625f, to = 0.0625f)
public double getAf0() {
return mAf0;
}
/** Returns the satellite clock time drift correction coefficient in seconds per second. */
@FloatRange(from = -1.5e-8f, to = 1.5e-8f)
public double getAf1() {
return mAf1;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mSvid);
dest.writeInt(mSvHealth);
dest.writeDouble(mEccentricity);
dest.writeDouble(mInclination);
dest.writeDouble(mOmega);
dest.writeDouble(mOmega0);
dest.writeDouble(mOmegaDot);
dest.writeDouble(mRootA);
dest.writeDouble(mM0);
dest.writeDouble(mAf0);
dest.writeDouble(mAf1);
}
public static final @NonNull Creator<GnssSatelliteAlmanac> CREATOR =
new Creator<GnssSatelliteAlmanac>() {
@Override
public GnssSatelliteAlmanac createFromParcel(Parcel in) {
return new GnssSatelliteAlmanac(
new Builder()
.setSvid(in.readInt())
.setSvHealth(in.readInt())
.setEccentricity(in.readDouble())
.setInclination(in.readDouble())
.setOmega(in.readDouble())
.setOmega0(in.readDouble())
.setOmegaDot(in.readDouble())
.setRootA(in.readDouble())
.setM0(in.readDouble())
.setAf0(in.readDouble())
.setAf1(in.readDouble()));
}
@Override
public GnssSatelliteAlmanac[] newArray(int size) {
return new GnssSatelliteAlmanac[size];
}
};
@Override
@NonNull
public String toString() {
StringBuilder builder = new StringBuilder("GnssSatelliteAlmanac[");
builder.append("svid = ").append(mSvid);
builder.append(", svHealth = ").append(mSvHealth);
builder.append(", eccentricity = ").append(mEccentricity);
builder.append(", inclination = ").append(mInclination);
builder.append(", omega = ").append(mOmega);
builder.append(", omega0 = ").append(mOmega0);
builder.append(", omegaDot = ").append(mOmegaDot);
builder.append(", rootA = ").append(mRootA);
builder.append(", m0 = ").append(mM0);
builder.append(", af0 = ").append(mAf0);
builder.append(", af1 = ").append(mAf1);
builder.append("]");
return builder.toString();
}
/** Builder for {@link GnssSatelliteAlmanac}. */
public static final class Builder {
private int mSvid;
private int mSvHealth;
private double mEccentricity;
private double mInclination;
private double mOmega;
private double mOmega0;
private double mOmegaDot;
private double mRootA;
private double mM0;
private double mAf0;
private double mAf1;
/** Sets the PRN or satellite ID number of the GNSS satellite. */
@NonNull
public Builder setSvid(@IntRange(from = 1) int svid) {
mSvid = svid;
return this;
}
/**
* Sets the satellite health information.
*
* <p>For GPS, this is satellite subframe 4 and 5, page 25 6-bit health code as defined
* in IS-GPS-200 Table 20-VIII expressed in integer form.
*
* <p>For QZSS, this is the 5-bit health code as defined in IS-QZSS-PNT, Table 4.1.2-5-2
* expressed in integer form.
*
* <p>For Beidou, this is 1-bit health information. (0=healthy, 1=unhealthy).
*
* <p>For Galileo, this is 6-bit health, bit 0 and 1 is for E5a,
* bit 2 and 3 is for E5b, bit 4 and 5 is for E1b.
*/
@NonNull
public Builder setSvHealth(@IntRange(from = 0) int svHealth) {
mSvHealth = svHealth;
return this;
}
/** Sets the eccentricity. */
@NonNull
public Builder setEccentricity(@FloatRange(from = 0.0f) double eccentricity) {
mEccentricity = eccentricity;
return this;
}
/**
* Sets the inclination in semi-circles.
*
* <p>For GPS and Galileo, this is the difference between the inclination angle at
* reference time and the nominal inclination in semi-circles.
*
* <p>For Beidou and QZSS, this is the inclination angle at reference time in
* semi-circles.
*/
@NonNull
public Builder setInclination(@FloatRange(from = -1.0f, to = 1.0f) double inclination) {
mInclination = inclination;
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;
}
/**
* Sets the longitude of ascending node of orbital plane at weekly epoch in
* semi-circles.
*/
@NonNull
public Builder setOmega0(@FloatRange(from = -1.0f, to = 1.0f) double omega0) {
mOmega0 = omega0;
return this;
}
/** Sets the rate of right ascension in semi-circles per second. */
@NonNull
public Builder setOmegaDot(@FloatRange(from = -1.0f, to = 1.0f) double omegaDot) {
mOmegaDot = omegaDot;
return this;
}
/**
* Sets the square root of semi-major axis in square root of meters.
*
* <p>For Galileo, this is the difference with respect to the square root of the nominal
* semi-major axis in square root of meters.
*/
@NonNull
public Builder setRootA(@FloatRange(from = 0.0f, to = 8192.0f) double rootA) {
mRootA = rootA;
return this;
}
/** Sets the mean anomaly at reference time in semi-circles. */
@NonNull
public Builder setM0(@FloatRange(from = -1.0f, to = 1.0f) double m0) {
mM0 = m0;
return this;
}
/** Sets the satellite clock time bias correction coefficient in seconds. */
@NonNull
public Builder setAf0(@FloatRange(from = -0.0625f, to = 0.0625f) double af0) {
mAf0 = af0;
return this;
}
/** Sets the satellite clock time drift correction coefficient in seconds per second. */
@NonNull
public Builder setAf1(@FloatRange(from = -1.5e-8f, to = 1.5e-8f) double af1) {
mAf1 = af1;
return this;
}
/** Builds a {@link GnssSatelliteAlmanac} instance as specified by this builder. */
@NonNull
public GnssSatelliteAlmanac build() {
return new GnssSatelliteAlmanac(this);
}
}
}
}