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