blob: f0720f326e1591525e38aab0273cd2a97103f70d [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;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060029import com.android.internal.util.DumpUtils;
destradaaa4fa3b52014-07-09 10:46:39 -070030import com.android.server.location.ActivityRecognitionProxy;
destradaaea8a8a62014-06-23 18:19:03 -070031import com.android.server.location.FlpHardwareProvider;
32import com.android.server.location.FusedProxy;
33import com.android.server.location.GeocoderProxy;
34import com.android.server.location.GeofenceManager;
35import com.android.server.location.GeofenceProxy;
Lifu Tang818aa2c2016-02-01 01:52:00 -080036import com.android.server.location.GnssLocationProvider;
37import com.android.server.location.GnssMeasurementsProvider;
38import com.android.server.location.GnssNavigationMessageProvider;
destradaaea8a8a62014-06-23 18:19:03 -070039import com.android.server.location.LocationBlacklist;
40import com.android.server.location.LocationFudger;
41import com.android.server.location.LocationProviderInterface;
42import com.android.server.location.LocationProviderProxy;
43import com.android.server.location.LocationRequestStatistics;
44import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
45import com.android.server.location.LocationRequestStatistics.PackageStatistics;
46import com.android.server.location.MockProvider;
47import com.android.server.location.PassiveProvider;
48
Dianne Hackborna06de0f2012-12-11 16:34:47 -080049import android.app.AppOpsManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.app.PendingIntent;
Victoria Lease38389b62012-09-30 11:44:22 -070051import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.content.ContentResolver;
53import android.content.Context;
54import android.content.Intent;
Victoria Lease38389b62012-09-30 11:44:22 -070055import android.content.IntentFilter;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070056import android.content.pm.ApplicationInfo;
Jeff Hamiltonfbadb692012-10-05 14:21:58 -050057import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.content.pm.PackageManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070059import android.content.pm.PackageManager.NameNotFoundException;
Jeff Hamiltonfbadb692012-10-05 14:21:58 -050060import android.content.pm.ResolveInfo;
61import android.content.pm.Signature;
Mike Lockwood628fd6d2010-01-25 22:46:13 -050062import android.content.res.Resources;
Brian Muramatsubb95cb92012-08-29 10:43:21 -070063import android.database.ContentObserver;
destradaaa4fa3b52014-07-09 10:46:39 -070064import android.hardware.location.ActivityRecognitionHardware;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.location.Address;
Mike Lockwood03ca2162010-04-01 08:10:09 -070066import android.location.Criteria;
Mike Lockwood34901402010-01-04 12:14:21 -050067import android.location.GeocoderParams;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070068import android.location.Geofence;
Wyatt Rileycf879db2017-01-12 13:57:38 -080069import android.location.IBatchedLocationCallback;
Lifu Tang818aa2c2016-02-01 01:52:00 -080070import android.location.IGnssMeasurementsListener;
Lifu Tang30f95a72016-01-07 23:20:38 -080071import android.location.IGnssStatusListener;
72import android.location.IGnssStatusProvider;
Wei Liu5241a4c2015-05-11 14:00:36 -070073import android.location.IGpsGeofenceHardware;
Lifu Tang818aa2c2016-02-01 01:52:00 -080074import android.location.IGnssNavigationMessageListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.location.ILocationListener;
76import android.location.ILocationManager;
Danke Xie22d1f9f2009-08-18 18:28:45 -040077import android.location.INetInitiatedListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078import android.location.Location;
79import android.location.LocationManager;
80import android.location.LocationProvider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070081import android.location.LocationRequest;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.os.Binder;
83import android.os.Bundle;
84import android.os.Handler;
85import android.os.IBinder;
Mike Lockwood3d12b512009-04-21 23:25:35 -070086import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.os.Message;
88import android.os.PowerManager;
Mike Lockwoode932f7f2009-04-06 10:51:26 -070089import android.os.Process;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090import android.os.RemoteException;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070091import android.os.SystemClock;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070092import android.os.UserHandle;
Amith Yamasanib27528d2014-06-05 15:02:10 -070093import android.os.UserManager;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070094import android.os.WorkSource;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095import android.provider.Settings;
Tom O'Neilla206a0f2016-12-15 10:26:28 -080096import android.text.TextUtils;
97import android.util.EventLog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098import android.util.Log;
Joe Onorato8a9b2202010-02-26 18:56:32 -080099import android.util.Slog;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700100
Mike Lockwood43e33f22010-03-26 10:41:48 -0400101import java.io.FileDescriptor;
102import java.io.PrintWriter;
103import java.util.ArrayList;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700104import java.util.Arrays;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400105import java.util.HashMap;
106import java.util.HashSet;
107import java.util.List;
108import java.util.Map;
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800109import java.util.Map.Entry;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800110import java.util.NoSuchElementException;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400111import java.util.Set;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112
113/**
114 * The service class that manages LocationProviders and issues location
115 * updates and alerts.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116 */
Victoria Lease5cd731a2012-12-19 15:04:21 -0800117public class LocationManagerService extends ILocationManager.Stub {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 private static final String TAG = "LocationManagerService";
JP Abgrallf79811e72013-02-01 18:45:05 -0800119 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700120
121 private static final String WAKELOCK_KEY = TAG;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122
Victoria Lease37425c32012-10-16 16:08:48 -0700123 // Location resolution level: no location data whatsoever
124 private static final int RESOLUTION_LEVEL_NONE = 0;
125 // Location resolution level: coarse location data only
126 private static final int RESOLUTION_LEVEL_COARSE = 1;
127 // Location resolution level: fine location data
128 private static final int RESOLUTION_LEVEL_FINE = 2;
129
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130 private static final String ACCESS_MOCK_LOCATION =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700131 android.Manifest.permission.ACCESS_MOCK_LOCATION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700133 android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
Mike Lockwood275555c2009-05-01 11:30:34 -0400134 private static final String INSTALL_LOCATION_PROVIDER =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700135 android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
136
137 private static final String NETWORK_LOCATION_SERVICE_ACTION =
Stan Chesnutt39062dd2013-07-22 14:33:30 -0700138 "com.android.location.service.v3.NetworkLocationProvider";
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700139 private static final String FUSED_LOCATION_SERVICE_ACTION =
140 "com.android.location.service.FusedLocationProvider";
141
142 private static final int MSG_LOCATION_CHANGED = 1;
143
David Christie1b9b7b12013-04-15 15:31:11 -0700144 private static final long NANOS_PER_MILLI = 1000000L;
145
David Christie0b837452013-07-29 16:02:13 -0700146 // The maximum interval a location request can have and still be considered "high power".
147 private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
148
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800149 // default background throttling interval if not overriden in settings
Soonil Nagarkarde6780a2017-02-07 10:39:41 -0800150 private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800151
Nick Pellyf1be6862012-05-15 10:53:42 -0700152 // Location Providers may sometimes deliver location updates
153 // slightly faster that requested - provide grace period so
154 // we don't unnecessarily filter events that are otherwise on
155 // time
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700156 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
Nick Pellyf1be6862012-05-15 10:53:42 -0700157
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700158 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
159
160 private final Context mContext;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800161 private final AppOpsManager mAppOps;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700162
163 // used internally for synchronization
164 private final Object mLock = new Object();
165
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700166 // --- fields below are final after systemRunning() ---
Nick Pelly74fa7ea2012-08-13 19:36:38 -0700167 private LocationFudger mLocationFudger;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700168 private GeofenceManager mGeofenceManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700169 private PackageManager mPackageManager;
Victoria Lease0aa28602013-05-29 15:28:26 -0700170 private PowerManager mPowerManager;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800171 private ActivityManager mActivityManager;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700172 private UserManager mUserManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700173 private GeocoderProxy mGeocodeProvider;
Lifu Tang30f95a72016-01-07 23:20:38 -0800174 private IGnssStatusProvider mGnssStatusProvider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700175 private INetInitiatedListener mNetInitiatedListener;
176 private LocationWorkerHandler mLocationHandler;
Nick Pelly4035f5a2012-08-17 14:43:49 -0700177 private PassiveProvider mPassiveProvider; // track passive provider for special cases
178 private LocationBlacklist mBlacklist;
Lifu Tang818aa2c2016-02-01 01:52:00 -0800179 private GnssMeasurementsProvider mGnssMeasurementsProvider;
180 private GnssNavigationMessageProvider mGnssNavigationMessageProvider;
Wei Liu5241a4c2015-05-11 14:00:36 -0700181 private IGpsGeofenceHardware mGpsGeofenceProxy;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700182
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700183 // --- fields below are protected by mLock ---
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 // Set of providers that are explicitly enabled
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700185 // Only used by passive, fused & test. Network & GPS are controlled separately, and not listed.
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800186 private final Set<String> mEnabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187
188 // Set of providers that are explicitly disabled
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800189 private final Set<String> mDisabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700191 // Mock (test) providers
192 private final HashMap<String, MockProvider> mMockProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800193 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700195 // all receivers
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800196 private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700198 // currently installed providers (with mocks replacing real providers)
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500199 private final ArrayList<LocationProviderInterface> mProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800200 new ArrayList<>();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400201
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700202 // real providers, saved here when mocked out
203 private final HashMap<String, LocationProviderInterface> mRealProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800204 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700206 // mapping from provider name to provider
207 private final HashMap<String, LocationProviderInterface> mProvidersByName =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800208 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700210 // mapping from provider name to all its UpdateRecords
211 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800212 new HashMap<>();
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700213
David Christie2ff96af2014-01-30 16:09:37 -0800214 private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics();
215
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700216 // mapping from provider name to last known location
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800217 private final HashMap<String, Location> mLastLocation = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218
David Christie1b9b7b12013-04-15 15:31:11 -0700219 // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
220 // locations stored here are not fudged for coarse permissions.
221 private final HashMap<String, Location> mLastLocationCoarseInterval =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800222 new HashMap<>();
David Christie1b9b7b12013-04-15 15:31:11 -0700223
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800224 // all providers that operate over proxy, for authorizing incoming location and whitelisting
225 // throttling
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700226 private final ArrayList<LocationProviderProxy> mProxyProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800227 new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800229 private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800230
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800231 private final ArrayMap<IGnssMeasurementsListener, Identity> mGnssMeasurementsListeners =
232 new ArrayMap<>();
233
234 private final ArrayMap<IGnssNavigationMessageListener, Identity>
235 mGnssNavigationMessageListeners = new ArrayMap<>();
236
Victoria Lease38389b62012-09-30 11:44:22 -0700237 // current active user on the device - other users are denied location data
Xiaohui Chena4490622015-09-22 15:29:31 -0700238 private int mCurrentUserId = UserHandle.USER_SYSTEM;
239 private int[] mCurrentUserProfiles = new int[] { UserHandle.USER_SYSTEM };
Victoria Lease38389b62012-09-30 11:44:22 -0700240
Lifu Tang9363b942016-02-16 18:07:00 -0800241 private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;
Lifu Tang82f893d2016-01-21 18:15:33 -0800242
Wyatt Rileycf879db2017-01-12 13:57:38 -0800243 private GnssLocationProvider.GnssBatchingProvider mGnssBatchingProvider;
244 private IBatchedLocationCallback mGnssBatchingCallback;
245 private LinkedCallback mGnssBatchingDeathCallback;
246 private boolean mGnssBatchingInProgress = false;
247
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700248 public LocationManagerService(Context context) {
249 super();
250 mContext = context;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800251 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800252
Svet Ganovadc1cf42015-06-15 16:36:24 -0700253 // Let the package manager query which are the default location
254 // providers as they get certain permissions granted by default.
255 PackageManagerInternal packageManagerInternal = LocalServices.getService(
256 PackageManagerInternal.class);
257 packageManagerInternal.setLocationPackagesProvider(
258 new PackageManagerInternal.PackagesProvider() {
259 @Override
260 public String[] getPackages(int userId) {
261 return mContext.getResources().getStringArray(
262 com.android.internal.R.array.config_locationProviderPackageNames);
263 }
264 });
265
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700266 if (D) Log.d(TAG, "Constructed");
267
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700268 // most startup is deferred until systemRunning()
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700269 }
270
Svetoslav Ganova0027152013-06-25 14:59:53 -0700271 public void systemRunning() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700272 synchronized (mLock) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700273 if (D) Log.d(TAG, "systemRunning()");
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700274
Victoria Lease5cd731a2012-12-19 15:04:21 -0800275 // fetch package manager
276 mPackageManager = mContext.getPackageManager();
277
Victoria Lease0aa28602013-05-29 15:28:26 -0700278 // fetch power manager
279 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
Victoria Lease5cd731a2012-12-19 15:04:21 -0800280
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800281 // fetch activity manager
282 mActivityManager
283 = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
284
Victoria Lease5cd731a2012-12-19 15:04:21 -0800285 // prepare worker thread
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700286 mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper());
Victoria Lease5cd731a2012-12-19 15:04:21 -0800287
288 // prepare mLocationHandler's dependents
289 mLocationFudger = new LocationFudger(mContext, mLocationHandler);
290 mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
291 mBlacklist.init();
292 mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
293
Dianne Hackbornc2293022013-02-06 23:14:49 -0800294 // Monitor for app ops mode changes.
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700295 AppOpsManager.OnOpChangedListener callback
296 = new AppOpsManager.OnOpChangedInternalListener() {
297 public void onOpChanged(int op, String packageName) {
Dianne Hackbornc2293022013-02-06 23:14:49 -0800298 synchronized (mLock) {
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700299 for (Receiver receiver : mReceivers.values()) {
300 receiver.updateMonitoring(true);
301 }
Dianne Hackbornc2293022013-02-06 23:14:49 -0800302 applyAllProviderRequirementsLocked();
303 }
304 }
305 };
306 mAppOps.startWatchingMode(AppOpsManager.OP_COARSE_LOCATION, null, callback);
307
David Christieb870dbf2015-06-22 12:42:53 -0700308 PackageManager.OnPermissionsChangedListener permissionListener
309 = new PackageManager.OnPermissionsChangedListener() {
310 @Override
311 public void onPermissionsChanged(final int uid) {
312 synchronized (mLock) {
313 applyAllProviderRequirementsLocked();
314 }
315 }
316 };
317 mPackageManager.addOnPermissionsChangeListener(permissionListener);
318
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800319 // listen for background/foreground changes
320 ActivityManager.OnUidImportanceListener uidImportanceListener
321 = new ActivityManager.OnUidImportanceListener() {
322 @Override
323 public void onUidImportance(int uid, int importance) {
324 boolean foreground = isImportanceForeground(importance);
325 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
326 synchronized (mLock) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800327 for (Entry<String, ArrayList<UpdateRecord>> entry
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800328 : mRecordsByProvider.entrySet()) {
329 String provider = entry.getKey();
330 for (UpdateRecord record : entry.getValue()) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800331 if (record.mReceiver.mIdentity.mUid == uid
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800332 && record.mIsForegroundUid != foreground) {
333 if (D) Log.d(TAG, "request from uid " + uid + " is now "
334 + (foreground ? "foreground" : "background)"));
335 record.mIsForegroundUid = foreground;
336
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800337 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800338 affectedProviders.add(provider);
339 }
340 }
341 }
342 }
343 for (String provider : affectedProviders) {
344 applyRequirementsLocked(provider);
345 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800346
347 for (Entry<IGnssMeasurementsListener, Identity> entry
348 : mGnssMeasurementsListeners.entrySet()) {
349 if (entry.getValue().mUid == uid) {
350 if (D) Log.d(TAG, "gnss measurements listener from uid " + uid
351 + " is now " + (foreground ? "foreground" : "background)"));
352 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
353 mGnssMeasurementsProvider.addListener(entry.getKey());
354 } else {
355 mGnssMeasurementsProvider.removeListener(entry.getKey());
356 }
357 }
358 }
359
360 for (Entry<IGnssNavigationMessageListener, Identity> entry
361 : mGnssNavigationMessageListeners.entrySet()) {
362 if (entry.getValue().mUid == uid) {
363 if (D) Log.d(TAG, "gnss navigation message listener from uid "
364 + uid + " is now "
365 + (foreground ? "foreground" : "background)"));
366 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
367 mGnssNavigationMessageProvider.addListener(entry.getKey());
368 } else {
369 mGnssNavigationMessageProvider.removeListener(entry.getKey());
370 }
371 }
372 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800373 }
374
375 }
376 };
377 mActivityManager.addOnUidImportanceListener(uidImportanceListener,
378 ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE);
379
Amith Yamasanib27528d2014-06-05 15:02:10 -0700380 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
381 updateUserProfiles(mCurrentUserId);
382
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800383 updateBackgroundThrottlingWhitelistLocked();
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800384
Victoria Lease5cd731a2012-12-19 15:04:21 -0800385 // prepare providers
386 loadProvidersLocked();
387 updateProvidersLocked();
388 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700389
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700390 // listen for settings changes
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700391 mContext.getContentResolver().registerContentObserver(
Laurent Tu75defb62012-11-01 16:21:52 -0700392 Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700393 new ContentObserver(mLocationHandler) {
Victoria Lease5cd731a2012-12-19 15:04:21 -0800394 @Override
395 public void onChange(boolean selfChange) {
396 synchronized (mLock) {
397 updateProvidersLocked();
398 }
399 }
400 }, UserHandle.USER_ALL);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800401 mContext.getContentResolver().registerContentObserver(
402 Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS),
403 true,
404 new ContentObserver(mLocationHandler) {
405 @Override
406 public void onChange(boolean selfChange) {
407 synchronized (mLock) {
408 updateProvidersLocked();
409 }
410 }
411 }, UserHandle.USER_ALL);
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800412 mContext.getContentResolver().registerContentObserver(
413 Settings.Global.getUriFor(
414 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
415 true,
416 new ContentObserver(mLocationHandler) {
417 @Override
418 public void onChange(boolean selfChange) {
419 synchronized (mLock) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800420 updateBackgroundThrottlingWhitelistLocked();
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800421 updateProvidersLocked();
422 }
423 }
424 }, UserHandle.USER_ALL);
Victoria Lease5cd731a2012-12-19 15:04:21 -0800425 mPackageMonitor.register(mContext, mLocationHandler.getLooper(), true);
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700426
Victoria Lease38389b62012-09-30 11:44:22 -0700427 // listen for user change
428 IntentFilter intentFilter = new IntentFilter();
429 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700430 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
431 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
destradaab9026982015-08-27 17:34:54 -0700432 intentFilter.addAction(Intent.ACTION_SHUTDOWN);
Victoria Lease38389b62012-09-30 11:44:22 -0700433
434 mContext.registerReceiverAsUser(new BroadcastReceiver() {
435 @Override
436 public void onReceive(Context context, Intent intent) {
437 String action = intent.getAction();
438 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
439 switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
Amith Yamasanib27528d2014-06-05 15:02:10 -0700440 } else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)
441 || Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
442 updateUserProfiles(mCurrentUserId);
destradaab9026982015-08-27 17:34:54 -0700443 } else if (Intent.ACTION_SHUTDOWN.equals(action)) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700444 // shutdown only if UserId indicates whole system, not just one user
445 if(D) Log.d(TAG, "Shutdown received with UserId: " + getSendingUserId());
446 if (getSendingUserId() == UserHandle.USER_ALL) {
447 shutdownComponents();
448 }
Victoria Lease38389b62012-09-30 11:44:22 -0700449 }
450 }
Victoria Lease5cd731a2012-12-19 15:04:21 -0800451 }, UserHandle.ALL, intentFilter, null, mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700452 }
453
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800454 private static boolean isImportanceForeground(int importance) {
455 return importance <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
456 }
457
Amith Yamasanib27528d2014-06-05 15:02:10 -0700458 /**
destradaab9026982015-08-27 17:34:54 -0700459 * Provides a way for components held by the {@link LocationManagerService} to clean-up
460 * gracefully on system's shutdown.
461 *
462 * NOTES:
463 * 1) Only provides a chance to clean-up on an opt-in basis. This guarantees back-compat
464 * support for components that do not wish to handle such event.
465 */
466 private void shutdownComponents() {
467 if(D) Log.d(TAG, "Shutting down components...");
468
469 LocationProviderInterface gpsProvider = mProvidersByName.get(LocationManager.GPS_PROVIDER);
470 if (gpsProvider != null && gpsProvider.isEnabled()) {
471 gpsProvider.disable();
472 }
473
destradaa2e385072015-10-14 16:45:58 -0700474 // it is needed to check if FLP HW provider is supported before accessing the instance, this
475 // avoids an exception to be thrown by the singleton factory method
476 if (FlpHardwareProvider.isSupported()) {
477 FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
destradaab9026982015-08-27 17:34:54 -0700478 flpHardwareProvider.cleanup();
479 }
480 }
481
482 /**
Amith Yamasanib27528d2014-06-05 15:02:10 -0700483 * Makes a list of userids that are related to the current user. This is
484 * relevant when using managed profiles. Otherwise the list only contains
485 * the current user.
486 *
487 * @param currentUserId the current user, who might have an alter-ego.
488 */
489 void updateUserProfiles(int currentUserId) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700490 int[] profileIds = mUserManager.getProfileIdsWithDisabled(currentUserId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700491 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700492 mCurrentUserProfiles = profileIds;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700493 }
494 }
495
496 /**
497 * Checks if the specified userId matches any of the current foreground
498 * users stored in mCurrentUserProfiles.
499 */
500 private boolean isCurrentProfile(int userId) {
501 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700502 return ArrayUtils.contains(mCurrentUserProfiles, userId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700503 }
504 }
505
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500506 private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) {
507 PackageManager pm = mContext.getPackageManager();
508 String systemPackageName = mContext.getPackageName();
509 ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
510
511 List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
512 new Intent(FUSED_LOCATION_SERVICE_ACTION),
513 PackageManager.GET_META_DATA, mCurrentUserId);
514 for (ResolveInfo rInfo : rInfos) {
515 String packageName = rInfo.serviceInfo.packageName;
516
517 // Check that the signature is in the list of supported sigs. If it's not in
518 // this list the standard provider binding logic won't bind to it.
519 try {
520 PackageInfo pInfo;
521 pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
522 if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
523 Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
524 ", but has wrong signature, ignoring");
525 continue;
526 }
527 } catch (NameNotFoundException e) {
528 Log.e(TAG, "missing package: " + packageName);
529 continue;
530 }
531
532 // Get the version info
533 if (rInfo.serviceInfo.metaData == null) {
534 Log.w(TAG, "Found fused provider without metadata: " + packageName);
535 continue;
536 }
537
538 int version = rInfo.serviceInfo.metaData.getInt(
539 ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
540 if (version == 0) {
541 // This should be the fallback fused location provider.
542
543 // Make sure it's in the system partition.
544 if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
545 if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
546 continue;
547 }
548
549 // Check that the fallback is signed the same as the OS
550 // as a proxy for coreApp="true"
551 if (pm.checkSignatures(systemPackageName, packageName)
552 != PackageManager.SIGNATURE_MATCH) {
553 if (D) Log.d(TAG, "Fallback candidate not signed the same as system: "
554 + packageName);
555 continue;
556 }
557
558 // Found a valid fallback.
559 if (D) Log.d(TAG, "Found fallback provider: " + packageName);
560 return;
561 } else {
562 if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
563 }
564 }
565
566 throw new IllegalStateException("Unable to find a fused location provider that is in the "
567 + "system partition with version 0 and signed with the platform certificate. "
568 + "Such a package is needed to provide a default fused location provider in the "
569 + "event that no other fused location provider has been installed or is currently "
570 + "available. For example, coreOnly boot mode when decrypting the data "
571 + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
572 }
573
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700574 private void loadProvidersLocked() {
Victoria Lease5c24fd02012-10-01 11:00:50 -0700575 // create a passive location provider, which is always enabled
576 PassiveProvider passiveProvider = new PassiveProvider(this);
577 addProviderLocked(passiveProvider);
578 mEnabledProviders.add(passiveProvider.getName());
579 mPassiveProvider = passiveProvider;
580
Lifu Tang30f95a72016-01-07 23:20:38 -0800581 if (GnssLocationProvider.isSupported()) {
Wei Liu5241a4c2015-05-11 14:00:36 -0700582 // Create a gps location provider
Lifu Tang30f95a72016-01-07 23:20:38 -0800583 GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this,
Wei Liu5241a4c2015-05-11 14:00:36 -0700584 mLocationHandler.getLooper());
Lifu Tang9363b942016-02-16 18:07:00 -0800585 mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
Wyatt Rileycf879db2017-01-12 13:57:38 -0800586 mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800587 mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
588 mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
589 addProviderLocked(gnssProvider);
590 mRealProviders.put(LocationManager.GPS_PROVIDER, gnssProvider);
Lifu Tang818aa2c2016-02-01 01:52:00 -0800591 mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
592 mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800593 mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700594 }
595
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700596 /*
597 Load package name(s) containing location provider support.
598 These packages can contain services implementing location providers:
599 Geocoder Provider, Network Location Provider, and
600 Fused Location Provider. They will each be searched for
601 service components implementing these providers.
602 The location framework also has support for installation
603 of new location providers at run-time. The new package does not
604 have to be explicitly listed here, however it must have a signature
605 that matches the signature of at least one package on this list.
606 */
607 Resources resources = mContext.getResources();
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800608 ArrayList<String> providerPackageNames = new ArrayList<>();
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500609 String[] pkgs = resources.getStringArray(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700610 com.android.internal.R.array.config_locationProviderPackageNames);
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500611 if (D) Log.d(TAG, "certificates for location providers pulled from: " +
612 Arrays.toString(pkgs));
613 if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));
614
615 ensureFallbackFusedProviderPresentLocked(providerPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700616
617 // bind to network provider
618 LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
619 mContext,
620 LocationManager.NETWORK_PROVIDER,
621 NETWORK_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700622 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
623 com.android.internal.R.string.config_networkLocationProviderPackageName,
624 com.android.internal.R.array.config_locationProviderPackageNames,
625 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700626 if (networkProvider != null) {
627 mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
628 mProxyProviders.add(networkProvider);
629 addProviderLocked(networkProvider);
630 } else {
631 Slog.w(TAG, "no network location provider found");
632 }
633
634 // bind to fused provider
635 LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind(
636 mContext,
637 LocationManager.FUSED_PROVIDER,
638 FUSED_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700639 com.android.internal.R.bool.config_enableFusedLocationOverlay,
640 com.android.internal.R.string.config_fusedLocationProviderPackageName,
641 com.android.internal.R.array.config_locationProviderPackageNames,
642 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700643 if (fusedLocationProvider != null) {
644 addProviderLocked(fusedLocationProvider);
645 mProxyProviders.add(fusedLocationProvider);
646 mEnabledProviders.add(fusedLocationProvider.getName());
Kenny Rootc3575182012-10-09 12:44:40 -0700647 mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700648 } else {
649 Slog.e(TAG, "no fused location provider found",
650 new IllegalStateException("Location service needs a fused location provider"));
651 }
652
653 // bind to geocoder provider
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700654 mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
655 com.android.internal.R.bool.config_enableGeocoderOverlay,
656 com.android.internal.R.string.config_geocoderProviderPackageName,
657 com.android.internal.R.array.config_locationProviderPackageNames,
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800658 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700659 if (mGeocodeProvider == null) {
660 Slog.e(TAG, "no geocoder provider found");
661 }
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700662
destradaaa4fa3b52014-07-09 10:46:39 -0700663 // bind to fused hardware provider if supported
destradaabeea4422014-07-30 18:17:21 -0700664 // in devices without support, requesting an instance of FlpHardwareProvider will raise an
665 // exception, so make sure we only do that when supported
666 FlpHardwareProvider flpHardwareProvider;
destradaa5ce66d82014-05-28 18:24:08 -0700667 if (FlpHardwareProvider.isSupported()) {
destradaabeea4422014-07-30 18:17:21 -0700668 flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
destradaaf9a274c2014-07-25 15:11:56 -0700669 FusedProxy fusedProxy = FusedProxy.createAndBind(
670 mContext,
671 mLocationHandler,
672 flpHardwareProvider.getLocationHardware(),
673 com.android.internal.R.bool.config_enableHardwareFlpOverlay,
674 com.android.internal.R.string.config_hardwareFlpPackageName,
675 com.android.internal.R.array.config_locationProviderPackageNames);
676 if (fusedProxy == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700677 Slog.d(TAG, "Unable to bind FusedProxy.");
destradaaf9a274c2014-07-25 15:11:56 -0700678 }
destradaacfbdcd22014-04-30 11:29:11 -0700679 } else {
destradaabeea4422014-07-30 18:17:21 -0700680 flpHardwareProvider = null;
destradaa6b4893a2016-05-03 15:33:43 -0700681 Slog.d(TAG, "FLP HAL not supported");
destradaaf9a274c2014-07-25 15:11:56 -0700682 }
683
684 // bind to geofence provider
685 GeofenceProxy provider = GeofenceProxy.createAndBind(
686 mContext,com.android.internal.R.bool.config_enableGeofenceOverlay,
687 com.android.internal.R.string.config_geofenceProviderPackageName,
688 com.android.internal.R.array.config_locationProviderPackageNames,
689 mLocationHandler,
Wei Liu5241a4c2015-05-11 14:00:36 -0700690 mGpsGeofenceProxy,
destradaabeea4422014-07-30 18:17:21 -0700691 flpHardwareProvider != null ? flpHardwareProvider.getGeofenceHardware() : null);
destradaaf9a274c2014-07-25 15:11:56 -0700692 if (provider == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700693 Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
destradaa0682809a2013-08-12 18:50:30 -0700694 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900695
destradaa6e2fe752015-06-23 17:25:53 -0700696 // bind to hardware activity recognition
697 boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
698 ActivityRecognitionHardware activityRecognitionHardware = null;
699 if (activityRecognitionHardwareIsSupported) {
700 activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
destradaaa4fa3b52014-07-09 10:46:39 -0700701 } else {
destradaa6b4893a2016-05-03 15:33:43 -0700702 Slog.d(TAG, "Hardware Activity-Recognition not supported.");
destradaaa4fa3b52014-07-09 10:46:39 -0700703 }
destradaa6e2fe752015-06-23 17:25:53 -0700704 ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
705 mContext,
706 mLocationHandler,
707 activityRecognitionHardwareIsSupported,
708 activityRecognitionHardware,
709 com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
710 com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
711 com.android.internal.R.array.config_locationProviderPackageNames);
712 if (proxy == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700713 Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
destradaa6e2fe752015-06-23 17:25:53 -0700714 }
destradaaa4fa3b52014-07-09 10:46:39 -0700715
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900716 String[] testProviderStrings = resources.getStringArray(
717 com.android.internal.R.array.config_testLocationProviders);
718 for (String testProviderString : testProviderStrings) {
719 String fragments[] = testProviderString.split(",");
720 String name = fragments[0].trim();
721 if (mProvidersByName.get(name) != null) {
722 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
723 }
724 ProviderProperties properties = new ProviderProperties(
725 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
726 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
727 Boolean.parseBoolean(fragments[3]) /* requiresCell */,
728 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
729 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
730 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
731 Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
732 Integer.parseInt(fragments[8]) /* powerRequirement */,
733 Integer.parseInt(fragments[9]) /* accuracy */);
734 addTestProviderLocked(name, properties);
735 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700736 }
Mike Lockwood9637d472009-04-02 21:41:57 -0700737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738 /**
Victoria Lease38389b62012-09-30 11:44:22 -0700739 * Called when the device's active user changes.
740 * @param userId the new active user's UserId
741 */
742 private void switchUser(int userId) {
Jianzheng Zhoud5c69462013-10-10 14:02:09 +0800743 if (mCurrentUserId == userId) {
744 return;
745 }
Victoria Lease83762d22012-10-03 13:51:17 -0700746 mBlacklist.switchUser(userId);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800747 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED);
Victoria Lease38389b62012-09-30 11:44:22 -0700748 synchronized (mLock) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700749 mLastLocation.clear();
David Christie1b9b7b12013-04-15 15:31:11 -0700750 mLastLocationCoarseInterval.clear();
Victoria Leaseb711d572012-10-02 13:14:11 -0700751 for (LocationProviderInterface p : mProviders) {
Amith Yamasanib27528d2014-06-05 15:02:10 -0700752 updateProviderListenersLocked(p.getName(), false);
Victoria Leaseb711d572012-10-02 13:14:11 -0700753 }
Victoria Lease38389b62012-09-30 11:44:22 -0700754 mCurrentUserId = userId;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700755 updateUserProfiles(userId);
Victoria Leaseb711d572012-10-02 13:14:11 -0700756 updateProvidersLocked();
Victoria Lease38389b62012-09-30 11:44:22 -0700757 }
758 }
759
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800760 private static final class Identity {
761 final int mUid;
762 final int mPid;
763 final String mPackageName;
764
765 Identity(int uid, int pid, String packageName) {
766 mUid = uid;
767 mPid = pid;
768 mPackageName = packageName;
769 }
770 }
771
Victoria Lease38389b62012-09-30 11:44:22 -0700772 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773 * A wrapper class holding either an ILocationListener or a PendingIntent to receive
774 * location updates.
775 */
Mike Lockwood48f17512009-04-23 09:12:08 -0700776 private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800777 final Identity mIdentity;
Victoria Lease37425c32012-10-16 16:08:48 -0700778 final int mAllowedResolutionLevel; // resolution level allowed to receiver
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 final ILocationListener mListener;
781 final PendingIntent mPendingIntent;
David Christie82edc9b2013-07-19 11:31:42 -0700782 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
David Christie40e57822013-07-30 11:36:48 -0700783 final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 final Object mKey;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700785
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800786 final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<>();
Nick Pellyf1be6862012-05-15 10:53:42 -0700787
David Christie0b837452013-07-29 16:02:13 -0700788 // True if app ops has started monitoring this receiver for locations.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700789 boolean mOpMonitoring;
David Christie0b837452013-07-29 16:02:13 -0700790 // True if app ops has started monitoring this receiver for high power (gps) locations.
791 boolean mOpHighPowerMonitoring;
Mike Lockwood48f17512009-04-23 09:12:08 -0700792 int mPendingBroadcasts;
Victoria Lease0aa28602013-05-29 15:28:26 -0700793 PowerManager.WakeLock mWakeLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700795 Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -0700796 String packageName, WorkSource workSource, boolean hideFromAppOps) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 mListener = listener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 mPendingIntent = intent;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700799 if (listener != null) {
800 mKey = listener.asBinder();
801 } else {
802 mKey = intent;
803 }
Victoria Lease37425c32012-10-16 16:08:48 -0700804 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800805 mIdentity = new Identity(uid, pid, packageName);
David Christie82edc9b2013-07-19 11:31:42 -0700806 if (workSource != null && workSource.size() <= 0) {
807 workSource = null;
808 }
809 mWorkSource = workSource;
David Christie40e57822013-07-30 11:36:48 -0700810 mHideFromAppOps = hideFromAppOps;
Victoria Lease0aa28602013-05-29 15:28:26 -0700811
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700812 updateMonitoring(true);
813
Victoria Lease0aa28602013-05-29 15:28:26 -0700814 // construct/configure wakelock
815 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
David Christie82edc9b2013-07-19 11:31:42 -0700816 if (workSource == null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800817 workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -0700818 }
819 mWakeLock.setWorkSource(workSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800820 }
821
822 @Override
823 public boolean equals(Object otherObj) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800824 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825 }
826
827 @Override
828 public int hashCode() {
829 return mKey.hashCode();
830 }
Mike Lockwood3681f262009-05-12 10:52:03 -0400831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800832 @Override
833 public String toString() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700834 StringBuilder s = new StringBuilder();
835 s.append("Reciever[");
836 s.append(Integer.toHexString(System.identityHashCode(this)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800837 if (mListener != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700838 s.append(" listener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800839 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700840 s.append(" intent");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800841 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700842 for (String p : mUpdateRecords.keySet()) {
843 s.append(" ").append(mUpdateRecords.get(p).toString());
844 }
845 s.append("]");
846 return s.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800847 }
848
David Christie15b31912013-08-13 15:54:32 -0700849 /**
850 * Update AppOp monitoring for this receiver.
851 *
852 * @param allow If true receiver is currently active, if false it's been removed.
853 */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700854 public void updateMonitoring(boolean allow) {
David Christie40e57822013-07-30 11:36:48 -0700855 if (mHideFromAppOps) {
856 return;
857 }
858
David Christie15b31912013-08-13 15:54:32 -0700859 boolean requestingLocation = false;
860 boolean requestingHighPowerLocation = false;
861 if (allow) {
862 // See if receiver has any enabled update records. Also note if any update records
863 // are high power (has a high power provider with an interval under a threshold).
864 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
865 if (isAllowedByCurrentUserSettingsLocked(updateRecord.mProvider)) {
866 requestingLocation = true;
867 LocationProviderInterface locationProvider
David Christie2ff96af2014-01-30 16:09:37 -0800868 = mProvidersByName.get(updateRecord.mProvider);
David Christie15b31912013-08-13 15:54:32 -0700869 ProviderProperties properties = locationProvider != null
870 ? locationProvider.getProperties() : null;
871 if (properties != null
872 && properties.mPowerRequirement == Criteria.POWER_HIGH
873 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
874 requestingHighPowerLocation = true;
875 break;
876 }
877 }
878 }
879 }
880
David Christie0b837452013-07-29 16:02:13 -0700881 // First update monitoring of any location request (including high power).
David Christie15b31912013-08-13 15:54:32 -0700882 mOpMonitoring = updateMonitoring(
883 requestingLocation,
884 mOpMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700885 AppOpsManager.OP_MONITOR_LOCATION);
886
887 // Now update monitoring of high power requests only.
David Christiec750c1f2013-08-08 12:56:57 -0700888 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
David Christie15b31912013-08-13 15:54:32 -0700889 mOpHighPowerMonitoring = updateMonitoring(
890 requestingHighPowerLocation,
891 mOpHighPowerMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700892 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
David Christiec750c1f2013-08-08 12:56:57 -0700893 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
David Christie15b31912013-08-13 15:54:32 -0700894 // Send an intent to notify that a high power request has been added/removed.
David Christiec750c1f2013-08-08 12:56:57 -0700895 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
896 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
897 }
David Christie0b837452013-07-29 16:02:13 -0700898 }
899
900 /**
901 * Update AppOps monitoring for a single location request and op type.
902 *
903 * @param allowMonitoring True if monitoring is allowed for this request/op.
904 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
905 * @param op AppOps code for the op to update.
906 * @return True if monitoring is on for this request/op after updating.
907 */
908 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
909 int op) {
910 if (!currentlyMonitoring) {
911 if (allowMonitoring) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800912 return mAppOps.startOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700913 == AppOpsManager.MODE_ALLOWED;
914 }
915 } else {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800916 if (!allowMonitoring
917 || mAppOps.checkOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700918 != AppOpsManager.MODE_ALLOWED) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800919 mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName);
David Christie0b837452013-07-29 16:02:13 -0700920 return false;
921 }
922 }
923
924 return currentlyMonitoring;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700925 }
926
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800927 public boolean isListener() {
928 return mListener != null;
929 }
930
931 public boolean isPendingIntent() {
932 return mPendingIntent != null;
933 }
934
935 public ILocationListener getListener() {
936 if (mListener != null) {
937 return mListener;
938 }
939 throw new IllegalStateException("Request for non-existent listener");
940 }
941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800942 public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
943 if (mListener != null) {
944 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700945 synchronized (this) {
946 // synchronize to ensure incrementPendingBroadcastsLocked()
947 // is called before decrementPendingBroadcasts()
948 mListener.onStatusChanged(provider, status, extras);
Nick Pellye0fd6932012-07-11 10:26:13 -0700949 // call this after broadcasting so we do not increment
950 // if we throw an exeption.
951 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -0700952 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 } catch (RemoteException e) {
954 return false;
955 }
956 } else {
957 Intent statusChanged = new Intent();
Victoria Lease61ecb022012-11-13 15:12:51 -0800958 statusChanged.putExtras(new Bundle(extras));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800959 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
960 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700961 synchronized (this) {
962 // synchronize to ensure incrementPendingBroadcastsLocked()
963 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700964 mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -0700965 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -0700966 // call this after broadcasting so we do not increment
967 // if we throw an exeption.
968 incrementPendingBroadcastsLocked();
969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970 } catch (PendingIntent.CanceledException e) {
971 return false;
972 }
973 }
974 return true;
975 }
976
977 public boolean callLocationChangedLocked(Location location) {
978 if (mListener != null) {
979 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700980 synchronized (this) {
981 // synchronize to ensure incrementPendingBroadcastsLocked()
982 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c5406a2012-11-29 16:18:01 -0800983 mListener.onLocationChanged(new Location(location));
Nick Pellye0fd6932012-07-11 10:26:13 -0700984 // call this after broadcasting so we do not increment
985 // if we throw an exeption.
986 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -0700987 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 } catch (RemoteException e) {
989 return false;
990 }
991 } else {
992 Intent locationChanged = new Intent();
Victoria Lease61ecb022012-11-13 15:12:51 -0800993 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, new Location(location));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700995 synchronized (this) {
996 // synchronize to ensure incrementPendingBroadcastsLocked()
997 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700998 mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -0700999 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -07001000 // call this after broadcasting so we do not increment
1001 // if we throw an exeption.
1002 incrementPendingBroadcastsLocked();
1003 }
1004 } catch (PendingIntent.CanceledException e) {
1005 return false;
1006 }
1007 }
1008 return true;
1009 }
1010
1011 public boolean callProviderEnabledLocked(String provider, boolean enabled) {
David Christie15b31912013-08-13 15:54:32 -07001012 // First update AppOp monitoring.
1013 // An app may get/lose location access as providers are enabled/disabled.
1014 updateMonitoring(true);
1015
Mike Lockwood48f17512009-04-23 09:12:08 -07001016 if (mListener != null) {
1017 try {
1018 synchronized (this) {
1019 // synchronize to ensure incrementPendingBroadcastsLocked()
1020 // is called before decrementPendingBroadcasts()
1021 if (enabled) {
1022 mListener.onProviderEnabled(provider);
1023 } else {
1024 mListener.onProviderDisabled(provider);
1025 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001026 // call this after broadcasting so we do not increment
1027 // if we throw an exeption.
1028 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001029 }
1030 } catch (RemoteException e) {
1031 return false;
1032 }
1033 } else {
1034 Intent providerIntent = new Intent();
1035 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1036 try {
1037 synchronized (this) {
1038 // synchronize to ensure incrementPendingBroadcastsLocked()
1039 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001040 mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -07001041 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -07001042 // call this after broadcasting so we do not increment
1043 // if we throw an exeption.
1044 incrementPendingBroadcastsLocked();
1045 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001046 } catch (PendingIntent.CanceledException e) {
1047 return false;
1048 }
1049 }
1050 return true;
1051 }
1052
Nick Pellyf1be6862012-05-15 10:53:42 -07001053 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 public void binderDied() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001055 if (D) Log.d(TAG, "Location listener died");
1056
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001057 synchronized (mLock) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058 removeUpdatesLocked(this);
1059 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001060 synchronized (this) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001061 clearPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001062 }
1063 }
1064
Nick Pellye0fd6932012-07-11 10:26:13 -07001065 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001066 public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1067 int resultCode, String resultData, Bundle resultExtras) {
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001068 synchronized (this) {
1069 decrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001070 }
1071 }
1072
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001073 // this must be called while synchronized by caller in a synchronized block
1074 // containing the sending of the broadcaset
1075 private void incrementPendingBroadcastsLocked() {
1076 if (mPendingBroadcasts++ == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001077 mWakeLock.acquire();
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001078 }
1079 }
1080
1081 private void decrementPendingBroadcastsLocked() {
1082 if (--mPendingBroadcasts == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001083 if (mWakeLock.isHeld()) {
1084 mWakeLock.release();
1085 }
1086 }
1087 }
1088
1089 public void clearPendingBroadcastsLocked() {
1090 if (mPendingBroadcasts > 0) {
1091 mPendingBroadcasts = 0;
1092 if (mWakeLock.isHeld()) {
1093 mWakeLock.release();
1094 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001095 }
1096 }
1097 }
1098
Nick Pellye0fd6932012-07-11 10:26:13 -07001099 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001100 public void locationCallbackFinished(ILocationListener listener) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001101 //Do not use getReceiverLocked here as that will add the ILocationListener to
Joshua Bartel080b61b2009-10-05 12:44:46 -04001102 //the receiver list if it is not found. If it is not found then the
1103 //LocationListener was removed when it had a pending broadcast and should
1104 //not be added back.
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001105 synchronized (mLock) {
1106 IBinder binder = listener.asBinder();
1107 Receiver receiver = mReceivers.get(binder);
1108 if (receiver != null) {
1109 synchronized (receiver) {
1110 // so wakelock calls will succeed
1111 long identity = Binder.clearCallingIdentity();
1112 receiver.decrementPendingBroadcastsLocked();
1113 Binder.restoreCallingIdentity(identity);
David Christie2ff96af2014-01-30 16:09:37 -08001114 }
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001115 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001116 }
1117 }
1118
Lifu Tang82f893d2016-01-21 18:15:33 -08001119 /**
Lifu Tang9363b942016-02-16 18:07:00 -08001120 * Returns the system information of the GNSS hardware.
Lifu Tang82f893d2016-01-21 18:15:33 -08001121 */
1122 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001123 public int getGnssYearOfHardware() {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001124 if (mGnssSystemInfoProvider != null) {
Lifu Tang9363b942016-02-16 18:07:00 -08001125 return mGnssSystemInfoProvider.getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001126 } else {
1127 return 0;
1128 }
1129 }
1130
Wyatt Rileycf879db2017-01-12 13:57:38 -08001131 /**
1132 * Runs some checks for GNSS (FINE) level permissions, used by several methods which directly
1133 * (try to) access GNSS information at this layer.
1134 */
1135 private boolean hasGnssPermissions(String packageName) {
1136 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
1137 checkResolutionLevelIsSufficientForProviderUse(
1138 allowedResolutionLevel,
1139 LocationManager.GPS_PROVIDER);
1140
1141 int pid = Binder.getCallingPid();
1142 int uid = Binder.getCallingUid();
1143 long identity = Binder.clearCallingIdentity();
1144 boolean hasLocationAccess;
1145 try {
1146 hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
1147 } finally {
1148 Binder.restoreCallingIdentity(identity);
1149 }
1150
1151 return hasLocationAccess;
1152 }
1153
1154 /**
1155 * Returns the GNSS batching size, if available.
1156 */
1157 @Override
1158 public int getGnssBatchSize(String packageName) {
1159 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1160 "Location Hardware permission not granted to access hardware batching");
1161
1162 if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
1163 return mGnssBatchingProvider.getSize();
1164 } else {
1165 return 0;
1166 }
1167 }
1168
1169 /**
1170 * Adds a callback for GNSS Batching events, if permissions allow, which are transported
1171 * to potentially multiple listeners by the BatchedLocationCallbackTransport above this.
1172 */
1173 @Override
1174 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) {
1175 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1176 "Location Hardware permission not granted to access hardware batching");
1177
1178 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1179 return false;
1180 }
1181
1182 mGnssBatchingCallback = callback;
1183 mGnssBatchingDeathCallback = new LinkedCallback(callback);
1184 try {
1185 callback.asBinder().linkToDeath(mGnssBatchingDeathCallback, 0 /* flags */);
1186 } catch (RemoteException e) {
1187 // if the remote process registering the listener is already dead, just swallow the
1188 // exception and return
1189 Log.e(TAG, "Remote listener already died.", e);
1190 return false;
1191 }
1192
1193 return true;
1194 }
1195
1196 private class LinkedCallback implements IBinder.DeathRecipient {
1197 private final IBatchedLocationCallback mCallback;
1198
1199 public LinkedCallback(@NonNull IBatchedLocationCallback callback) {
1200 mCallback = callback;
1201 }
1202
1203 @NonNull
1204 public IBatchedLocationCallback getUnderlyingListener() {
1205 return mCallback;
1206 }
1207
1208 @Override
1209 public void binderDied() {
1210 Log.d(TAG, "Remote Batching Callback died: " + mCallback);
1211 stopGnssBatch();
1212 removeGnssBatchingCallback();
1213 }
1214 }
1215
1216 /**
1217 * Removes callback for GNSS batching
1218 */
1219 @Override
1220 public void removeGnssBatchingCallback() {
1221 try {
1222 mGnssBatchingCallback.asBinder().unlinkToDeath(mGnssBatchingDeathCallback,
1223 0 /* flags */);
1224 } catch (NoSuchElementException e) {
1225 // if the death callback isn't connected (it should be...), log error, swallow the
1226 // exception and return
1227 Log.e(TAG, "Couldn't unlink death callback.", e);
1228 }
1229 mGnssBatchingCallback = null;
1230 mGnssBatchingDeathCallback = null;
1231 }
1232
1233
1234 /**
1235 * Starts GNSS batching, if available.
1236 */
1237 @Override
1238 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
1239 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1240 "Location Hardware permission not granted to access hardware batching");
1241
1242 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1243 return false;
1244 }
1245
1246 if (mGnssBatchingInProgress) {
1247 // Current design does not expect multiple starts to be called repeatedly
1248 Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch");
1249 // Try to clean up anyway, and continue
1250 stopGnssBatch();
1251 }
1252
1253 mGnssBatchingInProgress = true;
1254 return mGnssBatchingProvider.start(periodNanos, wakeOnFifoFull);
1255 }
1256
1257 /**
1258 * Flushes a GNSS batch in progress
1259 */
1260 @Override
1261 public void flushGnssBatch(String packageName) {
1262 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1263 "Location Hardware permission not granted to access hardware batching");
1264
1265 if (!hasGnssPermissions(packageName)) {
1266 Log.e(TAG, "flushGnssBatch called without GNSS permissions");
1267 return;
1268 }
1269
1270 if (!mGnssBatchingInProgress) {
1271 Log.w(TAG, "flushGnssBatch called with no batch in progress");
1272 }
1273
1274 if (mGnssBatchingProvider != null) {
1275 mGnssBatchingProvider.flush();
1276 }
1277 }
1278
1279 /**
1280 * Stops GNSS batching
1281 */
1282 @Override
1283 public boolean stopGnssBatch() {
1284 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1285 "Location Hardware permission not granted to access hardware batching");
1286
1287 if (mGnssBatchingProvider != null) {
1288 mGnssBatchingInProgress = false;
1289 return mGnssBatchingProvider.stop();
1290 } else {
1291 return false;
1292 }
1293 }
1294
1295 @Override
1296 public void reportLocationBatch(List<Location> locations) {
1297 checkCallerIsProvider();
1298
1299 // Currently used only for GNSS locations - update permissions check if changed
1300 if (isAllowedByCurrentUserSettingsLocked(LocationManager.GPS_PROVIDER)) {
1301 if (mGnssBatchingCallback == null) {
1302 Slog.e(TAG, "reportLocationBatch() called without active Callback");
1303 return;
1304 }
1305 try {
1306 mGnssBatchingCallback.onLocationBatch(locations);
1307 } catch (RemoteException e) {
1308 Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e);
1309 }
1310 } else {
1311 Slog.w(TAG, "reportLocationBatch() called without user permission, locations blocked");
1312 }
1313 }
1314
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001315 private void addProviderLocked(LocationProviderInterface provider) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001316 mProviders.add(provider);
1317 mProvidersByName.put(provider.getName(), provider);
1318 }
1319
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001320 private void removeProviderLocked(LocationProviderInterface provider) {
1321 provider.disable();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001322 mProviders.remove(provider);
1323 mProvidersByName.remove(provider.getName());
1324 }
1325
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001326 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001327 * Returns "true" if access to the specified location provider is allowed by the current
1328 * user's settings. Access to all location providers is forbidden to non-location-provider
1329 * processes belonging to background users.
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001330 *
1331 * @param provider the name of the location provider
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001332 */
Victoria Lease09eeaec2013-02-05 11:34:13 -08001333 private boolean isAllowedByCurrentUserSettingsLocked(String provider) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001334 if (mEnabledProviders.contains(provider)) {
1335 return true;
1336 }
1337 if (mDisabledProviders.contains(provider)) {
1338 return false;
1339 }
1340 // Use system settings
1341 ContentResolver resolver = mContext.getContentResolver();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001342
Victoria Leaseb711d572012-10-02 13:14:11 -07001343 return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001344 }
1345
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001346 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001347 * Returns "true" if access to the specified location provider is allowed by the specified
1348 * user's settings. Access to all location providers is forbidden to non-location-provider
1349 * processes belonging to background users.
1350 *
1351 * @param provider the name of the location provider
1352 * @param uid the requestor's UID
Victoria Lease09eeaec2013-02-05 11:34:13 -08001353 */
1354 private boolean isAllowedByUserSettingsLocked(String provider, int uid) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001355 if (!isCurrentProfile(UserHandle.getUserId(uid)) && !isUidALocationProvider(uid)) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08001356 return false;
1357 }
1358 return isAllowedByCurrentUserSettingsLocked(provider);
1359 }
1360
1361 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001362 * Returns the permission string associated with the specified resolution level.
1363 *
1364 * @param resolutionLevel the resolution level
1365 * @return the permission string
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001366 */
Victoria Lease37425c32012-10-16 16:08:48 -07001367 private String getResolutionPermission(int resolutionLevel) {
1368 switch (resolutionLevel) {
1369 case RESOLUTION_LEVEL_FINE:
1370 return android.Manifest.permission.ACCESS_FINE_LOCATION;
1371 case RESOLUTION_LEVEL_COARSE:
1372 return android.Manifest.permission.ACCESS_COARSE_LOCATION;
1373 default:
1374 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 }
Victoria Leaseda479c52012-10-15 15:24:16 -07001376 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001377
Victoria Leaseda479c52012-10-15 15:24:16 -07001378 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001379 * Returns the resolution level allowed to the given PID/UID pair.
1380 *
1381 * @param pid the PID
1382 * @param uid the UID
1383 * @return resolution level allowed to the pid/uid pair
Victoria Leaseda479c52012-10-15 15:24:16 -07001384 */
Victoria Lease37425c32012-10-16 16:08:48 -07001385 private int getAllowedResolutionLevel(int pid, int uid) {
1386 if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
1387 pid, uid) == PackageManager.PERMISSION_GRANTED) {
1388 return RESOLUTION_LEVEL_FINE;
1389 } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
1390 pid, uid) == PackageManager.PERMISSION_GRANTED) {
1391 return RESOLUTION_LEVEL_COARSE;
1392 } else {
1393 return RESOLUTION_LEVEL_NONE;
Victoria Leaseda479c52012-10-15 15:24:16 -07001394 }
Victoria Lease4fab68b2012-09-13 13:20:59 -07001395 }
1396
1397 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001398 * Returns the resolution level allowed to the caller
1399 *
1400 * @return resolution level allowed to caller
Victoria Lease4fab68b2012-09-13 13:20:59 -07001401 */
Victoria Lease37425c32012-10-16 16:08:48 -07001402 private int getCallerAllowedResolutionLevel() {
1403 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
1404 }
1405
1406 /**
1407 * Throw SecurityException if specified resolution level is insufficient to use geofences.
1408 *
1409 * @param allowedResolutionLevel resolution level allowed to caller
1410 */
1411 private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
1412 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Lease4fab68b2012-09-13 13:20:59 -07001413 throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
1414 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001415 }
1416
Victoria Lease37425c32012-10-16 16:08:48 -07001417 /**
1418 * Return the minimum resolution level required to use the specified location provider.
1419 *
1420 * @param provider the name of the location provider
1421 * @return minimum resolution level required for provider
1422 */
1423 private int getMinimumResolutionLevelForProviderUse(String provider) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001424 if (LocationManager.GPS_PROVIDER.equals(provider) ||
1425 LocationManager.PASSIVE_PROVIDER.equals(provider)) {
1426 // gps and passive providers require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001427 return RESOLUTION_LEVEL_FINE;
Victoria Lease8dbb6342012-09-21 16:55:53 -07001428 } else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
1429 LocationManager.FUSED_PROVIDER.equals(provider)) {
1430 // network and fused providers are ok with COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001431 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001432 } else {
1433 // mock providers
1434 LocationProviderInterface lp = mMockProviders.get(provider);
1435 if (lp != null) {
1436 ProviderProperties properties = lp.getProperties();
1437 if (properties != null) {
1438 if (properties.mRequiresSatellite) {
1439 // provider requiring satellites require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001440 return RESOLUTION_LEVEL_FINE;
Laurent Tu941221c2012-10-04 14:21:52 -07001441 } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
1442 // provider requiring network and or cell require COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001443 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001444 }
1445 }
1446 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001447 }
Victoria Lease37425c32012-10-16 16:08:48 -07001448 return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
Victoria Leaseda479c52012-10-15 15:24:16 -07001449 }
1450
Victoria Lease37425c32012-10-16 16:08:48 -07001451 /**
1452 * Throw SecurityException if specified resolution level is insufficient to use the named
1453 * location provider.
1454 *
1455 * @param allowedResolutionLevel resolution level allowed to caller
1456 * @param providerName the name of the location provider
1457 */
1458 private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel,
1459 String providerName) {
1460 int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName);
1461 if (allowedResolutionLevel < requiredResolutionLevel) {
1462 switch (requiredResolutionLevel) {
1463 case RESOLUTION_LEVEL_FINE:
1464 throw new SecurityException("\"" + providerName + "\" location provider " +
1465 "requires ACCESS_FINE_LOCATION permission.");
1466 case RESOLUTION_LEVEL_COARSE:
1467 throw new SecurityException("\"" + providerName + "\" location provider " +
1468 "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
1469 default:
1470 throw new SecurityException("Insufficient permission for \"" + providerName +
1471 "\" location provider.");
Victoria Leaseda479c52012-10-15 15:24:16 -07001472 }
1473 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001474 }
1475
David Christie82edc9b2013-07-19 11:31:42 -07001476 /**
1477 * Throw SecurityException if WorkSource use is not allowed (i.e. can't blame other packages
1478 * for battery).
1479 */
David Christie40e57822013-07-30 11:36:48 -07001480 private void checkDeviceStatsAllowed() {
David Christie82edc9b2013-07-19 11:31:42 -07001481 mContext.enforceCallingOrSelfPermission(
1482 android.Manifest.permission.UPDATE_DEVICE_STATS, null);
1483 }
1484
David Christie40e57822013-07-30 11:36:48 -07001485 private void checkUpdateAppOpsAllowed() {
1486 mContext.enforceCallingOrSelfPermission(
1487 android.Manifest.permission.UPDATE_APP_OPS_STATS, null);
1488 }
1489
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001490 public static int resolutionLevelToOp(int allowedResolutionLevel) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001491 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
1492 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001493 return AppOpsManager.OP_COARSE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001494 } else {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001495 return AppOpsManager.OP_FINE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001496 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001497 }
1498 return -1;
1499 }
1500
David Christieb870dbf2015-06-22 12:42:53 -07001501 boolean reportLocationAccessNoThrow(
1502 int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001503 int op = resolutionLevelToOp(allowedResolutionLevel);
1504 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001505 if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1506 return false;
1507 }
1508 }
David Christieb870dbf2015-06-22 12:42:53 -07001509
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001510 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001511 }
1512
David Christieb870dbf2015-06-22 12:42:53 -07001513 boolean checkLocationAccess(int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001514 int op = resolutionLevelToOp(allowedResolutionLevel);
1515 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001516 if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1517 return false;
1518 }
1519 }
David Christieb870dbf2015-06-22 12:42:53 -07001520
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001521 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001522 }
1523
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001524 /**
1525 * Returns all providers by name, including passive, but excluding
Laurent Tu0d21e212012-10-02 15:33:48 -07001526 * fused, also including ones that are not permitted to
1527 * be accessed by the calling activity or are currently disabled.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001528 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001529 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530 public List<String> getAllProviders() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001531 ArrayList<String> out;
1532 synchronized (mLock) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001533 out = new ArrayList<>(mProviders.size());
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001534 for (LocationProviderInterface provider : mProviders) {
1535 String name = provider.getName();
1536 if (LocationManager.FUSED_PROVIDER.equals(name)) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07001537 continue;
1538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 out.add(name);
1540 }
1541 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001542
1543 if (D) Log.d(TAG, "getAllProviders()=" + out);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001544 return out;
1545 }
1546
Mike Lockwood03ca2162010-04-01 08:10:09 -07001547 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001548 * Return all providers by name, that match criteria and are optionally
1549 * enabled.
1550 * Can return passive provider, but never returns fused provider.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001551 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001552 @Override
1553 public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
Victoria Lease37425c32012-10-16 16:08:48 -07001554 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001555 ArrayList<String> out;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001556 int uid = Binder.getCallingUid();
Victoria Lease269518e2012-10-29 08:25:39 -07001557 long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07001558 try {
1559 synchronized (mLock) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001560 out = new ArrayList<>(mProviders.size());
Victoria Leaseb711d572012-10-02 13:14:11 -07001561 for (LocationProviderInterface provider : mProviders) {
1562 String name = provider.getName();
1563 if (LocationManager.FUSED_PROVIDER.equals(name)) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001564 continue;
1565 }
Victoria Lease37425c32012-10-16 16:08:48 -07001566 if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08001567 if (enabledOnly && !isAllowedByUserSettingsLocked(name, uid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001568 continue;
1569 }
1570 if (criteria != null && !LocationProvider.propertiesMeetCriteria(
1571 name, provider.getProperties(), criteria)) {
1572 continue;
1573 }
1574 out.add(name);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001575 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001576 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001577 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001578 } finally {
1579 Binder.restoreCallingIdentity(identity);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001580 }
1581
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001582 if (D) Log.d(TAG, "getProviders()=" + out);
1583 return out;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001584 }
1585
1586 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001587 * Return the name of the best provider given a Criteria object.
1588 * This method has been deprecated from the public API,
Victoria Lease8dbb6342012-09-21 16:55:53 -07001589 * and the whole LocationProvider (including #meetsCriteria)
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001590 * has been deprecated as well. So this method now uses
1591 * some simplified logic.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001592 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001593 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001594 public String getBestProvider(Criteria criteria, boolean enabledOnly) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001595 String result = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001596
1597 List<String> providers = getProviders(criteria, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001598 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001599 result = pickBest(providers);
1600 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1601 return result;
1602 }
1603 providers = getProviders(null, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001604 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001605 result = pickBest(providers);
1606 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1607 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001608 }
1609
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001610 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001611 return null;
1612 }
1613
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001614 private String pickBest(List<String> providers) {
Victoria Lease1925e292012-09-24 17:00:18 -07001615 if (providers.contains(LocationManager.GPS_PROVIDER)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001616 return LocationManager.GPS_PROVIDER;
Victoria Lease1925e292012-09-24 17:00:18 -07001617 } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
1618 return LocationManager.NETWORK_PROVIDER;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001619 } else {
1620 return providers.get(0);
1621 }
1622 }
1623
Nick Pellye0fd6932012-07-11 10:26:13 -07001624 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001625 public boolean providerMeetsCriteria(String provider, Criteria criteria) {
1626 LocationProviderInterface p = mProvidersByName.get(provider);
1627 if (p == null) {
1628 throw new IllegalArgumentException("provider=" + provider);
1629 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001630
1631 boolean result = LocationProvider.propertiesMeetCriteria(
1632 p.getName(), p.getProperties(), criteria);
1633 if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result);
1634 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001635 }
1636
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637 private void updateProvidersLocked() {
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001638 boolean changesMade = false;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001639 for (int i = mProviders.size() - 1; i >= 0; i--) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001640 LocationProviderInterface p = mProviders.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001641 boolean isEnabled = p.isEnabled();
1642 String name = p.getName();
Victoria Lease09eeaec2013-02-05 11:34:13 -08001643 boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001644 if (isEnabled && !shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001645 updateProviderListenersLocked(name, false);
David Christieb084fef2013-12-18 14:33:57 -08001646 // If any provider has been disabled, clear all last locations for all providers.
1647 // This is to be on the safe side in case a provider has location derived from
1648 // this disabled provider.
1649 mLastLocation.clear();
1650 mLastLocationCoarseInterval.clear();
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001651 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001652 } else if (!isEnabled && shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001653 updateProviderListenersLocked(name, true);
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001654 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001655 }
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001656 }
1657 if (changesMade) {
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001658 mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
1659 UserHandle.ALL);
Tom O'Neill40a86c22013-09-03 18:05:13 -07001660 mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
1661 UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662 }
1663 }
1664
Amith Yamasanib27528d2014-06-05 15:02:10 -07001665 private void updateProviderListenersLocked(String provider, boolean enabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001666 int listeners = 0;
1667
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001668 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001669 if (p == null) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670
1671 ArrayList<Receiver> deadReceivers = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07001672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1674 if (records != null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001675 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001676 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001677 // Sends a notification message to the receiver
1678 if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
1679 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001680 deadReceivers = new ArrayList<>();
Victoria Leaseb711d572012-10-02 13:14:11 -07001681 }
1682 deadReceivers.add(record.mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001684 listeners++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001686 }
1687 }
1688
1689 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001690 for (int i = deadReceivers.size() - 1; i >= 0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001691 removeUpdatesLocked(deadReceivers.get(i));
1692 }
1693 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001694
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001695 if (enabled) {
1696 p.enable();
1697 if (listeners > 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001698 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699 }
1700 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 p.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001703 }
1704
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001705 private void applyRequirementsLocked(String provider) {
1706 LocationProviderInterface p = mProvidersByName.get(provider);
1707 if (p == null) return;
1708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001710 WorkSource worksource = new WorkSource();
1711 ProviderRequest providerRequest = new ProviderRequest();
1712
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001713 ContentResolver resolver = mContext.getContentResolver();
1714 long backgroundThrottleInterval = Settings.Global.getLong(
1715 resolver,
1716 Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
1717 DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
1718
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001719 if (records != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001720 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001721 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
David Christieb870dbf2015-06-22 12:42:53 -07001722 if (checkLocationAccess(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001723 record.mReceiver.mIdentity.mPid,
1724 record.mReceiver.mIdentity.mUid,
1725 record.mReceiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001726 record.mReceiver.mAllowedResolutionLevel)) {
1727 LocationRequest locationRequest = record.mRequest;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001728 long interval = locationRequest.getInterval();
1729
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001730 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001731 if (!record.mIsForegroundUid) {
1732 interval = Math.max(interval, backgroundThrottleInterval);
1733 }
1734 if (interval != locationRequest.getInterval()) {
1735 locationRequest = new LocationRequest(locationRequest);
1736 locationRequest.setInterval(interval);
1737 }
1738 }
1739
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001740 providerRequest.locationRequests.add(locationRequest);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001741 if (interval < providerRequest.interval) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001742 providerRequest.reportLocation = true;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001743 providerRequest.interval = interval;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001744 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001745 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001746 }
1747 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001748
1749 if (providerRequest.reportLocation) {
1750 // calculate who to blame for power
1751 // This is somewhat arbitrary. We pick a threshold interval
1752 // that is slightly higher that the minimum interval, and
1753 // spread the blame across all applications with a request
1754 // under that threshold.
1755 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
1756 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001757 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001758 LocationRequest locationRequest = record.mRequest;
Svet Ganove998c732016-06-10 00:12:38 -07001759
1760 // Don't assign battery blame for update records whose
1761 // client has no permission to receive location data.
1762 if (!providerRequest.locationRequests.contains(locationRequest)) {
1763 continue;
1764 }
1765
Victoria Leaseb711d572012-10-02 13:14:11 -07001766 if (locationRequest.getInterval() <= thresholdInterval) {
David Christiee55c9682013-08-22 10:10:34 -07001767 if (record.mReceiver.mWorkSource != null
1768 && record.mReceiver.mWorkSource.size() > 0
1769 && record.mReceiver.mWorkSource.getName(0) != null) {
David Christie82edc9b2013-07-19 11:31:42 -07001770 // Assign blame to another work source.
David Christiee55c9682013-08-22 10:10:34 -07001771 // Can only assign blame if the WorkSource contains names.
David Christie82edc9b2013-07-19 11:31:42 -07001772 worksource.add(record.mReceiver.mWorkSource);
1773 } else {
1774 // Assign blame to caller.
1775 worksource.add(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001776 record.mReceiver.mIdentity.mUid,
1777 record.mReceiver.mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001778 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001779 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001780 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001781 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 }
1783 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001784
1785 if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
1786 p.setRequest(providerRequest, worksource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 }
1788
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001789 @Override
1790 public String[] getBackgroundThrottlingWhitelist() {
1791 synchronized (mLock) {
1792 return mBackgroundThrottlePackageWhitelist.toArray(
1793 new String[mBackgroundThrottlePackageWhitelist.size()]);
1794 }
1795 }
1796
1797 private void updateBackgroundThrottlingWhitelistLocked() {
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001798 String setting = Settings.Global.getString(
1799 mContext.getContentResolver(),
1800 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
1801 if (setting == null) {
1802 setting = "";
1803 }
1804
1805 mBackgroundThrottlePackageWhitelist.clear();
1806 mBackgroundThrottlePackageWhitelist.addAll(
1807 SystemConfig.getInstance().getAllowUnthrottledLocation());
1808 mBackgroundThrottlePackageWhitelist.addAll(
1809 Arrays.asList(setting.split(",")));
1810 }
1811
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001812 private boolean isThrottlingExemptLocked(Identity identity) {
1813 if (identity.mUid == Process.SYSTEM_UID) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001814 return true;
1815 }
1816
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001817 if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001818 return true;
1819 }
1820
1821 for (LocationProviderProxy provider : mProxyProviders) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001822 if (identity.mPackageName.equals(provider.getConnectedPackageName())) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001823 return true;
1824 }
1825 }
1826
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001827 return false;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001828 }
1829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001830 private class UpdateRecord {
1831 final String mProvider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001832 final LocationRequest mRequest;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001833 final Receiver mReceiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001834 boolean mIsForegroundUid;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001835 Location mLastFixBroadcast;
1836 long mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001837
1838 /**
1839 * Note: must be constructed with lock held.
1840 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001841 UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001842 mProvider = provider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001843 mRequest = request;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844 mReceiver = receiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001845 mIsForegroundUid = isImportanceForeground(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001846 mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847
1848 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1849 if (records == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001850 records = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001851 mRecordsByProvider.put(provider, records);
1852 }
1853 if (!records.contains(this)) {
1854 records.add(this);
1855 }
David Christie2ff96af2014-01-30 16:09:37 -08001856
1857 // Update statistics for historical location requests by package/provider
1858 mRequestStatistics.startRequesting(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001859 mReceiver.mIdentity.mPackageName, provider, request.getInterval());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001860 }
1861
1862 /**
David Christie2ff96af2014-01-30 16:09:37 -08001863 * Method to be called when a record will no longer be used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001864 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001865 void disposeLocked(boolean removeReceiver) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001866 mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider);
David Christie2ff96af2014-01-30 16:09:37 -08001867
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001868 // remove from mRecordsByProvider
1869 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
1870 if (globalRecords != null) {
1871 globalRecords.remove(this);
1872 }
1873
1874 if (!removeReceiver) return; // the caller will handle the rest
1875
1876 // remove from Receiver#mUpdateRecords
1877 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
1878 if (receiverRecords != null) {
1879 receiverRecords.remove(this.mProvider);
1880
1881 // and also remove the Receiver if it has no more update records
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001882 if (receiverRecords.size() == 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001883 removeUpdatesLocked(mReceiver);
1884 }
Mike Lockwood3a76fd62009-09-01 07:26:56 -04001885 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001886 }
1887
1888 @Override
1889 public String toString() {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001890 return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
1891 + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground" : " background")
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001892 + ")" + " " + mRequest + "]";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001893 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001894 }
1895
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001896 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -07001897 String packageName, WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001898 IBinder binder = listener.asBinder();
1899 Receiver receiver = mReceivers.get(binder);
1900 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07001901 receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
1902 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001903 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001904 receiver.getListener().asBinder().linkToDeath(receiver, 0);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001905 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001906 Slog.e(TAG, "linkToDeath failed:", e);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001907 return null;
1908 }
Wen Jingcb3ab222014-03-27 13:42:59 +08001909 mReceivers.put(binder, receiver);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001910 }
1911 return receiver;
1912 }
1913
David Christie82edc9b2013-07-19 11:31:42 -07001914 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
David Christie40e57822013-07-30 11:36:48 -07001915 WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001916 Receiver receiver = mReceivers.get(intent);
1917 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07001918 receiver = new Receiver(null, intent, pid, uid, packageName, workSource,
1919 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001920 mReceivers.put(intent, receiver);
1921 }
1922 return receiver;
1923 }
1924
Victoria Lease37425c32012-10-16 16:08:48 -07001925 /**
1926 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
1927 * and consistency requirements.
1928 *
1929 * @param request the LocationRequest from which to create a sanitized version
Victoria Lease37425c32012-10-16 16:08:48 -07001930 * @return a version of request that meets the given resolution and consistency requirements
1931 * @hide
1932 */
1933 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel) {
1934 LocationRequest sanitizedRequest = new LocationRequest(request);
1935 if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
1936 switch (sanitizedRequest.getQuality()) {
Victoria Lease09016ab2012-09-16 12:33:15 -07001937 case LocationRequest.ACCURACY_FINE:
Victoria Lease37425c32012-10-16 16:08:48 -07001938 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
Victoria Lease09016ab2012-09-16 12:33:15 -07001939 break;
1940 case LocationRequest.POWER_HIGH:
Victoria Lease37425c32012-10-16 16:08:48 -07001941 sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
Victoria Lease09016ab2012-09-16 12:33:15 -07001942 break;
1943 }
1944 // throttle
Victoria Lease37425c32012-10-16 16:08:48 -07001945 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1946 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001947 }
Victoria Lease37425c32012-10-16 16:08:48 -07001948 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1949 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001950 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07001951 }
Nick Pelly4e31c4f2012-08-13 19:35:39 -07001952 // make getFastestInterval() the minimum of interval and fastest interval
Victoria Lease37425c32012-10-16 16:08:48 -07001953 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07001954 request.setFastestInterval(request.getInterval());
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001955 }
Victoria Lease37425c32012-10-16 16:08:48 -07001956 return sanitizedRequest;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001957 }
1958
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001959 private void checkPackageName(String packageName) {
Nick Pellye0fd6932012-07-11 10:26:13 -07001960 if (packageName == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001961 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07001962 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001963 int uid = Binder.getCallingUid();
Nick Pellye0fd6932012-07-11 10:26:13 -07001964 String[] packages = mPackageManager.getPackagesForUid(uid);
1965 if (packages == null) {
1966 throw new SecurityException("invalid UID " + uid);
1967 }
1968 for (String pkg : packages) {
1969 if (packageName.equals(pkg)) return;
1970 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001971 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07001972 }
1973
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001974 private void checkPendingIntent(PendingIntent intent) {
1975 if (intent == null) {
1976 throw new IllegalArgumentException("invalid pending intent: " + intent);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001977 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001978 }
1979
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001980 private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent,
David Christie40e57822013-07-30 11:36:48 -07001981 int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001982 if (intent == null && listener == null) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001983 throw new IllegalArgumentException("need either listener or intent");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001984 } else if (intent != null && listener != null) {
1985 throw new IllegalArgumentException("cannot register both listener and intent");
1986 } else if (intent != null) {
1987 checkPendingIntent(intent);
David Christie40e57822013-07-30 11:36:48 -07001988 return getReceiverLocked(intent, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001989 } else {
David Christie40e57822013-07-30 11:36:48 -07001990 return getReceiverLocked(listener, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001991 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001992 }
1993
Nick Pellye0fd6932012-07-11 10:26:13 -07001994 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001995 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
1996 PendingIntent intent, String packageName) {
1997 if (request == null) request = DEFAULT_LOCATION_REQUEST;
1998 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07001999 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2000 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2001 request.getProvider());
David Christie82edc9b2013-07-19 11:31:42 -07002002 WorkSource workSource = request.getWorkSource();
2003 if (workSource != null && workSource.size() > 0) {
David Christie40e57822013-07-30 11:36:48 -07002004 checkDeviceStatsAllowed();
2005 }
2006 boolean hideFromAppOps = request.getHideFromAppOps();
2007 if (hideFromAppOps) {
2008 checkUpdateAppOpsAllowed();
David Christie82edc9b2013-07-19 11:31:42 -07002009 }
Victoria Lease37425c32012-10-16 16:08:48 -07002010 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002011
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002012 final int pid = Binder.getCallingPid();
2013 final int uid = Binder.getCallingUid();
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002014 // providers may use public location API's, need to clear identity
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002015 long identity = Binder.clearCallingIdentity();
2016 try {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002017 // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2018 // a location.
David Christieb870dbf2015-06-22 12:42:53 -07002019 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002020
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002021 synchronized (mLock) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002022 Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
David Christie40e57822013-07-30 11:36:48 -07002023 packageName, workSource, hideFromAppOps);
Victoria Lease37425c32012-10-16 16:08:48 -07002024 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
Mike Lockwood2d4d1bf2010-10-18 17:06:26 -04002025 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002026 } finally {
2027 Binder.restoreCallingIdentity(identity);
2028 }
2029 }
2030
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002031 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
2032 int pid, int uid, String packageName) {
2033 // Figure out the provider. Either its explicitly request (legacy use cases), or
2034 // use the fused provider
2035 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2036 String name = request.getProvider();
Victoria Lease09016ab2012-09-16 12:33:15 -07002037 if (name == null) {
2038 throw new IllegalArgumentException("provider name must not be null");
2039 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -07002040
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002041 LocationProviderInterface provider = mProvidersByName.get(name);
2042 if (provider == null) {
Victoria Leaseb30f3832013-10-13 12:15:40 -07002043 throw new IllegalArgumentException("provider doesn't exist: " + name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002044 }
2045
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002046 UpdateRecord record = new UpdateRecord(name, request, receiver);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002047 if (D) Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
2048 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
2049 + (record.mIsForegroundUid ? "foreground" : "background")
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002050 + (isThrottlingExemptLocked(receiver.mIdentity)
2051 ? " [whitelisted]" : "") + ")");
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002052
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002053 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
2054 if (oldRecord != null) {
2055 oldRecord.disposeLocked(false);
2056 }
2057
Victoria Lease09eeaec2013-02-05 11:34:13 -08002058 boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002059 if (isProviderEnabled) {
2060 applyRequirementsLocked(name);
2061 } else {
2062 // Notify the listener that updates are currently disabled
2063 receiver.callProviderEnabledLocked(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002064 }
David Christie0b837452013-07-29 16:02:13 -07002065 // Update the monitoring here just in case multiple location requests were added to the
2066 // same receiver (this request may be high power and the initial might not have been).
2067 receiver.updateMonitoring(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002068 }
2069
Nick Pellye0fd6932012-07-11 10:26:13 -07002070 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002071 public void removeUpdates(ILocationListener listener, PendingIntent intent,
2072 String packageName) {
2073 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002074
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002075 final int pid = Binder.getCallingPid();
2076 final int uid = Binder.getCallingUid();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002077
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002078 synchronized (mLock) {
David Christie82edc9b2013-07-19 11:31:42 -07002079 WorkSource workSource = null;
David Christie40e57822013-07-30 11:36:48 -07002080 boolean hideFromAppOps = false;
2081 Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid,
2082 packageName, workSource, hideFromAppOps);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002083
2084 // providers may use public location API's, need to clear identity
2085 long identity = Binder.clearCallingIdentity();
2086 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002087 removeUpdatesLocked(receiver);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002088 } finally {
2089 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002091 }
2092 }
2093
2094 private void removeUpdatesLocked(Receiver receiver) {
Dianne Hackborn7ff30112012-11-08 11:12:09 -08002095 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002096
2097 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
2098 receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
2099 synchronized (receiver) {
Victoria Lease0aa28602013-05-29 15:28:26 -07002100 receiver.clearPendingBroadcastsLocked();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002101 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002102 }
2103
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07002104 receiver.updateMonitoring(false);
2105
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002106 // Record which providers were associated with this listener
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002107 HashSet<String> providers = new HashSet<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002108 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2109 if (oldRecords != null) {
2110 // Call dispose() on the obsolete update records.
2111 for (UpdateRecord record : oldRecords.values()) {
David Christie2ff96af2014-01-30 16:09:37 -08002112 // Update statistics for historical location requests by package/provider
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002113 record.disposeLocked(false);
2114 }
2115 // Accumulate providers
2116 providers.addAll(oldRecords.keySet());
2117 }
2118
2119 // update provider
2120 for (String provider : providers) {
2121 // If provider is already disabled, don't need to do anything
Victoria Lease09eeaec2013-02-05 11:34:13 -08002122 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002123 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002124 }
2125
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002126 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002127 }
2128 }
2129
Dianne Hackbornc2293022013-02-06 23:14:49 -08002130 private void applyAllProviderRequirementsLocked() {
2131 for (LocationProviderInterface p : mProviders) {
2132 // If provider is already disabled, don't need to do anything
Dianne Hackborn64d41d72013-02-07 00:33:31 -08002133 if (!isAllowedByCurrentUserSettingsLocked(p.getName())) {
Dianne Hackbornc2293022013-02-06 23:14:49 -08002134 continue;
2135 }
2136
2137 applyRequirementsLocked(p.getName());
2138 }
2139 }
2140
Nick Pellye0fd6932012-07-11 10:26:13 -07002141 @Override
Nick Pelly4035f5a2012-08-17 14:43:49 -07002142 public Location getLastLocation(LocationRequest request, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002143 if (D) Log.d(TAG, "getLastLocation: " + request);
2144 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002145 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly4035f5a2012-08-17 14:43:49 -07002146 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002147 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2148 request.getProvider());
2149 // no need to sanitize this request, as only the provider name is used
Nick Pelly4035f5a2012-08-17 14:43:49 -07002150
David Christieb870dbf2015-06-22 12:42:53 -07002151 final int pid = Binder.getCallingPid();
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002152 final int uid = Binder.getCallingUid();
2153 final long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07002154 try {
2155 if (mBlacklist.isBlacklisted(packageName)) {
2156 if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
2157 packageName);
Victoria Lease09016ab2012-09-16 12:33:15 -07002158 return null;
2159 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002160
David Christieb870dbf2015-06-22 12:42:53 -07002161 if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel)) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002162 if (D) Log.d(TAG, "not returning last loc for no op app: " +
2163 packageName);
2164 return null;
2165 }
2166
Victoria Leaseb711d572012-10-02 13:14:11 -07002167 synchronized (mLock) {
2168 // Figure out the provider. Either its explicitly request (deprecated API's),
2169 // or use the fused provider
2170 String name = request.getProvider();
2171 if (name == null) name = LocationManager.FUSED_PROVIDER;
2172 LocationProviderInterface provider = mProvidersByName.get(name);
2173 if (provider == null) return null;
2174
Victoria Lease09eeaec2013-02-05 11:34:13 -08002175 if (!isAllowedByUserSettingsLocked(name, uid)) return null;
Victoria Leaseb711d572012-10-02 13:14:11 -07002176
David Christie1b9b7b12013-04-15 15:31:11 -07002177 Location location;
2178 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2179 // Make sure that an app with coarse permissions can't get frequent location
2180 // updates by calling LocationManager.getLastKnownLocation repeatedly.
2181 location = mLastLocationCoarseInterval.get(name);
2182 } else {
2183 location = mLastLocation.get(name);
2184 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002185 if (location == null) {
2186 return null;
2187 }
Victoria Lease37425c32012-10-16 16:08:48 -07002188 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002189 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2190 if (noGPSLocation != null) {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002191 return new Location(mLocationFudger.getOrCreate(noGPSLocation));
Victoria Leaseb711d572012-10-02 13:14:11 -07002192 }
Victoria Lease37425c32012-10-16 16:08:48 -07002193 } else {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002194 return new Location(location);
Victoria Lease09016ab2012-09-16 12:33:15 -07002195 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002196 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002197 return null;
2198 } finally {
2199 Binder.restoreCallingIdentity(identity);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002200 }
2201 }
2202
2203 @Override
2204 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
2205 String packageName) {
2206 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002207 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2208 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002209 checkPendingIntent(intent);
2210 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002211 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2212 request.getProvider());
2213 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002214
Victoria Lease37425c32012-10-16 16:08:48 -07002215 if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002216
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002217 // geo-fence manager uses the public location API, need to clear identity
2218 int uid = Binder.getCallingUid();
Xiaohui Chena4490622015-09-22 15:29:31 -07002219 // TODO: http://b/23822629
2220 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
Victoria Lease56e675b2012-11-05 19:25:06 -08002221 // temporary measure until geofences work for secondary users
2222 Log.w(TAG, "proximity alerts are currently available only to the primary user");
2223 return;
2224 }
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002225 long identity = Binder.clearCallingIdentity();
2226 try {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002227 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
2228 uid, packageName);
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002229 } finally {
2230 Binder.restoreCallingIdentity(identity);
2231 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002232 }
2233
2234 @Override
2235 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002236 checkPendingIntent(intent);
2237 checkPackageName(packageName);
2238
2239 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2240
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002241 // geo-fence manager uses the public location API, need to clear identity
2242 long identity = Binder.clearCallingIdentity();
2243 try {
2244 mGeofenceManager.removeFence(geofence, intent);
2245 } finally {
2246 Binder.restoreCallingIdentity(identity);
2247 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002248 }
2249
2250
2251 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002252 public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002253 if (!hasGnssPermissions(packageName) || mGnssStatusProvider == null) {
Takayuki Hoshib254ab6a2014-10-23 16:46:02 +09002254 return false;
2255 }
2256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002257 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002258 mGnssStatusProvider.registerGnssStatusCallback(callback);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002259 } catch (RemoteException e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002260 Slog.e(TAG, "mGpsStatusProvider.registerGnssStatusCallback failed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002261 return false;
2262 }
2263 return true;
2264 }
2265
Nick Pellye0fd6932012-07-11 10:26:13 -07002266 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002267 public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002268 synchronized (mLock) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002269 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002270 mGnssStatusProvider.unregisterGnssStatusCallback(callback);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002271 } catch (Exception e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002272 Slog.e(TAG, "mGpsStatusProvider.unregisterGnssStatusCallback failed", e);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002273 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002274 }
2275 }
2276
Nick Pellye0fd6932012-07-11 10:26:13 -07002277 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002278 public boolean addGnssMeasurementsListener(
2279 IGnssMeasurementsListener listener,
destradaaea8a8a62014-06-23 18:19:03 -07002280 String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002281 if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
destradaaea8a8a62014-06-23 18:19:03 -07002282 return false;
2283 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002284
2285 synchronized (mLock) {
2286 Identity callerIdentity
2287 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
2288 mGnssMeasurementsListeners.put(listener, callerIdentity);
2289 long identity = Binder.clearCallingIdentity();
2290 try {
2291 if (isThrottlingExemptLocked(callerIdentity)
2292 || isImportanceForeground(
2293 mActivityManager.getPackageImportance(packageName))) {
2294 return mGnssMeasurementsProvider.addListener(listener);
2295 }
2296 } finally {
2297 Binder.restoreCallingIdentity(identity);
2298 }
2299
2300 return true;
2301 }
destradaaea8a8a62014-06-23 18:19:03 -07002302 }
2303
2304 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002305 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
2306 if (mGnssMeasurementsProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002307 synchronized (mLock) {
2308 mGnssMeasurementsListeners.remove(listener);
2309 mGnssMeasurementsProvider.removeListener(listener);
2310 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002311 }
destradaaea8a8a62014-06-23 18:19:03 -07002312 }
2313
2314 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002315 public boolean addGnssNavigationMessageListener(
2316 IGnssNavigationMessageListener listener,
destradaa4b3e3932014-07-21 18:01:47 -07002317 String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002318 if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) {
destradaa4b3e3932014-07-21 18:01:47 -07002319 return false;
2320 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002321
2322 synchronized (mLock) {
2323 Identity callerIdentity
2324 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
2325 mGnssNavigationMessageListeners.put(listener, callerIdentity);
2326 long identity = Binder.clearCallingIdentity();
2327 try {
2328 if (isThrottlingExemptLocked(callerIdentity)
2329 || isImportanceForeground(
2330 mActivityManager.getPackageImportance(packageName))) {
2331 return mGnssNavigationMessageProvider.addListener(listener);
2332 }
2333 } finally {
2334 Binder.restoreCallingIdentity(identity);
2335 }
2336
2337 return true;
2338 }
destradaa4b3e3932014-07-21 18:01:47 -07002339 }
2340
2341 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002342 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
2343 if (mGnssNavigationMessageProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002344 synchronized (mLock) {
2345 mGnssNavigationMessageListeners.remove(listener);
2346 mGnssNavigationMessageProvider.removeListener(listener);
2347 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002348 }
destradaa4b3e3932014-07-21 18:01:47 -07002349 }
2350
2351 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002352 public boolean sendExtraCommand(String provider, String command, Bundle extras) {
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002353 if (provider == null) {
2354 // throw NullPointerException to remain compatible with previous implementation
2355 throw new NullPointerException();
2356 }
Victoria Lease37425c32012-10-16 16:08:48 -07002357 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2358 provider);
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002360 // and check for ACCESS_LOCATION_EXTRA_COMMANDS
Mike Lockwoodb7e99222009-07-07 13:18:21 -04002361 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002362 != PackageManager.PERMISSION_GRANTED)) {
2363 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
2364 }
2365
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002366 synchronized (mLock) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002367 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002368 if (p == null) return false;
Nick Pellye0fd6932012-07-11 10:26:13 -07002369
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002370 return p.sendExtraCommand(command, extras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002371 }
2372 }
2373
Nick Pellye0fd6932012-07-11 10:26:13 -07002374 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002375 public boolean sendNiResponse(int notifId, int userResponse) {
Mike Lockwood18ad9f62009-08-27 14:01:23 -07002376 if (Binder.getCallingUid() != Process.myUid()) {
2377 throw new SecurityException(
2378 "calling sendNiResponse from outside of the system is not allowed");
2379 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002380 try {
2381 return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002382 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002383 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
Danke Xie22d1f9f2009-08-18 18:28:45 -04002384 return false;
2385 }
2386 }
2387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002388 /**
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002389 * @return null if the provider does not exist
Alexey Tarasovf2db9fb2009-09-01 02:37:07 +11002390 * @throws SecurityException if the provider is not allowed to be
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002391 * accessed by the caller
2392 */
Nick Pellye0fd6932012-07-11 10:26:13 -07002393 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002394 public ProviderProperties getProviderProperties(String provider) {
Laurent Tub7f9d252012-10-16 14:25:00 -07002395 if (mProvidersByName.get(provider) == null) {
David Christie2ff96af2014-01-30 16:09:37 -08002396 return null;
Laurent Tub7f9d252012-10-16 14:25:00 -07002397 }
2398
Victoria Lease37425c32012-10-16 16:08:48 -07002399 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2400 provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002401
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002402 LocationProviderInterface p;
2403 synchronized (mLock) {
2404 p = mProvidersByName.get(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002405 }
2406
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002407 if (p == null) return null;
2408 return p.getProperties();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002409 }
2410
Jason Monkb71218a2015-06-17 14:44:39 -04002411 /**
2412 * @return null if the provider does not exist
2413 * @throws SecurityException if the provider is not allowed to be
2414 * accessed by the caller
2415 */
2416 @Override
2417 public String getNetworkProviderPackage() {
2418 LocationProviderInterface p;
2419 synchronized (mLock) {
2420 if (mProvidersByName.get(LocationManager.NETWORK_PROVIDER) == null) {
2421 return null;
2422 }
2423 p = mProvidersByName.get(LocationManager.NETWORK_PROVIDER);
2424 }
2425
2426 if (p instanceof LocationProviderProxy) {
2427 return ((LocationProviderProxy) p).getConnectedPackageName();
2428 }
2429 return null;
2430 }
2431
Nick Pellye0fd6932012-07-11 10:26:13 -07002432 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002433 public boolean isProviderEnabled(String provider) {
Tom O'Neilld5759432013-09-11 11:03:03 -07002434 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2435 // so we discourage its use
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002436 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
2437
Victoria Lease09eeaec2013-02-05 11:34:13 -08002438 int uid = Binder.getCallingUid();
Victoria Lease269518e2012-10-29 08:25:39 -07002439 long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07002440 try {
2441 synchronized (mLock) {
2442 LocationProviderInterface p = mProvidersByName.get(provider);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002443 return p != null && isAllowedByUserSettingsLocked(provider, uid);
Victoria Leaseb711d572012-10-02 13:14:11 -07002444 }
2445 } finally {
2446 Binder.restoreCallingIdentity(identity);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002447 }
2448 }
2449
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002450 /**
2451 * Returns "true" if the UID belongs to a bound location provider.
2452 *
2453 * @param uid the uid
2454 * @return true if uid belongs to a bound location provider
2455 */
2456 private boolean isUidALocationProvider(int uid) {
2457 if (uid == Process.SYSTEM_UID) {
2458 return true;
2459 }
2460 if (mGeocodeProvider != null) {
David Christie1f141c12014-05-14 15:11:15 -07002461 if (doesUidHavePackage(uid, mGeocodeProvider.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002462 }
2463 for (LocationProviderProxy proxy : mProxyProviders) {
David Christie1f141c12014-05-14 15:11:15 -07002464 if (doesUidHavePackage(uid, proxy.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002465 }
2466 return false;
2467 }
2468
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002469 private void checkCallerIsProvider() {
2470 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
2471 == PackageManager.PERMISSION_GRANTED) {
2472 return;
2473 }
2474
2475 // Previously we only used the INSTALL_LOCATION_PROVIDER
2476 // check. But that is system or signature
2477 // protection level which is not flexible enough for
2478 // providers installed oustide the system image. So
2479 // also allow providers with a UID matching the
2480 // currently bound package name
2481
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002482 if (isUidALocationProvider(Binder.getCallingUid())) {
2483 return;
2484 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002485
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002486 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
2487 "or UID of a currently bound location provider");
2488 }
2489
David Christie1f141c12014-05-14 15:11:15 -07002490 /**
2491 * Returns true if the given package belongs to the given uid.
2492 */
2493 private boolean doesUidHavePackage(int uid, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002494 if (packageName == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002495 return false;
2496 }
David Christie1f141c12014-05-14 15:11:15 -07002497 String[] packageNames = mPackageManager.getPackagesForUid(uid);
2498 if (packageNames == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002499 return false;
2500 }
David Christie1f141c12014-05-14 15:11:15 -07002501 for (String name : packageNames) {
2502 if (packageName.equals(name)) {
2503 return true;
2504 }
2505 }
2506 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002507 }
2508
Nick Pellye0fd6932012-07-11 10:26:13 -07002509 @Override
Mike Lockwooda4903f22010-02-17 06:42:23 -05002510 public void reportLocation(Location location, boolean passive) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002511 checkCallerIsProvider();
Mike Lockwood275555c2009-05-01 11:30:34 -04002512
Nick Pelly2eeeec22012-07-18 13:13:37 -07002513 if (!location.isComplete()) {
2514 Log.w(TAG, "Dropping incomplete location: " + location);
2515 return;
2516 }
2517
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002518 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location);
2519 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location);
Mike Lockwooda4903f22010-02-17 06:42:23 -05002520 m.arg1 = (passive ? 1 : 0);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002521 mLocationHandler.sendMessageAtFrontOfQueue(m);
2522 }
2523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524
Laurent Tu75defb62012-11-01 16:21:52 -07002525 private static boolean shouldBroadcastSafe(
2526 Location loc, Location lastLoc, UpdateRecord record, long now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527 // Always broadcast the first update
2528 if (lastLoc == null) {
2529 return true;
2530 }
2531
Nick Pellyf1be6862012-05-15 10:53:42 -07002532 // Check whether sufficient time has passed
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002533 long minTime = record.mRequest.getFastestInterval();
David Christie1b9b7b12013-04-15 15:31:11 -07002534 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
2535 / NANOS_PER_MILLI;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002536 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002537 return false;
2538 }
2539
2540 // Check whether sufficient distance has been traveled
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002541 double minDistance = record.mRequest.getSmallestDisplacement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002542 if (minDistance > 0.0) {
2543 if (loc.distanceTo(lastLoc) <= minDistance) {
2544 return false;
2545 }
2546 }
2547
Laurent Tu75defb62012-11-01 16:21:52 -07002548 // Check whether sufficient number of udpates is left
2549 if (record.mRequest.getNumUpdates() <= 0) {
2550 return false;
2551 }
2552
2553 // Check whether the expiry date has passed
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002554 return record.mRequest.getExpireAt() >= now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002555 }
2556
Mike Lockwooda4903f22010-02-17 06:42:23 -05002557 private void handleLocationChangedLocked(Location location, boolean passive) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002558 if (D) Log.d(TAG, "incoming location: " + location);
2559
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002560 long now = SystemClock.elapsedRealtime();
Mike Lockwooda4903f22010-02-17 06:42:23 -05002561 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002562
Laurent Tu60ec50a2012-10-04 17:00:10 -07002563 // Skip if the provider is unknown.
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002564 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002565 if (p == null) return;
2566
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002567 // Update last known locations
Victoria Lease09016ab2012-09-16 12:33:15 -07002568 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002569 Location lastNoGPSLocation;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002570 Location lastLocation = mLastLocation.get(provider);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002571 if (lastLocation == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002572 lastLocation = new Location(provider);
2573 mLastLocation.put(provider, lastLocation);
Victoria Lease09016ab2012-09-16 12:33:15 -07002574 } else {
2575 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2576 if (noGPSLocation == null && lastNoGPSLocation != null) {
2577 // New location has no no-GPS location: adopt last no-GPS location. This is set
2578 // directly into location because we do not want to notify COARSE clients.
2579 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
2580 }
Mike Lockwood4e50b782009-04-03 08:24:43 -07002581 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002582 lastLocation.set(location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002583
David Christie1b9b7b12013-04-15 15:31:11 -07002584 // Update last known coarse interval location if enough time has passed.
2585 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider);
2586 if (lastLocationCoarseInterval == null) {
2587 lastLocationCoarseInterval = new Location(location);
2588 mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval);
2589 }
2590 long timeDiffNanos = location.getElapsedRealtimeNanos()
2591 - lastLocationCoarseInterval.getElapsedRealtimeNanos();
2592 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
2593 lastLocationCoarseInterval.set(location);
2594 }
2595 // Don't ever return a coarse location that is more recent than the allowed update
2596 // interval (i.e. don't allow an app to keep registering and unregistering for
2597 // location updates to overcome the minimum interval).
2598 noGPSLocation =
2599 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2600
Laurent Tu60ec50a2012-10-04 17:00:10 -07002601 // Skip if there are no UpdateRecords for this provider.
2602 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
2603 if (records == null || records.size() == 0) return;
2604
Victoria Lease09016ab2012-09-16 12:33:15 -07002605 // Fetch coarse location
2606 Location coarseLocation = null;
David Christie1b9b7b12013-04-15 15:31:11 -07002607 if (noGPSLocation != null) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002608 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
2609 }
2610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002611 // Fetch latest status update time
2612 long newStatusUpdateTime = p.getStatusUpdateTime();
2613
David Christie2ff96af2014-01-30 16:09:37 -08002614 // Get latest status
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002615 Bundle extras = new Bundle();
2616 int status = p.getStatus(extras);
2617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002618 ArrayList<Receiver> deadReceivers = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002619 ArrayList<UpdateRecord> deadUpdateRecords = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07002620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002621 // Broadcast location or status to all listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002622 for (UpdateRecord r : records) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002623 Receiver receiver = r.mReceiver;
Mike Lockwood03ca2162010-04-01 08:10:09 -07002624 boolean receiverDead = false;
Nick Pelly4035f5a2012-08-17 14:43:49 -07002625
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002626 int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid);
2627 if (!isCurrentProfile(receiverUserId)
2628 && !isUidALocationProvider(receiver.mIdentity.mUid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002629 if (D) {
Victoria Lease269518e2012-10-29 08:25:39 -07002630 Log.d(TAG, "skipping loc update for background user " + receiverUserId +
Victoria Leaseb711d572012-10-02 13:14:11 -07002631 " (current user: " + mCurrentUserId + ", app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002632 receiver.mIdentity.mPackageName + ")");
Victoria Leaseb711d572012-10-02 13:14:11 -07002633 }
2634 continue;
2635 }
2636
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002637 if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) {
Nick Pelly4035f5a2012-08-17 14:43:49 -07002638 if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002639 receiver.mIdentity.mPackageName);
Nick Pelly4035f5a2012-08-17 14:43:49 -07002640 continue;
2641 }
2642
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002643 if (!reportLocationAccessNoThrow(
2644 receiver.mIdentity.mPid,
2645 receiver.mIdentity.mUid,
2646 receiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002647 receiver.mAllowedResolutionLevel)) {
2648 if (D) Log.d(TAG, "skipping loc update for no op app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002649 receiver.mIdentity.mPackageName);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002650 continue;
2651 }
2652
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002653 Location notifyLocation;
Victoria Lease37425c32012-10-16 16:08:48 -07002654 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2655 notifyLocation = coarseLocation; // use coarse location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002656 } else {
Victoria Lease37425c32012-10-16 16:08:48 -07002657 notifyLocation = lastLocation; // use fine location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002658 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002659 if (notifyLocation != null) {
2660 Location lastLoc = r.mLastFixBroadcast;
Laurent Tu75defb62012-11-01 16:21:52 -07002661 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002662 if (lastLoc == null) {
2663 lastLoc = new Location(notifyLocation);
2664 r.mLastFixBroadcast = lastLoc;
2665 } else {
2666 lastLoc.set(notifyLocation);
2667 }
2668 if (!receiver.callLocationChangedLocked(notifyLocation)) {
2669 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
2670 receiverDead = true;
2671 }
Laurent Tu75defb62012-11-01 16:21:52 -07002672 r.mRequest.decrementNumUpdates();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002673 }
2674 }
2675
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002676 long prevStatusUpdateTime = r.mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002677 if ((newStatusUpdateTime > prevStatusUpdateTime) &&
Victoria Lease09016ab2012-09-16 12:33:15 -07002678 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002679
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002680 r.mLastStatusBroadcast = newStatusUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002681 if (!receiver.callStatusChangedLocked(provider, status, extras)) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002682 receiverDead = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002683 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
Mike Lockwood03ca2162010-04-01 08:10:09 -07002684 }
2685 }
2686
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002687 // track expired records
Laurent Tu75defb62012-11-01 16:21:52 -07002688 if (r.mRequest.getNumUpdates() <= 0 || r.mRequest.getExpireAt() < now) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002689 if (deadUpdateRecords == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002690 deadUpdateRecords = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002691 }
2692 deadUpdateRecords.add(r);
2693 }
2694 // track dead receivers
2695 if (receiverDead) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002696 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002697 deadReceivers = new ArrayList<>();
Mike Lockwood03ca2162010-04-01 08:10:09 -07002698 }
2699 if (!deadReceivers.contains(receiver)) {
2700 deadReceivers.add(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002701 }
2702 }
2703 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002704
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002705 // remove dead records and receivers outside the loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002706 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002707 for (Receiver receiver : deadReceivers) {
2708 removeUpdatesLocked(receiver);
2709 }
2710 }
2711 if (deadUpdateRecords != null) {
2712 for (UpdateRecord r : deadUpdateRecords) {
2713 r.disposeLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 }
Victoria Lease8b38b292012-12-04 15:04:43 -08002715 applyRequirementsLocked(provider);
2716 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002717 }
2718
2719 private class LocationWorkerHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08002720 public LocationWorkerHandler(Looper looper) {
2721 super(looper, null, true);
2722 }
2723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002724 @Override
2725 public void handleMessage(Message msg) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002726 switch (msg.what) {
2727 case MSG_LOCATION_CHANGED:
2728 handleLocationChanged((Location) msg.obj, msg.arg1 == 1);
2729 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002730 }
2731 }
2732 }
2733
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002734 private boolean isMockProvider(String provider) {
2735 synchronized (mLock) {
2736 return mMockProviders.containsKey(provider);
2737 }
2738 }
2739
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002740 private void handleLocationChanged(Location location, boolean passive) {
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002741 // create a working copy of the incoming Location so that the service can modify it without
2742 // disturbing the caller's copy
2743 Location myLocation = new Location(location);
2744 String provider = myLocation.getProvider();
2745
2746 // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this
2747 // bit if location did not come from a mock provider because passive/fused providers can
2748 // forward locations from mock providers, and should not grant them legitimacy in doing so.
2749 if (!myLocation.isFromMockProvider() && isMockProvider(provider)) {
2750 myLocation.setIsFromMockProvider(true);
2751 }
Jeff Sharkey5e613312012-01-30 11:16:20 -08002752
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002753 synchronized (mLock) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08002754 if (isAllowedByCurrentUserSettingsLocked(provider)) {
2755 if (!passive) {
2756 // notify passive provider of the new location
2757 mPassiveProvider.updateLocation(myLocation);
2758 }
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002759 handleLocationChangedLocked(myLocation, passive);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002760 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002761 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002762 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002763
Mike Lockwoode97ae402010-09-29 15:23:46 -04002764 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
2765 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002766 public void onPackageDisappeared(String packageName, int reason) {
2767 // remove all receivers associated with this package name
2768 synchronized (mLock) {
2769 ArrayList<Receiver> deadReceivers = null;
2770
2771 for (Receiver receiver : mReceivers.values()) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002772 if (receiver.mIdentity.mPackageName.equals(packageName)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002773 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002774 deadReceivers = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002775 }
2776 deadReceivers.add(receiver);
2777 }
2778 }
2779
2780 // perform removal outside of mReceivers loop
2781 if (deadReceivers != null) {
2782 for (Receiver receiver : deadReceivers) {
2783 removeUpdatesLocked(receiver);
2784 }
2785 }
2786 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002787 }
Mike Lockwoode97ae402010-09-29 15:23:46 -04002788 };
2789
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002790 // Geocoder
2791
Nick Pellye0fd6932012-07-11 10:26:13 -07002792 @Override
Mike Lockwoode15735a2010-09-20 17:48:47 -04002793 public boolean geocoderIsPresent() {
Mark Vandevoorde01ac80b2010-05-21 15:43:26 -07002794 return mGeocodeProvider != null;
2795 }
2796
Nick Pellye0fd6932012-07-11 10:26:13 -07002797 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002798 public String getFromLocation(double latitude, double longitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002799 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002800 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002801 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
2802 params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002803 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002804 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002805 }
2806
Mike Lockwooda55c3212009-04-15 11:10:11 -04002807
Nick Pellye0fd6932012-07-11 10:26:13 -07002808 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002809 public String getFromLocationName(String locationName,
Mike Lockwooda55c3212009-04-15 11:10:11 -04002810 double lowerLeftLatitude, double lowerLeftLongitude,
2811 double upperRightLatitude, double upperRightLongitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002812 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002813
2814 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002815 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
2816 lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
2817 maxResults, params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002818 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002819 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002820 }
2821
2822 // Mock Providers
2823
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002824 private boolean canCallerAccessMockLocation(String opPackageName) {
2825 return mAppOps.noteOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(),
2826 opPackageName) == AppOpsManager.MODE_ALLOWED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002827 }
2828
Nick Pellye0fd6932012-07-11 10:26:13 -07002829 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002830 public void addTestProvider(String name, ProviderProperties properties, String opPackageName) {
2831 if (!canCallerAccessMockLocation(opPackageName)) {
2832 return;
2833 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002834
Mike Lockwooda4903f22010-02-17 06:42:23 -05002835 if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
2836 throw new IllegalArgumentException("Cannot mock the passive location provider");
2837 }
2838
Mike Lockwood86328a92009-10-23 08:38:25 -04002839 long identity = Binder.clearCallingIdentity();
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002840 synchronized (mLock) {
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002841 // remove the real provider if we are replacing GPS or network provider
2842 if (LocationManager.GPS_PROVIDER.equals(name)
Nick Pelly1332b532012-08-21 16:25:47 -07002843 || LocationManager.NETWORK_PROVIDER.equals(name)
2844 || LocationManager.FUSED_PROVIDER.equals(name)) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002845 LocationProviderInterface p = mProvidersByName.get(name);
2846 if (p != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002847 removeProviderLocked(p);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002848 }
2849 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09002850 addTestProviderLocked(name, properties);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002851 updateProvidersLocked();
2852 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002853 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002854 }
2855
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09002856 private void addTestProviderLocked(String name, ProviderProperties properties) {
2857 if (mProvidersByName.get(name) != null) {
2858 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
2859 }
2860 MockProvider provider = new MockProvider(name, this, properties);
2861 addProviderLocked(provider);
2862 mMockProviders.put(name, provider);
2863 mLastLocation.put(name, null);
2864 mLastLocationCoarseInterval.put(name, null);
2865 }
2866
Nick Pellye0fd6932012-07-11 10:26:13 -07002867 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002868 public void removeTestProvider(String provider, String opPackageName) {
2869 if (!canCallerAccessMockLocation(opPackageName)) {
2870 return;
2871 }
2872
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002873 synchronized (mLock) {
Tom O'Neill07ee5d12014-03-03 17:48:35 -08002874
2875 // These methods can't be called after removing the test provider, so first make sure
Tom O'Neillfe6d3c52014-03-04 08:26:17 -08002876 // we don't leave anything dangling.
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002877 clearTestProviderEnabled(provider, opPackageName);
2878 clearTestProviderLocation(provider, opPackageName);
2879 clearTestProviderStatus(provider, opPackageName);
Tom O'Neill07ee5d12014-03-03 17:48:35 -08002880
You Kima6d0b6f2012-10-28 03:58:44 +09002881 MockProvider mockProvider = mMockProviders.remove(provider);
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002882 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002883 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2884 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002885 long identity = Binder.clearCallingIdentity();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002886 removeProviderLocked(mProvidersByName.get(provider));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002887
2888 // reinstate real provider if available
2889 LocationProviderInterface realProvider = mRealProviders.get(provider);
2890 if (realProvider != null) {
2891 addProviderLocked(realProvider);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002892 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002893 mLastLocation.put(provider, null);
David Christie1b9b7b12013-04-15 15:31:11 -07002894 mLastLocationCoarseInterval.put(provider, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002895 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04002896 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002897 }
2898 }
2899
Nick Pellye0fd6932012-07-11 10:26:13 -07002900 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002901 public void setTestProviderLocation(String provider, Location loc, String opPackageName) {
2902 if (!canCallerAccessMockLocation(opPackageName)) {
2903 return;
2904 }
2905
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002906 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002907 MockProvider mockProvider = mMockProviders.get(provider);
2908 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002909 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2910 }
Tom O'Neilla206a0f2016-12-15 10:26:28 -08002911
2912 // Ensure that the location is marked as being mock. There's some logic to do this in
2913 // handleLocationChanged(), but it fails if loc has the wrong provider (bug 33091107).
2914 Location mock = new Location(loc);
2915 mock.setIsFromMockProvider(true);
2916
2917 if (!TextUtils.isEmpty(loc.getProvider()) && !provider.equals(loc.getProvider())) {
2918 // The location has an explicit provider that is different from the mock provider
2919 // name. The caller may be trying to fool us via bug 33091107.
2920 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
2921 provider + "!=" + loc.getProvider());
2922 }
2923
Mike Lockwood95427cd2009-05-07 13:27:54 -04002924 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
2925 long identity = Binder.clearCallingIdentity();
Tom O'Neilla206a0f2016-12-15 10:26:28 -08002926 mockProvider.setLocation(mock);
Mike Lockwood95427cd2009-05-07 13:27:54 -04002927 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002928 }
2929 }
2930
Nick Pellye0fd6932012-07-11 10:26:13 -07002931 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002932 public void clearTestProviderLocation(String provider, String opPackageName) {
2933 if (!canCallerAccessMockLocation(opPackageName)) {
2934 return;
2935 }
2936
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002937 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002938 MockProvider mockProvider = mMockProviders.get(provider);
2939 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002940 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2941 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002942 mockProvider.clearLocation();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002943 }
2944 }
2945
Nick Pellye0fd6932012-07-11 10:26:13 -07002946 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002947 public void setTestProviderEnabled(String provider, boolean enabled, String opPackageName) {
2948 if (!canCallerAccessMockLocation(opPackageName)) {
2949 return;
2950 }
2951
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002952 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002953 MockProvider mockProvider = mMockProviders.get(provider);
2954 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002955 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2956 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002957 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002958 if (enabled) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002959 mockProvider.enable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002960 mEnabledProviders.add(provider);
2961 mDisabledProviders.remove(provider);
2962 } else {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002963 mockProvider.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002964 mEnabledProviders.remove(provider);
2965 mDisabledProviders.add(provider);
2966 }
2967 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04002968 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002969 }
2970 }
2971
Nick Pellye0fd6932012-07-11 10:26:13 -07002972 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002973 public void clearTestProviderEnabled(String provider, String opPackageName) {
2974 if (!canCallerAccessMockLocation(opPackageName)) {
2975 return;
2976 }
2977
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002978 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002979 MockProvider mockProvider = mMockProviders.get(provider);
2980 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002981 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2982 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002983 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002984 mEnabledProviders.remove(provider);
2985 mDisabledProviders.remove(provider);
2986 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04002987 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002988 }
2989 }
2990
Nick Pellye0fd6932012-07-11 10:26:13 -07002991 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002992 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime,
2993 String opPackageName) {
2994 if (!canCallerAccessMockLocation(opPackageName)) {
2995 return;
2996 }
2997
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002998 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002999 MockProvider mockProvider = mMockProviders.get(provider);
3000 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003001 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3002 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003003 mockProvider.setStatus(status, extras, updateTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003004 }
3005 }
3006
Nick Pellye0fd6932012-07-11 10:26:13 -07003007 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003008 public void clearTestProviderStatus(String provider, String opPackageName) {
3009 if (!canCallerAccessMockLocation(opPackageName)) {
3010 return;
3011 }
3012
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003013 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003014 MockProvider mockProvider = mMockProviders.get(provider);
3015 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003016 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3017 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003018 mockProvider.clearStatus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003019 }
3020 }
3021
3022 private void log(String log) {
3023 if (Log.isLoggable(TAG, Log.VERBOSE)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003024 Slog.d(TAG, log);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003025 }
3026 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003027
3028 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003029 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003030 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Nick Pellye0fd6932012-07-11 10:26:13 -07003031
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003032 synchronized (mLock) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003033 pw.println("Current Location Manager state:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003034 pw.println(" Location Listeners:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003035 for (Receiver receiver : mReceivers.values()) {
3036 pw.println(" " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003037 }
David Christie2ff96af2014-01-30 16:09:37 -08003038 pw.println(" Active Records by Provider:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003039 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
3040 pw.println(" " + entry.getKey() + ":");
3041 for (UpdateRecord record : entry.getValue()) {
3042 pw.println(" " + record);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003043 }
3044 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003045 pw.println(" Overlay Provider Packages:");
3046 for (LocationProviderInterface provider : mProviders) {
3047 if (provider instanceof LocationProviderProxy) {
3048 pw.println(" " + provider.getName() + ": "
3049 + ((LocationProviderProxy) provider).getConnectedPackageName());
3050 }
3051 }
David Christie2ff96af2014-01-30 16:09:37 -08003052 pw.println(" Historical Records by Provider:");
3053 for (Map.Entry<PackageProviderKey, PackageStatistics> entry
3054 : mRequestStatistics.statistics.entrySet()) {
3055 PackageProviderKey key = entry.getKey();
3056 PackageStatistics stats = entry.getValue();
3057 pw.println(" " + key.packageName + ": " + key.providerName + ": " + stats);
3058 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003059 pw.println(" Last Known Locations:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003060 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
3061 String provider = entry.getKey();
3062 Location location = entry.getValue();
3063 pw.println(" " + provider + ": " + location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003064 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003065
David Christie1b9b7b12013-04-15 15:31:11 -07003066 pw.println(" Last Known Locations Coarse Intervals:");
3067 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
3068 String provider = entry.getKey();
3069 Location location = entry.getValue();
3070 pw.println(" " + provider + ": " + location);
3071 }
3072
Nick Pellye0fd6932012-07-11 10:26:13 -07003073 mGeofenceManager.dump(pw);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003074
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003075 if (mEnabledProviders.size() > 0) {
3076 pw.println(" Enabled Providers:");
3077 for (String i : mEnabledProviders) {
3078 pw.println(" " + i);
3079 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003081 }
3082 if (mDisabledProviders.size() > 0) {
3083 pw.println(" Disabled Providers:");
3084 for (String i : mDisabledProviders) {
3085 pw.println(" " + i);
3086 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003087 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07003088 pw.append(" ");
3089 mBlacklist.dump(pw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003090 if (mMockProviders.size() > 0) {
3091 pw.println(" Mock Providers:");
3092 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003093 i.getValue().dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003094 }
3095 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003096
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08003097 if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
3098 pw.println(" Throttling Whitelisted Packages:");
3099 for (String packageName : mBackgroundThrottlePackageWhitelist) {
3100 pw.println(" " + packageName);
3101 }
3102 }
3103
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003104 pw.append(" fudger: ");
3105 mLocationFudger.dump(fd, pw, args);
3106
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003107 if (args.length > 0 && "short".equals(args[0])) {
3108 return;
3109 }
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003110 for (LocationProviderInterface provider: mProviders) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003111 pw.print(provider.getName() + " Internal State");
3112 if (provider instanceof LocationProviderProxy) {
3113 LocationProviderProxy proxy = (LocationProviderProxy) provider;
3114 pw.print(" (" + proxy.getConnectedPackageName() + ")");
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003115 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003116 pw.println(":");
3117 provider.dump(fd, pw, args);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003118 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08003119 if (mGnssBatchingInProgress) {
3120 pw.println(" GNSS batching in progress");
3121 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003122 }
3123 }
3124}