1 /* 2 * Copyright (C) 2015 Google Inc. 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.cts; 18 19 import android.content.Context; 20 import android.content.pm.PackageManager; 21 import android.location.GnssClock; 22 import android.location.GnssMeasurement; 23 import android.location.GnssNavigationMessage; 24 import android.location.GnssStatus; 25 import android.location.LocationManager; 26 import android.os.Build; 27 import android.util.Log; 28 29 import junit.framework.Assert; 30 31 import java.util.List; 32 import java.util.concurrent.TimeUnit; 33 34 /** 35 * Helper class for GnssMeasurement Tests. 36 */ 37 public final class TestMeasurementUtil { 38 39 private static final String TAG = "TestMeasurementUtil"; 40 41 private static final long NSEC_IN_SEC = 1000_000_000L; 42 // Generally carrier phase quality prr's have uncertainties around 0.001-0.05 m/s, vs. 43 // doppler energy quality prr's closer to 0.25-10 m/s. Threshold is chosen between those 44 // typical ranges. 45 private static final float THRESHOLD_FOR_CARRIER_PRR_UNC_METERS_PER_SEC = 0.15F; 46 47 // For gpsTimeInNs >= 1.14 * 10^18 (year 2016+) 48 private static final long GPS_TIME_YEAR_2016_IN_NSEC = 1_140_000_000L * NSEC_IN_SEC; 49 50 // Error message for GnssMeasurements Registration. 51 public static final String REGISTRATION_ERROR_MESSAGE = "Registration of GnssMeasurements" + 52 " listener has failed, this indicates a platform bug. Please report the issue with" + 53 " a full bugreport."; 54 55 /** 56 * Check if test can be run on the current device. 57 * 58 * @param testLocationManager TestLocationManager 59 * @return true if Build.VERSION >= Build.VERSION_CODES.N and Location GPS present on 60 * device. 61 */ canTestRunOnCurrentDevice(TestLocationManager testLocationManager, String testTag, int minHardwareYear, boolean isCtsVerifier)62 public static boolean canTestRunOnCurrentDevice(TestLocationManager testLocationManager, 63 String testTag, 64 int minHardwareYear, 65 boolean isCtsVerifier) { 66 // TODO(sumitk): Enable this check once api 24 for N is avaiable. 67 /* 68 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { 69 Log.i(TAG, "This test is designed to work on N or newer. " + 70 "Test is being skipped because the platform version is being run in " + 71 Build.VERSION.SDK_INT); 72 return false; 73 } 74 */ 75 76 // If device does not have a GPS, skip the test. 77 PackageManager pm = testLocationManager.getContext().getPackageManager(); 78 if (!pm.hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS)) { 79 Log.w(testTag, "GPS feature not present on device, skipping GPS test."); 80 return false; 81 } 82 83 // If device has a GPS, but it's turned off in settings, and this is CTS verifier, 84 // fail the test now, because there's no point in going further. 85 // If this is CTS only,we'll warn instead, and quickly pass the test. 86 // (Cts non-verifier deep-indoors-forgiveness happens later, *if* needed) 87 boolean gpsProviderEnabled = testLocationManager.getLocationManager() 88 .isProviderEnabled(LocationManager.GPS_PROVIDER); 89 SoftAssert.failOrWarning(isCtsVerifier, " GPS location disabled on the device. " + 90 "Enable location in settings to continue test.", gpsProviderEnabled); 91 // If CTS only, allow an early exit pass 92 if (!isCtsVerifier && !gpsProviderEnabled) { 93 return false; 94 } 95 96 // TODO - add this to the test info page 97 int gnssYearOfHardware = testLocationManager.getLocationManager().getGnssYearOfHardware(); 98 Log.i(testTag, "This device is reporting GNSS hardware from year " 99 + (gnssYearOfHardware == 0 ? "2015 or earlier" : gnssYearOfHardware) + ". " 100 + "Devices " + (gnssYearOfHardware >= minHardwareYear ? "like this one " : "") 101 + "from year " + minHardwareYear + " or newer provide GnssMeasurement support." ); 102 103 return true; 104 } 105 106 /** 107 * Check if pseudorange rate uncertainty in Gnss Measurement is in the expected range. 108 * See field description in {@code gps.h}. 109 * 110 * @param measurement GnssMeasurement 111 * @return true if this measurement has prr uncertainty in a range indicative of carrier phase 112 */ gnssMeasurementHasCarrierPhasePrr(GnssMeasurement measurement)113 public static boolean gnssMeasurementHasCarrierPhasePrr(GnssMeasurement measurement) { 114 return (measurement.getPseudorangeRateUncertaintyMetersPerSecond() < 115 THRESHOLD_FOR_CARRIER_PRR_UNC_METERS_PER_SEC); 116 } 117 118 /** 119 * Assert all mandatory fields in Gnss Clock are in expected range. 120 * See mandatory fields in {@code gps.h}. 121 * 122 * @param clock GnssClock 123 * @param softAssert custom SoftAssert 124 * @param timeInNs event time in ns 125 */ assertGnssClockFields(GnssClock clock, SoftAssert softAssert, long timeInNs)126 public static void assertGnssClockFields(GnssClock clock, 127 SoftAssert softAssert, 128 long timeInNs) { 129 softAssert.assertTrue("time_ns: clock value", 130 timeInNs, 131 "X >= 0", 132 String.valueOf(timeInNs), 133 timeInNs >= 0L); 134 135 // If full bias is valid and accurate within one sec. verify its sign & magnitude 136 if (clock.hasFullBiasNanos() && 137 ((!clock.hasBiasUncertaintyNanos()) || 138 (clock.getBiasUncertaintyNanos() < NSEC_IN_SEC))) { 139 long gpsTimeInNs = timeInNs - clock.getFullBiasNanos(); 140 softAssert.assertTrue("TimeNanos - FullBiasNanos = GpsTimeNanos: clock value", 141 gpsTimeInNs, 142 "gpsTimeInNs >= 1.14 * 10^18 (year 2016+)", 143 String.valueOf(gpsTimeInNs), 144 gpsTimeInNs >= GPS_TIME_YEAR_2016_IN_NSEC); 145 } 146 147 } 148 149 /** 150 * Assert all mandatory fields in Gnss Measurement are in expected range. 151 * See mandatory fields in {@code gps.h}. 152 * 153 * @param measurement GnssMeasurement 154 * @param softAssert custom SoftAssert 155 * @param timeInNs event time in ns 156 */ assertAllGnssMeasurementMandatoryFields(GnssMeasurement measurement, SoftAssert softAssert, long timeInNs)157 public static void assertAllGnssMeasurementMandatoryFields(GnssMeasurement measurement, 158 SoftAssert softAssert, long timeInNs) { 159 160 verifySvid(measurement, softAssert, timeInNs); 161 verifyReceivedSatelliteVehicleTimeInNs(measurement, softAssert, timeInNs); 162 verifyAccumulatedDeltaRanges(measurement, softAssert, timeInNs); 163 164 int state = measurement.getState(); 165 softAssert.assertTrue("state: Satellite code sync state", 166 timeInNs, 167 "X > 0", 168 String.valueOf(state), 169 state > 0); 170 171 // Check received_gps_tow_uncertainty_ns 172 softAssert.assertTrueAsWarning("received_gps_tow_uncertainty_ns:" + 173 " Uncertainty of received GPS Time-of-Week in ns", 174 timeInNs, 175 "X > 0", 176 String.valueOf(measurement.getReceivedSvTimeUncertaintyNanos()), 177 measurement.getReceivedSvTimeUncertaintyNanos() > 0L); 178 179 long timeOffsetInSec = TimeUnit.NANOSECONDS.toSeconds( 180 (long) measurement.getTimeOffsetNanos()); 181 softAssert.assertTrue("time_offset_ns: Time offset", 182 timeInNs, 183 "-100 seconds < X < +10 seconds", 184 String.valueOf(measurement.getTimeOffsetNanos()), 185 (-100 < timeOffsetInSec) && (timeOffsetInSec < 10)); 186 187 softAssert.assertTrue("c_n0_dbhz: Carrier-to-noise density", 188 timeInNs, 189 "0.0 >= X <=63", 190 String.valueOf(measurement.getCn0DbHz()), 191 measurement.getCn0DbHz() >= 0.0 && 192 measurement.getCn0DbHz() <= 63.0); 193 194 softAssert.assertTrue("pseudorange_rate_mps: Pseudorange rate in m/s", 195 timeInNs, 196 "X != 0.0", 197 String.valueOf(measurement.getPseudorangeRateMetersPerSecond()), 198 measurement.getPseudorangeRateMetersPerSecond() != 0.0); 199 200 softAssert.assertTrue("pseudorange_rate_uncertainty_mps: " + 201 "Pseudorange Rate Uncertainty in m/s", 202 timeInNs, 203 "X > 0.0", 204 String.valueOf( 205 measurement.getPseudorangeRateUncertaintyMetersPerSecond()), 206 measurement.getPseudorangeRateUncertaintyMetersPerSecond() > 0.0); 207 208 // Check carrier_frequency_hz. 209 if (measurement.hasCarrierFrequencyHz()) { 210 softAssert.assertTrue("carrier_frequency_hz: Carrier frequency in hz", 211 timeInNs, 212 "X > 0.0", 213 String.valueOf(measurement.getCarrierFrequencyHz()), 214 measurement.getCarrierFrequencyHz() > 0.0); 215 } 216 217 // Check carrier_phase. 218 if (measurement.hasCarrierPhase()) { 219 softAssert.assertTrue("carrier_phase: Carrier phase", 220 timeInNs, 221 "0.0 >= X <= 1.0", 222 String.valueOf(measurement.getCarrierPhase()), 223 measurement.getCarrierPhase() >= 0.0 && measurement.getCarrierPhase() <= 1.0); 224 } 225 226 // Check carrier_phase_uncertainty.. 227 if (measurement.hasCarrierPhaseUncertainty()) { 228 softAssert.assertTrue("carrier_phase_uncertainty: 1-Sigma uncertainty of the " + 229 "carrier-phase", 230 timeInNs, 231 "X > 0.0", 232 String.valueOf(measurement.getCarrierPhaseUncertainty()), 233 measurement.getCarrierPhaseUncertainty() > 0.0); 234 } 235 236 // Check GNSS Measurement's multipath_indicator. 237 softAssert.assertTrue("multipath_indicator: GNSS Measurement's multipath indicator", 238 timeInNs, 239 "0 >= X <= 2", 240 String.valueOf(measurement.getMultipathIndicator()), 241 measurement.getMultipathIndicator() >= 0 242 && measurement.getMultipathIndicator() <= 2); 243 244 245 // Check Signal-to-Noise ratio (SNR). 246 if (measurement.hasSnrInDb()) { 247 softAssert.assertTrue("snr: Signal-to-Noise ratio (SNR) in dB", 248 timeInNs, 249 "0.0 >= X <= 63", 250 String.valueOf(measurement.getSnrInDb()), 251 measurement.getSnrInDb() >= 0.0 && measurement.getSnrInDb() <= 63); 252 } 253 } 254 255 /** 256 * Verify accumulated delta ranges are in expected range. 257 * 258 * @param measurement GnssMeasurement 259 * @param softAssert custom SoftAssert 260 * @param timeInNs event time in ns 261 */ verifyAccumulatedDeltaRanges(GnssMeasurement measurement, SoftAssert softAssert, long timeInNs)262 private static void verifyAccumulatedDeltaRanges(GnssMeasurement measurement, 263 SoftAssert softAssert, long timeInNs) { 264 265 int accumulatedDeltaRangeState = measurement.getAccumulatedDeltaRangeState(); 266 softAssert.assertTrue("accumulated_delta_range_state: " + 267 "Accumulated delta range state", 268 timeInNs, 269 "0 <= X <= 7", 270 String.valueOf(accumulatedDeltaRangeState), 271 accumulatedDeltaRangeState >= 0 && accumulatedDeltaRangeState <= 7); 272 if (accumulatedDeltaRangeState > 0) { 273 double accumulatedDeltaRangeInMeters = 274 measurement.getAccumulatedDeltaRangeMeters(); 275 softAssert.assertTrue("accumulated_delta_range_m: " + 276 "Accumulated delta range in meter", 277 timeInNs, 278 "X != 0.0", 279 String.valueOf(accumulatedDeltaRangeInMeters), 280 accumulatedDeltaRangeInMeters != 0.0); 281 double accumulatedDeltaRangeUncertainty = 282 measurement.getAccumulatedDeltaRangeUncertaintyMeters(); 283 softAssert.assertTrue("accumulated_delta_range_uncertainty_m: " + 284 "Accumulated delta range uncertainty in meter", 285 timeInNs, 286 "X > 0.0", 287 String.valueOf(accumulatedDeltaRangeUncertainty), 288 accumulatedDeltaRangeUncertainty > 0.0); 289 } 290 } 291 292 /** 293 * Verify svid's are in expected range. 294 * 295 * @param measurement GnssMeasurement 296 * @param softAssert custom SoftAssert 297 * @param timeInNs event time in ns 298 */ verifySvid(GnssMeasurement measurement, SoftAssert softAssert, long timeInNs)299 private static void verifySvid(GnssMeasurement measurement, SoftAssert softAssert, 300 long timeInNs) { 301 302 String svidLogMessageFormat = "svid: Space Vehicle ID. Constellation type = %s"; 303 int constellationType = measurement.getConstellationType(); 304 int svid = measurement.getSvid(); 305 String svidValue = String.valueOf(svid); 306 307 switch (constellationType) { 308 case GnssStatus.CONSTELLATION_GPS: 309 softAssert.assertTrue("svid: Space Vehicle ID. Constellation type " + 310 "= CONSTELLATION_GPS", 311 timeInNs, 312 "[1, 32]", 313 svidValue, 314 svid > 0 && svid <= 32); 315 break; 316 case GnssStatus.CONSTELLATION_SBAS: 317 softAssert.assertTrue("svid: Space Vehicle ID. Constellation type " + 318 "= CONSTELLATION_SBAS", 319 timeInNs, 320 "120 <= X <= 192", 321 svidValue, 322 svid >= 120 && svid <= 192); 323 break; 324 case GnssStatus.CONSTELLATION_GLONASS: 325 // Check Upper 8 bit, signed 326 int freq = (svid >> 8); 327 softAssert.assertTrue("svid: upper 8 bits, frequency number. Constellation type " + 328 "= CONSTELLATION_GLONASS", 329 timeInNs, 330 "freq == -127 || -7 <= freq <= 6", 331 svidValue, 332 // future proof check allowing a change in definition under discussion 333 (freq == -127) || (freq >= -7 && freq <= 6) || (freq >= 93 && freq <= 106)); 334 // Check lower 8 bits, signed 335 byte slot = (byte) svid; 336 softAssert.assertTrue("svid: lower 8 bits, slot. Constellation type " + 337 "= CONSTELLATION_GLONASS", 338 timeInNs, 339 "slot == -127 || 1 <= slot <= 24", 340 svidValue, 341 // future proof check allowingn a change in definition under discussion 342 (slot == -127) || (slot >= 1 && slot <= 24) || (slot >= 93 && slot <= 106)); 343 softAssert.assertTrue("svid: one of slot or freq is set (not -127). " + 344 "ConstellationType = CONSTELLATION_GLONASS,", 345 timeInNs, 346 "slot != -127 || freq != -127", 347 svidValue, 348 (slot != -127) || (freq != -127)); 349 break; 350 case GnssStatus.CONSTELLATION_QZSS: 351 softAssert.assertTrue("svid: Space Vehicle ID. Constellation type " + 352 "= CONSTELLATION_QZSS", 353 timeInNs, 354 "193 <= X <= 200", 355 svidValue, 356 svid >= 193 && svid <= 200); 357 break; 358 case GnssStatus.CONSTELLATION_BEIDOU: 359 softAssert.assertTrue("svid: Space Vehicle ID. Constellation type " + 360 "= CONSTELLATION_BEIDOU", 361 timeInNs, 362 "1 <= X <= 36", 363 svidValue, 364 svid >= 1 && svid <= 36); 365 break; 366 case GnssStatus.CONSTELLATION_GALILEO: 367 softAssert.assertTrue("svid: Space Vehicle ID. Constellation type " + 368 "= CONSTELLATION_GALILEO", 369 timeInNs, 370 "1 <= X <= 37", 371 String.valueOf(svid), 372 svid >= 1 && svid <= 37); 373 break; 374 default: 375 // Explicit fail if did not receive valid constellation type. 376 softAssert.assertTrue("svid: Space Vehicle ID. Did not receive any valid " + 377 "constellation type.", 378 timeInNs, 379 "Valid constellation type.", 380 svidValue, 381 false); 382 break; 383 } 384 } 385 386 /** 387 * Verify sv times are in expected range. 388 * 389 * @param measurement GnssMeasurement 390 * @param softAssert custom SoftAssert 391 * @param timeInNs event time in ns 392 * */ verifyReceivedSatelliteVehicleTimeInNs(GnssMeasurement measurement, SoftAssert softAssert, long timeInNs)393 private static void verifyReceivedSatelliteVehicleTimeInNs(GnssMeasurement measurement, 394 SoftAssert softAssert, long timeInNs) { 395 396 int constellationType = measurement.getConstellationType(); 397 int state = measurement.getState(); 398 long received_sv_time_ns = measurement.getReceivedSvTimeNanos(); 399 double sv_time_ms = TimeUnit.NANOSECONDS.toMillis(received_sv_time_ns); 400 double sv_time_sec = TimeUnit.NANOSECONDS.toSeconds(received_sv_time_ns); 401 double sv_time_days = TimeUnit.NANOSECONDS.toDays(received_sv_time_ns); 402 403 // Check ranges for received_sv_time_ns for given Gps State 404 if (state == 0) { 405 softAssert.assertTrue("received_sv_time_ns:" + 406 " Received SV Time-of-Week in ns." + 407 " GNSS_MEASUREMENT_STATE_UNKNOWN.", 408 timeInNs, 409 "X == 0", 410 String.valueOf(received_sv_time_ns), 411 sv_time_ms == 0); 412 } 413 414 switch (constellationType) { 415 case GnssStatus.CONSTELLATION_GPS: 416 verifyGpsQzssSvTimes(measurement, softAssert, timeInNs, state, "CONSTELLATION_GPS"); 417 break; 418 case GnssStatus.CONSTELLATION_QZSS: 419 verifyGpsQzssSvTimes(measurement, softAssert, timeInNs, state, 420 "CONSTELLATION_QZSS"); 421 break; 422 case GnssStatus.CONSTELLATION_SBAS: 423 if ((state | GnssMeasurement.STATE_SBAS_SYNC) 424 == GnssMeasurement.STATE_SBAS_SYNC) { 425 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 426 "GNSS_MEASUREMENT_STATE_SBAS_SYNC", 427 "GnssStatus.CONSTELLATION_SBAS"), 428 timeInNs, 429 "0s >= X <= 1s", 430 String.valueOf(sv_time_sec), 431 sv_time_sec >= 0 && sv_time_sec <= 1); 432 } else if ((state | GnssMeasurement.STATE_SYMBOL_SYNC) 433 == GnssMeasurement.STATE_SYMBOL_SYNC) { 434 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 435 "GNSS_MEASUREMENT_STATE_SYMBOL_SYNC", 436 "GnssStatus.CONSTELLATION_SBAS"), 437 timeInNs, 438 "0ms >= X <= 2ms", 439 String.valueOf(sv_time_ms), 440 sv_time_ms >= 0 && sv_time_ms <= 2); 441 } else if ((state | GnssMeasurement.STATE_CODE_LOCK) 442 == GnssMeasurement.STATE_CODE_LOCK) { 443 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 444 "GNSS_MEASUREMENT_STATE_CODE_LOCK", 445 "GnssStatus.CONSTELLATION_SBAS"), 446 timeInNs, 447 "0ms >= X <= 1ms", 448 String.valueOf(sv_time_ms), 449 sv_time_ms >= 0 && sv_time_ms <= 1); 450 } 451 break; 452 case GnssStatus.CONSTELLATION_GLONASS: 453 if ((state | GnssMeasurement.STATE_GLO_TOD_DECODED) 454 == GnssMeasurement.STATE_GLO_TOD_DECODED) { 455 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 456 "GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED", 457 "GnssStatus.CONSTELLATION_GLONASS"), 458 timeInNs, 459 "0 day >= X <= 1 day", 460 String.valueOf(sv_time_days), 461 sv_time_days >= 0 && sv_time_days <= 1); 462 } else if ((state | GnssMeasurement.STATE_GLO_STRING_SYNC) 463 == GnssMeasurement.STATE_GLO_STRING_SYNC) { 464 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 465 "GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC", 466 "GnssStatus.CONSTELLATION_GLONASS"), 467 timeInNs, 468 "0s >= X <= 2s", 469 String.valueOf(sv_time_sec), 470 sv_time_sec >= 0 && sv_time_sec <= 2); 471 } else if ((state | GnssMeasurement.STATE_BIT_SYNC) 472 == GnssMeasurement.STATE_BIT_SYNC) { 473 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 474 "GNSS_MEASUREMENT_STATE_BIT_SYNC", 475 "GnssStatus.CONSTELLATION_GLONASS"), 476 timeInNs, 477 "0ms >= X <= 20ms", 478 String.valueOf(sv_time_ms), 479 sv_time_ms >= 0 && sv_time_ms <= 20); 480 } else if ((state | GnssMeasurement.STATE_SYMBOL_SYNC) 481 == GnssMeasurement.STATE_SYMBOL_SYNC) { 482 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 483 "GNSS_MEASUREMENT_STATE_SYMBOL_SYNC", 484 "GnssStatus.CONSTELLATION_GLONASS"), 485 timeInNs, 486 "0ms >= X <= 10ms", 487 String.valueOf(sv_time_ms), 488 sv_time_ms >= 0 && sv_time_ms <= 10); 489 } else if ((state | GnssMeasurement.STATE_CODE_LOCK) 490 == GnssMeasurement.STATE_CODE_LOCK) { 491 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 492 "GNSS_MEASUREMENT_STATE_CODE_LOCK", 493 "GnssStatus.CONSTELLATION_GLONASS"), 494 timeInNs, 495 "0ms >= X <= 1ms", 496 String.valueOf(sv_time_ms), 497 sv_time_ms >= 0 && sv_time_ms <= 1); 498 } 499 break; 500 case GnssStatus.CONSTELLATION_GALILEO: 501 if ((state | GnssMeasurement.STATE_TOW_DECODED) 502 == GnssMeasurement.STATE_TOW_DECODED) { 503 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 504 "GNSS_MEASUREMENT_STATE_TOW_DECODED", 505 "GnssStatus.CONSTELLATION_GALILEO"), 506 timeInNs, 507 "0 >= X <= 7 days", 508 String.valueOf(sv_time_days), 509 sv_time_days >= 0 && sv_time_days <= 7); 510 } else if ((state | GnssMeasurement.STATE_GAL_E1B_PAGE_SYNC) 511 == GnssMeasurement.STATE_GAL_E1B_PAGE_SYNC) { 512 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 513 "GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC", 514 "GnssStatus.CONSTELLATION_GALILEO"), 515 timeInNs, 516 "0s >= X <= 2s", 517 String.valueOf(sv_time_sec), 518 sv_time_sec >= 0 && sv_time_sec <= 2); 519 } else if ((state | GnssMeasurement.STATE_GAL_E1C_2ND_CODE_LOCK) 520 == GnssMeasurement.STATE_GAL_E1C_2ND_CODE_LOCK) { 521 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 522 "GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK", 523 "GnssStatus.CONSTELLATION_GALILEO"), 524 timeInNs, 525 "0ms >= X <= 100ms", 526 String.valueOf(sv_time_ms), 527 sv_time_ms >= 0 && sv_time_ms <= 100); 528 } else if ((state | GnssMeasurement.STATE_GAL_E1BC_CODE_LOCK) 529 == GnssMeasurement.STATE_GAL_E1BC_CODE_LOCK) { 530 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 531 "GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK", 532 "GnssStatus.CONSTELLATION_GALILEO"), 533 timeInNs, 534 "0ms >= X <= 4ms", 535 String.valueOf(sv_time_ms), 536 sv_time_ms >= 0 && sv_time_ms <= 4); 537 } 538 break; 539 case GnssStatus.CONSTELLATION_BEIDOU: 540 if ((state | GnssMeasurement.STATE_TOW_DECODED) 541 == GnssMeasurement.STATE_TOW_DECODED) { 542 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 543 "GNSS_MEASUREMENT_STATE_TOW_DECODED", 544 "GnssStatus.CONSTELLATION_BEIDOU"), 545 timeInNs, 546 "0 >= X <= 7 days", 547 String.valueOf(sv_time_days), 548 sv_time_days >= 0 && sv_time_days <= 7); 549 } else if ((state | GnssMeasurement.STATE_SUBFRAME_SYNC) 550 == GnssMeasurement.STATE_SUBFRAME_SYNC) { 551 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 552 "GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC", 553 "GnssStatus.CONSTELLATION_BEIDOU"), 554 timeInNs, 555 "0s >= X <= 6s", 556 String.valueOf(sv_time_sec), 557 sv_time_sec >= 0 && sv_time_sec <= 6); 558 } else if ((state | GnssMeasurement.STATE_BDS_D2_SUBFRAME_SYNC) 559 == GnssMeasurement.STATE_BDS_D2_SUBFRAME_SYNC) { 560 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 561 "GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC", 562 "GnssStatus.CONSTELLATION_BEIDOU"), 563 timeInNs, 564 "0ms >= X <= 600ms (0.6sec)", 565 String.valueOf(sv_time_ms), 566 sv_time_ms >= 0 && sv_time_ms <= 600); 567 } else if ((state | GnssMeasurement.STATE_BIT_SYNC) 568 == GnssMeasurement.STATE_BIT_SYNC) { 569 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 570 "GNSS_MEASUREMENT_STATE_BIT_SYNC", 571 "GnssStatus.CONSTELLATION_BEIDOU"), 572 timeInNs, 573 "0ms >= X <= 20ms", 574 String.valueOf(sv_time_ms), 575 sv_time_ms >= 0 && sv_time_ms <= 20); 576 } else if ((state | GnssMeasurement.STATE_BDS_D2_BIT_SYNC) 577 == GnssMeasurement.STATE_BDS_D2_BIT_SYNC) { 578 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 579 "GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC", 580 "GnssStatus.CONSTELLATION_BEIDOU"), 581 timeInNs, 582 "0ms >= X <= 2ms", 583 String.valueOf(sv_time_ms), 584 sv_time_ms >= 0 && sv_time_ms <= 2); 585 } else if ((state | GnssMeasurement.STATE_CODE_LOCK) 586 == GnssMeasurement.STATE_CODE_LOCK) { 587 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 588 "GNSS_MEASUREMENT_STATE_CODE_LOCK", 589 "GnssStatus.CONSTELLATION_BEIDOU"), 590 timeInNs, 591 "0ms >= X <= 1ms", 592 String.valueOf(sv_time_ms), 593 sv_time_ms >= 0 && sv_time_ms <= 1); 594 } 595 break; 596 } 597 } 598 getReceivedSvTimeNsLogMessage(String constellationType, String state)599 private static String getReceivedSvTimeNsLogMessage(String constellationType, String state) { 600 return "received_sv_time_ns: Received SV Time-of-Week in ns. Constellation type = " 601 + constellationType + ". State = " + state; 602 } 603 604 /** 605 * Verify sv times are in expected range for given constellation type. 606 * This is common check for CONSTELLATION_GPS & CONSTELLATION_QZSS. 607 * 608 * @param measurement GnssMeasurement 609 * @param softAssert custom SoftAssert 610 * @param timeInNs event time in ns 611 * @param state GnssMeasurement State 612 * @param constellationType Gnss Constellation type 613 */ verifyGpsQzssSvTimes(GnssMeasurement measurement, SoftAssert softAssert, long timeInNs, int state, String constellationType)614 private static void verifyGpsQzssSvTimes(GnssMeasurement measurement, 615 SoftAssert softAssert, long timeInNs, int state, String constellationType) { 616 617 long received_sv_time_ns = measurement.getReceivedSvTimeNanos(); 618 double sv_time_ms = TimeUnit.NANOSECONDS.toMillis(received_sv_time_ns); 619 double sv_time_sec = TimeUnit.NANOSECONDS.toSeconds(received_sv_time_ns); 620 double sv_time_days = TimeUnit.NANOSECONDS.toDays(received_sv_time_ns); 621 622 if ((state | GnssMeasurement.STATE_TOW_DECODED) 623 == GnssMeasurement.STATE_TOW_DECODED) { 624 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 625 "GNSS_MEASUREMENT_STATE_TOW_DECODED", 626 constellationType), 627 timeInNs, 628 "0 >= X <= 7 days", 629 String.valueOf(sv_time_days), 630 sv_time_days >= 0 && sv_time_days <= 7); 631 } else if ((state | GnssMeasurement.STATE_SUBFRAME_SYNC) 632 == GnssMeasurement.STATE_SUBFRAME_SYNC) { 633 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 634 "GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC", 635 constellationType), 636 timeInNs, 637 "0s >= X <= 6s", 638 String.valueOf(sv_time_sec), 639 sv_time_sec >= 0 && sv_time_sec <= 6); 640 } else if ((state | GnssMeasurement.STATE_BIT_SYNC) 641 == GnssMeasurement.STATE_BIT_SYNC) { 642 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 643 "GNSS_MEASUREMENT_STATE_BIT_SYNC", 644 constellationType), 645 timeInNs, 646 "0ms >= X <= 20ms", 647 String.valueOf(sv_time_ms), 648 sv_time_ms >= 0 && sv_time_ms <= 20); 649 650 } else if ((state | GnssMeasurement.STATE_CODE_LOCK) 651 == GnssMeasurement.STATE_CODE_LOCK) { 652 softAssert.assertTrue(getReceivedSvTimeNsLogMessage( 653 "GNSS_MEASUREMENT_STATE_CODE_LOCK", 654 constellationType), 655 timeInNs, 656 "0ms >= X <= 1ms", 657 String.valueOf(sv_time_ms), 658 sv_time_ms >= 0 && sv_time_ms <= 1); 659 } 660 } 661 662 /** 663 * Assert all mandatory fields in Gnss Navigation Message are in expected range. 664 * See mandatory fields in {@code gps.h}. 665 * 666 * @param events GnssNavigationMessageEvents 667 */ verifyGnssNavMessageMandatoryField(List<GnssNavigationMessage> events)668 public static void verifyGnssNavMessageMandatoryField(List<GnssNavigationMessage> events) { 669 // Verify mandatory GnssNavigationMessage field values. 670 SoftAssert softAssert = new SoftAssert(TAG); 671 for (GnssNavigationMessage message : events) { 672 int type = message.getType(); 673 softAssert.assertTrue("Gnss Navigation Message Type:expected [0x0101 - 0x0104]," + 674 " actual = " + type, 675 type >= 0x0101 && type <= 0x0104); 676 677 // if message type == TYPE_L1CA, verify PRN & Data Size. 678 int messageType = message.getType(); 679 if (messageType == GnssNavigationMessage.TYPE_GPS_L1CA) { 680 int svid = message.getSvid(); 681 softAssert.assertTrue("Space Vehicle ID : expected = [1, 32], actual = " + 682 svid, 683 svid >= 1 && svid <= 32); 684 int dataSize = message.getData().length; 685 softAssert.assertTrue("Data size: expected = 40, actual = " + dataSize, 686 dataSize == 40); 687 } else { 688 Log.i(TAG, "GnssNavigationMessage (type = " + messageType 689 + ") skipped for verification."); 690 } 691 } 692 softAssert.assertAll(); 693 } 694 } 695