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.location.GnssMeasurement; 20 import android.location.GnssMeasurementsEvent; 21 import android.location.GpsStatus; 22 import android.platform.test.annotations.AppModeFull; 23 import android.util.Log; 24 25 import java.util.Arrays; 26 import java.util.Collection; 27 import java.util.List; 28 29 /** 30 * Test for {@link GnssMeasurement} without a location fix. 31 * 32 * Test steps: 33 * 1. Clear A-GPS: this ensures that the device is not in a warm mode and it has 4+ satellites 34 * acquired already. 35 * 2. Register a listener for: 36 * - {@link GnssMeasurementsEvent}s, 37 * - location updates and 38 * - {@link GpsStatus} events. 39 * 3. Wait for {@link GnssMeasurementsEvent}s to provide {@link EVENTS_COUNT} measurements 40 * 4. Ensure that zero locations have been received 41 * 5. Check {@link GnssMeasurementsEvent} status: if the status is not 42 * {@link GnssMeasurementsEvent#STATUS_READY}, the test will be skipped because one of the 43 * following reasons: 44 * 4.1 the device does not support the feature, 45 * 4.2 GPS Locaiton is disabled in the device && the test is CTS non-verifier 46 * 6. Check whether the device is deep indoor. This is done by performing the following steps: 47 * 4.1 If no {@link GpsStatus} is received this will mean that the device is located 48 * indoor. The test will be skipped if not strict (CTS or pre-2016.) 49 * 7. When the device is not indoor, verify that we receive {@link GnssMeasurementsEvent}s before 50 * a GPS location is calculated, and reported by GPS HAL. If {@link GnssMeasurementsEvent}s are 51 * only received after a location update is received: 52 * 4.1.1 The test will pass with a warning for the M release. 53 * 4.1.2 The test will fail on N with CTS-Verifier & newer (2016+) GPS hardware. 54 * 8. If {@link GnssMeasurementsEvent}s are received: verify all mandatory fields, the test will 55 * fail if any of the mandatory fields is not populated or in the expected range. 56 */ 57 public class GnssMeasurementWhenNoLocationTest extends GnssTestCase { 58 59 private static final String TAG = "GnssMeasBeforeLocTest"; 60 private TestGnssMeasurementListener mMeasurementListener; 61 private TestGpsStatusListener mGpsStatusListener; 62 private TestLocationListener mLocationListener; 63 private static final int EVENTS_COUNT = 2; 64 private static final int LOCATIONS_COUNT = 1; 65 66 // Command to delete cached A-GPS data to get a truer GPS fix. 67 private static final String AGPS_DELETE_COMMAND = "delete_aiding_data"; 68 69 @Override 70 protected void setUp() throws Exception { 71 super.setUp(); 72 73 mTestLocationManager = new TestLocationManager(getContext()); 74 } 75 76 @Override 77 protected void tearDown() throws Exception { 78 // Unregister listeners 79 if (mLocationListener != null) { 80 mTestLocationManager.removeLocationUpdates(mLocationListener); 81 } 82 if (mMeasurementListener != null) { 83 mTestLocationManager.unregisterGnssMeasurementCallback(mMeasurementListener); 84 } 85 if (mGpsStatusListener != null) { 86 mTestLocationManager.removeGpsStatusListener(mGpsStatusListener); 87 } 88 super.tearDown(); 89 } 90 91 /** 92 * Test for GPS measurements before a location fix. 93 */ 94 @AppModeFull(reason = "Requires use of extra LocationManager commands") 95 public void testGnssMeasurementWhenNoLocation() throws Exception { 96 // Checks if GPS hardware feature is present, skips test (pass) if not, 97 // and hard asserts that Location/GPS (Provider) is turned on if is Cts Verifier. 98 if (!TestMeasurementUtil.canTestRunOnCurrentDevice(mTestLocationManager, 99 TAG, MIN_HARDWARE_YEAR_MEASUREMENTS_REQUIRED, isCtsVerifierTest())) { 100 return; 101 } 102 103 // Clear A-GPS and skip the test if the operation fails. 104 if (!mTestLocationManager.sendExtraCommand(AGPS_DELETE_COMMAND)) { 105 Log.i(TAG, "A-GPS failed to clear. Skip test."); 106 return; 107 } 108 109 // Register for GPS measurements. 110 mMeasurementListener = new TestGnssMeasurementListener(TAG, EVENTS_COUNT); 111 mTestLocationManager.registerGnssMeasurementCallback(mMeasurementListener); 112 113 // Register for Gps Status updates. 114 mGpsStatusListener = new TestGpsStatusListener(EVENTS_COUNT, mTestLocationManager); 115 mTestLocationManager.addGpsStatusListener(mGpsStatusListener); 116 117 // Register for location updates. 118 mLocationListener = new TestLocationListener(LOCATIONS_COUNT); 119 mTestLocationManager.requestLocationUpdates(mLocationListener); 120 121 mMeasurementListener.awaitStatus(); 122 if (!mMeasurementListener.verifyStatus(isMeasurementTestStrict())) { 123 return; // exit peacefully (if not already asserted out inside verifyStatus) 124 } 125 126 // Wait for two measurement events - this is better than waiting for a location calculation 127 // because the test generally completes much faster. 128 mMeasurementListener.await(); 129 130 Log.i(TAG, "mLocationListener.isLocationReceived(): " 131 + mLocationListener.isLocationReceived()); 132 133 SoftAssert.failOrWarning(isMeasurementTestStrict(), 134 "No Satellites are visible. Device may be indoors. Retry outdoors?", 135 mGpsStatusListener.isGpsStatusReceived()); 136 137 List<GnssMeasurementsEvent> events = mMeasurementListener.getEvents(); 138 Log.i(TAG, "Number of GPS measurement events received = " + events.size()); 139 140 if (events.isEmpty()) { 141 SoftAssert.failOrWarning(isMeasurementTestStrict(), "No measurement events received", 142 false); 143 return; // All of the following checks rely on there being measurements 144 } 145 146 // Ensure that after getting a few (at least 2) measurement events, that we still don't have 147 // location (i.e. that we got measurements before location.) Fail, if strict, warn, if not. 148 SoftAssert.failOrWarning(isMeasurementTestStrict(), 149 "Location was received before " + events.size() + 150 " GnssMeasurementEvents with measurements were reported. " + 151 "Test expects at least " + EVENTS_COUNT + 152 " GnssMeasurementEvents before a location, given the cold start start. " + 153 "Ensure no other active GPS apps (so the cold start command works) " + 154 "and retry?", 155 !mLocationListener.isLocationReceived()); 156 if (mLocationListener.isLocationReceived() && !isMeasurementTestStrict()) { 157 return; // allow a (passing) return, if not strict, otherwise continue 158 } 159 160 // If device has received measurements also verify 161 // that mandatory fields of GnssMeasurement are in expected ranges. 162 GnssMeasurementsEvent firstEvent = events.get(0); 163 Collection<GnssMeasurement> gpsMeasurements = firstEvent.getMeasurements(); 164 int satelliteCount = gpsMeasurements.size(); 165 int[] gpsPrns = new int[satelliteCount]; 166 int i = 0; 167 for (GnssMeasurement measurement : gpsMeasurements) { 168 gpsPrns[i] = measurement.getSvid(); 169 ++i; 170 } 171 Log.i(TAG, "First GnssMeasurementsEvent with PRNs=" + Arrays.toString(gpsPrns)); 172 173 SoftAssert softAssert = new SoftAssert(TAG); 174 long timeInNs = firstEvent.getClock().getTimeNanos(); 175 softAssert.assertTrue("GPS measurement satellite count check: ", 176 timeInNs, // event time in ns 177 "satelliteCount > 0", // expected value 178 Integer.toString(satelliteCount), // actual value 179 satelliteCount > 0); // condition 180 181 TestMeasurementUtil.assertGnssClockFields(firstEvent.getClock(), softAssert, timeInNs); 182 183 // Verify mandatory fields of GnssMeasurement 184 for (GnssMeasurement measurement : gpsMeasurements) { 185 TestMeasurementUtil.assertAllGnssMeasurementMandatoryFields(mTestLocationManager, 186 measurement, softAssert, timeInNs); 187 } 188 softAssert.assertAll(); 189 } 190 } 191