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 package android.location.cts;
     17 
     18 import junit.framework.Assert;
     19 import android.location.GnssClock;
     20 import android.location.GnssMeasurement;
     21 import android.location.GnssMeasurementsEvent;
     22 import android.util.Log;
     23 
     24 import java.util.ArrayList;
     25 import java.util.HashMap;
     26 import java.util.List;
     27 import java.util.concurrent.CountDownLatch;
     28 import java.util.concurrent.TimeUnit;
     29 
     30 /**
     31  * Used for receiving GPS satellite measurements from the GPS engine.
     32  * Each measurement contains raw and computed data identifying a satellite.
     33  * Only counts measurement events with more than one actual Measurement in them (not just clock)
     34  */
     35 class TestGnssMeasurementListener extends GnssMeasurementsEvent.Callback {
     36     // When filterByEventSize flag is true, we only keep the GnssMeasurementsEvents that have at
     37     // least 4 decoded GnssMeasurement in same constellation.
     38     private boolean filterByEventSize = false;
     39     // Timeout in sec for count down latch wait
     40     private static final int STATUS_TIMEOUT_IN_SEC = 10;
     41     private static final int MEAS_TIMEOUT_IN_SEC = 60;
     42     private static final int TOW_DECODED_MEASUREMENT_STATE_BIT = 3;
     43     private static final int C_TO_N0_THRESHOLD_DB_HZ = 18;
     44     private volatile int mStatus = -1;
     45 
     46     private final String mTag;
     47     private final List<GnssMeasurementsEvent> mMeasurementsEvents;
     48     private final CountDownLatch mCountDownLatch;
     49     private final CountDownLatch mCountDownLatchStatus;
     50 
     51     /**
     52     * Constructor for TestGnssMeasurementListener
     53     * @param tag for Logging.
     54     */
     55     TestGnssMeasurementListener(String tag) {
     56         this(tag, 0, false);
     57     }
     58 
     59     /**
     60     * Constructor for TestGnssMeasurementListener
     61     * @param tag for Logging.
     62     * @param eventsToCollect wait until the number of events collected.
     63     */
     64     TestGnssMeasurementListener(String tag, int eventsToCollect) {
     65         this(tag, eventsToCollect, false);
     66     }
     67 
     68     /**
     69     * Constructor for TestGnssMeasurementListener
     70     * @param tag for Logging.
     71     * @param eventsToCollect wait until the number of events collected.
     72     * @param filterByEventSize whether filter the GnssMeasurementsEvents when we collect them.
     73     */
     74     TestGnssMeasurementListener(String tag, int eventsToCollect, boolean filterByEventSize) {
     75         mTag = tag;
     76         mCountDownLatch = new CountDownLatch(eventsToCollect);
     77         mCountDownLatchStatus = new CountDownLatch(1);
     78         mMeasurementsEvents = new ArrayList<>(eventsToCollect);
     79         this.filterByEventSize = filterByEventSize;
     80     }
     81 
     82     @Override
     83     public void onGnssMeasurementsReceived(GnssMeasurementsEvent event) {
     84         // Only count measurement events with more than 4 actual Measurements in same constellation
     85         // with Cn0DbHz value greater than 18
     86         if (event.getMeasurements().size() > 0) {
     87             Log.i(mTag, "GnssMeasurementsEvent size:" + event.getMeasurements().size());
     88             if (filterByEventSize) {
     89                 HashMap<Integer, Integer> constellationEventCount = new HashMap<>();
     90                 GnssClock gnssClock = event.getClock();
     91                 if (!gnssClock.hasFullBiasNanos()) {
     92                     // If devices does not have FullBiasNanos yet, it will be difficult to check the quality, so await
     93                     // this flag as well.
     94                     return;
     95                 }
     96                 for (GnssMeasurement gnssMeasurement : event.getMeasurements()){
     97                     int constellationType = gnssMeasurement.getConstellationType();
     98                     // if the measurement's signal level is too small ignore
     99                     if (gnssMeasurement.getCn0DbHz() < C_TO_N0_THRESHOLD_DB_HZ ||
    100                         (gnssMeasurement.getState() & (1L << TOW_DECODED_MEASUREMENT_STATE_BIT)) == 0) {
    101                         continue;
    102                     }
    103                     if (constellationEventCount.containsKey(constellationType)) {
    104                         constellationEventCount.put(constellationType,
    105                             constellationEventCount.get(constellationType) + 1);
    106                     }
    107                     else {
    108                         constellationEventCount.put(constellationType, 1);
    109                     }
    110                     if (constellationEventCount.get(constellationType) >= 4) {
    111                         synchronized(mMeasurementsEvents) {
    112                             mMeasurementsEvents.add(event);
    113                         }
    114                         mCountDownLatch.countDown();
    115                         return;
    116                     }
    117                 }
    118             }
    119             else {
    120                 synchronized(mMeasurementsEvents) {
    121                     mMeasurementsEvents.add(event);
    122                 }
    123                 mCountDownLatch.countDown();
    124             }
    125         }
    126     }
    127 
    128     @Override
    129     public void onStatusChanged(int status) {
    130         mStatus = status;
    131         mCountDownLatchStatus.countDown();
    132     }
    133 
    134     public boolean awaitStatus() throws InterruptedException {
    135         return TestUtils.waitFor(mCountDownLatchStatus, STATUS_TIMEOUT_IN_SEC);
    136     }
    137 
    138     public boolean await() throws InterruptedException {
    139         return TestUtils.waitFor(mCountDownLatch, MEAS_TIMEOUT_IN_SEC);
    140     }
    141 
    142 
    143     /**
    144      * @return {@code true} if the state of the test ensures that data is expected to be collected,
    145      *         {@code false} otherwise.
    146      */
    147     public boolean verifyStatus(boolean testIsStrict) {
    148         switch (getStatus()) {
    149             case GnssMeasurementsEvent.Callback.STATUS_NOT_SUPPORTED:
    150                 String message = "GnssMeasurements is not supported in the device:"
    151                         + " verifications performed by this test may be skipped on older devices.";
    152                 if (testIsStrict) {
    153                     Assert.fail(message);
    154                 } else {
    155                     SoftAssert.failAsWarning(mTag, message);
    156                 }
    157                 return false;
    158             case GnssMeasurementsEvent.Callback.STATUS_READY:
    159                 return true;
    160             case GnssMeasurementsEvent.Callback.STATUS_LOCATION_DISABLED:
    161                 message =  "Location or GPS is disabled on the device:"
    162                         + " enable location to continue the test";
    163                 if (testIsStrict) {
    164                     Assert.fail(message);
    165                 } else {
    166                     SoftAssert.failAsWarning(mTag, message);
    167                 }
    168                 return false;
    169             default:
    170                 Assert.fail("GnssMeasurementsEvent status callback was not received.");
    171         }
    172         return false;
    173     }
    174 
    175     /**
    176      * Get GPS Measurements Status.
    177      *
    178      * @return mStatus Gps Measurements Status
    179      */
    180     public int getStatus() {
    181         return mStatus;
    182     }
    183 
    184     /**
    185      * Get the current list of GPS Measurements Events.
    186      *
    187      * @return the current list of GPS Measurements Events
    188      */
    189     public List<GnssMeasurementsEvent> getEvents() {
    190         synchronized(mMeasurementsEvents) {
    191             List<GnssMeasurementsEvent> clone = new ArrayList<>();
    192             clone.addAll(mMeasurementsEvents);
    193             return clone;
    194         }
    195     }
    196 }
    197