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