• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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