| /* |
| * 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); |
| } |
| } |
| } |
| |