blob: 0f4775e2fac54c72b3ee64063efd70e9c2d67ac7 [file] [log] [blame]
/*
* Copyright (C) 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.location.cts;
import android.location.GnssMeasurement;
import android.location.GnssMeasurementsEvent;
import android.location.GpsStatus;
import android.util.Log;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
* Test for {@link GnssMeasurement} without a location fix.
*
* Test steps:
* 1. Clear A-GPS: this ensures that the device is not in a warm mode and it has 4+ satellites
* acquired already.
* 2. Register a listener for:
* - {@link GnssMeasurementsEvent}s,
* - location updates and
* - {@link GpsStatus} events.
* 3. Wait for {@link GnssMeasurementsEvent}s to provide {@link EVENTS_COUNT} measurements
* 4. Ensure that zero locations have been received
* 5. Check {@link GnssMeasurementsEvent} status: if the status is not
* {@link GnssMeasurementsEvent#STATUS_READY}, the test will be skipped because one of the
* following reasons:
* 4.1 the device does not support the feature,
* 4.2 GPS Locaiton is disabled in the device && the test is CTS non-verifier
* 6. Check whether the device is deep indoor. This is done by performing the following steps:
* 4.1 If no {@link GpsStatus} is received this will mean that the device is located
* indoor. The test will be skipped if not strict (CTS or pre-2016.)
* 7. When the device is not indoor, verify that we receive {@link GnssMeasurementsEvent}s before
* a GPS location is calculated, and reported by GPS HAL. If {@link GnssMeasurementsEvent}s are
* only received after a location update is received:
* 4.1.1 The test will pass with a warning for the M release.
* 4.1.2 The test will fail on N with CTS-Verifier & newer (2016+) GPS hardware.
* 8. If {@link GnssMeasurementsEvent}s are received: verify all mandatory fields, the test will
* fail if any of the mandatory fields is not populated or in the expected range.
*/
public class GnssMeasurementWhenNoLocationTest extends GnssTestCase {
private static final String TAG = "GnssMeasBeforeLocTest";
private TestGnssMeasurementListener mMeasurementListener;
private TestGpsStatusListener mGpsStatusListener;
private TestLocationListener mLocationListener;
private static final int EVENTS_COUNT = 2;
private static final int LOCATIONS_COUNT = 1;
// Command to delete cached A-GPS data to get a truer GPS fix.
private static final String AGPS_DELETE_COMMAND = "delete_aiding_data";
@Override
protected void setUp() throws Exception {
super.setUp();
mTestLocationManager = new TestLocationManager(getContext());
}
@Override
protected void tearDown() throws Exception {
// Unregister listeners
if (mLocationListener != null) {
mTestLocationManager.removeLocationUpdates(mLocationListener);
}
if (mMeasurementListener != null) {
mTestLocationManager.unregisterGnssMeasurementCallback(mMeasurementListener);
}
if (mGpsStatusListener != null) {
mTestLocationManager.removeGpsStatusListener(mGpsStatusListener);
}
super.tearDown();
}
/**
* Test for GPS measurements before a location fix.
*/
public void testGnssMeasurementWhenNoLocation() throws Exception {
// Checks if GPS hardware feature is present, skips test (pass) if not,
// and hard asserts that Location/GPS (Provider) is turned on if is Cts Verifier.
if (!TestMeasurementUtil.canTestRunOnCurrentDevice(mTestLocationManager,
TAG, MIN_HARDWARE_YEAR_MEASUREMENTS_REQUIRED, isCtsVerifierTest())) {
return;
}
// Clear A-GPS and skip the test if the operation fails.
if (!mTestLocationManager.sendExtraCommand(AGPS_DELETE_COMMAND)) {
Log.i(TAG, "A-GPS failed to clear. Skip test.");
return;
}
// Register for GPS measurements.
mMeasurementListener = new TestGnssMeasurementListener(TAG, EVENTS_COUNT);
mTestLocationManager.registerGnssMeasurementCallback(mMeasurementListener);
// Register for Gps Status updates.
mGpsStatusListener = new TestGpsStatusListener(EVENTS_COUNT, mTestLocationManager);
mTestLocationManager.addGpsStatusListener(mGpsStatusListener);
// Register for location updates.
mLocationListener = new TestLocationListener(LOCATIONS_COUNT);
mTestLocationManager.requestLocationUpdates(mLocationListener);
mMeasurementListener.awaitStatus();
if (!mMeasurementListener.verifyStatus(isMeasurementTestStrict())) {
return; // exit peacefully (if not already asserted out inside verifyStatus)
}
// Wait for two measurement events - this is better than waiting for a location calculation
// because the test generally completes much faster.
mMeasurementListener.await();
Log.i(TAG, "mLocationListener.isLocationReceived(): "
+ mLocationListener.isLocationReceived());
SoftAssert.failOrWarning(isMeasurementTestStrict(),
"No Satellites are visible. Device may be indoors. Retry outdoors?",
mGpsStatusListener.isGpsStatusReceived());
List<GnssMeasurementsEvent> events = mMeasurementListener.getEvents();
Log.i(TAG, "Number of GPS measurement events received = " + events.size());
// Ensure that after getting a few (at least 2) measurements, that we still don't have
// location (i.e. that we got measurements before location.) Fail, if strict, warn, if not.
SoftAssert.failOrWarning(isMeasurementTestStrict(),
"Location was received before " + events.size() +
" GnssMeasurementEvents with measurements were reported. " +
"Test expects at least " + EVENTS_COUNT +
" GnssMeasurementEvents before a location, given the cold start start. " +
"Ensure no other active GPS apps (so the cold start command works) " +
"and retry?",
!mLocationListener.isLocationReceived());
if (mLocationListener.isLocationReceived() && !isMeasurementTestStrict()) {
return; // allow a (passing) return, if not strict, otherwise continue
}
// If device is not indoors, verify
// 1) that we receive GPS measurements before being able to calculate the position solution
// 2) that mandatory fields of GnssMeasurement are in expected ranges.
GnssMeasurementsEvent firstEvent = events.get(0);
Collection<GnssMeasurement> gpsMeasurements = firstEvent.getMeasurements();
int satelliteCount = gpsMeasurements.size();
int[] gpsPrns = new int[satelliteCount];
int i = 0;
for (GnssMeasurement measurement : gpsMeasurements) {
gpsPrns[i] = measurement.getSvid();
++i;
}
Log.i(TAG, "First GnssMeasurementsEvent with PRNs=" + Arrays.toString(gpsPrns));
SoftAssert softAssert = new SoftAssert(TAG);
long timeInNs = firstEvent.getClock().getTimeNanos();
softAssert.assertTrue("GPS measurement satellite count check: ",
timeInNs, // event time in ns
"satelliteCount > 0", // expected value
Integer.toString(satelliteCount), // actual value
satelliteCount > 0); // condition
TestMeasurementUtil.assertGnssClockFields(firstEvent.getClock(), softAssert, timeInNs);
// Verify mandatory fields of GnssMeasurement
for (GnssMeasurement measurement : gpsMeasurements) {
TestMeasurementUtil.assertAllGnssMeasurementMandatoryFields(measurement,
softAssert, timeInNs);
}
softAssert.assertAll();
}
}