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.IntRange; 21 import android.annotation.NonNull; 22 import android.annotation.SystemApi; 23 import android.location.flags.Flags; 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 contains the real time integrity status of a GNSS satellite based on notice advisory. 35 * 36 * @hide 37 */ 38 @FlaggedApi(Flags.FLAG_GNSS_ASSISTANCE_INTERFACE) 39 @SystemApi 40 public final class RealTimeIntegrityModel implements Parcelable { 41 /** 42 * Bad satellite ID number or OSN number for Glonass. 43 * 44 * <p>The distinction is made by looking at the constellation field. Values 45 * must be in the range of: 46 * 47 * <p> - GPS: 1-32 48 * <p> - GLONASS: 1-25 49 * <p> - QZSS: 183-206 50 * <p> - Galileo: 1-36 51 * <p> - Beidou: 1-63 52 */ 53 private final int mBadSvid; 54 55 /** 56 * The type of the bad signal or signals. 57 * 58 * <p>An empty list means that all signals on the specific SV are not healthy. 59 */ 60 @NonNull private final List<GnssSignalType> mBadSignalTypes; 61 62 /** UTC timestamp (in seconds) when the advisory was published. */ 63 private final long mPublishDateSeconds; 64 65 /** UTC timestamp (in seconds) for the start of the event. */ 66 private final long mStartDateSeconds; 67 68 /** UTC timestamp (in seconds) for the end of the event. */ 69 private final long mEndDateSeconds; 70 71 /** 72 * Abbreviated type of the advisory, providing a concise summary of the event. 73 * 74 * <p>This field follows different definitions depending on the GNSS constellation: 75 * <p> - GPS: See NANU type definitions(https://www.navcen.uscg.gov/nanu-abbreviations-and-descriptions) 76 * <p> - Galileo: See NAGU type definitions(https://www.gsc-europa.eu/system-service-status/nagu-information) 77 * <p> - QZSS: See NAQU type definitions](https://sys.qzss.go.jp/dod/en/naqu/type.html) 78 * <p> - BeiDou: Not used; set to an empty string. 79 */ 80 @NonNull private final String mAdvisoryType; 81 82 /** 83 * Unique identifier for the advisory within its constellation's system. 84 * 85 * <p>For BeiDou, this is not used and should be an empty string. 86 */ 87 @NonNull private final String mAdvisoryNumber; 88 RealTimeIntegrityModel(Builder builder)89 private RealTimeIntegrityModel(Builder builder) { 90 // Allow SV ID beyond the range to support potential future extensibility. 91 Preconditions.checkArgument(builder.mBadSvid >= 1); 92 Preconditions.checkArgument(builder.mPublishDateSeconds > 0); 93 Preconditions.checkArgument(builder.mStartDateSeconds > 0); 94 Preconditions.checkArgument(builder.mEndDateSeconds > 0); 95 Preconditions.checkNotNull(builder.mAdvisoryType, "AdvisoryType cannot be null"); 96 Preconditions.checkNotNull(builder.mAdvisoryNumber, "AdvisoryNumber cannot be null"); 97 if (builder.mBadSignalTypes == null) { 98 mBadSignalTypes = new ArrayList<>(); 99 } else { 100 mBadSignalTypes = Collections.unmodifiableList( 101 new ArrayList<>(builder.mBadSignalTypes)); 102 } 103 mBadSvid = builder.mBadSvid; 104 mPublishDateSeconds = builder.mPublishDateSeconds; 105 mStartDateSeconds = builder.mStartDateSeconds; 106 mEndDateSeconds = builder.mEndDateSeconds; 107 mAdvisoryType = builder.mAdvisoryType; 108 mAdvisoryNumber = builder.mAdvisoryNumber; 109 } 110 111 /** 112 * Returns the Pseudo-random or satellite ID number for the satellite, 113 * a.k.a. Space Vehicle (SV), or OSN number for Glonass. 114 * 115 * <p>The distinction is made by looking at the constellation field. Values 116 * must be in the range of: 117 * 118 * <p> - GPS: 1-32 119 * <p> - GLONASS: 1-25 120 * <p> - QZSS: 183-206 121 * <p> - Galileo: 1-36 122 * <p> - Beidou: 1-63 123 */ 124 @IntRange(from = 1, to = 206) getBadSvid()125 public int getBadSvid() { 126 return mBadSvid; 127 } 128 129 /** 130 * Returns the type of the bad signal or signals. 131 * 132 * <p>An empty list means that all signals on the specific SV are not healthy. 133 */ 134 @NonNull getBadSignalTypes()135 public List<GnssSignalType> getBadSignalTypes() { 136 return mBadSignalTypes; 137 } 138 139 /** Returns the UTC timestamp (in seconds) when the advisory was published */ 140 @IntRange(from = 0) getPublishDateSeconds()141 public long getPublishDateSeconds() { 142 return mPublishDateSeconds; 143 } 144 145 /** Returns UTC timestamp (in seconds) for the start of the event. */ 146 @IntRange(from = 0) getStartDateSeconds()147 public long getStartDateSeconds() { 148 return mStartDateSeconds; 149 } 150 151 /** Returns UTC timestamp (in seconds) for the end of the event. */ 152 @IntRange(from = 0) getEndDateSeconds()153 public long getEndDateSeconds() { 154 return mEndDateSeconds; 155 } 156 157 /** Returns the abbreviated type of notice advisory. */ 158 @NonNull getAdvisoryType()159 public String getAdvisoryType() { 160 return mAdvisoryType; 161 } 162 163 /** Returns the unique identifier for the advisory. */ 164 @NonNull getAdvisoryNumber()165 public String getAdvisoryNumber() { 166 return mAdvisoryNumber; 167 } 168 169 public static final @NonNull Creator<RealTimeIntegrityModel> CREATOR = 170 new Creator<RealTimeIntegrityModel>() { 171 @Override 172 @NonNull 173 public RealTimeIntegrityModel createFromParcel(Parcel in) { 174 RealTimeIntegrityModel realTimeIntegrityModel = 175 new RealTimeIntegrityModel.Builder() 176 .setBadSvid(in.readInt()) 177 .setBadSignalTypes( 178 in.createTypedArrayList(GnssSignalType.CREATOR)) 179 .setPublishDateSeconds(in.readLong()) 180 .setStartDateSeconds(in.readLong()) 181 .setEndDateSeconds(in.readLong()) 182 .setAdvisoryType(in.readString8()) 183 .setAdvisoryNumber(in.readString8()) 184 .build(); 185 return realTimeIntegrityModel; 186 } 187 188 @Override 189 public RealTimeIntegrityModel[] newArray(int size) { 190 return new RealTimeIntegrityModel[size]; 191 } 192 }; 193 194 @Override describeContents()195 public int describeContents() { 196 return 0; 197 } 198 199 @Override writeToParcel(@onNull Parcel parcel, int flags)200 public void writeToParcel(@NonNull Parcel parcel, int flags) { 201 parcel.writeInt(mBadSvid); 202 parcel.writeTypedList(mBadSignalTypes); 203 parcel.writeLong(mPublishDateSeconds); 204 parcel.writeLong(mStartDateSeconds); 205 parcel.writeLong(mEndDateSeconds); 206 parcel.writeString8(mAdvisoryType); 207 parcel.writeString8(mAdvisoryNumber); 208 } 209 210 @Override 211 @NonNull toString()212 public String toString() { 213 StringBuilder builder = new StringBuilder("RealTimeIntegrityModel["); 214 builder.append("badSvid = ").append(mBadSvid); 215 builder.append(", badSignalTypes = ").append(mBadSignalTypes); 216 builder.append(", publishDateSeconds = ").append(mPublishDateSeconds); 217 builder.append(", startDateSeconds = ").append(mStartDateSeconds); 218 builder.append(", endDateSeconds = ").append(mEndDateSeconds); 219 builder.append(", advisoryType = ").append(mAdvisoryType); 220 builder.append(", advisoryNumber = ").append(mAdvisoryNumber); 221 builder.append("]"); 222 return builder.toString(); 223 } 224 225 /** Builder for {@link RealTimeIntegrityModel} */ 226 public static final class Builder { 227 private int mBadSvid; 228 private List<GnssSignalType> mBadSignalTypes; 229 private long mPublishDateSeconds; 230 private long mStartDateSeconds; 231 private long mEndDateSeconds; 232 private String mAdvisoryType; 233 private String mAdvisoryNumber; 234 235 /** 236 * Sets the bad satellite ID number or OSN number for Glonass. 237 * 238 * <p>The distinction is made by looking at the constellation field. Values 239 * must be in the range of: 240 * 241 * <p> - GPS: 1-32 242 * <p> - GLONASS: 1-25 243 * <p> - QZSS: 183-206 244 * <p> - Galileo: 1-36 245 * <p> - Beidou: 1-63 246 */ 247 @NonNull setBadSvid(@ntRangefrom = 1, to = 206) int badSvid)248 public Builder setBadSvid(@IntRange(from = 1, to = 206) int badSvid) { 249 mBadSvid = badSvid; 250 return this; 251 } 252 253 /** 254 * Sets the type of the bad signal or signals. 255 * 256 * <p>An empty list means that all signals on the specific SV are not healthy. 257 */ 258 @NonNull setBadSignalTypes(@onNull List<GnssSignalType> badSignalTypes)259 public Builder setBadSignalTypes(@NonNull List<GnssSignalType> badSignalTypes) { 260 mBadSignalTypes = badSignalTypes; 261 return this; 262 } 263 264 /** Sets the UTC timestamp (in seconds) when the advisory was published. */ 265 @NonNull setPublishDateSeconds(@ntRangefrom = 0) long publishDateSeconds)266 public Builder setPublishDateSeconds(@IntRange(from = 0) long publishDateSeconds) { 267 mPublishDateSeconds = publishDateSeconds; 268 return this; 269 } 270 271 /** Sets the UTC timestamp (in seconds) for the start of the event. */ 272 @NonNull setStartDateSeconds(@ntRangefrom = 0) long startDateSeconds)273 public Builder setStartDateSeconds(@IntRange(from = 0) long startDateSeconds) { 274 mStartDateSeconds = startDateSeconds; 275 return this; 276 } 277 278 /** Sets the UTC timestamp (in seconds) for the end of the event. */ 279 @NonNull setEndDateSeconds(@ntRangefrom = 0) long endDateSeconds)280 public Builder setEndDateSeconds(@IntRange(from = 0) long endDateSeconds) { 281 mEndDateSeconds = endDateSeconds; 282 return this; 283 } 284 285 /** Sets the abbreviated type of notice advisory. */ 286 @NonNull setAdvisoryType(@onNull String advisoryType)287 public Builder setAdvisoryType(@NonNull String advisoryType) { 288 mAdvisoryType = advisoryType; 289 return this; 290 } 291 292 /** Sets the unique identifier for the advisory. */ 293 @NonNull setAdvisoryNumber(@onNull String advisoryNumber)294 public Builder setAdvisoryNumber(@NonNull String advisoryNumber) { 295 mAdvisoryNumber = advisoryNumber; 296 return this; 297 } 298 299 /** Builds a {@link RealTimeIntegrityModel} instance as specified by this builder. */ 300 @NonNull build()301 public RealTimeIntegrityModel build() { 302 return new RealTimeIntegrityModel(this); 303 } 304 } 305 } 306