blob: 3bc93cc1302389d9894dd0d5f15a9d69d03cdea5 [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.AppOpsManager;
34import android.app.PendingIntent;
35import android.content.BroadcastReceiver;
Maggieaa080f92018-01-04 15:35:11 -080036import android.content.Context;
37import android.content.Intent;
38import android.content.IntentFilter;
Maggieaa080f92018-01-04 15:35:11 -080039import android.content.pm.PackageManager;
Maggieaa080f92018-01-04 15:35:11 -080040import android.location.Address;
41import android.location.Criteria;
42import android.location.GeocoderParams;
43import android.location.Geofence;
gomo226b7b72018-12-12 16:49:39 -080044import android.location.GnssMeasurementCorrections;
Maggieaa080f92018-01-04 15:35:11 -080045import android.location.IBatchedLocationCallback;
46import android.location.IGnssMeasurementsListener;
47import android.location.IGnssNavigationMessageListener;
48import android.location.IGnssStatusListener;
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -080049import android.location.IGpsGeofenceHardware;
Maggieaa080f92018-01-04 15:35:11 -080050import android.location.ILocationListener;
51import android.location.ILocationManager;
Maggieaa080f92018-01-04 15:35:11 -080052import android.location.Location;
53import android.location.LocationManager;
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -080054import android.location.LocationManagerInternal;
Maggieaa080f92018-01-04 15:35:11 -080055import android.location.LocationRequest;
Chad Brubakerf1133332019-03-15 14:13:59 -070056import android.location.LocationTime;
Maggieaa080f92018-01-04 15:35:11 -080057import android.os.Binder;
58import android.os.Bundle;
Soonil Nagarkar905e7222019-10-01 12:03:29 -070059import android.os.CancellationSignal;
Maggieaa080f92018-01-04 15:35:11 -080060import android.os.Handler;
61import android.os.IBinder;
Soonil Nagarkar905e7222019-10-01 12:03:29 -070062import android.os.ICancellationSignal;
Maggieaa080f92018-01-04 15:35:11 -080063import android.os.PowerManager;
Kweku Adams4fb074e2019-02-01 16:03:27 -080064import android.os.PowerManager.ServiceType;
65import android.os.PowerManagerInternal;
Maggieaa080f92018-01-04 15:35:11 -080066import android.os.Process;
67import android.os.RemoteException;
68import android.os.SystemClock;
69import android.os.UserHandle;
Maggieaa080f92018-01-04 15:35:11 -080070import android.os.WorkSource;
Narayan Kamath32684dd2018-01-08 17:32:51 +000071import android.os.WorkSource.WorkChain;
Hongyi Zhang700137e2019-05-23 21:19:36 -070072import android.stats.location.LocationStatsEnums;
Maggieaa080f92018-01-04 15:35:11 -080073import android.text.TextUtils;
Maggieaa080f92018-01-04 15:35:11 -080074import android.util.EventLog;
75import android.util.Log;
76import android.util.Slog;
Soonil Nagarkar06e37f62019-12-04 16:05:08 -080077import android.util.SparseArray;
WyattRileyba6072f2019-04-18 07:37:52 -070078import android.util.TimeUtils;
Yu-Han Yanga4d250e2018-10-02 21:29:20 -070079
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -080080import com.android.internal.annotations.GuardedBy;
destradaaea8a8a62014-06-23 18:19:03 -070081import com.android.internal.content.PackageMonitor;
82import com.android.internal.location.ProviderProperties;
83import com.android.internal.location.ProviderRequest;
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -080084import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060085import com.android.internal.util.DumpUtils;
Soonil Nagarkar1c572552019-07-10 13:31:47 -070086import com.android.internal.util.IndentingPrintWriter;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -080087import com.android.internal.util.Preconditions;
Soonil Nagarkar1575a042018-10-24 17:54:54 -070088import com.android.server.location.AbstractLocationProvider;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -080089import com.android.server.location.AbstractLocationProvider.State;
Soonil Nagarkarb6375a42020-01-29 15:23:06 -080090import com.android.server.location.AppForegroundHelper;
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 Nagarkar3f128402019-12-12 08:31:27 -0800101import com.android.server.location.LocationUsageLogger;
destradaaea8a8a62014-06-23 18:19:03 -0700102import com.android.server.location.MockProvider;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800103import com.android.server.location.MockableLocationProvider;
destradaaea8a8a62014-06-23 18:19:03 -0700104import com.android.server.location.PassiveProvider;
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800105import com.android.server.location.SettingsHelper;
106import com.android.server.location.UserInfoHelper;
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);
143 }
144
145 @Override
146 public void onStart() {
147 publishBinderService(Context.LOCATION_SERVICE, mService);
148 }
149
150 @Override
151 public void onBootPhase(int phase) {
Soonil Nagarkar37096062019-11-25 13:24:48 -0800152 if (phase == PHASE_SYSTEM_SERVICES_READY) {
153 // the location service must be functioning after this boot phase
154 mService.onSystemReady();
155 } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
156 // some providers rely on third party code, so we wait to initialize
157 // providers until third party code is allowed to run
158 mService.onSystemThirdPartyAppsCanStart();
Soonil Nagarkar141417a2019-10-28 11:12:48 -0700159 }
160 }
161 }
162
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800163 public static final String TAG = "LocationManagerService";
JP Abgrallf79811e72013-02-01 18:45:05 -0800164 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700165
Olivier Gaillard7a222662017-11-20 16:07:24 +0000166 private static final String WAKELOCK_KEY = "*location*";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167
Victoria Lease37425c32012-10-16 16:08:48 -0700168 private static final int RESOLUTION_LEVEL_NONE = 0;
Victoria Lease37425c32012-10-16 16:08:48 -0700169 private static final int RESOLUTION_LEVEL_COARSE = 1;
Victoria Lease37425c32012-10-16 16:08:48 -0700170 private static final int RESOLUTION_LEVEL_FINE = 2;
171
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700172 private static final String NETWORK_LOCATION_SERVICE_ACTION =
Stan Chesnutt39062dd2013-07-22 14:33:30 -0700173 "com.android.location.service.v3.NetworkLocationProvider";
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700174 private static final String FUSED_LOCATION_SERVICE_ACTION =
175 "com.android.location.service.FusedLocationProvider";
176
David Christie0b837452013-07-29 16:02:13 -0700177 // The maximum interval a location request can have and still be considered "high power".
178 private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
179
Soonil Nagarkar905e7222019-10-01 12:03:29 -0700180 // maximum age of a location before it is no longer considered "current"
181 private static final long MAX_CURRENT_LOCATION_AGE_MS = 10 * 1000;
182
Nick Pellyf1be6862012-05-15 10:53:42 -0700183 // Location Providers may sometimes deliver location updates
184 // slightly faster that requested - provide grace period so
185 // we don't unnecessarily filter events that are otherwise on
186 // time
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700187 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
Nick Pellyf1be6862012-05-15 10:53:42 -0700188
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700189 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
190
Soonil Nagarkar68257742019-01-09 19:42:34 +0000191 private final Object mLock = new Object();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800192 private final Context mContext;
193 private final Handler mHandler;
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800194 private final LocalService mLocalService;
195 private final UserInfoHelper mUserInfoHelper;
196 private final SettingsHelper mSettingsHelper;
197 private final AppForegroundHelper mAppForegroundHelper;
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800198 private final LocationUsageLogger mLocationUsageLogger;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700199
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800200 @Nullable private GnssManagerService mGnssManagerService = null;
201
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 Nagarkar90da1ab2019-01-04 16:26:59 -0800207
208 private GeofenceManager mGeofenceManager;
209 private LocationFudger mLocationFudger;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700210 private GeocoderProxy mGeocodeProvider;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800211
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800212 @GuardedBy("mLock")
Wei Wang114922a2019-01-30 18:19:35 -0800213 private String mExtraLocationControllerPackage;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800214 @GuardedBy("mLock")
Wei Wang114922a2019-01-30 18:19:35 -0800215 private boolean mExtraLocationControllerPackageEnabled;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700216
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800217 // @GuardedBy("mLock")
218 // hold lock for write or to prevent write, no lock for read
219 private final CopyOnWriteArrayList<LocationProviderManager> mProviderManagers =
220 new CopyOnWriteArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800222 @GuardedBy("mLock")
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800223 private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700224 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800225 new HashMap<>();
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700226
David Christie2ff96af2014-01-30 16:09:37 -0800227 private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics();
228
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700229 // mapping from provider name to last known location
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800230 @GuardedBy("mLock")
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800231 private final HashMap<String, Location> mLastLocation = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232
David Christie1b9b7b12013-04-15 15:31:11 -0700233 // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
234 // locations stored here are not fudged for coarse permissions.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800235 @GuardedBy("mLock")
David Christie1b9b7b12013-04-15 15:31:11 -0700236 private final HashMap<String, Location> mLastLocationCoarseInterval =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800237 new HashMap<>();
David Christie1b9b7b12013-04-15 15:31:11 -0700238
Kweku Adams4fb074e2019-02-01 16:03:27 -0800239 @GuardedBy("mLock")
240 @PowerManager.LocationPowerSaveMode
241 private int mBatterySaverMode;
242
Soonil Nagarkar141417a2019-10-28 11:12:48 -0700243 private LocationManagerService(Context context) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700244 mContext = context;
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -0800245 mHandler = FgThread.getHandler();
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800246 mLocalService = new LocalService();
247
248 LocalServices.addService(LocationManagerInternal.class, mLocalService);
249
250 mUserInfoHelper = new UserInfoHelper(mContext);
251 mSettingsHelper = new SettingsHelper(mContext, mHandler);
252 mAppForegroundHelper = new AppForegroundHelper(mContext);
Hongyi Zhang700137e2019-05-23 21:19:36 -0700253 mLocationUsageLogger = new LocationUsageLogger();
The Android Open Source Project4df24232009-03-05 14:34:35 -0800254
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800255 // set up passive provider - we do this early because it has no dependencies on system
256 // services or external code that isn't ready yet, and because this allows the variable to
257 // be final. other more complex providers are initialized later, when system services are
258 // ready
259 mPassiveManager = new PassiveLocationProviderManager();
260 mProviderManagers.add(mPassiveManager);
261 mPassiveManager.setRealProvider(new PassiveProvider(mContext));
262
Svet Ganovadc1cf42015-06-15 16:36:24 -0700263 // Let the package manager query which are the default location
264 // providers as they get certain permissions granted by default.
Todd Kennedy583378d2019-07-12 06:50:30 -0700265 PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
266 PermissionManagerServiceInternal.class);
267 permissionManagerInternal.setLocationPackagesProvider(
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700268 userId -> mContext.getResources().getStringArray(
269 com.android.internal.R.array.config_locationProviderPackageNames));
Todd Kennedy583378d2019-07-12 06:50:30 -0700270 permissionManagerInternal.setLocationExtraPackagesProvider(
Wei Wangffb94e62019-01-14 00:05:45 -0800271 userId -> mContext.getResources().getStringArray(
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700272 com.android.internal.R.array.config_locationExtraPackageNames));
Svet Ganovadc1cf42015-06-15 16:36:24 -0700273
Soonil Nagarkar37096062019-11-25 13:24:48 -0800274 // most startup is deferred until systemReady()
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700275 }
276
Soonil Nagarkar37096062019-11-25 13:24:48 -0800277 private void onSystemReady() {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800278 mUserInfoHelper.onSystemReady();
279 mSettingsHelper.onSystemReady();
280 mAppForegroundHelper.onSystemReady();
281
282 if (GnssManagerService.isGnssSupported()) {
283 mGnssManagerService = new GnssManagerService(mContext, mSettingsHelper,
284 mAppForegroundHelper, mLocationUsageLogger);
285 mGnssManagerService.onSystemReady();
286 }
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800287
Soonil Nagarkar68257742019-01-09 19:42:34 +0000288 synchronized (mLock) {
Soonil Nagarkar37096062019-11-25 13:24:48 -0800289 mPackageManager = mContext.getPackageManager();
290 mAppOps = mContext.getSystemService(AppOpsManager.class);
291 mPowerManager = mContext.getSystemService(PowerManager.class);
Soonil Nagarkar37096062019-11-25 13:24:48 -0800292
Soonil Nagarkar37096062019-11-25 13:24:48 -0800293 mLocationFudger = new LocationFudger(mContext, mHandler);
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800294 mGeofenceManager = new GeofenceManager(mContext, mSettingsHelper);
Soonil Nagarkar37096062019-11-25 13:24:48 -0800295
296 PowerManagerInternal localPowerManager =
297 LocalServices.getService(PowerManagerInternal.class);
298
299 // add listeners
300 mAppOps.startWatchingMode(
301 AppOpsManager.OP_COARSE_LOCATION,
302 null,
303 AppOpsManager.WATCH_FOREGROUND_CHANGES,
304 new AppOpsManager.OnOpChangedInternalListener() {
305 public void onOpChanged(int op, String packageName) {
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800306 // onOpChanged invoked on ui thread, move to our thread to reduce risk
307 // of blocking ui thread
Soonil Nagarkar37096062019-11-25 13:24:48 -0800308 mHandler.post(() -> {
309 synchronized (mLock) {
310 onAppOpChangedLocked();
311 }
312 });
313 }
314 });
315 mPackageManager.addOnPermissionsChangeListener(
316 uid -> {
317 // listener invoked on ui thread, move to our thread to reduce risk of
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800318 // blocking ui thread
Soonil Nagarkar37096062019-11-25 13:24:48 -0800319 mHandler.post(() -> {
320 synchronized (mLock) {
321 onPermissionsChangedLocked();
322 }
323 });
324 });
Soonil Nagarkar37096062019-11-25 13:24:48 -0800325
326 localPowerManager.registerLowPowerModeObserver(ServiceType.LOCATION,
327 state -> {
328 // listener invoked on ui thread, move to our thread to reduce risk of
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800329 // blocking ui thread
Soonil Nagarkar37096062019-11-25 13:24:48 -0800330 mHandler.post(() -> {
331 synchronized (mLock) {
332 onBatterySaverModeChangedLocked(state.locationMode);
333 }
334 });
335 });
336 mBatterySaverMode = mPowerManager.getLocationPowerSaveMode();
337
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800338 mSettingsHelper.addOnLocationEnabledChangedListener(this::onLocationModeChanged);
339 mSettingsHelper.addOnBackgroundThrottleIntervalChangedListener(
340 this::onBackgroundThrottleIntervalChanged);
341 mSettingsHelper.addOnBackgroundThrottlePackageWhitelistChangedListener(
342 this::onBackgroundThrottleWhitelistChanged);
343 mSettingsHelper.addOnIgnoreSettingsPackageWhitelistChangedListener(
344 this::onIgnoreSettingsWhitelistChanged);
Soonil Nagarkar37096062019-11-25 13:24:48 -0800345
346 new PackageMonitor() {
347 @Override
348 public void onPackageDisappeared(String packageName, int reason) {
349 synchronized (mLock) {
350 LocationManagerService.this.onPackageDisappearedLocked(packageName);
351 }
352 }
353 }.register(mContext, mHandler.getLooper(), true);
354
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800355 mUserInfoHelper.addListener(this::onUserChanged);
356
357 mAppForegroundHelper.addListener(this::onAppForegroundChanged);
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800358
Soonil Nagarkar37096062019-11-25 13:24:48 -0800359 IntentFilter intentFilter = new IntentFilter();
Soonil Nagarkar37096062019-11-25 13:24:48 -0800360 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
361 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
362
363 mContext.registerReceiverAsUser(new BroadcastReceiver() {
364 @Override
365 public void onReceive(Context context, Intent intent) {
366 final String action = intent.getAction();
367 if (action == null) {
368 return;
369 }
370 synchronized (mLock) {
371 switch (action) {
Soonil Nagarkar37096062019-11-25 13:24:48 -0800372 case Intent.ACTION_SCREEN_ON:
373 case Intent.ACTION_SCREEN_OFF:
374 onScreenStateChangedLocked();
375 break;
376 }
377 }
378 }
379 }, UserHandle.ALL, intentFilter, null, mHandler);
380
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800381 // switching the user from null to current here performs the bulk of the initialization
Soonil Nagarkar37096062019-11-25 13:24:48 -0800382 // work. the user being changed will cause a reload of all user specific settings, which
383 // causes initialization, and propagates changes until a steady state is reached
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800384 onUserChanged(UserHandle.USER_NULL, mUserInfoHelper.getCurrentUserId());
Victoria Lease5cd731a2012-12-19 15:04:21 -0800385 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800386 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700387
Soonil Nagarkar37096062019-11-25 13:24:48 -0800388 private void onSystemThirdPartyAppsCanStart() {
389 synchronized (mLock) {
390 // prepare providers
391 initializeProvidersLocked();
392 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700393 }
394
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800395 @GuardedBy("mLock")
396 private void onAppOpChangedLocked() {
397 for (Receiver receiver : mReceivers.values()) {
398 receiver.updateMonitoring(true);
399 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800400 for (LocationProviderManager manager : mProviderManagers) {
401 applyRequirementsLocked(manager);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800402 }
403 }
404
405 @GuardedBy("mLock")
406 private void onPermissionsChangedLocked() {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800407 for (LocationProviderManager manager : mProviderManagers) {
408 applyRequirementsLocked(manager);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800409 }
410 }
411
412 @GuardedBy("mLock")
Kweku Adams4fb074e2019-02-01 16:03:27 -0800413 private void onBatterySaverModeChangedLocked(int newLocationMode) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700414 if (mBatterySaverMode == newLocationMode) {
415 return;
416 }
417
Kweku Adams4fb074e2019-02-01 16:03:27 -0800418 if (D) {
419 Slog.d(TAG,
420 "Battery Saver location mode changed from "
421 + locationPowerSaveModeToString(mBatterySaverMode) + " to "
422 + locationPowerSaveModeToString(newLocationMode));
423 }
424
Kweku Adams4fb074e2019-02-01 16:03:27 -0800425 mBatterySaverMode = newLocationMode;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700426
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800427 for (LocationProviderManager manager : mProviderManagers) {
428 applyRequirementsLocked(manager);
Kweku Adams4fb074e2019-02-01 16:03:27 -0800429 }
430 }
431
432 @GuardedBy("mLock")
433 private void onScreenStateChangedLocked() {
434 if (mBatterySaverMode == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800435 for (LocationProviderManager manager : mProviderManagers) {
436 applyRequirementsLocked(manager);
Kweku Adams4fb074e2019-02-01 16:03:27 -0800437 }
438 }
439 }
440
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800441 private void onLocationModeChanged(int userId) {
442 boolean enabled = mSettingsHelper.isLocationEnabled(userId);
443
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800444 if (D) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800445 Log.d(TAG, "[u" + userId + "] location enabled = " + enabled);
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800446 }
447
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800448 synchronized (mLock) {
449 Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION)
450 .putExtra(LocationManager.EXTRA_LOCATION_ENABLED, enabled)
451 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
452 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
453 mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800454
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800455 for (LocationProviderManager manager : mProviderManagers) {
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800456 manager.onEnabledChangedLocked(userId);
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800457 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800458 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800459 }
460
461 @GuardedBy("mLock")
462 private void onPackageDisappearedLocked(String packageName) {
463 ArrayList<Receiver> deadReceivers = null;
464
465 for (Receiver receiver : mReceivers.values()) {
Anil Admal08b96122019-01-30 16:55:05 -0800466 if (receiver.mCallerIdentity.mPackageName.equals(packageName)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800467 if (deadReceivers == null) {
468 deadReceivers = new ArrayList<>();
469 }
470 deadReceivers.add(receiver);
471 }
472 }
473
474 // perform removal outside of mReceivers loop
475 if (deadReceivers != null) {
476 for (Receiver receiver : deadReceivers) {
477 removeUpdatesLocked(receiver);
478 }
479 }
480 }
481
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800482 private void onAppForegroundChanged(int uid, boolean foreground) {
483 synchronized (mLock) {
484 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
485 for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
486 String provider = entry.getKey();
487 for (UpdateRecord record : entry.getValue()) {
488 if (record.mReceiver.mCallerIdentity.mUid == uid
489 && record.mIsForegroundUid != foreground) {
490 record.updateForeground(foreground);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800491
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800492 if (!isThrottlingExempt(record.mReceiver.mCallerIdentity)) {
493 affectedProviders.add(provider);
494 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700495 }
496 }
497 }
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800498 for (String provider : affectedProviders) {
499 applyRequirementsLocked(provider);
500 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800501 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800502 }
503
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800504 private void onBackgroundThrottleIntervalChanged() {
505 synchronized (mLock) {
506 for (LocationProviderManager manager : mProviderManagers) {
507 applyRequirementsLocked(manager);
508 }
Soonil Nagarkar68257742019-01-09 19:42:34 +0000509 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -0800510 }
511
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800512 private void onBackgroundThrottleWhitelistChanged() {
513 synchronized (mLock) {
514 for (LocationProviderManager manager : mProviderManagers) {
515 applyRequirementsLocked(manager);
516 }
Soonil Nagarkar68257742019-01-09 19:42:34 +0000517 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -0800518 }
519
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800520 private void onIgnoreSettingsWhitelistChanged() {
521 synchronized (mLock) {
522 for (LocationProviderManager manager : mProviderManagers) {
523 applyRequirementsLocked(manager);
524 }
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800525 }
526 }
527
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800528 @GuardedBy("mLock")
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800529 private void initializeProvidersLocked() {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800530 if (mGnssManagerService != null) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800531 LocationProviderManager gnssManager = new LocationProviderManager(GPS_PROVIDER);
532 mProviderManagers.add(gnssManager);
533 gnssManager.setRealProvider(mGnssManagerService.getGnssLocationProvider());
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700534 }
535
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800536 LocationProviderProxy networkProvider = LocationProviderProxy.createAndRegister(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700537 mContext,
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700538 NETWORK_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700539 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800540 com.android.internal.R.string.config_networkLocationProviderPackageName);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700541 if (networkProvider != null) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800542 LocationProviderManager networkManager = new LocationProviderManager(NETWORK_PROVIDER);
543 mProviderManagers.add(networkManager);
544 networkManager.setRealProvider(networkProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700545 } else {
gomo48f1a642017-11-10 20:35:46 -0800546 Slog.w(TAG, "no network location provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700547 }
548
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800549 // ensure that a fused provider exists which will work in direct boot
550 Preconditions.checkState(!mContext.getPackageManager().queryIntentServicesAsUser(
551 new Intent(FUSED_LOCATION_SERVICE_ACTION),
552 MATCH_DIRECT_BOOT_AWARE | MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM).isEmpty(),
553 "Unable to find a direct boot aware fused location provider");
554
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700555 // bind to fused provider
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800556 LocationProviderProxy fusedProvider = LocationProviderProxy.createAndRegister(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700557 mContext,
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700558 FUSED_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700559 com.android.internal.R.bool.config_enableFusedLocationOverlay,
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800560 com.android.internal.R.string.config_fusedLocationProviderPackageName);
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700561 if (fusedProvider != null) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800562 LocationProviderManager fusedManager = new LocationProviderManager(FUSED_PROVIDER);
563 mProviderManagers.add(fusedManager);
564 fusedManager.setRealProvider(fusedProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700565 } else {
566 Slog.e(TAG, "no fused location provider found",
567 new IllegalStateException("Location service needs a fused location provider"));
568 }
569
570 // bind to geocoder provider
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800571 mGeocodeProvider = GeocoderProxy.createAndRegister(mContext);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700572 if (mGeocodeProvider == null) {
gomo48f1a642017-11-10 20:35:46 -0800573 Slog.e(TAG, "no geocoder provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700574 }
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700575
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800576 // bind to geofence proxy
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700577 if (mGnssManagerService != null) {
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800578 IGpsGeofenceHardware gpsGeofenceHardware = mGnssManagerService.getGpsGeofenceProxy();
579 if (gpsGeofenceHardware != null) {
580 GeofenceProxy provider = GeofenceProxy.createAndBind(mContext, gpsGeofenceHardware);
581 if (provider == null) {
582 Slog.d(TAG, "unable to bind to GeofenceProxy");
583 }
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700584 }
destradaa0682809a2013-08-12 18:50:30 -0700585 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900586
Brian Duddiecfa5b5b2019-01-22 18:01:40 +0000587 // bind to hardware activity recognition
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800588 HardwareActivityRecognitionProxy hardwareActivityRecognitionProxy =
589 HardwareActivityRecognitionProxy.createAndRegister(mContext);
590 if (hardwareActivityRecognitionProxy == null) {
591 Log.e(TAG, "unable to bind ActivityRecognitionProxy");
Brian Duddiecfa5b5b2019-01-22 18:01:40 +0000592 }
593
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800594 String[] testProviderStrings = mContext.getResources().getStringArray(
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900595 com.android.internal.R.array.config_testLocationProviders);
596 for (String testProviderString : testProviderStrings) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -0800597 String[] fragments = testProviderString.split(",");
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900598 String name = fragments[0].trim();
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900599 ProviderProperties properties = new ProviderProperties(
600 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
601 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
602 Boolean.parseBoolean(fragments[3]) /* requiresCell */,
603 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
604 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
605 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
606 Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
607 Integer.parseInt(fragments[8]) /* powerRequirement */,
608 Integer.parseInt(fragments[9]) /* accuracy */);
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800609 addTestProvider(name, properties, mContext.getOpPackageName());
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900610 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700611 }
Mike Lockwood9637d472009-04-02 21:41:57 -0700612
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800613 private void onUserChanged(int oldUserId, int newUserId) {
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800614 if (D) {
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800615 Log.d(TAG, "foreground user is changing to " + newUserId);
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800616 }
617
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800618 synchronized (mLock) {
619 for (LocationProviderManager manager : mProviderManagers) {
620 // update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility
621 mSettingsHelper.setLocationProviderAllowed(manager.getName(),
622 manager.isEnabled(newUserId), newUserId);
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800623
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800624 manager.onEnabledChangedLocked(oldUserId);
625 manager.onEnabledChangedLocked(newUserId);
626 }
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800627 }
Victoria Lease38389b62012-09-30 11:44:22 -0700628 }
629
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700630 /**
631 * Location provider manager, manages a LocationProvider.
632 */
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800633 class LocationProviderManager implements MockableLocationProvider.Listener {
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700634
635 private final String mName;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700636
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800637 // acquiring mLock makes operations on mProvider atomic, but is otherwise unnecessary
638 protected final MockableLocationProvider mProvider;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700639
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800640 // enabled state for parent user ids, no entry implies false. location state is only kept
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800641 // for parent user ids, the location state for a profile user id is assumed to be the same
642 // as for the parent. if querying this structure, ensure that the user id being used is a
643 // parent id or the results may be incorrect.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800644 @GuardedBy("mLock")
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800645 private final SparseArray<Boolean> mEnabled;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700646
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800647 private LocationProviderManager(String name) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800648 mName = name;
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800649 mEnabled = new SparseArray<>(1);
Soonil Nagarkar42da1b12019-01-22 11:29:27 -0800650
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800651 // initialize last since this lets our reference escape
652 mProvider = new MockableLocationProvider(mContext, mLock, this);
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800653
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800654 // we can assume all users start with disabled location state since the initial state
655 // of all providers is disabled. no need to initialize mEnabled further.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800656 }
657
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700658 public String getName() {
659 return mName;
660 }
661
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800662 public boolean hasProvider() {
663 return mProvider.getProvider() != null;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700664 }
665
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800666 public void setRealProvider(AbstractLocationProvider provider) {
667 mProvider.setRealProvider(provider);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800668 }
669
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800670 public void setMockProvider(@Nullable MockProvider provider) {
671 mProvider.setMockProvider(provider);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800672 }
673
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800674 public Set<String> getPackages() {
675 return mProvider.getState().providerPackageNames;
676 }
677
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700678 @Nullable
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800679 public ProviderProperties getProperties() {
680 return mProvider.getState().properties;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700681 }
682
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800683 public void setMockProviderAllowed(boolean enabled) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800684 synchronized (mLock) {
685 if (!mProvider.isMock()) {
686 throw new IllegalArgumentException(mName + " provider is not a test provider");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800687 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800688
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800689 mProvider.setMockProviderAllowed(enabled);
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800690 }
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700691 }
692
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800693 public void setMockProviderLocation(Location location) {
694 synchronized (mLock) {
695 if (!mProvider.isMock()) {
696 throw new IllegalArgumentException(mName + " provider is not a test provider");
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700697 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800698
699 String locationProvider = location.getProvider();
700 if (!TextUtils.isEmpty(locationProvider) && !mName.equals(locationProvider)) {
701 // The location has an explicit provider that is different from the mock
702 // provider name. The caller may be trying to fool us via b/33091107.
703 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
704 mName + "!=" + locationProvider);
705 }
706
707 mProvider.setMockProviderLocation(location);
708 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700709 }
710
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800711 public List<LocationRequest> getMockProviderRequests() {
712 synchronized (mLock) {
713 if (!mProvider.isMock()) {
714 throw new IllegalArgumentException(mName + " provider is not a test provider");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800715 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800716
717 return mProvider.getCurrentRequest().locationRequests;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800718 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800719 }
720
721 public void setRequest(ProviderRequest request) {
722 mProvider.setRequest(request);
723 }
724
725 public void sendExtraCommand(int uid, int pid, String command, Bundle extras) {
726 mProvider.sendExtraCommand(uid, pid, command, extras);
727 }
728
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800729 @GuardedBy("mLock")
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700730 @Override
731 public void onReportLocation(Location location) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800732 // don't validate mock locations
733 if (!location.isFromMockProvider()) {
734 if (location.getLatitude() == 0 && location.getLongitude() == 0) {
735 Slog.w(TAG, "blocking 0,0 location from " + mName + " provider");
736 return;
737 }
Soonil Nagarkar7fc24c62019-10-18 17:32:38 -0700738 }
739
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800740 handleLocationChangedLocked(location, this);
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700741 }
742
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800743 @GuardedBy("mLock")
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700744 @Override
745 public void onReportLocation(List<Location> locations) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700746 if (mGnssManagerService == null) {
747 return;
748 }
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700749
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800750 if (!GPS_PROVIDER.equals(mName) || !isEnabled()) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800751 Slog.w(TAG, "reportLocationBatch() called without user permission");
752 return;
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700753 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800754
755 mGnssManagerService.onReportLocation(locations);
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700756 }
757
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800758 @GuardedBy("mLock")
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700759 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800760 public void onStateChanged(State oldState, State newState) {
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800761 if (oldState.allowed != newState.allowed) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800762 // it would be more correct to call this for all users, but we know this can
763 // only affect the current user since providers are disabled for non-current
764 // users
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800765 onEnabledChangedLocked(mUserInfoHelper.getCurrentUserId());
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700766 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700767 }
768
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800769 public void requestSetAllowed(boolean allowed) {
770 mProvider.requestSetAllowed(allowed);
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800771 }
772
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800773 public boolean isEnabled() {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800774 return isEnabled(mUserInfoHelper.getCurrentUserId());
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800775 }
776
777 public boolean isEnabled(int userId) {
Soonil Nagarkar66c0bac2019-01-15 13:36:44 -0800778 synchronized (mLock) {
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800779 // normalize user id to always refer to parent since profile state is always the
780 // same as parent state
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800781 userId = mUserInfoHelper.getParentUserId(userId);
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800782 return mEnabled.get(userId, Boolean.FALSE);
Soonil Nagarkar66c0bac2019-01-15 13:36:44 -0800783 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700784 }
785
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800786 @GuardedBy("mLock")
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800787 public void onEnabledChangedLocked(int userId) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800788 if (userId == UserHandle.USER_NULL) {
789 // only used during initialization - we don't care about the null user
790 return;
791 }
792
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800793 // normalize user id to always refer to parent since profile state is always the same
794 // as parent state
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800795 userId = mUserInfoHelper.getParentUserId(userId);
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800796
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800797 // if any property that contributes to "enabled" here changes state, it MUST result
798 // in a direct or indrect call to onEnabledChangedLocked. this allows the provider to
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800799 // guarantee that it will always eventually reach the correct state.
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800800 boolean enabled = (userId == mUserInfoHelper.getCurrentUserId())
801 && mSettingsHelper.isLocationEnabled(userId) && mProvider.getState().allowed;
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800802
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800803 if (enabled == isEnabled(userId)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800804 return;
805 }
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800806
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800807 mEnabled.put(userId, enabled);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800808
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800809 if (D) {
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800810 Log.d(TAG, "[u" + userId + "] " + mName + " provider enabled = " + enabled);
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800811 }
812
Soonil Nagarkar57f4b7b2019-12-09 10:19:18 -0800813 // fused and passive provider never get public updates for legacy reasons
814 if (!FUSED_PROVIDER.equals(mName) && !PASSIVE_PROVIDER.equals(mName)) {
815 // update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800816 mSettingsHelper.setLocationProviderAllowed(mName, enabled, userId);
Soonil Nagarkar57f4b7b2019-12-09 10:19:18 -0800817
Soonil Nagarkardbd467e2020-01-14 15:10:45 -0800818 Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION)
819 .putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName)
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800820 .putExtra(LocationManager.EXTRA_PROVIDER_ENABLED, enabled)
Soonil Nagarkardbd467e2020-01-14 15:10:45 -0800821 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
822 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Soonil Nagarkar57f4b7b2019-12-09 10:19:18 -0800823 mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
824 }
825
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800826 if (!enabled) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800827 // If any provider has been disabled, clear all last locations for all
828 // providers. This is to be on the safe side in case a provider has location
829 // derived from this disabled provider.
830 mLastLocation.clear();
831 mLastLocationCoarseInterval.clear();
832 }
833
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800834 updateProviderEnabledLocked(this);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800835 }
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800836
837 public void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
838 synchronized (mLock) {
839 pw.print(mName + " provider");
840 if (mProvider.isMock()) {
841 pw.print(" [mock]");
842 }
843 pw.println(":");
844
845 pw.increaseIndent();
846
Soonil Nagarkared5a2002020-01-28 10:53:53 -0800847 pw.println("enabled=" + isEnabled());
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800848 }
849
850 mProvider.dump(fd, pw, args);
851
852 pw.decreaseIndent();
853 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800854 }
855
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800856 class PassiveLocationProviderManager extends LocationProviderManager {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800857
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800858 private PassiveLocationProviderManager() {
859 super(PASSIVE_PROVIDER);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800860 }
861
862 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800863 public void setRealProvider(AbstractLocationProvider provider) {
864 Preconditions.checkArgument(provider instanceof PassiveProvider);
865 super.setRealProvider(provider);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800866 }
867
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800868 @Override
869 public void setMockProvider(@Nullable MockProvider provider) {
870 if (provider != null) {
871 throw new IllegalArgumentException("Cannot mock the passive provider");
872 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800873 }
874
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800875 public void updateLocation(Location location) {
876 synchronized (mLock) {
877 PassiveProvider passiveProvider = (PassiveProvider) mProvider.getProvider();
878 Preconditions.checkState(passiveProvider != null);
879
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800880 long identity = Binder.clearCallingIdentity();
881 try {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800882 passiveProvider.updateLocation(location);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800883 } finally {
884 Binder.restoreCallingIdentity(identity);
Soonil Nagarkar68257742019-01-09 19:42:34 +0000885 }
886 }
887 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700888 }
889
Victoria Lease38389b62012-09-30 11:44:22 -0700890 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800891 * A wrapper class holding either an ILocationListener or a PendingIntent to receive
892 * location updates.
893 */
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700894 private final class Receiver extends LocationManagerServiceUtils.LinkedListenerBase implements
895 PendingIntent.OnFinished {
Yu-Han Yang24189822018-07-11 15:24:11 -0700896 private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700897 private final int mAllowedResolutionLevel; // resolution level allowed to receiver
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700898
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700899 private final ILocationListener mListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800900 final PendingIntent mPendingIntent;
David Christie82edc9b2013-07-19 11:31:42 -0700901 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700902 private final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
903 private final Object mKey;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700904
gomo48f1a642017-11-10 20:35:46 -0800905 final HashMap<String, UpdateRecord> mUpdateRecords = new HashMap<>();
Nick Pellyf1be6862012-05-15 10:53:42 -0700906
David Christie0b837452013-07-29 16:02:13 -0700907 // True if app ops has started monitoring this receiver for locations.
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700908 private boolean mOpMonitoring;
David Christie0b837452013-07-29 16:02:13 -0700909 // True if app ops has started monitoring this receiver for high power (gps) locations.
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700910 private boolean mOpHighPowerMonitoring;
911 private int mPendingBroadcasts;
Victoria Lease0aa28602013-05-29 15:28:26 -0700912 PowerManager.WakeLock mWakeLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800913
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700914 private Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -0700915 String packageName, @Nullable String featureId, WorkSource workSource,
916 boolean hideFromAppOps, @NonNull String listenerIdentifier) {
917 super(new CallerIdentity(uid, pid, packageName, featureId, listenerIdentifier),
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -0700918 "LocationListener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800919 mListener = listener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800920 mPendingIntent = intent;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700921 if (listener != null) {
922 mKey = listener.asBinder();
923 } else {
924 mKey = intent;
925 }
Victoria Lease37425c32012-10-16 16:08:48 -0700926 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
Narayan Kamath32684dd2018-01-08 17:32:51 +0000927 if (workSource != null && workSource.isEmpty()) {
David Christie82edc9b2013-07-19 11:31:42 -0700928 workSource = null;
929 }
930 mWorkSource = workSource;
David Christie40e57822013-07-30 11:36:48 -0700931 mHideFromAppOps = hideFromAppOps;
Victoria Lease0aa28602013-05-29 15:28:26 -0700932
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700933 updateMonitoring(true);
934
Victoria Lease0aa28602013-05-29 15:28:26 -0700935 // construct/configure wakelock
936 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
David Christie82edc9b2013-07-19 11:31:42 -0700937 if (workSource == null) {
Anil Admal08b96122019-01-30 16:55:05 -0800938 workSource = new WorkSource(mCallerIdentity.mUid, mCallerIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -0700939 }
940 mWakeLock.setWorkSource(workSource);
Yu-Han Yang24189822018-07-11 15:24:11 -0700941
942 // For a non-reference counted wakelock, each acquire will reset the timeout, and we
943 // only need to release it once.
944 mWakeLock.setReferenceCounted(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800945 }
946
947 @Override
948 public boolean equals(Object otherObj) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800949 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950 }
951
952 @Override
953 public int hashCode() {
954 return mKey.hashCode();
955 }
Mike Lockwood3681f262009-05-12 10:52:03 -0400956
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 @Override
958 public String toString() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700959 StringBuilder s = new StringBuilder();
960 s.append("Reciever[");
961 s.append(Integer.toHexString(System.identityHashCode(this)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800962 if (mListener != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700963 s.append(" listener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700965 s.append(" intent");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800966 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700967 for (String p : mUpdateRecords.keySet()) {
968 s.append(" ").append(mUpdateRecords.get(p).toString());
969 }
Wei Wangdd070f22018-06-21 11:29:40 -0700970 s.append(" monitoring location: ").append(mOpMonitoring);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700971 s.append("]");
972 return s.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 }
974
David Christie15b31912013-08-13 15:54:32 -0700975 /**
976 * Update AppOp monitoring for this receiver.
977 *
978 * @param allow If true receiver is currently active, if false it's been removed.
979 */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700980 public void updateMonitoring(boolean allow) {
David Christie40e57822013-07-30 11:36:48 -0700981 if (mHideFromAppOps) {
982 return;
983 }
984
David Christie15b31912013-08-13 15:54:32 -0700985 boolean requestingLocation = false;
986 boolean requestingHighPowerLocation = false;
987 if (allow) {
988 // See if receiver has any enabled update records. Also note if any update records
989 // are high power (has a high power provider with an interval under a threshold).
990 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800991 LocationProviderManager manager = getLocationProviderManager(
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800992 updateRecord.mProvider);
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800993 if (manager == null) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -0800994 continue;
995 }
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800996 if (!manager.isEnabled() && !isSettingsExempt(updateRecord)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800997 continue;
998 }
999
1000 requestingLocation = true;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001001 ProviderProperties properties = manager.getProperties();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001002 if (properties != null
1003 && properties.mPowerRequirement == Criteria.POWER_HIGH
1004 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
1005 requestingHighPowerLocation = true;
1006 break;
David Christie15b31912013-08-13 15:54:32 -07001007 }
1008 }
1009 }
1010
David Christie0b837452013-07-29 16:02:13 -07001011 // First update monitoring of any location request (including high power).
David Christie15b31912013-08-13 15:54:32 -07001012 mOpMonitoring = updateMonitoring(
1013 requestingLocation,
1014 mOpMonitoring,
David Christie0b837452013-07-29 16:02:13 -07001015 AppOpsManager.OP_MONITOR_LOCATION);
1016
1017 // Now update monitoring of high power requests only.
David Christiec750c1f2013-08-08 12:56:57 -07001018 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
David Christie15b31912013-08-13 15:54:32 -07001019 mOpHighPowerMonitoring = updateMonitoring(
1020 requestingHighPowerLocation,
1021 mOpHighPowerMonitoring,
David Christie0b837452013-07-29 16:02:13 -07001022 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
David Christiec750c1f2013-08-08 12:56:57 -07001023 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
David Christie15b31912013-08-13 15:54:32 -07001024 // Send an intent to notify that a high power request has been added/removed.
David Christiec750c1f2013-08-08 12:56:57 -07001025 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
1026 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
1027 }
David Christie0b837452013-07-29 16:02:13 -07001028 }
1029
1030 /**
1031 * Update AppOps monitoring for a single location request and op type.
1032 *
gomo48f1a642017-11-10 20:35:46 -08001033 * @param allowMonitoring True if monitoring is allowed for this request/op.
David Christie0b837452013-07-29 16:02:13 -07001034 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
gomo48f1a642017-11-10 20:35:46 -08001035 * @param op AppOps code for the op to update.
David Christie0b837452013-07-29 16:02:13 -07001036 * @return True if monitoring is on for this request/op after updating.
1037 */
1038 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
1039 int op) {
1040 if (!currentlyMonitoring) {
1041 if (allowMonitoring) {
Anil Admal08b96122019-01-30 16:55:05 -08001042 return mAppOps.startOpNoThrow(op, mCallerIdentity.mUid,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001043 mCallerIdentity.mPackageName, false, mCallerIdentity.mFeatureId, null)
1044 == AppOpsManager.MODE_ALLOWED;
David Christie0b837452013-07-29 16:02:13 -07001045 }
1046 } else {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001047 if (!allowMonitoring
Wei Wang16276a42019-02-04 18:23:31 -08001048 || mAppOps.checkOpNoThrow(op, mCallerIdentity.mUid,
Anil Admal08b96122019-01-30 16:55:05 -08001049 mCallerIdentity.mPackageName) != AppOpsManager.MODE_ALLOWED) {
1050 mAppOps.finishOp(op, mCallerIdentity.mUid, mCallerIdentity.mPackageName);
David Christie0b837452013-07-29 16:02:13 -07001051 return false;
1052 }
1053 }
1054
1055 return currentlyMonitoring;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001056 }
1057
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058 public boolean isListener() {
1059 return mListener != null;
1060 }
1061
1062 public boolean isPendingIntent() {
1063 return mPendingIntent != null;
1064 }
1065
1066 public ILocationListener getListener() {
1067 if (mListener != null) {
1068 return mListener;
1069 }
1070 throw new IllegalStateException("Request for non-existent listener");
1071 }
1072
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001073 public boolean callLocationChangedLocked(Location location) {
1074 if (mListener != null) {
1075 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001076 mListener.onLocationChanged(new Location(location));
1077 // call this after broadcasting so we do not increment
1078 // if we throw an exception.
1079 incrementPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001080 } catch (RemoteException e) {
1081 return false;
1082 }
1083 } else {
1084 Intent locationChanged = new Intent();
gomo48f1a642017-11-10 20:35:46 -08001085 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED,
1086 new Location(location));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001088 mPendingIntent.send(mContext, 0, locationChanged, this, mHandler,
1089 getResolutionPermission(mAllowedResolutionLevel),
1090 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
1091 // call this after broadcasting so we do not increment
1092 // if we throw an exception.
1093 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001094 } catch (PendingIntent.CanceledException e) {
1095 return false;
1096 }
1097 }
1098 return true;
1099 }
1100
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001101 private boolean callProviderEnabledLocked(String provider, boolean enabled) {
David Christie15b31912013-08-13 15:54:32 -07001102 // First update AppOp monitoring.
1103 // An app may get/lose location access as providers are enabled/disabled.
1104 updateMonitoring(true);
1105
Mike Lockwood48f17512009-04-23 09:12:08 -07001106 if (mListener != null) {
1107 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001108 if (enabled) {
1109 mListener.onProviderEnabled(provider);
1110 } else {
1111 mListener.onProviderDisabled(provider);
Mike Lockwood48f17512009-04-23 09:12:08 -07001112 }
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001113 // call this after broadcasting so we do not increment
1114 // if we throw an exception.
1115 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001116 } catch (RemoteException e) {
1117 return false;
1118 }
1119 } else {
1120 Intent providerIntent = new Intent();
1121 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1122 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001123 mPendingIntent.send(mContext, 0, providerIntent, this, mHandler,
1124 getResolutionPermission(mAllowedResolutionLevel),
1125 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
1126 // call this after broadcasting so we do not increment
1127 // if we throw an exception.
1128 incrementPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001129 } catch (PendingIntent.CanceledException e) {
1130 return false;
1131 }
1132 }
1133 return true;
1134 }
1135
Soonil Nagarkar39d614a2019-10-31 12:10:31 -07001136 public void callRemovedLocked() {
1137 if (mListener != null) {
1138 try {
1139 mListener.onRemoved();
1140 } catch (RemoteException e) {
1141 // doesn't matter
1142 }
1143 }
1144 }
1145
Nick Pellyf1be6862012-05-15 10:53:42 -07001146 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001147 public void binderDied() {
Anil Admal98d49b72019-02-06 15:26:33 -08001148 if (D) Log.d(TAG, "Remote " + mListenerName + " died.");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001149
Soonil Nagarkar68257742019-01-09 19:42:34 +00001150 synchronized (mLock) {
1151 removeUpdatesLocked(this);
Soonil Nagarkar68257742019-01-09 19:42:34 +00001152 clearPendingBroadcastsLocked();
1153 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001154 }
1155
Nick Pellye0fd6932012-07-11 10:26:13 -07001156 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001157 public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1158 int resultCode, String resultData, Bundle resultExtras) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001159 synchronized (mLock) {
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001160 decrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001161 }
1162 }
1163
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001164 // this must be called while synchronized by caller in a synchronized block
1165 // containing the sending of the broadcaset
1166 private void incrementPendingBroadcastsLocked() {
Yu-Han Yang24189822018-07-11 15:24:11 -07001167 mPendingBroadcasts++;
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001168 // so wakelock calls will succeed
1169 long identity = Binder.clearCallingIdentity();
1170 try {
1171 mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
1172 } finally {
1173 Binder.restoreCallingIdentity(identity);
1174 }
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001175 }
1176
1177 private void decrementPendingBroadcastsLocked() {
1178 if (--mPendingBroadcasts == 0) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001179 // so wakelock calls will succeed
1180 long identity = Binder.clearCallingIdentity();
1181 try {
1182 if (mWakeLock.isHeld()) {
1183 mWakeLock.release();
1184 }
1185 } finally {
1186 Binder.restoreCallingIdentity(identity);
Victoria Lease0aa28602013-05-29 15:28:26 -07001187 }
1188 }
1189 }
1190
1191 public void clearPendingBroadcastsLocked() {
1192 if (mPendingBroadcasts > 0) {
1193 mPendingBroadcasts = 0;
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001194 // so wakelock calls will succeed
1195 long identity = Binder.clearCallingIdentity();
1196 try {
1197 if (mWakeLock.isHeld()) {
1198 mWakeLock.release();
1199 }
1200 } finally {
1201 Binder.restoreCallingIdentity(identity);
Victoria Lease0aa28602013-05-29 15:28:26 -07001202 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001203 }
1204 }
1205 }
1206
Nick Pellye0fd6932012-07-11 10:26:13 -07001207 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001208 public void locationCallbackFinished(ILocationListener listener) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001209 //Do not use getReceiverLocked here as that will add the ILocationListener to
Joshua Bartel080b61b2009-10-05 12:44:46 -04001210 //the receiver list if it is not found. If it is not found then the
1211 //LocationListener was removed when it had a pending broadcast and should
1212 //not be added back.
Soonil Nagarkar68257742019-01-09 19:42:34 +00001213 synchronized (mLock) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001214 Receiver receiver = mReceivers.get(listener.asBinder());
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001215 if (receiver != null) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001216 receiver.decrementPendingBroadcastsLocked();
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001217 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00001218 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001219 }
1220
Lifu Tang82f893d2016-01-21 18:15:33 -08001221 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001222 public int getGnssYearOfHardware() {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001223 return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001224 }
1225
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001226 @Override
Wyatt Riley49097c02018-03-15 09:14:43 -07001227 @Nullable
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001228 public String getGnssHardwareModelName() {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001229 return mGnssManagerService == null ? "" : mGnssManagerService.getGnssHardwareModelName();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001230 }
1231
Wyatt Rileycf879db2017-01-12 13:57:38 -08001232 @Override
1233 public int getGnssBatchSize(String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001234 return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssBatchSize(packageName);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001235 }
1236
Wyatt Rileycf879db2017-01-12 13:57:38 -08001237 @Override
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001238 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001239 String featureId, String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00001240 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001241
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001242 return mGnssManagerService != null && mGnssManagerService.addGnssBatchingCallback(
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001243 callback, packageName, featureId, listenerIdentifier);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001244 }
1245
Wyatt Rileycf879db2017-01-12 13:57:38 -08001246 @Override
1247 public void removeGnssBatchingCallback() {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001248 if (mGnssManagerService != null) mGnssManagerService.removeGnssBatchingCallback();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001249 }
1250
Wyatt Rileycf879db2017-01-12 13:57:38 -08001251 @Override
1252 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001253 return mGnssManagerService != null && mGnssManagerService.startGnssBatch(periodNanos,
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001254 wakeOnFifoFull, packageName);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001255 }
1256
Wyatt Rileycf879db2017-01-12 13:57:38 -08001257 @Override
1258 public void flushGnssBatch(String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001259 if (mGnssManagerService != null) mGnssManagerService.flushGnssBatch(packageName);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001260 }
1261
Wyatt Rileycf879db2017-01-12 13:57:38 -08001262 @Override
1263 public boolean stopGnssBatch() {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001264 return mGnssManagerService != null && mGnssManagerService.stopGnssBatch();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001265 }
1266
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001267 @Nullable
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001268 private LocationProviderManager getLocationProviderManager(String providerName) {
1269 for (LocationProviderManager manager : mProviderManagers) {
1270 if (providerName.equals(manager.getName())) {
1271 return manager;
Soonil Nagarkar68257742019-01-09 19:42:34 +00001272 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001273 }
1274
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001275 return null;
Maggie2a9409e2018-03-21 11:47:28 -07001276 }
1277
Victoria Lease37425c32012-10-16 16:08:48 -07001278 private String getResolutionPermission(int resolutionLevel) {
1279 switch (resolutionLevel) {
1280 case RESOLUTION_LEVEL_FINE:
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001281 return ACCESS_FINE_LOCATION;
Victoria Lease37425c32012-10-16 16:08:48 -07001282 case RESOLUTION_LEVEL_COARSE:
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001283 return ACCESS_COARSE_LOCATION;
Victoria Lease37425c32012-10-16 16:08:48 -07001284 default:
1285 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001286 }
Victoria Leaseda479c52012-10-15 15:24:16 -07001287 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001288
Victoria Lease37425c32012-10-16 16:08:48 -07001289 private int getAllowedResolutionLevel(int pid, int uid) {
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001290 if (mContext.checkPermission(ACCESS_FINE_LOCATION, pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001291 return RESOLUTION_LEVEL_FINE;
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001292 } else if (mContext.checkPermission(ACCESS_COARSE_LOCATION, pid, uid)
1293 == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001294 return RESOLUTION_LEVEL_COARSE;
1295 } else {
1296 return RESOLUTION_LEVEL_NONE;
Victoria Leaseda479c52012-10-15 15:24:16 -07001297 }
Victoria Lease4fab68b2012-09-13 13:20:59 -07001298 }
1299
Victoria Lease37425c32012-10-16 16:08:48 -07001300 private int getCallerAllowedResolutionLevel() {
1301 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
1302 }
1303
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001304 private boolean checkCallingOrSelfLocationPermission() {
1305 return mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED
1306 || mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
1307 == PERMISSION_GRANTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001308 }
1309
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001310 private void enforceCallingOrSelfLocationPermission() {
1311 if (checkCallingOrSelfLocationPermission()) {
1312 return;
Victoria Lease8dbb6342012-09-21 16:55:53 -07001313 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001314
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001315 throw new SecurityException("uid " + Binder.getCallingUid() + " does not have "
1316 + ACCESS_COARSE_LOCATION + " or " + ACCESS_FINE_LOCATION + ".");
Victoria Leaseda479c52012-10-15 15:24:16 -07001317 }
1318
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001319 private void enforceCallingOrSelfPackageName(String packageName) {
1320 int uid = Binder.getCallingUid();
1321 if (ArrayUtils.contains(mPackageManager.getPackagesForUid(uid), packageName)) {
1322 return;
Victoria Leaseda479c52012-10-15 15:24:16 -07001323 }
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001324
1325 throw new SecurityException("invalid package \"" + packageName + "\" for uid " + uid);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001326 }
1327
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001328 public static int resolutionLevelToOp(int allowedResolutionLevel) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001329 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
1330 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001331 return AppOpsManager.OP_COARSE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001332 } else {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001333 return AppOpsManager.OP_FINE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001334 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001335 }
1336 return -1;
1337 }
1338
Wei Wangb86334f2018-07-03 16:33:24 -07001339 private static String resolutionLevelToOpStr(int allowedResolutionLevel) {
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001340 switch (allowedResolutionLevel) {
Wei Wangb86334f2018-07-03 16:33:24 -07001341 case RESOLUTION_LEVEL_COARSE:
1342 return AppOpsManager.OPSTR_COARSE_LOCATION;
1343 case RESOLUTION_LEVEL_FINE:
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001344 // fall through
Wei Wangb86334f2018-07-03 16:33:24 -07001345 case RESOLUTION_LEVEL_NONE:
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001346 // fall through
Wei Wangb86334f2018-07-03 16:33:24 -07001347 default:
1348 // Use the most restrictive ops if not sure.
1349 return AppOpsManager.OPSTR_FINE_LOCATION;
1350 }
1351 }
1352
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001353 private boolean reportLocationAccessNoThrow(int pid, int uid, String packageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001354 @Nullable String featureId, int allowedResolutionLevel, @Nullable String message) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001355 int op = resolutionLevelToOp(allowedResolutionLevel);
1356 if (op >= 0) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001357 if (mAppOps.noteOpNoThrow(op, uid, packageName, featureId, message)
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001358 != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001359 return false;
1360 }
1361 }
David Christieb870dbf2015-06-22 12:42:53 -07001362
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001363 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001364 }
1365
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001366 private boolean checkLocationAccess(int pid, int uid, String packageName,
1367 int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001368 int op = resolutionLevelToOp(allowedResolutionLevel);
1369 if (op >= 0) {
Wei Wang16276a42019-02-04 18:23:31 -08001370 if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001371 return false;
1372 }
1373 }
David Christieb870dbf2015-06-22 12:42:53 -07001374
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001375 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001376 }
1377
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001378 /**
Maggie91e630c2018-01-24 17:31:46 -08001379 * Returns all providers by name, including passive and the ones that are not permitted to
1380 * be accessed by the calling activity or are currently disabled, but excluding fused.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001381 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001382 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001383 public List<String> getAllProviders() {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001384 ArrayList<String> providers = new ArrayList<>(mProviderManagers.size());
1385 for (LocationProviderManager manager : mProviderManagers) {
1386 if (FUSED_PROVIDER.equals(manager.getName())) {
1387 continue;
Maggie91e630c2018-01-24 17:31:46 -08001388 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001389 providers.add(manager.getName());
Maggie91e630c2018-01-24 17:31:46 -08001390 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001391 return providers;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 }
1393
Mike Lockwood03ca2162010-04-01 08:10:09 -07001394 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001395 * Return all providers by name, that match criteria and are optionally
1396 * enabled.
1397 * Can return passive provider, but never returns fused provider.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001398 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001399 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001400 public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001401 if (!checkCallingOrSelfLocationPermission()) {
1402 return Collections.emptyList();
1403 }
1404
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001405 synchronized (mLock) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001406 ArrayList<String> providers = new ArrayList<>(mProviderManagers.size());
1407 for (LocationProviderManager manager : mProviderManagers) {
1408 String name = manager.getName();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001409 if (FUSED_PROVIDER.equals(name)) {
1410 continue;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001411 }
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08001412 if (enabledOnly && !manager.isEnabled()) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001413 continue;
1414 }
1415 if (criteria != null
1416 && !android.location.LocationProvider.propertiesMeetCriteria(
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001417 name, manager.getProperties(), criteria)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001418 continue;
1419 }
1420 providers.add(name);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001421 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001422 return providers;
Soonil Nagarkar68257742019-01-09 19:42:34 +00001423 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001424 }
1425
1426 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001427 * Return the name of the best provider given a Criteria object.
1428 * This method has been deprecated from the public API,
Victoria Lease8dbb6342012-09-21 16:55:53 -07001429 * and the whole LocationProvider (including #meetsCriteria)
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001430 * has been deprecated as well. So this method now uses
1431 * some simplified logic.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001432 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001433 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001434 public String getBestProvider(Criteria criteria, boolean enabledOnly) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001435 List<String> providers = getProviders(criteria, enabledOnly);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001436 if (providers.isEmpty()) {
1437 providers = getProviders(null, enabledOnly);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08001438 }
1439
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001440 if (!providers.isEmpty()) {
1441 if (providers.contains(GPS_PROVIDER)) {
1442 return GPS_PROVIDER;
1443 } else if (providers.contains(NETWORK_PROVIDER)) {
1444 return NETWORK_PROVIDER;
1445 } else {
1446 return providers.get(0);
1447 }
1448 }
1449
Mike Lockwood03ca2162010-04-01 08:10:09 -07001450 return null;
1451 }
1452
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001453 @GuardedBy("mLock")
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08001454 private void updateProviderEnabledLocked(LocationProviderManager manager) {
1455 boolean enabled = manager.isEnabled();
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 ArrayList<Receiver> deadReceivers = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07001458
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001459 ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 if (records != null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001461 for (UpdateRecord record : records) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001462 if (!mUserInfoHelper.isCurrentUserOrProfile(
Anil Admal08b96122019-01-30 16:55:05 -08001463 UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001464 continue;
1465 }
1466
Kweku Adams5e0052b2019-02-22 15:17:52 -08001467 // requests that ignore location settings will never provide notifications
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001468 if (isSettingsExempt(record)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001469 continue;
1470 }
1471
1472 // Sends a notification message to the receiver
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08001473 if (!record.mReceiver.callProviderEnabledLocked(manager.getName(), enabled)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001474 if (deadReceivers == null) {
1475 deadReceivers = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001476 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001477 deadReceivers.add(record.mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001478 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001479 }
1480 }
1481
1482 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001483 for (int i = deadReceivers.size() - 1; i >= 0; i--) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00001484 removeUpdatesLocked(deadReceivers.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485 }
1486 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001487
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001488 applyRequirementsLocked(manager);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001489 }
1490
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001491 @GuardedBy("mLock")
1492 private void applyRequirementsLocked(String providerName) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001493 LocationProviderManager manager = getLocationProviderManager(providerName);
1494 if (manager != null) {
1495 applyRequirementsLocked(manager);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001496 }
1497 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001498
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001499 @GuardedBy("mLock")
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001500 private void applyRequirementsLocked(LocationProviderManager manager) {
1501 ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName());
1502 ProviderRequest.Builder providerRequest = new ProviderRequest.Builder();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001503
Soonil Nagarkar04cff6c2019-03-19 11:29:52 -07001504 // if provider is not active, it should not respond to requests
1505
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001506 if (mProviderManagers.contains(manager) && records != null && !records.isEmpty()) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001507 long backgroundThrottleInterval = mSettingsHelper.getBackgroundThrottleIntervalMs();
Kweku Adams5e0052b2019-02-22 15:17:52 -08001508
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001509 ArrayList<LocationRequest> requests = new ArrayList<>(records.size());
1510
Kweku Adams5e0052b2019-02-22 15:17:52 -08001511 final boolean isForegroundOnlyMode =
Kweku Adams4fb074e2019-02-01 16:03:27 -08001512 mBatterySaverMode == PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
1513 final boolean shouldThrottleRequests =
1514 mBatterySaverMode
1515 == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF
1516 && !mPowerManager.isInteractive();
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001517 // initialize the low power mode to true and set to false if any of the records requires
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001518 providerRequest.setLowPowerMode(true);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001519 for (UpdateRecord record : records) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001520 if (!mUserInfoHelper.isCurrentUserOrProfile(
Anil Admal08b96122019-01-30 16:55:05 -08001521 UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001522 continue;
1523 }
1524 if (!checkLocationAccess(
Anil Admal08b96122019-01-30 16:55:05 -08001525 record.mReceiver.mCallerIdentity.mPid,
1526 record.mReceiver.mCallerIdentity.mUid,
1527 record.mReceiver.mCallerIdentity.mPackageName,
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001528 record.mReceiver.mAllowedResolutionLevel)) {
1529 continue;
1530 }
Kweku Adams4fb074e2019-02-01 16:03:27 -08001531 final boolean isBatterySaverDisablingLocation = shouldThrottleRequests
1532 || (isForegroundOnlyMode && !record.mIsForegroundUid);
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08001533 if (!manager.isEnabled() || isBatterySaverDisablingLocation) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001534 if (isSettingsExempt(record)) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001535 providerRequest.setLocationSettingsIgnored(true);
1536 providerRequest.setLowPowerMode(false);
Soonil Nagarkar35c3b912019-01-31 10:31:24 -08001537 } else {
1538 continue;
1539 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001540 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001541
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001542 LocationRequest locationRequest = record.mRealRequest;
1543 long interval = locationRequest.getInterval();
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001544
Soonil Nagarkar509580f2019-02-06 15:57:26 -08001545
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001546 // if we're forcing location, don't apply any throttling
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001547 if (!providerRequest.isLocationSettingsIgnored() && !isThrottlingExempt(
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001548 record.mReceiver.mCallerIdentity)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001549 if (!record.mIsForegroundUid) {
1550 interval = Math.max(interval, backgroundThrottleInterval);
Victoria Leaseb711d572012-10-02 13:14:11 -07001551 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001552 if (interval != locationRequest.getInterval()) {
1553 locationRequest = new LocationRequest(locationRequest);
1554 locationRequest.setInterval(interval);
1555 }
1556 }
1557
1558 record.mRequest = locationRequest;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001559 requests.add(locationRequest);
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001560 if (!locationRequest.isLowPowerMode()) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001561 providerRequest.setLowPowerMode(false);
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001562 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001563 if (interval < providerRequest.getInterval()) {
1564 providerRequest.setInterval(interval);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001565 }
1566 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001567
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001568 providerRequest.setLocationRequests(requests);
1569
1570 if (providerRequest.getInterval() < Long.MAX_VALUE) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001571 // calculate who to blame for power
1572 // This is somewhat arbitrary. We pick a threshold interval
1573 // that is slightly higher that the minimum interval, and
1574 // spread the blame across all applications with a request
1575 // under that threshold.
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001576 // TODO: overflow
1577 long thresholdInterval = (providerRequest.getInterval() + 1000) * 3 / 2;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001578 for (UpdateRecord record : records) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001579 if (mUserInfoHelper.isCurrentUserOrProfile(
Anil Admal08b96122019-01-30 16:55:05 -08001580 UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001581 LocationRequest locationRequest = record.mRequest;
Svet Ganove998c732016-06-10 00:12:38 -07001582
1583 // Don't assign battery blame for update records whose
1584 // client has no permission to receive location data.
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001585 if (!providerRequest.getLocationRequests().contains(locationRequest)) {
Svet Ganove998c732016-06-10 00:12:38 -07001586 continue;
1587 }
1588
Victoria Leaseb711d572012-10-02 13:14:11 -07001589 if (locationRequest.getInterval() <= thresholdInterval) {
David Christiee55c9682013-08-22 10:10:34 -07001590 if (record.mReceiver.mWorkSource != null
Narayan Kamath32684dd2018-01-08 17:32:51 +00001591 && isValidWorkSource(record.mReceiver.mWorkSource)) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001592 providerRequest.getWorkSource().add(record.mReceiver.mWorkSource);
David Christie82edc9b2013-07-19 11:31:42 -07001593 } else {
Narayan Kamath32684dd2018-01-08 17:32:51 +00001594 // Assign blame to caller if there's no WorkSource associated with
1595 // the request or if it's invalid.
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001596 providerRequest.getWorkSource().add(
Anil Admal08b96122019-01-30 16:55:05 -08001597 record.mReceiver.mCallerIdentity.mUid,
1598 record.mReceiver.mCallerIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001599 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001600 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001601 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001602 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001603 }
1604 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001605
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001606 manager.setRequest(providerRequest.build());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001607 }
1608
Narayan Kamath32684dd2018-01-08 17:32:51 +00001609 /**
1610 * Whether a given {@code WorkSource} associated with a Location request is valid.
1611 */
1612 private static boolean isValidWorkSource(WorkSource workSource) {
1613 if (workSource.size() > 0) {
1614 // If the WorkSource has one or more non-chained UIDs, make sure they're accompanied
1615 // by tags.
Suprabh Shuklaf7cffa72019-11-08 17:03:03 -08001616 return workSource.getPackageName(0) != null;
Narayan Kamath32684dd2018-01-08 17:32:51 +00001617 } else {
1618 // For now, make sure callers have supplied an attribution tag for use with
1619 // AppOpsManager. This might be relaxed in the future.
Suprabh Shuklaf7cffa72019-11-08 17:03:03 -08001620 final List<WorkChain> workChains = workSource.getWorkChains();
Narayan Kamath32684dd2018-01-08 17:32:51 +00001621 return workChains != null && !workChains.isEmpty() &&
1622 workChains.get(0).getAttributionTag() != null;
1623 }
1624 }
1625
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001626 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001627 public String[] getBackgroundThrottlingWhitelist() {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001628 return mSettingsHelper.getBackgroundThrottlePackageWhitelist().toArray(new String[0]);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001629 }
1630
Soonil Nagarkar5140e4f2019-02-14 17:21:33 -08001631 @Override
1632 public String[] getIgnoreSettingsWhitelist() {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001633 return mSettingsHelper.getIgnoreSettingsPackageWhitelist().toArray(new String[0]);
Soonil Nagarkar5140e4f2019-02-14 17:21:33 -08001634 }
1635
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001636 private boolean isThrottlingExempt(CallerIdentity callerIdentity) {
Anil Admal08b96122019-01-30 16:55:05 -08001637 if (callerIdentity.mUid == Process.SYSTEM_UID) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001638 return true;
1639 }
1640
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001641 if (mSettingsHelper.getBackgroundThrottlePackageWhitelist().contains(
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07001642 callerIdentity.mPackageName)) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001643 return true;
1644 }
1645
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001646 return mLocalService.isProviderPackage(callerIdentity.mPackageName);
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001647
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001648 }
1649
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001650 private boolean isSettingsExempt(UpdateRecord record) {
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001651 if (!record.mRealRequest.isLocationSettingsIgnored()) {
1652 return false;
1653 }
1654
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001655 if (mSettingsHelper.getIgnoreSettingsPackageWhitelist().contains(
Anil Admal08b96122019-01-30 16:55:05 -08001656 record.mReceiver.mCallerIdentity.mPackageName)) {
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001657 return true;
1658 }
1659
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001660 return mLocalService.isProviderPackage(record.mReceiver.mCallerIdentity.mPackageName);
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001661
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001662 }
1663
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001664 private class UpdateRecord {
1665 final String mProvider;
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001666 private final LocationRequest mRealRequest; // original request from client
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001667 LocationRequest mRequest; // possibly throttled version of the request
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001668 private final Receiver mReceiver;
1669 private boolean mIsForegroundUid;
1670 private Location mLastFixBroadcast;
Soonil Nagarkarae6ce772019-05-01 13:16:17 -07001671 private Throwable mStackTrace; // for debugging only
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08001672 private long mExpirationRealtimeMs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673
1674 /**
1675 * Note: must be constructed with lock held.
1676 */
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001677 private UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08001678 mExpirationRealtimeMs = request.getExpirationRealtimeMs(SystemClock.elapsedRealtime());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679 mProvider = provider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001680 mRealRequest = request;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001681 mRequest = request;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 mReceiver = receiver;
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001683 mIsForegroundUid = mAppForegroundHelper.isAppForeground(mReceiver.mCallerIdentity.mUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684
Soonil Nagarkarae6ce772019-05-01 13:16:17 -07001685 if (D && receiver.mCallerIdentity.mPid == Process.myPid()) {
1686 mStackTrace = new Throwable();
1687 }
1688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001689 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1690 if (records == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001691 records = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001692 mRecordsByProvider.put(provider, records);
1693 }
1694 if (!records.contains(this)) {
1695 records.add(this);
1696 }
David Christie2ff96af2014-01-30 16:09:37 -08001697
1698 // Update statistics for historical location requests by package/provider
1699 mRequestStatistics.startRequesting(
Anil Admal08b96122019-01-30 16:55:05 -08001700 mReceiver.mCallerIdentity.mPackageName, provider, request.getInterval(),
Wyatt Rileyf7075e02018-04-12 17:54:26 -07001701 mIsForegroundUid);
1702 }
1703
1704 /**
1705 * Method to be called when record changes foreground/background
1706 */
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001707 private void updateForeground(boolean isForeground) {
Wyatt Rileyf7075e02018-04-12 17:54:26 -07001708 mIsForegroundUid = isForeground;
1709 mRequestStatistics.updateForeground(
Anil Admal08b96122019-01-30 16:55:05 -08001710 mReceiver.mCallerIdentity.mPackageName, mProvider, isForeground);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001711 }
1712
1713 /**
David Christie2ff96af2014-01-30 16:09:37 -08001714 * Method to be called when a record will no longer be used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001715 */
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001716 private void disposeLocked(boolean removeReceiver) {
Hongyi Zhang700137e2019-05-23 21:19:36 -07001717 String packageName = mReceiver.mCallerIdentity.mPackageName;
1718 mRequestStatistics.stopRequesting(packageName, mProvider);
1719
1720 mLocationUsageLogger.logLocationApiUsage(
1721 LocationStatsEnums.USAGE_ENDED,
1722 LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
1723 packageName,
1724 mRealRequest,
1725 mReceiver.isListener(),
1726 mReceiver.isPendingIntent(),
Hongyi Zhang0e9ea752019-06-09 22:49:25 -07001727 /* geofence= */ null,
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001728 mAppForegroundHelper.getImportance(mReceiver.mCallerIdentity.mUid));
David Christie2ff96af2014-01-30 16:09:37 -08001729
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001730 // remove from mRecordsByProvider
1731 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
1732 if (globalRecords != null) {
1733 globalRecords.remove(this);
1734 }
1735
1736 if (!removeReceiver) return; // the caller will handle the rest
1737
1738 // remove from Receiver#mUpdateRecords
1739 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001740 receiverRecords.remove(this.mProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001741
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001742 // and also remove the Receiver if it has no more update records
1743 if (receiverRecords.size() == 0) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00001744 removeUpdatesLocked(mReceiver);
Mike Lockwood3a76fd62009-09-01 07:26:56 -04001745 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001746 }
1747
1748 @Override
1749 public String toString() {
Soonil Nagarkarae6ce772019-05-01 13:16:17 -07001750 StringBuilder b = new StringBuilder("UpdateRecord[");
1751 b.append(mProvider).append(" ");
1752 b.append(mReceiver.mCallerIdentity.mPackageName);
1753 b.append("(").append(mReceiver.mCallerIdentity.mUid);
1754 if (mIsForegroundUid) {
1755 b.append(" foreground");
1756 } else {
1757 b.append(" background");
1758 }
1759 b.append(") ");
1760 b.append(mRealRequest).append(" ").append(mReceiver.mWorkSource);
1761
1762 if (mStackTrace != null) {
1763 ByteArrayOutputStream tmp = new ByteArrayOutputStream();
1764 mStackTrace.printStackTrace(new PrintStream(tmp));
1765 b.append("\n\n").append(tmp.toString()).append("\n");
1766 }
1767
1768 b.append("]");
1769 return b.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771 }
1772
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001773 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00001774 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001775 String packageName, @Nullable String featureId, WorkSource workSource,
1776 boolean hideFromAppOps, @NonNull String listenerIdentifier) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001777 IBinder binder = listener.asBinder();
1778 Receiver receiver = mReceivers.get(binder);
1779 if (receiver == null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001780 receiver = new Receiver(listener, null, pid, uid, packageName, featureId, workSource,
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001781 hideFromAppOps, listenerIdentifier);
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001782 if (!receiver.linkToListenerDeathNotificationLocked(
1783 receiver.getListener().asBinder())) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001784 return null;
1785 }
Wen Jingcb3ab222014-03-27 13:42:59 +08001786 mReceivers.put(binder, receiver);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001787 }
1788 return receiver;
1789 }
1790
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001791 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00001792 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001793 @Nullable String featureId, WorkSource workSource, boolean hideFromAppOps,
1794 @NonNull String listenerIdentifier) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001795 Receiver receiver = mReceivers.get(intent);
1796 if (receiver == null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001797 receiver = new Receiver(null, intent, pid, uid, packageName, featureId, workSource,
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001798 hideFromAppOps, listenerIdentifier);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001799 mReceivers.put(intent, receiver);
1800 }
1801 return receiver;
1802 }
1803
Victoria Lease37425c32012-10-16 16:08:48 -07001804 /**
1805 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
1806 * and consistency requirements.
1807 *
1808 * @param request the LocationRequest from which to create a sanitized version
Victoria Lease37425c32012-10-16 16:08:48 -07001809 * @return a version of request that meets the given resolution and consistency requirements
1810 * @hide
1811 */
gomo48f1a642017-11-10 20:35:46 -08001812 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel,
1813 boolean callerHasLocationHardwarePermission) {
Victoria Lease37425c32012-10-16 16:08:48 -07001814 LocationRequest sanitizedRequest = new LocationRequest(request);
gomo48f1a642017-11-10 20:35:46 -08001815 if (!callerHasLocationHardwarePermission) {
1816 // allow setting low power mode only for callers with location hardware permission
1817 sanitizedRequest.setLowPowerMode(false);
1818 }
Victoria Lease37425c32012-10-16 16:08:48 -07001819 if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
1820 switch (sanitizedRequest.getQuality()) {
Victoria Lease09016ab2012-09-16 12:33:15 -07001821 case LocationRequest.ACCURACY_FINE:
Victoria Lease37425c32012-10-16 16:08:48 -07001822 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
Victoria Lease09016ab2012-09-16 12:33:15 -07001823 break;
1824 case LocationRequest.POWER_HIGH:
Victoria Lease37425c32012-10-16 16:08:48 -07001825 sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
Victoria Lease09016ab2012-09-16 12:33:15 -07001826 break;
1827 }
1828 // throttle
Victoria Lease37425c32012-10-16 16:08:48 -07001829 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1830 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001831 }
Victoria Lease37425c32012-10-16 16:08:48 -07001832 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1833 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001834 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07001835 }
Nick Pelly4e31c4f2012-08-13 19:35:39 -07001836 // make getFastestInterval() the minimum of interval and fastest interval
Victoria Lease37425c32012-10-16 16:08:48 -07001837 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001838 sanitizedRequest.setFastestInterval(request.getInterval());
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001839 }
Victoria Lease37425c32012-10-16 16:08:48 -07001840 return sanitizedRequest;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001841 }
1842
Nick Pellye0fd6932012-07-11 10:26:13 -07001843 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001844 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001845 PendingIntent intent, String packageName, String featureId,
1846 String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00001847 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001848
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001849 enforceCallingOrSelfLocationPermission();
1850 enforceCallingOrSelfPackageName(packageName);
1851
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001852 synchronized (mLock) {
1853 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001854 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001855 WorkSource workSource = request.getWorkSource();
1856 if (workSource != null && !workSource.isEmpty()) {
1857 mContext.enforceCallingOrSelfPermission(
1858 Manifest.permission.UPDATE_DEVICE_STATS, null);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08001859 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001860 boolean hideFromAppOps = request.getHideFromAppOps();
1861 if (hideFromAppOps) {
1862 mContext.enforceCallingOrSelfPermission(
1863 Manifest.permission.UPDATE_APP_OPS_STATS, null);
1864 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001865 if (request.isLocationSettingsIgnored()) {
1866 mContext.enforceCallingOrSelfPermission(
1867 Manifest.permission.WRITE_SECURE_SETTINGS, null);
1868 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001869 boolean callerHasLocationHardwarePermission =
1870 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
1871 == PERMISSION_GRANTED;
1872 LocationRequest sanitizedRequest = createSanitizedRequest(request,
1873 allowedResolutionLevel,
1874 callerHasLocationHardwarePermission);
1875
1876 final int pid = Binder.getCallingPid();
1877 final int uid = Binder.getCallingUid();
1878
1879 long identity = Binder.clearCallingIdentity();
1880 try {
1881
1882 // We don't check for MODE_IGNORED here; we will do that when we go to deliver
1883 // a location.
1884 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
1885
1886 if (intent == null && listener == null) {
1887 throw new IllegalArgumentException("need either listener or intent");
1888 } else if (intent != null && listener != null) {
1889 throw new IllegalArgumentException(
1890 "cannot register both listener and intent");
1891 }
1892
Hongyi Zhang700137e2019-05-23 21:19:36 -07001893 mLocationUsageLogger.logLocationApiUsage(
1894 LocationStatsEnums.USAGE_STARTED,
1895 LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
1896 packageName, request, listener != null, intent != null,
Hongyi Zhang0e9ea752019-06-09 22:49:25 -07001897 /* geofence= */ null,
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001898 mAppForegroundHelper.getImportance(uid));
Hongyi Zhang700137e2019-05-23 21:19:36 -07001899
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001900 Receiver receiver;
1901 if (intent != null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001902 receiver = getReceiverLocked(intent, pid, uid, packageName, featureId,
1903 workSource, hideFromAppOps, listenerIdentifier);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001904 } else {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001905 receiver = getReceiverLocked(listener, pid, uid, packageName, featureId,
1906 workSource, hideFromAppOps, listenerIdentifier);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001907 }
1908 requestLocationUpdatesLocked(sanitizedRequest, receiver, uid, packageName);
1909 } finally {
1910 Binder.restoreCallingIdentity(identity);
1911 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00001912 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001913 }
1914
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001915 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00001916 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001917 int uid, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001918 // Figure out the provider. Either its explicitly request (legacy use cases), or
1919 // use the fused provider
1920 if (request == null) request = DEFAULT_LOCATION_REQUEST;
1921 String name = request.getProvider();
Victoria Lease09016ab2012-09-16 12:33:15 -07001922 if (name == null) {
1923 throw new IllegalArgumentException("provider name must not be null");
1924 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -07001925
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001926 LocationProviderManager manager = getLocationProviderManager(name);
1927 if (manager == null) {
Victoria Leaseb30f3832013-10-13 12:15:40 -07001928 throw new IllegalArgumentException("provider doesn't exist: " + name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001929 }
1930
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001931 UpdateRecord record = new UpdateRecord(name, request, receiver);
gomo48f1a642017-11-10 20:35:46 -08001932 if (D) {
1933 Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
1934 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
1935 + (record.mIsForegroundUid ? "foreground" : "background")
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001936 + (isThrottlingExempt(receiver.mCallerIdentity)
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001937 ? " [whitelisted]" : "") + ")");
gomo48f1a642017-11-10 20:35:46 -08001938 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001939
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001940 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
1941 if (oldRecord != null) {
1942 oldRecord.disposeLocked(false);
1943 }
1944
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001945 if (!manager.isEnabled() && !isSettingsExempt(record)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001946 // Notify the listener that updates are currently disabled - but only if the request
1947 // does not ignore location settings
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001948 receiver.callProviderEnabledLocked(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001949 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001950
1951 applyRequirementsLocked(name);
1952
David Christie0b837452013-07-29 16:02:13 -07001953 // Update the monitoring here just in case multiple location requests were added to the
1954 // same receiver (this request may be high power and the initial might not have been).
1955 receiver.updateMonitoring(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001956 }
1957
Nick Pellye0fd6932012-07-11 10:26:13 -07001958 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001959 public void removeUpdates(ILocationListener listener, PendingIntent intent,
Soonil Nagarkar68257742019-01-09 19:42:34 +00001960 String packageName) {
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001961 enforceCallingOrSelfPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07001962
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001963 int pid = Binder.getCallingPid();
1964 int uid = Binder.getCallingUid();
1965
1966 if (intent == null && listener == null) {
1967 throw new IllegalArgumentException("need either listener or intent");
1968 } else if (intent != null && listener != null) {
1969 throw new IllegalArgumentException("cannot register both listener and intent");
1970 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001971
Soonil Nagarkar68257742019-01-09 19:42:34 +00001972 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001973 Receiver receiver;
1974 if (intent != null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001975 receiver = getReceiverLocked(intent, pid, uid, packageName, null, null, false, "");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001976 } else {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001977 receiver = getReceiverLocked(listener, pid, uid, packageName, null, null, false,
1978 "");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001979 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08001980
Soonil Nagarkar68257742019-01-09 19:42:34 +00001981 long identity = Binder.clearCallingIdentity();
1982 try {
1983 removeUpdatesLocked(receiver);
1984 } finally {
1985 Binder.restoreCallingIdentity(identity);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08001986 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00001987 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001988 }
1989
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001990 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00001991 private void removeUpdatesLocked(Receiver receiver) {
Dianne Hackborn7ff30112012-11-08 11:12:09 -08001992 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001993
1994 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001995 receiver.unlinkFromListenerDeathNotificationLocked(
1996 receiver.getListener().asBinder());
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001997 receiver.clearPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001998 }
1999
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07002000 receiver.updateMonitoring(false);
2001
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002002 // Record which providers were associated with this listener
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002003 HashSet<String> providers = new HashSet<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002004 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2005 if (oldRecords != null) {
2006 // Call dispose() on the obsolete update records.
2007 for (UpdateRecord record : oldRecords.values()) {
David Christie2ff96af2014-01-30 16:09:37 -08002008 // Update statistics for historical location requests by package/provider
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002009 record.disposeLocked(false);
2010 }
2011 // Accumulate providers
2012 providers.addAll(oldRecords.keySet());
2013 }
2014
2015 // update provider
2016 for (String provider : providers) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002017 applyRequirementsLocked(provider);
2018 }
2019 }
2020
Nick Pellye0fd6932012-07-11 10:26:13 -07002021 @Override
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002022 public Location getLastLocation(LocationRequest r, String packageName, String featureId) {
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002023 enforceCallingOrSelfLocationPermission();
2024 enforceCallingOrSelfPackageName(packageName);
2025
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002026 synchronized (mLock) {
2027 LocationRequest request = r != null ? r : DEFAULT_LOCATION_REQUEST;
2028 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002029 // no need to sanitize this request, as only the provider name is used
Nick Pelly4035f5a2012-08-17 14:43:49 -07002030
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002031 final int pid = Binder.getCallingPid();
2032 final int uid = Binder.getCallingUid();
2033 final long identity = Binder.clearCallingIdentity();
2034 try {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002035 if (mSettingsHelper.isLocationPackageBlacklisted(UserHandle.getUserId(uid),
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07002036 packageName)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002037 if (D) {
2038 Log.d(TAG, "not returning last loc for blacklisted app: "
2039 + packageName);
2040 }
2041 return null;
gomo48f1a642017-11-10 20:35:46 -08002042 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002043
Soonil Nagarkar68257742019-01-09 19:42:34 +00002044 // Figure out the provider. Either its explicitly request (deprecated API's),
2045 // or use the fused provider
2046 String name = request.getProvider();
2047 if (name == null) name = LocationManager.FUSED_PROVIDER;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002048 LocationProviderManager manager = getLocationProviderManager(name);
2049 if (manager == null) return null;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002050
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002051 // only the current user or location providers may get location this way
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002052 if (!mUserInfoHelper.isCurrentUserOrProfile(UserHandle.getUserId(uid))
2053 && !mLocalService.isProviderPackage(packageName)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002054 return null;
2055 }
2056
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08002057 if (!manager.isEnabled()) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002058 return null;
2059 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002060
2061 Location location;
2062 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2063 // Make sure that an app with coarse permissions can't get frequent location
2064 // updates by calling LocationManager.getLastKnownLocation repeatedly.
2065 location = mLastLocationCoarseInterval.get(name);
2066 } else {
2067 location = mLastLocation.get(name);
2068 }
2069 if (location == null) {
2070 return null;
2071 }
2072
2073 // Don't return stale location to apps with foreground-only location permission.
2074 String op = resolutionLevelToOpStr(allowedResolutionLevel);
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002075 long locationAgeMs = TimeUnit.NANOSECONDS.toMillis(
2076 SystemClock.elapsedRealtime() - location.getElapsedRealtimeNanos());
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002077 if (locationAgeMs > mSettingsHelper.getMaxLastLocationAgeMs()
Soonil Nagarkar68257742019-01-09 19:42:34 +00002078 && (mAppOps.unsafeCheckOp(op, uid, packageName)
2079 == AppOpsManager.MODE_FOREGROUND)) {
2080 return null;
2081 }
2082
Wei Wang16276a42019-02-04 18:23:31 -08002083 Location lastLocation = null;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002084 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2085 Location noGPSLocation = location.getExtraLocation(
2086 Location.EXTRA_NO_GPS_LOCATION);
2087 if (noGPSLocation != null) {
Wei Wang16276a42019-02-04 18:23:31 -08002088 lastLocation = new Location(mLocationFudger.getOrCreate(noGPSLocation));
Soonil Nagarkar68257742019-01-09 19:42:34 +00002089 }
2090 } else {
Wei Wang16276a42019-02-04 18:23:31 -08002091 lastLocation = new Location(location);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002092 }
Wei Wang16276a42019-02-04 18:23:31 -08002093 // Don't report location access if there is no last location to deliver.
2094 if (lastLocation != null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002095 if (!reportLocationAccessNoThrow(pid, uid, packageName, featureId,
2096 allowedResolutionLevel, null)) {
Wei Wang16276a42019-02-04 18:23:31 -08002097 if (D) {
2098 Log.d(TAG, "not returning last loc for no op app: " + packageName);
2099 }
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002100 lastLocation = null;
Wei Wang16276a42019-02-04 18:23:31 -08002101 }
2102 }
2103 return lastLocation;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002104 } finally {
2105 Binder.restoreCallingIdentity(identity);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002106 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002107 }
2108 }
2109
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002110 @Override
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002111 public boolean getCurrentLocation(LocationRequest locationRequest,
2112 ICancellationSignal remoteCancellationSignal, ILocationListener listener,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002113 String packageName, String featureId, String listenerIdentifier) {
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002114 // side effect of validating locationRequest and packageName
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002115 Location lastLocation = getLastLocation(locationRequest, packageName, featureId);
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002116 if (lastLocation != null) {
2117 long locationAgeMs = TimeUnit.NANOSECONDS.toMillis(
2118 SystemClock.elapsedRealtimeNanos() - lastLocation.getElapsedRealtimeNanos());
2119
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002120 if (locationAgeMs < MAX_CURRENT_LOCATION_AGE_MS) {
2121 try {
2122 listener.onLocationChanged(lastLocation);
2123 return true;
2124 } catch (RemoteException e) {
2125 Log.w(TAG, e);
2126 return false;
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002127 }
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002128 }
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002129
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002130 if (!mAppForegroundHelper.isAppForeground(Binder.getCallingUid())) {
2131 if (locationAgeMs < mSettingsHelper.getBackgroundThrottleIntervalMs()) {
2132 // not allowed to request new locations, so we can't return anything
2133 return false;
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002134 }
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002135 }
2136 }
2137
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002138 requestLocationUpdates(locationRequest, listener, null, packageName, featureId,
2139 listenerIdentifier);
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002140 CancellationSignal cancellationSignal = CancellationSignal.fromTransport(
2141 remoteCancellationSignal);
2142 if (cancellationSignal != null) {
2143 cancellationSignal.setOnCancelListener(
2144 () -> removeUpdates(listener, null, packageName));
2145 }
2146 return true;
2147 }
2148
2149 @Override
Chad Brubakerf1133332019-03-15 14:13:59 -07002150 public LocationTime getGnssTimeMillis() {
2151 synchronized (mLock) {
2152 Location location = mLastLocation.get(LocationManager.GPS_PROVIDER);
2153 if (location == null) {
2154 return null;
2155 }
2156 long currentNanos = SystemClock.elapsedRealtimeNanos();
2157 long deltaMs = (currentNanos - location.getElapsedRealtimeNanos()) / 1000000L;
2158 return new LocationTime(location.getTime() + deltaMs, currentNanos);
2159 }
2160 }
2161
2162 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002163 public boolean injectLocation(Location location) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002164 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
2165 "Location Hardware permission not granted to inject location");
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002166 mContext.enforceCallingPermission(ACCESS_FINE_LOCATION,
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002167 "Access Fine Location permission not granted to inject Location");
2168
Soonil Nagarkar68257742019-01-09 19:42:34 +00002169 synchronized (mLock) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002170 LocationProviderManager manager = getLocationProviderManager(location.getProvider());
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08002171 if (manager == null || !manager.isEnabled()) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002172 return false;
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002173 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002174
2175 // NOTE: If last location is already available, location is not injected. If
2176 // provider's normal source (like a GPS chipset) have already provided an output
2177 // there is no need to inject this location.
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002178 if (mLastLocation.get(manager.getName()) != null) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002179 return false;
2180 }
2181
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002182 updateLastLocationLocked(location, manager.getName());
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002183 return true;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002184 }
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002185 }
2186
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002187 @Override
2188 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002189 String packageName, String featureId, String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002190 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002191
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002192 mContext.enforceCallingOrSelfPermission(ACCESS_FINE_LOCATION, null);
2193 enforceCallingOrSelfPackageName(packageName);
2194
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002195 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002196 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002197 if (intent == null) {
2198 throw new IllegalArgumentException("invalid pending intent: " + null);
Victoria Lease56e675b2012-11-05 19:25:06 -08002199 }
Soonil Nagarkar8c4655e2019-02-27 13:00:56 -08002200 // Require that caller can manage given document
2201 boolean callerHasLocationHardwarePermission =
2202 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
2203 == PERMISSION_GRANTED;
2204 LocationRequest sanitizedRequest = createSanitizedRequest(request,
2205 allowedResolutionLevel,
2206 callerHasLocationHardwarePermission);
2207
2208 if (D) {
2209 Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
2210 }
2211
2212 // geo-fence manager uses the public location API, need to clear identity
2213 int uid = Binder.getCallingUid();
2214 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
2215 // temporary measure until geofences work for secondary users
2216 Log.w(TAG, "proximity alerts are currently available only to the primary user");
2217 return;
2218 }
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002219
2220 mLocationUsageLogger.logLocationApiUsage(
2221 LocationStatsEnums.USAGE_STARTED,
2222 LocationStatsEnums.API_REQUEST_GEOFENCE,
2223 packageName,
2224 request,
2225 /* hasListener= */ false,
2226 true,
2227 geofence,
2228 mAppForegroundHelper.getImportance(uid));
2229
Soonil Nagarkar8c4655e2019-02-27 13:00:56 -08002230 long identity = Binder.clearCallingIdentity();
2231 try {
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002232 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002233 uid, packageName, featureId, listenerIdentifier);
Soonil Nagarkar8c4655e2019-02-27 13:00:56 -08002234 } finally {
2235 Binder.restoreCallingIdentity(identity);
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002236 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002237 }
2238
2239 @Override
2240 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002241 if (intent == null) {
2242 throw new IllegalArgumentException("invalid pending intent: " + null);
2243 }
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002244 enforceCallingOrSelfPackageName(packageName);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002245
2246 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2247
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002248 mLocationUsageLogger.logLocationApiUsage(
2249 LocationStatsEnums.USAGE_ENDED,
2250 LocationStatsEnums.API_REQUEST_GEOFENCE,
2251 packageName,
2252 /* LocationRequest= */ null,
2253 /* hasListener= */ false,
2254 true,
2255 geofence,
2256 mAppForegroundHelper.getImportance(Binder.getCallingUid()));
2257
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002258 // geo-fence manager uses the public location API, need to clear identity
2259 long identity = Binder.clearCallingIdentity();
2260 try {
2261 mGeofenceManager.removeFence(geofence, intent);
2262 } finally {
2263 Binder.restoreCallingIdentity(identity);
2264 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002265 }
2266
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002267 @Override
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002268 public boolean registerGnssStatusCallback(IGnssStatusListener listener, String packageName,
2269 String featureId) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002270 return mGnssManagerService != null && mGnssManagerService.registerGnssStatusCallback(
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002271 listener, packageName, featureId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002272 }
2273
Nick Pellye0fd6932012-07-11 10:26:13 -07002274 @Override
Anil Admal98d49b72019-02-06 15:26:33 -08002275 public void unregisterGnssStatusCallback(IGnssStatusListener listener) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002276 if (mGnssManagerService != null) mGnssManagerService.unregisterGnssStatusCallback(listener);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002277 }
2278
Nick Pellye0fd6932012-07-11 10:26:13 -07002279 @Override
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002280 public boolean addGnssMeasurementsListener(IGnssMeasurementsListener listener,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002281 String packageName, String featureId, String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002282 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002283
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002284 return mGnssManagerService != null && mGnssManagerService.addGnssMeasurementsListener(
2285 listener, packageName, featureId, listenerIdentifier);
Anil Admal52686f82019-02-13 19:04:10 -08002286 }
2287
2288 @Override
2289 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002290 if (mGnssManagerService != null) {
2291 mGnssManagerService.removeGnssMeasurementsListener(
2292 listener);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002293 }
destradaaea8a8a62014-06-23 18:19:03 -07002294 }
2295
2296 @Override
gomo226b7b72018-12-12 16:49:39 -08002297 public void injectGnssMeasurementCorrections(
2298 GnssMeasurementCorrections measurementCorrections, String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002299 if (mGnssManagerService != null) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002300 mGnssManagerService.injectGnssMeasurementCorrections(measurementCorrections,
2301 packageName);
gomo226b7b72018-12-12 16:49:39 -08002302 }
2303 }
2304
2305 @Override
Anil Admal99349782019-03-19 18:58:42 -07002306 public long getGnssCapabilities(String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002307 return mGnssManagerService == null ? 0L : mGnssManagerService.getGnssCapabilities(
2308 packageName);
gomo226b7b72018-12-12 16:49:39 -08002309 }
2310
2311 @Override
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002312 public boolean addGnssNavigationMessageListener(IGnssNavigationMessageListener listener,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002313 String packageName, String featureId, String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002314 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002315
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002316 return mGnssManagerService != null && mGnssManagerService.addGnssNavigationMessageListener(
2317 listener, packageName, featureId, listenerIdentifier);
destradaa4b3e3932014-07-21 18:01:47 -07002318 }
2319
2320 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002321 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002322 if (mGnssManagerService != null) {
2323 mGnssManagerService.removeGnssNavigationMessageListener(
2324 listener);
2325 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002326 }
2327
2328 @Override
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002329 public boolean sendExtraCommand(String providerName, String command, Bundle extras) {
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002330 Objects.requireNonNull(providerName);
2331 Objects.requireNonNull(command);
Soonil Nagarkar3f128402019-12-12 08:31:27 -08002332
2333 mContext.enforceCallingOrSelfPermission(
2334 Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, null);
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002335 enforceCallingOrSelfLocationPermission();
Soonil Nagarkar3f128402019-12-12 08:31:27 -08002336
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002337 mLocationUsageLogger.logLocationApiUsage(
2338 LocationStatsEnums.USAGE_STARTED,
2339 LocationStatsEnums.API_SEND_EXTRA_COMMAND,
2340 providerName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002341
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002342 LocationProviderManager manager = getLocationProviderManager(providerName);
2343 if (manager != null) {
2344 manager.sendExtraCommand(Binder.getCallingUid(), Binder.getCallingPid(), command,
2345 extras);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002346 }
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002347
2348 mLocationUsageLogger.logLocationApiUsage(
2349 LocationStatsEnums.USAGE_ENDED,
2350 LocationStatsEnums.API_SEND_EXTRA_COMMAND,
2351 providerName);
2352
2353 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 }
2355
Nick Pellye0fd6932012-07-11 10:26:13 -07002356 @Override
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002357 public ProviderProperties getProviderProperties(String providerName) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002358 LocationProviderManager manager = getLocationProviderManager(providerName);
2359 if (manager == null) {
2360 return null;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002361 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002362 return manager.getProperties();
Jason Monkb71218a2015-06-17 14:44:39 -04002363 }
2364
Wei Wang980b7c22018-12-06 17:53:00 -08002365 @Override
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08002366 public boolean isProviderPackage(String packageName) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002367 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, null);
2368 return mLocalService.isProviderPackage(packageName);
Maggie2a9409e2018-03-21 11:47:28 -07002369 }
2370
Maggie2a9409e2018-03-21 11:47:28 -07002371 @Override
Wei Wang9f52d552019-10-02 14:49:02 -07002372 public List<String> getProviderPackages(String providerName) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002373 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, null);
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002374 LocationProviderManager manager = getLocationProviderManager(providerName);
2375 return manager == null ? Collections.emptyList() : new ArrayList<>(manager.getPackages());
Wei Wang9f52d552019-10-02 14:49:02 -07002376 }
2377
2378 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002379 public void setExtraLocationControllerPackage(String packageName) {
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002380 mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
2381 Manifest.permission.LOCATION_HARDWARE + " permission required");
Soonil Nagarkar68257742019-01-09 19:42:34 +00002382 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002383 mExtraLocationControllerPackage = packageName;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002384 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002385 }
2386
2387 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002388 public String getExtraLocationControllerPackage() {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002389 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002390 return mExtraLocationControllerPackage;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002391 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002392 }
2393
2394 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002395 public void setExtraLocationControllerPackageEnabled(boolean enabled) {
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002396 mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
2397 Manifest.permission.LOCATION_HARDWARE + " permission required");
Soonil Nagarkar68257742019-01-09 19:42:34 +00002398 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002399 mExtraLocationControllerPackageEnabled = enabled;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002400 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002401 }
2402
2403 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002404 public boolean isExtraLocationControllerPackageEnabled() {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002405 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002406 return mExtraLocationControllerPackageEnabled
2407 && (mExtraLocationControllerPackage != null);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002408 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002409 }
2410
2411 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002412 public boolean isLocationEnabledForUser(int userId) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002413 if (UserHandle.getCallingUserId() != userId) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002414 mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS,
2415 null);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002416 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002417
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002418 return mSettingsHelper.isLocationEnabled(userId);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002419 }
2420
Maggie2a9409e2018-03-21 11:47:28 -07002421 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002422 public boolean isProviderEnabledForUser(String providerName, int userId) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002423 if (UserHandle.getCallingUserId() != userId) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002424 mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS,
2425 null);
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002426 }
2427
Maggie2a9409e2018-03-21 11:47:28 -07002428 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2429 // so we discourage its use
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002430 if (FUSED_PROVIDER.equals(providerName)) return false;
Maggie2a9409e2018-03-21 11:47:28 -07002431
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002432 synchronized (mLock) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002433 LocationProviderManager manager = getLocationProviderManager(providerName);
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08002434 return manager != null && manager.isEnabled(userId);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002435 }
Maggie2a9409e2018-03-21 11:47:28 -07002436 }
2437
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002438 @GuardedBy("mLock")
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002439 private static boolean shouldBroadcastSafeLocked(
Laurent Tu75defb62012-11-01 16:21:52 -07002440 Location loc, Location lastLoc, UpdateRecord record, long now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002441 // Always broadcast the first update
2442 if (lastLoc == null) {
2443 return true;
2444 }
2445
Nick Pellyf1be6862012-05-15 10:53:42 -07002446 // Check whether sufficient time has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002447 long minTime = record.mRealRequest.getFastestInterval();
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002448 long deltaMs = TimeUnit.NANOSECONDS.toMillis(
2449 loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos());
2450 if (deltaMs < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002451 return false;
2452 }
2453
2454 // Check whether sufficient distance has been traveled
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002455 double minDistance = record.mRealRequest.getSmallestDisplacement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002456 if (minDistance > 0.0) {
2457 if (loc.distanceTo(lastLoc) <= minDistance) {
2458 return false;
2459 }
2460 }
2461
Laurent Tu75defb62012-11-01 16:21:52 -07002462 // Check whether sufficient number of udpates is left
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002463 if (record.mRealRequest.getNumUpdates() <= 0) {
Laurent Tu75defb62012-11-01 16:21:52 -07002464 return false;
2465 }
2466
2467 // Check whether the expiry date has passed
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08002468 return record.mExpirationRealtimeMs >= now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002469 }
2470
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002471 @GuardedBy("mLock")
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002472 private void handleLocationChangedLocked(Location location, LocationProviderManager manager) {
2473 if (!mProviderManagers.contains(manager)) {
2474 Log.w(TAG, "received location from unknown provider: " + manager.getName());
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002475 return;
2476 }
2477 if (!location.isComplete()) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002478 Log.w(TAG, "dropping incomplete location from " + manager.getName() + " provider: "
2479 + location);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002480 return;
2481 }
2482
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002483 // notify passive provider
2484 if (manager != mPassiveManager) {
2485 mPassiveManager.updateLocation(new Location(location));
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002486 }
2487
Soonil Nagarkar68257742019-01-09 19:42:34 +00002488 if (D) Log.d(TAG, "incoming location: " + location);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002489 long now = SystemClock.elapsedRealtime();
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002490
2491
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08002492 // only update last location for locations that come from enabled providers
2493 if (manager.isEnabled()) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002494 updateLastLocationLocked(location, manager.getName());
Mike Lockwood4e50b782009-04-03 08:24:43 -07002495 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002496
David Christie1b9b7b12013-04-15 15:31:11 -07002497 // Update last known coarse interval location if enough time has passed.
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002498 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002499 manager.getName());
David Christie1b9b7b12013-04-15 15:31:11 -07002500 if (lastLocationCoarseInterval == null) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002501 lastLocationCoarseInterval = new Location(location);
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002502
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08002503 if (manager.isEnabled()) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002504 mLastLocationCoarseInterval.put(manager.getName(), lastLocationCoarseInterval);
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002505 }
David Christie1b9b7b12013-04-15 15:31:11 -07002506 }
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002507 long timeDeltaMs = TimeUnit.NANOSECONDS.toMillis(location.getElapsedRealtimeNanos()
2508 - lastLocationCoarseInterval.getElapsedRealtimeNanos());
2509 if (timeDeltaMs > LocationFudger.FASTEST_INTERVAL_MS) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002510 lastLocationCoarseInterval.set(location);
David Christie1b9b7b12013-04-15 15:31:11 -07002511 }
2512 // Don't ever return a coarse location that is more recent than the allowed update
2513 // interval (i.e. don't allow an app to keep registering and unregistering for
2514 // location updates to overcome the minimum interval).
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002515 Location noGPSLocation =
David Christie1b9b7b12013-04-15 15:31:11 -07002516 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2517
Laurent Tu60ec50a2012-10-04 17:00:10 -07002518 // Skip if there are no UpdateRecords for this provider.
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002519 ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName());
Laurent Tu60ec50a2012-10-04 17:00:10 -07002520 if (records == null || records.size() == 0) return;
2521
Victoria Lease09016ab2012-09-16 12:33:15 -07002522 // Fetch coarse location
2523 Location coarseLocation = null;
David Christie1b9b7b12013-04-15 15:31:11 -07002524 if (noGPSLocation != null) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002525 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
2526 }
2527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002528 ArrayList<Receiver> deadReceivers = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002529 ArrayList<UpdateRecord> deadUpdateRecords = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07002530
Soonil Nagarkar94749f72018-11-08 11:46:43 -08002531 // Broadcast location to all listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002532 for (UpdateRecord r : records) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002533 Receiver receiver = r.mReceiver;
Mike Lockwood03ca2162010-04-01 08:10:09 -07002534 boolean receiverDead = false;
Nick Pelly4035f5a2012-08-17 14:43:49 -07002535
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002536 if (!manager.isEnabled() && !isSettingsExempt(r)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002537 continue;
2538 }
2539
Anil Admal08b96122019-01-30 16:55:05 -08002540 int receiverUserId = UserHandle.getUserId(receiver.mCallerIdentity.mUid);
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002541 if (!mUserInfoHelper.isCurrentUserOrProfile(receiverUserId)
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08002542 && !isProviderPackage(receiver.mCallerIdentity.mPackageName)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002543 if (D) {
Victoria Lease269518e2012-10-29 08:25:39 -07002544 Log.d(TAG, "skipping loc update for background user " + receiverUserId +
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08002545 " (app: " + receiver.mCallerIdentity.mPackageName + ")");
Victoria Leaseb711d572012-10-02 13:14:11 -07002546 }
2547 continue;
2548 }
2549
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002550 if (mSettingsHelper.isLocationPackageBlacklisted(receiverUserId,
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07002551 receiver.mCallerIdentity.mPackageName)) {
gomo48f1a642017-11-10 20:35:46 -08002552 if (D) {
2553 Log.d(TAG, "skipping loc update for blacklisted app: " +
Anil Admal08b96122019-01-30 16:55:05 -08002554 receiver.mCallerIdentity.mPackageName);
gomo48f1a642017-11-10 20:35:46 -08002555 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07002556 continue;
2557 }
2558
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002559 Location notifyLocation;
Victoria Lease37425c32012-10-16 16:08:48 -07002560 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2561 notifyLocation = coarseLocation; // use coarse location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002562 } else {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002563 notifyLocation = location; // use fine location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002564 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002565 if (notifyLocation != null) {
2566 Location lastLoc = r.mLastFixBroadcast;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002567 if ((lastLoc == null)
2568 || shouldBroadcastSafeLocked(notifyLocation, lastLoc, r, now)) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002569 if (lastLoc == null) {
2570 lastLoc = new Location(notifyLocation);
2571 r.mLastFixBroadcast = lastLoc;
2572 } else {
2573 lastLoc.set(notifyLocation);
2574 }
Wei Wang8486fc72019-03-07 18:49:21 -08002575 // Report location access before delivering location to the client. This will
2576 // note location delivery to appOps, so it should be called only when a
2577 // location is really being delivered to the client.
2578 if (!reportLocationAccessNoThrow(
2579 receiver.mCallerIdentity.mPid,
2580 receiver.mCallerIdentity.mUid,
2581 receiver.mCallerIdentity.mPackageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002582 receiver.mCallerIdentity.mFeatureId,
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002583 receiver.mAllowedResolutionLevel,
2584 "Location sent to " + receiver.mCallerIdentity.mListenerIdentifier)) {
Wei Wang8486fc72019-03-07 18:49:21 -08002585 if (D) {
2586 Log.d(TAG, "skipping loc update for no op app: "
2587 + receiver.mCallerIdentity.mPackageName);
2588 }
2589 continue;
2590 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002591 if (!receiver.callLocationChangedLocked(notifyLocation)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002592 Slog.w(TAG, "RemoteException calling onLocationChanged on "
2593 + receiver);
Victoria Lease09016ab2012-09-16 12:33:15 -07002594 receiverDead = true;
2595 }
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002596 r.mRealRequest.decrementNumUpdates();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002597 }
2598 }
2599
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002600 // track expired records
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08002601 if (r.mRealRequest.getNumUpdates() <= 0 || r.mExpirationRealtimeMs < now) {
Soonil Nagarkar39d614a2019-10-31 12:10:31 -07002602 // notify the client it can remove this listener
2603 r.mReceiver.callRemovedLocked();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002604 if (deadUpdateRecords == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002605 deadUpdateRecords = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002606 }
2607 deadUpdateRecords.add(r);
2608 }
2609 // track dead receivers
2610 if (receiverDead) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002611 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002612 deadReceivers = new ArrayList<>();
Mike Lockwood03ca2162010-04-01 08:10:09 -07002613 }
2614 if (!deadReceivers.contains(receiver)) {
2615 deadReceivers.add(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002616 }
2617 }
2618 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002619
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002620 // remove dead records and receivers outside the loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002621 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002622 for (Receiver receiver : deadReceivers) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002623 removeUpdatesLocked(receiver);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002624 }
2625 }
2626 if (deadUpdateRecords != null) {
2627 for (UpdateRecord r : deadUpdateRecords) {
2628 r.disposeLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002629 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002630 applyRequirementsLocked(manager);
Victoria Lease8b38b292012-12-04 15:04:43 -08002631 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002632 }
2633
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002634 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00002635 private void updateLastLocationLocked(Location location, String provider) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002636 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2637 Location lastNoGPSLocation;
2638 Location lastLocation = mLastLocation.get(provider);
2639 if (lastLocation == null) {
2640 lastLocation = new Location(provider);
2641 mLastLocation.put(provider, lastLocation);
2642 } else {
2643 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2644 if (noGPSLocation == null && lastNoGPSLocation != null) {
2645 // New location has no no-GPS location: adopt last no-GPS location. This is set
2646 // directly into location because we do not want to notify COARSE clients.
2647 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
2648 }
2649 }
2650 lastLocation.set(location);
2651 }
2652
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002653 // Geocoder
2654
Nick Pellye0fd6932012-07-11 10:26:13 -07002655 @Override
Mike Lockwoode15735a2010-09-20 17:48:47 -04002656 public boolean geocoderIsPresent() {
Mark Vandevoorde01ac80b2010-05-21 15:43:26 -07002657 return mGeocodeProvider != null;
2658 }
2659
Nick Pellye0fd6932012-07-11 10:26:13 -07002660 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661 public String getFromLocation(double latitude, double longitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002662 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002663 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002664 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
2665 params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002666 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002667 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002668 }
2669
Mike Lockwooda55c3212009-04-15 11:10:11 -04002670
Nick Pellye0fd6932012-07-11 10:26:13 -07002671 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002672 public String getFromLocationName(String locationName,
Mike Lockwooda55c3212009-04-15 11:10:11 -04002673 double lowerLeftLatitude, double lowerLeftLongitude,
2674 double upperRightLatitude, double upperRightLongitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002675 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002676
2677 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002678 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
2679 lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
2680 maxResults, params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002681 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002682 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002683 }
2684
2685 // Mock Providers
2686
Nick Pellye0fd6932012-07-11 10:26:13 -07002687 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002688 public void addTestProvider(String provider, ProviderProperties properties,
2689 String packageName) {
2690 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2691 != AppOpsManager.MODE_ALLOWED) {
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002692 return;
2693 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002694
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002695 synchronized (mLock) {
2696 LocationProviderManager manager = getLocationProviderManager(provider);
2697 if (manager == null) {
2698 manager = new LocationProviderManager(provider);
2699 mProviderManagers.add(manager);
2700 }
2701
2702 manager.setMockProvider(new MockProvider(mContext, properties));
2703 }
2704 }
2705
2706 @Override
2707 public void removeTestProvider(String provider, String packageName) {
2708 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2709 != AppOpsManager.MODE_ALLOWED) {
2710 return;
Mike Lockwooda4903f22010-02-17 06:42:23 -05002711 }
2712
Soonil Nagarkar68257742019-01-09 19:42:34 +00002713 synchronized (mLock) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002714 LocationProviderManager manager = getLocationProviderManager(provider);
2715 if (manager == null) {
2716 return;
2717 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002718
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002719 manager.setMockProvider(null);
2720 if (!manager.hasProvider()) {
2721 mProviderManagers.remove(manager);
2722 mLastLocation.remove(manager.getName());
2723 mLastLocationCoarseInterval.remove(manager.getName());
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002724 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002725 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09002726 }
2727
Nick Pellye0fd6932012-07-11 10:26:13 -07002728 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002729 public void setTestProviderLocation(String provider, Location location, String packageName) {
2730 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2731 != AppOpsManager.MODE_ALLOWED) {
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002732 return;
2733 }
2734
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002735 LocationProviderManager manager = getLocationProviderManager(provider);
2736 if (manager == null) {
2737 throw new IllegalArgumentException("provider doesn't exist: " + provider);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002738 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002739
2740 manager.setMockProviderLocation(location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002741 }
2742
Nick Pellye0fd6932012-07-11 10:26:13 -07002743 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002744 public void setTestProviderEnabled(String provider, boolean enabled, String packageName) {
2745 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2746 != AppOpsManager.MODE_ALLOWED) {
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002747 return;
2748 }
2749
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002750 LocationProviderManager manager = getLocationProviderManager(provider);
2751 if (manager == null) {
2752 throw new IllegalArgumentException("provider doesn't exist: " + provider);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002753 }
2754
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08002755 manager.setMockProviderAllowed(enabled);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002756 }
2757
2758 @Override
Kweku Adams4fb074e2019-02-01 16:03:27 -08002759 @NonNull
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002760 public List<LocationRequest> getTestProviderCurrentRequests(String provider,
2761 String packageName) {
2762 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2763 != AppOpsManager.MODE_ALLOWED) {
Kweku Adams4fb074e2019-02-01 16:03:27 -08002764 return Collections.emptyList();
2765 }
2766
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002767 LocationProviderManager manager = getLocationProviderManager(provider);
2768 if (manager == null) {
2769 throw new IllegalArgumentException("provider doesn't exist: " + provider);
Kweku Adams4fb074e2019-02-01 16:03:27 -08002770 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002771
2772 return manager.getMockProviderRequests();
Kweku Adams4fb074e2019-02-01 16:03:27 -08002773 }
2774
2775 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002776 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002777 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) {
2778 return;
2779 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002780
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002781 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
2782
Soonil Nagarkar68257742019-01-09 19:42:34 +00002783 synchronized (mLock) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002784 if (mGnssManagerService != null && args.length > 0 && args[0].equals("--gnssmetrics")) {
2785 mGnssManagerService.dump(fd, pw, args);
Blake Kragten47014d22019-12-06 14:18:38 -08002786 return;
Siddharth Raybb608c82017-03-16 11:33:34 -07002787 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002788
2789 ipw.println("Location Manager State:");
2790 ipw.increaseIndent();
2791 ipw.print("Current System Time: "
WyattRileyba6072f2019-04-18 07:37:52 -07002792 + TimeUtils.logTimeOfDay(System.currentTimeMillis()));
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002793 ipw.println(", Current Elapsed Time: "
WyattRileyba6072f2019-04-18 07:37:52 -07002794 + TimeUtils.formatDuration(SystemClock.elapsedRealtime()));
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08002795
2796 ipw.println("User Info:");
2797 ipw.increaseIndent();
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002798 mUserInfoHelper.dump(fd, ipw, args);
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08002799 ipw.decreaseIndent();
2800
2801 ipw.println("Location Settings:");
2802 ipw.increaseIndent();
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002803 mSettingsHelper.dump(fd, ipw, args);
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08002804 ipw.decreaseIndent();
2805
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002806 ipw.println("Battery Saver Location Mode: "
Kweku Adams4fb074e2019-02-01 16:03:27 -08002807 + locationPowerSaveModeToString(mBatterySaverMode));
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002808
2809 ipw.println("Location Listeners:");
2810 ipw.increaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002811 for (Receiver receiver : mReceivers.values()) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002812 ipw.println(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002813 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002814 ipw.decreaseIndent();
2815
2816 ipw.println("Active Records by Provider:");
2817 ipw.increaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002818 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002819 ipw.println(entry.getKey() + ":");
2820 ipw.increaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002821 for (UpdateRecord record : entry.getValue()) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002822 ipw.println(record);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002823 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002824 ipw.decreaseIndent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002825 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002826 ipw.decreaseIndent();
Anil Admal98d49b72019-02-06 15:26:33 -08002827
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002828 ipw.println("Historical Records by Provider:");
2829 ipw.increaseIndent();
WyattRileyd6b82a62019-12-30 18:12:50 -08002830 TreeMap<PackageProviderKey, PackageStatistics> sorted = new TreeMap<>();
2831 sorted.putAll(mRequestStatistics.statistics);
David Christie2ff96af2014-01-30 16:09:37 -08002832 for (Map.Entry<PackageProviderKey, PackageStatistics> entry
WyattRileyd6b82a62019-12-30 18:12:50 -08002833 : sorted.entrySet()) {
David Christie2ff96af2014-01-30 16:09:37 -08002834 PackageProviderKey key = entry.getKey();
WyattRileyd6b82a62019-12-30 18:12:50 -08002835 ipw.println(key.providerName + ": " + key.packageName + ": " + entry.getValue());
David Christie2ff96af2014-01-30 16:09:37 -08002836 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002837 ipw.decreaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002838
WyattRileyfa1ef8d32019-12-30 17:19:55 -08002839 mRequestStatistics.history.dump(ipw);
2840
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002841 ipw.println("Last Known Locations:");
2842 ipw.increaseIndent();
2843 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
2844 ipw.println(entry.getKey() + ": " + entry.getValue());
David Christie1b9b7b12013-04-15 15:31:11 -07002845 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002846 ipw.decreaseIndent();
2847
2848 ipw.println("Last Known Coarse Locations:");
2849 ipw.increaseIndent();
2850 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
2851 ipw.println(entry.getKey() + ": " + entry.getValue());
2852 }
2853 ipw.decreaseIndent();
David Christie1b9b7b12013-04-15 15:31:11 -07002854
Tyler Trephan2f3ee9a2019-03-21 10:54:22 -07002855 if (mGeofenceManager != null) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002856 ipw.println("Geofences:");
2857 ipw.increaseIndent();
2858 mGeofenceManager.dump(ipw);
2859 ipw.decreaseIndent();
Tyler Trephan2f3ee9a2019-03-21 10:54:22 -07002860 }
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002861
Wei Wang114922a2019-01-30 18:19:35 -08002862 if (mExtraLocationControllerPackage != null) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002863 ipw.println("Location Controller Extra Package: " + mExtraLocationControllerPackage
2864 + (mExtraLocationControllerPackageEnabled ? " [enabled]" : "[disabled]"));
Wei Wang980b7c22018-12-06 17:53:00 -08002865 }
2866
Tyler Trephan2f3ee9a2019-03-21 10:54:22 -07002867 if (mLocationFudger != null) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002868 ipw.println("Location Fudger:");
2869 ipw.increaseIndent();
2870 mLocationFudger.dump(fd, ipw, args);
2871 ipw.decreaseIndent();
Tyler Trephan2f3ee9a2019-03-21 10:54:22 -07002872 }
Anil Admal98d49b72019-02-06 15:26:33 -08002873
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08002874 ipw.println("Location Providers:");
2875 ipw.increaseIndent();
2876 for (LocationProviderManager manager : mProviderManagers) {
2877 manager.dump(fd, ipw, args);
2878 }
2879 ipw.decreaseIndent();
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002880
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002881 if (mGnssManagerService != null) {
2882 ipw.println("GNSS:");
2883 ipw.increaseIndent();
2884 mGnssManagerService.dump(fd, ipw, args);
2885 ipw.decreaseIndent();
2886 }
Anil Admal98d49b72019-02-06 15:26:33 -08002887 }
2888 }
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08002889
2890 private class LocalService extends LocationManagerInternal {
2891
2892 @Override
2893 public void requestSetProviderAllowed(String provider, boolean allowed) {
2894 Preconditions.checkArgument(provider != null, "invalid null provider");
2895
2896 synchronized (mLock) {
2897 LocationProviderManager manager = getLocationProviderManager(provider);
2898 if (manager != null) {
2899 manager.requestSetAllowed(allowed);
2900 }
2901 }
2902 }
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002903
2904 @Override
2905 public boolean isProviderPackage(String packageName) {
2906 for (LocationProviderManager manager : mProviderManagers) {
2907 if (manager.getPackages().contains(packageName)) {
2908 return true;
2909 }
2910 }
2911 return false;
2912 }
2913
2914 @Override
2915 public void sendNiResponse(int notifId, int userResponse) {
2916 if (mGnssManagerService != null) {
2917 mGnssManagerService.sendNiResponse(notifId, userResponse);
2918 }
2919 }
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08002920 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002921}