blob: 979096e158fe332d63e79931f6a9735f58ae0546 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Soonil Nagarkar7decfb62017-01-18 12:18:49 -080019import android.app.ActivityManager;
Wyatt Rileycf879db2017-01-12 13:57:38 -080020import android.annotation.NonNull;
Svet Ganovadc1cf42015-06-15 16:36:24 -070021import android.content.pm.PackageManagerInternal;
Soonil Nagarkar681d7112017-02-23 17:14:16 -080022import android.util.ArrayMap;
Soonil Nagarkar2b565df2017-02-14 13:33:23 -080023import android.util.ArraySet;
destradaaea8a8a62014-06-23 18:19:03 -070024import com.android.internal.content.PackageMonitor;
25import com.android.internal.location.ProviderProperties;
26import com.android.internal.location.ProviderRequest;
27import com.android.internal.os.BackgroundThread;
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -070028import com.android.internal.util.ArrayUtils;
destradaaa4fa3b52014-07-09 10:46:39 -070029import com.android.server.location.ActivityRecognitionProxy;
destradaaea8a8a62014-06-23 18:19:03 -070030import com.android.server.location.FlpHardwareProvider;
31import com.android.server.location.FusedProxy;
32import com.android.server.location.GeocoderProxy;
33import com.android.server.location.GeofenceManager;
34import com.android.server.location.GeofenceProxy;
Lifu Tang818aa2c2016-02-01 01:52:00 -080035import com.android.server.location.GnssLocationProvider;
36import com.android.server.location.GnssMeasurementsProvider;
37import com.android.server.location.GnssNavigationMessageProvider;
destradaaea8a8a62014-06-23 18:19:03 -070038import com.android.server.location.LocationBlacklist;
39import com.android.server.location.LocationFudger;
40import com.android.server.location.LocationProviderInterface;
41import com.android.server.location.LocationProviderProxy;
42import com.android.server.location.LocationRequestStatistics;
43import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
44import com.android.server.location.LocationRequestStatistics.PackageStatistics;
45import com.android.server.location.MockProvider;
46import com.android.server.location.PassiveProvider;
47
Dianne Hackborna06de0f2012-12-11 16:34:47 -080048import android.app.AppOpsManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.app.PendingIntent;
Victoria Lease38389b62012-09-30 11:44:22 -070050import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import android.content.ContentResolver;
52import android.content.Context;
53import android.content.Intent;
Victoria Lease38389b62012-09-30 11:44:22 -070054import android.content.IntentFilter;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070055import android.content.pm.ApplicationInfo;
Jeff Hamiltonfbadb692012-10-05 14:21:58 -050056import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import android.content.pm.PackageManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070058import android.content.pm.PackageManager.NameNotFoundException;
Jeff Hamiltonfbadb692012-10-05 14:21:58 -050059import android.content.pm.ResolveInfo;
60import android.content.pm.Signature;
Mike Lockwood628fd6d2010-01-25 22:46:13 -050061import android.content.res.Resources;
Brian Muramatsubb95cb92012-08-29 10:43:21 -070062import android.database.ContentObserver;
destradaaa4fa3b52014-07-09 10:46:39 -070063import android.hardware.location.ActivityRecognitionHardware;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import android.location.Address;
Mike Lockwood03ca2162010-04-01 08:10:09 -070065import android.location.Criteria;
Mike Lockwood34901402010-01-04 12:14:21 -050066import android.location.GeocoderParams;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070067import android.location.Geofence;
Wyatt Rileycf879db2017-01-12 13:57:38 -080068import android.location.IBatchedLocationCallback;
Lifu Tang818aa2c2016-02-01 01:52:00 -080069import android.location.IGnssMeasurementsListener;
Lifu Tang30f95a72016-01-07 23:20:38 -080070import android.location.IGnssStatusListener;
71import android.location.IGnssStatusProvider;
Wei Liu5241a4c2015-05-11 14:00:36 -070072import android.location.IGpsGeofenceHardware;
Lifu Tang818aa2c2016-02-01 01:52:00 -080073import android.location.IGnssNavigationMessageListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074import android.location.ILocationListener;
75import android.location.ILocationManager;
Danke Xie22d1f9f2009-08-18 18:28:45 -040076import android.location.INetInitiatedListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.location.Location;
78import android.location.LocationManager;
79import android.location.LocationProvider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070080import android.location.LocationRequest;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081import android.os.Binder;
82import android.os.Bundle;
83import android.os.Handler;
84import android.os.IBinder;
Mike Lockwood3d12b512009-04-21 23:25:35 -070085import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import android.os.Message;
87import android.os.PowerManager;
Mike Lockwoode932f7f2009-04-06 10:51:26 -070088import android.os.Process;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089import android.os.RemoteException;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070090import android.os.SystemClock;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070091import android.os.UserHandle;
Amith Yamasanib27528d2014-06-05 15:02:10 -070092import android.os.UserManager;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070093import android.os.WorkSource;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import android.provider.Settings;
Tom O'Neilla206a0f2016-12-15 10:26:28 -080095import android.text.TextUtils;
96import android.util.EventLog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.util.Log;
Joe Onorato8a9b2202010-02-26 18:56:32 -080098import android.util.Slog;
Amith Yamasanib27528d2014-06-05 15:02:10 -070099
Mike Lockwood43e33f22010-03-26 10:41:48 -0400100import java.io.FileDescriptor;
101import java.io.PrintWriter;
102import java.util.ArrayList;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700103import java.util.Arrays;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400104import java.util.HashMap;
105import java.util.HashSet;
106import java.util.List;
107import java.util.Map;
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800108import java.util.Map.Entry;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800109import java.util.NoSuchElementException;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400110import java.util.Set;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111
112/**
113 * The service class that manages LocationProviders and issues location
114 * updates and alerts.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 */
Victoria Lease5cd731a2012-12-19 15:04:21 -0800116public class LocationManagerService extends ILocationManager.Stub {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117 private static final String TAG = "LocationManagerService";
JP Abgrallf79811e72013-02-01 18:45:05 -0800118 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700119
120 private static final String WAKELOCK_KEY = TAG;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121
Victoria Lease37425c32012-10-16 16:08:48 -0700122 // Location resolution level: no location data whatsoever
123 private static final int RESOLUTION_LEVEL_NONE = 0;
124 // Location resolution level: coarse location data only
125 private static final int RESOLUTION_LEVEL_COARSE = 1;
126 // Location resolution level: fine location data
127 private static final int RESOLUTION_LEVEL_FINE = 2;
128
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129 private static final String ACCESS_MOCK_LOCATION =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700130 android.Manifest.permission.ACCESS_MOCK_LOCATION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131 private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700132 android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
Mike Lockwood275555c2009-05-01 11:30:34 -0400133 private static final String INSTALL_LOCATION_PROVIDER =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700134 android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
135
136 private static final String NETWORK_LOCATION_SERVICE_ACTION =
Stan Chesnutt39062dd2013-07-22 14:33:30 -0700137 "com.android.location.service.v3.NetworkLocationProvider";
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700138 private static final String FUSED_LOCATION_SERVICE_ACTION =
139 "com.android.location.service.FusedLocationProvider";
140
141 private static final int MSG_LOCATION_CHANGED = 1;
142
David Christie1b9b7b12013-04-15 15:31:11 -0700143 private static final long NANOS_PER_MILLI = 1000000L;
144
David Christie0b837452013-07-29 16:02:13 -0700145 // The maximum interval a location request can have and still be considered "high power".
146 private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
147
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800148 // default background throttling interval if not overriden in settings
Soonil Nagarkarde6780a2017-02-07 10:39:41 -0800149 private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800150
Nick Pellyf1be6862012-05-15 10:53:42 -0700151 // Location Providers may sometimes deliver location updates
152 // slightly faster that requested - provide grace period so
153 // we don't unnecessarily filter events that are otherwise on
154 // time
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700155 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
Nick Pellyf1be6862012-05-15 10:53:42 -0700156
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700157 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
158
159 private final Context mContext;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800160 private final AppOpsManager mAppOps;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700161
162 // used internally for synchronization
163 private final Object mLock = new Object();
164
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700165 // --- fields below are final after systemRunning() ---
Nick Pelly74fa7ea2012-08-13 19:36:38 -0700166 private LocationFudger mLocationFudger;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700167 private GeofenceManager mGeofenceManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700168 private PackageManager mPackageManager;
Victoria Lease0aa28602013-05-29 15:28:26 -0700169 private PowerManager mPowerManager;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800170 private ActivityManager mActivityManager;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700171 private UserManager mUserManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700172 private GeocoderProxy mGeocodeProvider;
Lifu Tang30f95a72016-01-07 23:20:38 -0800173 private IGnssStatusProvider mGnssStatusProvider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700174 private INetInitiatedListener mNetInitiatedListener;
175 private LocationWorkerHandler mLocationHandler;
Nick Pelly4035f5a2012-08-17 14:43:49 -0700176 private PassiveProvider mPassiveProvider; // track passive provider for special cases
177 private LocationBlacklist mBlacklist;
Lifu Tang818aa2c2016-02-01 01:52:00 -0800178 private GnssMeasurementsProvider mGnssMeasurementsProvider;
179 private GnssNavigationMessageProvider mGnssNavigationMessageProvider;
Wei Liu5241a4c2015-05-11 14:00:36 -0700180 private IGpsGeofenceHardware mGpsGeofenceProxy;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700181
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700182 // --- fields below are protected by mLock ---
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 // Set of providers that are explicitly enabled
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700184 // Only used by passive, fused & test. Network & GPS are controlled separately, and not listed.
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800185 private final Set<String> mEnabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186
187 // Set of providers that are explicitly disabled
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800188 private final Set<String> mDisabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700190 // Mock (test) providers
191 private final HashMap<String, MockProvider> mMockProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800192 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700194 // all receivers
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800195 private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700197 // currently installed providers (with mocks replacing real providers)
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500198 private final ArrayList<LocationProviderInterface> mProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800199 new ArrayList<>();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400200
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700201 // real providers, saved here when mocked out
202 private final HashMap<String, LocationProviderInterface> mRealProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800203 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700205 // mapping from provider name to provider
206 private final HashMap<String, LocationProviderInterface> mProvidersByName =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800207 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700209 // mapping from provider name to all its UpdateRecords
210 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800211 new HashMap<>();
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700212
David Christie2ff96af2014-01-30 16:09:37 -0800213 private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics();
214
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700215 // mapping from provider name to last known location
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800216 private final HashMap<String, Location> mLastLocation = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217
David Christie1b9b7b12013-04-15 15:31:11 -0700218 // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
219 // locations stored here are not fudged for coarse permissions.
220 private final HashMap<String, Location> mLastLocationCoarseInterval =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800221 new HashMap<>();
David Christie1b9b7b12013-04-15 15:31:11 -0700222
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800223 // all providers that operate over proxy, for authorizing incoming location and whitelisting
224 // throttling
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700225 private final ArrayList<LocationProviderProxy> mProxyProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800226 new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800228 private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800229
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800230 private final ArrayMap<IGnssMeasurementsListener, Identity> mGnssMeasurementsListeners =
231 new ArrayMap<>();
232
233 private final ArrayMap<IGnssNavigationMessageListener, Identity>
234 mGnssNavigationMessageListeners = new ArrayMap<>();
235
Victoria Lease38389b62012-09-30 11:44:22 -0700236 // current active user on the device - other users are denied location data
Xiaohui Chena4490622015-09-22 15:29:31 -0700237 private int mCurrentUserId = UserHandle.USER_SYSTEM;
238 private int[] mCurrentUserProfiles = new int[] { UserHandle.USER_SYSTEM };
Victoria Lease38389b62012-09-30 11:44:22 -0700239
Lifu Tang9363b942016-02-16 18:07:00 -0800240 private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;
Lifu Tang82f893d2016-01-21 18:15:33 -0800241
Wyatt Rileycf879db2017-01-12 13:57:38 -0800242 private GnssLocationProvider.GnssBatchingProvider mGnssBatchingProvider;
243 private IBatchedLocationCallback mGnssBatchingCallback;
244 private LinkedCallback mGnssBatchingDeathCallback;
245 private boolean mGnssBatchingInProgress = false;
246
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700247 public LocationManagerService(Context context) {
248 super();
249 mContext = context;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800250 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800251
Svet Ganovadc1cf42015-06-15 16:36:24 -0700252 // Let the package manager query which are the default location
253 // providers as they get certain permissions granted by default.
254 PackageManagerInternal packageManagerInternal = LocalServices.getService(
255 PackageManagerInternal.class);
256 packageManagerInternal.setLocationPackagesProvider(
257 new PackageManagerInternal.PackagesProvider() {
258 @Override
259 public String[] getPackages(int userId) {
260 return mContext.getResources().getStringArray(
261 com.android.internal.R.array.config_locationProviderPackageNames);
262 }
263 });
264
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700265 if (D) Log.d(TAG, "Constructed");
266
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700267 // most startup is deferred until systemRunning()
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700268 }
269
Svetoslav Ganova0027152013-06-25 14:59:53 -0700270 public void systemRunning() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700271 synchronized (mLock) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700272 if (D) Log.d(TAG, "systemRunning()");
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700273
Victoria Lease5cd731a2012-12-19 15:04:21 -0800274 // fetch package manager
275 mPackageManager = mContext.getPackageManager();
276
Victoria Lease0aa28602013-05-29 15:28:26 -0700277 // fetch power manager
278 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
Victoria Lease5cd731a2012-12-19 15:04:21 -0800279
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800280 // fetch activity manager
281 mActivityManager
282 = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
283
Victoria Lease5cd731a2012-12-19 15:04:21 -0800284 // prepare worker thread
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700285 mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper());
Victoria Lease5cd731a2012-12-19 15:04:21 -0800286
287 // prepare mLocationHandler's dependents
288 mLocationFudger = new LocationFudger(mContext, mLocationHandler);
289 mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
290 mBlacklist.init();
291 mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
292
Dianne Hackbornc2293022013-02-06 23:14:49 -0800293 // Monitor for app ops mode changes.
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700294 AppOpsManager.OnOpChangedListener callback
295 = new AppOpsManager.OnOpChangedInternalListener() {
296 public void onOpChanged(int op, String packageName) {
Dianne Hackbornc2293022013-02-06 23:14:49 -0800297 synchronized (mLock) {
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700298 for (Receiver receiver : mReceivers.values()) {
299 receiver.updateMonitoring(true);
300 }
Dianne Hackbornc2293022013-02-06 23:14:49 -0800301 applyAllProviderRequirementsLocked();
302 }
303 }
304 };
305 mAppOps.startWatchingMode(AppOpsManager.OP_COARSE_LOCATION, null, callback);
306
David Christieb870dbf2015-06-22 12:42:53 -0700307 PackageManager.OnPermissionsChangedListener permissionListener
308 = new PackageManager.OnPermissionsChangedListener() {
309 @Override
310 public void onPermissionsChanged(final int uid) {
311 synchronized (mLock) {
312 applyAllProviderRequirementsLocked();
313 }
314 }
315 };
316 mPackageManager.addOnPermissionsChangeListener(permissionListener);
317
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800318 // listen for background/foreground changes
319 ActivityManager.OnUidImportanceListener uidImportanceListener
320 = new ActivityManager.OnUidImportanceListener() {
321 @Override
322 public void onUidImportance(int uid, int importance) {
323 boolean foreground = isImportanceForeground(importance);
324 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
325 synchronized (mLock) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800326 for (Entry<String, ArrayList<UpdateRecord>> entry
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800327 : mRecordsByProvider.entrySet()) {
328 String provider = entry.getKey();
329 for (UpdateRecord record : entry.getValue()) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800330 if (record.mReceiver.mIdentity.mUid == uid
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800331 && record.mIsForegroundUid != foreground) {
332 if (D) Log.d(TAG, "request from uid " + uid + " is now "
333 + (foreground ? "foreground" : "background)"));
334 record.mIsForegroundUid = foreground;
335
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800336 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800337 affectedProviders.add(provider);
338 }
339 }
340 }
341 }
342 for (String provider : affectedProviders) {
343 applyRequirementsLocked(provider);
344 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800345
346 for (Entry<IGnssMeasurementsListener, Identity> entry
347 : mGnssMeasurementsListeners.entrySet()) {
348 if (entry.getValue().mUid == uid) {
349 if (D) Log.d(TAG, "gnss measurements listener from uid " + uid
350 + " is now " + (foreground ? "foreground" : "background)"));
351 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
352 mGnssMeasurementsProvider.addListener(entry.getKey());
353 } else {
354 mGnssMeasurementsProvider.removeListener(entry.getKey());
355 }
356 }
357 }
358
359 for (Entry<IGnssNavigationMessageListener, Identity> entry
360 : mGnssNavigationMessageListeners.entrySet()) {
361 if (entry.getValue().mUid == uid) {
362 if (D) Log.d(TAG, "gnss navigation message listener from uid "
363 + uid + " is now "
364 + (foreground ? "foreground" : "background)"));
365 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
366 mGnssNavigationMessageProvider.addListener(entry.getKey());
367 } else {
368 mGnssNavigationMessageProvider.removeListener(entry.getKey());
369 }
370 }
371 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800372 }
373
374 }
375 };
376 mActivityManager.addOnUidImportanceListener(uidImportanceListener,
377 ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE);
378
Amith Yamasanib27528d2014-06-05 15:02:10 -0700379 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
380 updateUserProfiles(mCurrentUserId);
381
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800382 updateBackgroundThrottlingWhitelistLocked();
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800383
Victoria Lease5cd731a2012-12-19 15:04:21 -0800384 // prepare providers
385 loadProvidersLocked();
386 updateProvidersLocked();
387 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700388
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700389 // listen for settings changes
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700390 mContext.getContentResolver().registerContentObserver(
Laurent Tu75defb62012-11-01 16:21:52 -0700391 Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700392 new ContentObserver(mLocationHandler) {
Victoria Lease5cd731a2012-12-19 15:04:21 -0800393 @Override
394 public void onChange(boolean selfChange) {
395 synchronized (mLock) {
396 updateProvidersLocked();
397 }
398 }
399 }, UserHandle.USER_ALL);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800400 mContext.getContentResolver().registerContentObserver(
401 Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS),
402 true,
403 new ContentObserver(mLocationHandler) {
404 @Override
405 public void onChange(boolean selfChange) {
406 synchronized (mLock) {
407 updateProvidersLocked();
408 }
409 }
410 }, UserHandle.USER_ALL);
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800411 mContext.getContentResolver().registerContentObserver(
412 Settings.Global.getUriFor(
413 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
414 true,
415 new ContentObserver(mLocationHandler) {
416 @Override
417 public void onChange(boolean selfChange) {
418 synchronized (mLock) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800419 updateBackgroundThrottlingWhitelistLocked();
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800420 updateProvidersLocked();
421 }
422 }
423 }, UserHandle.USER_ALL);
Victoria Lease5cd731a2012-12-19 15:04:21 -0800424 mPackageMonitor.register(mContext, mLocationHandler.getLooper(), true);
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700425
Victoria Lease38389b62012-09-30 11:44:22 -0700426 // listen for user change
427 IntentFilter intentFilter = new IntentFilter();
428 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700429 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
430 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
destradaab9026982015-08-27 17:34:54 -0700431 intentFilter.addAction(Intent.ACTION_SHUTDOWN);
Victoria Lease38389b62012-09-30 11:44:22 -0700432
433 mContext.registerReceiverAsUser(new BroadcastReceiver() {
434 @Override
435 public void onReceive(Context context, Intent intent) {
436 String action = intent.getAction();
437 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
438 switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
Amith Yamasanib27528d2014-06-05 15:02:10 -0700439 } else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)
440 || Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
441 updateUserProfiles(mCurrentUserId);
destradaab9026982015-08-27 17:34:54 -0700442 } else if (Intent.ACTION_SHUTDOWN.equals(action)) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700443 // shutdown only if UserId indicates whole system, not just one user
444 if(D) Log.d(TAG, "Shutdown received with UserId: " + getSendingUserId());
445 if (getSendingUserId() == UserHandle.USER_ALL) {
446 shutdownComponents();
447 }
Victoria Lease38389b62012-09-30 11:44:22 -0700448 }
449 }
Victoria Lease5cd731a2012-12-19 15:04:21 -0800450 }, UserHandle.ALL, intentFilter, null, mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700451 }
452
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800453 private static boolean isImportanceForeground(int importance) {
454 return importance <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
455 }
456
Amith Yamasanib27528d2014-06-05 15:02:10 -0700457 /**
destradaab9026982015-08-27 17:34:54 -0700458 * Provides a way for components held by the {@link LocationManagerService} to clean-up
459 * gracefully on system's shutdown.
460 *
461 * NOTES:
462 * 1) Only provides a chance to clean-up on an opt-in basis. This guarantees back-compat
463 * support for components that do not wish to handle such event.
464 */
465 private void shutdownComponents() {
466 if(D) Log.d(TAG, "Shutting down components...");
467
468 LocationProviderInterface gpsProvider = mProvidersByName.get(LocationManager.GPS_PROVIDER);
469 if (gpsProvider != null && gpsProvider.isEnabled()) {
470 gpsProvider.disable();
471 }
472
destradaa2e385072015-10-14 16:45:58 -0700473 // it is needed to check if FLP HW provider is supported before accessing the instance, this
474 // avoids an exception to be thrown by the singleton factory method
475 if (FlpHardwareProvider.isSupported()) {
476 FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
destradaab9026982015-08-27 17:34:54 -0700477 flpHardwareProvider.cleanup();
478 }
479 }
480
481 /**
Amith Yamasanib27528d2014-06-05 15:02:10 -0700482 * Makes a list of userids that are related to the current user. This is
483 * relevant when using managed profiles. Otherwise the list only contains
484 * the current user.
485 *
486 * @param currentUserId the current user, who might have an alter-ego.
487 */
488 void updateUserProfiles(int currentUserId) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700489 int[] profileIds = mUserManager.getProfileIdsWithDisabled(currentUserId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700490 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700491 mCurrentUserProfiles = profileIds;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700492 }
493 }
494
495 /**
496 * Checks if the specified userId matches any of the current foreground
497 * users stored in mCurrentUserProfiles.
498 */
499 private boolean isCurrentProfile(int userId) {
500 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700501 return ArrayUtils.contains(mCurrentUserProfiles, userId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700502 }
503 }
504
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500505 private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) {
506 PackageManager pm = mContext.getPackageManager();
507 String systemPackageName = mContext.getPackageName();
508 ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
509
510 List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
511 new Intent(FUSED_LOCATION_SERVICE_ACTION),
512 PackageManager.GET_META_DATA, mCurrentUserId);
513 for (ResolveInfo rInfo : rInfos) {
514 String packageName = rInfo.serviceInfo.packageName;
515
516 // Check that the signature is in the list of supported sigs. If it's not in
517 // this list the standard provider binding logic won't bind to it.
518 try {
519 PackageInfo pInfo;
520 pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
521 if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
522 Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
523 ", but has wrong signature, ignoring");
524 continue;
525 }
526 } catch (NameNotFoundException e) {
527 Log.e(TAG, "missing package: " + packageName);
528 continue;
529 }
530
531 // Get the version info
532 if (rInfo.serviceInfo.metaData == null) {
533 Log.w(TAG, "Found fused provider without metadata: " + packageName);
534 continue;
535 }
536
537 int version = rInfo.serviceInfo.metaData.getInt(
538 ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
539 if (version == 0) {
540 // This should be the fallback fused location provider.
541
542 // Make sure it's in the system partition.
543 if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
544 if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
545 continue;
546 }
547
548 // Check that the fallback is signed the same as the OS
549 // as a proxy for coreApp="true"
550 if (pm.checkSignatures(systemPackageName, packageName)
551 != PackageManager.SIGNATURE_MATCH) {
552 if (D) Log.d(TAG, "Fallback candidate not signed the same as system: "
553 + packageName);
554 continue;
555 }
556
557 // Found a valid fallback.
558 if (D) Log.d(TAG, "Found fallback provider: " + packageName);
559 return;
560 } else {
561 if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
562 }
563 }
564
565 throw new IllegalStateException("Unable to find a fused location provider that is in the "
566 + "system partition with version 0 and signed with the platform certificate. "
567 + "Such a package is needed to provide a default fused location provider in the "
568 + "event that no other fused location provider has been installed or is currently "
569 + "available. For example, coreOnly boot mode when decrypting the data "
570 + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
571 }
572
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700573 private void loadProvidersLocked() {
Victoria Lease5c24fd02012-10-01 11:00:50 -0700574 // create a passive location provider, which is always enabled
575 PassiveProvider passiveProvider = new PassiveProvider(this);
576 addProviderLocked(passiveProvider);
577 mEnabledProviders.add(passiveProvider.getName());
578 mPassiveProvider = passiveProvider;
579
Lifu Tang30f95a72016-01-07 23:20:38 -0800580 if (GnssLocationProvider.isSupported()) {
Wei Liu5241a4c2015-05-11 14:00:36 -0700581 // Create a gps location provider
Lifu Tang30f95a72016-01-07 23:20:38 -0800582 GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this,
Wei Liu5241a4c2015-05-11 14:00:36 -0700583 mLocationHandler.getLooper());
Lifu Tang9363b942016-02-16 18:07:00 -0800584 mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
Wyatt Rileycf879db2017-01-12 13:57:38 -0800585 mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800586 mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
587 mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
588 addProviderLocked(gnssProvider);
589 mRealProviders.put(LocationManager.GPS_PROVIDER, gnssProvider);
Lifu Tang818aa2c2016-02-01 01:52:00 -0800590 mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
591 mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800592 mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700593 }
594
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700595 /*
596 Load package name(s) containing location provider support.
597 These packages can contain services implementing location providers:
598 Geocoder Provider, Network Location Provider, and
599 Fused Location Provider. They will each be searched for
600 service components implementing these providers.
601 The location framework also has support for installation
602 of new location providers at run-time. The new package does not
603 have to be explicitly listed here, however it must have a signature
604 that matches the signature of at least one package on this list.
605 */
606 Resources resources = mContext.getResources();
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800607 ArrayList<String> providerPackageNames = new ArrayList<>();
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500608 String[] pkgs = resources.getStringArray(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700609 com.android.internal.R.array.config_locationProviderPackageNames);
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500610 if (D) Log.d(TAG, "certificates for location providers pulled from: " +
611 Arrays.toString(pkgs));
612 if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));
613
614 ensureFallbackFusedProviderPresentLocked(providerPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700615
616 // bind to network provider
617 LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
618 mContext,
619 LocationManager.NETWORK_PROVIDER,
620 NETWORK_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700621 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
622 com.android.internal.R.string.config_networkLocationProviderPackageName,
623 com.android.internal.R.array.config_locationProviderPackageNames,
624 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700625 if (networkProvider != null) {
626 mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
627 mProxyProviders.add(networkProvider);
628 addProviderLocked(networkProvider);
629 } else {
630 Slog.w(TAG, "no network location provider found");
631 }
632
633 // bind to fused provider
634 LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind(
635 mContext,
636 LocationManager.FUSED_PROVIDER,
637 FUSED_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700638 com.android.internal.R.bool.config_enableFusedLocationOverlay,
639 com.android.internal.R.string.config_fusedLocationProviderPackageName,
640 com.android.internal.R.array.config_locationProviderPackageNames,
641 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700642 if (fusedLocationProvider != null) {
643 addProviderLocked(fusedLocationProvider);
644 mProxyProviders.add(fusedLocationProvider);
645 mEnabledProviders.add(fusedLocationProvider.getName());
Kenny Rootc3575182012-10-09 12:44:40 -0700646 mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700647 } else {
648 Slog.e(TAG, "no fused location provider found",
649 new IllegalStateException("Location service needs a fused location provider"));
650 }
651
652 // bind to geocoder provider
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700653 mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
654 com.android.internal.R.bool.config_enableGeocoderOverlay,
655 com.android.internal.R.string.config_geocoderProviderPackageName,
656 com.android.internal.R.array.config_locationProviderPackageNames,
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800657 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700658 if (mGeocodeProvider == null) {
659 Slog.e(TAG, "no geocoder provider found");
660 }
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700661
destradaaa4fa3b52014-07-09 10:46:39 -0700662 // bind to fused hardware provider if supported
destradaabeea4422014-07-30 18:17:21 -0700663 // in devices without support, requesting an instance of FlpHardwareProvider will raise an
664 // exception, so make sure we only do that when supported
665 FlpHardwareProvider flpHardwareProvider;
destradaa5ce66d82014-05-28 18:24:08 -0700666 if (FlpHardwareProvider.isSupported()) {
destradaabeea4422014-07-30 18:17:21 -0700667 flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
destradaaf9a274c2014-07-25 15:11:56 -0700668 FusedProxy fusedProxy = FusedProxy.createAndBind(
669 mContext,
670 mLocationHandler,
671 flpHardwareProvider.getLocationHardware(),
672 com.android.internal.R.bool.config_enableHardwareFlpOverlay,
673 com.android.internal.R.string.config_hardwareFlpPackageName,
674 com.android.internal.R.array.config_locationProviderPackageNames);
675 if (fusedProxy == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700676 Slog.d(TAG, "Unable to bind FusedProxy.");
destradaaf9a274c2014-07-25 15:11:56 -0700677 }
destradaacfbdcd22014-04-30 11:29:11 -0700678 } else {
destradaabeea4422014-07-30 18:17:21 -0700679 flpHardwareProvider = null;
destradaa6b4893a2016-05-03 15:33:43 -0700680 Slog.d(TAG, "FLP HAL not supported");
destradaaf9a274c2014-07-25 15:11:56 -0700681 }
682
683 // bind to geofence provider
684 GeofenceProxy provider = GeofenceProxy.createAndBind(
685 mContext,com.android.internal.R.bool.config_enableGeofenceOverlay,
686 com.android.internal.R.string.config_geofenceProviderPackageName,
687 com.android.internal.R.array.config_locationProviderPackageNames,
688 mLocationHandler,
Wei Liu5241a4c2015-05-11 14:00:36 -0700689 mGpsGeofenceProxy,
destradaabeea4422014-07-30 18:17:21 -0700690 flpHardwareProvider != null ? flpHardwareProvider.getGeofenceHardware() : null);
destradaaf9a274c2014-07-25 15:11:56 -0700691 if (provider == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700692 Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
destradaa0682809a2013-08-12 18:50:30 -0700693 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900694
destradaa6e2fe752015-06-23 17:25:53 -0700695 // bind to hardware activity recognition
696 boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
697 ActivityRecognitionHardware activityRecognitionHardware = null;
698 if (activityRecognitionHardwareIsSupported) {
699 activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
destradaaa4fa3b52014-07-09 10:46:39 -0700700 } else {
destradaa6b4893a2016-05-03 15:33:43 -0700701 Slog.d(TAG, "Hardware Activity-Recognition not supported.");
destradaaa4fa3b52014-07-09 10:46:39 -0700702 }
destradaa6e2fe752015-06-23 17:25:53 -0700703 ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
704 mContext,
705 mLocationHandler,
706 activityRecognitionHardwareIsSupported,
707 activityRecognitionHardware,
708 com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
709 com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
710 com.android.internal.R.array.config_locationProviderPackageNames);
711 if (proxy == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700712 Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
destradaa6e2fe752015-06-23 17:25:53 -0700713 }
destradaaa4fa3b52014-07-09 10:46:39 -0700714
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900715 String[] testProviderStrings = resources.getStringArray(
716 com.android.internal.R.array.config_testLocationProviders);
717 for (String testProviderString : testProviderStrings) {
718 String fragments[] = testProviderString.split(",");
719 String name = fragments[0].trim();
720 if (mProvidersByName.get(name) != null) {
721 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
722 }
723 ProviderProperties properties = new ProviderProperties(
724 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
725 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
726 Boolean.parseBoolean(fragments[3]) /* requiresCell */,
727 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
728 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
729 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
730 Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
731 Integer.parseInt(fragments[8]) /* powerRequirement */,
732 Integer.parseInt(fragments[9]) /* accuracy */);
733 addTestProviderLocked(name, properties);
734 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700735 }
Mike Lockwood9637d472009-04-02 21:41:57 -0700736
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800737 /**
Victoria Lease38389b62012-09-30 11:44:22 -0700738 * Called when the device's active user changes.
739 * @param userId the new active user's UserId
740 */
741 private void switchUser(int userId) {
Jianzheng Zhoud5c69462013-10-10 14:02:09 +0800742 if (mCurrentUserId == userId) {
743 return;
744 }
Victoria Lease83762d22012-10-03 13:51:17 -0700745 mBlacklist.switchUser(userId);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800746 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED);
Victoria Lease38389b62012-09-30 11:44:22 -0700747 synchronized (mLock) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700748 mLastLocation.clear();
David Christie1b9b7b12013-04-15 15:31:11 -0700749 mLastLocationCoarseInterval.clear();
Victoria Leaseb711d572012-10-02 13:14:11 -0700750 for (LocationProviderInterface p : mProviders) {
Amith Yamasanib27528d2014-06-05 15:02:10 -0700751 updateProviderListenersLocked(p.getName(), false);
Victoria Leaseb711d572012-10-02 13:14:11 -0700752 }
Victoria Lease38389b62012-09-30 11:44:22 -0700753 mCurrentUserId = userId;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700754 updateUserProfiles(userId);
Victoria Leaseb711d572012-10-02 13:14:11 -0700755 updateProvidersLocked();
Victoria Lease38389b62012-09-30 11:44:22 -0700756 }
757 }
758
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800759 private static final class Identity {
760 final int mUid;
761 final int mPid;
762 final String mPackageName;
763
764 Identity(int uid, int pid, String packageName) {
765 mUid = uid;
766 mPid = pid;
767 mPackageName = packageName;
768 }
769 }
770
Victoria Lease38389b62012-09-30 11:44:22 -0700771 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 * A wrapper class holding either an ILocationListener or a PendingIntent to receive
773 * location updates.
774 */
Mike Lockwood48f17512009-04-23 09:12:08 -0700775 private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800776 final Identity mIdentity;
Victoria Lease37425c32012-10-16 16:08:48 -0700777 final int mAllowedResolutionLevel; // resolution level allowed to receiver
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779 final ILocationListener mListener;
780 final PendingIntent mPendingIntent;
David Christie82edc9b2013-07-19 11:31:42 -0700781 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
David Christie40e57822013-07-30 11:36:48 -0700782 final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800783 final Object mKey;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700784
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800785 final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<>();
Nick Pellyf1be6862012-05-15 10:53:42 -0700786
David Christie0b837452013-07-29 16:02:13 -0700787 // True if app ops has started monitoring this receiver for locations.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700788 boolean mOpMonitoring;
David Christie0b837452013-07-29 16:02:13 -0700789 // True if app ops has started monitoring this receiver for high power (gps) locations.
790 boolean mOpHighPowerMonitoring;
Mike Lockwood48f17512009-04-23 09:12:08 -0700791 int mPendingBroadcasts;
Victoria Lease0aa28602013-05-29 15:28:26 -0700792 PowerManager.WakeLock mWakeLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800793
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700794 Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -0700795 String packageName, WorkSource workSource, boolean hideFromAppOps) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796 mListener = listener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 mPendingIntent = intent;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700798 if (listener != null) {
799 mKey = listener.asBinder();
800 } else {
801 mKey = intent;
802 }
Victoria Lease37425c32012-10-16 16:08:48 -0700803 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800804 mIdentity = new Identity(uid, pid, packageName);
David Christie82edc9b2013-07-19 11:31:42 -0700805 if (workSource != null && workSource.size() <= 0) {
806 workSource = null;
807 }
808 mWorkSource = workSource;
David Christie40e57822013-07-30 11:36:48 -0700809 mHideFromAppOps = hideFromAppOps;
Victoria Lease0aa28602013-05-29 15:28:26 -0700810
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700811 updateMonitoring(true);
812
Victoria Lease0aa28602013-05-29 15:28:26 -0700813 // construct/configure wakelock
814 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
David Christie82edc9b2013-07-19 11:31:42 -0700815 if (workSource == null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800816 workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -0700817 }
818 mWakeLock.setWorkSource(workSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 }
820
821 @Override
822 public boolean equals(Object otherObj) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800823 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800824 }
825
826 @Override
827 public int hashCode() {
828 return mKey.hashCode();
829 }
Mike Lockwood3681f262009-05-12 10:52:03 -0400830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800831 @Override
832 public String toString() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700833 StringBuilder s = new StringBuilder();
834 s.append("Reciever[");
835 s.append(Integer.toHexString(System.identityHashCode(this)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836 if (mListener != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700837 s.append(" listener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800838 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700839 s.append(" intent");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700841 for (String p : mUpdateRecords.keySet()) {
842 s.append(" ").append(mUpdateRecords.get(p).toString());
843 }
844 s.append("]");
845 return s.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846 }
847
David Christie15b31912013-08-13 15:54:32 -0700848 /**
849 * Update AppOp monitoring for this receiver.
850 *
851 * @param allow If true receiver is currently active, if false it's been removed.
852 */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700853 public void updateMonitoring(boolean allow) {
David Christie40e57822013-07-30 11:36:48 -0700854 if (mHideFromAppOps) {
855 return;
856 }
857
David Christie15b31912013-08-13 15:54:32 -0700858 boolean requestingLocation = false;
859 boolean requestingHighPowerLocation = false;
860 if (allow) {
861 // See if receiver has any enabled update records. Also note if any update records
862 // are high power (has a high power provider with an interval under a threshold).
863 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
864 if (isAllowedByCurrentUserSettingsLocked(updateRecord.mProvider)) {
865 requestingLocation = true;
866 LocationProviderInterface locationProvider
David Christie2ff96af2014-01-30 16:09:37 -0800867 = mProvidersByName.get(updateRecord.mProvider);
David Christie15b31912013-08-13 15:54:32 -0700868 ProviderProperties properties = locationProvider != null
869 ? locationProvider.getProperties() : null;
870 if (properties != null
871 && properties.mPowerRequirement == Criteria.POWER_HIGH
872 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
873 requestingHighPowerLocation = true;
874 break;
875 }
876 }
877 }
878 }
879
David Christie0b837452013-07-29 16:02:13 -0700880 // First update monitoring of any location request (including high power).
David Christie15b31912013-08-13 15:54:32 -0700881 mOpMonitoring = updateMonitoring(
882 requestingLocation,
883 mOpMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700884 AppOpsManager.OP_MONITOR_LOCATION);
885
886 // Now update monitoring of high power requests only.
David Christiec750c1f2013-08-08 12:56:57 -0700887 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
David Christie15b31912013-08-13 15:54:32 -0700888 mOpHighPowerMonitoring = updateMonitoring(
889 requestingHighPowerLocation,
890 mOpHighPowerMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700891 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
David Christiec750c1f2013-08-08 12:56:57 -0700892 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
David Christie15b31912013-08-13 15:54:32 -0700893 // Send an intent to notify that a high power request has been added/removed.
David Christiec750c1f2013-08-08 12:56:57 -0700894 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
895 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
896 }
David Christie0b837452013-07-29 16:02:13 -0700897 }
898
899 /**
900 * Update AppOps monitoring for a single location request and op type.
901 *
902 * @param allowMonitoring True if monitoring is allowed for this request/op.
903 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
904 * @param op AppOps code for the op to update.
905 * @return True if monitoring is on for this request/op after updating.
906 */
907 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
908 int op) {
909 if (!currentlyMonitoring) {
910 if (allowMonitoring) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800911 return mAppOps.startOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700912 == AppOpsManager.MODE_ALLOWED;
913 }
914 } else {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800915 if (!allowMonitoring
916 || mAppOps.checkOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700917 != AppOpsManager.MODE_ALLOWED) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800918 mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName);
David Christie0b837452013-07-29 16:02:13 -0700919 return false;
920 }
921 }
922
923 return currentlyMonitoring;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700924 }
925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926 public boolean isListener() {
927 return mListener != null;
928 }
929
930 public boolean isPendingIntent() {
931 return mPendingIntent != null;
932 }
933
934 public ILocationListener getListener() {
935 if (mListener != null) {
936 return mListener;
937 }
938 throw new IllegalStateException("Request for non-existent listener");
939 }
940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
942 if (mListener != null) {
943 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700944 synchronized (this) {
945 // synchronize to ensure incrementPendingBroadcastsLocked()
946 // is called before decrementPendingBroadcasts()
947 mListener.onStatusChanged(provider, status, extras);
Nick Pellye0fd6932012-07-11 10:26:13 -0700948 // call this after broadcasting so we do not increment
949 // if we throw an exeption.
950 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -0700951 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800952 } catch (RemoteException e) {
953 return false;
954 }
955 } else {
956 Intent statusChanged = new Intent();
Victoria Lease61ecb022012-11-13 15:12:51 -0800957 statusChanged.putExtras(new Bundle(extras));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800958 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
959 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700960 synchronized (this) {
961 // synchronize to ensure incrementPendingBroadcastsLocked()
962 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700963 mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -0700964 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -0700965 // call this after broadcasting so we do not increment
966 // if we throw an exeption.
967 incrementPendingBroadcastsLocked();
968 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800969 } catch (PendingIntent.CanceledException e) {
970 return false;
971 }
972 }
973 return true;
974 }
975
976 public boolean callLocationChangedLocked(Location location) {
977 if (mListener != null) {
978 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700979 synchronized (this) {
980 // synchronize to ensure incrementPendingBroadcastsLocked()
981 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c5406a2012-11-29 16:18:01 -0800982 mListener.onLocationChanged(new Location(location));
Nick Pellye0fd6932012-07-11 10:26:13 -0700983 // call this after broadcasting so we do not increment
984 // if we throw an exeption.
985 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -0700986 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 } catch (RemoteException e) {
988 return false;
989 }
990 } else {
991 Intent locationChanged = new Intent();
Victoria Lease61ecb022012-11-13 15:12:51 -0800992 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, new Location(location));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700994 synchronized (this) {
995 // synchronize to ensure incrementPendingBroadcastsLocked()
996 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700997 mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -0700998 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -0700999 // call this after broadcasting so we do not increment
1000 // if we throw an exeption.
1001 incrementPendingBroadcastsLocked();
1002 }
1003 } catch (PendingIntent.CanceledException e) {
1004 return false;
1005 }
1006 }
1007 return true;
1008 }
1009
1010 public boolean callProviderEnabledLocked(String provider, boolean enabled) {
David Christie15b31912013-08-13 15:54:32 -07001011 // First update AppOp monitoring.
1012 // An app may get/lose location access as providers are enabled/disabled.
1013 updateMonitoring(true);
1014
Mike Lockwood48f17512009-04-23 09:12:08 -07001015 if (mListener != null) {
1016 try {
1017 synchronized (this) {
1018 // synchronize to ensure incrementPendingBroadcastsLocked()
1019 // is called before decrementPendingBroadcasts()
1020 if (enabled) {
1021 mListener.onProviderEnabled(provider);
1022 } else {
1023 mListener.onProviderDisabled(provider);
1024 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001025 // call this after broadcasting so we do not increment
1026 // if we throw an exeption.
1027 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001028 }
1029 } catch (RemoteException e) {
1030 return false;
1031 }
1032 } else {
1033 Intent providerIntent = new Intent();
1034 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1035 try {
1036 synchronized (this) {
1037 // synchronize to ensure incrementPendingBroadcastsLocked()
1038 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001039 mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -07001040 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -07001041 // call this after broadcasting so we do not increment
1042 // if we throw an exeption.
1043 incrementPendingBroadcastsLocked();
1044 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001045 } catch (PendingIntent.CanceledException e) {
1046 return false;
1047 }
1048 }
1049 return true;
1050 }
1051
Nick Pellyf1be6862012-05-15 10:53:42 -07001052 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001053 public void binderDied() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001054 if (D) Log.d(TAG, "Location listener died");
1055
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001056 synchronized (mLock) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057 removeUpdatesLocked(this);
1058 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001059 synchronized (this) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001060 clearPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001061 }
1062 }
1063
Nick Pellye0fd6932012-07-11 10:26:13 -07001064 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001065 public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1066 int resultCode, String resultData, Bundle resultExtras) {
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001067 synchronized (this) {
1068 decrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001069 }
1070 }
1071
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001072 // this must be called while synchronized by caller in a synchronized block
1073 // containing the sending of the broadcaset
1074 private void incrementPendingBroadcastsLocked() {
1075 if (mPendingBroadcasts++ == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001076 mWakeLock.acquire();
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001077 }
1078 }
1079
1080 private void decrementPendingBroadcastsLocked() {
1081 if (--mPendingBroadcasts == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001082 if (mWakeLock.isHeld()) {
1083 mWakeLock.release();
1084 }
1085 }
1086 }
1087
1088 public void clearPendingBroadcastsLocked() {
1089 if (mPendingBroadcasts > 0) {
1090 mPendingBroadcasts = 0;
1091 if (mWakeLock.isHeld()) {
1092 mWakeLock.release();
1093 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001094 }
1095 }
1096 }
1097
Nick Pellye0fd6932012-07-11 10:26:13 -07001098 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001099 public void locationCallbackFinished(ILocationListener listener) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001100 //Do not use getReceiverLocked here as that will add the ILocationListener to
Joshua Bartel080b61b2009-10-05 12:44:46 -04001101 //the receiver list if it is not found. If it is not found then the
1102 //LocationListener was removed when it had a pending broadcast and should
1103 //not be added back.
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001104 synchronized (mLock) {
1105 IBinder binder = listener.asBinder();
1106 Receiver receiver = mReceivers.get(binder);
1107 if (receiver != null) {
1108 synchronized (receiver) {
1109 // so wakelock calls will succeed
1110 long identity = Binder.clearCallingIdentity();
1111 receiver.decrementPendingBroadcastsLocked();
1112 Binder.restoreCallingIdentity(identity);
David Christie2ff96af2014-01-30 16:09:37 -08001113 }
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001114 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 }
1116 }
1117
Lifu Tang82f893d2016-01-21 18:15:33 -08001118 /**
Lifu Tang9363b942016-02-16 18:07:00 -08001119 * Returns the system information of the GNSS hardware.
Lifu Tang82f893d2016-01-21 18:15:33 -08001120 */
1121 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001122 public int getGnssYearOfHardware() {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001123 if (mGnssSystemInfoProvider != null) {
Lifu Tang9363b942016-02-16 18:07:00 -08001124 return mGnssSystemInfoProvider.getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001125 } else {
1126 return 0;
1127 }
1128 }
1129
Wyatt Rileycf879db2017-01-12 13:57:38 -08001130 /**
1131 * Runs some checks for GNSS (FINE) level permissions, used by several methods which directly
1132 * (try to) access GNSS information at this layer.
1133 */
1134 private boolean hasGnssPermissions(String packageName) {
1135 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
1136 checkResolutionLevelIsSufficientForProviderUse(
1137 allowedResolutionLevel,
1138 LocationManager.GPS_PROVIDER);
1139
1140 int pid = Binder.getCallingPid();
1141 int uid = Binder.getCallingUid();
1142 long identity = Binder.clearCallingIdentity();
1143 boolean hasLocationAccess;
1144 try {
1145 hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
1146 } finally {
1147 Binder.restoreCallingIdentity(identity);
1148 }
1149
1150 return hasLocationAccess;
1151 }
1152
1153 /**
1154 * Returns the GNSS batching size, if available.
1155 */
1156 @Override
1157 public int getGnssBatchSize(String packageName) {
1158 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1159 "Location Hardware permission not granted to access hardware batching");
1160
1161 if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
1162 return mGnssBatchingProvider.getSize();
1163 } else {
1164 return 0;
1165 }
1166 }
1167
1168 /**
1169 * Adds a callback for GNSS Batching events, if permissions allow, which are transported
1170 * to potentially multiple listeners by the BatchedLocationCallbackTransport above this.
1171 */
1172 @Override
1173 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) {
1174 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1175 "Location Hardware permission not granted to access hardware batching");
1176
1177 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1178 return false;
1179 }
1180
1181 mGnssBatchingCallback = callback;
1182 mGnssBatchingDeathCallback = new LinkedCallback(callback);
1183 try {
1184 callback.asBinder().linkToDeath(mGnssBatchingDeathCallback, 0 /* flags */);
1185 } catch (RemoteException e) {
1186 // if the remote process registering the listener is already dead, just swallow the
1187 // exception and return
1188 Log.e(TAG, "Remote listener already died.", e);
1189 return false;
1190 }
1191
1192 return true;
1193 }
1194
1195 private class LinkedCallback implements IBinder.DeathRecipient {
1196 private final IBatchedLocationCallback mCallback;
1197
1198 public LinkedCallback(@NonNull IBatchedLocationCallback callback) {
1199 mCallback = callback;
1200 }
1201
1202 @NonNull
1203 public IBatchedLocationCallback getUnderlyingListener() {
1204 return mCallback;
1205 }
1206
1207 @Override
1208 public void binderDied() {
1209 Log.d(TAG, "Remote Batching Callback died: " + mCallback);
1210 stopGnssBatch();
1211 removeGnssBatchingCallback();
1212 }
1213 }
1214
1215 /**
1216 * Removes callback for GNSS batching
1217 */
1218 @Override
1219 public void removeGnssBatchingCallback() {
1220 try {
1221 mGnssBatchingCallback.asBinder().unlinkToDeath(mGnssBatchingDeathCallback,
1222 0 /* flags */);
1223 } catch (NoSuchElementException e) {
1224 // if the death callback isn't connected (it should be...), log error, swallow the
1225 // exception and return
1226 Log.e(TAG, "Couldn't unlink death callback.", e);
1227 }
1228 mGnssBatchingCallback = null;
1229 mGnssBatchingDeathCallback = null;
1230 }
1231
1232
1233 /**
1234 * Starts GNSS batching, if available.
1235 */
1236 @Override
1237 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
1238 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1239 "Location Hardware permission not granted to access hardware batching");
1240
1241 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1242 return false;
1243 }
1244
1245 if (mGnssBatchingInProgress) {
1246 // Current design does not expect multiple starts to be called repeatedly
1247 Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch");
1248 // Try to clean up anyway, and continue
1249 stopGnssBatch();
1250 }
1251
1252 mGnssBatchingInProgress = true;
1253 return mGnssBatchingProvider.start(periodNanos, wakeOnFifoFull);
1254 }
1255
1256 /**
1257 * Flushes a GNSS batch in progress
1258 */
1259 @Override
1260 public void flushGnssBatch(String packageName) {
1261 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1262 "Location Hardware permission not granted to access hardware batching");
1263
1264 if (!hasGnssPermissions(packageName)) {
1265 Log.e(TAG, "flushGnssBatch called without GNSS permissions");
1266 return;
1267 }
1268
1269 if (!mGnssBatchingInProgress) {
1270 Log.w(TAG, "flushGnssBatch called with no batch in progress");
1271 }
1272
1273 if (mGnssBatchingProvider != null) {
1274 mGnssBatchingProvider.flush();
1275 }
1276 }
1277
1278 /**
1279 * Stops GNSS batching
1280 */
1281 @Override
1282 public boolean stopGnssBatch() {
1283 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1284 "Location Hardware permission not granted to access hardware batching");
1285
1286 if (mGnssBatchingProvider != null) {
1287 mGnssBatchingInProgress = false;
1288 return mGnssBatchingProvider.stop();
1289 } else {
1290 return false;
1291 }
1292 }
1293
1294 @Override
1295 public void reportLocationBatch(List<Location> locations) {
1296 checkCallerIsProvider();
1297
1298 // Currently used only for GNSS locations - update permissions check if changed
1299 if (isAllowedByCurrentUserSettingsLocked(LocationManager.GPS_PROVIDER)) {
1300 if (mGnssBatchingCallback == null) {
1301 Slog.e(TAG, "reportLocationBatch() called without active Callback");
1302 return;
1303 }
1304 try {
1305 mGnssBatchingCallback.onLocationBatch(locations);
1306 } catch (RemoteException e) {
1307 Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e);
1308 }
1309 } else {
1310 Slog.w(TAG, "reportLocationBatch() called without user permission, locations blocked");
1311 }
1312 }
1313
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001314 private void addProviderLocked(LocationProviderInterface provider) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001315 mProviders.add(provider);
1316 mProvidersByName.put(provider.getName(), provider);
1317 }
1318
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001319 private void removeProviderLocked(LocationProviderInterface provider) {
1320 provider.disable();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001321 mProviders.remove(provider);
1322 mProvidersByName.remove(provider.getName());
1323 }
1324
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001325 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001326 * Returns "true" if access to the specified location provider is allowed by the current
1327 * user's settings. Access to all location providers is forbidden to non-location-provider
1328 * processes belonging to background users.
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001329 *
1330 * @param provider the name of the location provider
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001331 */
Victoria Lease09eeaec2013-02-05 11:34:13 -08001332 private boolean isAllowedByCurrentUserSettingsLocked(String provider) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001333 if (mEnabledProviders.contains(provider)) {
1334 return true;
1335 }
1336 if (mDisabledProviders.contains(provider)) {
1337 return false;
1338 }
1339 // Use system settings
1340 ContentResolver resolver = mContext.getContentResolver();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001341
Victoria Leaseb711d572012-10-02 13:14:11 -07001342 return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001343 }
1344
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001345 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001346 * Returns "true" if access to the specified location provider is allowed by the specified
1347 * user's settings. Access to all location providers is forbidden to non-location-provider
1348 * processes belonging to background users.
1349 *
1350 * @param provider the name of the location provider
1351 * @param uid the requestor's UID
Victoria Lease09eeaec2013-02-05 11:34:13 -08001352 */
1353 private boolean isAllowedByUserSettingsLocked(String provider, int uid) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001354 if (!isCurrentProfile(UserHandle.getUserId(uid)) && !isUidALocationProvider(uid)) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08001355 return false;
1356 }
1357 return isAllowedByCurrentUserSettingsLocked(provider);
1358 }
1359
1360 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001361 * Returns the permission string associated with the specified resolution level.
1362 *
1363 * @param resolutionLevel the resolution level
1364 * @return the permission string
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001365 */
Victoria Lease37425c32012-10-16 16:08:48 -07001366 private String getResolutionPermission(int resolutionLevel) {
1367 switch (resolutionLevel) {
1368 case RESOLUTION_LEVEL_FINE:
1369 return android.Manifest.permission.ACCESS_FINE_LOCATION;
1370 case RESOLUTION_LEVEL_COARSE:
1371 return android.Manifest.permission.ACCESS_COARSE_LOCATION;
1372 default:
1373 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001374 }
Victoria Leaseda479c52012-10-15 15:24:16 -07001375 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001376
Victoria Leaseda479c52012-10-15 15:24:16 -07001377 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001378 * Returns the resolution level allowed to the given PID/UID pair.
1379 *
1380 * @param pid the PID
1381 * @param uid the UID
1382 * @return resolution level allowed to the pid/uid pair
Victoria Leaseda479c52012-10-15 15:24:16 -07001383 */
Victoria Lease37425c32012-10-16 16:08:48 -07001384 private int getAllowedResolutionLevel(int pid, int uid) {
1385 if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
1386 pid, uid) == PackageManager.PERMISSION_GRANTED) {
1387 return RESOLUTION_LEVEL_FINE;
1388 } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
1389 pid, uid) == PackageManager.PERMISSION_GRANTED) {
1390 return RESOLUTION_LEVEL_COARSE;
1391 } else {
1392 return RESOLUTION_LEVEL_NONE;
Victoria Leaseda479c52012-10-15 15:24:16 -07001393 }
Victoria Lease4fab68b2012-09-13 13:20:59 -07001394 }
1395
1396 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001397 * Returns the resolution level allowed to the caller
1398 *
1399 * @return resolution level allowed to caller
Victoria Lease4fab68b2012-09-13 13:20:59 -07001400 */
Victoria Lease37425c32012-10-16 16:08:48 -07001401 private int getCallerAllowedResolutionLevel() {
1402 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
1403 }
1404
1405 /**
1406 * Throw SecurityException if specified resolution level is insufficient to use geofences.
1407 *
1408 * @param allowedResolutionLevel resolution level allowed to caller
1409 */
1410 private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
1411 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Lease4fab68b2012-09-13 13:20:59 -07001412 throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
1413 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001414 }
1415
Victoria Lease37425c32012-10-16 16:08:48 -07001416 /**
1417 * Return the minimum resolution level required to use the specified location provider.
1418 *
1419 * @param provider the name of the location provider
1420 * @return minimum resolution level required for provider
1421 */
1422 private int getMinimumResolutionLevelForProviderUse(String provider) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001423 if (LocationManager.GPS_PROVIDER.equals(provider) ||
1424 LocationManager.PASSIVE_PROVIDER.equals(provider)) {
1425 // gps and passive providers require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001426 return RESOLUTION_LEVEL_FINE;
Victoria Lease8dbb6342012-09-21 16:55:53 -07001427 } else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
1428 LocationManager.FUSED_PROVIDER.equals(provider)) {
1429 // network and fused providers are ok with COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001430 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001431 } else {
1432 // mock providers
1433 LocationProviderInterface lp = mMockProviders.get(provider);
1434 if (lp != null) {
1435 ProviderProperties properties = lp.getProperties();
1436 if (properties != null) {
1437 if (properties.mRequiresSatellite) {
1438 // provider requiring satellites require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001439 return RESOLUTION_LEVEL_FINE;
Laurent Tu941221c2012-10-04 14:21:52 -07001440 } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
1441 // provider requiring network and or cell require COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001442 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001443 }
1444 }
1445 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001446 }
Victoria Lease37425c32012-10-16 16:08:48 -07001447 return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
Victoria Leaseda479c52012-10-15 15:24:16 -07001448 }
1449
Victoria Lease37425c32012-10-16 16:08:48 -07001450 /**
1451 * Throw SecurityException if specified resolution level is insufficient to use the named
1452 * location provider.
1453 *
1454 * @param allowedResolutionLevel resolution level allowed to caller
1455 * @param providerName the name of the location provider
1456 */
1457 private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel,
1458 String providerName) {
1459 int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName);
1460 if (allowedResolutionLevel < requiredResolutionLevel) {
1461 switch (requiredResolutionLevel) {
1462 case RESOLUTION_LEVEL_FINE:
1463 throw new SecurityException("\"" + providerName + "\" location provider " +
1464 "requires ACCESS_FINE_LOCATION permission.");
1465 case RESOLUTION_LEVEL_COARSE:
1466 throw new SecurityException("\"" + providerName + "\" location provider " +
1467 "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
1468 default:
1469 throw new SecurityException("Insufficient permission for \"" + providerName +
1470 "\" location provider.");
Victoria Leaseda479c52012-10-15 15:24:16 -07001471 }
1472 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001473 }
1474
David Christie82edc9b2013-07-19 11:31:42 -07001475 /**
1476 * Throw SecurityException if WorkSource use is not allowed (i.e. can't blame other packages
1477 * for battery).
1478 */
David Christie40e57822013-07-30 11:36:48 -07001479 private void checkDeviceStatsAllowed() {
David Christie82edc9b2013-07-19 11:31:42 -07001480 mContext.enforceCallingOrSelfPermission(
1481 android.Manifest.permission.UPDATE_DEVICE_STATS, null);
1482 }
1483
David Christie40e57822013-07-30 11:36:48 -07001484 private void checkUpdateAppOpsAllowed() {
1485 mContext.enforceCallingOrSelfPermission(
1486 android.Manifest.permission.UPDATE_APP_OPS_STATS, null);
1487 }
1488
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001489 public static int resolutionLevelToOp(int allowedResolutionLevel) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001490 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
1491 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001492 return AppOpsManager.OP_COARSE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001493 } else {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001494 return AppOpsManager.OP_FINE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001495 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001496 }
1497 return -1;
1498 }
1499
David Christieb870dbf2015-06-22 12:42:53 -07001500 boolean reportLocationAccessNoThrow(
1501 int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001502 int op = resolutionLevelToOp(allowedResolutionLevel);
1503 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001504 if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1505 return false;
1506 }
1507 }
David Christieb870dbf2015-06-22 12:42:53 -07001508
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001509 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001510 }
1511
David Christieb870dbf2015-06-22 12:42:53 -07001512 boolean checkLocationAccess(int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001513 int op = resolutionLevelToOp(allowedResolutionLevel);
1514 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001515 if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1516 return false;
1517 }
1518 }
David Christieb870dbf2015-06-22 12:42:53 -07001519
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001520 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001521 }
1522
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001523 /**
1524 * Returns all providers by name, including passive, but excluding
Laurent Tu0d21e212012-10-02 15:33:48 -07001525 * fused, also including ones that are not permitted to
1526 * be accessed by the calling activity or are currently disabled.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001527 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001528 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001529 public List<String> getAllProviders() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001530 ArrayList<String> out;
1531 synchronized (mLock) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001532 out = new ArrayList<>(mProviders.size());
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001533 for (LocationProviderInterface provider : mProviders) {
1534 String name = provider.getName();
1535 if (LocationManager.FUSED_PROVIDER.equals(name)) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07001536 continue;
1537 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 out.add(name);
1539 }
1540 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001541
1542 if (D) Log.d(TAG, "getAllProviders()=" + out);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543 return out;
1544 }
1545
Mike Lockwood03ca2162010-04-01 08:10:09 -07001546 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001547 * Return all providers by name, that match criteria and are optionally
1548 * enabled.
1549 * Can return passive provider, but never returns fused provider.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001550 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001551 @Override
1552 public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
Victoria Lease37425c32012-10-16 16:08:48 -07001553 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001554 ArrayList<String> out;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001555 int uid = Binder.getCallingUid();
Victoria Lease269518e2012-10-29 08:25:39 -07001556 long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07001557 try {
1558 synchronized (mLock) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001559 out = new ArrayList<>(mProviders.size());
Victoria Leaseb711d572012-10-02 13:14:11 -07001560 for (LocationProviderInterface provider : mProviders) {
1561 String name = provider.getName();
1562 if (LocationManager.FUSED_PROVIDER.equals(name)) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001563 continue;
1564 }
Victoria Lease37425c32012-10-16 16:08:48 -07001565 if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08001566 if (enabledOnly && !isAllowedByUserSettingsLocked(name, uid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001567 continue;
1568 }
1569 if (criteria != null && !LocationProvider.propertiesMeetCriteria(
1570 name, provider.getProperties(), criteria)) {
1571 continue;
1572 }
1573 out.add(name);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001574 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001575 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001576 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001577 } finally {
1578 Binder.restoreCallingIdentity(identity);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001579 }
1580
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001581 if (D) Log.d(TAG, "getProviders()=" + out);
1582 return out;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001583 }
1584
1585 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001586 * Return the name of the best provider given a Criteria object.
1587 * This method has been deprecated from the public API,
Victoria Lease8dbb6342012-09-21 16:55:53 -07001588 * and the whole LocationProvider (including #meetsCriteria)
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001589 * has been deprecated as well. So this method now uses
1590 * some simplified logic.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001591 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001592 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001593 public String getBestProvider(Criteria criteria, boolean enabledOnly) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001594 String result = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001595
1596 List<String> providers = getProviders(criteria, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001597 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001598 result = pickBest(providers);
1599 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1600 return result;
1601 }
1602 providers = getProviders(null, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001603 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001604 result = pickBest(providers);
1605 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1606 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001607 }
1608
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001609 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001610 return null;
1611 }
1612
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001613 private String pickBest(List<String> providers) {
Victoria Lease1925e292012-09-24 17:00:18 -07001614 if (providers.contains(LocationManager.GPS_PROVIDER)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001615 return LocationManager.GPS_PROVIDER;
Victoria Lease1925e292012-09-24 17:00:18 -07001616 } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
1617 return LocationManager.NETWORK_PROVIDER;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001618 } else {
1619 return providers.get(0);
1620 }
1621 }
1622
Nick Pellye0fd6932012-07-11 10:26:13 -07001623 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001624 public boolean providerMeetsCriteria(String provider, Criteria criteria) {
1625 LocationProviderInterface p = mProvidersByName.get(provider);
1626 if (p == null) {
1627 throw new IllegalArgumentException("provider=" + provider);
1628 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001629
1630 boolean result = LocationProvider.propertiesMeetCriteria(
1631 p.getName(), p.getProperties(), criteria);
1632 if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result);
1633 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001634 }
1635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 private void updateProvidersLocked() {
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001637 boolean changesMade = false;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001638 for (int i = mProviders.size() - 1; i >= 0; i--) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001639 LocationProviderInterface p = mProviders.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001640 boolean isEnabled = p.isEnabled();
1641 String name = p.getName();
Victoria Lease09eeaec2013-02-05 11:34:13 -08001642 boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 if (isEnabled && !shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001644 updateProviderListenersLocked(name, false);
David Christieb084fef2013-12-18 14:33:57 -08001645 // If any provider has been disabled, clear all last locations for all providers.
1646 // This is to be on the safe side in case a provider has location derived from
1647 // this disabled provider.
1648 mLastLocation.clear();
1649 mLastLocationCoarseInterval.clear();
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001650 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001651 } else if (!isEnabled && shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001652 updateProviderListenersLocked(name, true);
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001653 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001654 }
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001655 }
1656 if (changesMade) {
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001657 mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
1658 UserHandle.ALL);
Tom O'Neill40a86c22013-09-03 18:05:13 -07001659 mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
1660 UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001661 }
1662 }
1663
Amith Yamasanib27528d2014-06-05 15:02:10 -07001664 private void updateProviderListenersLocked(String provider, boolean enabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001665 int listeners = 0;
1666
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001667 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001668 if (p == null) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001669
1670 ArrayList<Receiver> deadReceivers = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07001671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001672 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1673 if (records != null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001674 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001675 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001676 // Sends a notification message to the receiver
1677 if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
1678 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001679 deadReceivers = new ArrayList<>();
Victoria Leaseb711d572012-10-02 13:14:11 -07001680 }
1681 deadReceivers.add(record.mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001683 listeners++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 }
1686 }
1687
1688 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001689 for (int i = deadReceivers.size() - 1; i >= 0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690 removeUpdatesLocked(deadReceivers.get(i));
1691 }
1692 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001693
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001694 if (enabled) {
1695 p.enable();
1696 if (listeners > 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001697 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001698 }
1699 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001700 p.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 }
1703
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001704 private void applyRequirementsLocked(String provider) {
1705 LocationProviderInterface p = mProvidersByName.get(provider);
1706 if (p == null) return;
1707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001709 WorkSource worksource = new WorkSource();
1710 ProviderRequest providerRequest = new ProviderRequest();
1711
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001712 ContentResolver resolver = mContext.getContentResolver();
1713 long backgroundThrottleInterval = Settings.Global.getLong(
1714 resolver,
1715 Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
1716 DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
1717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001718 if (records != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001719 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001720 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
David Christieb870dbf2015-06-22 12:42:53 -07001721 if (checkLocationAccess(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001722 record.mReceiver.mIdentity.mPid,
1723 record.mReceiver.mIdentity.mUid,
1724 record.mReceiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001725 record.mReceiver.mAllowedResolutionLevel)) {
1726 LocationRequest locationRequest = record.mRequest;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001727 long interval = locationRequest.getInterval();
1728
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001729 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001730 if (!record.mIsForegroundUid) {
1731 interval = Math.max(interval, backgroundThrottleInterval);
1732 }
1733 if (interval != locationRequest.getInterval()) {
1734 locationRequest = new LocationRequest(locationRequest);
1735 locationRequest.setInterval(interval);
1736 }
1737 }
1738
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001739 providerRequest.locationRequests.add(locationRequest);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001740 if (interval < providerRequest.interval) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001741 providerRequest.reportLocation = true;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001742 providerRequest.interval = interval;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001743 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001744 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001745 }
1746 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001747
1748 if (providerRequest.reportLocation) {
1749 // calculate who to blame for power
1750 // This is somewhat arbitrary. We pick a threshold interval
1751 // that is slightly higher that the minimum interval, and
1752 // spread the blame across all applications with a request
1753 // under that threshold.
1754 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
1755 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001756 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001757 LocationRequest locationRequest = record.mRequest;
Svet Ganove998c732016-06-10 00:12:38 -07001758
1759 // Don't assign battery blame for update records whose
1760 // client has no permission to receive location data.
1761 if (!providerRequest.locationRequests.contains(locationRequest)) {
1762 continue;
1763 }
1764
Victoria Leaseb711d572012-10-02 13:14:11 -07001765 if (locationRequest.getInterval() <= thresholdInterval) {
David Christiee55c9682013-08-22 10:10:34 -07001766 if (record.mReceiver.mWorkSource != null
1767 && record.mReceiver.mWorkSource.size() > 0
1768 && record.mReceiver.mWorkSource.getName(0) != null) {
David Christie82edc9b2013-07-19 11:31:42 -07001769 // Assign blame to another work source.
David Christiee55c9682013-08-22 10:10:34 -07001770 // Can only assign blame if the WorkSource contains names.
David Christie82edc9b2013-07-19 11:31:42 -07001771 worksource.add(record.mReceiver.mWorkSource);
1772 } else {
1773 // Assign blame to caller.
1774 worksource.add(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001775 record.mReceiver.mIdentity.mUid,
1776 record.mReceiver.mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001777 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001778 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001779 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001780 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 }
1782 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001783
1784 if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
1785 p.setRequest(providerRequest, worksource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001786 }
1787
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001788 @Override
1789 public String[] getBackgroundThrottlingWhitelist() {
1790 synchronized (mLock) {
1791 return mBackgroundThrottlePackageWhitelist.toArray(
1792 new String[mBackgroundThrottlePackageWhitelist.size()]);
1793 }
1794 }
1795
1796 private void updateBackgroundThrottlingWhitelistLocked() {
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001797 String setting = Settings.Global.getString(
1798 mContext.getContentResolver(),
1799 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
1800 if (setting == null) {
1801 setting = "";
1802 }
1803
1804 mBackgroundThrottlePackageWhitelist.clear();
1805 mBackgroundThrottlePackageWhitelist.addAll(
1806 SystemConfig.getInstance().getAllowUnthrottledLocation());
1807 mBackgroundThrottlePackageWhitelist.addAll(
1808 Arrays.asList(setting.split(",")));
1809 }
1810
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001811 private boolean isThrottlingExemptLocked(Identity identity) {
1812 if (identity.mUid == Process.SYSTEM_UID) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001813 return true;
1814 }
1815
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001816 if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001817 return true;
1818 }
1819
1820 for (LocationProviderProxy provider : mProxyProviders) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001821 if (identity.mPackageName.equals(provider.getConnectedPackageName())) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001822 return true;
1823 }
1824 }
1825
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001826 return false;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001827 }
1828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 private class UpdateRecord {
1830 final String mProvider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001831 final LocationRequest mRequest;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832 final Receiver mReceiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001833 boolean mIsForegroundUid;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001834 Location mLastFixBroadcast;
1835 long mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001836
1837 /**
1838 * Note: must be constructed with lock held.
1839 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001840 UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001841 mProvider = provider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001842 mRequest = request;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001843 mReceiver = receiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001844 mIsForegroundUid = isImportanceForeground(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001845 mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001846
1847 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1848 if (records == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001849 records = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001850 mRecordsByProvider.put(provider, records);
1851 }
1852 if (!records.contains(this)) {
1853 records.add(this);
1854 }
David Christie2ff96af2014-01-30 16:09:37 -08001855
1856 // Update statistics for historical location requests by package/provider
1857 mRequestStatistics.startRequesting(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001858 mReceiver.mIdentity.mPackageName, provider, request.getInterval());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001859 }
1860
1861 /**
David Christie2ff96af2014-01-30 16:09:37 -08001862 * Method to be called when a record will no longer be used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001863 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001864 void disposeLocked(boolean removeReceiver) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001865 mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider);
David Christie2ff96af2014-01-30 16:09:37 -08001866
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001867 // remove from mRecordsByProvider
1868 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
1869 if (globalRecords != null) {
1870 globalRecords.remove(this);
1871 }
1872
1873 if (!removeReceiver) return; // the caller will handle the rest
1874
1875 // remove from Receiver#mUpdateRecords
1876 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
1877 if (receiverRecords != null) {
1878 receiverRecords.remove(this.mProvider);
1879
1880 // and also remove the Receiver if it has no more update records
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001881 if (receiverRecords.size() == 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001882 removeUpdatesLocked(mReceiver);
1883 }
Mike Lockwood3a76fd62009-09-01 07:26:56 -04001884 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001885 }
1886
1887 @Override
1888 public String toString() {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001889 return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
1890 + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground" : " background")
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001891 + ")" + " " + mRequest + "]";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001892 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001893 }
1894
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001895 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -07001896 String packageName, WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001897 IBinder binder = listener.asBinder();
1898 Receiver receiver = mReceivers.get(binder);
1899 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07001900 receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
1901 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001902 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001903 receiver.getListener().asBinder().linkToDeath(receiver, 0);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001904 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001905 Slog.e(TAG, "linkToDeath failed:", e);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001906 return null;
1907 }
Wen Jingcb3ab222014-03-27 13:42:59 +08001908 mReceivers.put(binder, receiver);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001909 }
1910 return receiver;
1911 }
1912
David Christie82edc9b2013-07-19 11:31:42 -07001913 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
David Christie40e57822013-07-30 11:36:48 -07001914 WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001915 Receiver receiver = mReceivers.get(intent);
1916 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07001917 receiver = new Receiver(null, intent, pid, uid, packageName, workSource,
1918 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001919 mReceivers.put(intent, receiver);
1920 }
1921 return receiver;
1922 }
1923
Victoria Lease37425c32012-10-16 16:08:48 -07001924 /**
1925 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
1926 * and consistency requirements.
1927 *
1928 * @param request the LocationRequest from which to create a sanitized version
Victoria Lease37425c32012-10-16 16:08:48 -07001929 * @return a version of request that meets the given resolution and consistency requirements
1930 * @hide
1931 */
1932 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel) {
1933 LocationRequest sanitizedRequest = new LocationRequest(request);
1934 if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
1935 switch (sanitizedRequest.getQuality()) {
Victoria Lease09016ab2012-09-16 12:33:15 -07001936 case LocationRequest.ACCURACY_FINE:
Victoria Lease37425c32012-10-16 16:08:48 -07001937 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
Victoria Lease09016ab2012-09-16 12:33:15 -07001938 break;
1939 case LocationRequest.POWER_HIGH:
Victoria Lease37425c32012-10-16 16:08:48 -07001940 sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
Victoria Lease09016ab2012-09-16 12:33:15 -07001941 break;
1942 }
1943 // throttle
Victoria Lease37425c32012-10-16 16:08:48 -07001944 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1945 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001946 }
Victoria Lease37425c32012-10-16 16:08:48 -07001947 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1948 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001949 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07001950 }
Nick Pelly4e31c4f2012-08-13 19:35:39 -07001951 // make getFastestInterval() the minimum of interval and fastest interval
Victoria Lease37425c32012-10-16 16:08:48 -07001952 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07001953 request.setFastestInterval(request.getInterval());
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001954 }
Victoria Lease37425c32012-10-16 16:08:48 -07001955 return sanitizedRequest;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001956 }
1957
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001958 private void checkPackageName(String packageName) {
Nick Pellye0fd6932012-07-11 10:26:13 -07001959 if (packageName == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001960 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07001961 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001962 int uid = Binder.getCallingUid();
Nick Pellye0fd6932012-07-11 10:26:13 -07001963 String[] packages = mPackageManager.getPackagesForUid(uid);
1964 if (packages == null) {
1965 throw new SecurityException("invalid UID " + uid);
1966 }
1967 for (String pkg : packages) {
1968 if (packageName.equals(pkg)) return;
1969 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001970 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07001971 }
1972
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001973 private void checkPendingIntent(PendingIntent intent) {
1974 if (intent == null) {
1975 throw new IllegalArgumentException("invalid pending intent: " + intent);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001976 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001977 }
1978
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001979 private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent,
David Christie40e57822013-07-30 11:36:48 -07001980 int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001981 if (intent == null && listener == null) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001982 throw new IllegalArgumentException("need either listener or intent");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001983 } else if (intent != null && listener != null) {
1984 throw new IllegalArgumentException("cannot register both listener and intent");
1985 } else if (intent != null) {
1986 checkPendingIntent(intent);
David Christie40e57822013-07-30 11:36:48 -07001987 return getReceiverLocked(intent, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001988 } else {
David Christie40e57822013-07-30 11:36:48 -07001989 return getReceiverLocked(listener, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001990 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001991 }
1992
Nick Pellye0fd6932012-07-11 10:26:13 -07001993 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001994 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
1995 PendingIntent intent, String packageName) {
1996 if (request == null) request = DEFAULT_LOCATION_REQUEST;
1997 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07001998 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
1999 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2000 request.getProvider());
David Christie82edc9b2013-07-19 11:31:42 -07002001 WorkSource workSource = request.getWorkSource();
2002 if (workSource != null && workSource.size() > 0) {
David Christie40e57822013-07-30 11:36:48 -07002003 checkDeviceStatsAllowed();
2004 }
2005 boolean hideFromAppOps = request.getHideFromAppOps();
2006 if (hideFromAppOps) {
2007 checkUpdateAppOpsAllowed();
David Christie82edc9b2013-07-19 11:31:42 -07002008 }
Victoria Lease37425c32012-10-16 16:08:48 -07002009 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002010
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002011 final int pid = Binder.getCallingPid();
2012 final int uid = Binder.getCallingUid();
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002013 // providers may use public location API's, need to clear identity
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002014 long identity = Binder.clearCallingIdentity();
2015 try {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002016 // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2017 // a location.
David Christieb870dbf2015-06-22 12:42:53 -07002018 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002019
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002020 synchronized (mLock) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002021 Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
David Christie40e57822013-07-30 11:36:48 -07002022 packageName, workSource, hideFromAppOps);
Victoria Lease37425c32012-10-16 16:08:48 -07002023 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
Mike Lockwood2d4d1bf2010-10-18 17:06:26 -04002024 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002025 } finally {
2026 Binder.restoreCallingIdentity(identity);
2027 }
2028 }
2029
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002030 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
2031 int pid, int uid, String packageName) {
2032 // Figure out the provider. Either its explicitly request (legacy use cases), or
2033 // use the fused provider
2034 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2035 String name = request.getProvider();
Victoria Lease09016ab2012-09-16 12:33:15 -07002036 if (name == null) {
2037 throw new IllegalArgumentException("provider name must not be null");
2038 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -07002039
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002040 LocationProviderInterface provider = mProvidersByName.get(name);
2041 if (provider == null) {
Victoria Leaseb30f3832013-10-13 12:15:40 -07002042 throw new IllegalArgumentException("provider doesn't exist: " + name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002043 }
2044
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002045 UpdateRecord record = new UpdateRecord(name, request, receiver);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002046 if (D) Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
2047 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
2048 + (record.mIsForegroundUid ? "foreground" : "background")
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002049 + (isThrottlingExemptLocked(receiver.mIdentity)
2050 ? " [whitelisted]" : "") + ")");
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002051
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002052 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
2053 if (oldRecord != null) {
2054 oldRecord.disposeLocked(false);
2055 }
2056
Victoria Lease09eeaec2013-02-05 11:34:13 -08002057 boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002058 if (isProviderEnabled) {
2059 applyRequirementsLocked(name);
2060 } else {
2061 // Notify the listener that updates are currently disabled
2062 receiver.callProviderEnabledLocked(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002063 }
David Christie0b837452013-07-29 16:02:13 -07002064 // Update the monitoring here just in case multiple location requests were added to the
2065 // same receiver (this request may be high power and the initial might not have been).
2066 receiver.updateMonitoring(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002067 }
2068
Nick Pellye0fd6932012-07-11 10:26:13 -07002069 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002070 public void removeUpdates(ILocationListener listener, PendingIntent intent,
2071 String packageName) {
2072 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002073
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002074 final int pid = Binder.getCallingPid();
2075 final int uid = Binder.getCallingUid();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002076
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002077 synchronized (mLock) {
David Christie82edc9b2013-07-19 11:31:42 -07002078 WorkSource workSource = null;
David Christie40e57822013-07-30 11:36:48 -07002079 boolean hideFromAppOps = false;
2080 Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid,
2081 packageName, workSource, hideFromAppOps);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002082
2083 // providers may use public location API's, need to clear identity
2084 long identity = Binder.clearCallingIdentity();
2085 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002086 removeUpdatesLocked(receiver);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002087 } finally {
2088 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002089 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002090 }
2091 }
2092
2093 private void removeUpdatesLocked(Receiver receiver) {
Dianne Hackborn7ff30112012-11-08 11:12:09 -08002094 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002095
2096 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
2097 receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
2098 synchronized (receiver) {
Victoria Lease0aa28602013-05-29 15:28:26 -07002099 receiver.clearPendingBroadcastsLocked();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002101 }
2102
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07002103 receiver.updateMonitoring(false);
2104
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002105 // Record which providers were associated with this listener
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002106 HashSet<String> providers = new HashSet<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002107 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2108 if (oldRecords != null) {
2109 // Call dispose() on the obsolete update records.
2110 for (UpdateRecord record : oldRecords.values()) {
David Christie2ff96af2014-01-30 16:09:37 -08002111 // Update statistics for historical location requests by package/provider
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002112 record.disposeLocked(false);
2113 }
2114 // Accumulate providers
2115 providers.addAll(oldRecords.keySet());
2116 }
2117
2118 // update provider
2119 for (String provider : providers) {
2120 // If provider is already disabled, don't need to do anything
Victoria Lease09eeaec2013-02-05 11:34:13 -08002121 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002122 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002123 }
2124
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002125 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002126 }
2127 }
2128
Dianne Hackbornc2293022013-02-06 23:14:49 -08002129 private void applyAllProviderRequirementsLocked() {
2130 for (LocationProviderInterface p : mProviders) {
2131 // If provider is already disabled, don't need to do anything
Dianne Hackborn64d41d72013-02-07 00:33:31 -08002132 if (!isAllowedByCurrentUserSettingsLocked(p.getName())) {
Dianne Hackbornc2293022013-02-06 23:14:49 -08002133 continue;
2134 }
2135
2136 applyRequirementsLocked(p.getName());
2137 }
2138 }
2139
Nick Pellye0fd6932012-07-11 10:26:13 -07002140 @Override
Nick Pelly4035f5a2012-08-17 14:43:49 -07002141 public Location getLastLocation(LocationRequest request, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002142 if (D) Log.d(TAG, "getLastLocation: " + request);
2143 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002144 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly4035f5a2012-08-17 14:43:49 -07002145 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002146 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2147 request.getProvider());
2148 // no need to sanitize this request, as only the provider name is used
Nick Pelly4035f5a2012-08-17 14:43:49 -07002149
David Christieb870dbf2015-06-22 12:42:53 -07002150 final int pid = Binder.getCallingPid();
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002151 final int uid = Binder.getCallingUid();
2152 final long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07002153 try {
2154 if (mBlacklist.isBlacklisted(packageName)) {
2155 if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
2156 packageName);
Victoria Lease09016ab2012-09-16 12:33:15 -07002157 return null;
2158 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002159
David Christieb870dbf2015-06-22 12:42:53 -07002160 if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel)) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002161 if (D) Log.d(TAG, "not returning last loc for no op app: " +
2162 packageName);
2163 return null;
2164 }
2165
Victoria Leaseb711d572012-10-02 13:14:11 -07002166 synchronized (mLock) {
2167 // Figure out the provider. Either its explicitly request (deprecated API's),
2168 // or use the fused provider
2169 String name = request.getProvider();
2170 if (name == null) name = LocationManager.FUSED_PROVIDER;
2171 LocationProviderInterface provider = mProvidersByName.get(name);
2172 if (provider == null) return null;
2173
Victoria Lease09eeaec2013-02-05 11:34:13 -08002174 if (!isAllowedByUserSettingsLocked(name, uid)) return null;
Victoria Leaseb711d572012-10-02 13:14:11 -07002175
David Christie1b9b7b12013-04-15 15:31:11 -07002176 Location location;
2177 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2178 // Make sure that an app with coarse permissions can't get frequent location
2179 // updates by calling LocationManager.getLastKnownLocation repeatedly.
2180 location = mLastLocationCoarseInterval.get(name);
2181 } else {
2182 location = mLastLocation.get(name);
2183 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002184 if (location == null) {
2185 return null;
2186 }
Victoria Lease37425c32012-10-16 16:08:48 -07002187 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002188 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2189 if (noGPSLocation != null) {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002190 return new Location(mLocationFudger.getOrCreate(noGPSLocation));
Victoria Leaseb711d572012-10-02 13:14:11 -07002191 }
Victoria Lease37425c32012-10-16 16:08:48 -07002192 } else {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002193 return new Location(location);
Victoria Lease09016ab2012-09-16 12:33:15 -07002194 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002195 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002196 return null;
2197 } finally {
2198 Binder.restoreCallingIdentity(identity);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002199 }
2200 }
2201
2202 @Override
2203 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
2204 String packageName) {
2205 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002206 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2207 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002208 checkPendingIntent(intent);
2209 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002210 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2211 request.getProvider());
2212 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002213
Victoria Lease37425c32012-10-16 16:08:48 -07002214 if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002215
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002216 // geo-fence manager uses the public location API, need to clear identity
2217 int uid = Binder.getCallingUid();
Xiaohui Chena4490622015-09-22 15:29:31 -07002218 // TODO: http://b/23822629
2219 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
Victoria Lease56e675b2012-11-05 19:25:06 -08002220 // temporary measure until geofences work for secondary users
2221 Log.w(TAG, "proximity alerts are currently available only to the primary user");
2222 return;
2223 }
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002224 long identity = Binder.clearCallingIdentity();
2225 try {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002226 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
2227 uid, packageName);
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002228 } finally {
2229 Binder.restoreCallingIdentity(identity);
2230 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002231 }
2232
2233 @Override
2234 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002235 checkPendingIntent(intent);
2236 checkPackageName(packageName);
2237
2238 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2239
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002240 // geo-fence manager uses the public location API, need to clear identity
2241 long identity = Binder.clearCallingIdentity();
2242 try {
2243 mGeofenceManager.removeFence(geofence, intent);
2244 } finally {
2245 Binder.restoreCallingIdentity(identity);
2246 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002247 }
2248
2249
2250 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002251 public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002252 if (!hasGnssPermissions(packageName) || mGnssStatusProvider == null) {
Takayuki Hoshib254ab6a2014-10-23 16:46:02 +09002253 return false;
2254 }
2255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002256 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002257 mGnssStatusProvider.registerGnssStatusCallback(callback);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002258 } catch (RemoteException e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002259 Slog.e(TAG, "mGpsStatusProvider.registerGnssStatusCallback failed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002260 return false;
2261 }
2262 return true;
2263 }
2264
Nick Pellye0fd6932012-07-11 10:26:13 -07002265 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002266 public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002267 synchronized (mLock) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002268 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002269 mGnssStatusProvider.unregisterGnssStatusCallback(callback);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002270 } catch (Exception e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002271 Slog.e(TAG, "mGpsStatusProvider.unregisterGnssStatusCallback failed", e);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002272 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002273 }
2274 }
2275
Nick Pellye0fd6932012-07-11 10:26:13 -07002276 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002277 public boolean addGnssMeasurementsListener(
2278 IGnssMeasurementsListener listener,
destradaaea8a8a62014-06-23 18:19:03 -07002279 String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002280 if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
destradaaea8a8a62014-06-23 18:19:03 -07002281 return false;
2282 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002283
2284 synchronized (mLock) {
2285 Identity callerIdentity
2286 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
2287 mGnssMeasurementsListeners.put(listener, callerIdentity);
2288 long identity = Binder.clearCallingIdentity();
2289 try {
2290 if (isThrottlingExemptLocked(callerIdentity)
2291 || isImportanceForeground(
2292 mActivityManager.getPackageImportance(packageName))) {
2293 return mGnssMeasurementsProvider.addListener(listener);
2294 }
2295 } finally {
2296 Binder.restoreCallingIdentity(identity);
2297 }
2298
2299 return true;
2300 }
destradaaea8a8a62014-06-23 18:19:03 -07002301 }
2302
2303 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002304 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
2305 if (mGnssMeasurementsProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002306 synchronized (mLock) {
2307 mGnssMeasurementsListeners.remove(listener);
2308 mGnssMeasurementsProvider.removeListener(listener);
2309 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002310 }
destradaaea8a8a62014-06-23 18:19:03 -07002311 }
2312
2313 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002314 public boolean addGnssNavigationMessageListener(
2315 IGnssNavigationMessageListener listener,
destradaa4b3e3932014-07-21 18:01:47 -07002316 String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002317 if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) {
destradaa4b3e3932014-07-21 18:01:47 -07002318 return false;
2319 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002320
2321 synchronized (mLock) {
2322 Identity callerIdentity
2323 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
2324 mGnssNavigationMessageListeners.put(listener, callerIdentity);
2325 long identity = Binder.clearCallingIdentity();
2326 try {
2327 if (isThrottlingExemptLocked(callerIdentity)
2328 || isImportanceForeground(
2329 mActivityManager.getPackageImportance(packageName))) {
2330 return mGnssNavigationMessageProvider.addListener(listener);
2331 }
2332 } finally {
2333 Binder.restoreCallingIdentity(identity);
2334 }
2335
2336 return true;
2337 }
destradaa4b3e3932014-07-21 18:01:47 -07002338 }
2339
2340 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002341 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
2342 if (mGnssNavigationMessageProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002343 synchronized (mLock) {
2344 mGnssNavigationMessageListeners.remove(listener);
2345 mGnssNavigationMessageProvider.removeListener(listener);
2346 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002347 }
destradaa4b3e3932014-07-21 18:01:47 -07002348 }
2349
2350 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002351 public boolean sendExtraCommand(String provider, String command, Bundle extras) {
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002352 if (provider == null) {
2353 // throw NullPointerException to remain compatible with previous implementation
2354 throw new NullPointerException();
2355 }
Victoria Lease37425c32012-10-16 16:08:48 -07002356 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2357 provider);
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002359 // and check for ACCESS_LOCATION_EXTRA_COMMANDS
Mike Lockwoodb7e99222009-07-07 13:18:21 -04002360 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002361 != PackageManager.PERMISSION_GRANTED)) {
2362 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
2363 }
2364
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002365 synchronized (mLock) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002366 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002367 if (p == null) return false;
Nick Pellye0fd6932012-07-11 10:26:13 -07002368
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002369 return p.sendExtraCommand(command, extras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002370 }
2371 }
2372
Nick Pellye0fd6932012-07-11 10:26:13 -07002373 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002374 public boolean sendNiResponse(int notifId, int userResponse) {
Mike Lockwood18ad9f62009-08-27 14:01:23 -07002375 if (Binder.getCallingUid() != Process.myUid()) {
2376 throw new SecurityException(
2377 "calling sendNiResponse from outside of the system is not allowed");
2378 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002379 try {
2380 return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002381 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002382 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
Danke Xie22d1f9f2009-08-18 18:28:45 -04002383 return false;
2384 }
2385 }
2386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002387 /**
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002388 * @return null if the provider does not exist
Alexey Tarasovf2db9fb2009-09-01 02:37:07 +11002389 * @throws SecurityException if the provider is not allowed to be
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002390 * accessed by the caller
2391 */
Nick Pellye0fd6932012-07-11 10:26:13 -07002392 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002393 public ProviderProperties getProviderProperties(String provider) {
Laurent Tub7f9d252012-10-16 14:25:00 -07002394 if (mProvidersByName.get(provider) == null) {
David Christie2ff96af2014-01-30 16:09:37 -08002395 return null;
Laurent Tub7f9d252012-10-16 14:25:00 -07002396 }
2397
Victoria Lease37425c32012-10-16 16:08:48 -07002398 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2399 provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002400
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002401 LocationProviderInterface p;
2402 synchronized (mLock) {
2403 p = mProvidersByName.get(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002404 }
2405
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002406 if (p == null) return null;
2407 return p.getProperties();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002408 }
2409
Jason Monkb71218a2015-06-17 14:44:39 -04002410 /**
2411 * @return null if the provider does not exist
2412 * @throws SecurityException if the provider is not allowed to be
2413 * accessed by the caller
2414 */
2415 @Override
2416 public String getNetworkProviderPackage() {
2417 LocationProviderInterface p;
2418 synchronized (mLock) {
2419 if (mProvidersByName.get(LocationManager.NETWORK_PROVIDER) == null) {
2420 return null;
2421 }
2422 p = mProvidersByName.get(LocationManager.NETWORK_PROVIDER);
2423 }
2424
2425 if (p instanceof LocationProviderProxy) {
2426 return ((LocationProviderProxy) p).getConnectedPackageName();
2427 }
2428 return null;
2429 }
2430
Nick Pellye0fd6932012-07-11 10:26:13 -07002431 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002432 public boolean isProviderEnabled(String provider) {
Tom O'Neilld5759432013-09-11 11:03:03 -07002433 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2434 // so we discourage its use
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002435 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
2436
Victoria Lease09eeaec2013-02-05 11:34:13 -08002437 int uid = Binder.getCallingUid();
Victoria Lease269518e2012-10-29 08:25:39 -07002438 long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07002439 try {
2440 synchronized (mLock) {
2441 LocationProviderInterface p = mProvidersByName.get(provider);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002442 return p != null && isAllowedByUserSettingsLocked(provider, uid);
Victoria Leaseb711d572012-10-02 13:14:11 -07002443 }
2444 } finally {
2445 Binder.restoreCallingIdentity(identity);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002446 }
2447 }
2448
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002449 /**
2450 * Returns "true" if the UID belongs to a bound location provider.
2451 *
2452 * @param uid the uid
2453 * @return true if uid belongs to a bound location provider
2454 */
2455 private boolean isUidALocationProvider(int uid) {
2456 if (uid == Process.SYSTEM_UID) {
2457 return true;
2458 }
2459 if (mGeocodeProvider != null) {
David Christie1f141c12014-05-14 15:11:15 -07002460 if (doesUidHavePackage(uid, mGeocodeProvider.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002461 }
2462 for (LocationProviderProxy proxy : mProxyProviders) {
David Christie1f141c12014-05-14 15:11:15 -07002463 if (doesUidHavePackage(uid, proxy.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002464 }
2465 return false;
2466 }
2467
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002468 private void checkCallerIsProvider() {
2469 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
2470 == PackageManager.PERMISSION_GRANTED) {
2471 return;
2472 }
2473
2474 // Previously we only used the INSTALL_LOCATION_PROVIDER
2475 // check. But that is system or signature
2476 // protection level which is not flexible enough for
2477 // providers installed oustide the system image. So
2478 // also allow providers with a UID matching the
2479 // currently bound package name
2480
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002481 if (isUidALocationProvider(Binder.getCallingUid())) {
2482 return;
2483 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002484
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002485 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
2486 "or UID of a currently bound location provider");
2487 }
2488
David Christie1f141c12014-05-14 15:11:15 -07002489 /**
2490 * Returns true if the given package belongs to the given uid.
2491 */
2492 private boolean doesUidHavePackage(int uid, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002493 if (packageName == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002494 return false;
2495 }
David Christie1f141c12014-05-14 15:11:15 -07002496 String[] packageNames = mPackageManager.getPackagesForUid(uid);
2497 if (packageNames == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002498 return false;
2499 }
David Christie1f141c12014-05-14 15:11:15 -07002500 for (String name : packageNames) {
2501 if (packageName.equals(name)) {
2502 return true;
2503 }
2504 }
2505 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002506 }
2507
Nick Pellye0fd6932012-07-11 10:26:13 -07002508 @Override
Mike Lockwooda4903f22010-02-17 06:42:23 -05002509 public void reportLocation(Location location, boolean passive) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002510 checkCallerIsProvider();
Mike Lockwood275555c2009-05-01 11:30:34 -04002511
Nick Pelly2eeeec22012-07-18 13:13:37 -07002512 if (!location.isComplete()) {
2513 Log.w(TAG, "Dropping incomplete location: " + location);
2514 return;
2515 }
2516
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002517 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location);
2518 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location);
Mike Lockwooda4903f22010-02-17 06:42:23 -05002519 m.arg1 = (passive ? 1 : 0);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002520 mLocationHandler.sendMessageAtFrontOfQueue(m);
2521 }
2522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002523
Laurent Tu75defb62012-11-01 16:21:52 -07002524 private static boolean shouldBroadcastSafe(
2525 Location loc, Location lastLoc, UpdateRecord record, long now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002526 // Always broadcast the first update
2527 if (lastLoc == null) {
2528 return true;
2529 }
2530
Nick Pellyf1be6862012-05-15 10:53:42 -07002531 // Check whether sufficient time has passed
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002532 long minTime = record.mRequest.getFastestInterval();
David Christie1b9b7b12013-04-15 15:31:11 -07002533 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
2534 / NANOS_PER_MILLI;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002535 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002536 return false;
2537 }
2538
2539 // Check whether sufficient distance has been traveled
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002540 double minDistance = record.mRequest.getSmallestDisplacement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002541 if (minDistance > 0.0) {
2542 if (loc.distanceTo(lastLoc) <= minDistance) {
2543 return false;
2544 }
2545 }
2546
Laurent Tu75defb62012-11-01 16:21:52 -07002547 // Check whether sufficient number of udpates is left
2548 if (record.mRequest.getNumUpdates() <= 0) {
2549 return false;
2550 }
2551
2552 // Check whether the expiry date has passed
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002553 return record.mRequest.getExpireAt() >= now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002554 }
2555
Mike Lockwooda4903f22010-02-17 06:42:23 -05002556 private void handleLocationChangedLocked(Location location, boolean passive) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002557 if (D) Log.d(TAG, "incoming location: " + location);
2558
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002559 long now = SystemClock.elapsedRealtime();
Mike Lockwooda4903f22010-02-17 06:42:23 -05002560 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002561
Laurent Tu60ec50a2012-10-04 17:00:10 -07002562 // Skip if the provider is unknown.
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002563 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002564 if (p == null) return;
2565
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002566 // Update last known locations
Victoria Lease09016ab2012-09-16 12:33:15 -07002567 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002568 Location lastNoGPSLocation;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002569 Location lastLocation = mLastLocation.get(provider);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002570 if (lastLocation == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002571 lastLocation = new Location(provider);
2572 mLastLocation.put(provider, lastLocation);
Victoria Lease09016ab2012-09-16 12:33:15 -07002573 } else {
2574 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2575 if (noGPSLocation == null && lastNoGPSLocation != null) {
2576 // New location has no no-GPS location: adopt last no-GPS location. This is set
2577 // directly into location because we do not want to notify COARSE clients.
2578 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
2579 }
Mike Lockwood4e50b782009-04-03 08:24:43 -07002580 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002581 lastLocation.set(location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002582
David Christie1b9b7b12013-04-15 15:31:11 -07002583 // Update last known coarse interval location if enough time has passed.
2584 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider);
2585 if (lastLocationCoarseInterval == null) {
2586 lastLocationCoarseInterval = new Location(location);
2587 mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval);
2588 }
2589 long timeDiffNanos = location.getElapsedRealtimeNanos()
2590 - lastLocationCoarseInterval.getElapsedRealtimeNanos();
2591 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
2592 lastLocationCoarseInterval.set(location);
2593 }
2594 // Don't ever return a coarse location that is more recent than the allowed update
2595 // interval (i.e. don't allow an app to keep registering and unregistering for
2596 // location updates to overcome the minimum interval).
2597 noGPSLocation =
2598 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2599
Laurent Tu60ec50a2012-10-04 17:00:10 -07002600 // Skip if there are no UpdateRecords for this provider.
2601 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
2602 if (records == null || records.size() == 0) return;
2603
Victoria Lease09016ab2012-09-16 12:33:15 -07002604 // Fetch coarse location
2605 Location coarseLocation = null;
David Christie1b9b7b12013-04-15 15:31:11 -07002606 if (noGPSLocation != null) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002607 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
2608 }
2609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002610 // Fetch latest status update time
2611 long newStatusUpdateTime = p.getStatusUpdateTime();
2612
David Christie2ff96af2014-01-30 16:09:37 -08002613 // Get latest status
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002614 Bundle extras = new Bundle();
2615 int status = p.getStatus(extras);
2616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002617 ArrayList<Receiver> deadReceivers = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002618 ArrayList<UpdateRecord> deadUpdateRecords = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07002619
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002620 // Broadcast location or status to all listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002621 for (UpdateRecord r : records) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 Receiver receiver = r.mReceiver;
Mike Lockwood03ca2162010-04-01 08:10:09 -07002623 boolean receiverDead = false;
Nick Pelly4035f5a2012-08-17 14:43:49 -07002624
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002625 int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid);
2626 if (!isCurrentProfile(receiverUserId)
2627 && !isUidALocationProvider(receiver.mIdentity.mUid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002628 if (D) {
Victoria Lease269518e2012-10-29 08:25:39 -07002629 Log.d(TAG, "skipping loc update for background user " + receiverUserId +
Victoria Leaseb711d572012-10-02 13:14:11 -07002630 " (current user: " + mCurrentUserId + ", app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002631 receiver.mIdentity.mPackageName + ")");
Victoria Leaseb711d572012-10-02 13:14:11 -07002632 }
2633 continue;
2634 }
2635
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002636 if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) {
Nick Pelly4035f5a2012-08-17 14:43:49 -07002637 if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002638 receiver.mIdentity.mPackageName);
Nick Pelly4035f5a2012-08-17 14:43:49 -07002639 continue;
2640 }
2641
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002642 if (!reportLocationAccessNoThrow(
2643 receiver.mIdentity.mPid,
2644 receiver.mIdentity.mUid,
2645 receiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002646 receiver.mAllowedResolutionLevel)) {
2647 if (D) Log.d(TAG, "skipping loc update for no op app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002648 receiver.mIdentity.mPackageName);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002649 continue;
2650 }
2651
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002652 Location notifyLocation;
Victoria Lease37425c32012-10-16 16:08:48 -07002653 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2654 notifyLocation = coarseLocation; // use coarse location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002655 } else {
Victoria Lease37425c32012-10-16 16:08:48 -07002656 notifyLocation = lastLocation; // use fine location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002657 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002658 if (notifyLocation != null) {
2659 Location lastLoc = r.mLastFixBroadcast;
Laurent Tu75defb62012-11-01 16:21:52 -07002660 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002661 if (lastLoc == null) {
2662 lastLoc = new Location(notifyLocation);
2663 r.mLastFixBroadcast = lastLoc;
2664 } else {
2665 lastLoc.set(notifyLocation);
2666 }
2667 if (!receiver.callLocationChangedLocked(notifyLocation)) {
2668 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
2669 receiverDead = true;
2670 }
Laurent Tu75defb62012-11-01 16:21:52 -07002671 r.mRequest.decrementNumUpdates();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002672 }
2673 }
2674
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002675 long prevStatusUpdateTime = r.mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002676 if ((newStatusUpdateTime > prevStatusUpdateTime) &&
Victoria Lease09016ab2012-09-16 12:33:15 -07002677 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002678
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002679 r.mLastStatusBroadcast = newStatusUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002680 if (!receiver.callStatusChangedLocked(provider, status, extras)) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002681 receiverDead = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002682 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
Mike Lockwood03ca2162010-04-01 08:10:09 -07002683 }
2684 }
2685
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002686 // track expired records
Laurent Tu75defb62012-11-01 16:21:52 -07002687 if (r.mRequest.getNumUpdates() <= 0 || r.mRequest.getExpireAt() < now) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002688 if (deadUpdateRecords == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002689 deadUpdateRecords = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002690 }
2691 deadUpdateRecords.add(r);
2692 }
2693 // track dead receivers
2694 if (receiverDead) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002695 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002696 deadReceivers = new ArrayList<>();
Mike Lockwood03ca2162010-04-01 08:10:09 -07002697 }
2698 if (!deadReceivers.contains(receiver)) {
2699 deadReceivers.add(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002700 }
2701 }
2702 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002703
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002704 // remove dead records and receivers outside the loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002705 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002706 for (Receiver receiver : deadReceivers) {
2707 removeUpdatesLocked(receiver);
2708 }
2709 }
2710 if (deadUpdateRecords != null) {
2711 for (UpdateRecord r : deadUpdateRecords) {
2712 r.disposeLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002713 }
Victoria Lease8b38b292012-12-04 15:04:43 -08002714 applyRequirementsLocked(provider);
2715 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002716 }
2717
2718 private class LocationWorkerHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08002719 public LocationWorkerHandler(Looper looper) {
2720 super(looper, null, true);
2721 }
2722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002723 @Override
2724 public void handleMessage(Message msg) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002725 switch (msg.what) {
2726 case MSG_LOCATION_CHANGED:
2727 handleLocationChanged((Location) msg.obj, msg.arg1 == 1);
2728 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002729 }
2730 }
2731 }
2732
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002733 private boolean isMockProvider(String provider) {
2734 synchronized (mLock) {
2735 return mMockProviders.containsKey(provider);
2736 }
2737 }
2738
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002739 private void handleLocationChanged(Location location, boolean passive) {
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002740 // create a working copy of the incoming Location so that the service can modify it without
2741 // disturbing the caller's copy
2742 Location myLocation = new Location(location);
2743 String provider = myLocation.getProvider();
2744
2745 // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this
2746 // bit if location did not come from a mock provider because passive/fused providers can
2747 // forward locations from mock providers, and should not grant them legitimacy in doing so.
2748 if (!myLocation.isFromMockProvider() && isMockProvider(provider)) {
2749 myLocation.setIsFromMockProvider(true);
2750 }
Jeff Sharkey5e613312012-01-30 11:16:20 -08002751
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002752 synchronized (mLock) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08002753 if (isAllowedByCurrentUserSettingsLocked(provider)) {
2754 if (!passive) {
2755 // notify passive provider of the new location
2756 mPassiveProvider.updateLocation(myLocation);
2757 }
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002758 handleLocationChangedLocked(myLocation, passive);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002759 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002760 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002761 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002762
Mike Lockwoode97ae402010-09-29 15:23:46 -04002763 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
2764 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002765 public void onPackageDisappeared(String packageName, int reason) {
2766 // remove all receivers associated with this package name
2767 synchronized (mLock) {
2768 ArrayList<Receiver> deadReceivers = null;
2769
2770 for (Receiver receiver : mReceivers.values()) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002771 if (receiver.mIdentity.mPackageName.equals(packageName)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002772 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002773 deadReceivers = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002774 }
2775 deadReceivers.add(receiver);
2776 }
2777 }
2778
2779 // perform removal outside of mReceivers loop
2780 if (deadReceivers != null) {
2781 for (Receiver receiver : deadReceivers) {
2782 removeUpdatesLocked(receiver);
2783 }
2784 }
2785 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002786 }
Mike Lockwoode97ae402010-09-29 15:23:46 -04002787 };
2788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002789 // Geocoder
2790
Nick Pellye0fd6932012-07-11 10:26:13 -07002791 @Override
Mike Lockwoode15735a2010-09-20 17:48:47 -04002792 public boolean geocoderIsPresent() {
Mark Vandevoorde01ac80b2010-05-21 15:43:26 -07002793 return mGeocodeProvider != null;
2794 }
2795
Nick Pellye0fd6932012-07-11 10:26:13 -07002796 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002797 public String getFromLocation(double latitude, double longitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002798 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002799 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002800 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
2801 params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002802 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002803 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002804 }
2805
Mike Lockwooda55c3212009-04-15 11:10:11 -04002806
Nick Pellye0fd6932012-07-11 10:26:13 -07002807 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002808 public String getFromLocationName(String locationName,
Mike Lockwooda55c3212009-04-15 11:10:11 -04002809 double lowerLeftLatitude, double lowerLeftLongitude,
2810 double upperRightLatitude, double upperRightLongitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002811 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002812
2813 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002814 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
2815 lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
2816 maxResults, params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002817 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002818 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002819 }
2820
2821 // Mock Providers
2822
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002823 private boolean canCallerAccessMockLocation(String opPackageName) {
2824 return mAppOps.noteOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(),
2825 opPackageName) == AppOpsManager.MODE_ALLOWED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002826 }
2827
Nick Pellye0fd6932012-07-11 10:26:13 -07002828 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002829 public void addTestProvider(String name, ProviderProperties properties, String opPackageName) {
2830 if (!canCallerAccessMockLocation(opPackageName)) {
2831 return;
2832 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002833
Mike Lockwooda4903f22010-02-17 06:42:23 -05002834 if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
2835 throw new IllegalArgumentException("Cannot mock the passive location provider");
2836 }
2837
Mike Lockwood86328a92009-10-23 08:38:25 -04002838 long identity = Binder.clearCallingIdentity();
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002839 synchronized (mLock) {
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002840 // remove the real provider if we are replacing GPS or network provider
2841 if (LocationManager.GPS_PROVIDER.equals(name)
Nick Pelly1332b532012-08-21 16:25:47 -07002842 || LocationManager.NETWORK_PROVIDER.equals(name)
2843 || LocationManager.FUSED_PROVIDER.equals(name)) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002844 LocationProviderInterface p = mProvidersByName.get(name);
2845 if (p != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002846 removeProviderLocked(p);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002847 }
2848 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09002849 addTestProviderLocked(name, properties);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002850 updateProvidersLocked();
2851 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002852 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002853 }
2854
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09002855 private void addTestProviderLocked(String name, ProviderProperties properties) {
2856 if (mProvidersByName.get(name) != null) {
2857 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
2858 }
2859 MockProvider provider = new MockProvider(name, this, properties);
2860 addProviderLocked(provider);
2861 mMockProviders.put(name, provider);
2862 mLastLocation.put(name, null);
2863 mLastLocationCoarseInterval.put(name, null);
2864 }
2865
Nick Pellye0fd6932012-07-11 10:26:13 -07002866 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002867 public void removeTestProvider(String provider, String opPackageName) {
2868 if (!canCallerAccessMockLocation(opPackageName)) {
2869 return;
2870 }
2871
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002872 synchronized (mLock) {
Tom O'Neill07ee5d12014-03-03 17:48:35 -08002873
2874 // These methods can't be called after removing the test provider, so first make sure
Tom O'Neillfe6d3c52014-03-04 08:26:17 -08002875 // we don't leave anything dangling.
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002876 clearTestProviderEnabled(provider, opPackageName);
2877 clearTestProviderLocation(provider, opPackageName);
2878 clearTestProviderStatus(provider, opPackageName);
Tom O'Neill07ee5d12014-03-03 17:48:35 -08002879
You Kima6d0b6f2012-10-28 03:58:44 +09002880 MockProvider mockProvider = mMockProviders.remove(provider);
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002881 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002882 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2883 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002884 long identity = Binder.clearCallingIdentity();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002885 removeProviderLocked(mProvidersByName.get(provider));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002886
2887 // reinstate real provider if available
2888 LocationProviderInterface realProvider = mRealProviders.get(provider);
2889 if (realProvider != null) {
2890 addProviderLocked(realProvider);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002891 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002892 mLastLocation.put(provider, null);
David Christie1b9b7b12013-04-15 15:31:11 -07002893 mLastLocationCoarseInterval.put(provider, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002894 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04002895 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002896 }
2897 }
2898
Nick Pellye0fd6932012-07-11 10:26:13 -07002899 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002900 public void setTestProviderLocation(String provider, Location loc, String opPackageName) {
2901 if (!canCallerAccessMockLocation(opPackageName)) {
2902 return;
2903 }
2904
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002905 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002906 MockProvider mockProvider = mMockProviders.get(provider);
2907 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002908 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2909 }
Tom O'Neilla206a0f2016-12-15 10:26:28 -08002910
2911 // Ensure that the location is marked as being mock. There's some logic to do this in
2912 // handleLocationChanged(), but it fails if loc has the wrong provider (bug 33091107).
2913 Location mock = new Location(loc);
2914 mock.setIsFromMockProvider(true);
2915
2916 if (!TextUtils.isEmpty(loc.getProvider()) && !provider.equals(loc.getProvider())) {
2917 // The location has an explicit provider that is different from the mock provider
2918 // name. The caller may be trying to fool us via bug 33091107.
2919 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
2920 provider + "!=" + loc.getProvider());
2921 }
2922
Mike Lockwood95427cd2009-05-07 13:27:54 -04002923 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
2924 long identity = Binder.clearCallingIdentity();
Tom O'Neilla206a0f2016-12-15 10:26:28 -08002925 mockProvider.setLocation(mock);
Mike Lockwood95427cd2009-05-07 13:27:54 -04002926 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002927 }
2928 }
2929
Nick Pellye0fd6932012-07-11 10:26:13 -07002930 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002931 public void clearTestProviderLocation(String provider, String opPackageName) {
2932 if (!canCallerAccessMockLocation(opPackageName)) {
2933 return;
2934 }
2935
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002936 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002937 MockProvider mockProvider = mMockProviders.get(provider);
2938 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002939 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2940 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002941 mockProvider.clearLocation();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002942 }
2943 }
2944
Nick Pellye0fd6932012-07-11 10:26:13 -07002945 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002946 public void setTestProviderEnabled(String provider, boolean enabled, String opPackageName) {
2947 if (!canCallerAccessMockLocation(opPackageName)) {
2948 return;
2949 }
2950
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002951 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002952 MockProvider mockProvider = mMockProviders.get(provider);
2953 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002954 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2955 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002956 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002957 if (enabled) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002958 mockProvider.enable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002959 mEnabledProviders.add(provider);
2960 mDisabledProviders.remove(provider);
2961 } else {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002962 mockProvider.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002963 mEnabledProviders.remove(provider);
2964 mDisabledProviders.add(provider);
2965 }
2966 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04002967 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002968 }
2969 }
2970
Nick Pellye0fd6932012-07-11 10:26:13 -07002971 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002972 public void clearTestProviderEnabled(String provider, String opPackageName) {
2973 if (!canCallerAccessMockLocation(opPackageName)) {
2974 return;
2975 }
2976
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002977 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002978 MockProvider mockProvider = mMockProviders.get(provider);
2979 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002980 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2981 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002982 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002983 mEnabledProviders.remove(provider);
2984 mDisabledProviders.remove(provider);
2985 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04002986 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002987 }
2988 }
2989
Nick Pellye0fd6932012-07-11 10:26:13 -07002990 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002991 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime,
2992 String opPackageName) {
2993 if (!canCallerAccessMockLocation(opPackageName)) {
2994 return;
2995 }
2996
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002997 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002998 MockProvider mockProvider = mMockProviders.get(provider);
2999 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003000 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3001 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003002 mockProvider.setStatus(status, extras, updateTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003003 }
3004 }
3005
Nick Pellye0fd6932012-07-11 10:26:13 -07003006 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003007 public void clearTestProviderStatus(String provider, String opPackageName) {
3008 if (!canCallerAccessMockLocation(opPackageName)) {
3009 return;
3010 }
3011
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003012 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003013 MockProvider mockProvider = mMockProviders.get(provider);
3014 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003015 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3016 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003017 mockProvider.clearStatus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003018 }
3019 }
3020
3021 private void log(String log) {
3022 if (Log.isLoggable(TAG, Log.VERBOSE)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003023 Slog.d(TAG, log);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003024 }
3025 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003026
3027 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003028 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
3029 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
3030 != PackageManager.PERMISSION_GRANTED) {
Mike Lockwood0528b9b2009-05-07 10:12:54 -04003031 pw.println("Permission Denial: can't dump LocationManagerService from from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003032 + Binder.getCallingPid()
3033 + ", uid=" + Binder.getCallingUid());
3034 return;
3035 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003036
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003037 synchronized (mLock) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003038 pw.println("Current Location Manager state:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003039 pw.println(" Location Listeners:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003040 for (Receiver receiver : mReceivers.values()) {
3041 pw.println(" " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003042 }
David Christie2ff96af2014-01-30 16:09:37 -08003043 pw.println(" Active Records by Provider:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003044 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
3045 pw.println(" " + entry.getKey() + ":");
3046 for (UpdateRecord record : entry.getValue()) {
3047 pw.println(" " + record);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003048 }
3049 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003050 pw.println(" Overlay Provider Packages:");
3051 for (LocationProviderInterface provider : mProviders) {
3052 if (provider instanceof LocationProviderProxy) {
3053 pw.println(" " + provider.getName() + ": "
3054 + ((LocationProviderProxy) provider).getConnectedPackageName());
3055 }
3056 }
David Christie2ff96af2014-01-30 16:09:37 -08003057 pw.println(" Historical Records by Provider:");
3058 for (Map.Entry<PackageProviderKey, PackageStatistics> entry
3059 : mRequestStatistics.statistics.entrySet()) {
3060 PackageProviderKey key = entry.getKey();
3061 PackageStatistics stats = entry.getValue();
3062 pw.println(" " + key.packageName + ": " + key.providerName + ": " + stats);
3063 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003064 pw.println(" Last Known Locations:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003065 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
3066 String provider = entry.getKey();
3067 Location location = entry.getValue();
3068 pw.println(" " + provider + ": " + location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003069 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003070
David Christie1b9b7b12013-04-15 15:31:11 -07003071 pw.println(" Last Known Locations Coarse Intervals:");
3072 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
3073 String provider = entry.getKey();
3074 Location location = entry.getValue();
3075 pw.println(" " + provider + ": " + location);
3076 }
3077
Nick Pellye0fd6932012-07-11 10:26:13 -07003078 mGeofenceManager.dump(pw);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003080 if (mEnabledProviders.size() > 0) {
3081 pw.println(" Enabled Providers:");
3082 for (String i : mEnabledProviders) {
3083 pw.println(" " + i);
3084 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086 }
3087 if (mDisabledProviders.size() > 0) {
3088 pw.println(" Disabled Providers:");
3089 for (String i : mDisabledProviders) {
3090 pw.println(" " + i);
3091 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003092 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07003093 pw.append(" ");
3094 mBlacklist.dump(pw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003095 if (mMockProviders.size() > 0) {
3096 pw.println(" Mock Providers:");
3097 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003098 i.getValue().dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003099 }
3100 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003101
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08003102 if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
3103 pw.println(" Throttling Whitelisted Packages:");
3104 for (String packageName : mBackgroundThrottlePackageWhitelist) {
3105 pw.println(" " + packageName);
3106 }
3107 }
3108
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003109 pw.append(" fudger: ");
3110 mLocationFudger.dump(fd, pw, args);
3111
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003112 if (args.length > 0 && "short".equals(args[0])) {
3113 return;
3114 }
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003115 for (LocationProviderInterface provider: mProviders) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003116 pw.print(provider.getName() + " Internal State");
3117 if (provider instanceof LocationProviderProxy) {
3118 LocationProviderProxy proxy = (LocationProviderProxy) provider;
3119 pw.print(" (" + proxy.getConnectedPackageName() + ")");
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003120 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003121 pw.println(":");
3122 provider.dump(fd, pw, args);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003123 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08003124 if (mGnssBatchingInProgress) {
3125 pw.println(" GNSS batching in progress");
3126 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003127 }
3128 }
3129}