1 /* 2 * Copyright (C) 2022 The Android Open Source Project 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 com.android.bedstead.nene.location; 18 19 import static android.app.AppOpsManager.OPSTR_MOCK_LOCATION; 20 21 import static com.android.bedstead.nene.appops.AppOpsMode.DEFAULT; 22 23 import android.app.AppOpsManager; 24 import android.content.Context; 25 import android.location.Location; 26 import android.location.LocationManager; 27 import android.location.provider.ProviderProperties; 28 import android.os.SystemClock; 29 30 import com.android.bedstead.nene.TestApis; 31 import com.android.bedstead.permissions.PermissionContext; 32 33 /** A test location provider on the device. */ 34 public final class LocationProvider implements AutoCloseable { 35 36 private static final Context sContext = TestApis.context().instrumentedContext(); 37 private static final LocationManager sLocationManager = sContext.getSystemService( 38 LocationManager.class); 39 private final String sProviderName; 40 LocationProvider(String provider)41 LocationProvider(String provider) { 42 this.sProviderName = provider; 43 addAndEnableTestProvider(); 44 } 45 46 @Override close()47 public void close() { 48 removeTestProvider(); 49 clearTestProviderLocation(); 50 } 51 addAndEnableTestProvider()52 private void addAndEnableTestProvider() { 53 try (PermissionContext p = TestApis.permissions().withAppOp(OPSTR_MOCK_LOCATION)) { 54 addTestProvider(); 55 enableTestProvider(); 56 } 57 } 58 addTestProvider()59 private void addTestProvider() { 60 sLocationManager.addTestProvider(sProviderName, 61 /* requiresNetwork= */ true, 62 /* requiresSatellite= */ false, 63 /* requiresCell= */ true, 64 /* hasMonetaryCost= */ false, 65 /* supportsAltitude= */ false, 66 /* supportsSpeed= */ false, 67 /* supportsBearing= */ false, 68 ProviderProperties.POWER_USAGE_MEDIUM, 69 ProviderProperties.ACCURACY_COARSE); 70 } 71 enableTestProvider()72 private void enableTestProvider() { 73 sLocationManager.setTestProviderEnabled(sProviderName, /* enabled= */true); 74 } 75 removeTestProvider()76 private void removeTestProvider() { 77 try (PermissionContext p = TestApis.permissions().withAppOp(OPSTR_MOCK_LOCATION)) { 78 sLocationManager.removeTestProvider(sProviderName); 79 } 80 TestApis.packages().instrumented().appOps().set(AppOpsManager.OPSTR_MOCK_LOCATION, DEFAULT); 81 } 82 clearTestProviderLocation()83 private void clearTestProviderLocation() { 84 // This is a work-around for removing the test provider's location. 85 // There is no LocationManager test API to do this. 86 TestApis.location().setLocationEnabled(false); 87 TestApis.location().setLocationEnabled(true); 88 } 89 setLocation(double latitude, double longitude, float accuracy)90 public void setLocation(double latitude, double longitude, float accuracy) { 91 sLocationManager.setTestProviderLocation(sProviderName, 92 createLocation(sProviderName, latitude, longitude, accuracy)); 93 } 94 createLocation(String provider, double latitude, double longitude, float accuracy)95 private static Location createLocation(String provider, double latitude, double longitude, 96 float accuracy) { 97 Location location = new Location(provider); 98 location.setLatitude(latitude); 99 location.setLongitude(longitude); 100 location.setAccuracy(accuracy); 101 location.setTime(System.currentTimeMillis()); 102 location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos()); 103 return location; 104 } 105 } 106