blob: 93a6640f36027177f1ae85b33e0ebd39b073429f [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* 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.privileged;
import android.Manifest;
import android.location.Location;
import android.location.cts.common.GnssTestCase;
import android.location.cts.common.SoftAssert;
import android.location.cts.common.TestLocationListener;
import android.location.cts.common.TestLocationManager;
import android.location.cts.common.TestMeasurementUtil;
import android.os.Build;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
import org.junit.Assert;
/**
* Test the {@link Location} values.
*
* Test steps:
* 1. Register for location updates.
* 2. Wait for {@link #LOCATION_TO_COLLECT_COUNT} locations.
* 3.1 Confirm locations have been found.
* 3. Get LastKnownLocation, verified all fields are in the correct range.
*/
public class GnssLocationValuesTest extends GnssTestCase {
private static final String TAG = "GnssLocationValuesTest";
private static final int LOCATION_TO_COLLECT_COUNT = 5;
private TestLocationListener mLocationListener;
// TODO(b/65458848): Re-tighten the limit to 0.001 when sufficient devices in the market comply
private static final double MINIMUM_SPEED_FOR_BEARING = 1.000;
private static final int MIN_ANDROID_SDK_VERSION_REQUIRED = Build.VERSION_CODES.O;
@Override
protected void setUp() throws Exception {
super.setUp();
InstrumentationRegistry.getInstrumentation().getUiAutomation()
.adoptShellPermissionIdentity(Manifest.permission.LOCATION_HARDWARE);
mTestLocationManager = new TestLocationManager(getContext());
mLocationListener = new TestLocationListener(LOCATION_TO_COLLECT_COUNT);
}
@Override
protected void tearDown() throws Exception {
// Unregister listeners
if (mLocationListener != null) {
mTestLocationManager.removeLocationUpdates(mLocationListener);
}
InstrumentationRegistry.getInstrumentation().getUiAutomation()
.dropShellPermissionIdentity();
super.tearDown();
}
/**
* 1. Get regular GNSS locations to warm up the engine.
* 2. Get low-power GNSS locations.
* 3. Check whether all fields' value make sense.
*/
public void testLowPowerModeGnssLocation() throws Exception {
// Checks if GPS hardware feature is present, skips test (pass) if not,
if (!TestMeasurementUtil.canTestRunOnCurrentDevice(mTestLocationManager, TAG)) {
return;
}
// Get regular GNSS locations to warm up the engine.
waitForRegularGnssLocations();
mTestLocationManager.requestLowPowerModeGnssLocationUpdates(5000, mLocationListener);
waitAndValidateLowPowerLocations();
}
private void waitForRegularGnssLocations() throws InterruptedException {
TestLocationListener locationListener = new TestLocationListener(LOCATION_TO_COLLECT_COUNT);
mTestLocationManager.requestLocationUpdates(locationListener);
boolean success = locationListener.await();
mTestLocationManager.removeLocationUpdates(locationListener);
if (success) {
Log.i(TAG, "Successfully received " + LOCATION_TO_COLLECT_COUNT
+ " regular GNSS locations.");
}
Assert.assertTrue("Time elapsed without getting enough regular GNSS locations."
+ " Possibly, the test has been run deep indoors."
+ " Consider retrying test outdoors.", success);
}
private void waitAndValidateLowPowerLocations() throws InterruptedException {
boolean success = mLocationListener.await();
SoftAssert softAssert = new SoftAssert(TAG);
softAssert.assertTrue(
"Time elapsed without getting the low-power GNSS locations."
+ " Possibly, the test has been run deep indoors."
+ " Consider retrying test outdoors.",
success);
// don't check speed of first GNSS location - it may not be ready in some cases
boolean checkSpeed = false;
for (Location location : mLocationListener.getReceivedLocationList()) {
checkLocationRegularFields(softAssert, location, checkSpeed);
checkSpeed = true;
}
softAssert.assertAll();
}
private static void checkLocationRegularFields(SoftAssert softAssert, Location location,
boolean checkSpeed) {
// For the altitude: the unit is meter
// The lowest exposed land on Earth is at the Dead Sea shore, at -413 meters.
// Whilst University of Tokyo Atacama Obsevatory is on 5,640m above sea level.
softAssert.assertTrue("All GNSS locations generated by the LocationManager "
+ "must have altitudes.", location.hasAltitude());
if (location.hasAltitude()) {
softAssert.assertTrue("Altitude should be greater than -500 (meters).",
location.getAltitude() >= -500);
softAssert.assertTrue("Altitude should be less than 6000 (meters).",
location.getAltitude() < 6000);
}
// It is guaranteed to be in the range [0.0, 360.0] if the device has a bearing.
// The API will return 0.0 if there is no bearing
if (location.hasSpeed() && location.getSpeed() > MINIMUM_SPEED_FOR_BEARING) {
softAssert.assertTrue("When speed is greater than 0, all GNSS locations generated by "
+ "the LocationManager must have bearings.", location.hasBearing());
if (location.hasBearing()) {
softAssert.assertTrue("Bearing should be in the range of [0.0, 360.0]",
location.getBearing() >= 0 && location.getBearing() <= 360);
}
}
softAssert.assertTrue("ElapsedRaltimeNanos should be great than 0.",
location.getElapsedRealtimeNanos() > 0);
assertEquals("gps", location.getProvider());
assertTrue(location.getTime() > 0);
softAssert.assertTrue("Longitude should be in the range of [-180.0, 180.0] degrees",
location.getLongitude() >= -180 && location.getLongitude() <= 180);
softAssert.assertTrue("Latitude should be in the range of [-90.0, 90.0] degrees",
location.getLatitude() >= -90 && location.getLatitude() <= 90);
if (checkSpeed) {
softAssert.assertTrue("All but the first GNSS location from LocationManager "
+ "must have speeds.", location.hasSpeed());
}
// For the speed, during the cts test device shouldn't move faster than 1m/s, but
// allowing up to 5m/s for possible early fix noise in moderate signal test environments.
if (location.hasSpeed()) {
softAssert.assertTrue(
"In the test environment, speed should be in the range of [0, 5] m/s",
location.getSpeed() >= 0 && location.getSpeed() <= 5);
}
}
}