blob: f1f2d2abea3f60cf2842c2e5664ef51ef446580a [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 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
17package com.android.server;
18
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -080019import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
20import static android.Manifest.permission.ACCESS_FINE_LOCATION;
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -080021import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
22import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
Maggieaa080f92018-01-04 15:35:11 -080023import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -080024import static android.location.LocationManager.FUSED_PROVIDER;
25import static android.location.LocationManager.GPS_PROVIDER;
26import static android.location.LocationManager.NETWORK_PROVIDER;
27import static android.location.LocationManager.PASSIVE_PROVIDER;
Kweku Adams4fb074e2019-02-01 16:03:27 -080028import static android.os.PowerManager.locationPowerSaveModeToString;
Maggieaa080f92018-01-04 15:35:11 -080029
Wei Wang980b7c22018-12-06 17:53:00 -080030import android.Manifest;
Wyatt Rileycf879db2017-01-12 13:57:38 -080031import android.annotation.NonNull;
Wyatt Riley49097c02018-03-15 09:14:43 -070032import android.annotation.Nullable;
Maggieaa080f92018-01-04 15:35:11 -080033import android.app.ActivityManager;
34import android.app.AppOpsManager;
35import android.app.PendingIntent;
36import android.content.BroadcastReceiver;
Maggieaa080f92018-01-04 15:35:11 -080037import android.content.Context;
38import android.content.Intent;
39import android.content.IntentFilter;
Maggieaa080f92018-01-04 15:35:11 -080040import android.content.pm.PackageManager;
Maggieaa080f92018-01-04 15:35:11 -080041import android.location.Address;
42import android.location.Criteria;
43import android.location.GeocoderParams;
44import android.location.Geofence;
gomo226b7b72018-12-12 16:49:39 -080045import android.location.GnssMeasurementCorrections;
Maggieaa080f92018-01-04 15:35:11 -080046import android.location.IBatchedLocationCallback;
47import android.location.IGnssMeasurementsListener;
48import android.location.IGnssNavigationMessageListener;
49import android.location.IGnssStatusListener;
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -080050import android.location.IGpsGeofenceHardware;
Maggieaa080f92018-01-04 15:35:11 -080051import android.location.ILocationListener;
52import android.location.ILocationManager;
Maggieaa080f92018-01-04 15:35:11 -080053import android.location.Location;
54import android.location.LocationManager;
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -080055import android.location.LocationManagerInternal;
Maggieaa080f92018-01-04 15:35:11 -080056import android.location.LocationRequest;
Chad Brubakerf1133332019-03-15 14:13:59 -070057import android.location.LocationTime;
Maggieaa080f92018-01-04 15:35:11 -080058import android.os.Binder;
59import android.os.Bundle;
Soonil Nagarkar905e7222019-10-01 12:03:29 -070060import android.os.CancellationSignal;
Maggieaa080f92018-01-04 15:35:11 -080061import android.os.Handler;
62import android.os.IBinder;
Soonil Nagarkar905e7222019-10-01 12:03:29 -070063import android.os.ICancellationSignal;
Maggieaa080f92018-01-04 15:35:11 -080064import android.os.PowerManager;
Kweku Adams4fb074e2019-02-01 16:03:27 -080065import android.os.PowerManager.ServiceType;
66import android.os.PowerManagerInternal;
Maggieaa080f92018-01-04 15:35:11 -080067import android.os.Process;
68import android.os.RemoteException;
69import android.os.SystemClock;
70import android.os.UserHandle;
Maggieaa080f92018-01-04 15:35:11 -080071import android.os.WorkSource;
Narayan Kamath32684dd2018-01-08 17:32:51 +000072import android.os.WorkSource.WorkChain;
Hongyi Zhang700137e2019-05-23 21:19:36 -070073import android.stats.location.LocationStatsEnums;
Maggieaa080f92018-01-04 15:35:11 -080074import android.text.TextUtils;
Maggieaa080f92018-01-04 15:35:11 -080075import android.util.EventLog;
76import android.util.Log;
77import android.util.Slog;
Soonil Nagarkar06e37f62019-12-04 16:05:08 -080078import android.util.SparseArray;
WyattRileyba6072f2019-04-18 07:37:52 -070079import android.util.TimeUtils;
Yu-Han Yanga4d250e2018-10-02 21:29:20 -070080
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -080081import com.android.internal.annotations.GuardedBy;
destradaaea8a8a62014-06-23 18:19:03 -070082import com.android.internal.content.PackageMonitor;
83import com.android.internal.location.ProviderProperties;
84import com.android.internal.location.ProviderRequest;
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -080085import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060086import com.android.internal.util.DumpUtils;
Soonil Nagarkar1c572552019-07-10 13:31:47 -070087import com.android.internal.util.IndentingPrintWriter;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -080088import com.android.internal.util.Preconditions;
Soonil Nagarkar1575a042018-10-24 17:54:54 -070089import com.android.server.location.AbstractLocationProvider;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -080090import com.android.server.location.AbstractLocationProvider.State;
Anil Admal08b96122019-01-30 16:55:05 -080091import com.android.server.location.CallerIdentity;
destradaaea8a8a62014-06-23 18:19:03 -070092import com.android.server.location.GeocoderProxy;
93import com.android.server.location.GeofenceManager;
94import com.android.server.location.GeofenceProxy;
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -080095import com.android.server.location.HardwareActivityRecognitionProxy;
destradaaea8a8a62014-06-23 18:19:03 -070096import com.android.server.location.LocationFudger;
destradaaea8a8a62014-06-23 18:19:03 -070097import com.android.server.location.LocationProviderProxy;
98import com.android.server.location.LocationRequestStatistics;
99import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
100import com.android.server.location.LocationRequestStatistics.PackageStatistics;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700101import com.android.server.location.LocationSettingsStore;
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800102import com.android.server.location.LocationUsageLogger;
destradaaea8a8a62014-06-23 18:19:03 -0700103import com.android.server.location.MockProvider;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800104import com.android.server.location.MockableLocationProvider;
destradaaea8a8a62014-06-23 18:19:03 -0700105import com.android.server.location.PassiveProvider;
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800106import com.android.server.location.UserInfoStore;
Soonil Nagarkarf20d10e2020-01-27 11:05:40 -0800107import com.android.server.location.gnss.GnssManagerService;
Todd Kennedy583378d2019-07-12 06:50:30 -0700108import com.android.server.pm.permission.PermissionManagerServiceInternal;
Yu-Han Yanga4d250e2018-10-02 21:29:20 -0700109
Soonil Nagarkarae6ce772019-05-01 13:16:17 -0700110import java.io.ByteArrayOutputStream;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400111import java.io.FileDescriptor;
Soonil Nagarkarae6ce772019-05-01 13:16:17 -0700112import java.io.PrintStream;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400113import java.io.PrintWriter;
114import java.util.ArrayList;
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -0800115import java.util.Collections;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400116import java.util.HashMap;
117import java.util.HashSet;
118import java.util.List;
119import java.util.Map;
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800120import java.util.Map.Entry;
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +0000121import java.util.Objects;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800122import java.util.Set;
WyattRileyd6b82a62019-12-30 18:12:50 -0800123import java.util.TreeMap;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800124import java.util.concurrent.CopyOnWriteArrayList;
Soonil Nagarkar905e7222019-10-01 12:03:29 -0700125import java.util.concurrent.TimeUnit;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126
127/**
128 * The service class that manages LocationProviders and issues location
129 * updates and alerts.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130 */
Victoria Lease5cd731a2012-12-19 15:04:21 -0800131public class LocationManagerService extends ILocationManager.Stub {
Soonil Nagarkar141417a2019-10-28 11:12:48 -0700132
133 /**
134 * Controls lifecycle of LocationManagerService.
135 */
136 public static class Lifecycle extends SystemService {
137
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800138 private final LocationManagerService mService;
Soonil Nagarkar141417a2019-10-28 11:12:48 -0700139
140 public Lifecycle(Context context) {
141 super(context);
142 mService = new LocationManagerService(context);
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800143 LocalServices.addService(LocationManagerInternal.class, mService.new LocalService());
Soonil Nagarkar141417a2019-10-28 11:12:48 -0700144 }
145
146 @Override
147 public void onStart() {
148 publishBinderService(Context.LOCATION_SERVICE, mService);
149 }
150
151 @Override
152 public void onBootPhase(int phase) {
Soonil Nagarkar37096062019-11-25 13:24:48 -0800153 if (phase == PHASE_SYSTEM_SERVICES_READY) {
154 // the location service must be functioning after this boot phase
155 mService.onSystemReady();
156 } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
157 // some providers rely on third party code, so we wait to initialize
158 // providers until third party code is allowed to run
159 mService.onSystemThirdPartyAppsCanStart();
Soonil Nagarkar141417a2019-10-28 11:12:48 -0700160 }
161 }
162 }
163
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800164 public static final String TAG = "LocationManagerService";
JP Abgrallf79811e72013-02-01 18:45:05 -0800165 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700166
Olivier Gaillard7a222662017-11-20 16:07:24 +0000167 private static final String WAKELOCK_KEY = "*location*";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168
Victoria Lease37425c32012-10-16 16:08:48 -0700169 private static final int RESOLUTION_LEVEL_NONE = 0;
Victoria Lease37425c32012-10-16 16:08:48 -0700170 private static final int RESOLUTION_LEVEL_COARSE = 1;
Victoria Lease37425c32012-10-16 16:08:48 -0700171 private static final int RESOLUTION_LEVEL_FINE = 2;
172
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700173 private static final String NETWORK_LOCATION_SERVICE_ACTION =
Stan Chesnutt39062dd2013-07-22 14:33:30 -0700174 "com.android.location.service.v3.NetworkLocationProvider";
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700175 private static final String FUSED_LOCATION_SERVICE_ACTION =
176 "com.android.location.service.FusedLocationProvider";
177
David Christie0b837452013-07-29 16:02:13 -0700178 // The maximum interval a location request can have and still be considered "high power".
179 private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
180
Soonil Nagarkar905e7222019-10-01 12:03:29 -0700181 // maximum age of a location before it is no longer considered "current"
182 private static final long MAX_CURRENT_LOCATION_AGE_MS = 10 * 1000;
183
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700184 private static final int FOREGROUND_IMPORTANCE_CUTOFF
gomo48f1a642017-11-10 20:35:46 -0800185 = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700186
Nick Pellyf1be6862012-05-15 10:53:42 -0700187 // Location Providers may sometimes deliver location updates
188 // slightly faster that requested - provide grace period so
189 // we don't unnecessarily filter events that are otherwise on
190 // time
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700191 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
Nick Pellyf1be6862012-05-15 10:53:42 -0700192
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700193 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
194
Soonil Nagarkar68257742019-01-09 19:42:34 +0000195 private final Object mLock = new Object();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800196 private final Context mContext;
197 private final Handler mHandler;
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800198 private final UserInfoStore mUserInfoStore;
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800199 private final LocationSettingsStore mSettingsStore;
200 private final LocationUsageLogger mLocationUsageLogger;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700201
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800202 private final PassiveLocationProviderManager mPassiveManager;
203
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800204 private AppOpsManager mAppOps;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700205 private PackageManager mPackageManager;
Victoria Lease0aa28602013-05-29 15:28:26 -0700206 private PowerManager mPowerManager;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800207 private ActivityManager mActivityManager;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800208
209 private GeofenceManager mGeofenceManager;
210 private LocationFudger mLocationFudger;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700211 private GeocoderProxy mGeocodeProvider;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800212 @Nullable private GnssManagerService mGnssManagerService;
213
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800214 @GuardedBy("mLock")
Wei Wang114922a2019-01-30 18:19:35 -0800215 private String mExtraLocationControllerPackage;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800216 @GuardedBy("mLock")
Wei Wang114922a2019-01-30 18:19:35 -0800217 private boolean mExtraLocationControllerPackageEnabled;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700218
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800219 // @GuardedBy("mLock")
220 // hold lock for write or to prevent write, no lock for read
221 private final CopyOnWriteArrayList<LocationProviderManager> mProviderManagers =
222 new CopyOnWriteArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800224 @GuardedBy("mLock")
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800225 private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700226 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800227 new HashMap<>();
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700228
David Christie2ff96af2014-01-30 16:09:37 -0800229 private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics();
230
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700231 // mapping from provider name to last known location
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800232 @GuardedBy("mLock")
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800233 private final HashMap<String, Location> mLastLocation = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234
David Christie1b9b7b12013-04-15 15:31:11 -0700235 // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
236 // locations stored here are not fudged for coarse permissions.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800237 @GuardedBy("mLock")
David Christie1b9b7b12013-04-15 15:31:11 -0700238 private final HashMap<String, Location> mLastLocationCoarseInterval =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800239 new HashMap<>();
David Christie1b9b7b12013-04-15 15:31:11 -0700240
Kweku Adams4fb074e2019-02-01 16:03:27 -0800241 @GuardedBy("mLock")
242 @PowerManager.LocationPowerSaveMode
243 private int mBatterySaverMode;
244
Soonil Nagarkar141417a2019-10-28 11:12:48 -0700245 private LocationManagerService(Context context) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700246 mContext = context;
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -0800247 mHandler = FgThread.getHandler();
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800248 mUserInfoStore = new UserInfoStore(mContext);
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800249 mSettingsStore = new LocationSettingsStore(mContext, mHandler);
Hongyi Zhang700137e2019-05-23 21:19:36 -0700250 mLocationUsageLogger = new LocationUsageLogger();
The Android Open Source Project4df24232009-03-05 14:34:35 -0800251
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800252 // set up passive provider - we do this early because it has no dependencies on system
253 // services or external code that isn't ready yet, and because this allows the variable to
254 // be final. other more complex providers are initialized later, when system services are
255 // ready
256 mPassiveManager = new PassiveLocationProviderManager();
257 mProviderManagers.add(mPassiveManager);
258 mPassiveManager.setRealProvider(new PassiveProvider(mContext));
259
Svet Ganovadc1cf42015-06-15 16:36:24 -0700260 // Let the package manager query which are the default location
261 // providers as they get certain permissions granted by default.
Todd Kennedy583378d2019-07-12 06:50:30 -0700262 PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
263 PermissionManagerServiceInternal.class);
264 permissionManagerInternal.setLocationPackagesProvider(
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700265 userId -> mContext.getResources().getStringArray(
266 com.android.internal.R.array.config_locationProviderPackageNames));
Todd Kennedy583378d2019-07-12 06:50:30 -0700267 permissionManagerInternal.setLocationExtraPackagesProvider(
Wei Wangffb94e62019-01-14 00:05:45 -0800268 userId -> mContext.getResources().getStringArray(
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700269 com.android.internal.R.array.config_locationExtraPackageNames));
Svet Ganovadc1cf42015-06-15 16:36:24 -0700270
Soonil Nagarkar37096062019-11-25 13:24:48 -0800271 // most startup is deferred until systemReady()
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700272 }
273
Soonil Nagarkar37096062019-11-25 13:24:48 -0800274 private void onSystemReady() {
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800275 mUserInfoStore.onSystemReady();
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800276 mSettingsStore.onSystemReady();
277
Soonil Nagarkar68257742019-01-09 19:42:34 +0000278 synchronized (mLock) {
Soonil Nagarkar37096062019-11-25 13:24:48 -0800279 mPackageManager = mContext.getPackageManager();
280 mAppOps = mContext.getSystemService(AppOpsManager.class);
281 mPowerManager = mContext.getSystemService(PowerManager.class);
282 mActivityManager = mContext.getSystemService(ActivityManager.class);
Soonil Nagarkar37096062019-11-25 13:24:48 -0800283
Soonil Nagarkar37096062019-11-25 13:24:48 -0800284 mLocationFudger = new LocationFudger(mContext, mHandler);
285 mGeofenceManager = new GeofenceManager(mContext, mSettingsStore);
286
287 PowerManagerInternal localPowerManager =
288 LocalServices.getService(PowerManagerInternal.class);
289
290 // add listeners
291 mAppOps.startWatchingMode(
292 AppOpsManager.OP_COARSE_LOCATION,
293 null,
294 AppOpsManager.WATCH_FOREGROUND_CHANGES,
295 new AppOpsManager.OnOpChangedInternalListener() {
296 public void onOpChanged(int op, String packageName) {
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800297 // onOpChanged invoked on ui thread, move to our thread to reduce risk
298 // of blocking ui thread
Soonil Nagarkar37096062019-11-25 13:24:48 -0800299 mHandler.post(() -> {
300 synchronized (mLock) {
301 onAppOpChangedLocked();
302 }
303 });
304 }
305 });
306 mPackageManager.addOnPermissionsChangeListener(
307 uid -> {
308 // listener invoked on ui thread, move to our thread to reduce risk of
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800309 // blocking ui thread
Soonil Nagarkar37096062019-11-25 13:24:48 -0800310 mHandler.post(() -> {
311 synchronized (mLock) {
312 onPermissionsChangedLocked();
313 }
314 });
315 });
316 mActivityManager.addOnUidImportanceListener(
317 (uid, importance) -> {
318 // listener invoked on ui thread, move to our thread to reduce risk of
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800319 // blocking ui thread
Soonil Nagarkar37096062019-11-25 13:24:48 -0800320 mHandler.post(() -> {
321 synchronized (mLock) {
322 onUidImportanceChangedLocked(uid, importance);
323 }
324 });
325 },
326 FOREGROUND_IMPORTANCE_CUTOFF);
327
328 localPowerManager.registerLowPowerModeObserver(ServiceType.LOCATION,
329 state -> {
330 // listener invoked on ui thread, move to our thread to reduce risk of
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800331 // blocking ui thread
Soonil Nagarkar37096062019-11-25 13:24:48 -0800332 mHandler.post(() -> {
333 synchronized (mLock) {
334 onBatterySaverModeChangedLocked(state.locationMode);
335 }
336 });
337 });
338 mBatterySaverMode = mPowerManager.getLocationPowerSaveMode();
339
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800340 mSettingsStore.addOnLocationEnabledChangedListener((userId) -> {
Soonil Nagarkar37096062019-11-25 13:24:48 -0800341 synchronized (mLock) {
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800342 onLocationModeChangedLocked(userId);
Soonil Nagarkar37096062019-11-25 13:24:48 -0800343 }
344 });
Soonil Nagarkar37096062019-11-25 13:24:48 -0800345 mSettingsStore.addOnBackgroundThrottleIntervalChangedListener(() -> {
346 synchronized (mLock) {
347 onBackgroundThrottleIntervalChangedLocked();
348 }
349 });
350 mSettingsStore.addOnBackgroundThrottlePackageWhitelistChangedListener(() -> {
351 synchronized (mLock) {
352 onBackgroundThrottleWhitelistChangedLocked();
353 }
354 });
355 mSettingsStore.addOnIgnoreSettingsPackageWhitelistChangedListener(() -> {
356 synchronized (mLock) {
357 onIgnoreSettingsWhitelistChangedLocked();
358 }
359 });
360
361 new PackageMonitor() {
362 @Override
363 public void onPackageDisappeared(String packageName, int reason) {
364 synchronized (mLock) {
365 LocationManagerService.this.onPackageDisappearedLocked(packageName);
366 }
367 }
368 }.register(mContext, mHandler.getLooper(), true);
369
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800370 mUserInfoStore.addListener((oldUserId, newUserId) -> {
371 synchronized (mLock) {
372 onUserChangedLocked(oldUserId, newUserId);
373 }
374 });
375
Soonil Nagarkar37096062019-11-25 13:24:48 -0800376 IntentFilter intentFilter = new IntentFilter();
Soonil Nagarkar37096062019-11-25 13:24:48 -0800377 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
378 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
379
380 mContext.registerReceiverAsUser(new BroadcastReceiver() {
381 @Override
382 public void onReceive(Context context, Intent intent) {
383 final String action = intent.getAction();
384 if (action == null) {
385 return;
386 }
387 synchronized (mLock) {
388 switch (action) {
Soonil Nagarkar37096062019-11-25 13:24:48 -0800389 case Intent.ACTION_SCREEN_ON:
390 case Intent.ACTION_SCREEN_OFF:
391 onScreenStateChangedLocked();
392 break;
393 }
394 }
395 }
396 }, UserHandle.ALL, intentFilter, null, mHandler);
397
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800398 // switching the user from null to current here performs the bulk of the initialization
Soonil Nagarkar37096062019-11-25 13:24:48 -0800399 // work. the user being changed will cause a reload of all user specific settings, which
400 // causes initialization, and propagates changes until a steady state is reached
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800401 onUserChangedLocked(UserHandle.USER_NULL, mUserInfoStore.getCurrentUserId());
Victoria Lease5cd731a2012-12-19 15:04:21 -0800402 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800403 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700404
Soonil Nagarkar37096062019-11-25 13:24:48 -0800405 private void onSystemThirdPartyAppsCanStart() {
406 synchronized (mLock) {
407 // prepare providers
408 initializeProvidersLocked();
409 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700410 }
411
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800412 @GuardedBy("mLock")
413 private void onAppOpChangedLocked() {
414 for (Receiver receiver : mReceivers.values()) {
415 receiver.updateMonitoring(true);
416 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800417 for (LocationProviderManager manager : mProviderManagers) {
418 applyRequirementsLocked(manager);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800419 }
420 }
421
422 @GuardedBy("mLock")
423 private void onPermissionsChangedLocked() {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800424 for (LocationProviderManager manager : mProviderManagers) {
425 applyRequirementsLocked(manager);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800426 }
427 }
428
429 @GuardedBy("mLock")
Kweku Adams4fb074e2019-02-01 16:03:27 -0800430 private void onBatterySaverModeChangedLocked(int newLocationMode) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700431 if (mBatterySaverMode == newLocationMode) {
432 return;
433 }
434
Kweku Adams4fb074e2019-02-01 16:03:27 -0800435 if (D) {
436 Slog.d(TAG,
437 "Battery Saver location mode changed from "
438 + locationPowerSaveModeToString(mBatterySaverMode) + " to "
439 + locationPowerSaveModeToString(newLocationMode));
440 }
441
Kweku Adams4fb074e2019-02-01 16:03:27 -0800442 mBatterySaverMode = newLocationMode;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700443
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800444 for (LocationProviderManager manager : mProviderManagers) {
445 applyRequirementsLocked(manager);
Kweku Adams4fb074e2019-02-01 16:03:27 -0800446 }
447 }
448
449 @GuardedBy("mLock")
450 private void onScreenStateChangedLocked() {
451 if (mBatterySaverMode == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800452 for (LocationProviderManager manager : mProviderManagers) {
453 applyRequirementsLocked(manager);
Kweku Adams4fb074e2019-02-01 16:03:27 -0800454 }
455 }
456 }
457
458 @GuardedBy("mLock")
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800459 private void onLocationModeChangedLocked(int userId) {
460 if (D) {
461 Log.d(TAG, "[u" + userId + "] location enabled = " + isLocationEnabledForUser(userId));
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800462 }
463
Soonil Nagarkardbd467e2020-01-14 15:10:45 -0800464 Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION)
465 .putExtra(LocationManager.EXTRA_LOCATION_ENABLED, isLocationEnabledForUser(userId))
466 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
467 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800468 mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800469
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800470 for (LocationProviderManager manager : mProviderManagers) {
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800471 manager.onEnabledChangedLocked(userId);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800472 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800473 }
474
475 @GuardedBy("mLock")
476 private void onPackageDisappearedLocked(String packageName) {
477 ArrayList<Receiver> deadReceivers = null;
478
479 for (Receiver receiver : mReceivers.values()) {
Anil Admal08b96122019-01-30 16:55:05 -0800480 if (receiver.mCallerIdentity.mPackageName.equals(packageName)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800481 if (deadReceivers == null) {
482 deadReceivers = new ArrayList<>();
483 }
484 deadReceivers.add(receiver);
485 }
486 }
487
488 // perform removal outside of mReceivers loop
489 if (deadReceivers != null) {
490 for (Receiver receiver : deadReceivers) {
491 removeUpdatesLocked(receiver);
492 }
493 }
494 }
495
496 @GuardedBy("mLock")
497 private void onUidImportanceChangedLocked(int uid, int importance) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700498 boolean foreground = LocationManagerServiceUtils.isImportanceForeground(importance);
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700499 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800500 for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
501 String provider = entry.getKey();
502 for (UpdateRecord record : entry.getValue()) {
Anil Admal08b96122019-01-30 16:55:05 -0800503 if (record.mReceiver.mCallerIdentity.mUid == uid
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800504 && record.mIsForegroundUid != foreground) {
gomo48f1a642017-11-10 20:35:46 -0800505 if (D) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800506 Log.d(TAG, "request from uid " + uid + " is now "
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700507 + LocationManagerServiceUtils.foregroundAsString(
508 foreground));
gomo48f1a642017-11-10 20:35:46 -0800509 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800510 record.updateForeground(foreground);
511
Anil Admal08b96122019-01-30 16:55:05 -0800512 if (!isThrottlingExemptLocked(record.mReceiver.mCallerIdentity)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800513 affectedProviders.add(provider);
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700514 }
515 }
516 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800517 }
518 for (String provider : affectedProviders) {
519 applyRequirementsLocked(provider);
520 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800521 }
522
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800523 @GuardedBy("mLock")
524 private void onBackgroundThrottleIntervalChangedLocked() {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800525 for (LocationProviderManager manager : mProviderManagers) {
526 applyRequirementsLocked(manager);
Soonil Nagarkar68257742019-01-09 19:42:34 +0000527 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -0800528 }
529
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800530 @GuardedBy("mLock")
531 private void onBackgroundThrottleWhitelistChangedLocked() {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800532 for (LocationProviderManager manager : mProviderManagers) {
533 applyRequirementsLocked(manager);
Soonil Nagarkar68257742019-01-09 19:42:34 +0000534 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -0800535 }
536
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800537 @GuardedBy("lock")
538 private void onIgnoreSettingsWhitelistChangedLocked() {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800539 for (LocationProviderManager manager : mProviderManagers) {
540 applyRequirementsLocked(manager);
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800541 }
542 }
543
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800544 @GuardedBy("mLock")
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800545 private void initializeProvidersLocked() {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700546 if (GnssManagerService.isGnssSupported()) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800547 mGnssManagerService = new GnssManagerService(this, mContext, mLocationUsageLogger);
548 LocationProviderManager gnssManager = new LocationProviderManager(GPS_PROVIDER);
549 mProviderManagers.add(gnssManager);
550 gnssManager.setRealProvider(mGnssManagerService.getGnssLocationProvider());
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700551 }
552
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800553 LocationProviderProxy networkProvider = LocationProviderProxy.createAndRegister(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700554 mContext,
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700555 NETWORK_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700556 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800557 com.android.internal.R.string.config_networkLocationProviderPackageName);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700558 if (networkProvider != null) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800559 LocationProviderManager networkManager = new LocationProviderManager(NETWORK_PROVIDER);
560 mProviderManagers.add(networkManager);
561 networkManager.setRealProvider(networkProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700562 } else {
gomo48f1a642017-11-10 20:35:46 -0800563 Slog.w(TAG, "no network location provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700564 }
565
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800566 // ensure that a fused provider exists which will work in direct boot
567 Preconditions.checkState(!mContext.getPackageManager().queryIntentServicesAsUser(
568 new Intent(FUSED_LOCATION_SERVICE_ACTION),
569 MATCH_DIRECT_BOOT_AWARE | MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM).isEmpty(),
570 "Unable to find a direct boot aware fused location provider");
571
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700572 // bind to fused provider
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800573 LocationProviderProxy fusedProvider = LocationProviderProxy.createAndRegister(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700574 mContext,
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700575 FUSED_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700576 com.android.internal.R.bool.config_enableFusedLocationOverlay,
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800577 com.android.internal.R.string.config_fusedLocationProviderPackageName);
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700578 if (fusedProvider != null) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800579 LocationProviderManager fusedManager = new LocationProviderManager(FUSED_PROVIDER);
580 mProviderManagers.add(fusedManager);
581 fusedManager.setRealProvider(fusedProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700582 } else {
583 Slog.e(TAG, "no fused location provider found",
584 new IllegalStateException("Location service needs a fused location provider"));
585 }
586
587 // bind to geocoder provider
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800588 mGeocodeProvider = GeocoderProxy.createAndRegister(mContext);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700589 if (mGeocodeProvider == null) {
gomo48f1a642017-11-10 20:35:46 -0800590 Slog.e(TAG, "no geocoder provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700591 }
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700592
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800593 // bind to geofence proxy
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700594 if (mGnssManagerService != null) {
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800595 IGpsGeofenceHardware gpsGeofenceHardware = mGnssManagerService.getGpsGeofenceProxy();
596 if (gpsGeofenceHardware != null) {
597 GeofenceProxy provider = GeofenceProxy.createAndBind(mContext, gpsGeofenceHardware);
598 if (provider == null) {
599 Slog.d(TAG, "unable to bind to GeofenceProxy");
600 }
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700601 }
destradaa0682809a2013-08-12 18:50:30 -0700602 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900603
Brian Duddiecfa5b5b2019-01-22 18:01:40 +0000604 // bind to hardware activity recognition
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800605 HardwareActivityRecognitionProxy hardwareActivityRecognitionProxy =
606 HardwareActivityRecognitionProxy.createAndRegister(mContext);
607 if (hardwareActivityRecognitionProxy == null) {
608 Log.e(TAG, "unable to bind ActivityRecognitionProxy");
Brian Duddiecfa5b5b2019-01-22 18:01:40 +0000609 }
610
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800611 String[] testProviderStrings = mContext.getResources().getStringArray(
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900612 com.android.internal.R.array.config_testLocationProviders);
613 for (String testProviderString : testProviderStrings) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -0800614 String[] fragments = testProviderString.split(",");
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900615 String name = fragments[0].trim();
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900616 ProviderProperties properties = new ProviderProperties(
617 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
618 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
619 Boolean.parseBoolean(fragments[3]) /* requiresCell */,
620 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
621 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
622 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
623 Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
624 Integer.parseInt(fragments[8]) /* powerRequirement */,
625 Integer.parseInt(fragments[9]) /* accuracy */);
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800626 addTestProvider(name, properties, mContext.getOpPackageName());
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900627 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700628 }
Mike Lockwood9637d472009-04-02 21:41:57 -0700629
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800630 @GuardedBy("mLock")
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800631 private void onUserChangedLocked(int oldUserId, int newUserId) {
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800632 if (D) {
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800633 Log.d(TAG, "foreground user is changing to " + newUserId);
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800634 }
635
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800636 for (LocationProviderManager manager : mProviderManagers) {
637 // update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility
638 mSettingsStore.setLocationProviderAllowed(manager.getName(),
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800639 manager.isEnabled(newUserId), newUserId);
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800640
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800641 manager.onEnabledChangedLocked(oldUserId);
642 manager.onEnabledChangedLocked(newUserId);
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800643 }
Victoria Lease38389b62012-09-30 11:44:22 -0700644 }
645
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700646 /**
647 * Location provider manager, manages a LocationProvider.
648 */
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800649 class LocationProviderManager implements MockableLocationProvider.Listener {
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700650
651 private final String mName;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700652
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800653 // acquiring mLock makes operations on mProvider atomic, but is otherwise unnecessary
654 protected final MockableLocationProvider mProvider;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700655
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800656 // enabled state for parent user ids, no entry implies false. location state is only kept
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800657 // for parent user ids, the location state for a profile user id is assumed to be the same
658 // as for the parent. if querying this structure, ensure that the user id being used is a
659 // parent id or the results may be incorrect.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800660 @GuardedBy("mLock")
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800661 private final SparseArray<Boolean> mEnabled;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700662
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800663 private LocationProviderManager(String name) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800664 mName = name;
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800665 mEnabled = new SparseArray<>(1);
Soonil Nagarkar42da1b12019-01-22 11:29:27 -0800666
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800667 // initialize last since this lets our reference escape
668 mProvider = new MockableLocationProvider(mContext, mLock, this);
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800669
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800670 // we can assume all users start with disabled location state since the initial state
671 // of all providers is disabled. no need to initialize mEnabled further.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800672 }
673
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700674 public String getName() {
675 return mName;
676 }
677
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800678 public boolean hasProvider() {
679 return mProvider.getProvider() != null;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700680 }
681
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800682 public void setRealProvider(AbstractLocationProvider provider) {
683 mProvider.setRealProvider(provider);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800684 }
685
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800686 public void setMockProvider(@Nullable MockProvider provider) {
687 mProvider.setMockProvider(provider);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800688 }
689
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800690 public Set<String> getPackages() {
691 return mProvider.getState().providerPackageNames;
692 }
693
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700694 @Nullable
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800695 public ProviderProperties getProperties() {
696 return mProvider.getState().properties;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700697 }
698
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800699 public void setMockProviderAllowed(boolean enabled) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800700 synchronized (mLock) {
701 if (!mProvider.isMock()) {
702 throw new IllegalArgumentException(mName + " provider is not a test provider");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800703 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800704
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800705 mProvider.setMockProviderAllowed(enabled);
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800706 }
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700707 }
708
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800709 public void setMockProviderLocation(Location location) {
710 synchronized (mLock) {
711 if (!mProvider.isMock()) {
712 throw new IllegalArgumentException(mName + " provider is not a test provider");
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700713 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800714
715 String locationProvider = location.getProvider();
716 if (!TextUtils.isEmpty(locationProvider) && !mName.equals(locationProvider)) {
717 // The location has an explicit provider that is different from the mock
718 // provider name. The caller may be trying to fool us via b/33091107.
719 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
720 mName + "!=" + locationProvider);
721 }
722
723 mProvider.setMockProviderLocation(location);
724 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700725 }
726
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800727 public List<LocationRequest> getMockProviderRequests() {
728 synchronized (mLock) {
729 if (!mProvider.isMock()) {
730 throw new IllegalArgumentException(mName + " provider is not a test provider");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800731 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800732
733 return mProvider.getCurrentRequest().locationRequests;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800734 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800735 }
736
737 public void setRequest(ProviderRequest request) {
738 mProvider.setRequest(request);
739 }
740
741 public void sendExtraCommand(int uid, int pid, String command, Bundle extras) {
742 mProvider.sendExtraCommand(uid, pid, command, extras);
743 }
744
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800745 @GuardedBy("mLock")
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700746 @Override
747 public void onReportLocation(Location location) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800748 // don't validate mock locations
749 if (!location.isFromMockProvider()) {
750 if (location.getLatitude() == 0 && location.getLongitude() == 0) {
751 Slog.w(TAG, "blocking 0,0 location from " + mName + " provider");
752 return;
753 }
Soonil Nagarkar7fc24c62019-10-18 17:32:38 -0700754 }
755
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800756 handleLocationChangedLocked(location, this);
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700757 }
758
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800759 @GuardedBy("mLock")
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700760 @Override
761 public void onReportLocation(List<Location> locations) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700762 if (mGnssManagerService == null) {
763 return;
764 }
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700765
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800766 if (!GPS_PROVIDER.equals(mName) || !isEnabled()) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800767 Slog.w(TAG, "reportLocationBatch() called without user permission");
768 return;
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700769 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800770
771 mGnssManagerService.onReportLocation(locations);
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700772 }
773
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800774 @GuardedBy("mLock")
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700775 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800776 public void onStateChanged(State oldState, State newState) {
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800777 if (oldState.allowed != newState.allowed) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800778 // it would be more correct to call this for all users, but we know this can
779 // only affect the current user since providers are disabled for non-current
780 // users
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800781 onEnabledChangedLocked(mUserInfoStore.getCurrentUserId());
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700782 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700783 }
784
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800785 public void requestSetAllowed(boolean allowed) {
786 mProvider.requestSetAllowed(allowed);
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800787 }
788
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800789 public boolean isEnabled() {
790 return isEnabled(mUserInfoStore.getCurrentUserId());
791 }
792
793 public boolean isEnabled(int userId) {
Soonil Nagarkar66c0bac2019-01-15 13:36:44 -0800794 synchronized (mLock) {
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800795 // normalize user id to always refer to parent since profile state is always the
796 // same as parent state
797 userId = mUserInfoStore.getParentUserId(userId);
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800798 return mEnabled.get(userId, Boolean.FALSE);
Soonil Nagarkar66c0bac2019-01-15 13:36:44 -0800799 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700800 }
801
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800802 @GuardedBy("mLock")
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800803 public void onEnabledChangedLocked(int userId) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800804 if (userId == UserHandle.USER_NULL) {
805 // only used during initialization - we don't care about the null user
806 return;
807 }
808
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800809 // normalize user id to always refer to parent since profile state is always the same
810 // as parent state
811 userId = mUserInfoStore.getParentUserId(userId);
812
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800813 // if any property that contributes to "enabled" here changes state, it MUST result
814 // in a direct or indrect call to onEnabledChangedLocked. this allows the provider to
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800815 // guarantee that it will always eventually reach the correct state.
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800816 boolean enabled = (userId == mUserInfoStore.getCurrentUserId())
817 && mSettingsStore.isLocationEnabled(userId) && mProvider.getState().allowed;
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800818
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800819 if (enabled == isEnabled(userId)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800820 return;
821 }
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800822
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800823 mEnabled.put(userId, enabled);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800824
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800825 if (D) {
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800826 Log.d(TAG, "[u" + userId + "] " + mName + " provider enabled = " + enabled);
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800827 }
828
Soonil Nagarkar57f4b7b2019-12-09 10:19:18 -0800829 // fused and passive provider never get public updates for legacy reasons
830 if (!FUSED_PROVIDER.equals(mName) && !PASSIVE_PROVIDER.equals(mName)) {
831 // update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800832 mSettingsStore.setLocationProviderAllowed(mName, enabled, userId);
Soonil Nagarkar57f4b7b2019-12-09 10:19:18 -0800833
Soonil Nagarkardbd467e2020-01-14 15:10:45 -0800834 Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION)
835 .putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName)
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800836 .putExtra(LocationManager.EXTRA_PROVIDER_ENABLED, enabled)
Soonil Nagarkardbd467e2020-01-14 15:10:45 -0800837 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
838 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Soonil Nagarkar57f4b7b2019-12-09 10:19:18 -0800839 mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
840 }
841
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800842 if (!enabled) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800843 // If any provider has been disabled, clear all last locations for all
844 // providers. This is to be on the safe side in case a provider has location
845 // derived from this disabled provider.
846 mLastLocation.clear();
847 mLastLocationCoarseInterval.clear();
848 }
849
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800850 updateProviderEnabledLocked(this);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800851 }
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800852
853 public void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
854 synchronized (mLock) {
855 pw.print(mName + " provider");
856 if (mProvider.isMock()) {
857 pw.print(" [mock]");
858 }
859 pw.println(":");
860
861 pw.increaseIndent();
862
Soonil Nagarkared5a2002020-01-28 10:53:53 -0800863 pw.println("enabled=" + isEnabled());
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800864 }
865
866 mProvider.dump(fd, pw, args);
867
868 pw.decreaseIndent();
869 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800870 }
871
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800872 class PassiveLocationProviderManager extends LocationProviderManager {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800873
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800874 private PassiveLocationProviderManager() {
875 super(PASSIVE_PROVIDER);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800876 }
877
878 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800879 public void setRealProvider(AbstractLocationProvider provider) {
880 Preconditions.checkArgument(provider instanceof PassiveProvider);
881 super.setRealProvider(provider);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800882 }
883
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800884 @Override
885 public void setMockProvider(@Nullable MockProvider provider) {
886 if (provider != null) {
887 throw new IllegalArgumentException("Cannot mock the passive provider");
888 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800889 }
890
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800891 public void updateLocation(Location location) {
892 synchronized (mLock) {
893 PassiveProvider passiveProvider = (PassiveProvider) mProvider.getProvider();
894 Preconditions.checkState(passiveProvider != null);
895
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800896 long identity = Binder.clearCallingIdentity();
897 try {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800898 passiveProvider.updateLocation(location);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800899 } finally {
900 Binder.restoreCallingIdentity(identity);
Soonil Nagarkar68257742019-01-09 19:42:34 +0000901 }
902 }
903 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700904 }
905
Victoria Lease38389b62012-09-30 11:44:22 -0700906 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800907 * A wrapper class holding either an ILocationListener or a PendingIntent to receive
908 * location updates.
909 */
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700910 private final class Receiver extends LocationManagerServiceUtils.LinkedListenerBase implements
911 PendingIntent.OnFinished {
Yu-Han Yang24189822018-07-11 15:24:11 -0700912 private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700913 private final int mAllowedResolutionLevel; // resolution level allowed to receiver
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700914
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700915 private final ILocationListener mListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800916 final PendingIntent mPendingIntent;
David Christie82edc9b2013-07-19 11:31:42 -0700917 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700918 private final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
919 private final Object mKey;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700920
gomo48f1a642017-11-10 20:35:46 -0800921 final HashMap<String, UpdateRecord> mUpdateRecords = new HashMap<>();
Nick Pellyf1be6862012-05-15 10:53:42 -0700922
David Christie0b837452013-07-29 16:02:13 -0700923 // True if app ops has started monitoring this receiver for locations.
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700924 private boolean mOpMonitoring;
David Christie0b837452013-07-29 16:02:13 -0700925 // True if app ops has started monitoring this receiver for high power (gps) locations.
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700926 private boolean mOpHighPowerMonitoring;
927 private int mPendingBroadcasts;
Victoria Lease0aa28602013-05-29 15:28:26 -0700928 PowerManager.WakeLock mWakeLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800929
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700930 private Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -0700931 String packageName, @Nullable String featureId, WorkSource workSource,
932 boolean hideFromAppOps, @NonNull String listenerIdentifier) {
933 super(new CallerIdentity(uid, pid, packageName, featureId, listenerIdentifier),
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -0700934 "LocationListener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 mListener = listener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936 mPendingIntent = intent;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700937 if (listener != null) {
938 mKey = listener.asBinder();
939 } else {
940 mKey = intent;
941 }
Victoria Lease37425c32012-10-16 16:08:48 -0700942 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
Narayan Kamath32684dd2018-01-08 17:32:51 +0000943 if (workSource != null && workSource.isEmpty()) {
David Christie82edc9b2013-07-19 11:31:42 -0700944 workSource = null;
945 }
946 mWorkSource = workSource;
David Christie40e57822013-07-30 11:36:48 -0700947 mHideFromAppOps = hideFromAppOps;
Victoria Lease0aa28602013-05-29 15:28:26 -0700948
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700949 updateMonitoring(true);
950
Victoria Lease0aa28602013-05-29 15:28:26 -0700951 // construct/configure wakelock
952 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
David Christie82edc9b2013-07-19 11:31:42 -0700953 if (workSource == null) {
Anil Admal08b96122019-01-30 16:55:05 -0800954 workSource = new WorkSource(mCallerIdentity.mUid, mCallerIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -0700955 }
956 mWakeLock.setWorkSource(workSource);
Yu-Han Yang24189822018-07-11 15:24:11 -0700957
958 // For a non-reference counted wakelock, each acquire will reset the timeout, and we
959 // only need to release it once.
960 mWakeLock.setReferenceCounted(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961 }
962
963 @Override
964 public boolean equals(Object otherObj) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800965 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800966 }
967
968 @Override
969 public int hashCode() {
970 return mKey.hashCode();
971 }
Mike Lockwood3681f262009-05-12 10:52:03 -0400972
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 @Override
974 public String toString() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700975 StringBuilder s = new StringBuilder();
976 s.append("Reciever[");
977 s.append(Integer.toHexString(System.identityHashCode(this)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 if (mListener != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700979 s.append(" listener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800980 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700981 s.append(" intent");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700983 for (String p : mUpdateRecords.keySet()) {
984 s.append(" ").append(mUpdateRecords.get(p).toString());
985 }
Wei Wangdd070f22018-06-21 11:29:40 -0700986 s.append(" monitoring location: ").append(mOpMonitoring);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700987 s.append("]");
988 return s.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800989 }
990
David Christie15b31912013-08-13 15:54:32 -0700991 /**
992 * Update AppOp monitoring for this receiver.
993 *
994 * @param allow If true receiver is currently active, if false it's been removed.
995 */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700996 public void updateMonitoring(boolean allow) {
David Christie40e57822013-07-30 11:36:48 -0700997 if (mHideFromAppOps) {
998 return;
999 }
1000
David Christie15b31912013-08-13 15:54:32 -07001001 boolean requestingLocation = false;
1002 boolean requestingHighPowerLocation = false;
1003 if (allow) {
1004 // See if receiver has any enabled update records. Also note if any update records
1005 // are high power (has a high power provider with an interval under a threshold).
1006 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001007 LocationProviderManager manager = getLocationProviderManager(
Soonil Nagarkar3f128402019-12-12 08:31:27 -08001008 updateRecord.mProvider);
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001009 if (manager == null) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001010 continue;
1011 }
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08001012 if (!manager.isEnabled() && !isSettingsExemptLocked(updateRecord)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001013 continue;
1014 }
1015
1016 requestingLocation = true;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001017 ProviderProperties properties = manager.getProperties();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001018 if (properties != null
1019 && properties.mPowerRequirement == Criteria.POWER_HIGH
1020 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
1021 requestingHighPowerLocation = true;
1022 break;
David Christie15b31912013-08-13 15:54:32 -07001023 }
1024 }
1025 }
1026
David Christie0b837452013-07-29 16:02:13 -07001027 // First update monitoring of any location request (including high power).
David Christie15b31912013-08-13 15:54:32 -07001028 mOpMonitoring = updateMonitoring(
1029 requestingLocation,
1030 mOpMonitoring,
David Christie0b837452013-07-29 16:02:13 -07001031 AppOpsManager.OP_MONITOR_LOCATION);
1032
1033 // Now update monitoring of high power requests only.
David Christiec750c1f2013-08-08 12:56:57 -07001034 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
David Christie15b31912013-08-13 15:54:32 -07001035 mOpHighPowerMonitoring = updateMonitoring(
1036 requestingHighPowerLocation,
1037 mOpHighPowerMonitoring,
David Christie0b837452013-07-29 16:02:13 -07001038 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
David Christiec750c1f2013-08-08 12:56:57 -07001039 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
David Christie15b31912013-08-13 15:54:32 -07001040 // Send an intent to notify that a high power request has been added/removed.
David Christiec750c1f2013-08-08 12:56:57 -07001041 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
1042 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
1043 }
David Christie0b837452013-07-29 16:02:13 -07001044 }
1045
1046 /**
1047 * Update AppOps monitoring for a single location request and op type.
1048 *
gomo48f1a642017-11-10 20:35:46 -08001049 * @param allowMonitoring True if monitoring is allowed for this request/op.
David Christie0b837452013-07-29 16:02:13 -07001050 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
gomo48f1a642017-11-10 20:35:46 -08001051 * @param op AppOps code for the op to update.
David Christie0b837452013-07-29 16:02:13 -07001052 * @return True if monitoring is on for this request/op after updating.
1053 */
1054 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
1055 int op) {
1056 if (!currentlyMonitoring) {
1057 if (allowMonitoring) {
Anil Admal08b96122019-01-30 16:55:05 -08001058 return mAppOps.startOpNoThrow(op, mCallerIdentity.mUid,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001059 mCallerIdentity.mPackageName, false, mCallerIdentity.mFeatureId, null)
1060 == AppOpsManager.MODE_ALLOWED;
David Christie0b837452013-07-29 16:02:13 -07001061 }
1062 } else {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001063 if (!allowMonitoring
Wei Wang16276a42019-02-04 18:23:31 -08001064 || mAppOps.checkOpNoThrow(op, mCallerIdentity.mUid,
Anil Admal08b96122019-01-30 16:55:05 -08001065 mCallerIdentity.mPackageName) != AppOpsManager.MODE_ALLOWED) {
1066 mAppOps.finishOp(op, mCallerIdentity.mUid, mCallerIdentity.mPackageName);
David Christie0b837452013-07-29 16:02:13 -07001067 return false;
1068 }
1069 }
1070
1071 return currentlyMonitoring;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001072 }
1073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 public boolean isListener() {
1075 return mListener != null;
1076 }
1077
1078 public boolean isPendingIntent() {
1079 return mPendingIntent != null;
1080 }
1081
1082 public ILocationListener getListener() {
1083 if (mListener != null) {
1084 return mListener;
1085 }
1086 throw new IllegalStateException("Request for non-existent listener");
1087 }
1088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 public boolean callLocationChangedLocked(Location location) {
1090 if (mListener != null) {
1091 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001092 mListener.onLocationChanged(new Location(location));
1093 // call this after broadcasting so we do not increment
1094 // if we throw an exception.
1095 incrementPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096 } catch (RemoteException e) {
1097 return false;
1098 }
1099 } else {
1100 Intent locationChanged = new Intent();
gomo48f1a642017-11-10 20:35:46 -08001101 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED,
1102 new Location(location));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001103 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001104 mPendingIntent.send(mContext, 0, locationChanged, this, mHandler,
1105 getResolutionPermission(mAllowedResolutionLevel),
1106 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
1107 // call this after broadcasting so we do not increment
1108 // if we throw an exception.
1109 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001110 } catch (PendingIntent.CanceledException e) {
1111 return false;
1112 }
1113 }
1114 return true;
1115 }
1116
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001117 private boolean callProviderEnabledLocked(String provider, boolean enabled) {
David Christie15b31912013-08-13 15:54:32 -07001118 // First update AppOp monitoring.
1119 // An app may get/lose location access as providers are enabled/disabled.
1120 updateMonitoring(true);
1121
Mike Lockwood48f17512009-04-23 09:12:08 -07001122 if (mListener != null) {
1123 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001124 if (enabled) {
1125 mListener.onProviderEnabled(provider);
1126 } else {
1127 mListener.onProviderDisabled(provider);
Mike Lockwood48f17512009-04-23 09:12:08 -07001128 }
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001129 // call this after broadcasting so we do not increment
1130 // if we throw an exception.
1131 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001132 } catch (RemoteException e) {
1133 return false;
1134 }
1135 } else {
1136 Intent providerIntent = new Intent();
1137 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1138 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001139 mPendingIntent.send(mContext, 0, providerIntent, this, mHandler,
1140 getResolutionPermission(mAllowedResolutionLevel),
1141 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
1142 // call this after broadcasting so we do not increment
1143 // if we throw an exception.
1144 incrementPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001145 } catch (PendingIntent.CanceledException e) {
1146 return false;
1147 }
1148 }
1149 return true;
1150 }
1151
Soonil Nagarkar39d614a2019-10-31 12:10:31 -07001152 public void callRemovedLocked() {
1153 if (mListener != null) {
1154 try {
1155 mListener.onRemoved();
1156 } catch (RemoteException e) {
1157 // doesn't matter
1158 }
1159 }
1160 }
1161
Nick Pellyf1be6862012-05-15 10:53:42 -07001162 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163 public void binderDied() {
Anil Admal98d49b72019-02-06 15:26:33 -08001164 if (D) Log.d(TAG, "Remote " + mListenerName + " died.");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001165
Soonil Nagarkar68257742019-01-09 19:42:34 +00001166 synchronized (mLock) {
1167 removeUpdatesLocked(this);
Soonil Nagarkar68257742019-01-09 19:42:34 +00001168 clearPendingBroadcastsLocked();
1169 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001170 }
1171
Nick Pellye0fd6932012-07-11 10:26:13 -07001172 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001173 public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1174 int resultCode, String resultData, Bundle resultExtras) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001175 synchronized (mLock) {
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001176 decrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001177 }
1178 }
1179
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001180 // this must be called while synchronized by caller in a synchronized block
1181 // containing the sending of the broadcaset
1182 private void incrementPendingBroadcastsLocked() {
Yu-Han Yang24189822018-07-11 15:24:11 -07001183 mPendingBroadcasts++;
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001184 // so wakelock calls will succeed
1185 long identity = Binder.clearCallingIdentity();
1186 try {
1187 mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
1188 } finally {
1189 Binder.restoreCallingIdentity(identity);
1190 }
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001191 }
1192
1193 private void decrementPendingBroadcastsLocked() {
1194 if (--mPendingBroadcasts == 0) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001195 // so wakelock calls will succeed
1196 long identity = Binder.clearCallingIdentity();
1197 try {
1198 if (mWakeLock.isHeld()) {
1199 mWakeLock.release();
1200 }
1201 } finally {
1202 Binder.restoreCallingIdentity(identity);
Victoria Lease0aa28602013-05-29 15:28:26 -07001203 }
1204 }
1205 }
1206
1207 public void clearPendingBroadcastsLocked() {
1208 if (mPendingBroadcasts > 0) {
1209 mPendingBroadcasts = 0;
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001210 // so wakelock calls will succeed
1211 long identity = Binder.clearCallingIdentity();
1212 try {
1213 if (mWakeLock.isHeld()) {
1214 mWakeLock.release();
1215 }
1216 } finally {
1217 Binder.restoreCallingIdentity(identity);
Victoria Lease0aa28602013-05-29 15:28:26 -07001218 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001219 }
1220 }
1221 }
1222
Nick Pellye0fd6932012-07-11 10:26:13 -07001223 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001224 public void locationCallbackFinished(ILocationListener listener) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001225 //Do not use getReceiverLocked here as that will add the ILocationListener to
Joshua Bartel080b61b2009-10-05 12:44:46 -04001226 //the receiver list if it is not found. If it is not found then the
1227 //LocationListener was removed when it had a pending broadcast and should
1228 //not be added back.
Soonil Nagarkar68257742019-01-09 19:42:34 +00001229 synchronized (mLock) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001230 Receiver receiver = mReceivers.get(listener.asBinder());
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001231 if (receiver != null) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001232 receiver.decrementPendingBroadcastsLocked();
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001233 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00001234 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001235 }
1236
Lifu Tang82f893d2016-01-21 18:15:33 -08001237 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001238 public int getGnssYearOfHardware() {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001239 return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001240 }
1241
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001242 @Override
Wyatt Riley49097c02018-03-15 09:14:43 -07001243 @Nullable
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001244 public String getGnssHardwareModelName() {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001245 return mGnssManagerService == null ? "" : mGnssManagerService.getGnssHardwareModelName();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001246 }
1247
Wyatt Rileycf879db2017-01-12 13:57:38 -08001248 @Override
1249 public int getGnssBatchSize(String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001250 return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssBatchSize(packageName);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001251 }
1252
Wyatt Rileycf879db2017-01-12 13:57:38 -08001253 @Override
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001254 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001255 String featureId, String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00001256 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001257
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001258 return mGnssManagerService != null && mGnssManagerService.addGnssBatchingCallback(
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001259 callback, packageName, featureId, listenerIdentifier);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001260 }
1261
Wyatt Rileycf879db2017-01-12 13:57:38 -08001262 @Override
1263 public void removeGnssBatchingCallback() {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001264 if (mGnssManagerService != null) mGnssManagerService.removeGnssBatchingCallback();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001265 }
1266
Wyatt Rileycf879db2017-01-12 13:57:38 -08001267 @Override
1268 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001269 return mGnssManagerService != null && mGnssManagerService.startGnssBatch(periodNanos,
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001270 wakeOnFifoFull, packageName);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001271 }
1272
Wyatt Rileycf879db2017-01-12 13:57:38 -08001273 @Override
1274 public void flushGnssBatch(String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001275 if (mGnssManagerService != null) mGnssManagerService.flushGnssBatch(packageName);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001276 }
1277
Wyatt Rileycf879db2017-01-12 13:57:38 -08001278 @Override
1279 public boolean stopGnssBatch() {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001280 return mGnssManagerService != null && mGnssManagerService.stopGnssBatch();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001281 }
1282
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001283 @Nullable
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001284 private LocationProviderManager getLocationProviderManager(String providerName) {
1285 for (LocationProviderManager manager : mProviderManagers) {
1286 if (providerName.equals(manager.getName())) {
1287 return manager;
Soonil Nagarkar68257742019-01-09 19:42:34 +00001288 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001289 }
1290
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001291 return null;
Maggie2a9409e2018-03-21 11:47:28 -07001292 }
1293
Victoria Lease37425c32012-10-16 16:08:48 -07001294 private String getResolutionPermission(int resolutionLevel) {
1295 switch (resolutionLevel) {
1296 case RESOLUTION_LEVEL_FINE:
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001297 return ACCESS_FINE_LOCATION;
Victoria Lease37425c32012-10-16 16:08:48 -07001298 case RESOLUTION_LEVEL_COARSE:
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001299 return ACCESS_COARSE_LOCATION;
Victoria Lease37425c32012-10-16 16:08:48 -07001300 default:
1301 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001302 }
Victoria Leaseda479c52012-10-15 15:24:16 -07001303 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001304
Victoria Lease37425c32012-10-16 16:08:48 -07001305 private int getAllowedResolutionLevel(int pid, int uid) {
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001306 if (mContext.checkPermission(ACCESS_FINE_LOCATION, pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001307 return RESOLUTION_LEVEL_FINE;
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001308 } else if (mContext.checkPermission(ACCESS_COARSE_LOCATION, pid, uid)
1309 == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001310 return RESOLUTION_LEVEL_COARSE;
1311 } else {
1312 return RESOLUTION_LEVEL_NONE;
Victoria Leaseda479c52012-10-15 15:24:16 -07001313 }
Victoria Lease4fab68b2012-09-13 13:20:59 -07001314 }
1315
Victoria Lease37425c32012-10-16 16:08:48 -07001316 private int getCallerAllowedResolutionLevel() {
1317 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
1318 }
1319
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001320 private boolean checkCallingOrSelfLocationPermission() {
1321 return mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED
1322 || mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
1323 == PERMISSION_GRANTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001324 }
1325
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001326 private void enforceCallingOrSelfLocationPermission() {
1327 if (checkCallingOrSelfLocationPermission()) {
1328 return;
Victoria Lease8dbb6342012-09-21 16:55:53 -07001329 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001330
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001331 throw new SecurityException("uid " + Binder.getCallingUid() + " does not have "
1332 + ACCESS_COARSE_LOCATION + " or " + ACCESS_FINE_LOCATION + ".");
Victoria Leaseda479c52012-10-15 15:24:16 -07001333 }
1334
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001335 private void enforceCallingOrSelfPackageName(String packageName) {
1336 int uid = Binder.getCallingUid();
1337 if (ArrayUtils.contains(mPackageManager.getPackagesForUid(uid), packageName)) {
1338 return;
Victoria Leaseda479c52012-10-15 15:24:16 -07001339 }
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001340
1341 throw new SecurityException("invalid package \"" + packageName + "\" for uid " + uid);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001342 }
1343
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001344 public static int resolutionLevelToOp(int allowedResolutionLevel) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001345 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
1346 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001347 return AppOpsManager.OP_COARSE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001348 } else {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001349 return AppOpsManager.OP_FINE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001350 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001351 }
1352 return -1;
1353 }
1354
Wei Wangb86334f2018-07-03 16:33:24 -07001355 private static String resolutionLevelToOpStr(int allowedResolutionLevel) {
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001356 switch (allowedResolutionLevel) {
Wei Wangb86334f2018-07-03 16:33:24 -07001357 case RESOLUTION_LEVEL_COARSE:
1358 return AppOpsManager.OPSTR_COARSE_LOCATION;
1359 case RESOLUTION_LEVEL_FINE:
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001360 // fall through
Wei Wangb86334f2018-07-03 16:33:24 -07001361 case RESOLUTION_LEVEL_NONE:
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001362 // fall through
Wei Wangb86334f2018-07-03 16:33:24 -07001363 default:
1364 // Use the most restrictive ops if not sure.
1365 return AppOpsManager.OPSTR_FINE_LOCATION;
1366 }
1367 }
1368
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001369 private boolean reportLocationAccessNoThrow(int pid, int uid, String packageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001370 @Nullable String featureId, int allowedResolutionLevel, @Nullable String message) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001371 int op = resolutionLevelToOp(allowedResolutionLevel);
1372 if (op >= 0) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001373 if (mAppOps.noteOpNoThrow(op, uid, packageName, featureId, message)
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001374 != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001375 return false;
1376 }
1377 }
David Christieb870dbf2015-06-22 12:42:53 -07001378
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001379 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001380 }
1381
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001382 private boolean checkLocationAccess(int pid, int uid, String packageName,
1383 int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001384 int op = resolutionLevelToOp(allowedResolutionLevel);
1385 if (op >= 0) {
Wei Wang16276a42019-02-04 18:23:31 -08001386 if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001387 return false;
1388 }
1389 }
David Christieb870dbf2015-06-22 12:42:53 -07001390
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001391 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001392 }
1393
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001394 /**
Maggie91e630c2018-01-24 17:31:46 -08001395 * Returns all providers by name, including passive and the ones that are not permitted to
1396 * be accessed by the calling activity or are currently disabled, but excluding fused.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001397 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001398 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001399 public List<String> getAllProviders() {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001400 ArrayList<String> providers = new ArrayList<>(mProviderManagers.size());
1401 for (LocationProviderManager manager : mProviderManagers) {
1402 if (FUSED_PROVIDER.equals(manager.getName())) {
1403 continue;
Maggie91e630c2018-01-24 17:31:46 -08001404 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001405 providers.add(manager.getName());
Maggie91e630c2018-01-24 17:31:46 -08001406 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001407 return providers;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 }
1409
Mike Lockwood03ca2162010-04-01 08:10:09 -07001410 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001411 * Return all providers by name, that match criteria and are optionally
1412 * enabled.
1413 * Can return passive provider, but never returns fused provider.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001414 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001415 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001416 public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001417 if (!checkCallingOrSelfLocationPermission()) {
1418 return Collections.emptyList();
1419 }
1420
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001421 synchronized (mLock) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001422 ArrayList<String> providers = new ArrayList<>(mProviderManagers.size());
1423 for (LocationProviderManager manager : mProviderManagers) {
1424 String name = manager.getName();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001425 if (FUSED_PROVIDER.equals(name)) {
1426 continue;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001427 }
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08001428 if (enabledOnly && !manager.isEnabled()) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001429 continue;
1430 }
1431 if (criteria != null
1432 && !android.location.LocationProvider.propertiesMeetCriteria(
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001433 name, manager.getProperties(), criteria)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001434 continue;
1435 }
1436 providers.add(name);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001437 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001438 return providers;
Soonil Nagarkar68257742019-01-09 19:42:34 +00001439 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001440 }
1441
1442 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001443 * Return the name of the best provider given a Criteria object.
1444 * This method has been deprecated from the public API,
Victoria Lease8dbb6342012-09-21 16:55:53 -07001445 * and the whole LocationProvider (including #meetsCriteria)
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001446 * has been deprecated as well. So this method now uses
1447 * some simplified logic.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001448 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001449 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001450 public String getBestProvider(Criteria criteria, boolean enabledOnly) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001451 List<String> providers = getProviders(criteria, enabledOnly);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001452 if (providers.isEmpty()) {
1453 providers = getProviders(null, enabledOnly);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08001454 }
1455
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001456 if (!providers.isEmpty()) {
1457 if (providers.contains(GPS_PROVIDER)) {
1458 return GPS_PROVIDER;
1459 } else if (providers.contains(NETWORK_PROVIDER)) {
1460 return NETWORK_PROVIDER;
1461 } else {
1462 return providers.get(0);
1463 }
1464 }
1465
Mike Lockwood03ca2162010-04-01 08:10:09 -07001466 return null;
1467 }
1468
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001469 @GuardedBy("mLock")
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08001470 private void updateProviderEnabledLocked(LocationProviderManager manager) {
1471 boolean enabled = manager.isEnabled();
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 ArrayList<Receiver> deadReceivers = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07001474
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001475 ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001476 if (records != null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001477 for (UpdateRecord record : records) {
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08001478 if (!mUserInfoStore.isCurrentUserOrProfile(
Anil Admal08b96122019-01-30 16:55:05 -08001479 UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001480 continue;
1481 }
1482
Kweku Adams5e0052b2019-02-22 15:17:52 -08001483 // requests that ignore location settings will never provide notifications
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001484 if (isSettingsExemptLocked(record)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001485 continue;
1486 }
1487
1488 // Sends a notification message to the receiver
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08001489 if (!record.mReceiver.callProviderEnabledLocked(manager.getName(), enabled)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001490 if (deadReceivers == null) {
1491 deadReceivers = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001493 deadReceivers.add(record.mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001495 }
1496 }
1497
1498 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001499 for (int i = deadReceivers.size() - 1; i >= 0; i--) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00001500 removeUpdatesLocked(deadReceivers.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 }
1502 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001503
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001504 applyRequirementsLocked(manager);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 }
1506
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001507 @GuardedBy("mLock")
1508 private void applyRequirementsLocked(String providerName) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001509 LocationProviderManager manager = getLocationProviderManager(providerName);
1510 if (manager != null) {
1511 applyRequirementsLocked(manager);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001512 }
1513 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001514
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001515 @GuardedBy("mLock")
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001516 private void applyRequirementsLocked(LocationProviderManager manager) {
1517 ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName());
1518 ProviderRequest.Builder providerRequest = new ProviderRequest.Builder();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001519
Soonil Nagarkar04cff6c2019-03-19 11:29:52 -07001520 // if provider is not active, it should not respond to requests
1521
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001522 if (mProviderManagers.contains(manager) && records != null && !records.isEmpty()) {
Kweku Adams5e0052b2019-02-22 15:17:52 -08001523 long backgroundThrottleInterval;
1524
1525 long identity = Binder.clearCallingIdentity();
1526 try {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07001527 backgroundThrottleInterval = mSettingsStore.getBackgroundThrottleIntervalMs();
Kweku Adams5e0052b2019-02-22 15:17:52 -08001528 } finally {
1529 Binder.restoreCallingIdentity(identity);
1530 }
1531
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001532 ArrayList<LocationRequest> requests = new ArrayList<>(records.size());
1533
Kweku Adams5e0052b2019-02-22 15:17:52 -08001534 final boolean isForegroundOnlyMode =
Kweku Adams4fb074e2019-02-01 16:03:27 -08001535 mBatterySaverMode == PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
1536 final boolean shouldThrottleRequests =
1537 mBatterySaverMode
1538 == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF
1539 && !mPowerManager.isInteractive();
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001540 // initialize the low power mode to true and set to false if any of the records requires
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001541 providerRequest.setLowPowerMode(true);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001542 for (UpdateRecord record : records) {
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08001543 if (!mUserInfoStore.isCurrentUserOrProfile(
Anil Admal08b96122019-01-30 16:55:05 -08001544 UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001545 continue;
1546 }
1547 if (!checkLocationAccess(
Anil Admal08b96122019-01-30 16:55:05 -08001548 record.mReceiver.mCallerIdentity.mPid,
1549 record.mReceiver.mCallerIdentity.mUid,
1550 record.mReceiver.mCallerIdentity.mPackageName,
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001551 record.mReceiver.mAllowedResolutionLevel)) {
1552 continue;
1553 }
Kweku Adams4fb074e2019-02-01 16:03:27 -08001554 final boolean isBatterySaverDisablingLocation = shouldThrottleRequests
1555 || (isForegroundOnlyMode && !record.mIsForegroundUid);
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08001556 if (!manager.isEnabled() || isBatterySaverDisablingLocation) {
Soonil Nagarkar35c3b912019-01-31 10:31:24 -08001557 if (isSettingsExemptLocked(record)) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001558 providerRequest.setLocationSettingsIgnored(true);
1559 providerRequest.setLowPowerMode(false);
Soonil Nagarkar35c3b912019-01-31 10:31:24 -08001560 } else {
1561 continue;
1562 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001563 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001564
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001565 LocationRequest locationRequest = record.mRealRequest;
1566 long interval = locationRequest.getInterval();
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001567
Soonil Nagarkar509580f2019-02-06 15:57:26 -08001568
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001569 // if we're forcing location, don't apply any throttling
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001570 if (!providerRequest.isLocationSettingsIgnored() && !isThrottlingExemptLocked(
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001571 record.mReceiver.mCallerIdentity)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001572 if (!record.mIsForegroundUid) {
1573 interval = Math.max(interval, backgroundThrottleInterval);
Victoria Leaseb711d572012-10-02 13:14:11 -07001574 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001575 if (interval != locationRequest.getInterval()) {
1576 locationRequest = new LocationRequest(locationRequest);
1577 locationRequest.setInterval(interval);
1578 }
1579 }
1580
1581 record.mRequest = locationRequest;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001582 requests.add(locationRequest);
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001583 if (!locationRequest.isLowPowerMode()) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001584 providerRequest.setLowPowerMode(false);
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001585 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001586 if (interval < providerRequest.getInterval()) {
1587 providerRequest.setInterval(interval);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001588 }
1589 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001590
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001591 providerRequest.setLocationRequests(requests);
1592
1593 if (providerRequest.getInterval() < Long.MAX_VALUE) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001594 // calculate who to blame for power
1595 // This is somewhat arbitrary. We pick a threshold interval
1596 // that is slightly higher that the minimum interval, and
1597 // spread the blame across all applications with a request
1598 // under that threshold.
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001599 // TODO: overflow
1600 long thresholdInterval = (providerRequest.getInterval() + 1000) * 3 / 2;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001601 for (UpdateRecord record : records) {
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08001602 if (mUserInfoStore.isCurrentUserOrProfile(
Anil Admal08b96122019-01-30 16:55:05 -08001603 UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001604 LocationRequest locationRequest = record.mRequest;
Svet Ganove998c732016-06-10 00:12:38 -07001605
1606 // Don't assign battery blame for update records whose
1607 // client has no permission to receive location data.
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001608 if (!providerRequest.getLocationRequests().contains(locationRequest)) {
Svet Ganove998c732016-06-10 00:12:38 -07001609 continue;
1610 }
1611
Victoria Leaseb711d572012-10-02 13:14:11 -07001612 if (locationRequest.getInterval() <= thresholdInterval) {
David Christiee55c9682013-08-22 10:10:34 -07001613 if (record.mReceiver.mWorkSource != null
Narayan Kamath32684dd2018-01-08 17:32:51 +00001614 && isValidWorkSource(record.mReceiver.mWorkSource)) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001615 providerRequest.getWorkSource().add(record.mReceiver.mWorkSource);
David Christie82edc9b2013-07-19 11:31:42 -07001616 } else {
Narayan Kamath32684dd2018-01-08 17:32:51 +00001617 // Assign blame to caller if there's no WorkSource associated with
1618 // the request or if it's invalid.
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001619 providerRequest.getWorkSource().add(
Anil Admal08b96122019-01-30 16:55:05 -08001620 record.mReceiver.mCallerIdentity.mUid,
1621 record.mReceiver.mCallerIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001622 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001623 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001624 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001625 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001626 }
1627 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001628
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001629 manager.setRequest(providerRequest.build());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001630 }
1631
Narayan Kamath32684dd2018-01-08 17:32:51 +00001632 /**
1633 * Whether a given {@code WorkSource} associated with a Location request is valid.
1634 */
1635 private static boolean isValidWorkSource(WorkSource workSource) {
1636 if (workSource.size() > 0) {
1637 // If the WorkSource has one or more non-chained UIDs, make sure they're accompanied
1638 // by tags.
Suprabh Shuklaf7cffa72019-11-08 17:03:03 -08001639 return workSource.getPackageName(0) != null;
Narayan Kamath32684dd2018-01-08 17:32:51 +00001640 } else {
1641 // For now, make sure callers have supplied an attribution tag for use with
1642 // AppOpsManager. This might be relaxed in the future.
Suprabh Shuklaf7cffa72019-11-08 17:03:03 -08001643 final List<WorkChain> workChains = workSource.getWorkChains();
Narayan Kamath32684dd2018-01-08 17:32:51 +00001644 return workChains != null && !workChains.isEmpty() &&
1645 workChains.get(0).getAttributionTag() != null;
1646 }
1647 }
1648
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001649 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001650 public String[] getBackgroundThrottlingWhitelist() {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07001651 return mSettingsStore.getBackgroundThrottlePackageWhitelist().toArray(new String[0]);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001652 }
1653
Soonil Nagarkar5140e4f2019-02-14 17:21:33 -08001654 @Override
1655 public String[] getIgnoreSettingsWhitelist() {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07001656 return mSettingsStore.getIgnoreSettingsPackageWhitelist().toArray(new String[0]);
Soonil Nagarkar5140e4f2019-02-14 17:21:33 -08001657 }
1658
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001659 @GuardedBy("mLock")
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001660 public boolean isThrottlingExemptLocked(CallerIdentity callerIdentity) {
Anil Admal08b96122019-01-30 16:55:05 -08001661 if (callerIdentity.mUid == Process.SYSTEM_UID) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001662 return true;
1663 }
1664
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07001665 if (mSettingsStore.getBackgroundThrottlePackageWhitelist().contains(
1666 callerIdentity.mPackageName)) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001667 return true;
1668 }
1669
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001670 return isProviderPackage(callerIdentity.mPackageName);
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001671
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001672 }
1673
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001674 @GuardedBy("mLock")
1675 private boolean isSettingsExemptLocked(UpdateRecord record) {
1676 if (!record.mRealRequest.isLocationSettingsIgnored()) {
1677 return false;
1678 }
1679
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07001680 if (mSettingsStore.getIgnoreSettingsPackageWhitelist().contains(
Anil Admal08b96122019-01-30 16:55:05 -08001681 record.mReceiver.mCallerIdentity.mPackageName)) {
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001682 return true;
1683 }
1684
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001685 return isProviderPackage(record.mReceiver.mCallerIdentity.mPackageName);
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001686
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001687 }
1688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001689 private class UpdateRecord {
1690 final String mProvider;
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001691 private final LocationRequest mRealRequest; // original request from client
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001692 LocationRequest mRequest; // possibly throttled version of the request
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001693 private final Receiver mReceiver;
1694 private boolean mIsForegroundUid;
1695 private Location mLastFixBroadcast;
Soonil Nagarkarae6ce772019-05-01 13:16:17 -07001696 private Throwable mStackTrace; // for debugging only
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08001697 private long mExpirationRealtimeMs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001698
1699 /**
1700 * Note: must be constructed with lock held.
1701 */
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001702 private UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08001703 mExpirationRealtimeMs = request.getExpirationRealtimeMs(SystemClock.elapsedRealtime());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 mProvider = provider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001705 mRealRequest = request;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001706 mRequest = request;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001707 mReceiver = receiver;
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001708 mIsForegroundUid =
1709 LocationManagerServiceUtils.isImportanceForeground(
1710 mActivityManager.getPackageImportance(
1711 mReceiver.mCallerIdentity.mPackageName));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001712
Soonil Nagarkarae6ce772019-05-01 13:16:17 -07001713 if (D && receiver.mCallerIdentity.mPid == Process.myPid()) {
1714 mStackTrace = new Throwable();
1715 }
1716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001717 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1718 if (records == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001719 records = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 mRecordsByProvider.put(provider, records);
1721 }
1722 if (!records.contains(this)) {
1723 records.add(this);
1724 }
David Christie2ff96af2014-01-30 16:09:37 -08001725
1726 // Update statistics for historical location requests by package/provider
1727 mRequestStatistics.startRequesting(
Anil Admal08b96122019-01-30 16:55:05 -08001728 mReceiver.mCallerIdentity.mPackageName, provider, request.getInterval(),
Wyatt Rileyf7075e02018-04-12 17:54:26 -07001729 mIsForegroundUid);
1730 }
1731
1732 /**
1733 * Method to be called when record changes foreground/background
1734 */
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001735 private void updateForeground(boolean isForeground) {
Wyatt Rileyf7075e02018-04-12 17:54:26 -07001736 mIsForegroundUid = isForeground;
1737 mRequestStatistics.updateForeground(
Anil Admal08b96122019-01-30 16:55:05 -08001738 mReceiver.mCallerIdentity.mPackageName, mProvider, isForeground);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739 }
1740
1741 /**
David Christie2ff96af2014-01-30 16:09:37 -08001742 * Method to be called when a record will no longer be used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001743 */
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001744 private void disposeLocked(boolean removeReceiver) {
Hongyi Zhang700137e2019-05-23 21:19:36 -07001745 String packageName = mReceiver.mCallerIdentity.mPackageName;
1746 mRequestStatistics.stopRequesting(packageName, mProvider);
1747
1748 mLocationUsageLogger.logLocationApiUsage(
1749 LocationStatsEnums.USAGE_ENDED,
1750 LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
1751 packageName,
1752 mRealRequest,
1753 mReceiver.isListener(),
1754 mReceiver.isPendingIntent(),
Hongyi Zhang0e9ea752019-06-09 22:49:25 -07001755 /* geofence= */ null,
Hongyi Zhang700137e2019-05-23 21:19:36 -07001756 mActivityManager.getPackageImportance(packageName));
David Christie2ff96af2014-01-30 16:09:37 -08001757
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001758 // remove from mRecordsByProvider
1759 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
1760 if (globalRecords != null) {
1761 globalRecords.remove(this);
1762 }
1763
1764 if (!removeReceiver) return; // the caller will handle the rest
1765
1766 // remove from Receiver#mUpdateRecords
1767 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001768 receiverRecords.remove(this.mProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001769
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001770 // and also remove the Receiver if it has no more update records
1771 if (receiverRecords.size() == 0) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00001772 removeUpdatesLocked(mReceiver);
Mike Lockwood3a76fd62009-09-01 07:26:56 -04001773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 }
1775
1776 @Override
1777 public String toString() {
Soonil Nagarkarae6ce772019-05-01 13:16:17 -07001778 StringBuilder b = new StringBuilder("UpdateRecord[");
1779 b.append(mProvider).append(" ");
1780 b.append(mReceiver.mCallerIdentity.mPackageName);
1781 b.append("(").append(mReceiver.mCallerIdentity.mUid);
1782 if (mIsForegroundUid) {
1783 b.append(" foreground");
1784 } else {
1785 b.append(" background");
1786 }
1787 b.append(") ");
1788 b.append(mRealRequest).append(" ").append(mReceiver.mWorkSource);
1789
1790 if (mStackTrace != null) {
1791 ByteArrayOutputStream tmp = new ByteArrayOutputStream();
1792 mStackTrace.printStackTrace(new PrintStream(tmp));
1793 b.append("\n\n").append(tmp.toString()).append("\n");
1794 }
1795
1796 b.append("]");
1797 return b.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001798 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001799 }
1800
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001801 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00001802 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001803 String packageName, @Nullable String featureId, WorkSource workSource,
1804 boolean hideFromAppOps, @NonNull String listenerIdentifier) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001805 IBinder binder = listener.asBinder();
1806 Receiver receiver = mReceivers.get(binder);
1807 if (receiver == null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001808 receiver = new Receiver(listener, null, pid, uid, packageName, featureId, workSource,
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001809 hideFromAppOps, listenerIdentifier);
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001810 if (!receiver.linkToListenerDeathNotificationLocked(
1811 receiver.getListener().asBinder())) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001812 return null;
1813 }
Wen Jingcb3ab222014-03-27 13:42:59 +08001814 mReceivers.put(binder, receiver);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001815 }
1816 return receiver;
1817 }
1818
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001819 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00001820 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001821 @Nullable String featureId, WorkSource workSource, boolean hideFromAppOps,
1822 @NonNull String listenerIdentifier) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001823 Receiver receiver = mReceivers.get(intent);
1824 if (receiver == null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001825 receiver = new Receiver(null, intent, pid, uid, packageName, featureId, workSource,
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001826 hideFromAppOps, listenerIdentifier);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001827 mReceivers.put(intent, receiver);
1828 }
1829 return receiver;
1830 }
1831
Victoria Lease37425c32012-10-16 16:08:48 -07001832 /**
1833 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
1834 * and consistency requirements.
1835 *
1836 * @param request the LocationRequest from which to create a sanitized version
Victoria Lease37425c32012-10-16 16:08:48 -07001837 * @return a version of request that meets the given resolution and consistency requirements
1838 * @hide
1839 */
gomo48f1a642017-11-10 20:35:46 -08001840 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel,
1841 boolean callerHasLocationHardwarePermission) {
Victoria Lease37425c32012-10-16 16:08:48 -07001842 LocationRequest sanitizedRequest = new LocationRequest(request);
gomo48f1a642017-11-10 20:35:46 -08001843 if (!callerHasLocationHardwarePermission) {
1844 // allow setting low power mode only for callers with location hardware permission
1845 sanitizedRequest.setLowPowerMode(false);
1846 }
Victoria Lease37425c32012-10-16 16:08:48 -07001847 if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
1848 switch (sanitizedRequest.getQuality()) {
Victoria Lease09016ab2012-09-16 12:33:15 -07001849 case LocationRequest.ACCURACY_FINE:
Victoria Lease37425c32012-10-16 16:08:48 -07001850 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
Victoria Lease09016ab2012-09-16 12:33:15 -07001851 break;
1852 case LocationRequest.POWER_HIGH:
Victoria Lease37425c32012-10-16 16:08:48 -07001853 sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
Victoria Lease09016ab2012-09-16 12:33:15 -07001854 break;
1855 }
1856 // throttle
Victoria Lease37425c32012-10-16 16:08:48 -07001857 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1858 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001859 }
Victoria Lease37425c32012-10-16 16:08:48 -07001860 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1861 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001862 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07001863 }
Nick Pelly4e31c4f2012-08-13 19:35:39 -07001864 // make getFastestInterval() the minimum of interval and fastest interval
Victoria Lease37425c32012-10-16 16:08:48 -07001865 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001866 sanitizedRequest.setFastestInterval(request.getInterval());
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001867 }
Victoria Lease37425c32012-10-16 16:08:48 -07001868 return sanitizedRequest;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001869 }
1870
Nick Pellye0fd6932012-07-11 10:26:13 -07001871 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001872 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001873 PendingIntent intent, String packageName, String featureId,
1874 String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00001875 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001876
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001877 enforceCallingOrSelfLocationPermission();
1878 enforceCallingOrSelfPackageName(packageName);
1879
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001880 synchronized (mLock) {
1881 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001882 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001883 WorkSource workSource = request.getWorkSource();
1884 if (workSource != null && !workSource.isEmpty()) {
1885 mContext.enforceCallingOrSelfPermission(
1886 Manifest.permission.UPDATE_DEVICE_STATS, null);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08001887 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001888 boolean hideFromAppOps = request.getHideFromAppOps();
1889 if (hideFromAppOps) {
1890 mContext.enforceCallingOrSelfPermission(
1891 Manifest.permission.UPDATE_APP_OPS_STATS, null);
1892 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001893 if (request.isLocationSettingsIgnored()) {
1894 mContext.enforceCallingOrSelfPermission(
1895 Manifest.permission.WRITE_SECURE_SETTINGS, null);
1896 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001897 boolean callerHasLocationHardwarePermission =
1898 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
1899 == PERMISSION_GRANTED;
1900 LocationRequest sanitizedRequest = createSanitizedRequest(request,
1901 allowedResolutionLevel,
1902 callerHasLocationHardwarePermission);
1903
1904 final int pid = Binder.getCallingPid();
1905 final int uid = Binder.getCallingUid();
1906
1907 long identity = Binder.clearCallingIdentity();
1908 try {
1909
1910 // We don't check for MODE_IGNORED here; we will do that when we go to deliver
1911 // a location.
1912 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
1913
1914 if (intent == null && listener == null) {
1915 throw new IllegalArgumentException("need either listener or intent");
1916 } else if (intent != null && listener != null) {
1917 throw new IllegalArgumentException(
1918 "cannot register both listener and intent");
1919 }
1920
Hongyi Zhang700137e2019-05-23 21:19:36 -07001921 mLocationUsageLogger.logLocationApiUsage(
1922 LocationStatsEnums.USAGE_STARTED,
1923 LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
1924 packageName, request, listener != null, intent != null,
Hongyi Zhang0e9ea752019-06-09 22:49:25 -07001925 /* geofence= */ null,
Hongyi Zhang700137e2019-05-23 21:19:36 -07001926 mActivityManager.getPackageImportance(packageName));
1927
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001928 Receiver receiver;
1929 if (intent != null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001930 receiver = getReceiverLocked(intent, pid, uid, packageName, featureId,
1931 workSource, hideFromAppOps, listenerIdentifier);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001932 } else {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001933 receiver = getReceiverLocked(listener, pid, uid, packageName, featureId,
1934 workSource, hideFromAppOps, listenerIdentifier);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001935 }
1936 requestLocationUpdatesLocked(sanitizedRequest, receiver, uid, packageName);
1937 } finally {
1938 Binder.restoreCallingIdentity(identity);
1939 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00001940 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001941 }
1942
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001943 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00001944 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001945 int uid, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001946 // Figure out the provider. Either its explicitly request (legacy use cases), or
1947 // use the fused provider
1948 if (request == null) request = DEFAULT_LOCATION_REQUEST;
1949 String name = request.getProvider();
Victoria Lease09016ab2012-09-16 12:33:15 -07001950 if (name == null) {
1951 throw new IllegalArgumentException("provider name must not be null");
1952 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -07001953
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001954 LocationProviderManager manager = getLocationProviderManager(name);
1955 if (manager == null) {
Victoria Leaseb30f3832013-10-13 12:15:40 -07001956 throw new IllegalArgumentException("provider doesn't exist: " + name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001957 }
1958
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001959 UpdateRecord record = new UpdateRecord(name, request, receiver);
gomo48f1a642017-11-10 20:35:46 -08001960 if (D) {
1961 Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
1962 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
1963 + (record.mIsForegroundUid ? "foreground" : "background")
Anil Admal08b96122019-01-30 16:55:05 -08001964 + (isThrottlingExemptLocked(receiver.mCallerIdentity)
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001965 ? " [whitelisted]" : "") + ")");
gomo48f1a642017-11-10 20:35:46 -08001966 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001967
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001968 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
1969 if (oldRecord != null) {
1970 oldRecord.disposeLocked(false);
1971 }
1972
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08001973 if (!manager.isEnabled() && !isSettingsExemptLocked(record)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001974 // Notify the listener that updates are currently disabled - but only if the request
1975 // does not ignore location settings
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001976 receiver.callProviderEnabledLocked(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001977 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001978
1979 applyRequirementsLocked(name);
1980
David Christie0b837452013-07-29 16:02:13 -07001981 // Update the monitoring here just in case multiple location requests were added to the
1982 // same receiver (this request may be high power and the initial might not have been).
1983 receiver.updateMonitoring(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001984 }
1985
Nick Pellye0fd6932012-07-11 10:26:13 -07001986 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001987 public void removeUpdates(ILocationListener listener, PendingIntent intent,
Soonil Nagarkar68257742019-01-09 19:42:34 +00001988 String packageName) {
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001989 enforceCallingOrSelfPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07001990
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001991 int pid = Binder.getCallingPid();
1992 int uid = Binder.getCallingUid();
1993
1994 if (intent == null && listener == null) {
1995 throw new IllegalArgumentException("need either listener or intent");
1996 } else if (intent != null && listener != null) {
1997 throw new IllegalArgumentException("cannot register both listener and intent");
1998 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001999
Soonil Nagarkar68257742019-01-09 19:42:34 +00002000 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002001 Receiver receiver;
2002 if (intent != null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002003 receiver = getReceiverLocked(intent, pid, uid, packageName, null, null, false, "");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002004 } else {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002005 receiver = getReceiverLocked(listener, pid, uid, packageName, null, null, false,
2006 "");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002007 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002008
Soonil Nagarkar68257742019-01-09 19:42:34 +00002009 long identity = Binder.clearCallingIdentity();
2010 try {
2011 removeUpdatesLocked(receiver);
2012 } finally {
2013 Binder.restoreCallingIdentity(identity);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002014 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002015 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002016 }
2017
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002018 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00002019 private void removeUpdatesLocked(Receiver receiver) {
Dianne Hackborn7ff30112012-11-08 11:12:09 -08002020 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002021
2022 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002023 receiver.unlinkFromListenerDeathNotificationLocked(
2024 receiver.getListener().asBinder());
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08002025 receiver.clearPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002026 }
2027
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07002028 receiver.updateMonitoring(false);
2029
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002030 // Record which providers were associated with this listener
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002031 HashSet<String> providers = new HashSet<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002032 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2033 if (oldRecords != null) {
2034 // Call dispose() on the obsolete update records.
2035 for (UpdateRecord record : oldRecords.values()) {
David Christie2ff96af2014-01-30 16:09:37 -08002036 // Update statistics for historical location requests by package/provider
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002037 record.disposeLocked(false);
2038 }
2039 // Accumulate providers
2040 providers.addAll(oldRecords.keySet());
2041 }
2042
2043 // update provider
2044 for (String provider : providers) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002045 applyRequirementsLocked(provider);
2046 }
2047 }
2048
Nick Pellye0fd6932012-07-11 10:26:13 -07002049 @Override
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002050 public Location getLastLocation(LocationRequest r, String packageName, String featureId) {
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002051 enforceCallingOrSelfLocationPermission();
2052 enforceCallingOrSelfPackageName(packageName);
2053
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002054 synchronized (mLock) {
2055 LocationRequest request = r != null ? r : DEFAULT_LOCATION_REQUEST;
2056 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002057 // no need to sanitize this request, as only the provider name is used
Nick Pelly4035f5a2012-08-17 14:43:49 -07002058
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002059 final int pid = Binder.getCallingPid();
2060 final int uid = Binder.getCallingUid();
2061 final long identity = Binder.clearCallingIdentity();
2062 try {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07002063 if (mSettingsStore.isLocationPackageBlacklisted(UserHandle.getUserId(uid),
2064 packageName)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002065 if (D) {
2066 Log.d(TAG, "not returning last loc for blacklisted app: "
2067 + packageName);
2068 }
2069 return null;
gomo48f1a642017-11-10 20:35:46 -08002070 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002071
Soonil Nagarkar68257742019-01-09 19:42:34 +00002072 // Figure out the provider. Either its explicitly request (deprecated API's),
2073 // or use the fused provider
2074 String name = request.getProvider();
2075 if (name == null) name = LocationManager.FUSED_PROVIDER;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002076 LocationProviderManager manager = getLocationProviderManager(name);
2077 if (manager == null) return null;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002078
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002079 // only the current user or location providers may get location this way
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08002080 if (!mUserInfoStore.isCurrentUserOrProfile(UserHandle.getUserId(uid))
2081 && !isProviderPackage(packageName)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002082 return null;
2083 }
2084
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08002085 if (!manager.isEnabled()) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002086 return null;
2087 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002088
2089 Location location;
2090 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2091 // Make sure that an app with coarse permissions can't get frequent location
2092 // updates by calling LocationManager.getLastKnownLocation repeatedly.
2093 location = mLastLocationCoarseInterval.get(name);
2094 } else {
2095 location = mLastLocation.get(name);
2096 }
2097 if (location == null) {
2098 return null;
2099 }
2100
2101 // Don't return stale location to apps with foreground-only location permission.
2102 String op = resolutionLevelToOpStr(allowedResolutionLevel);
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002103 long locationAgeMs = TimeUnit.NANOSECONDS.toMillis(
2104 SystemClock.elapsedRealtime() - location.getElapsedRealtimeNanos());
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07002105 if (locationAgeMs > mSettingsStore.getMaxLastLocationAgeMs()
Soonil Nagarkar68257742019-01-09 19:42:34 +00002106 && (mAppOps.unsafeCheckOp(op, uid, packageName)
2107 == AppOpsManager.MODE_FOREGROUND)) {
2108 return null;
2109 }
2110
Wei Wang16276a42019-02-04 18:23:31 -08002111 Location lastLocation = null;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002112 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2113 Location noGPSLocation = location.getExtraLocation(
2114 Location.EXTRA_NO_GPS_LOCATION);
2115 if (noGPSLocation != null) {
Wei Wang16276a42019-02-04 18:23:31 -08002116 lastLocation = new Location(mLocationFudger.getOrCreate(noGPSLocation));
Soonil Nagarkar68257742019-01-09 19:42:34 +00002117 }
2118 } else {
Wei Wang16276a42019-02-04 18:23:31 -08002119 lastLocation = new Location(location);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002120 }
Wei Wang16276a42019-02-04 18:23:31 -08002121 // Don't report location access if there is no last location to deliver.
2122 if (lastLocation != null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002123 if (!reportLocationAccessNoThrow(pid, uid, packageName, featureId,
2124 allowedResolutionLevel, null)) {
Wei Wang16276a42019-02-04 18:23:31 -08002125 if (D) {
2126 Log.d(TAG, "not returning last loc for no op app: " + packageName);
2127 }
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002128 lastLocation = null;
Wei Wang16276a42019-02-04 18:23:31 -08002129 }
2130 }
2131 return lastLocation;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002132 } finally {
2133 Binder.restoreCallingIdentity(identity);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002134 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002135 }
2136 }
2137
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002138 @Override
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002139 public boolean getCurrentLocation(LocationRequest locationRequest,
2140 ICancellationSignal remoteCancellationSignal, ILocationListener listener,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002141 String packageName, String featureId, String listenerIdentifier) {
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002142 // side effect of validating locationRequest and packageName
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002143 Location lastLocation = getLastLocation(locationRequest, packageName, featureId);
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002144 if (lastLocation != null) {
2145 long locationAgeMs = TimeUnit.NANOSECONDS.toMillis(
2146 SystemClock.elapsedRealtimeNanos() - lastLocation.getElapsedRealtimeNanos());
2147
2148 long identity = Binder.clearCallingIdentity();
2149 try {
2150 if (locationAgeMs < MAX_CURRENT_LOCATION_AGE_MS) {
2151 try {
2152 listener.onLocationChanged(lastLocation);
2153 return true;
2154 } catch (RemoteException e) {
2155 Log.w(TAG, e);
2156 return false;
2157 }
2158 }
2159
2160 // packageName already validated by getLastLocation() call above
2161 boolean foreground = LocationManagerServiceUtils.isImportanceForeground(
2162 mActivityManager.getPackageImportance(packageName));
2163 if (!foreground) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07002164 if (locationAgeMs < mSettingsStore.getBackgroundThrottleIntervalMs()) {
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002165 // not allowed to request new locations, so we can't return anything
2166 return false;
2167 }
2168 }
2169 } finally {
2170 Binder.restoreCallingIdentity(identity);
2171 }
2172 }
2173
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002174 requestLocationUpdates(locationRequest, listener, null, packageName, featureId,
2175 listenerIdentifier);
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002176 CancellationSignal cancellationSignal = CancellationSignal.fromTransport(
2177 remoteCancellationSignal);
2178 if (cancellationSignal != null) {
2179 cancellationSignal.setOnCancelListener(
2180 () -> removeUpdates(listener, null, packageName));
2181 }
2182 return true;
2183 }
2184
2185 @Override
Chad Brubakerf1133332019-03-15 14:13:59 -07002186 public LocationTime getGnssTimeMillis() {
2187 synchronized (mLock) {
2188 Location location = mLastLocation.get(LocationManager.GPS_PROVIDER);
2189 if (location == null) {
2190 return null;
2191 }
2192 long currentNanos = SystemClock.elapsedRealtimeNanos();
2193 long deltaMs = (currentNanos - location.getElapsedRealtimeNanos()) / 1000000L;
2194 return new LocationTime(location.getTime() + deltaMs, currentNanos);
2195 }
2196 }
2197
2198 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002199 public boolean injectLocation(Location location) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002200 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
2201 "Location Hardware permission not granted to inject location");
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002202 mContext.enforceCallingPermission(ACCESS_FINE_LOCATION,
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002203 "Access Fine Location permission not granted to inject Location");
2204
Soonil Nagarkar68257742019-01-09 19:42:34 +00002205 synchronized (mLock) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002206 LocationProviderManager manager = getLocationProviderManager(location.getProvider());
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08002207 if (manager == null || !manager.isEnabled()) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002208 return false;
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002209 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002210
2211 // NOTE: If last location is already available, location is not injected. If
2212 // provider's normal source (like a GPS chipset) have already provided an output
2213 // there is no need to inject this location.
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002214 if (mLastLocation.get(manager.getName()) != null) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002215 return false;
2216 }
2217
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002218 updateLastLocationLocked(location, manager.getName());
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002219 return true;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002220 }
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002221 }
2222
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002223 @Override
2224 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002225 String packageName, String featureId, String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002226 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002227
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002228 mContext.enforceCallingOrSelfPermission(ACCESS_FINE_LOCATION, null);
2229 enforceCallingOrSelfPackageName(packageName);
2230
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002231 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002232 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002233 if (intent == null) {
2234 throw new IllegalArgumentException("invalid pending intent: " + null);
Victoria Lease56e675b2012-11-05 19:25:06 -08002235 }
Soonil Nagarkar8c4655e2019-02-27 13:00:56 -08002236 // Require that caller can manage given document
2237 boolean callerHasLocationHardwarePermission =
2238 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
2239 == PERMISSION_GRANTED;
2240 LocationRequest sanitizedRequest = createSanitizedRequest(request,
2241 allowedResolutionLevel,
2242 callerHasLocationHardwarePermission);
2243
2244 if (D) {
2245 Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
2246 }
2247
2248 // geo-fence manager uses the public location API, need to clear identity
2249 int uid = Binder.getCallingUid();
2250 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
2251 // temporary measure until geofences work for secondary users
2252 Log.w(TAG, "proximity alerts are currently available only to the primary user");
2253 return;
2254 }
2255 long identity = Binder.clearCallingIdentity();
2256 try {
Hongyi Zhang700137e2019-05-23 21:19:36 -07002257 synchronized (mLock) {
2258 mLocationUsageLogger.logLocationApiUsage(
2259 LocationStatsEnums.USAGE_STARTED,
2260 LocationStatsEnums.API_REQUEST_GEOFENCE,
2261 packageName,
2262 request,
2263 /* hasListener= */ false,
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002264 true,
Hongyi Zhang0e9ea752019-06-09 22:49:25 -07002265 geofence,
Hongyi Zhang700137e2019-05-23 21:19:36 -07002266 mActivityManager.getPackageImportance(packageName));
2267 }
2268
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002269 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002270 uid, packageName, featureId, listenerIdentifier);
Soonil Nagarkar8c4655e2019-02-27 13:00:56 -08002271 } finally {
2272 Binder.restoreCallingIdentity(identity);
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002273 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002274 }
2275
2276 @Override
2277 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002278 if (intent == null) {
2279 throw new IllegalArgumentException("invalid pending intent: " + null);
2280 }
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002281 enforceCallingOrSelfPackageName(packageName);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002282
2283 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2284
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002285 // geo-fence manager uses the public location API, need to clear identity
2286 long identity = Binder.clearCallingIdentity();
2287 try {
Hongyi Zhang700137e2019-05-23 21:19:36 -07002288 synchronized (mLock) {
2289 mLocationUsageLogger.logLocationApiUsage(
2290 LocationStatsEnums.USAGE_ENDED,
2291 LocationStatsEnums.API_REQUEST_GEOFENCE,
2292 packageName,
2293 /* LocationRequest= */ null,
2294 /* hasListener= */ false,
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002295 true,
Hongyi Zhang0e9ea752019-06-09 22:49:25 -07002296 geofence,
Hongyi Zhang700137e2019-05-23 21:19:36 -07002297 mActivityManager.getPackageImportance(packageName));
2298 }
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002299 mGeofenceManager.removeFence(geofence, intent);
2300 } finally {
2301 Binder.restoreCallingIdentity(identity);
2302 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002303 }
2304
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002305 @Override
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002306 public boolean registerGnssStatusCallback(IGnssStatusListener listener, String packageName,
2307 String featureId) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002308 return mGnssManagerService != null && mGnssManagerService.registerGnssStatusCallback(
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002309 listener, packageName, featureId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002310 }
2311
Nick Pellye0fd6932012-07-11 10:26:13 -07002312 @Override
Anil Admal98d49b72019-02-06 15:26:33 -08002313 public void unregisterGnssStatusCallback(IGnssStatusListener listener) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002314 if (mGnssManagerService != null) mGnssManagerService.unregisterGnssStatusCallback(listener);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002315 }
2316
Nick Pellye0fd6932012-07-11 10:26:13 -07002317 @Override
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002318 public boolean addGnssMeasurementsListener(IGnssMeasurementsListener listener,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002319 String packageName, String featureId, String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002320 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002321
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002322 return mGnssManagerService != null && mGnssManagerService.addGnssMeasurementsListener(
2323 listener, packageName, featureId, listenerIdentifier);
Anil Admal52686f82019-02-13 19:04:10 -08002324 }
2325
2326 @Override
2327 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002328 if (mGnssManagerService != null) {
2329 mGnssManagerService.removeGnssMeasurementsListener(
2330 listener);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002331 }
destradaaea8a8a62014-06-23 18:19:03 -07002332 }
2333
2334 @Override
gomo226b7b72018-12-12 16:49:39 -08002335 public void injectGnssMeasurementCorrections(
2336 GnssMeasurementCorrections measurementCorrections, String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002337 if (mGnssManagerService != null) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002338 mGnssManagerService.injectGnssMeasurementCorrections(measurementCorrections,
2339 packageName);
gomo226b7b72018-12-12 16:49:39 -08002340 }
2341 }
2342
2343 @Override
Anil Admal99349782019-03-19 18:58:42 -07002344 public long getGnssCapabilities(String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002345 return mGnssManagerService == null ? 0L : mGnssManagerService.getGnssCapabilities(
2346 packageName);
gomo226b7b72018-12-12 16:49:39 -08002347 }
2348
2349 @Override
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002350 public boolean addGnssNavigationMessageListener(IGnssNavigationMessageListener listener,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002351 String packageName, String featureId, String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002352 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002353
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002354 return mGnssManagerService != null && mGnssManagerService.addGnssNavigationMessageListener(
2355 listener, packageName, featureId, listenerIdentifier);
destradaa4b3e3932014-07-21 18:01:47 -07002356 }
2357
2358 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002359 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002360 if (mGnssManagerService != null) {
2361 mGnssManagerService.removeGnssNavigationMessageListener(
2362 listener);
2363 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002364 }
2365
2366 @Override
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002367 public boolean sendExtraCommand(String providerName, String command, Bundle extras) {
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002368 Objects.requireNonNull(providerName);
2369 Objects.requireNonNull(command);
Soonil Nagarkar3f128402019-12-12 08:31:27 -08002370
2371 mContext.enforceCallingOrSelfPermission(
2372 Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, null);
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002373 enforceCallingOrSelfLocationPermission();
Soonil Nagarkar3f128402019-12-12 08:31:27 -08002374
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002375 mLocationUsageLogger.logLocationApiUsage(
2376 LocationStatsEnums.USAGE_STARTED,
2377 LocationStatsEnums.API_SEND_EXTRA_COMMAND,
2378 providerName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002379
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002380 LocationProviderManager manager = getLocationProviderManager(providerName);
2381 if (manager != null) {
2382 manager.sendExtraCommand(Binder.getCallingUid(), Binder.getCallingPid(), command,
2383 extras);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002384 }
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002385
2386 mLocationUsageLogger.logLocationApiUsage(
2387 LocationStatsEnums.USAGE_ENDED,
2388 LocationStatsEnums.API_SEND_EXTRA_COMMAND,
2389 providerName);
2390
2391 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002392 }
2393
Nick Pellye0fd6932012-07-11 10:26:13 -07002394 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002395 public boolean sendNiResponse(int notifId, int userResponse) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002396 return mGnssManagerService != null && mGnssManagerService.sendNiResponse(notifId,
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002397 userResponse);
Danke Xie22d1f9f2009-08-18 18:28:45 -04002398 }
2399
Nick Pellye0fd6932012-07-11 10:26:13 -07002400 @Override
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002401 public ProviderProperties getProviderProperties(String providerName) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002402 LocationProviderManager manager = getLocationProviderManager(providerName);
2403 if (manager == null) {
2404 return null;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002405 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002406 return manager.getProperties();
Jason Monkb71218a2015-06-17 14:44:39 -04002407 }
2408
Wei Wang980b7c22018-12-06 17:53:00 -08002409 @Override
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08002410 public boolean isProviderPackage(String packageName) {
Soonil Nagarkar514dff42019-04-30 12:04:28 -07002411 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG,
2412 Manifest.permission.READ_DEVICE_CONFIG + " permission required");
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002413 for (LocationProviderManager manager : mProviderManagers) {
2414 if (manager.getPackages().contains(packageName)) {
2415 return true;
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08002416 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002417 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002418 return false;
Maggie2a9409e2018-03-21 11:47:28 -07002419 }
2420
Maggie2a9409e2018-03-21 11:47:28 -07002421 @Override
Wei Wang9f52d552019-10-02 14:49:02 -07002422 public List<String> getProviderPackages(String providerName) {
2423 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG,
2424 Manifest.permission.READ_DEVICE_CONFIG + " permission required");
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002425 LocationProviderManager manager = getLocationProviderManager(providerName);
2426 return manager == null ? Collections.emptyList() : new ArrayList<>(manager.getPackages());
Wei Wang9f52d552019-10-02 14:49:02 -07002427 }
2428
2429 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002430 public void setExtraLocationControllerPackage(String packageName) {
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002431 mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
2432 Manifest.permission.LOCATION_HARDWARE + " permission required");
Soonil Nagarkar68257742019-01-09 19:42:34 +00002433 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002434 mExtraLocationControllerPackage = packageName;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002435 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002436 }
2437
2438 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002439 public String getExtraLocationControllerPackage() {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002440 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002441 return mExtraLocationControllerPackage;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002442 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002443 }
2444
2445 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002446 public void setExtraLocationControllerPackageEnabled(boolean enabled) {
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002447 mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
2448 Manifest.permission.LOCATION_HARDWARE + " permission required");
Soonil Nagarkar68257742019-01-09 19:42:34 +00002449 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002450 mExtraLocationControllerPackageEnabled = enabled;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002451 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002452 }
2453
2454 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002455 public boolean isExtraLocationControllerPackageEnabled() {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002456 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002457 return mExtraLocationControllerPackageEnabled
2458 && (mExtraLocationControllerPackage != null);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002459 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002460 }
2461
2462 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002463 public boolean isLocationEnabledForUser(int userId) {
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002464 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002465 if (UserHandle.getCallingUserId() != userId) {
2466 mContext.enforceCallingOrSelfPermission(
2467 Manifest.permission.INTERACT_ACROSS_USERS,
2468 "Requires INTERACT_ACROSS_USERS permission");
2469 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002470
Soonil Nagarkar68257742019-01-09 19:42:34 +00002471 long identity = Binder.clearCallingIdentity();
2472 try {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07002473 return mSettingsStore.isLocationEnabled(userId);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002474 } finally {
2475 Binder.restoreCallingIdentity(identity);
2476 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002477 }
2478
Maggie2a9409e2018-03-21 11:47:28 -07002479 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002480 public boolean isProviderEnabledForUser(String providerName, int userId) {
Maggie2a9409e2018-03-21 11:47:28 -07002481 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002482 if (UserHandle.getCallingUserId() != userId) {
2483 mContext.enforceCallingOrSelfPermission(
2484 Manifest.permission.INTERACT_ACROSS_USERS,
2485 "Requires INTERACT_ACROSS_USERS permission");
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002486 }
2487
Maggie2a9409e2018-03-21 11:47:28 -07002488 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2489 // so we discourage its use
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002490 if (FUSED_PROVIDER.equals(providerName)) return false;
Maggie2a9409e2018-03-21 11:47:28 -07002491
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002492 synchronized (mLock) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002493 LocationProviderManager manager = getLocationProviderManager(providerName);
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08002494 return manager != null && manager.isEnabled(userId);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002495 }
Maggie2a9409e2018-03-21 11:47:28 -07002496 }
2497
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002498 @GuardedBy("mLock")
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002499 private static boolean shouldBroadcastSafeLocked(
Laurent Tu75defb62012-11-01 16:21:52 -07002500 Location loc, Location lastLoc, UpdateRecord record, long now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002501 // Always broadcast the first update
2502 if (lastLoc == null) {
2503 return true;
2504 }
2505
Nick Pellyf1be6862012-05-15 10:53:42 -07002506 // Check whether sufficient time has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002507 long minTime = record.mRealRequest.getFastestInterval();
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002508 long deltaMs = TimeUnit.NANOSECONDS.toMillis(
2509 loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos());
2510 if (deltaMs < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002511 return false;
2512 }
2513
2514 // Check whether sufficient distance has been traveled
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002515 double minDistance = record.mRealRequest.getSmallestDisplacement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002516 if (minDistance > 0.0) {
2517 if (loc.distanceTo(lastLoc) <= minDistance) {
2518 return false;
2519 }
2520 }
2521
Laurent Tu75defb62012-11-01 16:21:52 -07002522 // Check whether sufficient number of udpates is left
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002523 if (record.mRealRequest.getNumUpdates() <= 0) {
Laurent Tu75defb62012-11-01 16:21:52 -07002524 return false;
2525 }
2526
2527 // Check whether the expiry date has passed
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08002528 return record.mExpirationRealtimeMs >= now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002529 }
2530
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002531 @GuardedBy("mLock")
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002532 private void handleLocationChangedLocked(Location location, LocationProviderManager manager) {
2533 if (!mProviderManagers.contains(manager)) {
2534 Log.w(TAG, "received location from unknown provider: " + manager.getName());
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002535 return;
2536 }
2537 if (!location.isComplete()) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002538 Log.w(TAG, "dropping incomplete location from " + manager.getName() + " provider: "
2539 + location);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002540 return;
2541 }
2542
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002543 // notify passive provider
2544 if (manager != mPassiveManager) {
2545 mPassiveManager.updateLocation(new Location(location));
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002546 }
2547
Soonil Nagarkar68257742019-01-09 19:42:34 +00002548 if (D) Log.d(TAG, "incoming location: " + location);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002549 long now = SystemClock.elapsedRealtime();
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002550
2551
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08002552 // only update last location for locations that come from enabled providers
2553 if (manager.isEnabled()) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002554 updateLastLocationLocked(location, manager.getName());
Mike Lockwood4e50b782009-04-03 08:24:43 -07002555 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002556
David Christie1b9b7b12013-04-15 15:31:11 -07002557 // Update last known coarse interval location if enough time has passed.
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002558 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002559 manager.getName());
David Christie1b9b7b12013-04-15 15:31:11 -07002560 if (lastLocationCoarseInterval == null) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002561 lastLocationCoarseInterval = new Location(location);
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002562
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08002563 if (manager.isEnabled()) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002564 mLastLocationCoarseInterval.put(manager.getName(), lastLocationCoarseInterval);
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002565 }
David Christie1b9b7b12013-04-15 15:31:11 -07002566 }
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002567 long timeDeltaMs = TimeUnit.NANOSECONDS.toMillis(location.getElapsedRealtimeNanos()
2568 - lastLocationCoarseInterval.getElapsedRealtimeNanos());
2569 if (timeDeltaMs > LocationFudger.FASTEST_INTERVAL_MS) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002570 lastLocationCoarseInterval.set(location);
David Christie1b9b7b12013-04-15 15:31:11 -07002571 }
2572 // Don't ever return a coarse location that is more recent than the allowed update
2573 // interval (i.e. don't allow an app to keep registering and unregistering for
2574 // location updates to overcome the minimum interval).
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002575 Location noGPSLocation =
David Christie1b9b7b12013-04-15 15:31:11 -07002576 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2577
Laurent Tu60ec50a2012-10-04 17:00:10 -07002578 // Skip if there are no UpdateRecords for this provider.
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002579 ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName());
Laurent Tu60ec50a2012-10-04 17:00:10 -07002580 if (records == null || records.size() == 0) return;
2581
Victoria Lease09016ab2012-09-16 12:33:15 -07002582 // Fetch coarse location
2583 Location coarseLocation = null;
David Christie1b9b7b12013-04-15 15:31:11 -07002584 if (noGPSLocation != null) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002585 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
2586 }
2587
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002588 ArrayList<Receiver> deadReceivers = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002589 ArrayList<UpdateRecord> deadUpdateRecords = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07002590
Soonil Nagarkar94749f72018-11-08 11:46:43 -08002591 // Broadcast location to all listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002592 for (UpdateRecord r : records) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593 Receiver receiver = r.mReceiver;
Mike Lockwood03ca2162010-04-01 08:10:09 -07002594 boolean receiverDead = false;
Nick Pelly4035f5a2012-08-17 14:43:49 -07002595
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08002596 if (!manager.isEnabled() && !isSettingsExemptLocked(r)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002597 continue;
2598 }
2599
Anil Admal08b96122019-01-30 16:55:05 -08002600 int receiverUserId = UserHandle.getUserId(receiver.mCallerIdentity.mUid);
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08002601 if (!mUserInfoStore.isCurrentUserOrProfile(receiverUserId)
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08002602 && !isProviderPackage(receiver.mCallerIdentity.mPackageName)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002603 if (D) {
Victoria Lease269518e2012-10-29 08:25:39 -07002604 Log.d(TAG, "skipping loc update for background user " + receiverUserId +
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08002605 " (app: " + receiver.mCallerIdentity.mPackageName + ")");
Victoria Leaseb711d572012-10-02 13:14:11 -07002606 }
2607 continue;
2608 }
2609
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07002610 if (mSettingsStore.isLocationPackageBlacklisted(receiverUserId,
2611 receiver.mCallerIdentity.mPackageName)) {
gomo48f1a642017-11-10 20:35:46 -08002612 if (D) {
2613 Log.d(TAG, "skipping loc update for blacklisted app: " +
Anil Admal08b96122019-01-30 16:55:05 -08002614 receiver.mCallerIdentity.mPackageName);
gomo48f1a642017-11-10 20:35:46 -08002615 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07002616 continue;
2617 }
2618
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002619 Location notifyLocation;
Victoria Lease37425c32012-10-16 16:08:48 -07002620 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2621 notifyLocation = coarseLocation; // use coarse location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002622 } else {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002623 notifyLocation = location; // use fine location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002624 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002625 if (notifyLocation != null) {
2626 Location lastLoc = r.mLastFixBroadcast;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002627 if ((lastLoc == null)
2628 || shouldBroadcastSafeLocked(notifyLocation, lastLoc, r, now)) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002629 if (lastLoc == null) {
2630 lastLoc = new Location(notifyLocation);
2631 r.mLastFixBroadcast = lastLoc;
2632 } else {
2633 lastLoc.set(notifyLocation);
2634 }
Wei Wang8486fc72019-03-07 18:49:21 -08002635 // Report location access before delivering location to the client. This will
2636 // note location delivery to appOps, so it should be called only when a
2637 // location is really being delivered to the client.
2638 if (!reportLocationAccessNoThrow(
2639 receiver.mCallerIdentity.mPid,
2640 receiver.mCallerIdentity.mUid,
2641 receiver.mCallerIdentity.mPackageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002642 receiver.mCallerIdentity.mFeatureId,
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002643 receiver.mAllowedResolutionLevel,
2644 "Location sent to " + receiver.mCallerIdentity.mListenerIdentifier)) {
Wei Wang8486fc72019-03-07 18:49:21 -08002645 if (D) {
2646 Log.d(TAG, "skipping loc update for no op app: "
2647 + receiver.mCallerIdentity.mPackageName);
2648 }
2649 continue;
2650 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002651 if (!receiver.callLocationChangedLocked(notifyLocation)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002652 Slog.w(TAG, "RemoteException calling onLocationChanged on "
2653 + receiver);
Victoria Lease09016ab2012-09-16 12:33:15 -07002654 receiverDead = true;
2655 }
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002656 r.mRealRequest.decrementNumUpdates();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002657 }
2658 }
2659
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002660 // track expired records
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08002661 if (r.mRealRequest.getNumUpdates() <= 0 || r.mExpirationRealtimeMs < now) {
Soonil Nagarkar39d614a2019-10-31 12:10:31 -07002662 // notify the client it can remove this listener
2663 r.mReceiver.callRemovedLocked();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002664 if (deadUpdateRecords == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002665 deadUpdateRecords = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002666 }
2667 deadUpdateRecords.add(r);
2668 }
2669 // track dead receivers
2670 if (receiverDead) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002671 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002672 deadReceivers = new ArrayList<>();
Mike Lockwood03ca2162010-04-01 08:10:09 -07002673 }
2674 if (!deadReceivers.contains(receiver)) {
2675 deadReceivers.add(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002676 }
2677 }
2678 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002679
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002680 // remove dead records and receivers outside the loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002681 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002682 for (Receiver receiver : deadReceivers) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002683 removeUpdatesLocked(receiver);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002684 }
2685 }
2686 if (deadUpdateRecords != null) {
2687 for (UpdateRecord r : deadUpdateRecords) {
2688 r.disposeLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002689 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002690 applyRequirementsLocked(manager);
Victoria Lease8b38b292012-12-04 15:04:43 -08002691 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002692 }
2693
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002694 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00002695 private void updateLastLocationLocked(Location location, String provider) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002696 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2697 Location lastNoGPSLocation;
2698 Location lastLocation = mLastLocation.get(provider);
2699 if (lastLocation == null) {
2700 lastLocation = new Location(provider);
2701 mLastLocation.put(provider, lastLocation);
2702 } else {
2703 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2704 if (noGPSLocation == null && lastNoGPSLocation != null) {
2705 // New location has no no-GPS location: adopt last no-GPS location. This is set
2706 // directly into location because we do not want to notify COARSE clients.
2707 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
2708 }
2709 }
2710 lastLocation.set(location);
2711 }
2712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002713 // Geocoder
2714
Nick Pellye0fd6932012-07-11 10:26:13 -07002715 @Override
Mike Lockwoode15735a2010-09-20 17:48:47 -04002716 public boolean geocoderIsPresent() {
Mark Vandevoorde01ac80b2010-05-21 15:43:26 -07002717 return mGeocodeProvider != null;
2718 }
2719
Nick Pellye0fd6932012-07-11 10:26:13 -07002720 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002721 public String getFromLocation(double latitude, double longitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002722 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002723 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002724 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
2725 params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002726 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002727 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002728 }
2729
Mike Lockwooda55c3212009-04-15 11:10:11 -04002730
Nick Pellye0fd6932012-07-11 10:26:13 -07002731 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002732 public String getFromLocationName(String locationName,
Mike Lockwooda55c3212009-04-15 11:10:11 -04002733 double lowerLeftLatitude, double lowerLeftLongitude,
2734 double upperRightLatitude, double upperRightLongitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002735 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002736
2737 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002738 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
2739 lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
2740 maxResults, params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002741 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002742 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002743 }
2744
2745 // Mock Providers
2746
Nick Pellye0fd6932012-07-11 10:26:13 -07002747 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002748 public void addTestProvider(String provider, ProviderProperties properties,
2749 String packageName) {
2750 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2751 != AppOpsManager.MODE_ALLOWED) {
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002752 return;
2753 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002754
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002755 synchronized (mLock) {
2756 LocationProviderManager manager = getLocationProviderManager(provider);
2757 if (manager == null) {
2758 manager = new LocationProviderManager(provider);
2759 mProviderManagers.add(manager);
2760 }
2761
2762 manager.setMockProvider(new MockProvider(mContext, properties));
2763 }
2764 }
2765
2766 @Override
2767 public void removeTestProvider(String provider, String packageName) {
2768 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2769 != AppOpsManager.MODE_ALLOWED) {
2770 return;
Mike Lockwooda4903f22010-02-17 06:42:23 -05002771 }
2772
Soonil Nagarkar68257742019-01-09 19:42:34 +00002773 synchronized (mLock) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002774 LocationProviderManager manager = getLocationProviderManager(provider);
2775 if (manager == null) {
2776 return;
2777 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002778
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002779 manager.setMockProvider(null);
2780 if (!manager.hasProvider()) {
2781 mProviderManagers.remove(manager);
2782 mLastLocation.remove(manager.getName());
2783 mLastLocationCoarseInterval.remove(manager.getName());
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002784 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002785 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09002786 }
2787
Nick Pellye0fd6932012-07-11 10:26:13 -07002788 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002789 public void setTestProviderLocation(String provider, Location location, String packageName) {
2790 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2791 != AppOpsManager.MODE_ALLOWED) {
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002792 return;
2793 }
2794
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002795 LocationProviderManager manager = getLocationProviderManager(provider);
2796 if (manager == null) {
2797 throw new IllegalArgumentException("provider doesn't exist: " + provider);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002798 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002799
2800 manager.setMockProviderLocation(location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002801 }
2802
Nick Pellye0fd6932012-07-11 10:26:13 -07002803 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002804 public void setTestProviderEnabled(String provider, boolean enabled, String packageName) {
2805 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2806 != AppOpsManager.MODE_ALLOWED) {
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002807 return;
2808 }
2809
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002810 LocationProviderManager manager = getLocationProviderManager(provider);
2811 if (manager == null) {
2812 throw new IllegalArgumentException("provider doesn't exist: " + provider);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002813 }
2814
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08002815 manager.setMockProviderAllowed(enabled);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002816 }
2817
2818 @Override
Kweku Adams4fb074e2019-02-01 16:03:27 -08002819 @NonNull
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002820 public List<LocationRequest> getTestProviderCurrentRequests(String provider,
2821 String packageName) {
2822 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2823 != AppOpsManager.MODE_ALLOWED) {
Kweku Adams4fb074e2019-02-01 16:03:27 -08002824 return Collections.emptyList();
2825 }
2826
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002827 LocationProviderManager manager = getLocationProviderManager(provider);
2828 if (manager == null) {
2829 throw new IllegalArgumentException("provider doesn't exist: " + provider);
Kweku Adams4fb074e2019-02-01 16:03:27 -08002830 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002831
2832 return manager.getMockProviderRequests();
Kweku Adams4fb074e2019-02-01 16:03:27 -08002833 }
2834
2835 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002836 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002837 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) {
2838 return;
2839 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002840
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002841 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
2842
Soonil Nagarkar68257742019-01-09 19:42:34 +00002843 synchronized (mLock) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002844 if (mGnssManagerService != null && args.length > 0 && args[0].equals("--gnssmetrics")) {
2845 mGnssManagerService.dump(fd, pw, args);
Blake Kragten47014d22019-12-06 14:18:38 -08002846 return;
Siddharth Raybb608c82017-03-16 11:33:34 -07002847 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002848
2849 ipw.println("Location Manager State:");
2850 ipw.increaseIndent();
2851 ipw.print("Current System Time: "
WyattRileyba6072f2019-04-18 07:37:52 -07002852 + TimeUtils.logTimeOfDay(System.currentTimeMillis()));
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002853 ipw.println(", Current Elapsed Time: "
WyattRileyba6072f2019-04-18 07:37:52 -07002854 + TimeUtils.formatDuration(SystemClock.elapsedRealtime()));
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08002855
2856 ipw.println("User Info:");
2857 ipw.increaseIndent();
2858 mUserInfoStore.dump(fd, ipw, args);
2859 ipw.decreaseIndent();
2860
2861 ipw.println("Location Settings:");
2862 ipw.increaseIndent();
2863 mSettingsStore.dump(fd, ipw, args);
2864 ipw.decreaseIndent();
2865
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002866 ipw.println("Battery Saver Location Mode: "
Kweku Adams4fb074e2019-02-01 16:03:27 -08002867 + locationPowerSaveModeToString(mBatterySaverMode));
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002868
2869 ipw.println("Location Listeners:");
2870 ipw.increaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002871 for (Receiver receiver : mReceivers.values()) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002872 ipw.println(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002873 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002874 ipw.decreaseIndent();
2875
2876 ipw.println("Active Records by Provider:");
2877 ipw.increaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002878 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002879 ipw.println(entry.getKey() + ":");
2880 ipw.increaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002881 for (UpdateRecord record : entry.getValue()) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002882 ipw.println(record);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002883 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002884 ipw.decreaseIndent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002885 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002886 ipw.decreaseIndent();
Anil Admal98d49b72019-02-06 15:26:33 -08002887
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002888 ipw.println("Historical Records by Provider:");
2889 ipw.increaseIndent();
WyattRileyd6b82a62019-12-30 18:12:50 -08002890 TreeMap<PackageProviderKey, PackageStatistics> sorted = new TreeMap<>();
2891 sorted.putAll(mRequestStatistics.statistics);
David Christie2ff96af2014-01-30 16:09:37 -08002892 for (Map.Entry<PackageProviderKey, PackageStatistics> entry
WyattRileyd6b82a62019-12-30 18:12:50 -08002893 : sorted.entrySet()) {
David Christie2ff96af2014-01-30 16:09:37 -08002894 PackageProviderKey key = entry.getKey();
WyattRileyd6b82a62019-12-30 18:12:50 -08002895 ipw.println(key.providerName + ": " + key.packageName + ": " + entry.getValue());
David Christie2ff96af2014-01-30 16:09:37 -08002896 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002897 ipw.decreaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002898
WyattRileyfa1ef8d32019-12-30 17:19:55 -08002899 mRequestStatistics.history.dump(ipw);
2900
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002901 ipw.println("Last Known Locations:");
2902 ipw.increaseIndent();
2903 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
2904 ipw.println(entry.getKey() + ": " + entry.getValue());
David Christie1b9b7b12013-04-15 15:31:11 -07002905 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002906 ipw.decreaseIndent();
2907
2908 ipw.println("Last Known Coarse Locations:");
2909 ipw.increaseIndent();
2910 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
2911 ipw.println(entry.getKey() + ": " + entry.getValue());
2912 }
2913 ipw.decreaseIndent();
David Christie1b9b7b12013-04-15 15:31:11 -07002914
Tyler Trephan2f3ee9a2019-03-21 10:54:22 -07002915 if (mGeofenceManager != null) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002916 ipw.println("Geofences:");
2917 ipw.increaseIndent();
2918 mGeofenceManager.dump(ipw);
2919 ipw.decreaseIndent();
Tyler Trephan2f3ee9a2019-03-21 10:54:22 -07002920 }
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002921
Wei Wang114922a2019-01-30 18:19:35 -08002922 if (mExtraLocationControllerPackage != null) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002923 ipw.println("Location Controller Extra Package: " + mExtraLocationControllerPackage
2924 + (mExtraLocationControllerPackageEnabled ? " [enabled]" : "[disabled]"));
Wei Wang980b7c22018-12-06 17:53:00 -08002925 }
2926
Tyler Trephan2f3ee9a2019-03-21 10:54:22 -07002927 if (mLocationFudger != null) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002928 ipw.println("Location Fudger:");
2929 ipw.increaseIndent();
2930 mLocationFudger.dump(fd, ipw, args);
2931 ipw.decreaseIndent();
Tyler Trephan2f3ee9a2019-03-21 10:54:22 -07002932 }
Anil Admal98d49b72019-02-06 15:26:33 -08002933
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08002934 ipw.println("Location Providers:");
2935 ipw.increaseIndent();
2936 for (LocationProviderManager manager : mProviderManagers) {
2937 manager.dump(fd, ipw, args);
2938 }
2939 ipw.decreaseIndent();
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002940
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002941 if (mGnssManagerService != null) {
2942 ipw.println("GNSS:");
2943 ipw.increaseIndent();
2944 mGnssManagerService.dump(fd, ipw, args);
2945 ipw.decreaseIndent();
2946 }
Anil Admal98d49b72019-02-06 15:26:33 -08002947 }
2948 }
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08002949
2950 private class LocalService extends LocationManagerInternal {
2951
2952 @Override
2953 public void requestSetProviderAllowed(String provider, boolean allowed) {
2954 Preconditions.checkArgument(provider != null, "invalid null provider");
2955
2956 synchronized (mLock) {
2957 LocationProviderManager manager = getLocationProviderManager(provider);
2958 if (manager != null) {
2959 manager.requestSetAllowed(allowed);
2960 }
2961 }
2962 }
2963 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002964}