Home | History | Annotate | Download | only in cts
      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 &gt;=  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                 softAssert.assertTrue("svid: Slot ID, or if unknown, Frequency + 100 (93-106). " +
    356                                 "Constellation type = CONSTELLATION_GLONASS",
    357                         timeInNs,
    358                         "1 <= svid <= 24 || 93 <= svid <= 106",
    359                         svidValue,
    360                         (svid >= 1 && svid <= 24) || (svid >= 93 && svid <= 106));
    361                 break;
    362             case GnssStatus.CONSTELLATION_QZSS:
    363                 softAssert.assertTrue("svid: Space Vehicle ID. Constellation type " +
    364                                 "= CONSTELLATION_QZSS",
    365                         timeInNs,
    366                         "193 <= X <= 200",
    367                         svidValue,
    368                         svid >= 193 && svid <= 200);
    369                 break;
    370             case GnssStatus.CONSTELLATION_BEIDOU:
    371                 softAssert.assertTrue("svid: Space Vehicle ID. Constellation type " +
    372                                 "= CONSTELLATION_BEIDOU",
    373                         timeInNs,
    374                         "1 <= X <= 36",
    375                         svidValue,
    376                         svid >= 1 && svid <= 36);
    377                 break;
    378             case GnssStatus.CONSTELLATION_GALILEO:
    379                 softAssert.assertTrue("svid: Space Vehicle ID. Constellation type " +
    380                                 "= CONSTELLATION_GALILEO",
    381                         timeInNs,
    382                         "1 <= X <= 37",
    383                         String.valueOf(svid),
    384                         svid >= 1 && svid <= 37);
    385                 break;
    386             default:
    387                 // Explicit fail if did not receive valid constellation type.
    388                 softAssert.assertTrue("svid: Space Vehicle ID. Did not receive any valid " +
    389                                 "constellation type.",
    390                         timeInNs,
    391                         "Valid constellation type.",
    392                         svidValue,
    393                         false);
    394                 break;
    395         }
    396     }
    397 
    398     /**
    399      * Verify sv times are in expected range.
    400      *
    401      * @param measurement GnssMeasurement
    402      * @param softAssert  custom SoftAssert
    403      * @param timeInNs    event time in ns
    404      * */
    405     private static void verifyReceivedSatelliteVehicleTimeInNs(GnssMeasurement measurement,
    406         SoftAssert softAssert, long timeInNs) {
    407 
    408         int constellationType = measurement.getConstellationType();
    409         int state = measurement.getState();
    410         long received_sv_time_ns = measurement.getReceivedSvTimeNanos();
    411         double sv_time_ms = TimeUnit.NANOSECONDS.toMillis(received_sv_time_ns);
    412         double sv_time_sec = TimeUnit.NANOSECONDS.toSeconds(received_sv_time_ns);
    413         double sv_time_days = TimeUnit.NANOSECONDS.toDays(received_sv_time_ns);
    414 
    415         // Check ranges for received_sv_time_ns for given Gps State
    416         if (state == 0) {
    417             softAssert.assertTrue("received_sv_time_ns:" +
    418                             " Received SV Time-of-Week in ns." +
    419                             " GNSS_MEASUREMENT_STATE_UNKNOWN.",
    420                     timeInNs,
    421                     "X == 0",
    422                     String.valueOf(received_sv_time_ns),
    423                     sv_time_ms == 0);
    424         }
    425 
    426         switch (constellationType) {
    427             case GnssStatus.CONSTELLATION_GPS:
    428                 verifyGpsQzssSvTimes(measurement, softAssert, timeInNs, state, "CONSTELLATION_GPS");
    429                 break;
    430             case GnssStatus.CONSTELLATION_QZSS:
    431                 verifyGpsQzssSvTimes(measurement, softAssert, timeInNs, state,
    432                         "CONSTELLATION_QZSS");
    433                 break;
    434             case GnssStatus.CONSTELLATION_SBAS:
    435                 if ((state & GnssMeasurement.STATE_SBAS_SYNC)
    436                         == GnssMeasurement.STATE_SBAS_SYNC) {
    437                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    438                                     "GNSS_MEASUREMENT_STATE_SBAS_SYNC",
    439                                     "GnssStatus.CONSTELLATION_SBAS"),
    440                             timeInNs,
    441                             "0s >= X <= 1s",
    442                             String.valueOf(sv_time_sec),
    443                             sv_time_sec >= 0 && sv_time_sec <= 1);
    444                 } else if ((state & GnssMeasurement.STATE_SYMBOL_SYNC)
    445                         == GnssMeasurement.STATE_SYMBOL_SYNC) {
    446                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    447                                     "GNSS_MEASUREMENT_STATE_SYMBOL_SYNC",
    448                                     "GnssStatus.CONSTELLATION_SBAS"),
    449                             timeInNs,
    450                             "0ms >= X <= 2ms",
    451                             String.valueOf(sv_time_ms),
    452                             sv_time_ms >= 0 && sv_time_ms <= 2);
    453                 } else if ((state & GnssMeasurement.STATE_CODE_LOCK)
    454                         == GnssMeasurement.STATE_CODE_LOCK) {
    455                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    456                                     "GNSS_MEASUREMENT_STATE_CODE_LOCK",
    457                                     "GnssStatus.CONSTELLATION_SBAS"),
    458                             timeInNs,
    459                             "0ms >= X <= 1ms",
    460                             String.valueOf(sv_time_ms),
    461                             sv_time_ms >= 0 && sv_time_ms <= 1);
    462                 }
    463                 break;
    464             case GnssStatus.CONSTELLATION_GLONASS:
    465                 if ((state & GnssMeasurement.STATE_GLO_TOD_DECODED)
    466                         == GnssMeasurement.STATE_GLO_TOD_DECODED) {
    467                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    468                                     "GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED",
    469                                     "GnssStatus.CONSTELLATION_GLONASS"),
    470                             timeInNs,
    471                             "0 day >= X <= 1 day",
    472                             String.valueOf(sv_time_days),
    473                             sv_time_days >= 0 && sv_time_days <= 1);
    474                 } else if ((state & GnssMeasurement.STATE_GLO_TOD_KNOWN)
    475                          == GnssMeasurement.STATE_GLO_TOD_KNOWN) {
    476                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    477                                     "GNSS_MEASUREMENT_STATE_GLO_TOD_KNOWN",
    478                                     "GnssStatus.CONSTELLATION_GLONASS"),
    479                             timeInNs,
    480                             "0 day >= X <= 1 day",
    481                             String.valueOf(sv_time_days),
    482                             sv_time_days >= 0 && sv_time_days <= 1);
    483                 } else if ((state & GnssMeasurement.STATE_GLO_STRING_SYNC)
    484                         == GnssMeasurement.STATE_GLO_STRING_SYNC) {
    485                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    486                                     "GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC",
    487                                     "GnssStatus.CONSTELLATION_GLONASS"),
    488                             timeInNs,
    489                             "0s >= X <= 2s",
    490                             String.valueOf(sv_time_sec),
    491                             sv_time_sec >= 0 && sv_time_sec <= 2);
    492                 } else if ((state & GnssMeasurement.STATE_BIT_SYNC)
    493                         == GnssMeasurement.STATE_BIT_SYNC) {
    494                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    495                                     "GNSS_MEASUREMENT_STATE_BIT_SYNC",
    496                                     "GnssStatus.CONSTELLATION_GLONASS"),
    497                             timeInNs,
    498                             "0ms >= X <= 20ms",
    499                             String.valueOf(sv_time_ms),
    500                             sv_time_ms >= 0 && sv_time_ms <= 20);
    501                 } else if ((state & GnssMeasurement.STATE_SYMBOL_SYNC)
    502                         == GnssMeasurement.STATE_SYMBOL_SYNC) {
    503                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    504                                     "GNSS_MEASUREMENT_STATE_SYMBOL_SYNC",
    505                                     "GnssStatus.CONSTELLATION_GLONASS"),
    506                             timeInNs,
    507                             "0ms >= X <= 10ms",
    508                             String.valueOf(sv_time_ms),
    509                             sv_time_ms >= 0 && sv_time_ms <= 10);
    510                 } else if ((state & GnssMeasurement.STATE_CODE_LOCK)
    511                         == GnssMeasurement.STATE_CODE_LOCK) {
    512                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    513                                     "GNSS_MEASUREMENT_STATE_CODE_LOCK",
    514                                     "GnssStatus.CONSTELLATION_GLONASS"),
    515                             timeInNs,
    516                             "0ms >= X <= 1ms",
    517                             String.valueOf(sv_time_ms),
    518                             sv_time_ms >= 0 && sv_time_ms <= 1);
    519                 }
    520                 break;
    521             case GnssStatus.CONSTELLATION_GALILEO:
    522                 if ((state & GnssMeasurement.STATE_TOW_DECODED)
    523                         == GnssMeasurement.STATE_TOW_DECODED) {
    524                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    525                                     "GNSS_MEASUREMENT_STATE_TOW_DECODED",
    526                                     "GnssStatus.CONSTELLATION_GALILEO"),
    527                             timeInNs,
    528                             "0 >= X <= 7 days",
    529                             String.valueOf(sv_time_days),
    530                             sv_time_days >= 0 && sv_time_days <= 7);
    531                 } else if ((state & GnssMeasurement.STATE_TOW_KNOWN)
    532                               == GnssMeasurement.STATE_TOW_KNOWN) {
    533                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    534                                     "GNSS_MEASUREMENT_STATE_TOW_DECODED",
    535                                     "GnssStatus.CONSTELLATION_GALILEO"),
    536                         timeInNs,
    537                         "0 >= X <= 7 days",
    538                         String.valueOf(sv_time_days),
    539                         sv_time_days >= 0 && sv_time_days <= 7);
    540                 } else if ((state & GnssMeasurement.STATE_GAL_E1B_PAGE_SYNC)
    541                         == GnssMeasurement.STATE_GAL_E1B_PAGE_SYNC) {
    542                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    543                                     "GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC",
    544                                     "GnssStatus.CONSTELLATION_GALILEO"),
    545                             timeInNs,
    546                             "0s >= X <= 2s",
    547                             String.valueOf(sv_time_sec),
    548                             sv_time_sec >= 0 && sv_time_sec <= 2);
    549                 } else if ((state & GnssMeasurement.STATE_GAL_E1C_2ND_CODE_LOCK)
    550                         == GnssMeasurement.STATE_GAL_E1C_2ND_CODE_LOCK) {
    551                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    552                                     "GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK",
    553                                     "GnssStatus.CONSTELLATION_GALILEO"),
    554                             timeInNs,
    555                             "0ms >= X <= 100ms",
    556                             String.valueOf(sv_time_ms),
    557                             sv_time_ms >= 0 && sv_time_ms <= 100);
    558                 } else if ((state & GnssMeasurement.STATE_GAL_E1BC_CODE_LOCK)
    559                         == GnssMeasurement.STATE_GAL_E1BC_CODE_LOCK) {
    560                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    561                                     "GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK",
    562                                     "GnssStatus.CONSTELLATION_GALILEO"),
    563                             timeInNs,
    564                             "0ms >= X <= 4ms",
    565                             String.valueOf(sv_time_ms),
    566                             sv_time_ms >= 0 && sv_time_ms <= 4);
    567                 }
    568                 break;
    569             case GnssStatus.CONSTELLATION_BEIDOU:
    570                 if ((state & GnssMeasurement.STATE_TOW_DECODED)
    571                         == GnssMeasurement.STATE_TOW_DECODED) {
    572                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    573                                     "GNSS_MEASUREMENT_STATE_TOW_DECODED",
    574                                     "GnssStatus.CONSTELLATION_BEIDOU"),
    575                             timeInNs,
    576                             "0 >= X <= 7 days",
    577                             String.valueOf(sv_time_days),
    578                             sv_time_days >= 0 && sv_time_days <= 7);
    579                 } else if ((state & GnssMeasurement.STATE_SUBFRAME_SYNC)
    580                         == GnssMeasurement.STATE_SUBFRAME_SYNC) {
    581                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    582                                     "GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC",
    583                                     "GnssStatus.CONSTELLATION_BEIDOU"),
    584                             timeInNs,
    585                             "0s >= X <= 6s",
    586                             String.valueOf(sv_time_sec),
    587                             sv_time_sec >= 0 && sv_time_sec <= 6);
    588                 } else if ((state & GnssMeasurement.STATE_BDS_D2_SUBFRAME_SYNC)
    589                         == GnssMeasurement.STATE_BDS_D2_SUBFRAME_SYNC) {
    590                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    591                                     "GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC",
    592                                     "GnssStatus.CONSTELLATION_BEIDOU"),
    593                             timeInNs,
    594                             "0ms >= X <= 600ms (0.6sec)",
    595                             String.valueOf(sv_time_ms),
    596                             sv_time_ms >= 0 && sv_time_ms <= 600);
    597                 } else if ((state & GnssMeasurement.STATE_BIT_SYNC)
    598                         == GnssMeasurement.STATE_BIT_SYNC) {
    599                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    600                                     "GNSS_MEASUREMENT_STATE_BIT_SYNC",
    601                                     "GnssStatus.CONSTELLATION_BEIDOU"),
    602                             timeInNs,
    603                             "0ms >= X <= 20ms",
    604                             String.valueOf(sv_time_ms),
    605                             sv_time_ms >= 0 && sv_time_ms <= 20);
    606                 } else if ((state & GnssMeasurement.STATE_BDS_D2_BIT_SYNC)
    607                         == GnssMeasurement.STATE_BDS_D2_BIT_SYNC) {
    608                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    609                                     "GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC",
    610                                     "GnssStatus.CONSTELLATION_BEIDOU"),
    611                             timeInNs,
    612                             "0ms >= X <= 2ms",
    613                             String.valueOf(sv_time_ms),
    614                             sv_time_ms >= 0 && sv_time_ms <= 2);
    615                 } else if ((state & GnssMeasurement.STATE_CODE_LOCK)
    616                         == GnssMeasurement.STATE_CODE_LOCK) {
    617                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    618                                     "GNSS_MEASUREMENT_STATE_CODE_LOCK",
    619                                     "GnssStatus.CONSTELLATION_BEIDOU"),
    620                             timeInNs,
    621                             "0ms >= X <= 1ms",
    622                             String.valueOf(sv_time_ms),
    623                             sv_time_ms >= 0 && sv_time_ms <= 1);
    624                 }
    625                 break;
    626         }
    627     }
    628 
    629     private static String getReceivedSvTimeNsLogMessage(String constellationType, String state) {
    630         return "received_sv_time_ns: Received SV Time-of-Week in ns. Constellation type = "
    631                 + constellationType + ". State = " + state;
    632     }
    633 
    634     /**
    635      * Verify sv times are in expected range for given constellation type.
    636      * This is common check for CONSTELLATION_GPS & CONSTELLATION_QZSS.
    637      *
    638      * @param measurement GnssMeasurement
    639      * @param softAssert  custom SoftAssert
    640      * @param timeInNs    event time in ns
    641      * @param state       GnssMeasurement State
    642      * @param constellationType Gnss Constellation type
    643      */
    644     private static void verifyGpsQzssSvTimes(GnssMeasurement measurement,
    645         SoftAssert softAssert, long timeInNs, int state, String constellationType) {
    646 
    647         long received_sv_time_ns = measurement.getReceivedSvTimeNanos();
    648         double sv_time_ms = TimeUnit.NANOSECONDS.toMillis(received_sv_time_ns);
    649         double sv_time_sec = TimeUnit.NANOSECONDS.toSeconds(received_sv_time_ns);
    650         double sv_time_days = TimeUnit.NANOSECONDS.toDays(received_sv_time_ns);
    651 
    652         if ((state & GnssMeasurement.STATE_TOW_DECODED)
    653                 == GnssMeasurement.STATE_TOW_DECODED) {
    654             softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    655                             "GNSS_MEASUREMENT_STATE_TOW_DECODED",
    656                             constellationType),
    657                     timeInNs,
    658                     "0 >= X <= 7 days",
    659                     String.valueOf(sv_time_days),
    660                     sv_time_days >= 0 && sv_time_days <= 7);
    661         } else if ((state & GnssMeasurement.STATE_SUBFRAME_SYNC)
    662                 == GnssMeasurement.STATE_SUBFRAME_SYNC) {
    663             softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    664                             "GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC",
    665                             constellationType),
    666                     timeInNs,
    667                     "0s >= X <= 6s",
    668                     String.valueOf(sv_time_sec),
    669                     sv_time_sec >= 0 && sv_time_sec <= 6);
    670         } else if ((state & GnssMeasurement.STATE_BIT_SYNC)
    671                 == GnssMeasurement.STATE_BIT_SYNC) {
    672             softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    673                             "GNSS_MEASUREMENT_STATE_BIT_SYNC",
    674                             constellationType),
    675                     timeInNs,
    676                     "0ms >= X <= 20ms",
    677                     String.valueOf(sv_time_ms),
    678                     sv_time_ms >= 0 && sv_time_ms <= 20);
    679 
    680         } else if ((state & GnssMeasurement.STATE_CODE_LOCK)
    681                 == GnssMeasurement.STATE_CODE_LOCK) {
    682             softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
    683                             "GNSS_MEASUREMENT_STATE_CODE_LOCK",
    684                             constellationType),
    685                     timeInNs,
    686                     "0ms >= X <= 1ms",
    687                     String.valueOf(sv_time_ms),
    688                     sv_time_ms >= 0 && sv_time_ms <= 1);
    689         }
    690     }
    691 
    692     /**
    693      * Assert all mandatory fields in Gnss Navigation Message are in expected range.
    694      * See mandatory fields in {@code gps.h}.
    695      *
    696      * @param testLocationManager TestLocationManager
    697      * @param events GnssNavigationMessageEvents
    698      */
    699     public static void verifyGnssNavMessageMandatoryField(TestLocationManager testLocationManager,
    700                                                           List<GnssNavigationMessage> events) {
    701         // Verify mandatory GnssNavigationMessage field values.
    702         SoftAssert softAssert = new SoftAssert(TAG);
    703         for (GnssNavigationMessage message : events) {
    704             int type = message.getType();
    705             softAssert.assertTrue("Gnss Navigation Message Type:expected [" +
    706                 getGnssNavMessageTypes() + "] actual = " + type,
    707                     GNSS_NAVIGATION_MESSAGE_TYPE.contains(type));
    708 
    709             int gnssYearOfHardware = testLocationManager.getLocationManager().getGnssYearOfHardware();
    710             if (gnssYearOfHardware >= YEAR_2016) {
    711                 softAssert.assertTrue("Message ID cannot be 0", message.getMessageId() != 0);
    712                 softAssert.assertTrue("Sub Message ID cannot be 0", message.getSubmessageId() != 0);
    713             }
    714 
    715             // if message type == TYPE_L1CA, verify PRN & Data Size.
    716             int messageType = message.getType();
    717             if (messageType == GnssNavigationMessage.TYPE_GPS_L1CA) {
    718                 int svid = message.getSvid();
    719                 softAssert.assertTrue("Space Vehicle ID : expected = [1, 32], actual = " +
    720                                 svid,
    721                         svid >= 1 && svid <= 32);
    722                 int dataSize = message.getData().length;
    723                 softAssert.assertTrue("Data size: expected = 40, actual = " + dataSize,
    724                         dataSize == 40);
    725             } else {
    726                 Log.i(TAG, "GnssNavigationMessage (type = " + messageType
    727                         + ") skipped for verification.");
    728             }
    729         }
    730         softAssert.assertAll();
    731     }
    732 
    733     private static String getGnssNavMessageTypes() {
    734         StringBuilder typesStr = new StringBuilder();
    735         for (int type : GNSS_NAVIGATION_MESSAGE_TYPE) {
    736             typesStr.append(String.format("0x%04X", type));
    737             typesStr.append(", ");
    738         }
    739 
    740         return typesStr.length() > 2 ? typesStr.substring(0, typesStr.length() - 2) : "";
    741     }
    742 }
    743