blob: c2a06117cf149dc75cc74065b07627c3d6da9215 [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
Maggieaa080f92018-01-04 15:35:11 -080019import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -080020import static android.location.LocationManager.FUSED_PROVIDER;
21import static android.location.LocationManager.GPS_PROVIDER;
22import static android.location.LocationManager.NETWORK_PROVIDER;
23import static android.location.LocationManager.PASSIVE_PROVIDER;
Soonil Nagarkar1575a042018-10-24 17:54:54 -070024import static android.location.LocationProvider.AVAILABLE;
Kweku Adams4fb074e2019-02-01 16:03:27 -080025import static android.os.PowerManager.locationPowerSaveModeToString;
Soonil Nagarkar94749f72018-11-08 11:46:43 -080026import static android.provider.Settings.Global.LOCATION_DISABLE_STATUS_CALLBACKS;
Maggieaa080f92018-01-04 15:35:11 -080027
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -080028import static com.android.internal.util.Preconditions.checkNotNull;
Soonil Nagarkar1575a042018-10-24 17:54:54 -070029import static com.android.internal.util.Preconditions.checkState;
30
Wei Wang980b7c22018-12-06 17:53:00 -080031import android.Manifest;
Wyatt Rileycf879db2017-01-12 13:57:38 -080032import android.annotation.NonNull;
Wyatt Riley49097c02018-03-15 09:14:43 -070033import android.annotation.Nullable;
Maggieaa080f92018-01-04 15:35:11 -080034import android.app.ActivityManager;
35import android.app.AppOpsManager;
36import android.app.PendingIntent;
37import android.content.BroadcastReceiver;
Maggieaa080f92018-01-04 15:35:11 -080038import android.content.Context;
39import android.content.Intent;
40import android.content.IntentFilter;
41import android.content.pm.ApplicationInfo;
42import android.content.pm.PackageInfo;
43import android.content.pm.PackageManager;
44import android.content.pm.PackageManager.NameNotFoundException;
45import android.content.pm.PackageManagerInternal;
46import android.content.pm.ResolveInfo;
47import android.content.pm.Signature;
48import android.content.res.Resources;
49import android.database.ContentObserver;
Brian Duddiecfa5b5b2019-01-22 18:01:40 +000050import android.hardware.location.ActivityRecognitionHardware;
Maggieaa080f92018-01-04 15:35:11 -080051import android.location.Address;
52import android.location.Criteria;
53import android.location.GeocoderParams;
54import android.location.Geofence;
gomo226b7b72018-12-12 16:49:39 -080055import android.location.GnssMeasurementCorrections;
Maggieaa080f92018-01-04 15:35:11 -080056import android.location.IBatchedLocationCallback;
57import android.location.IGnssMeasurementsListener;
58import android.location.IGnssNavigationMessageListener;
59import android.location.IGnssStatusListener;
Maggieaa080f92018-01-04 15:35:11 -080060import android.location.IGpsGeofenceHardware;
61import android.location.ILocationListener;
62import android.location.ILocationManager;
63import android.location.INetInitiatedListener;
64import android.location.Location;
65import android.location.LocationManager;
Maggieaa080f92018-01-04 15:35:11 -080066import android.location.LocationRequest;
67import android.os.Binder;
68import android.os.Bundle;
69import android.os.Handler;
70import android.os.IBinder;
Anil Admal98d49b72019-02-06 15:26:33 -080071import android.os.IInterface;
Maggieaa080f92018-01-04 15:35:11 -080072import android.os.PowerManager;
Kweku Adams4fb074e2019-02-01 16:03:27 -080073import android.os.PowerManager.ServiceType;
74import android.os.PowerManagerInternal;
Maggieaa080f92018-01-04 15:35:11 -080075import android.os.Process;
76import android.os.RemoteException;
77import android.os.SystemClock;
78import android.os.UserHandle;
79import android.os.UserManager;
80import android.os.WorkSource;
Narayan Kamath32684dd2018-01-08 17:32:51 +000081import android.os.WorkSource.WorkChain;
Maggieaa080f92018-01-04 15:35:11 -080082import android.provider.Settings;
83import android.text.TextUtils;
Soonil Nagarkar681d7112017-02-23 17:14:16 -080084import android.util.ArrayMap;
Soonil Nagarkar2b565df2017-02-14 13:33:23 -080085import android.util.ArraySet;
Maggieaa080f92018-01-04 15:35:11 -080086import android.util.EventLog;
87import android.util.Log;
88import android.util.Slog;
Yu-Han Yanga4d250e2018-10-02 21:29:20 -070089
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -080090import com.android.internal.annotations.GuardedBy;
destradaaea8a8a62014-06-23 18:19:03 -070091import com.android.internal.content.PackageMonitor;
92import com.android.internal.location.ProviderProperties;
93import com.android.internal.location.ProviderRequest;
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -070094import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060095import com.android.internal.util.DumpUtils;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -080096import com.android.internal.util.Preconditions;
Soonil Nagarkar1575a042018-10-24 17:54:54 -070097import com.android.server.location.AbstractLocationProvider;
Brian Duddiecfa5b5b2019-01-22 18:01:40 +000098import com.android.server.location.ActivityRecognitionProxy;
Anil Admal08b96122019-01-30 16:55:05 -080099import com.android.server.location.CallerIdentity;
destradaaea8a8a62014-06-23 18:19:03 -0700100import com.android.server.location.GeocoderProxy;
101import com.android.server.location.GeofenceManager;
102import com.android.server.location.GeofenceProxy;
Yu-Han Yang3557cc72018-03-21 12:48:36 -0700103import com.android.server.location.GnssBatchingProvider;
Lifu Tang818aa2c2016-02-01 01:52:00 -0800104import com.android.server.location.GnssLocationProvider;
105import com.android.server.location.GnssMeasurementsProvider;
106import com.android.server.location.GnssNavigationMessageProvider;
Anil Admal75b9fd62018-11-28 11:22:50 -0800107import com.android.server.location.GnssStatusListenerHelper;
destradaaea8a8a62014-06-23 18:19:03 -0700108import com.android.server.location.LocationBlacklist;
109import com.android.server.location.LocationFudger;
destradaaea8a8a62014-06-23 18:19:03 -0700110import com.android.server.location.LocationProviderProxy;
111import com.android.server.location.LocationRequestStatistics;
112import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
113import com.android.server.location.LocationRequestStatistics.PackageStatistics;
114import com.android.server.location.MockProvider;
115import com.android.server.location.PassiveProvider;
Anil Admal98d49b72019-02-06 15:26:33 -0800116import com.android.server.location.RemoteListenerHelper;
Yu-Han Yanga4d250e2018-10-02 21:29:20 -0700117
Mike Lockwood43e33f22010-03-26 10:41:48 -0400118import java.io.FileDescriptor;
119import java.io.PrintWriter;
120import java.util.ArrayList;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700121import java.util.Arrays;
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -0800122import java.util.Collections;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400123import java.util.HashMap;
124import java.util.HashSet;
125import java.util.List;
126import java.util.Map;
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800127import java.util.Map.Entry;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800128import java.util.NoSuchElementException;
Anil Admal98d49b72019-02-06 15:26:33 -0800129import java.util.function.Consumer;
130import java.util.function.Function;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131
132/**
133 * The service class that manages LocationProviders and issues location
134 * updates and alerts.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 */
Victoria Lease5cd731a2012-12-19 15:04:21 -0800136public class LocationManagerService extends ILocationManager.Stub {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137 private static final String TAG = "LocationManagerService";
JP Abgrallf79811e72013-02-01 18:45:05 -0800138 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700139
Olivier Gaillard7a222662017-11-20 16:07:24 +0000140 private static final String WAKELOCK_KEY = "*location*";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141
Victoria Lease37425c32012-10-16 16:08:48 -0700142 // Location resolution level: no location data whatsoever
143 private static final int RESOLUTION_LEVEL_NONE = 0;
144 // Location resolution level: coarse location data only
145 private static final int RESOLUTION_LEVEL_COARSE = 1;
146 // Location resolution level: fine location data
147 private static final int RESOLUTION_LEVEL_FINE = 2;
148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700150 android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700151
152 private static final String NETWORK_LOCATION_SERVICE_ACTION =
Stan Chesnutt39062dd2013-07-22 14:33:30 -0700153 "com.android.location.service.v3.NetworkLocationProvider";
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700154 private static final String FUSED_LOCATION_SERVICE_ACTION =
155 "com.android.location.service.FusedLocationProvider";
156
David Christie1b9b7b12013-04-15 15:31:11 -0700157 private static final long NANOS_PER_MILLI = 1000000L;
158
David Christie0b837452013-07-29 16:02:13 -0700159 // The maximum interval a location request can have and still be considered "high power".
160 private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
161
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700162 private static final int FOREGROUND_IMPORTANCE_CUTOFF
gomo48f1a642017-11-10 20:35:46 -0800163 = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700164
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800165 // default background throttling interval if not overriden in settings
Soonil Nagarkarde6780a2017-02-07 10:39:41 -0800166 private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800167
Wei Wangdd070f22018-06-21 11:29:40 -0700168 // Default value for maximum age of last location returned to applications with foreground-only
169 // location permissions.
170 private static final long DEFAULT_LAST_LOCATION_MAX_AGE_MS = 20 * 60 * 1000;
171
Nick Pellyf1be6862012-05-15 10:53:42 -0700172 // Location Providers may sometimes deliver location updates
173 // slightly faster that requested - provide grace period so
174 // we don't unnecessarily filter events that are otherwise on
175 // time
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700176 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
Nick Pellyf1be6862012-05-15 10:53:42 -0700177
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700178 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
179
Soonil Nagarkar68257742019-01-09 19:42:34 +0000180 private final Object mLock = new Object();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800181 private final Context mContext;
182 private final Handler mHandler;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700183
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800184 private AppOpsManager mAppOps;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700185 private PackageManager mPackageManager;
Victoria Lease0aa28602013-05-29 15:28:26 -0700186 private PowerManager mPowerManager;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800187 private ActivityManager mActivityManager;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700188 private UserManager mUserManager;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800189
190 private GeofenceManager mGeofenceManager;
191 private LocationFudger mLocationFudger;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700192 private GeocoderProxy mGeocodeProvider;
Anil Admal75b9fd62018-11-28 11:22:50 -0800193 private GnssStatusListenerHelper mGnssStatusProvider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700194 private INetInitiatedListener mNetInitiatedListener;
Nick Pelly4035f5a2012-08-17 14:43:49 -0700195 private PassiveProvider mPassiveProvider; // track passive provider for special cases
196 private LocationBlacklist mBlacklist;
Lifu Tang818aa2c2016-02-01 01:52:00 -0800197 private GnssMeasurementsProvider mGnssMeasurementsProvider;
198 private GnssNavigationMessageProvider mGnssNavigationMessageProvider;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800199 @GuardedBy("mLock")
Wei Wang980b7c22018-12-06 17:53:00 -0800200 private String mLocationControllerExtraPackage;
201 private boolean mLocationControllerExtraPackageEnabled;
Wei Liu5241a4c2015-05-11 14:00:36 -0700202 private IGpsGeofenceHardware mGpsGeofenceProxy;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700203
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800204 // list of currently active providers
205 @GuardedBy("mLock")
206 private final ArrayList<LocationProvider> mProviders = new ArrayList<>();
Soonil Nagarkar68257742019-01-09 19:42:34 +0000207
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800208 // list of non-mock providers, so that when mock providers replace real providers, they can be
209 // later re-replaced
210 @GuardedBy("mLock")
211 private final ArrayList<LocationProvider> mRealProviders = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800213 @GuardedBy("mLock")
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800214 private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700215 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800216 new HashMap<>();
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700217
David Christie2ff96af2014-01-30 16:09:37 -0800218 private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics();
219
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700220 // mapping from provider name to last known location
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800221 @GuardedBy("mLock")
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800222 private final HashMap<String, Location> mLastLocation = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223
David Christie1b9b7b12013-04-15 15:31:11 -0700224 // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
225 // locations stored here are not fudged for coarse permissions.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800226 @GuardedBy("mLock")
David Christie1b9b7b12013-04-15 15:31:11 -0700227 private final HashMap<String, Location> mLastLocationCoarseInterval =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800228 new HashMap<>();
David Christie1b9b7b12013-04-15 15:31:11 -0700229
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800230 private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800231
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800232 private final ArraySet<String> mIgnoreSettingsPackageWhitelist = new ArraySet<>();
233
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800234 @GuardedBy("mLock")
Anil Admal98d49b72019-02-06 15:26:33 -0800235 private final ArrayMap<IBinder, LinkedListener<IGnssMeasurementsListener>>
236 mGnssMeasurementsListeners = new ArrayMap<>();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800237 @GuardedBy("mLock")
Anil Admal98d49b72019-02-06 15:26:33 -0800238 private final ArrayMap<IBinder, LinkedListener<IGnssNavigationMessageListener>>
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800239 mGnssNavigationMessageListeners = new ArrayMap<>();
Anil Admal98d49b72019-02-06 15:26:33 -0800240 @GuardedBy("mLock")
241 private final ArrayMap<IBinder, LinkedListener<IGnssStatusListener>>
242 mGnssStatusListeners = new ArrayMap<>();
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800243
Victoria Lease38389b62012-09-30 11:44:22 -0700244 // current active user on the device - other users are denied location data
Xiaohui Chena4490622015-09-22 15:29:31 -0700245 private int mCurrentUserId = UserHandle.USER_SYSTEM;
gomo48f1a642017-11-10 20:35:46 -0800246 private int[] mCurrentUserProfiles = new int[]{UserHandle.USER_SYSTEM};
Victoria Lease38389b62012-09-30 11:44:22 -0700247
Lifu Tang9363b942016-02-16 18:07:00 -0800248 private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;
Lifu Tang82f893d2016-01-21 18:15:33 -0800249
Siddharth Raybb608c82017-03-16 11:33:34 -0700250 private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;
Wyatt Rileyaa420d52017-07-03 15:14:42 -0700251
Yu-Han Yang3557cc72018-03-21 12:48:36 -0700252 private GnssBatchingProvider mGnssBatchingProvider;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800253 @GuardedBy("mLock")
Wyatt Rileycf879db2017-01-12 13:57:38 -0800254 private IBatchedLocationCallback mGnssBatchingCallback;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800255 @GuardedBy("mLock")
Anil Admal98d49b72019-02-06 15:26:33 -0800256 private LinkedListener<IBatchedLocationCallback> mGnssBatchingDeathCallback;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800257 @GuardedBy("mLock")
Wyatt Rileycf879db2017-01-12 13:57:38 -0800258 private boolean mGnssBatchingInProgress = false;
259
Kweku Adams4fb074e2019-02-01 16:03:27 -0800260 @GuardedBy("mLock")
261 @PowerManager.LocationPowerSaveMode
262 private int mBatterySaverMode;
263
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700264 public LocationManagerService(Context context) {
265 super();
266 mContext = context;
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -0800267 mHandler = FgThread.getHandler();
The Android Open Source Project4df24232009-03-05 14:34:35 -0800268
Svet Ganovadc1cf42015-06-15 16:36:24 -0700269 // Let the package manager query which are the default location
270 // providers as they get certain permissions granted by default.
271 PackageManagerInternal packageManagerInternal = LocalServices.getService(
272 PackageManagerInternal.class);
273 packageManagerInternal.setLocationPackagesProvider(
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700274 userId -> mContext.getResources().getStringArray(
275 com.android.internal.R.array.config_locationProviderPackageNames));
Wei Wangffb94e62019-01-14 00:05:45 -0800276 packageManagerInternal.setLocationExtraPackagesProvider(
277 userId -> mContext.getResources().getStringArray(
278 com.android.internal.R.array.config_locationExtraPackageNames));
Svet Ganovadc1cf42015-06-15 16:36:24 -0700279
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700280 // most startup is deferred until systemRunning()
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700281 }
282
Svetoslav Ganova0027152013-06-25 14:59:53 -0700283 public void systemRunning() {
Soonil Nagarkar68257742019-01-09 19:42:34 +0000284 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800285 initializeLocked();
Victoria Lease5cd731a2012-12-19 15:04:21 -0800286 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800287 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700288
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800289 @GuardedBy("mLock")
290 private void initializeLocked() {
291 mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
292 mPackageManager = mContext.getPackageManager();
293 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
294 mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
295 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
296
297 mLocationFudger = new LocationFudger(mContext, mHandler);
298 mBlacklist = new LocationBlacklist(mContext, mHandler);
299 mBlacklist.init();
300 mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
301
302 // prepare providers
303 initializeProvidersLocked();
304
305 // add listeners
306 mAppOps.startWatchingMode(
307 AppOpsManager.OP_COARSE_LOCATION,
308 null,
309 AppOpsManager.WATCH_FOREGROUND_CHANGES,
310 new AppOpsManager.OnOpChangedInternalListener() {
311 public void onOpChanged(int op, String packageName) {
312 synchronized (mLock) {
313 onAppOpChangedLocked();
314 }
315 }
316 });
317 mPackageManager.addOnPermissionsChangeListener(
318 uid -> {
319 synchronized (mLock) {
320 onPermissionsChangedLocked();
321 }
322 });
323
324 mActivityManager.addOnUidImportanceListener(
325 (uid, importance) -> {
326 synchronized (mLock) {
327 onUidImportanceChangedLocked(uid, importance);
328 }
329 },
330 FOREGROUND_IMPORTANCE_CUTOFF);
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700331 mContext.getContentResolver().registerContentObserver(
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800332 Settings.Secure.getUriFor(Settings.Secure.LOCATION_MODE), true,
333 new ContentObserver(mHandler) {
Victoria Lease5cd731a2012-12-19 15:04:21 -0800334 @Override
335 public void onChange(boolean selfChange) {
Soonil Nagarkar68257742019-01-09 19:42:34 +0000336 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800337 onLocationModeChangedLocked(true);
338 }
339 }
340 }, UserHandle.USER_ALL);
341 mContext.getContentResolver().registerContentObserver(
342 Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
343 new ContentObserver(mHandler) {
344 @Override
345 public void onChange(boolean selfChange) {
346 synchronized (mLock) {
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800347 onProviderAllowedChangedLocked();
Soonil Nagarkar68257742019-01-09 19:42:34 +0000348 }
Victoria Lease5cd731a2012-12-19 15:04:21 -0800349 }
350 }, UserHandle.USER_ALL);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800351 mContext.getContentResolver().registerContentObserver(
352 Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS),
353 true,
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800354 new ContentObserver(mHandler) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800355 @Override
356 public void onChange(boolean selfChange) {
Soonil Nagarkar68257742019-01-09 19:42:34 +0000357 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800358 onBackgroundThrottleIntervalChangedLocked();
Soonil Nagarkar68257742019-01-09 19:42:34 +0000359 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800360 }
361 }, UserHandle.USER_ALL);
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800362 mContext.getContentResolver().registerContentObserver(
gomo48f1a642017-11-10 20:35:46 -0800363 Settings.Global.getUriFor(
364 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
365 true,
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800366 new ContentObserver(mHandler) {
gomo48f1a642017-11-10 20:35:46 -0800367 @Override
368 public void onChange(boolean selfChange) {
Soonil Nagarkar68257742019-01-09 19:42:34 +0000369 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800370 onBackgroundThrottleWhitelistChangedLocked();
Soonil Nagarkar68257742019-01-09 19:42:34 +0000371 }
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800372 }
gomo48f1a642017-11-10 20:35:46 -0800373 }, UserHandle.USER_ALL);
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800374 mContext.getContentResolver().registerContentObserver(
375 Settings.Global.getUriFor(
376 Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST),
377 true,
378 new ContentObserver(mHandler) {
379 @Override
380 public void onChange(boolean selfChange) {
381 synchronized (mLock) {
382 onIgnoreSettingsWhitelistChangedLocked();
383 }
384 }
385 }, UserHandle.USER_ALL);
Kweku Adams4fb074e2019-02-01 16:03:27 -0800386 PowerManagerInternal localPowerManager =
387 LocalServices.getService(PowerManagerInternal.class);
388 localPowerManager.registerLowPowerModeObserver(ServiceType.LOCATION,
389 state -> {
390 synchronized (mLock) {
391 onBatterySaverModeChangedLocked(state.locationMode);
392 }
393 });
Wei Wangdd070f22018-06-21 11:29:40 -0700394
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800395 new PackageMonitor() {
396 @Override
397 public void onPackageDisappeared(String packageName, int reason) {
398 synchronized (mLock) {
399 LocationManagerService.this.onPackageDisappearedLocked(packageName);
400 }
401 }
402 }.register(mContext, mHandler.getLooper(), true);
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700403
Victoria Lease38389b62012-09-30 11:44:22 -0700404 IntentFilter intentFilter = new IntentFilter();
405 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700406 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
407 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
Kweku Adams4fb074e2019-02-01 16:03:27 -0800408 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
409 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
Victoria Lease38389b62012-09-30 11:44:22 -0700410
411 mContext.registerReceiverAsUser(new BroadcastReceiver() {
412 @Override
413 public void onReceive(Context context, Intent intent) {
Kweku Adams4fb074e2019-02-01 16:03:27 -0800414 final String action = intent.getAction();
415 if (action == null) {
416 return;
417 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800418 synchronized (mLock) {
Kweku Adams4fb074e2019-02-01 16:03:27 -0800419 switch (action) {
420 case Intent.ACTION_USER_SWITCHED:
421 onUserChangedLocked(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
422 break;
423 case Intent.ACTION_MANAGED_PROFILE_ADDED:
424 case Intent.ACTION_MANAGED_PROFILE_REMOVED:
425 onUserProfilesChangedLocked();
426 break;
427 case Intent.ACTION_SCREEN_ON:
428 case Intent.ACTION_SCREEN_OFF:
429 onScreenStateChangedLocked();
430 break;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800431 }
Victoria Lease38389b62012-09-30 11:44:22 -0700432 }
433 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800434 }, UserHandle.ALL, intentFilter, null, mHandler);
435
436 // switching the user from null to system here performs the bulk of the initialization work.
437 // the user being changed will cause a reload of all user specific settings, which causes
438 // provider initialization, and propagates changes until a steady state is reached
439 mCurrentUserId = UserHandle.USER_NULL;
440 onUserChangedLocked(UserHandle.USER_SYSTEM);
441
442 // initialize in-memory settings values
443 onBackgroundThrottleWhitelistChangedLocked();
Soonil Nagarkar835a0a02019-01-30 14:55:03 -0800444 onIgnoreSettingsWhitelistChangedLocked();
Kweku Adams4fb074e2019-02-01 16:03:27 -0800445 onBatterySaverModeChangedLocked(mPowerManager.getLocationPowerSaveMode());
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700446 }
447
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800448 @GuardedBy("mLock")
449 private void onAppOpChangedLocked() {
450 for (Receiver receiver : mReceivers.values()) {
451 receiver.updateMonitoring(true);
452 }
453 for (LocationProvider p : mProviders) {
454 applyRequirementsLocked(p);
455 }
456 }
457
458 @GuardedBy("mLock")
459 private void onPermissionsChangedLocked() {
460 for (LocationProvider p : mProviders) {
461 applyRequirementsLocked(p);
462 }
463 }
464
465 @GuardedBy("mLock")
Kweku Adams4fb074e2019-02-01 16:03:27 -0800466 private void onBatterySaverModeChangedLocked(int newLocationMode) {
467 if (D) {
468 Slog.d(TAG,
469 "Battery Saver location mode changed from "
470 + locationPowerSaveModeToString(mBatterySaverMode) + " to "
471 + locationPowerSaveModeToString(newLocationMode));
472 }
473
474 if (mBatterySaverMode == newLocationMode) {
475 return;
476 }
477
478 mBatterySaverMode = newLocationMode;
479 for (LocationProvider p : mProviders) {
480 applyRequirementsLocked(p);
481 }
482 }
483
484 @GuardedBy("mLock")
485 private void onScreenStateChangedLocked() {
486 if (mBatterySaverMode == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF) {
487 for (LocationProvider p : mProviders) {
488 applyRequirementsLocked(p);
489 }
490 }
491 }
492
493 @GuardedBy("mLock")
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800494 private void onLocationModeChangedLocked(boolean broadcast) {
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800495 if (D) {
496 Log.d(TAG, "location enabled is now " + isLocationEnabled());
497 }
498
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800499 for (LocationProvider p : mProviders) {
500 p.onLocationModeChangedLocked();
501 }
502
503 if (broadcast) {
504 mContext.sendBroadcastAsUser(
505 new Intent(LocationManager.MODE_CHANGED_ACTION),
506 UserHandle.ALL);
507 }
508 }
509
510 @GuardedBy("mLock")
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800511 private void onProviderAllowedChangedLocked() {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800512 for (LocationProvider p : mProviders) {
513 p.onAllowedChangedLocked();
514 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800515 }
516
517 @GuardedBy("mLock")
518 private void onPackageDisappearedLocked(String packageName) {
519 ArrayList<Receiver> deadReceivers = null;
520
521 for (Receiver receiver : mReceivers.values()) {
Anil Admal08b96122019-01-30 16:55:05 -0800522 if (receiver.mCallerIdentity.mPackageName.equals(packageName)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800523 if (deadReceivers == null) {
524 deadReceivers = new ArrayList<>();
525 }
526 deadReceivers.add(receiver);
527 }
528 }
529
530 // perform removal outside of mReceivers loop
531 if (deadReceivers != null) {
532 for (Receiver receiver : deadReceivers) {
533 removeUpdatesLocked(receiver);
534 }
535 }
536 }
537
538 @GuardedBy("mLock")
539 private void onUidImportanceChangedLocked(int uid, int importance) {
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700540 boolean foreground = isImportanceForeground(importance);
541 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800542 for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
543 String provider = entry.getKey();
544 for (UpdateRecord record : entry.getValue()) {
Anil Admal08b96122019-01-30 16:55:05 -0800545 if (record.mReceiver.mCallerIdentity.mUid == uid
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800546 && record.mIsForegroundUid != foreground) {
gomo48f1a642017-11-10 20:35:46 -0800547 if (D) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800548 Log.d(TAG, "request from uid " + uid + " is now "
Anil Admal98d49b72019-02-06 15:26:33 -0800549 + foregroundAsString(foreground));
gomo48f1a642017-11-10 20:35:46 -0800550 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800551 record.updateForeground(foreground);
552
Anil Admal08b96122019-01-30 16:55:05 -0800553 if (!isThrottlingExemptLocked(record.mReceiver.mCallerIdentity)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800554 affectedProviders.add(provider);
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700555 }
556 }
557 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800558 }
559 for (String provider : affectedProviders) {
560 applyRequirementsLocked(provider);
561 }
Anil Admal75b9fd62018-11-28 11:22:50 -0800562
Anil Admal98d49b72019-02-06 15:26:33 -0800563 updateGnssDataProviderOnUidImportanceChangedLocked(mGnssMeasurementsListeners,
564 mGnssMeasurementsProvider, IGnssMeasurementsListener.Stub::asInterface,
565 uid, foreground);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800566
Anil Admal98d49b72019-02-06 15:26:33 -0800567 updateGnssDataProviderOnUidImportanceChangedLocked(mGnssNavigationMessageListeners,
568 mGnssNavigationMessageProvider, IGnssNavigationMessageListener.Stub::asInterface,
569 uid, foreground);
570
571 updateGnssDataProviderOnUidImportanceChangedLocked(mGnssStatusListeners,
572 mGnssStatusProvider, IGnssStatusListener.Stub::asInterface, uid, foreground);
573 }
574
575 @GuardedBy("mLock")
576 private <TListener extends IInterface> void updateGnssDataProviderOnUidImportanceChangedLocked(
577 ArrayMap<IBinder, ? extends LinkedListenerBase> gnssDataListeners,
578 RemoteListenerHelper<TListener> gnssDataProvider,
579 Function<IBinder, TListener> mapBinderToListener, int uid, boolean foreground) {
580 for (Entry<IBinder, ? extends LinkedListenerBase> entry : gnssDataListeners.entrySet()) {
581 LinkedListenerBase linkedListener = entry.getValue();
582 CallerIdentity callerIdentity = linkedListener.mCallerIdentity;
583 if (callerIdentity.mUid != uid) {
584 continue;
585 }
586
587 if (D) {
588 Log.d(TAG, linkedListener.mListenerName + " from uid "
589 + uid + " is now " + foregroundAsString(foreground));
590 }
591
592 TListener listener = mapBinderToListener.apply(entry.getKey());
593 if (foreground || isThrottlingExemptLocked(callerIdentity)) {
594 gnssDataProvider.addListener(listener, callerIdentity);
595 } else {
596 gnssDataProvider.removeListener(listener);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800597 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700598 }
599 }
600
Anil Admal98d49b72019-02-06 15:26:33 -0800601 private static String foregroundAsString(boolean foreground) {
602 return foreground ? "foreground" : "background";
603 }
604
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800605 private static boolean isImportanceForeground(int importance) {
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700606 return importance <= FOREGROUND_IMPORTANCE_CUTOFF;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800607 }
608
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800609 @GuardedBy("mLock")
610 private void onBackgroundThrottleIntervalChangedLocked() {
611 for (LocationProvider provider : mProviders) {
612 applyRequirementsLocked(provider);
Soonil Nagarkar68257742019-01-09 19:42:34 +0000613 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -0800614 }
615
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800616 @GuardedBy("mLock")
617 private void onBackgroundThrottleWhitelistChangedLocked() {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800618 mBackgroundThrottlePackageWhitelist.clear();
619 mBackgroundThrottlePackageWhitelist.addAll(
620 SystemConfig.getInstance().getAllowUnthrottledLocation());
Soonil Nagarkar835a0a02019-01-30 14:55:03 -0800621
622 String setting = Settings.Global.getString(
623 mContext.getContentResolver(),
624 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
625 if (!TextUtils.isEmpty(setting)) {
626 mBackgroundThrottlePackageWhitelist.addAll(Arrays.asList(setting.split(",")));
627 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800628
629 for (LocationProvider p : mProviders) {
630 applyRequirementsLocked(p);
Soonil Nagarkar68257742019-01-09 19:42:34 +0000631 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -0800632 }
633
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800634 @GuardedBy("lock")
635 private void onIgnoreSettingsWhitelistChangedLocked() {
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800636 mIgnoreSettingsPackageWhitelist.clear();
637 mIgnoreSettingsPackageWhitelist.addAll(
638 SystemConfig.getInstance().getAllowIgnoreLocationSettings());
Soonil Nagarkar835a0a02019-01-30 14:55:03 -0800639
640 String setting = Settings.Global.getString(
641 mContext.getContentResolver(),
642 Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST);
643 if (!TextUtils.isEmpty(setting)) {
644 mIgnoreSettingsPackageWhitelist.addAll(Arrays.asList(setting.split(",")));
645 }
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800646
647 for (LocationProvider p : mProviders) {
648 applyRequirementsLocked(p);
649 }
650 }
651
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800652 @GuardedBy("mLock")
653 private void onUserProfilesChangedLocked() {
654 mCurrentUserProfiles = mUserManager.getProfileIdsWithDisabled(mCurrentUserId);
655 }
656
657 @GuardedBy("mLock")
658 private boolean isCurrentProfileLocked(int userId) {
659 return ArrayUtils.contains(mCurrentUserProfiles, userId);
660 }
661
662 @GuardedBy("mLock")
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700663 private void ensureFallbackFusedProviderPresentLocked(String[] pkgs) {
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500664 PackageManager pm = mContext.getPackageManager();
665 String systemPackageName = mContext.getPackageName();
666 ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
667
668 List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
669 new Intent(FUSED_LOCATION_SERVICE_ACTION),
670 PackageManager.GET_META_DATA, mCurrentUserId);
671 for (ResolveInfo rInfo : rInfos) {
672 String packageName = rInfo.serviceInfo.packageName;
673
674 // Check that the signature is in the list of supported sigs. If it's not in
675 // this list the standard provider binding logic won't bind to it.
676 try {
677 PackageInfo pInfo;
678 pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
679 if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
680 Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
681 ", but has wrong signature, ignoring");
682 continue;
683 }
684 } catch (NameNotFoundException e) {
685 Log.e(TAG, "missing package: " + packageName);
686 continue;
687 }
688
689 // Get the version info
690 if (rInfo.serviceInfo.metaData == null) {
691 Log.w(TAG, "Found fused provider without metadata: " + packageName);
692 continue;
693 }
694
695 int version = rInfo.serviceInfo.metaData.getInt(
696 ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
697 if (version == 0) {
698 // This should be the fallback fused location provider.
699
700 // Make sure it's in the system partition.
701 if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
702 if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
703 continue;
704 }
705
706 // Check that the fallback is signed the same as the OS
707 // as a proxy for coreApp="true"
708 if (pm.checkSignatures(systemPackageName, packageName)
709 != PackageManager.SIGNATURE_MATCH) {
gomo48f1a642017-11-10 20:35:46 -0800710 if (D) {
711 Log.d(TAG, "Fallback candidate not signed the same as system: "
712 + packageName);
713 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500714 continue;
715 }
716
717 // Found a valid fallback.
718 if (D) Log.d(TAG, "Found fallback provider: " + packageName);
719 return;
720 } else {
721 if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
722 }
723 }
724
725 throw new IllegalStateException("Unable to find a fused location provider that is in the "
726 + "system partition with version 0 and signed with the platform certificate. "
727 + "Such a package is needed to provide a default fused location provider in the "
728 + "event that no other fused location provider has been installed or is currently "
729 + "available. For example, coreOnly boot mode when decrypting the data "
730 + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
731 }
732
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800733 @GuardedBy("mLock")
734 private void initializeProvidersLocked() {
Victoria Lease5c24fd02012-10-01 11:00:50 -0700735 // create a passive location provider, which is always enabled
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800736 LocationProvider passiveProviderManager = new LocationProvider(PASSIVE_PROVIDER);
Soonil Nagarkar68257742019-01-09 19:42:34 +0000737 addProviderLocked(passiveProviderManager);
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -0800738 mPassiveProvider = new PassiveProvider(mContext, passiveProviderManager);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800739 passiveProviderManager.attachLocked(mPassiveProvider);
Victoria Lease5c24fd02012-10-01 11:00:50 -0700740
Lifu Tang30f95a72016-01-07 23:20:38 -0800741 if (GnssLocationProvider.isSupported()) {
Wei Liu5241a4c2015-05-11 14:00:36 -0700742 // Create a gps location provider
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800743 LocationProvider gnssProviderManager = new LocationProvider(GPS_PROVIDER, true);
744 mRealProviders.add(gnssProviderManager);
745 addProviderLocked(gnssProviderManager);
746
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700747 GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext,
748 gnssProviderManager,
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800749 mHandler.getLooper());
750 gnssProviderManager.attachLocked(gnssProvider);
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700751
Lifu Tang9363b942016-02-16 18:07:00 -0800752 mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
Wyatt Rileycf879db2017-01-12 13:57:38 -0800753 mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider();
Siddharth Raybb608c82017-03-16 11:33:34 -0700754 mGnssMetricsProvider = gnssProvider.getGnssMetricsProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800755 mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
756 mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
Lifu Tang818aa2c2016-02-01 01:52:00 -0800757 mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
758 mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800759 mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700760 }
761
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700762 /*
763 Load package name(s) containing location provider support.
764 These packages can contain services implementing location providers:
765 Geocoder Provider, Network Location Provider, and
766 Fused Location Provider. They will each be searched for
767 service components implementing these providers.
768 The location framework also has support for installation
769 of new location providers at run-time. The new package does not
770 have to be explicitly listed here, however it must have a signature
771 that matches the signature of at least one package on this list.
772 */
773 Resources resources = mContext.getResources();
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500774 String[] pkgs = resources.getStringArray(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700775 com.android.internal.R.array.config_locationProviderPackageNames);
gomo48f1a642017-11-10 20:35:46 -0800776 if (D) {
777 Log.d(TAG, "certificates for location providers pulled from: " +
778 Arrays.toString(pkgs));
779 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500780
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700781 ensureFallbackFusedProviderPresentLocked(pkgs);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700782
783 // bind to network provider
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800784 LocationProvider networkProviderManager = new LocationProvider(NETWORK_PROVIDER, true);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700785 LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
786 mContext,
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700787 networkProviderManager,
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700788 NETWORK_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700789 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
790 com.android.internal.R.string.config_networkLocationProviderPackageName,
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700791 com.android.internal.R.array.config_locationProviderPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700792 if (networkProvider != null) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800793 mRealProviders.add(networkProviderManager);
Soonil Nagarkar68257742019-01-09 19:42:34 +0000794 addProviderLocked(networkProviderManager);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800795 networkProviderManager.attachLocked(networkProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700796 } else {
gomo48f1a642017-11-10 20:35:46 -0800797 Slog.w(TAG, "no network location provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700798 }
799
800 // bind to fused provider
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800801 LocationProvider fusedProviderManager = new LocationProvider(FUSED_PROVIDER);
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700802 LocationProviderProxy fusedProvider = LocationProviderProxy.createAndBind(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700803 mContext,
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700804 fusedProviderManager,
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700805 FUSED_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700806 com.android.internal.R.bool.config_enableFusedLocationOverlay,
807 com.android.internal.R.string.config_fusedLocationProviderPackageName,
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700808 com.android.internal.R.array.config_locationProviderPackageNames);
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700809 if (fusedProvider != null) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800810 mRealProviders.add(fusedProviderManager);
Soonil Nagarkar68257742019-01-09 19:42:34 +0000811 addProviderLocked(fusedProviderManager);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800812 fusedProviderManager.attachLocked(fusedProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700813 } else {
814 Slog.e(TAG, "no fused location provider found",
815 new IllegalStateException("Location service needs a fused location provider"));
816 }
817
818 // bind to geocoder provider
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700819 mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
820 com.android.internal.R.bool.config_enableGeocoderOverlay,
821 com.android.internal.R.string.config_geocoderProviderPackageName,
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700822 com.android.internal.R.array.config_locationProviderPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700823 if (mGeocodeProvider == null) {
gomo48f1a642017-11-10 20:35:46 -0800824 Slog.e(TAG, "no geocoder provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700825 }
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700826
destradaaf9a274c2014-07-25 15:11:56 -0700827 // bind to geofence provider
828 GeofenceProxy provider = GeofenceProxy.createAndBind(
gomo48f1a642017-11-10 20:35:46 -0800829 mContext, com.android.internal.R.bool.config_enableGeofenceOverlay,
destradaaf9a274c2014-07-25 15:11:56 -0700830 com.android.internal.R.string.config_geofenceProviderPackageName,
831 com.android.internal.R.array.config_locationProviderPackageNames,
Wei Liu5241a4c2015-05-11 14:00:36 -0700832 mGpsGeofenceProxy,
Jiyong Park4cc3a1c2018-03-08 16:43:07 +0900833 null);
destradaaf9a274c2014-07-25 15:11:56 -0700834 if (provider == null) {
gomo48f1a642017-11-10 20:35:46 -0800835 Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
destradaa0682809a2013-08-12 18:50:30 -0700836 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900837
Brian Duddiecfa5b5b2019-01-22 18:01:40 +0000838 // bind to hardware activity recognition
839 boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
840 ActivityRecognitionHardware activityRecognitionHardware = null;
841 if (activityRecognitionHardwareIsSupported) {
842 activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
843 } else {
844 Slog.d(TAG, "Hardware Activity-Recognition not supported.");
845 }
846 ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
847 mContext,
848 activityRecognitionHardwareIsSupported,
849 activityRecognitionHardware,
850 com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
851 com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
852 com.android.internal.R.array.config_locationProviderPackageNames);
853 if (proxy == null) {
854 Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
855 }
856
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900857 String[] testProviderStrings = resources.getStringArray(
858 com.android.internal.R.array.config_testLocationProviders);
859 for (String testProviderString : testProviderStrings) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -0800860 String[] fragments = testProviderString.split(",");
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900861 String name = fragments[0].trim();
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900862 ProviderProperties properties = new ProviderProperties(
863 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
864 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
865 Boolean.parseBoolean(fragments[3]) /* requiresCell */,
866 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
867 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
868 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
869 Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
870 Integer.parseInt(fragments[8]) /* powerRequirement */,
871 Integer.parseInt(fragments[9]) /* accuracy */);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800872 LocationProvider testProviderManager = new LocationProvider(name);
873 addProviderLocked(testProviderManager);
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -0800874 new MockProvider(mContext, testProviderManager, properties);
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900875 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700876 }
Mike Lockwood9637d472009-04-02 21:41:57 -0700877
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800878 @GuardedBy("mLock")
879 private void onUserChangedLocked(int userId) {
Jianzheng Zhoud5c69462013-10-10 14:02:09 +0800880 if (mCurrentUserId == userId) {
881 return;
882 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800883
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800884 if (D) {
885 Log.d(TAG, "foreground user is changing to " + userId);
886 }
887
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800888 // let providers know the current user is on the way out before changing the user
889 for (LocationProvider p : mProviders) {
890 p.onUserChangingLocked();
Soonil Nagarkar68257742019-01-09 19:42:34 +0000891 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800892
893 mCurrentUserId = userId;
894 onUserProfilesChangedLocked();
895
896 mBlacklist.switchUser(userId);
897
898 // if the user changes, per-user settings may also have changed
899 onLocationModeChangedLocked(false);
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800900 onProviderAllowedChangedLocked();
901
902 // always force useability to be rechecked, even if no per-user settings have changed
903 for (LocationProvider p : mProviders) {
904 p.onUseableChangedLocked(false);
905 }
Victoria Lease38389b62012-09-30 11:44:22 -0700906 }
907
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700908 private class LocationProvider implements AbstractLocationProvider.LocationProviderManager {
909
910 private final String mName;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700911
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800912 // whether this provider should respect LOCATION_PROVIDERS_ALLOWED (ie gps and network)
913 private final boolean mIsManagedBySettings;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700914
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800915 // remember to clear binder identity before invoking any provider operation
916 @GuardedBy("mLock")
917 @Nullable protected AbstractLocationProvider mProvider;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700918
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800919 @GuardedBy("mLock")
920 private boolean mUseable; // combined state
921 @GuardedBy("mLock")
922 private boolean mAllowed; // state of LOCATION_PROVIDERS_ALLOWED
923 @GuardedBy("mLock")
924 private boolean mEnabled; // state of provider
925
926 @GuardedBy("mLock")
927 @Nullable private ProviderProperties mProperties;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700928
929 private LocationProvider(String name) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800930 this(name, false);
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700931 }
932
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800933 private LocationProvider(String name, boolean isManagedBySettings) {
934 mName = name;
935 mIsManagedBySettings = isManagedBySettings;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700936
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800937 mProvider = null;
938 mUseable = false;
939 mAllowed = !mIsManagedBySettings;
940 mEnabled = false;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700941 mProperties = null;
Soonil Nagarkar42da1b12019-01-22 11:29:27 -0800942
943 if (mIsManagedBySettings) {
944 // since we assume providers are disabled by default
945 Settings.Secure.putStringForUser(
946 mContext.getContentResolver(),
947 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
948 "-" + mName,
949 mCurrentUserId);
950 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700951 }
952
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800953 @GuardedBy("mLock")
954 public void attachLocked(AbstractLocationProvider provider) {
955 checkNotNull(provider);
956 checkState(mProvider == null);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800957
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800958 if (D) {
959 Log.d(TAG, mName + " provider attached");
960 }
961
962 mProvider = provider;
963 onUseableChangedLocked(false);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800964 }
965
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700966 public String getName() {
967 return mName;
968 }
969
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800970 @GuardedBy("mLock")
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -0800971 public List<String> getPackagesLocked() {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800972 if (mProvider == null) {
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -0800973 return Collections.emptyList();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800974 } else {
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -0800975 // safe to not clear binder context since this doesn't call into the real provider
976 return mProvider.getProviderPackages();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800977 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700978 }
979
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800980 public boolean isMock() {
981 return false;
982 }
983
984 @GuardedBy("mLock")
985 public boolean isPassiveLocked() {
986 return mProvider == mPassiveProvider;
987 }
988
989 @GuardedBy("mLock")
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700990 @Nullable
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800991 public ProviderProperties getPropertiesLocked() {
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700992 return mProperties;
993 }
994
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800995 @GuardedBy("mLock")
996 public void setRequestLocked(ProviderRequest request, WorkSource workSource) {
997 if (mProvider != null) {
998 long identity = Binder.clearCallingIdentity();
999 try {
1000 mProvider.setRequest(request, workSource);
1001 } finally {
1002 Binder.restoreCallingIdentity(identity);
1003 }
1004 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001005 }
1006
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001007 @GuardedBy("mLock")
1008 public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001009 pw.print(" " + mName + " provider");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001010 if (isMock()) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001011 pw.print(" [mock]");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001012 }
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001013 pw.println(":");
1014
1015 pw.println(" useable=" + mUseable);
1016 if (!mUseable) {
1017 pw.println(" attached=" + (mProvider != null));
1018 if (mIsManagedBySettings) {
1019 pw.println(" allowed=" + mAllowed);
1020 }
1021 pw.println(" enabled=" + mEnabled);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001022 }
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001023
1024 pw.println(" properties=" + mProperties);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001025
1026 if (mProvider != null) {
1027 long identity = Binder.clearCallingIdentity();
1028 try {
1029 mProvider.dump(fd, pw, args);
1030 } finally {
1031 Binder.restoreCallingIdentity(identity);
1032 }
1033 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001034 }
1035
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001036 @GuardedBy("mLock")
1037 public long getStatusUpdateTimeLocked() {
1038 if (mProvider != null) {
1039 long identity = Binder.clearCallingIdentity();
1040 try {
1041 return mProvider.getStatusUpdateTime();
1042 } finally {
1043 Binder.restoreCallingIdentity(identity);
1044 }
1045 } else {
1046 return 0;
1047 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001048 }
1049
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001050 @GuardedBy("mLock")
1051 public int getStatusLocked(Bundle extras) {
1052 if (mProvider != null) {
1053 long identity = Binder.clearCallingIdentity();
1054 try {
1055 return mProvider.getStatus(extras);
1056 } finally {
1057 Binder.restoreCallingIdentity(identity);
1058 }
1059 } else {
1060 return AVAILABLE;
1061 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001062 }
1063
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001064 @GuardedBy("mLock")
1065 public void sendExtraCommandLocked(String command, Bundle extras) {
1066 if (mProvider != null) {
1067 long identity = Binder.clearCallingIdentity();
1068 try {
1069 mProvider.sendExtraCommand(command, extras);
1070 } finally {
1071 Binder.restoreCallingIdentity(identity);
1072 }
1073 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001074 }
1075
1076 // called from any thread
1077 @Override
1078 public void onReportLocation(Location location) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001079 // no security check necessary because this is coming from an internal-only interface
1080 // move calls coming from below LMS onto a different thread to avoid deadlock
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001081 mHandler.post(() -> {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001082 synchronized (mLock) {
1083 handleLocationChangedLocked(location, this);
1084 }
1085 });
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001086 }
1087
1088 // called from any thread
1089 @Override
1090 public void onReportLocation(List<Location> locations) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001091 // move calls coming from below LMS onto a different thread to avoid deadlock
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001092 mHandler.post(() -> {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001093 synchronized (mLock) {
1094 LocationProvider gpsProvider = getLocationProviderLocked(GPS_PROVIDER);
1095 if (gpsProvider == null || !gpsProvider.isUseableLocked()) {
1096 Slog.w(TAG, "reportLocationBatch() called without user permission");
1097 return;
1098 }
1099
1100 if (mGnssBatchingCallback == null) {
1101 Slog.e(TAG, "reportLocationBatch() called without active Callback");
1102 return;
1103 }
1104
1105 try {
1106 mGnssBatchingCallback.onLocationBatch(locations);
1107 } catch (RemoteException e) {
1108 Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e);
1109 }
1110 }
1111 });
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001112 }
1113
1114 // called from any thread
1115 @Override
1116 public void onSetEnabled(boolean enabled) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001117 // move calls coming from below LMS onto a different thread to avoid deadlock
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001118 mHandler.post(() -> {
Soonil Nagarkar68257742019-01-09 19:42:34 +00001119 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001120 if (enabled == mEnabled) {
1121 return;
Soonil Nagarkar68257742019-01-09 19:42:34 +00001122 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001123
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001124 if (D) {
1125 Log.d(TAG, mName + " provider enabled is now " + mEnabled);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001126 }
1127
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001128 mEnabled = enabled;
1129 onUseableChangedLocked(false);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001130 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001131 });
1132 }
1133
1134 @Override
1135 public void onSetProperties(ProviderProperties properties) {
Soonil Nagarkar66c0bac2019-01-15 13:36:44 -08001136 // because this does not invoke any other methods which might result in calling back
1137 // into the location provider, it is safe to run this on the calling thread. it is also
1138 // currently necessary to run this on the calling thread to ensure that property changes
1139 // are publicly visibly immediately, ie for mock providers which are created.
1140 synchronized (mLock) {
1141 mProperties = properties;
1142 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001143 }
1144
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001145 @GuardedBy("mLock")
1146 public void onLocationModeChangedLocked() {
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001147 onUseableChangedLocked(false);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001148 }
1149
1150 @GuardedBy("mLock")
1151 public void onAllowedChangedLocked() {
1152 if (mIsManagedBySettings) {
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001153 String allowedProviders = Settings.Secure.getStringForUser(
1154 mContext.getContentResolver(),
1155 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
1156 mCurrentUserId);
1157 boolean allowed = TextUtils.delimitedStringContains(allowedProviders, ',', mName);
1158
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001159 if (allowed == mAllowed) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00001160 return;
1161 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001162
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001163 if (D) {
1164 Log.d(TAG, mName + " provider allowed is now " + mAllowed);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001165 }
1166
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001167 mAllowed = allowed;
1168 onUseableChangedLocked(true);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001169 }
1170 }
1171
1172 @GuardedBy("mLock")
1173 public boolean isUseableLocked() {
1174 return isUseableForUserLocked(mCurrentUserId);
1175 }
1176
1177 @GuardedBy("mLock")
1178 public boolean isUseableForUserLocked(int userId) {
Soonil Nagarkar497c1cb2019-03-04 16:22:39 -08001179 return isCurrentProfileLocked(userId) && mUseable;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001180 }
1181
1182 @GuardedBy("mLock")
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001183 private boolean isUseableIgnoringAllowedLocked() {
1184 return mProvider != null && mProviders.contains(this) && isLocationEnabled()
1185 && mEnabled;
1186 }
1187
1188 @GuardedBy("mLock")
1189 public void onUseableChangedLocked(boolean isAllowedChanged) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001190 // if any property that contributes to "useability" here changes state, it MUST result
1191 // in a direct or indrect call to onUseableChangedLocked. this allows the provider to
1192 // guarantee that it will always eventually reach the correct state.
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001193 boolean useableIgnoringAllowed = isUseableIgnoringAllowedLocked();
1194 boolean useable = useableIgnoringAllowed && mAllowed;
1195
1196 // update deprecated provider allowed settings for backwards compatibility, and do this
1197 // even if there is no change in overall useability state. this may result in trying to
1198 // overwrite the same value, but Settings handles deduping this.
1199 if (mIsManagedBySettings) {
1200 // a "-" change derived from the allowed setting should not be overwritten, but a
1201 // "+" change should be corrected if necessary
1202 if (useableIgnoringAllowed && !isAllowedChanged) {
1203 Settings.Secure.putStringForUser(
1204 mContext.getContentResolver(),
1205 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
1206 "+" + mName,
1207 mCurrentUserId);
1208 } else if (!useableIgnoringAllowed) {
1209 Settings.Secure.putStringForUser(
1210 mContext.getContentResolver(),
1211 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
1212 "-" + mName,
1213 mCurrentUserId);
1214 }
1215 }
1216
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001217 if (useable == mUseable) {
1218 return;
1219 }
1220 mUseable = useable;
1221
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001222 if (D) {
1223 Log.d(TAG, mName + " provider useable is now " + mUseable);
1224 }
1225
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001226 if (!mUseable) {
1227 // If any provider has been disabled, clear all last locations for all
1228 // providers. This is to be on the safe side in case a provider has location
1229 // derived from this disabled provider.
1230 mLastLocation.clear();
1231 mLastLocationCoarseInterval.clear();
1232 }
1233
1234 updateProviderUseableLocked(this);
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001235
1236 mContext.sendBroadcastAsUser(
1237 new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
1238 UserHandle.ALL);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001239 }
1240
1241 @GuardedBy("mLock")
1242 public void onUserChangingLocked() {
1243 // when the user is about to change, we set this provider to un-useable, and notify all
1244 // of the current user clients. when the user is finished changing, useability will be
1245 // updated back via onLocationModeChanged() and onAllowedChanged().
1246 mUseable = false;
1247 updateProviderUseableLocked(this);
1248 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001249 }
1250
1251 private class MockLocationProvider extends LocationProvider {
1252
Kweku Adams4fb074e2019-02-01 16:03:27 -08001253 private ProviderRequest mCurrentRequest;
1254
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001255 private MockLocationProvider(String name) {
1256 super(name);
1257 }
1258
1259 @Override
1260 public void attachLocked(AbstractLocationProvider provider) {
1261 checkState(provider instanceof MockProvider);
1262 super.attachLocked(provider);
1263 }
1264
1265 public boolean isMock() {
1266 return true;
1267 }
1268
1269 @GuardedBy("mLock")
1270 public void setEnabledLocked(boolean enabled) {
1271 if (mProvider != null) {
1272 long identity = Binder.clearCallingIdentity();
1273 try {
1274 ((MockProvider) mProvider).setEnabled(enabled);
1275 } finally {
1276 Binder.restoreCallingIdentity(identity);
Soonil Nagarkar68257742019-01-09 19:42:34 +00001277 }
1278 }
1279 }
1280
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001281 @GuardedBy("mLock")
1282 public void setLocationLocked(Location location) {
1283 if (mProvider != null) {
1284 long identity = Binder.clearCallingIdentity();
1285 try {
1286 ((MockProvider) mProvider).setLocation(location);
1287 } finally {
1288 Binder.restoreCallingIdentity(identity);
1289 }
1290 }
1291 }
1292
Kweku Adams4fb074e2019-02-01 16:03:27 -08001293 @Override
1294 @GuardedBy("mLock")
1295 public void setRequestLocked(ProviderRequest request, WorkSource workSource) {
1296 super.setRequestLocked(request, workSource);
1297 mCurrentRequest = request;
1298 }
1299
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001300 @GuardedBy("mLock")
1301 public void setStatusLocked(int status, Bundle extras, long updateTime) {
1302 if (mProvider != null) {
1303 long identity = Binder.clearCallingIdentity();
1304 try {
1305 ((MockProvider) mProvider).setStatus(status, extras, updateTime);
1306 } finally {
1307 Binder.restoreCallingIdentity(identity);
1308 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001309 }
1310 }
1311 }
1312
Victoria Lease38389b62012-09-30 11:44:22 -07001313 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001314 * A wrapper class holding either an ILocationListener or a PendingIntent to receive
1315 * location updates.
1316 */
Anil Admal98d49b72019-02-06 15:26:33 -08001317 private final class Receiver extends LinkedListenerBase implements PendingIntent.OnFinished {
Yu-Han Yang24189822018-07-11 15:24:11 -07001318 private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001319 private final int mAllowedResolutionLevel; // resolution level allowed to receiver
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001320
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001321 private final ILocationListener mListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001322 final PendingIntent mPendingIntent;
David Christie82edc9b2013-07-19 11:31:42 -07001323 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001324 private final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
1325 private final Object mKey;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001326
gomo48f1a642017-11-10 20:35:46 -08001327 final HashMap<String, UpdateRecord> mUpdateRecords = new HashMap<>();
Nick Pellyf1be6862012-05-15 10:53:42 -07001328
David Christie0b837452013-07-29 16:02:13 -07001329 // True if app ops has started monitoring this receiver for locations.
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001330 private boolean mOpMonitoring;
David Christie0b837452013-07-29 16:02:13 -07001331 // True if app ops has started monitoring this receiver for high power (gps) locations.
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001332 private boolean mOpHighPowerMonitoring;
1333 private int mPendingBroadcasts;
Victoria Lease0aa28602013-05-29 15:28:26 -07001334 PowerManager.WakeLock mWakeLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001335
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001336 private Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -07001337 String packageName, WorkSource workSource, boolean hideFromAppOps) {
Anil Admal98d49b72019-02-06 15:26:33 -08001338 super(new CallerIdentity(uid, pid, packageName), "LocationListener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001339 mListener = listener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001340 mPendingIntent = intent;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001341 if (listener != null) {
1342 mKey = listener.asBinder();
1343 } else {
1344 mKey = intent;
1345 }
Victoria Lease37425c32012-10-16 16:08:48 -07001346 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
Narayan Kamath32684dd2018-01-08 17:32:51 +00001347 if (workSource != null && workSource.isEmpty()) {
David Christie82edc9b2013-07-19 11:31:42 -07001348 workSource = null;
1349 }
1350 mWorkSource = workSource;
David Christie40e57822013-07-30 11:36:48 -07001351 mHideFromAppOps = hideFromAppOps;
Victoria Lease0aa28602013-05-29 15:28:26 -07001352
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001353 updateMonitoring(true);
1354
Victoria Lease0aa28602013-05-29 15:28:26 -07001355 // construct/configure wakelock
1356 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
David Christie82edc9b2013-07-19 11:31:42 -07001357 if (workSource == null) {
Anil Admal08b96122019-01-30 16:55:05 -08001358 workSource = new WorkSource(mCallerIdentity.mUid, mCallerIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001359 }
1360 mWakeLock.setWorkSource(workSource);
Yu-Han Yang24189822018-07-11 15:24:11 -07001361
1362 // For a non-reference counted wakelock, each acquire will reset the timeout, and we
1363 // only need to release it once.
1364 mWakeLock.setReferenceCounted(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001365 }
1366
1367 @Override
1368 public boolean equals(Object otherObj) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001369 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001370 }
1371
1372 @Override
1373 public int hashCode() {
1374 return mKey.hashCode();
1375 }
Mike Lockwood3681f262009-05-12 10:52:03 -04001376
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001377 @Override
1378 public String toString() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001379 StringBuilder s = new StringBuilder();
1380 s.append("Reciever[");
1381 s.append(Integer.toHexString(System.identityHashCode(this)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001382 if (mListener != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001383 s.append(" listener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001384 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001385 s.append(" intent");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001386 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001387 for (String p : mUpdateRecords.keySet()) {
1388 s.append(" ").append(mUpdateRecords.get(p).toString());
1389 }
Wei Wangdd070f22018-06-21 11:29:40 -07001390 s.append(" monitoring location: ").append(mOpMonitoring);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001391 s.append("]");
1392 return s.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393 }
1394
David Christie15b31912013-08-13 15:54:32 -07001395 /**
1396 * Update AppOp monitoring for this receiver.
1397 *
1398 * @param allow If true receiver is currently active, if false it's been removed.
1399 */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001400 public void updateMonitoring(boolean allow) {
David Christie40e57822013-07-30 11:36:48 -07001401 if (mHideFromAppOps) {
1402 return;
1403 }
1404
David Christie15b31912013-08-13 15:54:32 -07001405 boolean requestingLocation = false;
1406 boolean requestingHighPowerLocation = false;
1407 if (allow) {
1408 // See if receiver has any enabled update records. Also note if any update records
1409 // are high power (has a high power provider with an interval under a threshold).
1410 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001411 LocationProvider provider = getLocationProviderLocked(updateRecord.mProvider);
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001412 if (provider == null) {
1413 continue;
1414 }
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001415 if (!provider.isUseableLocked() && !isSettingsExemptLocked(updateRecord)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001416 continue;
1417 }
1418
1419 requestingLocation = true;
1420 ProviderProperties properties = provider.getPropertiesLocked();
1421 if (properties != null
1422 && properties.mPowerRequirement == Criteria.POWER_HIGH
1423 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
1424 requestingHighPowerLocation = true;
1425 break;
David Christie15b31912013-08-13 15:54:32 -07001426 }
1427 }
1428 }
1429
David Christie0b837452013-07-29 16:02:13 -07001430 // First update monitoring of any location request (including high power).
David Christie15b31912013-08-13 15:54:32 -07001431 mOpMonitoring = updateMonitoring(
1432 requestingLocation,
1433 mOpMonitoring,
David Christie0b837452013-07-29 16:02:13 -07001434 AppOpsManager.OP_MONITOR_LOCATION);
1435
1436 // Now update monitoring of high power requests only.
David Christiec750c1f2013-08-08 12:56:57 -07001437 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
David Christie15b31912013-08-13 15:54:32 -07001438 mOpHighPowerMonitoring = updateMonitoring(
1439 requestingHighPowerLocation,
1440 mOpHighPowerMonitoring,
David Christie0b837452013-07-29 16:02:13 -07001441 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
David Christiec750c1f2013-08-08 12:56:57 -07001442 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
David Christie15b31912013-08-13 15:54:32 -07001443 // Send an intent to notify that a high power request has been added/removed.
David Christiec750c1f2013-08-08 12:56:57 -07001444 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
1445 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
1446 }
David Christie0b837452013-07-29 16:02:13 -07001447 }
1448
1449 /**
1450 * Update AppOps monitoring for a single location request and op type.
1451 *
gomo48f1a642017-11-10 20:35:46 -08001452 * @param allowMonitoring True if monitoring is allowed for this request/op.
David Christie0b837452013-07-29 16:02:13 -07001453 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
gomo48f1a642017-11-10 20:35:46 -08001454 * @param op AppOps code for the op to update.
David Christie0b837452013-07-29 16:02:13 -07001455 * @return True if monitoring is on for this request/op after updating.
1456 */
1457 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
1458 int op) {
1459 if (!currentlyMonitoring) {
1460 if (allowMonitoring) {
Anil Admal08b96122019-01-30 16:55:05 -08001461 return mAppOps.startOpNoThrow(op, mCallerIdentity.mUid,
1462 mCallerIdentity.mPackageName) == AppOpsManager.MODE_ALLOWED;
David Christie0b837452013-07-29 16:02:13 -07001463 }
1464 } else {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001465 if (!allowMonitoring
Wei Wang16276a42019-02-04 18:23:31 -08001466 || mAppOps.checkOpNoThrow(op, mCallerIdentity.mUid,
Anil Admal08b96122019-01-30 16:55:05 -08001467 mCallerIdentity.mPackageName) != AppOpsManager.MODE_ALLOWED) {
1468 mAppOps.finishOp(op, mCallerIdentity.mUid, mCallerIdentity.mPackageName);
David Christie0b837452013-07-29 16:02:13 -07001469 return false;
1470 }
1471 }
1472
1473 return currentlyMonitoring;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001474 }
1475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001476 public boolean isListener() {
1477 return mListener != null;
1478 }
1479
1480 public boolean isPendingIntent() {
1481 return mPendingIntent != null;
1482 }
1483
1484 public ILocationListener getListener() {
1485 if (mListener != null) {
1486 return mListener;
1487 }
1488 throw new IllegalStateException("Request for non-existent listener");
1489 }
1490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
1492 if (mListener != null) {
1493 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001494 mListener.onStatusChanged(provider, status, extras);
1495 // call this after broadcasting so we do not increment
1496 // if we throw an exception.
1497 incrementPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001498 } catch (RemoteException e) {
1499 return false;
1500 }
1501 } else {
1502 Intent statusChanged = new Intent();
Victoria Lease61ecb022012-11-13 15:12:51 -08001503 statusChanged.putExtras(new Bundle(extras));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
1505 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001506 mPendingIntent.send(mContext, 0, statusChanged, this, mHandler,
1507 getResolutionPermission(mAllowedResolutionLevel),
1508 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
1509 // call this after broadcasting so we do not increment
1510 // if we throw an exception.
1511 incrementPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 } catch (PendingIntent.CanceledException e) {
1513 return false;
1514 }
1515 }
1516 return true;
1517 }
1518
1519 public boolean callLocationChangedLocked(Location location) {
1520 if (mListener != null) {
1521 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001522 mListener.onLocationChanged(new Location(location));
1523 // call this after broadcasting so we do not increment
1524 // if we throw an exception.
1525 incrementPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001526 } catch (RemoteException e) {
1527 return false;
1528 }
1529 } else {
1530 Intent locationChanged = new Intent();
gomo48f1a642017-11-10 20:35:46 -08001531 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED,
1532 new Location(location));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001533 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001534 mPendingIntent.send(mContext, 0, locationChanged, this, mHandler,
1535 getResolutionPermission(mAllowedResolutionLevel),
1536 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
1537 // call this after broadcasting so we do not increment
1538 // if we throw an exception.
1539 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001540 } catch (PendingIntent.CanceledException e) {
1541 return false;
1542 }
1543 }
1544 return true;
1545 }
1546
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001547 private boolean callProviderEnabledLocked(String provider, boolean enabled) {
David Christie15b31912013-08-13 15:54:32 -07001548 // First update AppOp monitoring.
1549 // An app may get/lose location access as providers are enabled/disabled.
1550 updateMonitoring(true);
1551
Mike Lockwood48f17512009-04-23 09:12:08 -07001552 if (mListener != null) {
1553 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001554 if (enabled) {
1555 mListener.onProviderEnabled(provider);
1556 } else {
1557 mListener.onProviderDisabled(provider);
Mike Lockwood48f17512009-04-23 09:12:08 -07001558 }
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001559 // call this after broadcasting so we do not increment
1560 // if we throw an exception.
1561 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001562 } catch (RemoteException e) {
1563 return false;
1564 }
1565 } else {
1566 Intent providerIntent = new Intent();
1567 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1568 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001569 mPendingIntent.send(mContext, 0, providerIntent, this, mHandler,
1570 getResolutionPermission(mAllowedResolutionLevel),
1571 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
1572 // call this after broadcasting so we do not increment
1573 // if we throw an exception.
1574 incrementPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575 } catch (PendingIntent.CanceledException e) {
1576 return false;
1577 }
1578 }
1579 return true;
1580 }
1581
Nick Pellyf1be6862012-05-15 10:53:42 -07001582 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001583 public void binderDied() {
Anil Admal98d49b72019-02-06 15:26:33 -08001584 if (D) Log.d(TAG, "Remote " + mListenerName + " died.");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001585
Soonil Nagarkar68257742019-01-09 19:42:34 +00001586 synchronized (mLock) {
1587 removeUpdatesLocked(this);
Soonil Nagarkar68257742019-01-09 19:42:34 +00001588 clearPendingBroadcastsLocked();
1589 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001590 }
1591
Nick Pellye0fd6932012-07-11 10:26:13 -07001592 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001593 public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1594 int resultCode, String resultData, Bundle resultExtras) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001595 synchronized (mLock) {
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001596 decrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001597 }
1598 }
1599
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001600 // this must be called while synchronized by caller in a synchronized block
1601 // containing the sending of the broadcaset
1602 private void incrementPendingBroadcastsLocked() {
Yu-Han Yang24189822018-07-11 15:24:11 -07001603 mPendingBroadcasts++;
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001604 // so wakelock calls will succeed
1605 long identity = Binder.clearCallingIdentity();
1606 try {
1607 mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
1608 } finally {
1609 Binder.restoreCallingIdentity(identity);
1610 }
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001611 }
1612
1613 private void decrementPendingBroadcastsLocked() {
1614 if (--mPendingBroadcasts == 0) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001615 // so wakelock calls will succeed
1616 long identity = Binder.clearCallingIdentity();
1617 try {
1618 if (mWakeLock.isHeld()) {
1619 mWakeLock.release();
1620 }
1621 } finally {
1622 Binder.restoreCallingIdentity(identity);
Victoria Lease0aa28602013-05-29 15:28:26 -07001623 }
1624 }
1625 }
1626
1627 public void clearPendingBroadcastsLocked() {
1628 if (mPendingBroadcasts > 0) {
1629 mPendingBroadcasts = 0;
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001630 // so wakelock calls will succeed
1631 long identity = Binder.clearCallingIdentity();
1632 try {
1633 if (mWakeLock.isHeld()) {
1634 mWakeLock.release();
1635 }
1636 } finally {
1637 Binder.restoreCallingIdentity(identity);
Victoria Lease0aa28602013-05-29 15:28:26 -07001638 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001639 }
1640 }
1641 }
1642
Nick Pellye0fd6932012-07-11 10:26:13 -07001643 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001644 public void locationCallbackFinished(ILocationListener listener) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001645 //Do not use getReceiverLocked here as that will add the ILocationListener to
Joshua Bartel080b61b2009-10-05 12:44:46 -04001646 //the receiver list if it is not found. If it is not found then the
1647 //LocationListener was removed when it had a pending broadcast and should
1648 //not be added back.
Soonil Nagarkar68257742019-01-09 19:42:34 +00001649 synchronized (mLock) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001650 Receiver receiver = mReceivers.get(listener.asBinder());
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001651 if (receiver != null) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001652 receiver.decrementPendingBroadcastsLocked();
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001653 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00001654 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001655 }
1656
Lifu Tang82f893d2016-01-21 18:15:33 -08001657 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001658 public int getGnssYearOfHardware() {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001659 if (mGnssSystemInfoProvider != null) {
Lifu Tang9363b942016-02-16 18:07:00 -08001660 return mGnssSystemInfoProvider.getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001661 } else {
1662 return 0;
1663 }
1664 }
1665
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001666 @Override
Wyatt Riley49097c02018-03-15 09:14:43 -07001667 @Nullable
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001668 public String getGnssHardwareModelName() {
1669 if (mGnssSystemInfoProvider != null) {
1670 return mGnssSystemInfoProvider.getGnssHardwareModelName();
1671 } else {
Wyatt Riley49097c02018-03-15 09:14:43 -07001672 return null;
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001673 }
1674 }
1675
Wyatt Rileycf879db2017-01-12 13:57:38 -08001676 private boolean hasGnssPermissions(String packageName) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001677 synchronized (mLock) {
1678 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
1679 checkResolutionLevelIsSufficientForProviderUseLocked(
1680 allowedResolutionLevel,
1681 GPS_PROVIDER);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001682
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001683 int pid = Binder.getCallingPid();
1684 int uid = Binder.getCallingUid();
1685 long identity = Binder.clearCallingIdentity();
1686 try {
1687 return checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
1688 } finally {
1689 Binder.restoreCallingIdentity(identity);
1690 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08001691 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08001692 }
1693
Wyatt Rileycf879db2017-01-12 13:57:38 -08001694 @Override
1695 public int getGnssBatchSize(String packageName) {
1696 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1697 "Location Hardware permission not granted to access hardware batching");
1698
1699 if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
Yu-Han Yang3557cc72018-03-21 12:48:36 -07001700 return mGnssBatchingProvider.getBatchSize();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001701 } else {
1702 return 0;
1703 }
1704 }
1705
Wyatt Rileycf879db2017-01-12 13:57:38 -08001706 @Override
1707 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) {
1708 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1709 "Location Hardware permission not granted to access hardware batching");
1710
1711 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1712 return false;
1713 }
1714
Anil Admal98d49b72019-02-06 15:26:33 -08001715 CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(),
1716 Binder.getCallingPid(), packageName);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001717 synchronized (mLock) {
1718 mGnssBatchingCallback = callback;
Anil Admal98d49b72019-02-06 15:26:33 -08001719 mGnssBatchingDeathCallback = new LinkedListener<>(callback,
1720 "BatchedLocationCallback", callerIdentity,
1721 (IBatchedLocationCallback listener) -> {
1722 stopGnssBatch();
1723 removeGnssBatchingCallback();
1724 });
1725 if (!linkToListenerDeathNotificationLocked(callback.asBinder(),
1726 mGnssBatchingDeathCallback)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001727 return false;
1728 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001729 return true;
1730 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08001731 }
1732
Wyatt Rileycf879db2017-01-12 13:57:38 -08001733 @Override
1734 public void removeGnssBatchingCallback() {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001735 synchronized (mLock) {
Anil Admal98d49b72019-02-06 15:26:33 -08001736 unlinkFromListenerDeathNotificationLocked(mGnssBatchingCallback.asBinder(),
1737 mGnssBatchingDeathCallback);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001738 mGnssBatchingCallback = null;
1739 mGnssBatchingDeathCallback = null;
Wyatt Rileycf879db2017-01-12 13:57:38 -08001740 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08001741 }
1742
Wyatt Rileycf879db2017-01-12 13:57:38 -08001743 @Override
1744 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
1745 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1746 "Location Hardware permission not granted to access hardware batching");
1747
1748 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1749 return false;
1750 }
1751
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001752 synchronized (mLock) {
1753 if (mGnssBatchingInProgress) {
1754 // Current design does not expect multiple starts to be called repeatedly
1755 Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch");
1756 // Try to clean up anyway, and continue
1757 stopGnssBatch();
1758 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08001759
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001760 mGnssBatchingInProgress = true;
1761 return mGnssBatchingProvider.start(periodNanos, wakeOnFifoFull);
1762 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08001763 }
1764
Wyatt Rileycf879db2017-01-12 13:57:38 -08001765 @Override
1766 public void flushGnssBatch(String packageName) {
1767 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1768 "Location Hardware permission not granted to access hardware batching");
1769
1770 if (!hasGnssPermissions(packageName)) {
1771 Log.e(TAG, "flushGnssBatch called without GNSS permissions");
1772 return;
1773 }
1774
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001775 synchronized (mLock) {
1776 if (!mGnssBatchingInProgress) {
1777 Log.w(TAG, "flushGnssBatch called with no batch in progress");
1778 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08001779
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001780 if (mGnssBatchingProvider != null) {
1781 mGnssBatchingProvider.flush();
1782 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08001783 }
1784 }
1785
Wyatt Rileycf879db2017-01-12 13:57:38 -08001786 @Override
1787 public boolean stopGnssBatch() {
1788 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1789 "Location Hardware permission not granted to access hardware batching");
1790
Soonil Nagarkar68257742019-01-09 19:42:34 +00001791 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001792 if (mGnssBatchingProvider != null) {
1793 mGnssBatchingInProgress = false;
1794 return mGnssBatchingProvider.stop();
1795 } else {
1796 return false;
1797 }
1798 }
1799 }
1800
1801 @GuardedBy("mLock")
1802 private void addProviderLocked(LocationProvider provider) {
1803 Preconditions.checkState(getLocationProviderLocked(provider.getName()) == null);
1804
1805 mProviders.add(provider);
1806
1807 provider.onAllowedChangedLocked(); // allowed state may change while provider was inactive
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001808 provider.onUseableChangedLocked(false);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001809 }
1810
1811 @GuardedBy("mLock")
1812 private void removeProviderLocked(LocationProvider provider) {
1813 if (mProviders.remove(provider)) {
1814 long identity = Binder.clearCallingIdentity();
1815 try {
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001816 provider.onUseableChangedLocked(false);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001817 } finally {
1818 Binder.restoreCallingIdentity(identity);
1819 }
1820 }
1821 }
1822
1823 @GuardedBy("mLock")
1824 @Nullable
1825 private LocationProvider getLocationProviderLocked(String providerName) {
1826 for (LocationProvider provider : mProviders) {
1827 if (providerName.equals(provider.getName())) {
1828 return provider;
Soonil Nagarkar68257742019-01-09 19:42:34 +00001829 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001830 }
1831
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001832 return null;
Maggie2a9409e2018-03-21 11:47:28 -07001833 }
1834
Victoria Lease37425c32012-10-16 16:08:48 -07001835 private String getResolutionPermission(int resolutionLevel) {
1836 switch (resolutionLevel) {
1837 case RESOLUTION_LEVEL_FINE:
1838 return android.Manifest.permission.ACCESS_FINE_LOCATION;
1839 case RESOLUTION_LEVEL_COARSE:
1840 return android.Manifest.permission.ACCESS_COARSE_LOCATION;
1841 default:
1842 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001843 }
Victoria Leaseda479c52012-10-15 15:24:16 -07001844 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001845
Victoria Lease37425c32012-10-16 16:08:48 -07001846 private int getAllowedResolutionLevel(int pid, int uid) {
1847 if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001848 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001849 return RESOLUTION_LEVEL_FINE;
1850 } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001851 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001852 return RESOLUTION_LEVEL_COARSE;
1853 } else {
1854 return RESOLUTION_LEVEL_NONE;
Victoria Leaseda479c52012-10-15 15:24:16 -07001855 }
Victoria Lease4fab68b2012-09-13 13:20:59 -07001856 }
1857
Victoria Lease37425c32012-10-16 16:08:48 -07001858 private int getCallerAllowedResolutionLevel() {
1859 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
1860 }
1861
Victoria Lease37425c32012-10-16 16:08:48 -07001862 private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
1863 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Lease4fab68b2012-09-13 13:20:59 -07001864 throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
1865 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001866 }
1867
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001868 @GuardedBy("mLock")
1869 private int getMinimumResolutionLevelForProviderUseLocked(String provider) {
1870 if (GPS_PROVIDER.equals(provider) || PASSIVE_PROVIDER.equals(provider)) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001871 // gps and passive providers require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001872 return RESOLUTION_LEVEL_FINE;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001873 } else if (NETWORK_PROVIDER.equals(provider) || FUSED_PROVIDER.equals(provider)) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001874 // network and fused providers are ok with COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001875 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001876 } else {
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001877 for (LocationProvider lp : mProviders) {
1878 if (!lp.getName().equals(provider)) {
1879 continue;
1880 }
1881
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001882 ProviderProperties properties = lp.getPropertiesLocked();
Laurent Tu941221c2012-10-04 14:21:52 -07001883 if (properties != null) {
1884 if (properties.mRequiresSatellite) {
1885 // provider requiring satellites require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001886 return RESOLUTION_LEVEL_FINE;
Laurent Tu941221c2012-10-04 14:21:52 -07001887 } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
1888 // provider requiring network and or cell require COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001889 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001890 }
1891 }
1892 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001893 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001894
Victoria Lease37425c32012-10-16 16:08:48 -07001895 return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
Victoria Leaseda479c52012-10-15 15:24:16 -07001896 }
1897
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001898 @GuardedBy("mLock")
1899 private void checkResolutionLevelIsSufficientForProviderUseLocked(int allowedResolutionLevel,
Victoria Lease37425c32012-10-16 16:08:48 -07001900 String providerName) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001901 int requiredResolutionLevel = getMinimumResolutionLevelForProviderUseLocked(providerName);
Victoria Lease37425c32012-10-16 16:08:48 -07001902 if (allowedResolutionLevel < requiredResolutionLevel) {
1903 switch (requiredResolutionLevel) {
1904 case RESOLUTION_LEVEL_FINE:
1905 throw new SecurityException("\"" + providerName + "\" location provider " +
1906 "requires ACCESS_FINE_LOCATION permission.");
1907 case RESOLUTION_LEVEL_COARSE:
1908 throw new SecurityException("\"" + providerName + "\" location provider " +
1909 "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
1910 default:
1911 throw new SecurityException("Insufficient permission for \"" + providerName +
1912 "\" location provider.");
Victoria Leaseda479c52012-10-15 15:24:16 -07001913 }
1914 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001915 }
1916
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001917 public static int resolutionLevelToOp(int allowedResolutionLevel) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001918 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
1919 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001920 return AppOpsManager.OP_COARSE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001921 } else {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001922 return AppOpsManager.OP_FINE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001923 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001924 }
1925 return -1;
1926 }
1927
Wei Wangb86334f2018-07-03 16:33:24 -07001928 private static String resolutionLevelToOpStr(int allowedResolutionLevel) {
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001929 switch (allowedResolutionLevel) {
Wei Wangb86334f2018-07-03 16:33:24 -07001930 case RESOLUTION_LEVEL_COARSE:
1931 return AppOpsManager.OPSTR_COARSE_LOCATION;
1932 case RESOLUTION_LEVEL_FINE:
1933 return AppOpsManager.OPSTR_FINE_LOCATION;
1934 case RESOLUTION_LEVEL_NONE:
1935 // The client is not allowed to get any location, so both FINE and COARSE ops will
1936 // be denied. Pick the most restrictive one to be safe.
1937 return AppOpsManager.OPSTR_FINE_LOCATION;
1938 default:
1939 // Use the most restrictive ops if not sure.
1940 return AppOpsManager.OPSTR_FINE_LOCATION;
1941 }
1942 }
1943
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001944 private boolean reportLocationAccessNoThrow(
David Christieb870dbf2015-06-22 12:42:53 -07001945 int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001946 int op = resolutionLevelToOp(allowedResolutionLevel);
1947 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001948 if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1949 return false;
1950 }
1951 }
David Christieb870dbf2015-06-22 12:42:53 -07001952
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001953 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001954 }
1955
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001956 private boolean checkLocationAccess(int pid, int uid, String packageName,
1957 int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001958 int op = resolutionLevelToOp(allowedResolutionLevel);
1959 if (op >= 0) {
Wei Wang16276a42019-02-04 18:23:31 -08001960 if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001961 return false;
1962 }
1963 }
David Christieb870dbf2015-06-22 12:42:53 -07001964
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001965 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001966 }
1967
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001968 /**
Maggie91e630c2018-01-24 17:31:46 -08001969 * Returns all providers by name, including passive and the ones that are not permitted to
1970 * be accessed by the calling activity or are currently disabled, but excluding fused.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001971 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001972 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001973 public List<String> getAllProviders() {
Soonil Nagarkar68257742019-01-09 19:42:34 +00001974 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001975 ArrayList<String> providers = new ArrayList<>(mProviders.size());
Soonil Nagarkar68257742019-01-09 19:42:34 +00001976 for (LocationProvider provider : mProviders) {
1977 String name = provider.getName();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001978 if (FUSED_PROVIDER.equals(name)) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00001979 continue;
1980 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001981 providers.add(name);
Maggie91e630c2018-01-24 17:31:46 -08001982 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001983 return providers;
Maggie91e630c2018-01-24 17:31:46 -08001984 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001985 }
1986
Mike Lockwood03ca2162010-04-01 08:10:09 -07001987 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001988 * Return all providers by name, that match criteria and are optionally
1989 * enabled.
1990 * Can return passive provider, but never returns fused provider.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001991 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001992 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001993 public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
Victoria Lease37425c32012-10-16 16:08:48 -07001994 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001995 synchronized (mLock) {
1996 ArrayList<String> providers = new ArrayList<>(mProviders.size());
1997 for (LocationProvider provider : mProviders) {
1998 String name = provider.getName();
1999 if (FUSED_PROVIDER.equals(name)) {
2000 continue;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002001 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002002 if (allowedResolutionLevel < getMinimumResolutionLevelForProviderUseLocked(name)) {
2003 continue;
2004 }
2005 if (enabledOnly && !provider.isUseableLocked()) {
2006 continue;
2007 }
2008 if (criteria != null
2009 && !android.location.LocationProvider.propertiesMeetCriteria(
2010 name, provider.getPropertiesLocked(), criteria)) {
2011 continue;
2012 }
2013 providers.add(name);
Mike Lockwood03ca2162010-04-01 08:10:09 -07002014 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002015 return providers;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002016 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07002017 }
2018
2019 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002020 * Return the name of the best provider given a Criteria object.
2021 * This method has been deprecated from the public API,
Victoria Lease8dbb6342012-09-21 16:55:53 -07002022 * and the whole LocationProvider (including #meetsCriteria)
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002023 * has been deprecated as well. So this method now uses
2024 * some simplified logic.
Mike Lockwood03ca2162010-04-01 08:10:09 -07002025 */
Nick Pellye0fd6932012-07-11 10:26:13 -07002026 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002027 public String getBestProvider(Criteria criteria, boolean enabledOnly) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002028 List<String> providers = getProviders(criteria, enabledOnly);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002029 if (providers.isEmpty()) {
2030 providers = getProviders(null, enabledOnly);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002031 }
2032
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002033 if (!providers.isEmpty()) {
2034 if (providers.contains(GPS_PROVIDER)) {
2035 return GPS_PROVIDER;
2036 } else if (providers.contains(NETWORK_PROVIDER)) {
2037 return NETWORK_PROVIDER;
2038 } else {
2039 return providers.get(0);
2040 }
2041 }
2042
Mike Lockwood03ca2162010-04-01 08:10:09 -07002043 return null;
2044 }
2045
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002046 @GuardedBy("mLock")
2047 private void updateProviderUseableLocked(LocationProvider provider) {
2048 boolean useable = provider.isUseableLocked();
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002049
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002050 ArrayList<Receiver> deadReceivers = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07002051
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002052 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002053 if (records != null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002054 for (UpdateRecord record : records) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002055 if (!isCurrentProfileLocked(
Anil Admal08b96122019-01-30 16:55:05 -08002056 UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002057 continue;
2058 }
2059
Kweku Adams5e0052b2019-02-22 15:17:52 -08002060 // requests that ignore location settings will never provide notifications
Soonil Nagarkar397ad582019-01-23 22:47:57 -08002061 if (isSettingsExemptLocked(record)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002062 continue;
2063 }
2064
2065 // Sends a notification message to the receiver
2066 if (!record.mReceiver.callProviderEnabledLocked(provider.getName(), useable)) {
2067 if (deadReceivers == null) {
2068 deadReceivers = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002069 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002070 deadReceivers.add(record.mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002072 }
2073 }
2074
2075 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002076 for (int i = deadReceivers.size() - 1; i >= 0; i--) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002077 removeUpdatesLocked(deadReceivers.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002078 }
2079 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002080
Soonil Nagarkar68257742019-01-09 19:42:34 +00002081 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002082 }
2083
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002084 @GuardedBy("mLock")
2085 private void applyRequirementsLocked(String providerName) {
2086 LocationProvider provider = getLocationProviderLocked(providerName);
2087 if (provider != null) {
2088 applyRequirementsLocked(provider);
2089 }
2090 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002091
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002092 @GuardedBy("mLock")
2093 private void applyRequirementsLocked(LocationProvider provider) {
2094 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider.getName());
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002095 WorkSource worksource = new WorkSource();
2096 ProviderRequest providerRequest = new ProviderRequest();
2097
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002098 if (records != null && !records.isEmpty()) {
Kweku Adams5e0052b2019-02-22 15:17:52 -08002099 long backgroundThrottleInterval;
2100
2101 long identity = Binder.clearCallingIdentity();
2102 try {
2103 backgroundThrottleInterval = Settings.Global.getLong(
2104 mContext.getContentResolver(),
2105 Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
2106 DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
2107 } finally {
2108 Binder.restoreCallingIdentity(identity);
2109 }
2110
2111 final boolean isForegroundOnlyMode =
Kweku Adams4fb074e2019-02-01 16:03:27 -08002112 mBatterySaverMode == PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
2113 final boolean shouldThrottleRequests =
2114 mBatterySaverMode
2115 == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF
2116 && !mPowerManager.isInteractive();
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002117 // initialize the low power mode to true and set to false if any of the records requires
2118 providerRequest.lowPowerMode = true;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002119 for (UpdateRecord record : records) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002120 if (!isCurrentProfileLocked(
Anil Admal08b96122019-01-30 16:55:05 -08002121 UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002122 continue;
2123 }
2124 if (!checkLocationAccess(
Anil Admal08b96122019-01-30 16:55:05 -08002125 record.mReceiver.mCallerIdentity.mPid,
2126 record.mReceiver.mCallerIdentity.mUid,
2127 record.mReceiver.mCallerIdentity.mPackageName,
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002128 record.mReceiver.mAllowedResolutionLevel)) {
2129 continue;
2130 }
Kweku Adams4fb074e2019-02-01 16:03:27 -08002131 final boolean isBatterySaverDisablingLocation = shouldThrottleRequests
2132 || (isForegroundOnlyMode && !record.mIsForegroundUid);
Kweku Adams5e0052b2019-02-22 15:17:52 -08002133 if (!provider.isUseableLocked() || isBatterySaverDisablingLocation) {
Soonil Nagarkar35c3b912019-01-31 10:31:24 -08002134 if (isSettingsExemptLocked(record)) {
Soonil Nagarkar509580f2019-02-06 15:57:26 -08002135 providerRequest.locationSettingsIgnored = true;
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08002136 providerRequest.lowPowerMode = false;
Soonil Nagarkar35c3b912019-01-31 10:31:24 -08002137 } else {
2138 continue;
2139 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002140 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002141
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002142 LocationRequest locationRequest = record.mRealRequest;
2143 long interval = locationRequest.getInterval();
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002144
Soonil Nagarkar509580f2019-02-06 15:57:26 -08002145
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08002146 // if we're forcing location, don't apply any throttling
Soonil Nagarkar509580f2019-02-06 15:57:26 -08002147 if (!providerRequest.locationSettingsIgnored && !isThrottlingExemptLocked(
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08002148 record.mReceiver.mCallerIdentity)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002149 if (!record.mIsForegroundUid) {
2150 interval = Math.max(interval, backgroundThrottleInterval);
Victoria Leaseb711d572012-10-02 13:14:11 -07002151 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002152 if (interval != locationRequest.getInterval()) {
2153 locationRequest = new LocationRequest(locationRequest);
2154 locationRequest.setInterval(interval);
2155 }
2156 }
2157
2158 record.mRequest = locationRequest;
2159 providerRequest.locationRequests.add(locationRequest);
2160 if (!locationRequest.isLowPowerMode()) {
2161 providerRequest.lowPowerMode = false;
2162 }
2163 if (interval < providerRequest.interval) {
2164 providerRequest.reportLocation = true;
2165 providerRequest.interval = interval;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07002166 }
2167 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002168
2169 if (providerRequest.reportLocation) {
2170 // calculate who to blame for power
2171 // This is somewhat arbitrary. We pick a threshold interval
2172 // that is slightly higher that the minimum interval, and
2173 // spread the blame across all applications with a request
2174 // under that threshold.
2175 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
2176 for (UpdateRecord record : records) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002177 if (isCurrentProfileLocked(
Anil Admal08b96122019-01-30 16:55:05 -08002178 UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002179 LocationRequest locationRequest = record.mRequest;
Svet Ganove998c732016-06-10 00:12:38 -07002180
2181 // Don't assign battery blame for update records whose
2182 // client has no permission to receive location data.
2183 if (!providerRequest.locationRequests.contains(locationRequest)) {
2184 continue;
2185 }
2186
Victoria Leaseb711d572012-10-02 13:14:11 -07002187 if (locationRequest.getInterval() <= thresholdInterval) {
David Christiee55c9682013-08-22 10:10:34 -07002188 if (record.mReceiver.mWorkSource != null
Narayan Kamath32684dd2018-01-08 17:32:51 +00002189 && isValidWorkSource(record.mReceiver.mWorkSource)) {
David Christie82edc9b2013-07-19 11:31:42 -07002190 worksource.add(record.mReceiver.mWorkSource);
2191 } else {
Narayan Kamath32684dd2018-01-08 17:32:51 +00002192 // Assign blame to caller if there's no WorkSource associated with
2193 // the request or if it's invalid.
David Christie82edc9b2013-07-19 11:31:42 -07002194 worksource.add(
Anil Admal08b96122019-01-30 16:55:05 -08002195 record.mReceiver.mCallerIdentity.mUid,
2196 record.mReceiver.mCallerIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07002197 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002198 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002199 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07002200 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002201 }
2202 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002203
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002204 provider.setRequestLocked(providerRequest, worksource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002205 }
2206
Narayan Kamath32684dd2018-01-08 17:32:51 +00002207 /**
2208 * Whether a given {@code WorkSource} associated with a Location request is valid.
2209 */
2210 private static boolean isValidWorkSource(WorkSource workSource) {
2211 if (workSource.size() > 0) {
2212 // If the WorkSource has one or more non-chained UIDs, make sure they're accompanied
2213 // by tags.
2214 return workSource.getName(0) != null;
2215 } else {
2216 // For now, make sure callers have supplied an attribution tag for use with
2217 // AppOpsManager. This might be relaxed in the future.
2218 final ArrayList<WorkChain> workChains = workSource.getWorkChains();
2219 return workChains != null && !workChains.isEmpty() &&
2220 workChains.get(0).getAttributionTag() != null;
2221 }
2222 }
2223
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002224 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002225 public String[] getBackgroundThrottlingWhitelist() {
2226 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002227 return mBackgroundThrottlePackageWhitelist.toArray(new String[0]);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002228 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002229 }
2230
Soonil Nagarkar5140e4f2019-02-14 17:21:33 -08002231 @Override
2232 public String[] getIgnoreSettingsWhitelist() {
2233 synchronized (mLock) {
2234 return mIgnoreSettingsPackageWhitelist.toArray(new String[0]);
2235 }
2236 }
2237
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002238 @GuardedBy("mLock")
Anil Admal08b96122019-01-30 16:55:05 -08002239 private boolean isThrottlingExemptLocked(CallerIdentity callerIdentity) {
2240 if (callerIdentity.mUid == Process.SYSTEM_UID) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08002241 return true;
2242 }
2243
Anil Admal08b96122019-01-30 16:55:05 -08002244 if (mBackgroundThrottlePackageWhitelist.contains(callerIdentity.mPackageName)) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08002245 return true;
2246 }
2247
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08002248 return isProviderPackage(callerIdentity.mPackageName);
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08002249
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002250 }
2251
Soonil Nagarkar397ad582019-01-23 22:47:57 -08002252 @GuardedBy("mLock")
2253 private boolean isSettingsExemptLocked(UpdateRecord record) {
2254 if (!record.mRealRequest.isLocationSettingsIgnored()) {
2255 return false;
2256 }
2257
Anil Admal08b96122019-01-30 16:55:05 -08002258 if (mIgnoreSettingsPackageWhitelist.contains(
2259 record.mReceiver.mCallerIdentity.mPackageName)) {
Soonil Nagarkar397ad582019-01-23 22:47:57 -08002260 return true;
2261 }
2262
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08002263 return isProviderPackage(record.mReceiver.mCallerIdentity.mPackageName);
Soonil Nagarkar397ad582019-01-23 22:47:57 -08002264
Soonil Nagarkar397ad582019-01-23 22:47:57 -08002265 }
2266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002267 private class UpdateRecord {
2268 final String mProvider;
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002269 private final LocationRequest mRealRequest; // original request from client
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002270 LocationRequest mRequest; // possibly throttled version of the request
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002271 private final Receiver mReceiver;
2272 private boolean mIsForegroundUid;
2273 private Location mLastFixBroadcast;
2274 private long mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002275
2276 /**
2277 * Note: must be constructed with lock held.
2278 */
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002279 private UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002280 mProvider = provider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002281 mRealRequest = request;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002282 mRequest = request;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002283 mReceiver = receiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002284 mIsForegroundUid = isImportanceForeground(
Anil Admal08b96122019-01-30 16:55:05 -08002285 mActivityManager.getPackageImportance(mReceiver.mCallerIdentity.mPackageName));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002286
2287 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
2288 if (records == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002289 records = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002290 mRecordsByProvider.put(provider, records);
2291 }
2292 if (!records.contains(this)) {
2293 records.add(this);
2294 }
David Christie2ff96af2014-01-30 16:09:37 -08002295
2296 // Update statistics for historical location requests by package/provider
2297 mRequestStatistics.startRequesting(
Anil Admal08b96122019-01-30 16:55:05 -08002298 mReceiver.mCallerIdentity.mPackageName, provider, request.getInterval(),
Wyatt Rileyf7075e02018-04-12 17:54:26 -07002299 mIsForegroundUid);
2300 }
2301
2302 /**
2303 * Method to be called when record changes foreground/background
2304 */
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002305 private void updateForeground(boolean isForeground) {
Wyatt Rileyf7075e02018-04-12 17:54:26 -07002306 mIsForegroundUid = isForeground;
2307 mRequestStatistics.updateForeground(
Anil Admal08b96122019-01-30 16:55:05 -08002308 mReceiver.mCallerIdentity.mPackageName, mProvider, isForeground);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 }
2310
2311 /**
David Christie2ff96af2014-01-30 16:09:37 -08002312 * Method to be called when a record will no longer be used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002313 */
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002314 private void disposeLocked(boolean removeReceiver) {
Anil Admal08b96122019-01-30 16:55:05 -08002315 mRequestStatistics.stopRequesting(mReceiver.mCallerIdentity.mPackageName, mProvider);
David Christie2ff96af2014-01-30 16:09:37 -08002316
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002317 // remove from mRecordsByProvider
2318 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
2319 if (globalRecords != null) {
2320 globalRecords.remove(this);
2321 }
2322
2323 if (!removeReceiver) return; // the caller will handle the rest
2324
2325 // remove from Receiver#mUpdateRecords
2326 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002327 receiverRecords.remove(this.mProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002328
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002329 // and also remove the Receiver if it has no more update records
2330 if (receiverRecords.size() == 0) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002331 removeUpdatesLocked(mReceiver);
Mike Lockwood3a76fd62009-09-01 07:26:56 -04002332 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002333 }
2334
2335 @Override
2336 public String toString() {
Anil Admal08b96122019-01-30 16:55:05 -08002337 return "UpdateRecord[" + mProvider + " " + mReceiver.mCallerIdentity.mPackageName
2338 + "(" + mReceiver.mCallerIdentity.mUid + (mIsForegroundUid ? " foreground"
gomo48f1a642017-11-10 20:35:46 -08002339 : " background")
Wyatt Riley19adc022018-05-22 13:30:51 -07002340 + ")" + " " + mRealRequest + " "
2341 + mReceiver.mWorkSource + "]";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002342 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002343 }
2344
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002345 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00002346 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -07002347 String packageName, WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002348 IBinder binder = listener.asBinder();
2349 Receiver receiver = mReceivers.get(binder);
2350 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07002351 receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
2352 hideFromAppOps);
Anil Admal98d49b72019-02-06 15:26:33 -08002353 if (!linkToListenerDeathNotificationLocked(receiver.getListener().asBinder(),
2354 receiver)) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002355 return null;
2356 }
Wen Jingcb3ab222014-03-27 13:42:59 +08002357 mReceivers.put(binder, receiver);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002358 }
2359 return receiver;
2360 }
2361
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002362 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00002363 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
David Christie40e57822013-07-30 11:36:48 -07002364 WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002365 Receiver receiver = mReceivers.get(intent);
2366 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07002367 receiver = new Receiver(null, intent, pid, uid, packageName, workSource,
2368 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002369 mReceivers.put(intent, receiver);
2370 }
2371 return receiver;
2372 }
2373
Victoria Lease37425c32012-10-16 16:08:48 -07002374 /**
2375 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
2376 * and consistency requirements.
2377 *
2378 * @param request the LocationRequest from which to create a sanitized version
Victoria Lease37425c32012-10-16 16:08:48 -07002379 * @return a version of request that meets the given resolution and consistency requirements
2380 * @hide
2381 */
gomo48f1a642017-11-10 20:35:46 -08002382 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel,
2383 boolean callerHasLocationHardwarePermission) {
Victoria Lease37425c32012-10-16 16:08:48 -07002384 LocationRequest sanitizedRequest = new LocationRequest(request);
gomo48f1a642017-11-10 20:35:46 -08002385 if (!callerHasLocationHardwarePermission) {
2386 // allow setting low power mode only for callers with location hardware permission
2387 sanitizedRequest.setLowPowerMode(false);
2388 }
Victoria Lease37425c32012-10-16 16:08:48 -07002389 if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
2390 switch (sanitizedRequest.getQuality()) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002391 case LocationRequest.ACCURACY_FINE:
Victoria Lease37425c32012-10-16 16:08:48 -07002392 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
Victoria Lease09016ab2012-09-16 12:33:15 -07002393 break;
2394 case LocationRequest.POWER_HIGH:
Victoria Lease37425c32012-10-16 16:08:48 -07002395 sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
Victoria Lease09016ab2012-09-16 12:33:15 -07002396 break;
2397 }
2398 // throttle
Victoria Lease37425c32012-10-16 16:08:48 -07002399 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
2400 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07002401 }
Victoria Lease37425c32012-10-16 16:08:48 -07002402 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
2403 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07002404 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07002405 }
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002406 // make getFastestInterval() the minimum of interval and fastest interval
Victoria Lease37425c32012-10-16 16:08:48 -07002407 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
Soonil Nagarkar397ad582019-01-23 22:47:57 -08002408 sanitizedRequest.setFastestInterval(request.getInterval());
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002409 }
Victoria Lease37425c32012-10-16 16:08:48 -07002410 return sanitizedRequest;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002411 }
2412
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002413 private void checkPackageName(String packageName) {
Nick Pellye0fd6932012-07-11 10:26:13 -07002414 if (packageName == null) {
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002415 throw new SecurityException("invalid package name: " + null);
Nick Pellye0fd6932012-07-11 10:26:13 -07002416 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002417 int uid = Binder.getCallingUid();
Nick Pellye0fd6932012-07-11 10:26:13 -07002418 String[] packages = mPackageManager.getPackagesForUid(uid);
2419 if (packages == null) {
2420 throw new SecurityException("invalid UID " + uid);
2421 }
2422 for (String pkg : packages) {
2423 if (packageName.equals(pkg)) return;
2424 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002425 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002426 }
2427
Nick Pellye0fd6932012-07-11 10:26:13 -07002428 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002429 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
Soonil Nagarkar68257742019-01-09 19:42:34 +00002430 PendingIntent intent, String packageName) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002431 synchronized (mLock) {
2432 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2433 checkPackageName(packageName);
2434 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2435 checkResolutionLevelIsSufficientForProviderUseLocked(allowedResolutionLevel,
2436 request.getProvider());
2437 WorkSource workSource = request.getWorkSource();
2438 if (workSource != null && !workSource.isEmpty()) {
2439 mContext.enforceCallingOrSelfPermission(
2440 Manifest.permission.UPDATE_DEVICE_STATS, null);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002441 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002442 boolean hideFromAppOps = request.getHideFromAppOps();
2443 if (hideFromAppOps) {
2444 mContext.enforceCallingOrSelfPermission(
2445 Manifest.permission.UPDATE_APP_OPS_STATS, null);
2446 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002447 if (request.isLocationSettingsIgnored()) {
2448 mContext.enforceCallingOrSelfPermission(
2449 Manifest.permission.WRITE_SECURE_SETTINGS, null);
2450 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002451 boolean callerHasLocationHardwarePermission =
2452 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
2453 == PERMISSION_GRANTED;
2454 LocationRequest sanitizedRequest = createSanitizedRequest(request,
2455 allowedResolutionLevel,
2456 callerHasLocationHardwarePermission);
2457
2458 final int pid = Binder.getCallingPid();
2459 final int uid = Binder.getCallingUid();
2460
2461 long identity = Binder.clearCallingIdentity();
2462 try {
2463
2464 // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2465 // a location.
2466 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
2467
2468 if (intent == null && listener == null) {
2469 throw new IllegalArgumentException("need either listener or intent");
2470 } else if (intent != null && listener != null) {
2471 throw new IllegalArgumentException(
2472 "cannot register both listener and intent");
2473 }
2474
2475 Receiver receiver;
2476 if (intent != null) {
2477 receiver = getReceiverLocked(intent, pid, uid, packageName, workSource,
2478 hideFromAppOps);
2479 } else {
2480 receiver = getReceiverLocked(listener, pid, uid, packageName, workSource,
2481 hideFromAppOps);
2482 }
2483 requestLocationUpdatesLocked(sanitizedRequest, receiver, uid, packageName);
2484 } finally {
2485 Binder.restoreCallingIdentity(identity);
2486 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002487 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002488 }
2489
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002490 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00002491 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002492 int uid, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002493 // Figure out the provider. Either its explicitly request (legacy use cases), or
2494 // use the fused provider
2495 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2496 String name = request.getProvider();
Victoria Lease09016ab2012-09-16 12:33:15 -07002497 if (name == null) {
2498 throw new IllegalArgumentException("provider name must not be null");
2499 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -07002500
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002501 LocationProvider provider = getLocationProviderLocked(name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002502 if (provider == null) {
Victoria Leaseb30f3832013-10-13 12:15:40 -07002503 throw new IllegalArgumentException("provider doesn't exist: " + name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002504 }
2505
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002506 UpdateRecord record = new UpdateRecord(name, request, receiver);
gomo48f1a642017-11-10 20:35:46 -08002507 if (D) {
2508 Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
2509 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
2510 + (record.mIsForegroundUid ? "foreground" : "background")
Anil Admal08b96122019-01-30 16:55:05 -08002511 + (isThrottlingExemptLocked(receiver.mCallerIdentity)
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002512 ? " [whitelisted]" : "") + ")");
gomo48f1a642017-11-10 20:35:46 -08002513 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002514
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002515 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
2516 if (oldRecord != null) {
2517 oldRecord.disposeLocked(false);
2518 }
2519
Soonil Nagarkar397ad582019-01-23 22:47:57 -08002520 if (!provider.isUseableLocked() && !isSettingsExemptLocked(record)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002521 // Notify the listener that updates are currently disabled - but only if the request
2522 // does not ignore location settings
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002523 receiver.callProviderEnabledLocked(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002525
2526 applyRequirementsLocked(name);
2527
David Christie0b837452013-07-29 16:02:13 -07002528 // Update the monitoring here just in case multiple location requests were added to the
2529 // same receiver (this request may be high power and the initial might not have been).
2530 receiver.updateMonitoring(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002531 }
2532
Nick Pellye0fd6932012-07-11 10:26:13 -07002533 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002534 public void removeUpdates(ILocationListener listener, PendingIntent intent,
Soonil Nagarkar68257742019-01-09 19:42:34 +00002535 String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002536 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002537
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002538 int pid = Binder.getCallingPid();
2539 int uid = Binder.getCallingUid();
2540
2541 if (intent == null && listener == null) {
2542 throw new IllegalArgumentException("need either listener or intent");
2543 } else if (intent != null && listener != null) {
2544 throw new IllegalArgumentException("cannot register both listener and intent");
2545 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002546
Soonil Nagarkar68257742019-01-09 19:42:34 +00002547 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002548 Receiver receiver;
2549 if (intent != null) {
2550 receiver = getReceiverLocked(intent, pid, uid, packageName, null, false);
2551 } else {
2552 receiver = getReceiverLocked(listener, pid, uid, packageName, null, false);
2553 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002554
Soonil Nagarkar68257742019-01-09 19:42:34 +00002555 long identity = Binder.clearCallingIdentity();
2556 try {
2557 removeUpdatesLocked(receiver);
2558 } finally {
2559 Binder.restoreCallingIdentity(identity);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002560 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002561 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002562 }
2563
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002564 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00002565 private void removeUpdatesLocked(Receiver receiver) {
Dianne Hackborn7ff30112012-11-08 11:12:09 -08002566 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002567
2568 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
Anil Admal98d49b72019-02-06 15:26:33 -08002569 unlinkFromListenerDeathNotificationLocked(receiver.getListener().asBinder(),
2570 receiver);
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08002571 receiver.clearPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002572 }
2573
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07002574 receiver.updateMonitoring(false);
2575
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002576 // Record which providers were associated with this listener
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002577 HashSet<String> providers = new HashSet<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002578 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2579 if (oldRecords != null) {
2580 // Call dispose() on the obsolete update records.
2581 for (UpdateRecord record : oldRecords.values()) {
David Christie2ff96af2014-01-30 16:09:37 -08002582 // Update statistics for historical location requests by package/provider
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002583 record.disposeLocked(false);
2584 }
2585 // Accumulate providers
2586 providers.addAll(oldRecords.keySet());
2587 }
2588
2589 // update provider
2590 for (String provider : providers) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002591 applyRequirementsLocked(provider);
2592 }
2593 }
2594
Nick Pellye0fd6932012-07-11 10:26:13 -07002595 @Override
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002596 public Location getLastLocation(LocationRequest r, String packageName) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002597 synchronized (mLock) {
2598 LocationRequest request = r != null ? r : DEFAULT_LOCATION_REQUEST;
2599 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2600 checkPackageName(packageName);
2601 checkResolutionLevelIsSufficientForProviderUseLocked(allowedResolutionLevel,
2602 request.getProvider());
2603 // no need to sanitize this request, as only the provider name is used
Nick Pelly4035f5a2012-08-17 14:43:49 -07002604
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002605 final int pid = Binder.getCallingPid();
2606 final int uid = Binder.getCallingUid();
2607 final long identity = Binder.clearCallingIdentity();
2608 try {
2609 if (mBlacklist.isBlacklisted(packageName)) {
2610 if (D) {
2611 Log.d(TAG, "not returning last loc for blacklisted app: "
2612 + packageName);
2613 }
2614 return null;
gomo48f1a642017-11-10 20:35:46 -08002615 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002616
Soonil Nagarkar68257742019-01-09 19:42:34 +00002617
Soonil Nagarkar68257742019-01-09 19:42:34 +00002618 // Figure out the provider. Either its explicitly request (deprecated API's),
2619 // or use the fused provider
2620 String name = request.getProvider();
2621 if (name == null) name = LocationManager.FUSED_PROVIDER;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002622 LocationProvider provider = getLocationProviderLocked(name);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002623 if (provider == null) return null;
2624
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002625 // only the current user or location providers may get location this way
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08002626 if (!isCurrentProfileLocked(UserHandle.getUserId(uid)) && !isProviderPackage(
2627 packageName)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002628 return null;
2629 }
2630
2631 if (!provider.isUseableLocked()) {
2632 return null;
2633 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002634
2635 Location location;
2636 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2637 // Make sure that an app with coarse permissions can't get frequent location
2638 // updates by calling LocationManager.getLastKnownLocation repeatedly.
2639 location = mLastLocationCoarseInterval.get(name);
2640 } else {
2641 location = mLastLocation.get(name);
2642 }
2643 if (location == null) {
2644 return null;
2645 }
2646
2647 // Don't return stale location to apps with foreground-only location permission.
2648 String op = resolutionLevelToOpStr(allowedResolutionLevel);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002649 long locationAgeMs = SystemClock.elapsedRealtime()
2650 - location.getElapsedRealtimeNanos() / NANOS_PER_MILLI;
2651 if ((locationAgeMs > Settings.Global.getLong(
2652 mContext.getContentResolver(),
2653 Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
2654 DEFAULT_LAST_LOCATION_MAX_AGE_MS))
Soonil Nagarkar68257742019-01-09 19:42:34 +00002655 && (mAppOps.unsafeCheckOp(op, uid, packageName)
2656 == AppOpsManager.MODE_FOREGROUND)) {
2657 return null;
2658 }
2659
Wei Wang16276a42019-02-04 18:23:31 -08002660 Location lastLocation = null;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002661 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2662 Location noGPSLocation = location.getExtraLocation(
2663 Location.EXTRA_NO_GPS_LOCATION);
2664 if (noGPSLocation != null) {
Wei Wang16276a42019-02-04 18:23:31 -08002665 lastLocation = new Location(mLocationFudger.getOrCreate(noGPSLocation));
Soonil Nagarkar68257742019-01-09 19:42:34 +00002666 }
2667 } else {
Wei Wang16276a42019-02-04 18:23:31 -08002668 lastLocation = new Location(location);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002669 }
Wei Wang16276a42019-02-04 18:23:31 -08002670 // Don't report location access if there is no last location to deliver.
2671 if (lastLocation != null) {
2672 if (!reportLocationAccessNoThrow(
2673 pid, uid, packageName, allowedResolutionLevel)) {
2674 if (D) {
2675 Log.d(TAG, "not returning last loc for no op app: " + packageName);
2676 }
2677 lastLocation = null;
2678 }
2679 }
2680 return lastLocation;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002681 } finally {
2682 Binder.restoreCallingIdentity(identity);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002683 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002684 }
2685 }
2686
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002687 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002688 public boolean injectLocation(Location location) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002689 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
2690 "Location Hardware permission not granted to inject location");
2691 mContext.enforceCallingPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
2692 "Access Fine Location permission not granted to inject Location");
2693
2694 if (location == null) {
2695 if (D) {
2696 Log.d(TAG, "injectLocation(): called with null location");
2697 }
2698 return false;
2699 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002700
Soonil Nagarkar68257742019-01-09 19:42:34 +00002701 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002702 LocationProvider provider = getLocationProviderLocked(location.getProvider());
2703 if (provider == null || !provider.isUseableLocked()) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002704 return false;
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002705 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002706
2707 // NOTE: If last location is already available, location is not injected. If
2708 // provider's normal source (like a GPS chipset) have already provided an output
2709 // there is no need to inject this location.
2710 if (mLastLocation.get(provider.getName()) != null) {
2711 return false;
2712 }
2713
2714 updateLastLocationLocked(location, provider.getName());
2715 return true;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002716 }
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002717 }
2718
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002719 @Override
2720 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
2721 String packageName) {
2722 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002723 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2724 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002725 if (intent == null) {
2726 throw new IllegalArgumentException("invalid pending intent: " + null);
Victoria Lease56e675b2012-11-05 19:25:06 -08002727 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002728 checkPackageName(packageName);
2729 synchronized (mLock) {
2730 checkResolutionLevelIsSufficientForProviderUseLocked(allowedResolutionLevel,
2731 request.getProvider());
Soonil Nagarkar8c4655e2019-02-27 13:00:56 -08002732 }
2733 // Require that caller can manage given document
2734 boolean callerHasLocationHardwarePermission =
2735 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
2736 == PERMISSION_GRANTED;
2737 LocationRequest sanitizedRequest = createSanitizedRequest(request,
2738 allowedResolutionLevel,
2739 callerHasLocationHardwarePermission);
2740
2741 if (D) {
2742 Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
2743 }
2744
2745 // geo-fence manager uses the public location API, need to clear identity
2746 int uid = Binder.getCallingUid();
2747 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
2748 // temporary measure until geofences work for secondary users
2749 Log.w(TAG, "proximity alerts are currently available only to the primary user");
2750 return;
2751 }
2752 long identity = Binder.clearCallingIdentity();
2753 try {
2754 mGeofenceManager.addFence(sanitizedRequest, geofence, intent,
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002755 allowedResolutionLevel,
Soonil Nagarkar8c4655e2019-02-27 13:00:56 -08002756 uid, packageName);
2757 } finally {
2758 Binder.restoreCallingIdentity(identity);
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002759 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002760 }
2761
2762 @Override
2763 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002764 if (intent == null) {
2765 throw new IllegalArgumentException("invalid pending intent: " + null);
2766 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002767 checkPackageName(packageName);
2768
2769 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2770
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002771 // geo-fence manager uses the public location API, need to clear identity
2772 long identity = Binder.clearCallingIdentity();
2773 try {
2774 mGeofenceManager.removeFence(geofence, intent);
2775 } finally {
2776 Binder.restoreCallingIdentity(identity);
2777 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002778 }
2779
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002780 @Override
Anil Admal98d49b72019-02-06 15:26:33 -08002781 public boolean registerGnssStatusCallback(IGnssStatusListener listener, String packageName) {
Anil Admal52686f82019-02-13 19:04:10 -08002782 return addGnssDataListener(listener, packageName, "GnssStatusListener",
2783 mGnssStatusProvider, mGnssStatusListeners,
2784 this::unregisterGnssStatusCallback);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002785 }
2786
Nick Pellye0fd6932012-07-11 10:26:13 -07002787 @Override
Anil Admal98d49b72019-02-06 15:26:33 -08002788 public void unregisterGnssStatusCallback(IGnssStatusListener listener) {
Anil Admal52686f82019-02-13 19:04:10 -08002789 removeGnssDataListener(listener, mGnssStatusProvider, mGnssStatusListeners);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002790 }
2791
Nick Pellye0fd6932012-07-11 10:26:13 -07002792 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002793 public boolean addGnssMeasurementsListener(
Soonil Nagarkar68257742019-01-09 19:42:34 +00002794 IGnssMeasurementsListener listener, String packageName) {
Anil Admal52686f82019-02-13 19:04:10 -08002795 return addGnssDataListener(listener, packageName, "GnssMeasurementsListener",
2796 mGnssMeasurementsProvider, mGnssMeasurementsListeners,
2797 this::removeGnssMeasurementsListener);
2798 }
2799
2800 @Override
2801 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
2802 removeGnssDataListener(listener, mGnssMeasurementsProvider, mGnssMeasurementsListeners);
2803 }
2804
2805 private abstract static class LinkedListenerBase implements IBinder.DeathRecipient {
2806 protected final CallerIdentity mCallerIdentity;
2807 protected final String mListenerName;
2808
2809 private LinkedListenerBase(@NonNull CallerIdentity callerIdentity,
2810 @NonNull String listenerName) {
2811 mCallerIdentity = callerIdentity;
2812 mListenerName = listenerName;
2813 }
2814 }
2815
2816 private static class LinkedListener<TListener> extends LinkedListenerBase {
2817 private final TListener mListener;
2818 private final Consumer<TListener> mBinderDeathCallback;
2819
2820 private LinkedListener(@NonNull TListener listener, String listenerName,
2821 @NonNull CallerIdentity callerIdentity,
2822 @NonNull Consumer<TListener> binderDeathCallback) {
2823 super(callerIdentity, listenerName);
2824 mListener = listener;
2825 mBinderDeathCallback = binderDeathCallback;
2826 }
2827
2828 @Override
2829 public void binderDied() {
2830 if (D) Log.d(TAG, "Remote " + mListenerName + " died.");
2831 mBinderDeathCallback.accept(mListener);
2832 }
2833 }
2834
2835 private <TListener extends IInterface> boolean addGnssDataListener(
2836 TListener listener, String packageName, String listenerName,
2837 RemoteListenerHelper<TListener> gnssDataProvider,
2838 ArrayMap<IBinder, LinkedListener<TListener>> gnssDataListeners,
2839 Consumer<TListener> binderDeathCallback) {
2840 if (!hasGnssPermissions(packageName) || gnssDataProvider == null) {
destradaaea8a8a62014-06-23 18:19:03 -07002841 return false;
2842 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002843
Anil Admal98d49b72019-02-06 15:26:33 -08002844 CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(),
2845 Binder.getCallingPid(), packageName);
Anil Admal52686f82019-02-13 19:04:10 -08002846 LinkedListener<TListener> linkedListener = new LinkedListener<>(listener,
2847 listenerName, callerIdentity, binderDeathCallback);
Anil Admal98d49b72019-02-06 15:26:33 -08002848 IBinder binder = listener.asBinder();
Soonil Nagarkar68257742019-01-09 19:42:34 +00002849 synchronized (mLock) {
Anil Admal98d49b72019-02-06 15:26:33 -08002850 if (!linkToListenerDeathNotificationLocked(binder, linkedListener)) {
2851 return false;
2852 }
2853
Anil Admal52686f82019-02-13 19:04:10 -08002854 gnssDataListeners.put(binder, linkedListener);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002855 long identity = Binder.clearCallingIdentity();
2856 try {
2857 if (isThrottlingExemptLocked(callerIdentity)
2858 || isImportanceForeground(
gomo48f1a642017-11-10 20:35:46 -08002859 mActivityManager.getPackageImportance(packageName))) {
Anil Admal52686f82019-02-13 19:04:10 -08002860 gnssDataProvider.addListener(listener, callerIdentity);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002861 }
Anil Admal98d49b72019-02-06 15:26:33 -08002862 return true;
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002863 } finally {
2864 Binder.restoreCallingIdentity(identity);
2865 }
Anil Admal98d49b72019-02-06 15:26:33 -08002866 }
2867 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002868
Anil Admal52686f82019-02-13 19:04:10 -08002869 private <TListener extends IInterface> void removeGnssDataListener(
2870 TListener listener, RemoteListenerHelper<TListener> gnssDataProvider,
2871 ArrayMap<IBinder, LinkedListener<TListener>> gnssDataListeners) {
2872 if (gnssDataProvider == null) {
Anil Admal98d49b72019-02-06 15:26:33 -08002873 return;
2874 }
2875
2876 IBinder binder = listener.asBinder();
2877 synchronized (mLock) {
Anil Admal52686f82019-02-13 19:04:10 -08002878 LinkedListener<TListener> linkedListener = gnssDataListeners.remove(binder);
Anil Admal98d49b72019-02-06 15:26:33 -08002879 if (linkedListener == null) {
2880 return;
2881 }
2882 unlinkFromListenerDeathNotificationLocked(binder, linkedListener);
Anil Admal52686f82019-02-13 19:04:10 -08002883 gnssDataProvider.removeListener(listener);
Anil Admal98d49b72019-02-06 15:26:33 -08002884 }
2885 }
2886
Anil Admal98d49b72019-02-06 15:26:33 -08002887 private boolean linkToListenerDeathNotificationLocked(IBinder binder,
2888 LinkedListenerBase linkedListener) {
2889 try {
2890 binder.linkToDeath(linkedListener, 0 /* flags */);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002891 return true;
Anil Admal98d49b72019-02-06 15:26:33 -08002892 } catch (RemoteException e) {
2893 // if the remote process registering the listener is already dead, just swallow the
2894 // exception and return
Anil Admal316f9482019-02-12 18:57:18 -08002895 Log.w(TAG, "Could not link " + linkedListener.mListenerName + " death callback.", e);
Anil Admal98d49b72019-02-06 15:26:33 -08002896 return false;
2897 }
2898 }
2899
2900 private boolean unlinkFromListenerDeathNotificationLocked(IBinder binder,
2901 LinkedListenerBase linkedListener) {
2902 try {
2903 binder.unlinkToDeath(linkedListener, 0 /* flags */);
2904 return true;
2905 } catch (NoSuchElementException e) {
2906 // if the death callback isn't connected (it should be...), log error,
2907 // swallow the exception and return
Anil Admal316f9482019-02-12 18:57:18 -08002908 Log.w(TAG, "Could not unlink " + linkedListener.mListenerName + " death callback.", e);
Anil Admal98d49b72019-02-06 15:26:33 -08002909 return false;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002910 }
destradaaea8a8a62014-06-23 18:19:03 -07002911 }
2912
2913 @Override
gomo226b7b72018-12-12 16:49:39 -08002914 public void injectGnssMeasurementCorrections(
2915 GnssMeasurementCorrections measurementCorrections, String packageName) {
2916 mContext.enforceCallingPermission(
2917 android.Manifest.permission.LOCATION_HARDWARE,
2918 "Location Hardware permission not granted to inject GNSS measurement corrections.");
2919 if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
gomo226b7b72018-12-12 16:49:39 -08002920 Slog.e(TAG, "Can not inject GNSS corrections due to no permission.");
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08002921 } else {
2922 mGnssMeasurementsProvider.injectGnssMeasurementCorrections(measurementCorrections);
gomo226b7b72018-12-12 16:49:39 -08002923 }
2924 }
2925
2926 @Override
2927 public int getGnssCapabilities(String packageName) {
2928 mContext.enforceCallingPermission(
2929 android.Manifest.permission.LOCATION_HARDWARE,
2930 "Location Hardware permission not granted to obrain GNSS chipset capabilities.");
2931 if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
2932 return -1;
2933 }
2934 return mGnssMeasurementsProvider.getGnssCapabilities();
2935 }
2936
2937 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002938 public boolean addGnssNavigationMessageListener(
Anil Admal98d49b72019-02-06 15:26:33 -08002939 IGnssNavigationMessageListener listener, String packageName) {
Anil Admal52686f82019-02-13 19:04:10 -08002940 return addGnssDataListener(listener, packageName, "GnssNavigationMessageListener",
2941 mGnssNavigationMessageProvider, mGnssNavigationMessageListeners,
2942 this::removeGnssNavigationMessageListener);
destradaa4b3e3932014-07-21 18:01:47 -07002943 }
2944
2945 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002946 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
Anil Admal52686f82019-02-13 19:04:10 -08002947 removeGnssDataListener(listener, mGnssNavigationMessageProvider,
2948 mGnssNavigationMessageListeners);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002949 }
2950
2951 @Override
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002952 public boolean sendExtraCommand(String providerName, String command, Bundle extras) {
2953 if (providerName == null) {
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002954 // throw NullPointerException to remain compatible with previous implementation
2955 throw new NullPointerException();
2956 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002957 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002958 checkResolutionLevelIsSufficientForProviderUseLocked(getCallerAllowedResolutionLevel(),
2959 providerName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002960
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002961 // and check for ACCESS_LOCATION_EXTRA_COMMANDS
2962 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
2963 != PERMISSION_GRANTED)) {
2964 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
2965 }
2966
2967 LocationProvider provider = getLocationProviderLocked(providerName);
2968 if (provider != null) {
2969 provider.sendExtraCommandLocked(command, extras);
2970 }
2971
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002972 return true;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002973 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002974 }
2975
Nick Pellye0fd6932012-07-11 10:26:13 -07002976 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002977 public boolean sendNiResponse(int notifId, int userResponse) {
Mike Lockwood18ad9f62009-08-27 14:01:23 -07002978 if (Binder.getCallingUid() != Process.myUid()) {
2979 throw new SecurityException(
2980 "calling sendNiResponse from outside of the system is not allowed");
2981 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002982 try {
2983 return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002984 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002985 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
Danke Xie22d1f9f2009-08-18 18:28:45 -04002986 return false;
2987 }
2988 }
2989
Nick Pellye0fd6932012-07-11 10:26:13 -07002990 @Override
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002991 public ProviderProperties getProviderProperties(String providerName) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002992 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002993 checkResolutionLevelIsSufficientForProviderUseLocked(getCallerAllowedResolutionLevel(),
2994 providerName);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002995
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002996 LocationProvider provider = getLocationProviderLocked(providerName);
2997 if (provider == null) {
2998 return null;
2999 }
3000 return provider.getPropertiesLocked();
3001 }
Jason Monkb71218a2015-06-17 14:44:39 -04003002 }
3003
Wei Wang980b7c22018-12-06 17:53:00 -08003004 @Override
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08003005 public boolean isProviderPackage(String packageName) {
3006 synchronized (mLock) {
3007 for (LocationProvider provider : mProviders) {
3008 if (provider.getPackagesLocked().contains(packageName)) {
3009 return true;
3010 }
3011 }
3012
3013 return false;
Soonil Nagarkar68257742019-01-09 19:42:34 +00003014 }
Maggie2a9409e2018-03-21 11:47:28 -07003015 }
3016
Maggie2a9409e2018-03-21 11:47:28 -07003017 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00003018 public void setLocationControllerExtraPackage(String packageName) {
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08003019 mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
3020 Manifest.permission.LOCATION_HARDWARE + " permission required");
Soonil Nagarkar68257742019-01-09 19:42:34 +00003021 synchronized (mLock) {
3022 mLocationControllerExtraPackage = packageName;
3023 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08003024 }
3025
3026 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00003027 public String getLocationControllerExtraPackage() {
3028 synchronized (mLock) {
3029 return mLocationControllerExtraPackage;
3030 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08003031 }
3032
3033 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00003034 public void setLocationControllerExtraPackageEnabled(boolean enabled) {
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08003035 mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
3036 Manifest.permission.LOCATION_HARDWARE + " permission required");
Soonil Nagarkar68257742019-01-09 19:42:34 +00003037 synchronized (mLock) {
3038 mLocationControllerExtraPackageEnabled = enabled;
3039 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08003040 }
3041
3042 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00003043 public boolean isLocationControllerExtraPackageEnabled() {
3044 synchronized (mLock) {
3045 return mLocationControllerExtraPackageEnabled
3046 && (mLocationControllerExtraPackage != null);
3047 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08003048 }
3049
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003050 private boolean isLocationEnabled() {
3051 return isLocationEnabledForUser(mCurrentUserId);
3052 }
3053
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08003054 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00003055 public boolean isLocationEnabledForUser(int userId) {
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08003056 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003057 if (UserHandle.getCallingUserId() != userId) {
3058 mContext.enforceCallingOrSelfPermission(
3059 Manifest.permission.INTERACT_ACROSS_USERS,
3060 "Requires INTERACT_ACROSS_USERS permission");
3061 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08003062
Soonil Nagarkar68257742019-01-09 19:42:34 +00003063 long identity = Binder.clearCallingIdentity();
3064 try {
Soonil Nagarkar42da1b12019-01-22 11:29:27 -08003065 return Settings.Secure.getIntForUser(
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003066 mContext.getContentResolver(),
3067 Settings.Secure.LOCATION_MODE,
Soonil Nagarkar42da1b12019-01-22 11:29:27 -08003068 Settings.Secure.LOCATION_MODE_OFF,
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003069 userId) != Settings.Secure.LOCATION_MODE_OFF;
Soonil Nagarkar68257742019-01-09 19:42:34 +00003070 } finally {
3071 Binder.restoreCallingIdentity(identity);
3072 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08003073 }
3074
Maggie2a9409e2018-03-21 11:47:28 -07003075 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00003076 public boolean isProviderEnabledForUser(String providerName, int userId) {
Maggie2a9409e2018-03-21 11:47:28 -07003077 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003078 if (UserHandle.getCallingUserId() != userId) {
3079 mContext.enforceCallingOrSelfPermission(
3080 Manifest.permission.INTERACT_ACROSS_USERS,
3081 "Requires INTERACT_ACROSS_USERS permission");
Soonil Nagarkar1575a042018-10-24 17:54:54 -07003082 }
3083
Maggie2a9409e2018-03-21 11:47:28 -07003084 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
3085 // so we discourage its use
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003086 if (FUSED_PROVIDER.equals(providerName)) return false;
Maggie2a9409e2018-03-21 11:47:28 -07003087
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003088 synchronized (mLock) {
3089 LocationProvider provider = getLocationProviderLocked(providerName);
3090 return provider != null && provider.isUseableForUserLocked(userId);
Soonil Nagarkar68257742019-01-09 19:42:34 +00003091 }
Maggie2a9409e2018-03-21 11:47:28 -07003092 }
3093
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003094 @GuardedBy("mLock")
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003095 private static boolean shouldBroadcastSafeLocked(
Laurent Tu75defb62012-11-01 16:21:52 -07003096 Location loc, Location lastLoc, UpdateRecord record, long now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003097 // Always broadcast the first update
3098 if (lastLoc == null) {
3099 return true;
3100 }
3101
Nick Pellyf1be6862012-05-15 10:53:42 -07003102 // Check whether sufficient time has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07003103 long minTime = record.mRealRequest.getFastestInterval();
David Christie1b9b7b12013-04-15 15:31:11 -07003104 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
3105 / NANOS_PER_MILLI;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003106 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003107 return false;
3108 }
3109
3110 // Check whether sufficient distance has been traveled
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07003111 double minDistance = record.mRealRequest.getSmallestDisplacement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003112 if (minDistance > 0.0) {
3113 if (loc.distanceTo(lastLoc) <= minDistance) {
3114 return false;
3115 }
3116 }
3117
Laurent Tu75defb62012-11-01 16:21:52 -07003118 // Check whether sufficient number of udpates is left
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07003119 if (record.mRealRequest.getNumUpdates() <= 0) {
Laurent Tu75defb62012-11-01 16:21:52 -07003120 return false;
3121 }
3122
3123 // Check whether the expiry date has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07003124 return record.mRealRequest.getExpireAt() >= now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003125 }
3126
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003127 @GuardedBy("mLock")
3128 private void handleLocationChangedLocked(Location location, LocationProvider provider) {
3129 if (!mProviders.contains(provider)) {
3130 return;
3131 }
3132 if (!location.isComplete()) {
3133 Log.w(TAG, "Dropping incomplete location: " + location);
3134 return;
3135 }
3136
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08003137 // only notify passive provider and update last location for locations that come from
3138 // useable providers
3139 if (provider.isUseableLocked()) {
3140 if (!provider.isPassiveLocked()) {
3141 mPassiveProvider.updateLocation(location);
3142 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003143 }
3144
Soonil Nagarkar68257742019-01-09 19:42:34 +00003145 if (D) Log.d(TAG, "incoming location: " + location);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003146 long now = SystemClock.elapsedRealtime();
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08003147 if (provider.isUseableLocked()) {
3148 updateLastLocationLocked(location, provider.getName());
Mike Lockwood4e50b782009-04-03 08:24:43 -07003149 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003150
David Christie1b9b7b12013-04-15 15:31:11 -07003151 // Update last known coarse interval location if enough time has passed.
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08003152 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(
3153 provider.getName());
David Christie1b9b7b12013-04-15 15:31:11 -07003154 if (lastLocationCoarseInterval == null) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00003155 lastLocationCoarseInterval = new Location(location);
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08003156
3157 if (provider.isUseableLocked()) {
3158 mLastLocationCoarseInterval.put(provider.getName(), lastLocationCoarseInterval);
3159 }
David Christie1b9b7b12013-04-15 15:31:11 -07003160 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00003161 long timeDiffNanos = location.getElapsedRealtimeNanos()
David Christie1b9b7b12013-04-15 15:31:11 -07003162 - lastLocationCoarseInterval.getElapsedRealtimeNanos();
3163 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00003164 lastLocationCoarseInterval.set(location);
David Christie1b9b7b12013-04-15 15:31:11 -07003165 }
3166 // Don't ever return a coarse location that is more recent than the allowed update
3167 // interval (i.e. don't allow an app to keep registering and unregistering for
3168 // location updates to overcome the minimum interval).
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08003169 Location noGPSLocation =
David Christie1b9b7b12013-04-15 15:31:11 -07003170 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
3171
Laurent Tu60ec50a2012-10-04 17:00:10 -07003172 // Skip if there are no UpdateRecords for this provider.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003173 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider.getName());
Laurent Tu60ec50a2012-10-04 17:00:10 -07003174 if (records == null || records.size() == 0) return;
3175
Victoria Lease09016ab2012-09-16 12:33:15 -07003176 // Fetch coarse location
3177 Location coarseLocation = null;
David Christie1b9b7b12013-04-15 15:31:11 -07003178 if (noGPSLocation != null) {
Victoria Lease09016ab2012-09-16 12:33:15 -07003179 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
3180 }
3181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003182 ArrayList<Receiver> deadReceivers = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003183 ArrayList<UpdateRecord> deadUpdateRecords = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07003184
Soonil Nagarkar94749f72018-11-08 11:46:43 -08003185 // Broadcast location to all listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003186 for (UpdateRecord r : records) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003187 Receiver receiver = r.mReceiver;
Mike Lockwood03ca2162010-04-01 08:10:09 -07003188 boolean receiverDead = false;
Nick Pelly4035f5a2012-08-17 14:43:49 -07003189
Soonil Nagarkar397ad582019-01-23 22:47:57 -08003190 if (!provider.isUseableLocked() && !isSettingsExemptLocked(r)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08003191 continue;
3192 }
3193
Anil Admal08b96122019-01-30 16:55:05 -08003194 int receiverUserId = UserHandle.getUserId(receiver.mCallerIdentity.mUid);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003195 if (!isCurrentProfileLocked(receiverUserId)
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08003196 && !isProviderPackage(receiver.mCallerIdentity.mPackageName)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07003197 if (D) {
Victoria Lease269518e2012-10-29 08:25:39 -07003198 Log.d(TAG, "skipping loc update for background user " + receiverUserId +
Victoria Leaseb711d572012-10-02 13:14:11 -07003199 " (current user: " + mCurrentUserId + ", app: " +
Anil Admal08b96122019-01-30 16:55:05 -08003200 receiver.mCallerIdentity.mPackageName + ")");
Victoria Leaseb711d572012-10-02 13:14:11 -07003201 }
3202 continue;
3203 }
3204
Anil Admal08b96122019-01-30 16:55:05 -08003205 if (mBlacklist.isBlacklisted(receiver.mCallerIdentity.mPackageName)) {
gomo48f1a642017-11-10 20:35:46 -08003206 if (D) {
3207 Log.d(TAG, "skipping loc update for blacklisted app: " +
Anil Admal08b96122019-01-30 16:55:05 -08003208 receiver.mCallerIdentity.mPackageName);
gomo48f1a642017-11-10 20:35:46 -08003209 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07003210 continue;
3211 }
3212
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003213 Location notifyLocation;
Victoria Lease37425c32012-10-16 16:08:48 -07003214 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
3215 notifyLocation = coarseLocation; // use coarse location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003216 } else {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08003217 notifyLocation = location; // use fine location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003218 }
Victoria Lease09016ab2012-09-16 12:33:15 -07003219 if (notifyLocation != null) {
3220 Location lastLoc = r.mLastFixBroadcast;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003221 if ((lastLoc == null)
3222 || shouldBroadcastSafeLocked(notifyLocation, lastLoc, r, now)) {
Victoria Lease09016ab2012-09-16 12:33:15 -07003223 if (lastLoc == null) {
3224 lastLoc = new Location(notifyLocation);
3225 r.mLastFixBroadcast = lastLoc;
3226 } else {
3227 lastLoc.set(notifyLocation);
3228 }
Wei Wang8486fc72019-03-07 18:49:21 -08003229 // Report location access before delivering location to the client. This will
3230 // note location delivery to appOps, so it should be called only when a
3231 // location is really being delivered to the client.
3232 if (!reportLocationAccessNoThrow(
3233 receiver.mCallerIdentity.mPid,
3234 receiver.mCallerIdentity.mUid,
3235 receiver.mCallerIdentity.mPackageName,
3236 receiver.mAllowedResolutionLevel)) {
3237 if (D) {
3238 Log.d(TAG, "skipping loc update for no op app: "
3239 + receiver.mCallerIdentity.mPackageName);
3240 }
3241 continue;
3242 }
Victoria Lease09016ab2012-09-16 12:33:15 -07003243 if (!receiver.callLocationChangedLocked(notifyLocation)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003244 Slog.w(TAG, "RemoteException calling onLocationChanged on "
3245 + receiver);
Victoria Lease09016ab2012-09-16 12:33:15 -07003246 receiverDead = true;
3247 }
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07003248 r.mRealRequest.decrementNumUpdates();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003249 }
3250 }
3251
Soonil Nagarkar94749f72018-11-08 11:46:43 -08003252 // TODO: location provider status callbacks have been disabled and deprecated, and are
3253 // guarded behind this setting now. should be removed completely post-Q
3254 if (Settings.Global.getInt(mContext.getContentResolver(),
3255 LOCATION_DISABLE_STATUS_CALLBACKS, 1) == 0) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003256 long newStatusUpdateTime = provider.getStatusUpdateTimeLocked();
3257 Bundle extras = new Bundle();
3258 int status = provider.getStatusLocked(extras);
3259
Soonil Nagarkar94749f72018-11-08 11:46:43 -08003260 long prevStatusUpdateTime = r.mLastStatusBroadcast;
3261 if ((newStatusUpdateTime > prevStatusUpdateTime)
Soonil Nagarkar1575a042018-10-24 17:54:54 -07003262 && (prevStatusUpdateTime != 0 || status != AVAILABLE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003263
Soonil Nagarkar94749f72018-11-08 11:46:43 -08003264 r.mLastStatusBroadcast = newStatusUpdateTime;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003265 if (!receiver.callStatusChangedLocked(provider.getName(), status, extras)) {
Soonil Nagarkar94749f72018-11-08 11:46:43 -08003266 receiverDead = true;
3267 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
3268 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07003269 }
3270 }
3271
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003272 // track expired records
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07003273 if (r.mRealRequest.getNumUpdates() <= 0 || r.mRealRequest.getExpireAt() < now) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003274 if (deadUpdateRecords == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003275 deadUpdateRecords = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003276 }
3277 deadUpdateRecords.add(r);
3278 }
3279 // track dead receivers
3280 if (receiverDead) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07003281 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003282 deadReceivers = new ArrayList<>();
Mike Lockwood03ca2162010-04-01 08:10:09 -07003283 }
3284 if (!deadReceivers.contains(receiver)) {
3285 deadReceivers.add(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003286 }
3287 }
3288 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003289
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003290 // remove dead records and receivers outside the loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003291 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003292 for (Receiver receiver : deadReceivers) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00003293 removeUpdatesLocked(receiver);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003294 }
3295 }
3296 if (deadUpdateRecords != null) {
3297 for (UpdateRecord r : deadUpdateRecords) {
3298 r.disposeLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003299 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00003300 applyRequirementsLocked(provider);
Victoria Lease8b38b292012-12-04 15:04:43 -08003301 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003302 }
3303
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003304 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00003305 private void updateLastLocationLocked(Location location, String provider) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08003306 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
3307 Location lastNoGPSLocation;
3308 Location lastLocation = mLastLocation.get(provider);
3309 if (lastLocation == null) {
3310 lastLocation = new Location(provider);
3311 mLastLocation.put(provider, lastLocation);
3312 } else {
3313 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
3314 if (noGPSLocation == null && lastNoGPSLocation != null) {
3315 // New location has no no-GPS location: adopt last no-GPS location. This is set
3316 // directly into location because we do not want to notify COARSE clients.
3317 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
3318 }
3319 }
3320 lastLocation.set(location);
3321 }
3322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003323 // Geocoder
3324
Nick Pellye0fd6932012-07-11 10:26:13 -07003325 @Override
Mike Lockwoode15735a2010-09-20 17:48:47 -04003326 public boolean geocoderIsPresent() {
Mark Vandevoorde01ac80b2010-05-21 15:43:26 -07003327 return mGeocodeProvider != null;
3328 }
3329
Nick Pellye0fd6932012-07-11 10:26:13 -07003330 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003331 public String getFromLocation(double latitude, double longitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05003332 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04003333 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05003334 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
3335 params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003336 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04003337 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003338 }
3339
Mike Lockwooda55c3212009-04-15 11:10:11 -04003340
Nick Pellye0fd6932012-07-11 10:26:13 -07003341 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003342 public String getFromLocationName(String locationName,
Mike Lockwooda55c3212009-04-15 11:10:11 -04003343 double lowerLeftLatitude, double lowerLeftLongitude,
3344 double upperRightLatitude, double upperRightLongitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05003345 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04003346
3347 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05003348 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
3349 lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
3350 maxResults, params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003351 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04003352 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003353 }
3354
3355 // Mock Providers
3356
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003357 private boolean canCallerAccessMockLocation(String opPackageName) {
Wei Wang16276a42019-02-04 18:23:31 -08003358 return mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(),
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003359 opPackageName) == AppOpsManager.MODE_ALLOWED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003360 }
3361
Nick Pellye0fd6932012-07-11 10:26:13 -07003362 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00003363 public void addTestProvider(String name, ProviderProperties properties, String opPackageName) {
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003364 if (!canCallerAccessMockLocation(opPackageName)) {
3365 return;
3366 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003367
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003368 if (PASSIVE_PROVIDER.equals(name)) {
Mike Lockwooda4903f22010-02-17 06:42:23 -05003369 throw new IllegalArgumentException("Cannot mock the passive location provider");
3370 }
3371
Soonil Nagarkar68257742019-01-09 19:42:34 +00003372 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003373 long identity = Binder.clearCallingIdentity();
3374 try {
3375 LocationProvider oldProvider = getLocationProviderLocked(name);
3376 if (oldProvider != null) {
3377 if (oldProvider.isMock()) {
3378 throw new IllegalArgumentException(
3379 "Provider \"" + name + "\" already exists");
3380 }
3381
3382 removeProviderLocked(oldProvider);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003383 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003384
3385 MockLocationProvider mockProviderManager = new MockLocationProvider(name);
3386 addProviderLocked(mockProviderManager);
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08003387 mockProviderManager.attachLocked(
3388 new MockProvider(mContext, mockProviderManager, properties));
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003389 } finally {
3390 Binder.restoreCallingIdentity(identity);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003391 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00003392 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09003393 }
3394
Nick Pellye0fd6932012-07-11 10:26:13 -07003395 @Override
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003396 public void removeTestProvider(String name, String opPackageName) {
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003397 if (!canCallerAccessMockLocation(opPackageName)) {
3398 return;
3399 }
3400
Soonil Nagarkar68257742019-01-09 19:42:34 +00003401 synchronized (mLock) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00003402 long identity = Binder.clearCallingIdentity();
3403 try {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003404 LocationProvider testProvider = getLocationProviderLocked(name);
3405 if (testProvider == null || !testProvider.isMock()) {
3406 throw new IllegalArgumentException("Provider \"" + name + "\" unknown");
3407 }
3408
3409 removeProviderLocked(testProvider);
Soonil Nagarkar1575a042018-10-24 17:54:54 -07003410
Soonil Nagarkar68257742019-01-09 19:42:34 +00003411 // reinstate real provider if available
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003412 LocationProvider realProvider = null;
3413 for (LocationProvider provider : mRealProviders) {
3414 if (name.equals(provider.getName())) {
3415 realProvider = provider;
3416 break;
3417 }
3418 }
3419
Soonil Nagarkar68257742019-01-09 19:42:34 +00003420 if (realProvider != null) {
3421 addProviderLocked(realProvider);
3422 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00003423 } finally {
3424 Binder.restoreCallingIdentity(identity);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003425 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00003426 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003427 }
3428
Nick Pellye0fd6932012-07-11 10:26:13 -07003429 @Override
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003430 public void setTestProviderLocation(String providerName, Location location,
Soonil Nagarkar68257742019-01-09 19:42:34 +00003431 String opPackageName) {
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003432 if (!canCallerAccessMockLocation(opPackageName)) {
3433 return;
3434 }
3435
Soonil Nagarkar68257742019-01-09 19:42:34 +00003436 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003437 LocationProvider testProvider = getLocationProviderLocked(providerName);
3438 if (testProvider == null || !testProvider.isMock()) {
3439 throw new IllegalArgumentException("Provider \"" + providerName + "\" unknown");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003440 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003441
3442 String locationProvider = location.getProvider();
3443 if (!TextUtils.isEmpty(locationProvider) && !providerName.equals(locationProvider)) {
3444 // The location has an explicit provider that is different from the mock
3445 // provider name. The caller may be trying to fool us via b/33091107.
3446 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
3447 providerName + "!=" + location.getProvider());
3448 }
3449
3450 ((MockLocationProvider) testProvider).setLocationLocked(location);
Soonil Nagarkar68257742019-01-09 19:42:34 +00003451 }
3452 }
3453
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003454 @Override
3455 public void setTestProviderEnabled(String providerName, boolean enabled, String opPackageName) {
3456 if (!canCallerAccessMockLocation(opPackageName)) {
3457 return;
3458 }
3459
3460 synchronized (mLock) {
3461 LocationProvider testProvider = getLocationProviderLocked(providerName);
3462 if (testProvider == null || !testProvider.isMock()) {
3463 throw new IllegalArgumentException("Provider \"" + providerName + "\" unknown");
3464 }
3465
3466 ((MockLocationProvider) testProvider).setEnabledLocked(enabled);
3467 }
3468 }
3469
3470 @Override
3471 public void setTestProviderStatus(String providerName, int status, Bundle extras,
3472 long updateTime, String opPackageName) {
3473 if (!canCallerAccessMockLocation(opPackageName)) {
3474 return;
3475 }
3476
3477 synchronized (mLock) {
3478 LocationProvider testProvider = getLocationProviderLocked(providerName);
3479 if (testProvider == null || !testProvider.isMock()) {
3480 throw new IllegalArgumentException("Provider \"" + providerName + "\" unknown");
3481 }
3482
3483 ((MockLocationProvider) testProvider).setStatusLocked(status, extras, updateTime);
Soonil Nagarkar68257742019-01-09 19:42:34 +00003484 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003485 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003486
3487 @Override
Kweku Adams4fb074e2019-02-01 16:03:27 -08003488 @NonNull
3489 public List<LocationRequest> getTestProviderCurrentRequests(String providerName,
3490 String opPackageName) {
3491 if (!canCallerAccessMockLocation(opPackageName)) {
3492 return Collections.emptyList();
3493 }
3494
3495 synchronized (mLock) {
3496 LocationProvider testProvider = getLocationProviderLocked(providerName);
3497 if (testProvider == null || !testProvider.isMock()) {
3498 throw new IllegalArgumentException("Provider \"" + providerName + "\" unknown");
3499 }
3500
3501 MockLocationProvider provider = (MockLocationProvider) testProvider;
3502 if (provider.mCurrentRequest == null) {
3503 return Collections.emptyList();
3504 }
3505 List<LocationRequest> requests = new ArrayList<>();
3506 for (LocationRequest request : provider.mCurrentRequest.locationRequests) {
3507 requests.add(new LocationRequest(request));
3508 }
3509 return requests;
3510 }
3511 }
3512
3513 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003514 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003515 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Nick Pellye0fd6932012-07-11 10:26:13 -07003516
Soonil Nagarkar68257742019-01-09 19:42:34 +00003517 synchronized (mLock) {
Siddharth Raybb608c82017-03-16 11:33:34 -07003518 if (args.length > 0 && args[0].equals("--gnssmetrics")) {
3519 if (mGnssMetricsProvider != null) {
3520 pw.append(mGnssMetricsProvider.getGnssMetricsAsProtoString());
3521 }
3522 return;
3523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003524 pw.println("Current Location Manager state:");
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08003525 pw.println(" Current user: " + mCurrentUserId + " " + Arrays.toString(
3526 mCurrentUserProfiles));
3527 pw.println(" Location mode: " + isLocationEnabled());
Kweku Adams4fb074e2019-02-01 16:03:27 -08003528 pw.println(" Battery Saver Location Mode: "
3529 + locationPowerSaveModeToString(mBatterySaverMode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003530 pw.println(" Location Listeners:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003531 for (Receiver receiver : mReceivers.values()) {
3532 pw.println(" " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003533 }
David Christie2ff96af2014-01-30 16:09:37 -08003534 pw.println(" Active Records by Provider:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003535 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
3536 pw.println(" " + entry.getKey() + ":");
3537 for (UpdateRecord record : entry.getValue()) {
3538 pw.println(" " + record);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003539 }
3540 }
Anil Admal98d49b72019-02-06 15:26:33 -08003541
Wyatt Riley11cc7492018-01-17 08:48:27 -08003542 pw.println(" Active GnssMeasurement Listeners:");
Anil Admal98d49b72019-02-06 15:26:33 -08003543 dumpGnssDataListenersLocked(pw, mGnssMeasurementsListeners);
Wyatt Riley11cc7492018-01-17 08:48:27 -08003544 pw.println(" Active GnssNavigationMessage Listeners:");
Anil Admal98d49b72019-02-06 15:26:33 -08003545 dumpGnssDataListenersLocked(pw, mGnssNavigationMessageListeners);
3546 pw.println(" Active GnssStatus Listeners:");
3547 dumpGnssDataListenersLocked(pw, mGnssStatusListeners);
3548
David Christie2ff96af2014-01-30 16:09:37 -08003549 pw.println(" Historical Records by Provider:");
3550 for (Map.Entry<PackageProviderKey, PackageStatistics> entry
3551 : mRequestStatistics.statistics.entrySet()) {
3552 PackageProviderKey key = entry.getKey();
3553 PackageStatistics stats = entry.getValue();
3554 pw.println(" " + key.packageName + ": " + key.providerName + ": " + stats);
3555 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003556 pw.println(" Last Known Locations:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003557 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
3558 String provider = entry.getKey();
3559 Location location = entry.getValue();
3560 pw.println(" " + provider + ": " + location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003561 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003562
David Christie1b9b7b12013-04-15 15:31:11 -07003563 pw.println(" Last Known Locations Coarse Intervals:");
3564 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
3565 String provider = entry.getKey();
3566 Location location = entry.getValue();
3567 pw.println(" " + provider + ": " + location);
3568 }
3569
Nick Pellye0fd6932012-07-11 10:26:13 -07003570 mGeofenceManager.dump(pw);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003571
Nick Pelly4035f5a2012-08-17 14:43:49 -07003572 pw.append(" ");
3573 mBlacklist.dump(pw);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003574
Wei Wang980b7c22018-12-06 17:53:00 -08003575 if (mLocationControllerExtraPackage != null) {
3576 pw.println(" Location controller extra package: " + mLocationControllerExtraPackage
3577 + " enabled: " + mLocationControllerExtraPackageEnabled);
3578 }
3579
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08003580 if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
3581 pw.println(" Throttling Whitelisted Packages:");
3582 for (String packageName : mBackgroundThrottlePackageWhitelist) {
3583 pw.println(" " + packageName);
3584 }
3585 }
3586
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003587 pw.append(" fudger: ");
gomo48f1a642017-11-10 20:35:46 -08003588 mLocationFudger.dump(fd, pw, args);
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003589
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003590 if (args.length > 0 && "short".equals(args[0])) {
3591 return;
3592 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07003593 for (LocationProvider provider : mProviders) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003594 provider.dumpLocked(fd, pw, args);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003595 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08003596 if (mGnssBatchingInProgress) {
3597 pw.println(" GNSS batching in progress");
3598 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003599 }
3600 }
Anil Admal98d49b72019-02-06 15:26:33 -08003601
3602 @GuardedBy("mLock")
3603 private void dumpGnssDataListenersLocked(PrintWriter pw,
3604 ArrayMap<IBinder, ? extends LinkedListenerBase> gnssDataListeners) {
3605 for (LinkedListenerBase listener : gnssDataListeners.values()) {
3606 CallerIdentity callerIdentity = listener.mCallerIdentity;
3607 pw.println(" " + callerIdentity.mPid + " " + callerIdentity.mUid + " "
3608 + callerIdentity.mPackageName + ": "
3609 + isThrottlingExemptLocked(callerIdentity));
3610 }
3611 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003612}