blob: 90ad09eed5d741934721e6bb060b8000979a2bfb [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Maggieaa080f92018-01-04 15:35:11 -080019import static android.content.pm.PackageManager.PERMISSION_GRANTED;
20
Wyatt Rileycf879db2017-01-12 13:57:38 -080021import android.annotation.NonNull;
Wyatt Riley49097c02018-03-15 09:14:43 -070022import android.annotation.Nullable;
Maggieaa080f92018-01-04 15:35:11 -080023import android.app.ActivityManager;
24import android.app.AppOpsManager;
25import android.app.PendingIntent;
26import android.content.BroadcastReceiver;
27import android.content.ContentResolver;
28import android.content.Context;
29import android.content.Intent;
30import android.content.IntentFilter;
31import android.content.pm.ApplicationInfo;
32import android.content.pm.PackageInfo;
33import android.content.pm.PackageManager;
34import android.content.pm.PackageManager.NameNotFoundException;
35import android.content.pm.PackageManagerInternal;
36import android.content.pm.ResolveInfo;
37import android.content.pm.Signature;
38import android.content.res.Resources;
39import android.database.ContentObserver;
40import android.hardware.location.ActivityRecognitionHardware;
41import android.location.Address;
42import android.location.Criteria;
43import android.location.GeocoderParams;
44import android.location.Geofence;
45import android.location.IBatchedLocationCallback;
46import android.location.IGnssMeasurementsListener;
47import android.location.IGnssNavigationMessageListener;
48import android.location.IGnssStatusListener;
49import android.location.IGnssStatusProvider;
50import android.location.IGpsGeofenceHardware;
51import android.location.ILocationListener;
52import android.location.ILocationManager;
53import android.location.INetInitiatedListener;
54import android.location.Location;
55import android.location.LocationManager;
56import android.location.LocationProvider;
57import android.location.LocationRequest;
58import android.os.Binder;
59import android.os.Bundle;
60import android.os.Handler;
61import android.os.IBinder;
62import android.os.Looper;
63import android.os.Message;
64import android.os.PowerManager;
65import android.os.Process;
66import android.os.RemoteException;
67import android.os.SystemClock;
68import android.os.UserHandle;
69import android.os.UserManager;
70import android.os.WorkSource;
Narayan Kamath32684dd2018-01-08 17:32:51 +000071import android.os.WorkSource.WorkChain;
Maggieaa080f92018-01-04 15:35:11 -080072import android.provider.Settings;
73import android.text.TextUtils;
Soonil Nagarkar681d7112017-02-23 17:14:16 -080074import android.util.ArrayMap;
Soonil Nagarkar2b565df2017-02-14 13:33:23 -080075import android.util.ArraySet;
Maggieaa080f92018-01-04 15:35:11 -080076import android.util.EventLog;
77import android.util.Log;
78import android.util.Slog;
Yu-Han Yanga4d250e2018-10-02 21:29:20 -070079
destradaaea8a8a62014-06-23 18:19:03 -070080import com.android.internal.content.PackageMonitor;
81import com.android.internal.location.ProviderProperties;
82import com.android.internal.location.ProviderRequest;
83import com.android.internal.os.BackgroundThread;
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -070084import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060085import com.android.internal.util.DumpUtils;
destradaaa4fa3b52014-07-09 10:46:39 -070086import com.android.server.location.ActivityRecognitionProxy;
destradaaea8a8a62014-06-23 18:19:03 -070087import com.android.server.location.GeocoderProxy;
88import com.android.server.location.GeofenceManager;
89import com.android.server.location.GeofenceProxy;
Yu-Han Yang3557cc72018-03-21 12:48:36 -070090import com.android.server.location.GnssBatchingProvider;
Lifu Tang818aa2c2016-02-01 01:52:00 -080091import com.android.server.location.GnssLocationProvider;
92import com.android.server.location.GnssMeasurementsProvider;
93import com.android.server.location.GnssNavigationMessageProvider;
destradaaea8a8a62014-06-23 18:19:03 -070094import com.android.server.location.LocationBlacklist;
95import com.android.server.location.LocationFudger;
96import com.android.server.location.LocationProviderInterface;
97import com.android.server.location.LocationProviderProxy;
98import com.android.server.location.LocationRequestStatistics;
99import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
100import com.android.server.location.LocationRequestStatistics.PackageStatistics;
101import com.android.server.location.MockProvider;
102import com.android.server.location.PassiveProvider;
Yu-Han Yanga4d250e2018-10-02 21:29:20 -0700103
Mike Lockwood43e33f22010-03-26 10:41:48 -0400104import java.io.FileDescriptor;
105import java.io.PrintWriter;
106import java.util.ArrayList;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700107import java.util.Arrays;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400108import java.util.HashMap;
109import java.util.HashSet;
110import java.util.List;
111import java.util.Map;
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800112import java.util.Map.Entry;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800113import java.util.NoSuchElementException;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400114import java.util.Set;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115
116/**
117 * The service class that manages LocationProviders and issues location
118 * updates and alerts.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119 */
Victoria Lease5cd731a2012-12-19 15:04:21 -0800120public class LocationManagerService extends ILocationManager.Stub {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121 private static final String TAG = "LocationManagerService";
JP Abgrallf79811e72013-02-01 18:45:05 -0800122 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700123
Olivier Gaillard7a222662017-11-20 16:07:24 +0000124 private static final String WAKELOCK_KEY = "*location*";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125
Victoria Lease37425c32012-10-16 16:08:48 -0700126 // Location resolution level: no location data whatsoever
127 private static final int RESOLUTION_LEVEL_NONE = 0;
128 // Location resolution level: coarse location data only
129 private static final int RESOLUTION_LEVEL_COARSE = 1;
130 // Location resolution level: fine location data
131 private static final int RESOLUTION_LEVEL_FINE = 2;
132
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 private static final String ACCESS_MOCK_LOCATION =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700134 android.Manifest.permission.ACCESS_MOCK_LOCATION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700136 android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
Mike Lockwood275555c2009-05-01 11:30:34 -0400137 private static final String INSTALL_LOCATION_PROVIDER =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700138 android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
139
140 private static final String NETWORK_LOCATION_SERVICE_ACTION =
Stan Chesnutt39062dd2013-07-22 14:33:30 -0700141 "com.android.location.service.v3.NetworkLocationProvider";
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700142 private static final String FUSED_LOCATION_SERVICE_ACTION =
143 "com.android.location.service.FusedLocationProvider";
144
145 private static final int MSG_LOCATION_CHANGED = 1;
146
David Christie1b9b7b12013-04-15 15:31:11 -0700147 private static final long NANOS_PER_MILLI = 1000000L;
148
David Christie0b837452013-07-29 16:02:13 -0700149 // The maximum interval a location request can have and still be considered "high power".
150 private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
151
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700152 private static final int FOREGROUND_IMPORTANCE_CUTOFF
gomo48f1a642017-11-10 20:35:46 -0800153 = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700154
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800155 // default background throttling interval if not overriden in settings
Soonil Nagarkarde6780a2017-02-07 10:39:41 -0800156 private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800157
Wei Wangdd070f22018-06-21 11:29:40 -0700158 // Default value for maximum age of last location returned to applications with foreground-only
159 // location permissions.
160 private static final long DEFAULT_LAST_LOCATION_MAX_AGE_MS = 20 * 60 * 1000;
161
Nick Pellyf1be6862012-05-15 10:53:42 -0700162 // Location Providers may sometimes deliver location updates
163 // slightly faster that requested - provide grace period so
164 // we don't unnecessarily filter events that are otherwise on
165 // time
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700166 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
Nick Pellyf1be6862012-05-15 10:53:42 -0700167
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700168 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
169
170 private final Context mContext;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800171 private final AppOpsManager mAppOps;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700172
173 // used internally for synchronization
174 private final Object mLock = new Object();
175
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700176 // --- fields below are final after systemRunning() ---
Nick Pelly74fa7ea2012-08-13 19:36:38 -0700177 private LocationFudger mLocationFudger;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700178 private GeofenceManager mGeofenceManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700179 private PackageManager mPackageManager;
Victoria Lease0aa28602013-05-29 15:28:26 -0700180 private PowerManager mPowerManager;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800181 private ActivityManager mActivityManager;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700182 private UserManager mUserManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700183 private GeocoderProxy mGeocodeProvider;
Lifu Tang30f95a72016-01-07 23:20:38 -0800184 private IGnssStatusProvider mGnssStatusProvider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700185 private INetInitiatedListener mNetInitiatedListener;
186 private LocationWorkerHandler mLocationHandler;
Nick Pelly4035f5a2012-08-17 14:43:49 -0700187 private PassiveProvider mPassiveProvider; // track passive provider for special cases
188 private LocationBlacklist mBlacklist;
Lifu Tang818aa2c2016-02-01 01:52:00 -0800189 private GnssMeasurementsProvider mGnssMeasurementsProvider;
190 private GnssNavigationMessageProvider mGnssNavigationMessageProvider;
Wei Liu5241a4c2015-05-11 14:00:36 -0700191 private IGpsGeofenceHardware mGpsGeofenceProxy;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700192
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700193 // --- fields below are protected by mLock ---
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 // Set of providers that are explicitly enabled
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700195 // Only used by passive, fused & test. Network & GPS are controlled separately, and not listed.
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800196 private final Set<String> mEnabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197
198 // Set of providers that are explicitly disabled
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800199 private final Set<String> mDisabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700201 // Mock (test) providers
202 private final HashMap<String, MockProvider> mMockProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800203 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700205 // all receivers
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800206 private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700208 // currently installed providers (with mocks replacing real providers)
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500209 private final ArrayList<LocationProviderInterface> mProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800210 new ArrayList<>();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400211
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700212 // real providers, saved here when mocked out
213 private final HashMap<String, LocationProviderInterface> mRealProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800214 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700216 // mapping from provider name to provider
217 private final HashMap<String, LocationProviderInterface> mProvidersByName =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800218 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700220 // mapping from provider name to all its UpdateRecords
221 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800222 new HashMap<>();
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700223
David Christie2ff96af2014-01-30 16:09:37 -0800224 private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics();
225
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700226 // mapping from provider name to last known location
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800227 private final HashMap<String, Location> mLastLocation = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228
David Christie1b9b7b12013-04-15 15:31:11 -0700229 // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
230 // locations stored here are not fudged for coarse permissions.
231 private final HashMap<String, Location> mLastLocationCoarseInterval =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800232 new HashMap<>();
David Christie1b9b7b12013-04-15 15:31:11 -0700233
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800234 // all providers that operate over proxy, for authorizing incoming location and whitelisting
235 // throttling
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700236 private final ArrayList<LocationProviderProxy> mProxyProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800237 new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800239 private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800240
Wyatt Riley11cc7492018-01-17 08:48:27 -0800241 private final ArrayMap<IBinder, Identity> mGnssMeasurementsListeners = new ArrayMap<>();
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800242
Wyatt Riley11cc7492018-01-17 08:48:27 -0800243 private final ArrayMap<IBinder, Identity>
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800244 mGnssNavigationMessageListeners = new ArrayMap<>();
245
Victoria Lease38389b62012-09-30 11:44:22 -0700246 // current active user on the device - other users are denied location data
Xiaohui Chena4490622015-09-22 15:29:31 -0700247 private int mCurrentUserId = UserHandle.USER_SYSTEM;
gomo48f1a642017-11-10 20:35:46 -0800248 private int[] mCurrentUserProfiles = new int[]{UserHandle.USER_SYSTEM};
Victoria Lease38389b62012-09-30 11:44:22 -0700249
Wei Wangdd070f22018-06-21 11:29:40 -0700250 // Maximum age of last location returned to clients with foreground-only location permissions.
251 private long mLastLocationMaxAgeMs;
252
Lifu Tang9363b942016-02-16 18:07:00 -0800253 private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;
Lifu Tang82f893d2016-01-21 18:15:33 -0800254
Siddharth Raybb608c82017-03-16 11:33:34 -0700255 private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;
Wyatt Rileyaa420d52017-07-03 15:14:42 -0700256
Yu-Han Yang3557cc72018-03-21 12:48:36 -0700257 private GnssBatchingProvider mGnssBatchingProvider;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800258 private IBatchedLocationCallback mGnssBatchingCallback;
259 private LinkedCallback mGnssBatchingDeathCallback;
260 private boolean mGnssBatchingInProgress = false;
261
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700262 public LocationManagerService(Context context) {
263 super();
264 mContext = context;
gomo48f1a642017-11-10 20:35:46 -0800265 mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800266
Svet Ganovadc1cf42015-06-15 16:36:24 -0700267 // Let the package manager query which are the default location
268 // providers as they get certain permissions granted by default.
269 PackageManagerInternal packageManagerInternal = LocalServices.getService(
270 PackageManagerInternal.class);
271 packageManagerInternal.setLocationPackagesProvider(
272 new PackageManagerInternal.PackagesProvider() {
273 @Override
274 public String[] getPackages(int userId) {
275 return mContext.getResources().getStringArray(
276 com.android.internal.R.array.config_locationProviderPackageNames);
277 }
278 });
279
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700280 if (D) Log.d(TAG, "Constructed");
281
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700282 // most startup is deferred until systemRunning()
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700283 }
284
Svetoslav Ganova0027152013-06-25 14:59:53 -0700285 public void systemRunning() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700286 synchronized (mLock) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700287 if (D) Log.d(TAG, "systemRunning()");
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700288
Victoria Lease5cd731a2012-12-19 15:04:21 -0800289 // fetch package manager
290 mPackageManager = mContext.getPackageManager();
291
Victoria Lease0aa28602013-05-29 15:28:26 -0700292 // fetch power manager
293 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
Victoria Lease5cd731a2012-12-19 15:04:21 -0800294
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800295 // fetch activity manager
296 mActivityManager
297 = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
298
Victoria Lease5cd731a2012-12-19 15:04:21 -0800299 // prepare worker thread
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700300 mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper());
Victoria Lease5cd731a2012-12-19 15:04:21 -0800301
302 // prepare mLocationHandler's dependents
303 mLocationFudger = new LocationFudger(mContext, mLocationHandler);
304 mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
305 mBlacklist.init();
306 mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
307
Dianne Hackbornc2293022013-02-06 23:14:49 -0800308 // Monitor for app ops mode changes.
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700309 AppOpsManager.OnOpChangedListener callback
310 = new AppOpsManager.OnOpChangedInternalListener() {
311 public void onOpChanged(int op, String packageName) {
Dianne Hackbornc2293022013-02-06 23:14:49 -0800312 synchronized (mLock) {
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700313 for (Receiver receiver : mReceivers.values()) {
314 receiver.updateMonitoring(true);
315 }
Dianne Hackbornc2293022013-02-06 23:14:49 -0800316 applyAllProviderRequirementsLocked();
317 }
318 }
319 };
Wei Wangdd070f22018-06-21 11:29:40 -0700320 mAppOps.startWatchingMode(AppOpsManager.OP_COARSE_LOCATION, null,
321 AppOpsManager.WATCH_FOREGROUND_CHANGES, callback);
Dianne Hackbornc2293022013-02-06 23:14:49 -0800322
David Christieb870dbf2015-06-22 12:42:53 -0700323 PackageManager.OnPermissionsChangedListener permissionListener
324 = new PackageManager.OnPermissionsChangedListener() {
325 @Override
326 public void onPermissionsChanged(final int uid) {
327 synchronized (mLock) {
328 applyAllProviderRequirementsLocked();
329 }
330 }
331 };
332 mPackageManager.addOnPermissionsChangeListener(permissionListener);
333
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800334 // listen for background/foreground changes
335 ActivityManager.OnUidImportanceListener uidImportanceListener
336 = new ActivityManager.OnUidImportanceListener() {
337 @Override
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700338 public void onUidImportance(final int uid, final int importance) {
339 mLocationHandler.post(new Runnable() {
340 @Override
341 public void run() {
342 onUidImportanceChanged(uid, importance);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800343 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700344 });
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800345 }
346 };
347 mActivityManager.addOnUidImportanceListener(uidImportanceListener,
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700348 FOREGROUND_IMPORTANCE_CUTOFF);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800349
Amith Yamasanib27528d2014-06-05 15:02:10 -0700350 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
351 updateUserProfiles(mCurrentUserId);
352
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800353 updateBackgroundThrottlingWhitelistLocked();
Wei Wangdd070f22018-06-21 11:29:40 -0700354 updateLastLocationMaxAgeLocked();
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800355
Victoria Lease5cd731a2012-12-19 15:04:21 -0800356 // prepare providers
357 loadProvidersLocked();
358 updateProvidersLocked();
359 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700360
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700361 // listen for settings changes
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700362 mContext.getContentResolver().registerContentObserver(
Laurent Tu75defb62012-11-01 16:21:52 -0700363 Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700364 new ContentObserver(mLocationHandler) {
Victoria Lease5cd731a2012-12-19 15:04:21 -0800365 @Override
366 public void onChange(boolean selfChange) {
367 synchronized (mLock) {
368 updateProvidersLocked();
369 }
370 }
371 }, UserHandle.USER_ALL);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800372 mContext.getContentResolver().registerContentObserver(
373 Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS),
374 true,
375 new ContentObserver(mLocationHandler) {
376 @Override
377 public void onChange(boolean selfChange) {
378 synchronized (mLock) {
379 updateProvidersLocked();
380 }
381 }
382 }, UserHandle.USER_ALL);
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800383 mContext.getContentResolver().registerContentObserver(
Wei Wangdd070f22018-06-21 11:29:40 -0700384 Settings.Global.getUriFor(Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS),
385 true,
386 new ContentObserver(mLocationHandler) {
387 @Override
388 public void onChange(boolean selfChange) {
389 synchronized (mLock) {
390 updateLastLocationMaxAgeLocked();
391 }
392 }
393 }
394 );
395 mContext.getContentResolver().registerContentObserver(
gomo48f1a642017-11-10 20:35:46 -0800396 Settings.Global.getUriFor(
397 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
398 true,
399 new ContentObserver(mLocationHandler) {
400 @Override
401 public void onChange(boolean selfChange) {
402 synchronized (mLock) {
403 updateBackgroundThrottlingWhitelistLocked();
404 updateProvidersLocked();
405 }
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800406 }
gomo48f1a642017-11-10 20:35:46 -0800407 }, UserHandle.USER_ALL);
Wei Wangdd070f22018-06-21 11:29:40 -0700408
Victoria Lease5cd731a2012-12-19 15:04:21 -0800409 mPackageMonitor.register(mContext, mLocationHandler.getLooper(), true);
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700410
Victoria Lease38389b62012-09-30 11:44:22 -0700411 // listen for user change
412 IntentFilter intentFilter = new IntentFilter();
413 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700414 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
415 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
destradaab9026982015-08-27 17:34:54 -0700416 intentFilter.addAction(Intent.ACTION_SHUTDOWN);
Victoria Lease38389b62012-09-30 11:44:22 -0700417
418 mContext.registerReceiverAsUser(new BroadcastReceiver() {
419 @Override
420 public void onReceive(Context context, Intent intent) {
421 String action = intent.getAction();
422 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
423 switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
Amith Yamasanib27528d2014-06-05 15:02:10 -0700424 } else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)
425 || Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
426 updateUserProfiles(mCurrentUserId);
destradaab9026982015-08-27 17:34:54 -0700427 } else if (Intent.ACTION_SHUTDOWN.equals(action)) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700428 // shutdown only if UserId indicates whole system, not just one user
gomo48f1a642017-11-10 20:35:46 -0800429 if (D) Log.d(TAG, "Shutdown received with UserId: " + getSendingUserId());
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700430 if (getSendingUserId() == UserHandle.USER_ALL) {
431 shutdownComponents();
432 }
Victoria Lease38389b62012-09-30 11:44:22 -0700433 }
434 }
Victoria Lease5cd731a2012-12-19 15:04:21 -0800435 }, UserHandle.ALL, intentFilter, null, mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700436 }
437
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700438 private void onUidImportanceChanged(int uid, int importance) {
439 boolean foreground = isImportanceForeground(importance);
440 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
441 synchronized (mLock) {
442 for (Entry<String, ArrayList<UpdateRecord>> entry
gomo48f1a642017-11-10 20:35:46 -0800443 : mRecordsByProvider.entrySet()) {
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700444 String provider = entry.getKey();
445 for (UpdateRecord record : entry.getValue()) {
446 if (record.mReceiver.mIdentity.mUid == uid
gomo48f1a642017-11-10 20:35:46 -0800447 && record.mIsForegroundUid != foreground) {
448 if (D) {
449 Log.d(TAG, "request from uid " + uid + " is now "
450 + (foreground ? "foreground" : "background)"));
451 }
Wyatt Rileyf7075e02018-04-12 17:54:26 -0700452 record.updateForeground(foreground);
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700453
454 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
455 affectedProviders.add(provider);
456 }
457 }
458 }
459 }
460 for (String provider : affectedProviders) {
461 applyRequirementsLocked(provider);
462 }
463
Wyatt Riley11cc7492018-01-17 08:48:27 -0800464 for (Entry<IBinder, Identity> entry : mGnssMeasurementsListeners.entrySet()) {
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700465 if (entry.getValue().mUid == uid) {
gomo48f1a642017-11-10 20:35:46 -0800466 if (D) {
467 Log.d(TAG, "gnss measurements listener from uid " + uid
468 + " is now " + (foreground ? "foreground" : "background)"));
469 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700470 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800471 mGnssMeasurementsProvider.addListener(
472 IGnssMeasurementsListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700473 } else {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800474 mGnssMeasurementsProvider.removeListener(
475 IGnssMeasurementsListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700476 }
477 }
478 }
479
Wyatt Riley11cc7492018-01-17 08:48:27 -0800480 for (Entry<IBinder, Identity> entry : mGnssNavigationMessageListeners.entrySet()) {
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700481 if (entry.getValue().mUid == uid) {
gomo48f1a642017-11-10 20:35:46 -0800482 if (D) {
483 Log.d(TAG, "gnss navigation message listener from uid "
484 + uid + " is now "
485 + (foreground ? "foreground" : "background)"));
486 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700487 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800488 mGnssNavigationMessageProvider.addListener(
489 IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700490 } else {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800491 mGnssNavigationMessageProvider.removeListener(
492 IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700493 }
494 }
495 }
496 }
497 }
498
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800499 private static boolean isImportanceForeground(int importance) {
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700500 return importance <= FOREGROUND_IMPORTANCE_CUTOFF;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800501 }
502
Amith Yamasanib27528d2014-06-05 15:02:10 -0700503 /**
destradaab9026982015-08-27 17:34:54 -0700504 * Provides a way for components held by the {@link LocationManagerService} to clean-up
505 * gracefully on system's shutdown.
506 *
507 * NOTES:
508 * 1) Only provides a chance to clean-up on an opt-in basis. This guarantees back-compat
509 * support for components that do not wish to handle such event.
510 */
511 private void shutdownComponents() {
gomo48f1a642017-11-10 20:35:46 -0800512 if (D) Log.d(TAG, "Shutting down components...");
destradaab9026982015-08-27 17:34:54 -0700513
514 LocationProviderInterface gpsProvider = mProvidersByName.get(LocationManager.GPS_PROVIDER);
515 if (gpsProvider != null && gpsProvider.isEnabled()) {
516 gpsProvider.disable();
517 }
destradaab9026982015-08-27 17:34:54 -0700518 }
519
520 /**
Amith Yamasanib27528d2014-06-05 15:02:10 -0700521 * Makes a list of userids that are related to the current user. This is
522 * relevant when using managed profiles. Otherwise the list only contains
523 * the current user.
524 *
525 * @param currentUserId the current user, who might have an alter-ego.
526 */
527 void updateUserProfiles(int currentUserId) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700528 int[] profileIds = mUserManager.getProfileIdsWithDisabled(currentUserId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700529 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700530 mCurrentUserProfiles = profileIds;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700531 }
532 }
533
534 /**
535 * Checks if the specified userId matches any of the current foreground
536 * users stored in mCurrentUserProfiles.
537 */
538 private boolean isCurrentProfile(int userId) {
539 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700540 return ArrayUtils.contains(mCurrentUserProfiles, userId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700541 }
542 }
543
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700544 private void ensureFallbackFusedProviderPresentLocked(String[] pkgs) {
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500545 PackageManager pm = mContext.getPackageManager();
546 String systemPackageName = mContext.getPackageName();
547 ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
548
549 List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
550 new Intent(FUSED_LOCATION_SERVICE_ACTION),
551 PackageManager.GET_META_DATA, mCurrentUserId);
552 for (ResolveInfo rInfo : rInfos) {
553 String packageName = rInfo.serviceInfo.packageName;
554
555 // Check that the signature is in the list of supported sigs. If it's not in
556 // this list the standard provider binding logic won't bind to it.
557 try {
558 PackageInfo pInfo;
559 pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
560 if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
561 Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
562 ", but has wrong signature, ignoring");
563 continue;
564 }
565 } catch (NameNotFoundException e) {
566 Log.e(TAG, "missing package: " + packageName);
567 continue;
568 }
569
570 // Get the version info
571 if (rInfo.serviceInfo.metaData == null) {
572 Log.w(TAG, "Found fused provider without metadata: " + packageName);
573 continue;
574 }
575
576 int version = rInfo.serviceInfo.metaData.getInt(
577 ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
578 if (version == 0) {
579 // This should be the fallback fused location provider.
580
581 // Make sure it's in the system partition.
582 if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
583 if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
584 continue;
585 }
586
587 // Check that the fallback is signed the same as the OS
588 // as a proxy for coreApp="true"
589 if (pm.checkSignatures(systemPackageName, packageName)
590 != PackageManager.SIGNATURE_MATCH) {
gomo48f1a642017-11-10 20:35:46 -0800591 if (D) {
592 Log.d(TAG, "Fallback candidate not signed the same as system: "
593 + packageName);
594 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500595 continue;
596 }
597
598 // Found a valid fallback.
599 if (D) Log.d(TAG, "Found fallback provider: " + packageName);
600 return;
601 } else {
602 if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
603 }
604 }
605
606 throw new IllegalStateException("Unable to find a fused location provider that is in the "
607 + "system partition with version 0 and signed with the platform certificate. "
608 + "Such a package is needed to provide a default fused location provider in the "
609 + "event that no other fused location provider has been installed or is currently "
610 + "available. For example, coreOnly boot mode when decrypting the data "
611 + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
612 }
613
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700614 private void loadProvidersLocked() {
Victoria Lease5c24fd02012-10-01 11:00:50 -0700615 // create a passive location provider, which is always enabled
616 PassiveProvider passiveProvider = new PassiveProvider(this);
617 addProviderLocked(passiveProvider);
618 mEnabledProviders.add(passiveProvider.getName());
619 mPassiveProvider = passiveProvider;
620
Lifu Tang30f95a72016-01-07 23:20:38 -0800621 if (GnssLocationProvider.isSupported()) {
Wei Liu5241a4c2015-05-11 14:00:36 -0700622 // Create a gps location provider
Lifu Tang30f95a72016-01-07 23:20:38 -0800623 GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this,
Wei Liu5241a4c2015-05-11 14:00:36 -0700624 mLocationHandler.getLooper());
Lifu Tang9363b942016-02-16 18:07:00 -0800625 mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
Wyatt Rileycf879db2017-01-12 13:57:38 -0800626 mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider();
Siddharth Raybb608c82017-03-16 11:33:34 -0700627 mGnssMetricsProvider = gnssProvider.getGnssMetricsProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800628 mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
629 mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
630 addProviderLocked(gnssProvider);
631 mRealProviders.put(LocationManager.GPS_PROVIDER, gnssProvider);
Lifu Tang818aa2c2016-02-01 01:52:00 -0800632 mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
633 mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800634 mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700635 }
636
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700637 /*
638 Load package name(s) containing location provider support.
639 These packages can contain services implementing location providers:
640 Geocoder Provider, Network Location Provider, and
641 Fused Location Provider. They will each be searched for
642 service components implementing these providers.
643 The location framework also has support for installation
644 of new location providers at run-time. The new package does not
645 have to be explicitly listed here, however it must have a signature
646 that matches the signature of at least one package on this list.
647 */
648 Resources resources = mContext.getResources();
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500649 String[] pkgs = resources.getStringArray(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700650 com.android.internal.R.array.config_locationProviderPackageNames);
gomo48f1a642017-11-10 20:35:46 -0800651 if (D) {
652 Log.d(TAG, "certificates for location providers pulled from: " +
653 Arrays.toString(pkgs));
654 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500655
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700656 ensureFallbackFusedProviderPresentLocked(pkgs);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700657
658 // bind to network provider
659 LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
660 mContext,
661 LocationManager.NETWORK_PROVIDER,
662 NETWORK_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700663 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
664 com.android.internal.R.string.config_networkLocationProviderPackageName,
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700665 com.android.internal.R.array.config_locationProviderPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700666 if (networkProvider != null) {
667 mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
668 mProxyProviders.add(networkProvider);
669 addProviderLocked(networkProvider);
670 } else {
gomo48f1a642017-11-10 20:35:46 -0800671 Slog.w(TAG, "no network location provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700672 }
673
674 // bind to fused provider
675 LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind(
676 mContext,
677 LocationManager.FUSED_PROVIDER,
678 FUSED_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700679 com.android.internal.R.bool.config_enableFusedLocationOverlay,
680 com.android.internal.R.string.config_fusedLocationProviderPackageName,
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700681 com.android.internal.R.array.config_locationProviderPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700682 if (fusedLocationProvider != null) {
683 addProviderLocked(fusedLocationProvider);
684 mProxyProviders.add(fusedLocationProvider);
685 mEnabledProviders.add(fusedLocationProvider.getName());
Kenny Rootc3575182012-10-09 12:44:40 -0700686 mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700687 } else {
688 Slog.e(TAG, "no fused location provider found",
689 new IllegalStateException("Location service needs a fused location provider"));
690 }
691
692 // bind to geocoder provider
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700693 mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
694 com.android.internal.R.bool.config_enableGeocoderOverlay,
695 com.android.internal.R.string.config_geocoderProviderPackageName,
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700696 com.android.internal.R.array.config_locationProviderPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700697 if (mGeocodeProvider == null) {
gomo48f1a642017-11-10 20:35:46 -0800698 Slog.e(TAG, "no geocoder provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700699 }
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700700
destradaaf9a274c2014-07-25 15:11:56 -0700701 // bind to geofence provider
702 GeofenceProxy provider = GeofenceProxy.createAndBind(
gomo48f1a642017-11-10 20:35:46 -0800703 mContext, com.android.internal.R.bool.config_enableGeofenceOverlay,
destradaaf9a274c2014-07-25 15:11:56 -0700704 com.android.internal.R.string.config_geofenceProviderPackageName,
705 com.android.internal.R.array.config_locationProviderPackageNames,
Wei Liu5241a4c2015-05-11 14:00:36 -0700706 mGpsGeofenceProxy,
Jiyong Park4cc3a1c2018-03-08 16:43:07 +0900707 null);
destradaaf9a274c2014-07-25 15:11:56 -0700708 if (provider == null) {
gomo48f1a642017-11-10 20:35:46 -0800709 Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
destradaa0682809a2013-08-12 18:50:30 -0700710 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900711
destradaa6e2fe752015-06-23 17:25:53 -0700712 // bind to hardware activity recognition
713 boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
714 ActivityRecognitionHardware activityRecognitionHardware = null;
715 if (activityRecognitionHardwareIsSupported) {
716 activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
destradaaa4fa3b52014-07-09 10:46:39 -0700717 } else {
destradaa6b4893a2016-05-03 15:33:43 -0700718 Slog.d(TAG, "Hardware Activity-Recognition not supported.");
destradaaa4fa3b52014-07-09 10:46:39 -0700719 }
destradaa6e2fe752015-06-23 17:25:53 -0700720 ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
721 mContext,
destradaa6e2fe752015-06-23 17:25:53 -0700722 activityRecognitionHardwareIsSupported,
723 activityRecognitionHardware,
724 com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
725 com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
726 com.android.internal.R.array.config_locationProviderPackageNames);
727 if (proxy == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700728 Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
destradaa6e2fe752015-06-23 17:25:53 -0700729 }
destradaaa4fa3b52014-07-09 10:46:39 -0700730
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900731 String[] testProviderStrings = resources.getStringArray(
732 com.android.internal.R.array.config_testLocationProviders);
733 for (String testProviderString : testProviderStrings) {
734 String fragments[] = testProviderString.split(",");
735 String name = fragments[0].trim();
736 if (mProvidersByName.get(name) != null) {
737 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
738 }
739 ProviderProperties properties = new ProviderProperties(
740 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
741 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
742 Boolean.parseBoolean(fragments[3]) /* requiresCell */,
743 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
744 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
745 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
746 Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
747 Integer.parseInt(fragments[8]) /* powerRequirement */,
748 Integer.parseInt(fragments[9]) /* accuracy */);
749 addTestProviderLocked(name, properties);
750 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700751 }
Mike Lockwood9637d472009-04-02 21:41:57 -0700752
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800753 /**
Victoria Lease38389b62012-09-30 11:44:22 -0700754 * Called when the device's active user changes.
gomo48f1a642017-11-10 20:35:46 -0800755 *
Victoria Lease38389b62012-09-30 11:44:22 -0700756 * @param userId the new active user's UserId
757 */
758 private void switchUser(int userId) {
Jianzheng Zhoud5c69462013-10-10 14:02:09 +0800759 if (mCurrentUserId == userId) {
760 return;
761 }
Victoria Lease83762d22012-10-03 13:51:17 -0700762 mBlacklist.switchUser(userId);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800763 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED);
Victoria Lease38389b62012-09-30 11:44:22 -0700764 synchronized (mLock) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700765 mLastLocation.clear();
David Christie1b9b7b12013-04-15 15:31:11 -0700766 mLastLocationCoarseInterval.clear();
Victoria Leaseb711d572012-10-02 13:14:11 -0700767 for (LocationProviderInterface p : mProviders) {
Amith Yamasanib27528d2014-06-05 15:02:10 -0700768 updateProviderListenersLocked(p.getName(), false);
Victoria Leaseb711d572012-10-02 13:14:11 -0700769 }
Victoria Lease38389b62012-09-30 11:44:22 -0700770 mCurrentUserId = userId;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700771 updateUserProfiles(userId);
Victoria Leaseb711d572012-10-02 13:14:11 -0700772 updateProvidersLocked();
Victoria Lease38389b62012-09-30 11:44:22 -0700773 }
774 }
775
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800776 private static final class Identity {
777 final int mUid;
778 final int mPid;
779 final String mPackageName;
780
781 Identity(int uid, int pid, String packageName) {
782 mUid = uid;
783 mPid = pid;
784 mPackageName = packageName;
785 }
786 }
787
Victoria Lease38389b62012-09-30 11:44:22 -0700788 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789 * A wrapper class holding either an ILocationListener or a PendingIntent to receive
790 * location updates.
791 */
Mike Lockwood48f17512009-04-23 09:12:08 -0700792 private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
Yu-Han Yang24189822018-07-11 15:24:11 -0700793 private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800794 final Identity mIdentity;
Victoria Lease37425c32012-10-16 16:08:48 -0700795 final int mAllowedResolutionLevel; // resolution level allowed to receiver
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 final ILocationListener mListener;
798 final PendingIntent mPendingIntent;
David Christie82edc9b2013-07-19 11:31:42 -0700799 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
David Christie40e57822013-07-30 11:36:48 -0700800 final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801 final Object mKey;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700802
gomo48f1a642017-11-10 20:35:46 -0800803 final HashMap<String, UpdateRecord> mUpdateRecords = new HashMap<>();
Nick Pellyf1be6862012-05-15 10:53:42 -0700804
David Christie0b837452013-07-29 16:02:13 -0700805 // True if app ops has started monitoring this receiver for locations.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700806 boolean mOpMonitoring;
David Christie0b837452013-07-29 16:02:13 -0700807 // True if app ops has started monitoring this receiver for high power (gps) locations.
808 boolean mOpHighPowerMonitoring;
Mike Lockwood48f17512009-04-23 09:12:08 -0700809 int mPendingBroadcasts;
Victoria Lease0aa28602013-05-29 15:28:26 -0700810 PowerManager.WakeLock mWakeLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800811
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700812 Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -0700813 String packageName, WorkSource workSource, boolean hideFromAppOps) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800814 mListener = listener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 mPendingIntent = intent;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700816 if (listener != null) {
817 mKey = listener.asBinder();
818 } else {
819 mKey = intent;
820 }
Victoria Lease37425c32012-10-16 16:08:48 -0700821 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800822 mIdentity = new Identity(uid, pid, packageName);
Narayan Kamath32684dd2018-01-08 17:32:51 +0000823 if (workSource != null && workSource.isEmpty()) {
David Christie82edc9b2013-07-19 11:31:42 -0700824 workSource = null;
825 }
826 mWorkSource = workSource;
David Christie40e57822013-07-30 11:36:48 -0700827 mHideFromAppOps = hideFromAppOps;
Victoria Lease0aa28602013-05-29 15:28:26 -0700828
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700829 updateMonitoring(true);
830
Victoria Lease0aa28602013-05-29 15:28:26 -0700831 // construct/configure wakelock
832 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
David Christie82edc9b2013-07-19 11:31:42 -0700833 if (workSource == null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800834 workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -0700835 }
836 mWakeLock.setWorkSource(workSource);
Yu-Han Yang24189822018-07-11 15:24:11 -0700837
838 // For a non-reference counted wakelock, each acquire will reset the timeout, and we
839 // only need to release it once.
840 mWakeLock.setReferenceCounted(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800841 }
842
843 @Override
844 public boolean equals(Object otherObj) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800845 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846 }
847
848 @Override
849 public int hashCode() {
850 return mKey.hashCode();
851 }
Mike Lockwood3681f262009-05-12 10:52:03 -0400852
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 @Override
854 public String toString() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700855 StringBuilder s = new StringBuilder();
856 s.append("Reciever[");
857 s.append(Integer.toHexString(System.identityHashCode(this)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800858 if (mListener != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700859 s.append(" listener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700861 s.append(" intent");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800862 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700863 for (String p : mUpdateRecords.keySet()) {
864 s.append(" ").append(mUpdateRecords.get(p).toString());
865 }
Wei Wangdd070f22018-06-21 11:29:40 -0700866 s.append(" monitoring location: ").append(mOpMonitoring);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700867 s.append("]");
868 return s.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 }
870
David Christie15b31912013-08-13 15:54:32 -0700871 /**
872 * Update AppOp monitoring for this receiver.
873 *
874 * @param allow If true receiver is currently active, if false it's been removed.
875 */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700876 public void updateMonitoring(boolean allow) {
David Christie40e57822013-07-30 11:36:48 -0700877 if (mHideFromAppOps) {
878 return;
879 }
880
David Christie15b31912013-08-13 15:54:32 -0700881 boolean requestingLocation = false;
882 boolean requestingHighPowerLocation = false;
883 if (allow) {
884 // See if receiver has any enabled update records. Also note if any update records
885 // are high power (has a high power provider with an interval under a threshold).
886 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
887 if (isAllowedByCurrentUserSettingsLocked(updateRecord.mProvider)) {
888 requestingLocation = true;
889 LocationProviderInterface locationProvider
David Christie2ff96af2014-01-30 16:09:37 -0800890 = mProvidersByName.get(updateRecord.mProvider);
David Christie15b31912013-08-13 15:54:32 -0700891 ProviderProperties properties = locationProvider != null
892 ? locationProvider.getProperties() : null;
893 if (properties != null
894 && properties.mPowerRequirement == Criteria.POWER_HIGH
895 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
896 requestingHighPowerLocation = true;
897 break;
898 }
899 }
900 }
901 }
902
David Christie0b837452013-07-29 16:02:13 -0700903 // First update monitoring of any location request (including high power).
David Christie15b31912013-08-13 15:54:32 -0700904 mOpMonitoring = updateMonitoring(
905 requestingLocation,
906 mOpMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700907 AppOpsManager.OP_MONITOR_LOCATION);
908
909 // Now update monitoring of high power requests only.
David Christiec750c1f2013-08-08 12:56:57 -0700910 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
David Christie15b31912013-08-13 15:54:32 -0700911 mOpHighPowerMonitoring = updateMonitoring(
912 requestingHighPowerLocation,
913 mOpHighPowerMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700914 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
David Christiec750c1f2013-08-08 12:56:57 -0700915 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
David Christie15b31912013-08-13 15:54:32 -0700916 // Send an intent to notify that a high power request has been added/removed.
David Christiec750c1f2013-08-08 12:56:57 -0700917 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
918 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
919 }
David Christie0b837452013-07-29 16:02:13 -0700920 }
921
922 /**
923 * Update AppOps monitoring for a single location request and op type.
924 *
gomo48f1a642017-11-10 20:35:46 -0800925 * @param allowMonitoring True if monitoring is allowed for this request/op.
David Christie0b837452013-07-29 16:02:13 -0700926 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
gomo48f1a642017-11-10 20:35:46 -0800927 * @param op AppOps code for the op to update.
David Christie0b837452013-07-29 16:02:13 -0700928 * @return True if monitoring is on for this request/op after updating.
929 */
930 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
931 int op) {
932 if (!currentlyMonitoring) {
933 if (allowMonitoring) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800934 return mAppOps.startOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700935 == AppOpsManager.MODE_ALLOWED;
936 }
937 } else {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800938 if (!allowMonitoring
Wei Wangdd070f22018-06-21 11:29:40 -0700939 || mAppOps.noteOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700940 != AppOpsManager.MODE_ALLOWED) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800941 mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName);
David Christie0b837452013-07-29 16:02:13 -0700942 return false;
943 }
944 }
945
946 return currentlyMonitoring;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700947 }
948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800949 public boolean isListener() {
950 return mListener != null;
951 }
952
953 public boolean isPendingIntent() {
954 return mPendingIntent != null;
955 }
956
957 public ILocationListener getListener() {
958 if (mListener != null) {
959 return mListener;
960 }
961 throw new IllegalStateException("Request for non-existent listener");
962 }
963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
965 if (mListener != null) {
966 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700967 synchronized (this) {
968 // synchronize to ensure incrementPendingBroadcastsLocked()
969 // is called before decrementPendingBroadcasts()
970 mListener.onStatusChanged(provider, status, extras);
Nick Pellye0fd6932012-07-11 10:26:13 -0700971 // call this after broadcasting so we do not increment
972 // if we throw an exeption.
973 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -0700974 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 } catch (RemoteException e) {
976 return false;
977 }
978 } else {
979 Intent statusChanged = new Intent();
Victoria Lease61ecb022012-11-13 15:12:51 -0800980 statusChanged.putExtras(new Bundle(extras));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800981 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
982 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700983 synchronized (this) {
984 // synchronize to ensure incrementPendingBroadcastsLocked()
985 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700986 mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
Lifu Tang519f0d02018-04-12 16:39:39 -0700987 getResolutionPermission(mAllowedResolutionLevel),
988 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
Mike Lockwood48f17512009-04-23 09:12:08 -0700989 // call this after broadcasting so we do not increment
990 // if we throw an exeption.
991 incrementPendingBroadcastsLocked();
992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 } catch (PendingIntent.CanceledException e) {
994 return false;
995 }
996 }
997 return true;
998 }
999
1000 public boolean callLocationChangedLocked(Location location) {
1001 if (mListener != null) {
1002 try {
Mike Lockwood48f17512009-04-23 09:12:08 -07001003 synchronized (this) {
1004 // synchronize to ensure incrementPendingBroadcastsLocked()
1005 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08001006 mListener.onLocationChanged(new Location(location));
Nick Pellye0fd6932012-07-11 10:26:13 -07001007 // call this after broadcasting so we do not increment
1008 // if we throw an exeption.
1009 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001010 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 } catch (RemoteException e) {
1012 return false;
1013 }
1014 } else {
1015 Intent locationChanged = new Intent();
gomo48f1a642017-11-10 20:35:46 -08001016 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED,
1017 new Location(location));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 try {
Mike Lockwood48f17512009-04-23 09:12:08 -07001019 synchronized (this) {
1020 // synchronize to ensure incrementPendingBroadcastsLocked()
1021 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001022 mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
Lifu Tang519f0d02018-04-12 16:39:39 -07001023 getResolutionPermission(mAllowedResolutionLevel),
1024 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
Mike Lockwood48f17512009-04-23 09:12:08 -07001025 // call this after broadcasting so we do not increment
1026 // if we throw an exeption.
1027 incrementPendingBroadcastsLocked();
1028 }
1029 } catch (PendingIntent.CanceledException e) {
1030 return false;
1031 }
1032 }
1033 return true;
1034 }
1035
1036 public boolean callProviderEnabledLocked(String provider, boolean enabled) {
David Christie15b31912013-08-13 15:54:32 -07001037 // First update AppOp monitoring.
1038 // An app may get/lose location access as providers are enabled/disabled.
1039 updateMonitoring(true);
1040
Mike Lockwood48f17512009-04-23 09:12:08 -07001041 if (mListener != null) {
1042 try {
1043 synchronized (this) {
1044 // synchronize to ensure incrementPendingBroadcastsLocked()
1045 // is called before decrementPendingBroadcasts()
1046 if (enabled) {
1047 mListener.onProviderEnabled(provider);
1048 } else {
1049 mListener.onProviderDisabled(provider);
1050 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001051 // call this after broadcasting so we do not increment
1052 // if we throw an exeption.
1053 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001054 }
1055 } catch (RemoteException e) {
1056 return false;
1057 }
1058 } else {
1059 Intent providerIntent = new Intent();
1060 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1061 try {
1062 synchronized (this) {
1063 // synchronize to ensure incrementPendingBroadcastsLocked()
1064 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001065 mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
Lifu Tang519f0d02018-04-12 16:39:39 -07001066 getResolutionPermission(mAllowedResolutionLevel),
1067 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
Mike Lockwood48f17512009-04-23 09:12:08 -07001068 // call this after broadcasting so we do not increment
1069 // if we throw an exeption.
1070 incrementPendingBroadcastsLocked();
1071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 } catch (PendingIntent.CanceledException e) {
1073 return false;
1074 }
1075 }
1076 return true;
1077 }
1078
Nick Pellyf1be6862012-05-15 10:53:42 -07001079 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001080 public void binderDied() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001081 if (D) Log.d(TAG, "Location listener died");
1082
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001083 synchronized (mLock) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084 removeUpdatesLocked(this);
1085 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001086 synchronized (this) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001087 clearPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001088 }
1089 }
1090
Nick Pellye0fd6932012-07-11 10:26:13 -07001091 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001092 public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1093 int resultCode, String resultData, Bundle resultExtras) {
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001094 synchronized (this) {
1095 decrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001096 }
1097 }
1098
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001099 // this must be called while synchronized by caller in a synchronized block
1100 // containing the sending of the broadcaset
1101 private void incrementPendingBroadcastsLocked() {
Yu-Han Yang24189822018-07-11 15:24:11 -07001102 mPendingBroadcasts++;
1103 mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001104 }
1105
1106 private void decrementPendingBroadcastsLocked() {
1107 if (--mPendingBroadcasts == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001108 if (mWakeLock.isHeld()) {
1109 mWakeLock.release();
1110 }
1111 }
1112 }
1113
1114 public void clearPendingBroadcastsLocked() {
1115 if (mPendingBroadcasts > 0) {
1116 mPendingBroadcasts = 0;
1117 if (mWakeLock.isHeld()) {
1118 mWakeLock.release();
1119 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001120 }
1121 }
1122 }
1123
Nick Pellye0fd6932012-07-11 10:26:13 -07001124 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001125 public void locationCallbackFinished(ILocationListener listener) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001126 //Do not use getReceiverLocked here as that will add the ILocationListener to
Joshua Bartel080b61b2009-10-05 12:44:46 -04001127 //the receiver list if it is not found. If it is not found then the
1128 //LocationListener was removed when it had a pending broadcast and should
1129 //not be added back.
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001130 synchronized (mLock) {
1131 IBinder binder = listener.asBinder();
1132 Receiver receiver = mReceivers.get(binder);
1133 if (receiver != null) {
1134 synchronized (receiver) {
1135 // so wakelock calls will succeed
1136 long identity = Binder.clearCallingIdentity();
1137 receiver.decrementPendingBroadcastsLocked();
1138 Binder.restoreCallingIdentity(identity);
David Christie2ff96af2014-01-30 16:09:37 -08001139 }
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001140 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001141 }
1142 }
1143
Lifu Tang82f893d2016-01-21 18:15:33 -08001144 /**
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001145 * Returns the year of the GNSS hardware.
Lifu Tang82f893d2016-01-21 18:15:33 -08001146 */
1147 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001148 public int getGnssYearOfHardware() {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001149 if (mGnssSystemInfoProvider != null) {
Lifu Tang9363b942016-02-16 18:07:00 -08001150 return mGnssSystemInfoProvider.getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001151 } else {
1152 return 0;
1153 }
1154 }
1155
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001156
1157 /**
1158 * Returns the model name of the GNSS hardware.
1159 */
1160 @Override
Wyatt Riley49097c02018-03-15 09:14:43 -07001161 @Nullable
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001162 public String getGnssHardwareModelName() {
1163 if (mGnssSystemInfoProvider != null) {
1164 return mGnssSystemInfoProvider.getGnssHardwareModelName();
1165 } else {
Wyatt Riley49097c02018-03-15 09:14:43 -07001166 return null;
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001167 }
1168 }
1169
Wyatt Rileycf879db2017-01-12 13:57:38 -08001170 /**
1171 * Runs some checks for GNSS (FINE) level permissions, used by several methods which directly
1172 * (try to) access GNSS information at this layer.
1173 */
1174 private boolean hasGnssPermissions(String packageName) {
1175 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
1176 checkResolutionLevelIsSufficientForProviderUse(
1177 allowedResolutionLevel,
1178 LocationManager.GPS_PROVIDER);
1179
1180 int pid = Binder.getCallingPid();
1181 int uid = Binder.getCallingUid();
1182 long identity = Binder.clearCallingIdentity();
1183 boolean hasLocationAccess;
1184 try {
1185 hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
1186 } finally {
1187 Binder.restoreCallingIdentity(identity);
1188 }
1189
1190 return hasLocationAccess;
1191 }
1192
1193 /**
1194 * Returns the GNSS batching size, if available.
1195 */
1196 @Override
1197 public int getGnssBatchSize(String packageName) {
1198 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1199 "Location Hardware permission not granted to access hardware batching");
1200
1201 if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
Yu-Han Yang3557cc72018-03-21 12:48:36 -07001202 return mGnssBatchingProvider.getBatchSize();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001203 } else {
1204 return 0;
1205 }
1206 }
1207
1208 /**
1209 * Adds a callback for GNSS Batching events, if permissions allow, which are transported
1210 * to potentially multiple listeners by the BatchedLocationCallbackTransport above this.
1211 */
1212 @Override
1213 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) {
1214 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1215 "Location Hardware permission not granted to access hardware batching");
1216
1217 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1218 return false;
1219 }
1220
1221 mGnssBatchingCallback = callback;
1222 mGnssBatchingDeathCallback = new LinkedCallback(callback);
1223 try {
1224 callback.asBinder().linkToDeath(mGnssBatchingDeathCallback, 0 /* flags */);
1225 } catch (RemoteException e) {
1226 // if the remote process registering the listener is already dead, just swallow the
1227 // exception and return
1228 Log.e(TAG, "Remote listener already died.", e);
1229 return false;
1230 }
1231
1232 return true;
1233 }
1234
1235 private class LinkedCallback implements IBinder.DeathRecipient {
1236 private final IBatchedLocationCallback mCallback;
1237
1238 public LinkedCallback(@NonNull IBatchedLocationCallback callback) {
1239 mCallback = callback;
1240 }
1241
1242 @NonNull
1243 public IBatchedLocationCallback getUnderlyingListener() {
1244 return mCallback;
1245 }
1246
1247 @Override
1248 public void binderDied() {
1249 Log.d(TAG, "Remote Batching Callback died: " + mCallback);
1250 stopGnssBatch();
1251 removeGnssBatchingCallback();
1252 }
1253 }
1254
1255 /**
1256 * Removes callback for GNSS batching
1257 */
1258 @Override
1259 public void removeGnssBatchingCallback() {
1260 try {
1261 mGnssBatchingCallback.asBinder().unlinkToDeath(mGnssBatchingDeathCallback,
1262 0 /* flags */);
1263 } catch (NoSuchElementException e) {
1264 // if the death callback isn't connected (it should be...), log error, swallow the
1265 // exception and return
1266 Log.e(TAG, "Couldn't unlink death callback.", e);
1267 }
1268 mGnssBatchingCallback = null;
1269 mGnssBatchingDeathCallback = null;
1270 }
1271
1272
1273 /**
1274 * Starts GNSS batching, if available.
1275 */
1276 @Override
1277 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
1278 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1279 "Location Hardware permission not granted to access hardware batching");
1280
1281 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1282 return false;
1283 }
1284
1285 if (mGnssBatchingInProgress) {
1286 // Current design does not expect multiple starts to be called repeatedly
1287 Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch");
1288 // Try to clean up anyway, and continue
1289 stopGnssBatch();
1290 }
1291
1292 mGnssBatchingInProgress = true;
1293 return mGnssBatchingProvider.start(periodNanos, wakeOnFifoFull);
1294 }
1295
1296 /**
1297 * Flushes a GNSS batch in progress
1298 */
1299 @Override
1300 public void flushGnssBatch(String packageName) {
1301 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1302 "Location Hardware permission not granted to access hardware batching");
1303
1304 if (!hasGnssPermissions(packageName)) {
1305 Log.e(TAG, "flushGnssBatch called without GNSS permissions");
1306 return;
1307 }
1308
1309 if (!mGnssBatchingInProgress) {
1310 Log.w(TAG, "flushGnssBatch called with no batch in progress");
1311 }
1312
1313 if (mGnssBatchingProvider != null) {
gomo48f1a642017-11-10 20:35:46 -08001314 mGnssBatchingProvider.flush();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001315 }
1316 }
1317
1318 /**
1319 * Stops GNSS batching
1320 */
1321 @Override
1322 public boolean stopGnssBatch() {
1323 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1324 "Location Hardware permission not granted to access hardware batching");
1325
1326 if (mGnssBatchingProvider != null) {
1327 mGnssBatchingInProgress = false;
1328 return mGnssBatchingProvider.stop();
gomo48f1a642017-11-10 20:35:46 -08001329 } else {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001330 return false;
1331 }
1332 }
1333
1334 @Override
1335 public void reportLocationBatch(List<Location> locations) {
1336 checkCallerIsProvider();
1337
1338 // Currently used only for GNSS locations - update permissions check if changed
1339 if (isAllowedByCurrentUserSettingsLocked(LocationManager.GPS_PROVIDER)) {
1340 if (mGnssBatchingCallback == null) {
1341 Slog.e(TAG, "reportLocationBatch() called without active Callback");
1342 return;
1343 }
1344 try {
1345 mGnssBatchingCallback.onLocationBatch(locations);
1346 } catch (RemoteException e) {
1347 Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e);
1348 }
1349 } else {
1350 Slog.w(TAG, "reportLocationBatch() called without user permission, locations blocked");
1351 }
1352 }
1353
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001354 private void addProviderLocked(LocationProviderInterface provider) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001355 mProviders.add(provider);
1356 mProvidersByName.put(provider.getName(), provider);
1357 }
1358
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001359 private void removeProviderLocked(LocationProviderInterface provider) {
1360 provider.disable();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001361 mProviders.remove(provider);
1362 mProvidersByName.remove(provider.getName());
1363 }
1364
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001365 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001366 * Returns "true" if access to the specified location provider is allowed by the current
1367 * user's settings. Access to all location providers is forbidden to non-location-provider
1368 * processes belonging to background users.
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001369 *
1370 * @param provider the name of the location provider
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001371 */
Victoria Lease09eeaec2013-02-05 11:34:13 -08001372 private boolean isAllowedByCurrentUserSettingsLocked(String provider) {
Maggie2a9409e2018-03-21 11:47:28 -07001373 return isAllowedByUserSettingsLockedForUser(provider, mCurrentUserId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001374 }
1375
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001376 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001377 * Returns "true" if access to the specified location provider is allowed by the specified
1378 * user's settings. Access to all location providers is forbidden to non-location-provider
1379 * processes belonging to background users.
1380 *
1381 * @param provider the name of the location provider
Maggie2a9409e2018-03-21 11:47:28 -07001382 * @param userId the user id to query
Victoria Lease09eeaec2013-02-05 11:34:13 -08001383 */
Maggie2a9409e2018-03-21 11:47:28 -07001384 private boolean isAllowedByUserSettingsLockedForUser(String provider, int userId) {
1385 if (mEnabledProviders.contains(provider)) {
1386 return true;
1387 }
1388 if (mDisabledProviders.contains(provider)) {
1389 return false;
1390 }
1391 return isLocationProviderEnabledForUser(provider, userId);
1392 }
1393
1394
1395 /**
1396 * Returns "true" if access to the specified location provider is allowed by the specified
1397 * user's settings. Access to all location providers is forbidden to non-location-provider
1398 * processes belonging to background users.
1399 *
1400 * @param provider the name of the location provider
1401 * @param uid the requestor's UID
1402 * @param userId the user id to query
1403 */
1404 private boolean isAllowedByUserSettingsLocked(String provider, int uid, int userId) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001405 if (!isCurrentProfile(UserHandle.getUserId(uid)) && !isUidALocationProvider(uid)) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08001406 return false;
1407 }
Maggie2a9409e2018-03-21 11:47:28 -07001408 return isAllowedByUserSettingsLockedForUser(provider, userId);
Victoria Lease09eeaec2013-02-05 11:34:13 -08001409 }
1410
1411 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001412 * Returns the permission string associated with the specified resolution level.
1413 *
1414 * @param resolutionLevel the resolution level
1415 * @return the permission string
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001416 */
Victoria Lease37425c32012-10-16 16:08:48 -07001417 private String getResolutionPermission(int resolutionLevel) {
1418 switch (resolutionLevel) {
1419 case RESOLUTION_LEVEL_FINE:
1420 return android.Manifest.permission.ACCESS_FINE_LOCATION;
1421 case RESOLUTION_LEVEL_COARSE:
1422 return android.Manifest.permission.ACCESS_COARSE_LOCATION;
1423 default:
1424 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001425 }
Victoria Leaseda479c52012-10-15 15:24:16 -07001426 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001427
Victoria Leaseda479c52012-10-15 15:24:16 -07001428 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001429 * Returns the resolution level allowed to the given PID/UID pair.
1430 *
1431 * @param pid the PID
1432 * @param uid the UID
1433 * @return resolution level allowed to the pid/uid pair
Victoria Leaseda479c52012-10-15 15:24:16 -07001434 */
Victoria Lease37425c32012-10-16 16:08:48 -07001435 private int getAllowedResolutionLevel(int pid, int uid) {
1436 if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001437 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001438 return RESOLUTION_LEVEL_FINE;
1439 } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001440 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001441 return RESOLUTION_LEVEL_COARSE;
1442 } else {
1443 return RESOLUTION_LEVEL_NONE;
Victoria Leaseda479c52012-10-15 15:24:16 -07001444 }
Victoria Lease4fab68b2012-09-13 13:20:59 -07001445 }
1446
1447 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001448 * Returns the resolution level allowed to the caller
1449 *
1450 * @return resolution level allowed to caller
Victoria Lease4fab68b2012-09-13 13:20:59 -07001451 */
Victoria Lease37425c32012-10-16 16:08:48 -07001452 private int getCallerAllowedResolutionLevel() {
1453 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
1454 }
1455
1456 /**
1457 * Throw SecurityException if specified resolution level is insufficient to use geofences.
1458 *
1459 * @param allowedResolutionLevel resolution level allowed to caller
1460 */
1461 private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
1462 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Lease4fab68b2012-09-13 13:20:59 -07001463 throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
1464 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001465 }
1466
Victoria Lease37425c32012-10-16 16:08:48 -07001467 /**
1468 * Return the minimum resolution level required to use the specified location provider.
1469 *
1470 * @param provider the name of the location provider
1471 * @return minimum resolution level required for provider
1472 */
1473 private int getMinimumResolutionLevelForProviderUse(String provider) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001474 if (LocationManager.GPS_PROVIDER.equals(provider) ||
1475 LocationManager.PASSIVE_PROVIDER.equals(provider)) {
1476 // gps and passive providers require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001477 return RESOLUTION_LEVEL_FINE;
Victoria Lease8dbb6342012-09-21 16:55:53 -07001478 } else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
1479 LocationManager.FUSED_PROVIDER.equals(provider)) {
1480 // network and fused providers are ok with COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001481 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001482 } else {
1483 // mock providers
1484 LocationProviderInterface lp = mMockProviders.get(provider);
1485 if (lp != null) {
1486 ProviderProperties properties = lp.getProperties();
1487 if (properties != null) {
1488 if (properties.mRequiresSatellite) {
1489 // provider requiring satellites require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001490 return RESOLUTION_LEVEL_FINE;
Laurent Tu941221c2012-10-04 14:21:52 -07001491 } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
1492 // provider requiring network and or cell require COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001493 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001494 }
1495 }
1496 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001497 }
Victoria Lease37425c32012-10-16 16:08:48 -07001498 return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
Victoria Leaseda479c52012-10-15 15:24:16 -07001499 }
1500
Victoria Lease37425c32012-10-16 16:08:48 -07001501 /**
1502 * Throw SecurityException if specified resolution level is insufficient to use the named
1503 * location provider.
1504 *
1505 * @param allowedResolutionLevel resolution level allowed to caller
gomo48f1a642017-11-10 20:35:46 -08001506 * @param providerName the name of the location provider
Victoria Lease37425c32012-10-16 16:08:48 -07001507 */
1508 private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel,
1509 String providerName) {
1510 int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName);
1511 if (allowedResolutionLevel < requiredResolutionLevel) {
1512 switch (requiredResolutionLevel) {
1513 case RESOLUTION_LEVEL_FINE:
1514 throw new SecurityException("\"" + providerName + "\" location provider " +
1515 "requires ACCESS_FINE_LOCATION permission.");
1516 case RESOLUTION_LEVEL_COARSE:
1517 throw new SecurityException("\"" + providerName + "\" location provider " +
1518 "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
1519 default:
1520 throw new SecurityException("Insufficient permission for \"" + providerName +
1521 "\" location provider.");
Victoria Leaseda479c52012-10-15 15:24:16 -07001522 }
1523 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001524 }
1525
David Christie82edc9b2013-07-19 11:31:42 -07001526 /**
1527 * Throw SecurityException if WorkSource use is not allowed (i.e. can't blame other packages
1528 * for battery).
1529 */
David Christie40e57822013-07-30 11:36:48 -07001530 private void checkDeviceStatsAllowed() {
David Christie82edc9b2013-07-19 11:31:42 -07001531 mContext.enforceCallingOrSelfPermission(
1532 android.Manifest.permission.UPDATE_DEVICE_STATS, null);
1533 }
1534
David Christie40e57822013-07-30 11:36:48 -07001535 private void checkUpdateAppOpsAllowed() {
1536 mContext.enforceCallingOrSelfPermission(
1537 android.Manifest.permission.UPDATE_APP_OPS_STATS, null);
1538 }
1539
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001540 public static int resolutionLevelToOp(int allowedResolutionLevel) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001541 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
1542 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001543 return AppOpsManager.OP_COARSE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001544 } else {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001545 return AppOpsManager.OP_FINE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001546 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001547 }
1548 return -1;
1549 }
1550
Wei Wangb86334f2018-07-03 16:33:24 -07001551 private static String resolutionLevelToOpStr(int allowedResolutionLevel) {
1552 switch(allowedResolutionLevel) {
1553 case RESOLUTION_LEVEL_COARSE:
1554 return AppOpsManager.OPSTR_COARSE_LOCATION;
1555 case RESOLUTION_LEVEL_FINE:
1556 return AppOpsManager.OPSTR_FINE_LOCATION;
1557 case RESOLUTION_LEVEL_NONE:
1558 // The client is not allowed to get any location, so both FINE and COARSE ops will
1559 // be denied. Pick the most restrictive one to be safe.
1560 return AppOpsManager.OPSTR_FINE_LOCATION;
1561 default:
1562 // Use the most restrictive ops if not sure.
1563 return AppOpsManager.OPSTR_FINE_LOCATION;
1564 }
1565 }
1566
David Christieb870dbf2015-06-22 12:42:53 -07001567 boolean reportLocationAccessNoThrow(
1568 int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001569 int op = resolutionLevelToOp(allowedResolutionLevel);
1570 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001571 if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1572 return false;
1573 }
1574 }
David Christieb870dbf2015-06-22 12:42:53 -07001575
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001576 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001577 }
1578
David Christieb870dbf2015-06-22 12:42:53 -07001579 boolean checkLocationAccess(int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001580 int op = resolutionLevelToOp(allowedResolutionLevel);
1581 if (op >= 0) {
Wei Wangdd070f22018-06-21 11:29:40 -07001582 if (mAppOps.noteOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001583 return false;
1584 }
1585 }
David Christieb870dbf2015-06-22 12:42:53 -07001586
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001587 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001588 }
1589
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001590 /**
Maggie91e630c2018-01-24 17:31:46 -08001591 * Returns all providers by name, including passive and the ones that are not permitted to
1592 * be accessed by the calling activity or are currently disabled, but excluding fused.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001593 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001594 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 public List<String> getAllProviders() {
Maggie91e630c2018-01-24 17:31:46 -08001596 ArrayList<String> out;
1597 synchronized (mLock) {
1598 out = new ArrayList<>(mProviders.size());
1599 for (LocationProviderInterface provider : mProviders) {
1600 String name = provider.getName();
1601 if (LocationManager.FUSED_PROVIDER.equals(name)) {
1602 continue;
1603 }
1604 out.add(name);
1605 }
1606 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001607 if (D) Log.d(TAG, "getAllProviders()=" + out);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001608 return out;
1609 }
1610
Mike Lockwood03ca2162010-04-01 08:10:09 -07001611 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001612 * Return all providers by name, that match criteria and are optionally
1613 * enabled.
1614 * Can return passive provider, but never returns fused provider.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001615 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001616 @Override
1617 public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
Victoria Lease37425c32012-10-16 16:08:48 -07001618 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001619 ArrayList<String> out;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001620 int uid = Binder.getCallingUid();
Victoria Lease269518e2012-10-29 08:25:39 -07001621 long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07001622 try {
1623 synchronized (mLock) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001624 out = new ArrayList<>(mProviders.size());
Victoria Leaseb711d572012-10-02 13:14:11 -07001625 for (LocationProviderInterface provider : mProviders) {
1626 String name = provider.getName();
1627 if (LocationManager.FUSED_PROVIDER.equals(name)) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001628 continue;
1629 }
Victoria Lease37425c32012-10-16 16:08:48 -07001630 if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
Maggie2a9409e2018-03-21 11:47:28 -07001631 if (enabledOnly
1632 && !isAllowedByUserSettingsLocked(name, uid, mCurrentUserId)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001633 continue;
1634 }
1635 if (criteria != null && !LocationProvider.propertiesMeetCriteria(
1636 name, provider.getProperties(), criteria)) {
1637 continue;
1638 }
1639 out.add(name);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001640 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001641 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001642 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001643 } finally {
1644 Binder.restoreCallingIdentity(identity);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001645 }
1646
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001647 if (D) Log.d(TAG, "getProviders()=" + out);
1648 return out;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001649 }
1650
1651 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001652 * Return the name of the best provider given a Criteria object.
1653 * This method has been deprecated from the public API,
Victoria Lease8dbb6342012-09-21 16:55:53 -07001654 * and the whole LocationProvider (including #meetsCriteria)
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001655 * has been deprecated as well. So this method now uses
1656 * some simplified logic.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001657 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001658 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001659 public String getBestProvider(Criteria criteria, boolean enabledOnly) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001660 String result = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001661
1662 List<String> providers = getProviders(criteria, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001663 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001664 result = pickBest(providers);
1665 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1666 return result;
1667 }
1668 providers = getProviders(null, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001669 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001670 result = pickBest(providers);
1671 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1672 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001673 }
1674
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001675 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001676 return null;
1677 }
1678
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001679 private String pickBest(List<String> providers) {
Victoria Lease1925e292012-09-24 17:00:18 -07001680 if (providers.contains(LocationManager.GPS_PROVIDER)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001681 return LocationManager.GPS_PROVIDER;
Victoria Lease1925e292012-09-24 17:00:18 -07001682 } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
1683 return LocationManager.NETWORK_PROVIDER;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001684 } else {
1685 return providers.get(0);
1686 }
1687 }
1688
Nick Pellye0fd6932012-07-11 10:26:13 -07001689 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001690 public boolean providerMeetsCriteria(String provider, Criteria criteria) {
1691 LocationProviderInterface p = mProvidersByName.get(provider);
1692 if (p == null) {
1693 throw new IllegalArgumentException("provider=" + provider);
1694 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001695
1696 boolean result = LocationProvider.propertiesMeetCriteria(
1697 p.getName(), p.getProperties(), criteria);
1698 if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result);
1699 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001700 }
1701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 private void updateProvidersLocked() {
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001703 boolean changesMade = false;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001704 for (int i = mProviders.size() - 1; i >= 0; i--) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001705 LocationProviderInterface p = mProviders.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001706 boolean isEnabled = p.isEnabled();
1707 String name = p.getName();
Victoria Lease09eeaec2013-02-05 11:34:13 -08001708 boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 if (isEnabled && !shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001710 updateProviderListenersLocked(name, false);
David Christieb084fef2013-12-18 14:33:57 -08001711 // If any provider has been disabled, clear all last locations for all providers.
1712 // This is to be on the safe side in case a provider has location derived from
1713 // this disabled provider.
1714 mLastLocation.clear();
1715 mLastLocationCoarseInterval.clear();
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001716 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001717 } else if (!isEnabled && shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001718 updateProviderListenersLocked(name, true);
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001719 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 }
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001721 }
1722 if (changesMade) {
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001723 mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
1724 UserHandle.ALL);
Tom O'Neill40a86c22013-09-03 18:05:13 -07001725 mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
1726 UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001727 }
1728 }
1729
Amith Yamasanib27528d2014-06-05 15:02:10 -07001730 private void updateProviderListenersLocked(String provider, boolean enabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731 int listeners = 0;
1732
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001733 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001734 if (p == null) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001735
1736 ArrayList<Receiver> deadReceivers = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07001737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1739 if (records != null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001740 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001741 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001742 // Sends a notification message to the receiver
1743 if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
1744 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001745 deadReceivers = new ArrayList<>();
Victoria Leaseb711d572012-10-02 13:14:11 -07001746 }
1747 deadReceivers.add(record.mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001748 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001749 listeners++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001750 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001751 }
1752 }
1753
1754 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001755 for (int i = deadReceivers.size() - 1; i >= 0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001756 removeUpdatesLocked(deadReceivers.get(i));
1757 }
1758 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001760 if (enabled) {
1761 p.enable();
Yu-Han Yanga4d250e2018-10-02 21:29:20 -07001762 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001763 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001764 p.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001766 }
1767
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001768 private void applyRequirementsLocked(String provider) {
1769 LocationProviderInterface p = mProvidersByName.get(provider);
1770 if (p == null) return;
1771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001773 WorkSource worksource = new WorkSource();
1774 ProviderRequest providerRequest = new ProviderRequest();
1775
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001776 ContentResolver resolver = mContext.getContentResolver();
1777 long backgroundThrottleInterval = Settings.Global.getLong(
1778 resolver,
1779 Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
1780 DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
gomo48f1a642017-11-10 20:35:46 -08001781 // initialize the low power mode to true and set to false if any of the records requires
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001782
gomo48f1a642017-11-10 20:35:46 -08001783 providerRequest.lowPowerMode = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 if (records != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001785 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001786 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
David Christieb870dbf2015-06-22 12:42:53 -07001787 if (checkLocationAccess(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001788 record.mReceiver.mIdentity.mPid,
1789 record.mReceiver.mIdentity.mUid,
1790 record.mReceiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001791 record.mReceiver.mAllowedResolutionLevel)) {
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001792 LocationRequest locationRequest = record.mRealRequest;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001793 long interval = locationRequest.getInterval();
1794
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001795 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001796 if (!record.mIsForegroundUid) {
1797 interval = Math.max(interval, backgroundThrottleInterval);
1798 }
1799 if (interval != locationRequest.getInterval()) {
1800 locationRequest = new LocationRequest(locationRequest);
1801 locationRequest.setInterval(interval);
1802 }
1803 }
1804
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001805 record.mRequest = locationRequest;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001806 providerRequest.locationRequests.add(locationRequest);
gomo48f1a642017-11-10 20:35:46 -08001807 if (!locationRequest.isLowPowerMode()) {
1808 providerRequest.lowPowerMode = false;
1809 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001810 if (interval < providerRequest.interval) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001811 providerRequest.reportLocation = true;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001812 providerRequest.interval = interval;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001813 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001814 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001815 }
1816 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001817
1818 if (providerRequest.reportLocation) {
1819 // calculate who to blame for power
1820 // This is somewhat arbitrary. We pick a threshold interval
1821 // that is slightly higher that the minimum interval, and
1822 // spread the blame across all applications with a request
1823 // under that threshold.
1824 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
1825 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001826 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001827 LocationRequest locationRequest = record.mRequest;
Svet Ganove998c732016-06-10 00:12:38 -07001828
1829 // Don't assign battery blame for update records whose
1830 // client has no permission to receive location data.
1831 if (!providerRequest.locationRequests.contains(locationRequest)) {
1832 continue;
1833 }
1834
Victoria Leaseb711d572012-10-02 13:14:11 -07001835 if (locationRequest.getInterval() <= thresholdInterval) {
David Christiee55c9682013-08-22 10:10:34 -07001836 if (record.mReceiver.mWorkSource != null
Narayan Kamath32684dd2018-01-08 17:32:51 +00001837 && isValidWorkSource(record.mReceiver.mWorkSource)) {
David Christie82edc9b2013-07-19 11:31:42 -07001838 worksource.add(record.mReceiver.mWorkSource);
1839 } else {
Narayan Kamath32684dd2018-01-08 17:32:51 +00001840 // Assign blame to caller if there's no WorkSource associated with
1841 // the request or if it's invalid.
David Christie82edc9b2013-07-19 11:31:42 -07001842 worksource.add(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001843 record.mReceiver.mIdentity.mUid,
1844 record.mReceiver.mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001845 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001846 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001847 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001848 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001849 }
1850 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001851
1852 if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
1853 p.setRequest(providerRequest, worksource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001854 }
1855
Narayan Kamath32684dd2018-01-08 17:32:51 +00001856 /**
1857 * Whether a given {@code WorkSource} associated with a Location request is valid.
1858 */
1859 private static boolean isValidWorkSource(WorkSource workSource) {
1860 if (workSource.size() > 0) {
1861 // If the WorkSource has one or more non-chained UIDs, make sure they're accompanied
1862 // by tags.
1863 return workSource.getName(0) != null;
1864 } else {
1865 // For now, make sure callers have supplied an attribution tag for use with
1866 // AppOpsManager. This might be relaxed in the future.
1867 final ArrayList<WorkChain> workChains = workSource.getWorkChains();
1868 return workChains != null && !workChains.isEmpty() &&
1869 workChains.get(0).getAttributionTag() != null;
1870 }
1871 }
1872
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001873 @Override
1874 public String[] getBackgroundThrottlingWhitelist() {
1875 synchronized (mLock) {
1876 return mBackgroundThrottlePackageWhitelist.toArray(
gomo48f1a642017-11-10 20:35:46 -08001877 new String[mBackgroundThrottlePackageWhitelist.size()]);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001878 }
1879 }
1880
1881 private void updateBackgroundThrottlingWhitelistLocked() {
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001882 String setting = Settings.Global.getString(
gomo48f1a642017-11-10 20:35:46 -08001883 mContext.getContentResolver(),
1884 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001885 if (setting == null) {
1886 setting = "";
1887 }
1888
1889 mBackgroundThrottlePackageWhitelist.clear();
1890 mBackgroundThrottlePackageWhitelist.addAll(
gomo48f1a642017-11-10 20:35:46 -08001891 SystemConfig.getInstance().getAllowUnthrottledLocation());
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001892 mBackgroundThrottlePackageWhitelist.addAll(
gomo48f1a642017-11-10 20:35:46 -08001893 Arrays.asList(setting.split(",")));
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001894 }
1895
Wei Wangdd070f22018-06-21 11:29:40 -07001896 private void updateLastLocationMaxAgeLocked() {
1897 mLastLocationMaxAgeMs =
1898 Settings.Global.getLong(
1899 mContext.getContentResolver(),
1900 Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
1901 DEFAULT_LAST_LOCATION_MAX_AGE_MS);
1902 }
1903
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001904 private boolean isThrottlingExemptLocked(Identity identity) {
1905 if (identity.mUid == Process.SYSTEM_UID) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001906 return true;
1907 }
1908
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001909 if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001910 return true;
1911 }
1912
1913 for (LocationProviderProxy provider : mProxyProviders) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001914 if (identity.mPackageName.equals(provider.getConnectedPackageName())) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001915 return true;
1916 }
1917 }
1918
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001919 return false;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001920 }
1921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001922 private class UpdateRecord {
1923 final String mProvider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001924 final LocationRequest mRealRequest; // original request from client
1925 LocationRequest mRequest; // possibly throttled version of the request
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001926 final Receiver mReceiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001927 boolean mIsForegroundUid;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001928 Location mLastFixBroadcast;
1929 long mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930
1931 /**
1932 * Note: must be constructed with lock held.
1933 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001934 UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001935 mProvider = provider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001936 mRealRequest = request;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001937 mRequest = request;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001938 mReceiver = receiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001939 mIsForegroundUid = isImportanceForeground(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001940 mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001941
1942 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1943 if (records == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001944 records = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001945 mRecordsByProvider.put(provider, records);
1946 }
1947 if (!records.contains(this)) {
1948 records.add(this);
1949 }
David Christie2ff96af2014-01-30 16:09:37 -08001950
1951 // Update statistics for historical location requests by package/provider
1952 mRequestStatistics.startRequesting(
Wyatt Rileyf7075e02018-04-12 17:54:26 -07001953 mReceiver.mIdentity.mPackageName, provider, request.getInterval(),
1954 mIsForegroundUid);
1955 }
1956
1957 /**
1958 * Method to be called when record changes foreground/background
1959 */
1960 void updateForeground(boolean isForeground){
1961 mIsForegroundUid = isForeground;
1962 mRequestStatistics.updateForeground(
1963 mReceiver.mIdentity.mPackageName, mProvider, isForeground);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001964 }
1965
1966 /**
David Christie2ff96af2014-01-30 16:09:37 -08001967 * Method to be called when a record will no longer be used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001968 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001969 void disposeLocked(boolean removeReceiver) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001970 mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider);
David Christie2ff96af2014-01-30 16:09:37 -08001971
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001972 // remove from mRecordsByProvider
1973 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
1974 if (globalRecords != null) {
1975 globalRecords.remove(this);
1976 }
1977
1978 if (!removeReceiver) return; // the caller will handle the rest
1979
1980 // remove from Receiver#mUpdateRecords
1981 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
1982 if (receiverRecords != null) {
1983 receiverRecords.remove(this.mProvider);
1984
1985 // and also remove the Receiver if it has no more update records
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001986 if (receiverRecords.size() == 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001987 removeUpdatesLocked(mReceiver);
1988 }
Mike Lockwood3a76fd62009-09-01 07:26:56 -04001989 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001990 }
1991
1992 @Override
1993 public String toString() {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001994 return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
gomo48f1a642017-11-10 20:35:46 -08001995 + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground"
1996 : " background")
Wyatt Riley19adc022018-05-22 13:30:51 -07001997 + ")" + " " + mRealRequest + " "
1998 + mReceiver.mWorkSource + "]";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001999 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002000 }
2001
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002002 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -07002003 String packageName, WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002004 IBinder binder = listener.asBinder();
2005 Receiver receiver = mReceivers.get(binder);
2006 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07002007 receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
2008 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002009 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002010 receiver.getListener().asBinder().linkToDeath(receiver, 0);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002011 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002012 Slog.e(TAG, "linkToDeath failed:", e);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002013 return null;
2014 }
Wen Jingcb3ab222014-03-27 13:42:59 +08002015 mReceivers.put(binder, receiver);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002016 }
2017 return receiver;
2018 }
2019
David Christie82edc9b2013-07-19 11:31:42 -07002020 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
David Christie40e57822013-07-30 11:36:48 -07002021 WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002022 Receiver receiver = mReceivers.get(intent);
2023 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07002024 receiver = new Receiver(null, intent, pid, uid, packageName, workSource,
2025 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002026 mReceivers.put(intent, receiver);
2027 }
2028 return receiver;
2029 }
2030
Victoria Lease37425c32012-10-16 16:08:48 -07002031 /**
2032 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
2033 * and consistency requirements.
2034 *
2035 * @param request the LocationRequest from which to create a sanitized version
Victoria Lease37425c32012-10-16 16:08:48 -07002036 * @return a version of request that meets the given resolution and consistency requirements
2037 * @hide
2038 */
gomo48f1a642017-11-10 20:35:46 -08002039 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel,
2040 boolean callerHasLocationHardwarePermission) {
Victoria Lease37425c32012-10-16 16:08:48 -07002041 LocationRequest sanitizedRequest = new LocationRequest(request);
gomo48f1a642017-11-10 20:35:46 -08002042 if (!callerHasLocationHardwarePermission) {
2043 // allow setting low power mode only for callers with location hardware permission
2044 sanitizedRequest.setLowPowerMode(false);
2045 }
Victoria Lease37425c32012-10-16 16:08:48 -07002046 if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
2047 switch (sanitizedRequest.getQuality()) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002048 case LocationRequest.ACCURACY_FINE:
Victoria Lease37425c32012-10-16 16:08:48 -07002049 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
Victoria Lease09016ab2012-09-16 12:33:15 -07002050 break;
2051 case LocationRequest.POWER_HIGH:
Victoria Lease37425c32012-10-16 16:08:48 -07002052 sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
Victoria Lease09016ab2012-09-16 12:33:15 -07002053 break;
2054 }
2055 // throttle
Victoria Lease37425c32012-10-16 16:08:48 -07002056 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
2057 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07002058 }
Victoria Lease37425c32012-10-16 16:08:48 -07002059 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
2060 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07002061 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07002062 }
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002063 // make getFastestInterval() the minimum of interval and fastest interval
Victoria Lease37425c32012-10-16 16:08:48 -07002064 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002065 request.setFastestInterval(request.getInterval());
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002066 }
Victoria Lease37425c32012-10-16 16:08:48 -07002067 return sanitizedRequest;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002068 }
2069
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002070 private void checkPackageName(String packageName) {
Nick Pellye0fd6932012-07-11 10:26:13 -07002071 if (packageName == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002072 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002073 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002074 int uid = Binder.getCallingUid();
Nick Pellye0fd6932012-07-11 10:26:13 -07002075 String[] packages = mPackageManager.getPackagesForUid(uid);
2076 if (packages == null) {
2077 throw new SecurityException("invalid UID " + uid);
2078 }
2079 for (String pkg : packages) {
2080 if (packageName.equals(pkg)) return;
2081 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002082 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002083 }
2084
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002085 private void checkPendingIntent(PendingIntent intent) {
2086 if (intent == null) {
2087 throw new IllegalArgumentException("invalid pending intent: " + intent);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002088 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002089 }
2090
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002091 private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent,
David Christie40e57822013-07-30 11:36:48 -07002092 int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002093 if (intent == null && listener == null) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002094 throw new IllegalArgumentException("need either listener or intent");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002095 } else if (intent != null && listener != null) {
2096 throw new IllegalArgumentException("cannot register both listener and intent");
2097 } else if (intent != null) {
2098 checkPendingIntent(intent);
David Christie40e57822013-07-30 11:36:48 -07002099 return getReceiverLocked(intent, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002100 } else {
David Christie40e57822013-07-30 11:36:48 -07002101 return getReceiverLocked(listener, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002102 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002103 }
2104
Nick Pellye0fd6932012-07-11 10:26:13 -07002105 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002106 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
2107 PendingIntent intent, String packageName) {
2108 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2109 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002110 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2111 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2112 request.getProvider());
David Christie82edc9b2013-07-19 11:31:42 -07002113 WorkSource workSource = request.getWorkSource();
Narayan Kamath32684dd2018-01-08 17:32:51 +00002114 if (workSource != null && !workSource.isEmpty()) {
David Christie40e57822013-07-30 11:36:48 -07002115 checkDeviceStatsAllowed();
2116 }
2117 boolean hideFromAppOps = request.getHideFromAppOps();
2118 if (hideFromAppOps) {
2119 checkUpdateAppOpsAllowed();
David Christie82edc9b2013-07-19 11:31:42 -07002120 }
gomo48f1a642017-11-10 20:35:46 -08002121 boolean callerHasLocationHardwarePermission =
2122 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
Maggieaa080f92018-01-04 15:35:11 -08002123 == PERMISSION_GRANTED;
gomo48f1a642017-11-10 20:35:46 -08002124 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel,
2125 callerHasLocationHardwarePermission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002126
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002127 final int pid = Binder.getCallingPid();
2128 final int uid = Binder.getCallingUid();
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002129 // providers may use public location API's, need to clear identity
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002130 long identity = Binder.clearCallingIdentity();
2131 try {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002132 // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2133 // a location.
David Christieb870dbf2015-06-22 12:42:53 -07002134 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002135
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002136 synchronized (mLock) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002137 Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
David Christie40e57822013-07-30 11:36:48 -07002138 packageName, workSource, hideFromAppOps);
Victoria Lease37425c32012-10-16 16:08:48 -07002139 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
Mike Lockwood2d4d1bf2010-10-18 17:06:26 -04002140 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002141 } finally {
2142 Binder.restoreCallingIdentity(identity);
2143 }
2144 }
2145
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002146 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
2147 int pid, int uid, String packageName) {
2148 // Figure out the provider. Either its explicitly request (legacy use cases), or
2149 // use the fused provider
2150 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2151 String name = request.getProvider();
Victoria Lease09016ab2012-09-16 12:33:15 -07002152 if (name == null) {
2153 throw new IllegalArgumentException("provider name must not be null");
2154 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -07002155
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002156 LocationProviderInterface provider = mProvidersByName.get(name);
2157 if (provider == null) {
Victoria Leaseb30f3832013-10-13 12:15:40 -07002158 throw new IllegalArgumentException("provider doesn't exist: " + name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002159 }
2160
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002161 UpdateRecord record = new UpdateRecord(name, request, receiver);
gomo48f1a642017-11-10 20:35:46 -08002162 if (D) {
2163 Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
2164 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
2165 + (record.mIsForegroundUid ? "foreground" : "background")
2166 + (isThrottlingExemptLocked(receiver.mIdentity)
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002167 ? " [whitelisted]" : "") + ")");
gomo48f1a642017-11-10 20:35:46 -08002168 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002169
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002170 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
2171 if (oldRecord != null) {
2172 oldRecord.disposeLocked(false);
2173 }
2174
Maggie2a9409e2018-03-21 11:47:28 -07002175 boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid, mCurrentUserId);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002176 if (isProviderEnabled) {
2177 applyRequirementsLocked(name);
2178 } else {
2179 // Notify the listener that updates are currently disabled
2180 receiver.callProviderEnabledLocked(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002181 }
David Christie0b837452013-07-29 16:02:13 -07002182 // Update the monitoring here just in case multiple location requests were added to the
2183 // same receiver (this request may be high power and the initial might not have been).
2184 receiver.updateMonitoring(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002185 }
2186
Nick Pellye0fd6932012-07-11 10:26:13 -07002187 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002188 public void removeUpdates(ILocationListener listener, PendingIntent intent,
2189 String packageName) {
2190 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002191
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002192 final int pid = Binder.getCallingPid();
2193 final int uid = Binder.getCallingUid();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002194
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002195 synchronized (mLock) {
David Christie82edc9b2013-07-19 11:31:42 -07002196 WorkSource workSource = null;
David Christie40e57822013-07-30 11:36:48 -07002197 boolean hideFromAppOps = false;
2198 Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid,
2199 packageName, workSource, hideFromAppOps);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002200
2201 // providers may use public location API's, need to clear identity
2202 long identity = Binder.clearCallingIdentity();
2203 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002204 removeUpdatesLocked(receiver);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002205 } finally {
2206 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002207 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002208 }
2209 }
2210
2211 private void removeUpdatesLocked(Receiver receiver) {
Dianne Hackborn7ff30112012-11-08 11:12:09 -08002212 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002213
2214 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
2215 receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
2216 synchronized (receiver) {
Victoria Lease0aa28602013-05-29 15:28:26 -07002217 receiver.clearPendingBroadcastsLocked();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002218 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002219 }
2220
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07002221 receiver.updateMonitoring(false);
2222
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002223 // Record which providers were associated with this listener
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002224 HashSet<String> providers = new HashSet<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002225 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2226 if (oldRecords != null) {
2227 // Call dispose() on the obsolete update records.
2228 for (UpdateRecord record : oldRecords.values()) {
David Christie2ff96af2014-01-30 16:09:37 -08002229 // Update statistics for historical location requests by package/provider
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002230 record.disposeLocked(false);
2231 }
2232 // Accumulate providers
2233 providers.addAll(oldRecords.keySet());
2234 }
2235
2236 // update provider
2237 for (String provider : providers) {
2238 // If provider is already disabled, don't need to do anything
Victoria Lease09eeaec2013-02-05 11:34:13 -08002239 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002240 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002241 }
2242
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002243 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002244 }
2245 }
2246
Dianne Hackbornc2293022013-02-06 23:14:49 -08002247 private void applyAllProviderRequirementsLocked() {
2248 for (LocationProviderInterface p : mProviders) {
2249 // If provider is already disabled, don't need to do anything
Dianne Hackborn64d41d72013-02-07 00:33:31 -08002250 if (!isAllowedByCurrentUserSettingsLocked(p.getName())) {
Dianne Hackbornc2293022013-02-06 23:14:49 -08002251 continue;
2252 }
2253
2254 applyRequirementsLocked(p.getName());
2255 }
2256 }
2257
Nick Pellye0fd6932012-07-11 10:26:13 -07002258 @Override
Nick Pelly4035f5a2012-08-17 14:43:49 -07002259 public Location getLastLocation(LocationRequest request, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002260 if (D) Log.d(TAG, "getLastLocation: " + request);
2261 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002262 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly4035f5a2012-08-17 14:43:49 -07002263 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002264 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2265 request.getProvider());
2266 // no need to sanitize this request, as only the provider name is used
Nick Pelly4035f5a2012-08-17 14:43:49 -07002267
David Christieb870dbf2015-06-22 12:42:53 -07002268 final int pid = Binder.getCallingPid();
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002269 final int uid = Binder.getCallingUid();
2270 final long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07002271 try {
2272 if (mBlacklist.isBlacklisted(packageName)) {
gomo48f1a642017-11-10 20:35:46 -08002273 if (D) {
2274 Log.d(TAG, "not returning last loc for blacklisted app: " +
2275 packageName);
2276 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002277 return null;
2278 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002279
David Christieb870dbf2015-06-22 12:42:53 -07002280 if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel)) {
gomo48f1a642017-11-10 20:35:46 -08002281 if (D) {
2282 Log.d(TAG, "not returning last loc for no op app: " +
2283 packageName);
2284 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002285 return null;
2286 }
2287
Victoria Leaseb711d572012-10-02 13:14:11 -07002288 synchronized (mLock) {
2289 // Figure out the provider. Either its explicitly request (deprecated API's),
2290 // or use the fused provider
2291 String name = request.getProvider();
2292 if (name == null) name = LocationManager.FUSED_PROVIDER;
2293 LocationProviderInterface provider = mProvidersByName.get(name);
2294 if (provider == null) return null;
2295
Maggie2a9409e2018-03-21 11:47:28 -07002296 if (!isAllowedByUserSettingsLocked(name, uid, mCurrentUserId)) return null;
Victoria Leaseb711d572012-10-02 13:14:11 -07002297
David Christie1b9b7b12013-04-15 15:31:11 -07002298 Location location;
2299 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2300 // Make sure that an app with coarse permissions can't get frequent location
2301 // updates by calling LocationManager.getLastKnownLocation repeatedly.
2302 location = mLastLocationCoarseInterval.get(name);
2303 } else {
2304 location = mLastLocation.get(name);
2305 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002306 if (location == null) {
2307 return null;
2308 }
Wei Wangdd070f22018-06-21 11:29:40 -07002309
2310 // Don't return stale location to apps with foreground-only location permission.
Wei Wangb86334f2018-07-03 16:33:24 -07002311 String op = resolutionLevelToOpStr(allowedResolutionLevel);
Wei Wangdd070f22018-06-21 11:29:40 -07002312 long locationAgeMs = SystemClock.elapsedRealtime() -
2313 location.getElapsedRealtimeNanos() / NANOS_PER_MILLI;
2314 if ((locationAgeMs > mLastLocationMaxAgeMs)
2315 && (mAppOps.unsafeCheckOp(op, uid, packageName)
2316 == AppOpsManager.MODE_FOREGROUND)) {
2317 return null;
2318 }
2319
Victoria Lease37425c32012-10-16 16:08:48 -07002320 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
gomo48f1a642017-11-10 20:35:46 -08002321 Location noGPSLocation = location.getExtraLocation(
2322 Location.EXTRA_NO_GPS_LOCATION);
Victoria Leaseb711d572012-10-02 13:14:11 -07002323 if (noGPSLocation != null) {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002324 return new Location(mLocationFudger.getOrCreate(noGPSLocation));
Victoria Leaseb711d572012-10-02 13:14:11 -07002325 }
Victoria Lease37425c32012-10-16 16:08:48 -07002326 } else {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002327 return new Location(location);
Victoria Lease09016ab2012-09-16 12:33:15 -07002328 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002329 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002330 return null;
2331 } finally {
2332 Binder.restoreCallingIdentity(identity);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002333 }
2334 }
2335
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002336 /**
2337 * Provides an interface to inject and set the last location if location is not available
2338 * currently.
2339 *
2340 * This helps in cases where the product (Cars for example) has saved the last known location
2341 * before powering off. This interface lets the client inject the saved location while the GPS
2342 * chipset is getting its first fix, there by improving user experience.
2343 *
2344 * @param location - Location object to inject
2345 * @return true if update was successful, false if not
2346 */
2347 @Override
2348 public boolean injectLocation(Location location) {
2349 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
2350 "Location Hardware permission not granted to inject location");
2351 mContext.enforceCallingPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
2352 "Access Fine Location permission not granted to inject Location");
2353
2354 if (location == null) {
2355 if (D) {
2356 Log.d(TAG, "injectLocation(): called with null location");
2357 }
2358 return false;
2359 }
2360 LocationProviderInterface p = null;
2361 String provider = location.getProvider();
2362 if (provider != null) {
2363 p = mProvidersByName.get(provider);
2364 }
2365 if (p == null) {
2366 if (D) {
2367 Log.d(TAG, "injectLocation(): unknown provider");
2368 }
2369 return false;
2370 }
2371 synchronized (mLock) {
2372 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
2373 if (D) {
2374 Log.d(TAG, "Location disabled in Settings for current user:" + mCurrentUserId);
2375 }
2376 return false;
2377 } else {
2378 // NOTE: If last location is already available, location is not injected. If
2379 // provider's normal source (like a GPS chipset) have already provided an output,
2380 // there is no need to inject this location.
2381 if (mLastLocation.get(provider) == null) {
2382 updateLastLocationLocked(location, provider);
2383 } else {
2384 if (D) {
2385 Log.d(TAG, "injectLocation(): Location exists. Not updating");
2386 }
2387 return false;
2388 }
2389 }
2390 }
2391 return true;
2392 }
2393
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002394 @Override
2395 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
2396 String packageName) {
2397 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002398 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2399 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002400 checkPendingIntent(intent);
2401 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002402 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2403 request.getProvider());
gomo48f1a642017-11-10 20:35:46 -08002404 // Require that caller can manage given document
2405 boolean callerHasLocationHardwarePermission =
2406 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
Maggieaa080f92018-01-04 15:35:11 -08002407 == PERMISSION_GRANTED;
gomo48f1a642017-11-10 20:35:46 -08002408 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel,
2409 callerHasLocationHardwarePermission);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002410
Victoria Lease37425c32012-10-16 16:08:48 -07002411 if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002412
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002413 // geo-fence manager uses the public location API, need to clear identity
2414 int uid = Binder.getCallingUid();
Xiaohui Chena4490622015-09-22 15:29:31 -07002415 // TODO: http://b/23822629
2416 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
Victoria Lease56e675b2012-11-05 19:25:06 -08002417 // temporary measure until geofences work for secondary users
2418 Log.w(TAG, "proximity alerts are currently available only to the primary user");
2419 return;
2420 }
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002421 long identity = Binder.clearCallingIdentity();
2422 try {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002423 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
2424 uid, packageName);
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002425 } finally {
2426 Binder.restoreCallingIdentity(identity);
2427 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002428 }
2429
2430 @Override
2431 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002432 checkPendingIntent(intent);
2433 checkPackageName(packageName);
2434
2435 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2436
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002437 // geo-fence manager uses the public location API, need to clear identity
2438 long identity = Binder.clearCallingIdentity();
2439 try {
2440 mGeofenceManager.removeFence(geofence, intent);
2441 } finally {
2442 Binder.restoreCallingIdentity(identity);
2443 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002444 }
2445
2446
2447 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002448 public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002449 if (!hasGnssPermissions(packageName) || mGnssStatusProvider == null) {
Takayuki Hoshib254ab6a2014-10-23 16:46:02 +09002450 return false;
2451 }
2452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002453 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002454 mGnssStatusProvider.registerGnssStatusCallback(callback);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002455 } catch (RemoteException e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002456 Slog.e(TAG, "mGpsStatusProvider.registerGnssStatusCallback failed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002457 return false;
2458 }
2459 return true;
2460 }
2461
Nick Pellye0fd6932012-07-11 10:26:13 -07002462 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002463 public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002464 synchronized (mLock) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002465 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002466 mGnssStatusProvider.unregisterGnssStatusCallback(callback);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002467 } catch (Exception e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002468 Slog.e(TAG, "mGpsStatusProvider.unregisterGnssStatusCallback failed", e);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002469 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002470 }
2471 }
2472
Nick Pellye0fd6932012-07-11 10:26:13 -07002473 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002474 public boolean addGnssMeasurementsListener(
gomo48f1a642017-11-10 20:35:46 -08002475 IGnssMeasurementsListener listener, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002476 if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
destradaaea8a8a62014-06-23 18:19:03 -07002477 return false;
2478 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002479
2480 synchronized (mLock) {
2481 Identity callerIdentity
2482 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
Wyatt Riley11cc7492018-01-17 08:48:27 -08002483 mGnssMeasurementsListeners.put(listener.asBinder(), callerIdentity);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002484 long identity = Binder.clearCallingIdentity();
2485 try {
2486 if (isThrottlingExemptLocked(callerIdentity)
2487 || isImportanceForeground(
gomo48f1a642017-11-10 20:35:46 -08002488 mActivityManager.getPackageImportance(packageName))) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002489 return mGnssMeasurementsProvider.addListener(listener);
2490 }
2491 } finally {
2492 Binder.restoreCallingIdentity(identity);
2493 }
2494
2495 return true;
2496 }
destradaaea8a8a62014-06-23 18:19:03 -07002497 }
2498
2499 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002500 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
2501 if (mGnssMeasurementsProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002502 synchronized (mLock) {
Wyatt Riley11cc7492018-01-17 08:48:27 -08002503 mGnssMeasurementsListeners.remove(listener.asBinder());
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002504 mGnssMeasurementsProvider.removeListener(listener);
2505 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002506 }
destradaaea8a8a62014-06-23 18:19:03 -07002507 }
2508
2509 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002510 public boolean addGnssNavigationMessageListener(
2511 IGnssNavigationMessageListener listener,
destradaa4b3e3932014-07-21 18:01:47 -07002512 String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002513 if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) {
destradaa4b3e3932014-07-21 18:01:47 -07002514 return false;
2515 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002516
2517 synchronized (mLock) {
2518 Identity callerIdentity
gomo48f1a642017-11-10 20:35:46 -08002519 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
Wyatt Riley11cc7492018-01-17 08:48:27 -08002520 mGnssNavigationMessageListeners.put(listener.asBinder(), callerIdentity);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002521 long identity = Binder.clearCallingIdentity();
2522 try {
2523 if (isThrottlingExemptLocked(callerIdentity)
2524 || isImportanceForeground(
gomo48f1a642017-11-10 20:35:46 -08002525 mActivityManager.getPackageImportance(packageName))) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002526 return mGnssNavigationMessageProvider.addListener(listener);
2527 }
2528 } finally {
2529 Binder.restoreCallingIdentity(identity);
2530 }
2531
2532 return true;
2533 }
destradaa4b3e3932014-07-21 18:01:47 -07002534 }
2535
2536 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002537 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
2538 if (mGnssNavigationMessageProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002539 synchronized (mLock) {
Wyatt Riley11cc7492018-01-17 08:48:27 -08002540 mGnssNavigationMessageListeners.remove(listener.asBinder());
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002541 mGnssNavigationMessageProvider.removeListener(listener);
2542 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002543 }
destradaa4b3e3932014-07-21 18:01:47 -07002544 }
2545
2546 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002547 public boolean sendExtraCommand(String provider, String command, Bundle extras) {
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002548 if (provider == null) {
2549 // throw NullPointerException to remain compatible with previous implementation
2550 throw new NullPointerException();
2551 }
Victoria Lease37425c32012-10-16 16:08:48 -07002552 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2553 provider);
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002554
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002555 // and check for ACCESS_LOCATION_EXTRA_COMMANDS
Mike Lockwoodb7e99222009-07-07 13:18:21 -04002556 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
Maggieaa080f92018-01-04 15:35:11 -08002557 != PERMISSION_GRANTED)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002558 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
2559 }
2560
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002561 synchronized (mLock) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002562 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002563 if (p == null) return false;
Nick Pellye0fd6932012-07-11 10:26:13 -07002564
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002565 return p.sendExtraCommand(command, extras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002566 }
2567 }
2568
Nick Pellye0fd6932012-07-11 10:26:13 -07002569 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002570 public boolean sendNiResponse(int notifId, int userResponse) {
Mike Lockwood18ad9f62009-08-27 14:01:23 -07002571 if (Binder.getCallingUid() != Process.myUid()) {
2572 throw new SecurityException(
2573 "calling sendNiResponse from outside of the system is not allowed");
2574 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002575 try {
2576 return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002577 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002578 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
Danke Xie22d1f9f2009-08-18 18:28:45 -04002579 return false;
2580 }
2581 }
2582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002583 /**
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002584 * @return null if the provider does not exist
Alexey Tarasovf2db9fb2009-09-01 02:37:07 +11002585 * @throws SecurityException if the provider is not allowed to be
gomo48f1a642017-11-10 20:35:46 -08002586 * accessed by the caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002587 */
Nick Pellye0fd6932012-07-11 10:26:13 -07002588 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002589 public ProviderProperties getProviderProperties(String provider) {
Laurent Tub7f9d252012-10-16 14:25:00 -07002590 if (mProvidersByName.get(provider) == null) {
David Christie2ff96af2014-01-30 16:09:37 -08002591 return null;
Laurent Tub7f9d252012-10-16 14:25:00 -07002592 }
2593
Victoria Lease37425c32012-10-16 16:08:48 -07002594 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2595 provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002596
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002597 LocationProviderInterface p;
2598 synchronized (mLock) {
2599 p = mProvidersByName.get(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600 }
2601
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002602 if (p == null) return null;
2603 return p.getProperties();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002604 }
2605
Jason Monkb71218a2015-06-17 14:44:39 -04002606 /**
2607 * @return null if the provider does not exist
2608 * @throws SecurityException if the provider is not allowed to be
gomo48f1a642017-11-10 20:35:46 -08002609 * accessed by the caller
Jason Monkb71218a2015-06-17 14:44:39 -04002610 */
2611 @Override
2612 public String getNetworkProviderPackage() {
2613 LocationProviderInterface p;
2614 synchronized (mLock) {
2615 if (mProvidersByName.get(LocationManager.NETWORK_PROVIDER) == null) {
2616 return null;
2617 }
2618 p = mProvidersByName.get(LocationManager.NETWORK_PROVIDER);
2619 }
2620
2621 if (p instanceof LocationProviderProxy) {
2622 return ((LocationProviderProxy) p).getConnectedPackageName();
2623 }
2624 return null;
2625 }
2626
Maggieaa080f92018-01-04 15:35:11 -08002627 /**
Maggie2a9409e2018-03-21 11:47:28 -07002628 * Returns the current location enabled/disabled status for a user
2629 *
2630 * @param userId the id of the user
2631 * @return true if location is enabled
2632 */
2633 @Override
2634 public boolean isLocationEnabledForUser(int userId) {
2635 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2636 checkInteractAcrossUsersPermission(userId);
2637
2638 long identity = Binder.clearCallingIdentity();
2639 try {
2640 synchronized (mLock) {
2641 final String allowedProviders = Settings.Secure.getStringForUser(
2642 mContext.getContentResolver(),
2643 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
2644 userId);
2645 if (allowedProviders == null) {
2646 return false;
2647 }
2648 final List<String> providerList = Arrays.asList(allowedProviders.split(","));
2649 for(String provider : mRealProviders.keySet()) {
2650 if (provider.equals(LocationManager.PASSIVE_PROVIDER)
2651 || provider.equals(LocationManager.FUSED_PROVIDER)) {
2652 continue;
2653 }
2654 if (providerList.contains(provider)) {
2655 return true;
2656 }
2657 }
2658 return false;
2659 }
2660 } finally {
2661 Binder.restoreCallingIdentity(identity);
2662 }
2663 }
2664
2665 /**
2666 * Enable or disable location for a user
2667 *
2668 * @param enabled true to enable location, false to disable location
2669 * @param userId the id of the user
2670 */
2671 @Override
2672 public void setLocationEnabledForUser(boolean enabled, int userId) {
2673 mContext.enforceCallingPermission(
2674 android.Manifest.permission.WRITE_SECURE_SETTINGS,
2675 "Requires WRITE_SECURE_SETTINGS permission");
2676
2677 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2678 checkInteractAcrossUsersPermission(userId);
2679
2680 long identity = Binder.clearCallingIdentity();
2681 try {
2682 synchronized (mLock) {
2683 final Set<String> allRealProviders = mRealProviders.keySet();
2684 // Update all providers on device plus gps and network provider when disabling
2685 // location
2686 Set<String> allProvidersSet = new ArraySet<>(allRealProviders.size() + 2);
2687 allProvidersSet.addAll(allRealProviders);
2688 // When disabling location, disable gps and network provider that could have been
2689 // enabled by location mode api.
2690 if (enabled == false) {
2691 allProvidersSet.add(LocationManager.GPS_PROVIDER);
2692 allProvidersSet.add(LocationManager.NETWORK_PROVIDER);
2693 }
2694 if (allProvidersSet.isEmpty()) {
2695 return;
2696 }
2697 // to ensure thread safety, we write the provider name with a '+' or '-'
2698 // and let the SettingsProvider handle it rather than reading and modifying
2699 // the list of enabled providers.
2700 final String prefix = enabled ? "+" : "-";
2701 StringBuilder locationProvidersAllowed = new StringBuilder();
2702 for (String provider : allProvidersSet) {
2703 if (provider.equals(LocationManager.PASSIVE_PROVIDER)
2704 || provider.equals(LocationManager.FUSED_PROVIDER)) {
2705 continue;
2706 }
2707 locationProvidersAllowed.append(prefix);
2708 locationProvidersAllowed.append(provider);
2709 locationProvidersAllowed.append(",");
2710 }
2711 // Remove the trailing comma
2712 locationProvidersAllowed.setLength(locationProvidersAllowed.length() - 1);
2713 Settings.Secure.putStringForUser(
2714 mContext.getContentResolver(),
2715 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
2716 locationProvidersAllowed.toString(),
2717 userId);
2718 }
2719 } finally {
2720 Binder.restoreCallingIdentity(identity);
2721 }
2722 }
2723
2724 /**
2725 * Returns the current enabled/disabled status of a location provider and user
2726 *
2727 * @param provider name of the provider
2728 * @param userId the id of the user
2729 * @return true if the provider exists and is enabled
2730 */
2731 @Override
2732 public boolean isProviderEnabledForUser(String provider, int userId) {
2733 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2734 checkInteractAcrossUsersPermission(userId);
2735
2736 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2737 // so we discourage its use
2738 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
2739
2740 int uid = Binder.getCallingUid();
2741 synchronized (mLock) {
2742 LocationProviderInterface p = mProvidersByName.get(provider);
2743 return p != null
2744 && isAllowedByUserSettingsLocked(provider, uid, userId);
2745 }
2746 }
2747
2748 /**
2749 * Enable or disable a single location provider.
2750 *
2751 * @param provider name of the provider
2752 * @param enabled true to enable the provider. False to disable the provider
2753 * @param userId the id of the user to set
2754 * @return true if the value was set, false on errors
2755 */
2756 @Override
2757 public boolean setProviderEnabledForUser(String provider, boolean enabled, int userId) {
2758 mContext.enforceCallingPermission(
2759 android.Manifest.permission.WRITE_SECURE_SETTINGS,
2760 "Requires WRITE_SECURE_SETTINGS permission");
2761
2762 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2763 checkInteractAcrossUsersPermission(userId);
2764
2765 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2766 // so we discourage its use
2767 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
2768
2769 long identity = Binder.clearCallingIdentity();
2770 try {
2771 synchronized (mLock) {
2772 // No such provider exists
2773 if (!mProvidersByName.containsKey(provider)) return false;
2774
2775 // If it is a test provider, do not write to Settings.Secure
2776 if (mMockProviders.containsKey(provider)) {
2777 setTestProviderEnabled(provider, enabled);
2778 return true;
2779 }
2780
2781 // to ensure thread safety, we write the provider name with a '+' or '-'
2782 // and let the SettingsProvider handle it rather than reading and modifying
2783 // the list of enabled providers.
2784 String providerChange = (enabled ? "+" : "-") + provider;
2785 return Settings.Secure.putStringForUser(
2786 mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
2787 providerChange, userId);
2788 }
2789 } finally {
2790 Binder.restoreCallingIdentity(identity);
2791 }
2792 }
2793
2794 /**
Maggieaa080f92018-01-04 15:35:11 -08002795 * Read location provider status from Settings.Secure
2796 *
2797 * @param provider the location provider to query
2798 * @param userId the user id to query
2799 * @return true if the provider is enabled
2800 */
2801 private boolean isLocationProviderEnabledForUser(String provider, int userId) {
2802 long identity = Binder.clearCallingIdentity();
2803 try {
2804 // Use system settings
2805 ContentResolver cr = mContext.getContentResolver();
2806 String allowedProviders = Settings.Secure.getStringForUser(
2807 cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userId);
2808 return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
2809 } finally {
2810 Binder.restoreCallingIdentity(identity);
2811 }
2812 }
2813
2814 /**
Maggie2a9409e2018-03-21 11:47:28 -07002815 * Method for checking INTERACT_ACROSS_USERS permission if specified user id is not the same as
2816 * current user id
2817 *
2818 * @param userId the user id to get or set value
2819 */
2820 private void checkInteractAcrossUsersPermission(int userId) {
2821 int uid = Binder.getCallingUid();
2822 if (UserHandle.getUserId(uid) != userId) {
2823 if (ActivityManager.checkComponentPermission(
2824 android.Manifest.permission.INTERACT_ACROSS_USERS, uid, -1, true)
2825 != PERMISSION_GRANTED) {
2826 throw new SecurityException("Requires INTERACT_ACROSS_USERS permission");
2827 }
2828 }
2829 }
2830
2831 /**
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002832 * Returns "true" if the UID belongs to a bound location provider.
2833 *
2834 * @param uid the uid
2835 * @return true if uid belongs to a bound location provider
2836 */
2837 private boolean isUidALocationProvider(int uid) {
2838 if (uid == Process.SYSTEM_UID) {
2839 return true;
2840 }
2841 if (mGeocodeProvider != null) {
David Christie1f141c12014-05-14 15:11:15 -07002842 if (doesUidHavePackage(uid, mGeocodeProvider.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002843 }
2844 for (LocationProviderProxy proxy : mProxyProviders) {
David Christie1f141c12014-05-14 15:11:15 -07002845 if (doesUidHavePackage(uid, proxy.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002846 }
2847 return false;
2848 }
2849
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002850 private void checkCallerIsProvider() {
2851 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
Maggieaa080f92018-01-04 15:35:11 -08002852 == PERMISSION_GRANTED) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002853 return;
2854 }
2855
2856 // Previously we only used the INSTALL_LOCATION_PROVIDER
2857 // check. But that is system or signature
2858 // protection level which is not flexible enough for
2859 // providers installed oustide the system image. So
2860 // also allow providers with a UID matching the
2861 // currently bound package name
2862
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002863 if (isUidALocationProvider(Binder.getCallingUid())) {
2864 return;
2865 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002866
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002867 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
2868 "or UID of a currently bound location provider");
2869 }
2870
David Christie1f141c12014-05-14 15:11:15 -07002871 /**
2872 * Returns true if the given package belongs to the given uid.
2873 */
2874 private boolean doesUidHavePackage(int uid, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002875 if (packageName == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002876 return false;
2877 }
David Christie1f141c12014-05-14 15:11:15 -07002878 String[] packageNames = mPackageManager.getPackagesForUid(uid);
2879 if (packageNames == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002880 return false;
2881 }
David Christie1f141c12014-05-14 15:11:15 -07002882 for (String name : packageNames) {
2883 if (packageName.equals(name)) {
2884 return true;
2885 }
2886 }
2887 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002888 }
2889
Nick Pellye0fd6932012-07-11 10:26:13 -07002890 @Override
Mike Lockwooda4903f22010-02-17 06:42:23 -05002891 public void reportLocation(Location location, boolean passive) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002892 checkCallerIsProvider();
Mike Lockwood275555c2009-05-01 11:30:34 -04002893
Nick Pelly2eeeec22012-07-18 13:13:37 -07002894 if (!location.isComplete()) {
2895 Log.w(TAG, "Dropping incomplete location: " + location);
2896 return;
2897 }
2898
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002899 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location);
2900 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location);
Mike Lockwooda4903f22010-02-17 06:42:23 -05002901 m.arg1 = (passive ? 1 : 0);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002902 mLocationHandler.sendMessageAtFrontOfQueue(m);
2903 }
2904
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002905
Laurent Tu75defb62012-11-01 16:21:52 -07002906 private static boolean shouldBroadcastSafe(
2907 Location loc, Location lastLoc, UpdateRecord record, long now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002908 // Always broadcast the first update
2909 if (lastLoc == null) {
2910 return true;
2911 }
2912
Nick Pellyf1be6862012-05-15 10:53:42 -07002913 // Check whether sufficient time has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002914 long minTime = record.mRealRequest.getFastestInterval();
David Christie1b9b7b12013-04-15 15:31:11 -07002915 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
2916 / NANOS_PER_MILLI;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002917 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002918 return false;
2919 }
2920
2921 // Check whether sufficient distance has been traveled
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002922 double minDistance = record.mRealRequest.getSmallestDisplacement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002923 if (minDistance > 0.0) {
2924 if (loc.distanceTo(lastLoc) <= minDistance) {
2925 return false;
2926 }
2927 }
2928
Laurent Tu75defb62012-11-01 16:21:52 -07002929 // Check whether sufficient number of udpates is left
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002930 if (record.mRealRequest.getNumUpdates() <= 0) {
Laurent Tu75defb62012-11-01 16:21:52 -07002931 return false;
2932 }
2933
2934 // Check whether the expiry date has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002935 return record.mRealRequest.getExpireAt() >= now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002936 }
2937
Mike Lockwooda4903f22010-02-17 06:42:23 -05002938 private void handleLocationChangedLocked(Location location, boolean passive) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002939 if (D) Log.d(TAG, "incoming location: " + location);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002940 long now = SystemClock.elapsedRealtime();
Mike Lockwooda4903f22010-02-17 06:42:23 -05002941 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
Laurent Tu60ec50a2012-10-04 17:00:10 -07002942 // Skip if the provider is unknown.
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002943 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002944 if (p == null) return;
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002945 updateLastLocationLocked(location, provider);
2946 // mLastLocation should have been updated from the updateLastLocationLocked call above.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002947 Location lastLocation = mLastLocation.get(provider);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002948 if (lastLocation == null) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002949 Log.e(TAG, "handleLocationChangedLocked() updateLastLocation failed");
2950 return;
Mike Lockwood4e50b782009-04-03 08:24:43 -07002951 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002952
David Christie1b9b7b12013-04-15 15:31:11 -07002953 // Update last known coarse interval location if enough time has passed.
2954 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider);
2955 if (lastLocationCoarseInterval == null) {
2956 lastLocationCoarseInterval = new Location(location);
2957 mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval);
2958 }
2959 long timeDiffNanos = location.getElapsedRealtimeNanos()
2960 - lastLocationCoarseInterval.getElapsedRealtimeNanos();
2961 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
2962 lastLocationCoarseInterval.set(location);
2963 }
2964 // Don't ever return a coarse location that is more recent than the allowed update
2965 // interval (i.e. don't allow an app to keep registering and unregistering for
2966 // location updates to overcome the minimum interval).
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002967 Location noGPSLocation =
David Christie1b9b7b12013-04-15 15:31:11 -07002968 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2969
Laurent Tu60ec50a2012-10-04 17:00:10 -07002970 // Skip if there are no UpdateRecords for this provider.
2971 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
2972 if (records == null || records.size() == 0) return;
2973
Victoria Lease09016ab2012-09-16 12:33:15 -07002974 // Fetch coarse location
2975 Location coarseLocation = null;
David Christie1b9b7b12013-04-15 15:31:11 -07002976 if (noGPSLocation != null) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002977 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
2978 }
2979
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002980 // Fetch latest status update time
2981 long newStatusUpdateTime = p.getStatusUpdateTime();
2982
David Christie2ff96af2014-01-30 16:09:37 -08002983 // Get latest status
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002984 Bundle extras = new Bundle();
2985 int status = p.getStatus(extras);
2986
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002987 ArrayList<Receiver> deadReceivers = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002988 ArrayList<UpdateRecord> deadUpdateRecords = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07002989
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002990 // Broadcast location or status to all listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002991 for (UpdateRecord r : records) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002992 Receiver receiver = r.mReceiver;
Mike Lockwood03ca2162010-04-01 08:10:09 -07002993 boolean receiverDead = false;
Nick Pelly4035f5a2012-08-17 14:43:49 -07002994
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002995 int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid);
2996 if (!isCurrentProfile(receiverUserId)
2997 && !isUidALocationProvider(receiver.mIdentity.mUid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002998 if (D) {
Victoria Lease269518e2012-10-29 08:25:39 -07002999 Log.d(TAG, "skipping loc update for background user " + receiverUserId +
Victoria Leaseb711d572012-10-02 13:14:11 -07003000 " (current user: " + mCurrentUserId + ", app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08003001 receiver.mIdentity.mPackageName + ")");
Victoria Leaseb711d572012-10-02 13:14:11 -07003002 }
3003 continue;
3004 }
3005
Soonil Nagarkar681d7112017-02-23 17:14:16 -08003006 if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) {
gomo48f1a642017-11-10 20:35:46 -08003007 if (D) {
3008 Log.d(TAG, "skipping loc update for blacklisted app: " +
3009 receiver.mIdentity.mPackageName);
3010 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07003011 continue;
3012 }
3013
Soonil Nagarkar681d7112017-02-23 17:14:16 -08003014 if (!reportLocationAccessNoThrow(
3015 receiver.mIdentity.mPid,
3016 receiver.mIdentity.mUid,
3017 receiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08003018 receiver.mAllowedResolutionLevel)) {
gomo48f1a642017-11-10 20:35:46 -08003019 if (D) {
3020 Log.d(TAG, "skipping loc update for no op app: " +
3021 receiver.mIdentity.mPackageName);
3022 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08003023 continue;
3024 }
3025
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003026 Location notifyLocation;
Victoria Lease37425c32012-10-16 16:08:48 -07003027 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
3028 notifyLocation = coarseLocation; // use coarse location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003029 } else {
Victoria Lease37425c32012-10-16 16:08:48 -07003030 notifyLocation = lastLocation; // use fine location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003031 }
Victoria Lease09016ab2012-09-16 12:33:15 -07003032 if (notifyLocation != null) {
3033 Location lastLoc = r.mLastFixBroadcast;
Laurent Tu75defb62012-11-01 16:21:52 -07003034 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) {
Victoria Lease09016ab2012-09-16 12:33:15 -07003035 if (lastLoc == null) {
3036 lastLoc = new Location(notifyLocation);
3037 r.mLastFixBroadcast = lastLoc;
3038 } else {
3039 lastLoc.set(notifyLocation);
3040 }
3041 if (!receiver.callLocationChangedLocked(notifyLocation)) {
3042 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
3043 receiverDead = true;
3044 }
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07003045 r.mRealRequest.decrementNumUpdates();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003046 }
3047 }
3048
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003049 long prevStatusUpdateTime = r.mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003050 if ((newStatusUpdateTime > prevStatusUpdateTime) &&
Victoria Lease09016ab2012-09-16 12:33:15 -07003051 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003052
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003053 r.mLastStatusBroadcast = newStatusUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 if (!receiver.callStatusChangedLocked(provider, status, extras)) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07003055 receiverDead = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003056 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
Mike Lockwood03ca2162010-04-01 08:10:09 -07003057 }
3058 }
3059
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003060 // track expired records
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07003061 if (r.mRealRequest.getNumUpdates() <= 0 || r.mRealRequest.getExpireAt() < now) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003062 if (deadUpdateRecords == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003063 deadUpdateRecords = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003064 }
3065 deadUpdateRecords.add(r);
3066 }
3067 // track dead receivers
3068 if (receiverDead) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07003069 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003070 deadReceivers = new ArrayList<>();
Mike Lockwood03ca2162010-04-01 08:10:09 -07003071 }
3072 if (!deadReceivers.contains(receiver)) {
3073 deadReceivers.add(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003074 }
3075 }
3076 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003077
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003078 // remove dead records and receivers outside the loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003079 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003080 for (Receiver receiver : deadReceivers) {
3081 removeUpdatesLocked(receiver);
3082 }
3083 }
3084 if (deadUpdateRecords != null) {
3085 for (UpdateRecord r : deadUpdateRecords) {
3086 r.disposeLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003087 }
Victoria Lease8b38b292012-12-04 15:04:43 -08003088 applyRequirementsLocked(provider);
3089 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003090 }
3091
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08003092 /**
3093 * Updates last location with the given location
3094 *
3095 * @param location new location to update
3096 * @param provider Location provider to update for
3097 */
3098 private void updateLastLocationLocked(Location location, String provider) {
3099 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
3100 Location lastNoGPSLocation;
3101 Location lastLocation = mLastLocation.get(provider);
3102 if (lastLocation == null) {
3103 lastLocation = new Location(provider);
3104 mLastLocation.put(provider, lastLocation);
3105 } else {
3106 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
3107 if (noGPSLocation == null && lastNoGPSLocation != null) {
3108 // New location has no no-GPS location: adopt last no-GPS location. This is set
3109 // directly into location because we do not want to notify COARSE clients.
3110 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
3111 }
3112 }
3113 lastLocation.set(location);
3114 }
3115
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003116 private class LocationWorkerHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08003117 public LocationWorkerHandler(Looper looper) {
3118 super(looper, null, true);
3119 }
3120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003121 @Override
3122 public void handleMessage(Message msg) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003123 switch (msg.what) {
3124 case MSG_LOCATION_CHANGED:
3125 handleLocationChanged((Location) msg.obj, msg.arg1 == 1);
3126 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003127 }
3128 }
3129 }
3130
Victoria Lease54ca7ae2013-01-08 09:39:50 -08003131 private boolean isMockProvider(String provider) {
3132 synchronized (mLock) {
3133 return mMockProviders.containsKey(provider);
3134 }
3135 }
3136
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003137 private void handleLocationChanged(Location location, boolean passive) {
Victoria Lease54ca7ae2013-01-08 09:39:50 -08003138 // create a working copy of the incoming Location so that the service can modify it without
3139 // disturbing the caller's copy
3140 Location myLocation = new Location(location);
3141 String provider = myLocation.getProvider();
3142
3143 // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this
3144 // bit if location did not come from a mock provider because passive/fused providers can
3145 // forward locations from mock providers, and should not grant them legitimacy in doing so.
3146 if (!myLocation.isFromMockProvider() && isMockProvider(provider)) {
3147 myLocation.setIsFromMockProvider(true);
3148 }
Jeff Sharkey5e613312012-01-30 11:16:20 -08003149
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003150 synchronized (mLock) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08003151 if (isAllowedByCurrentUserSettingsLocked(provider)) {
3152 if (!passive) {
3153 // notify passive provider of the new location
3154 mPassiveProvider.updateLocation(myLocation);
3155 }
Victoria Lease54ca7ae2013-01-08 09:39:50 -08003156 handleLocationChangedLocked(myLocation, passive);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003157 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003158 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003159 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003160
Mike Lockwoode97ae402010-09-29 15:23:46 -04003161 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
3162 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003163 public void onPackageDisappeared(String packageName, int reason) {
3164 // remove all receivers associated with this package name
3165 synchronized (mLock) {
3166 ArrayList<Receiver> deadReceivers = null;
3167
3168 for (Receiver receiver : mReceivers.values()) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08003169 if (receiver.mIdentity.mPackageName.equals(packageName)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003170 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003171 deadReceivers = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003172 }
3173 deadReceivers.add(receiver);
3174 }
3175 }
3176
3177 // perform removal outside of mReceivers loop
3178 if (deadReceivers != null) {
3179 for (Receiver receiver : deadReceivers) {
3180 removeUpdatesLocked(receiver);
3181 }
3182 }
3183 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003184 }
Mike Lockwoode97ae402010-09-29 15:23:46 -04003185 };
3186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003187 // Geocoder
3188
Nick Pellye0fd6932012-07-11 10:26:13 -07003189 @Override
Mike Lockwoode15735a2010-09-20 17:48:47 -04003190 public boolean geocoderIsPresent() {
Mark Vandevoorde01ac80b2010-05-21 15:43:26 -07003191 return mGeocodeProvider != null;
3192 }
3193
Nick Pellye0fd6932012-07-11 10:26:13 -07003194 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003195 public String getFromLocation(double latitude, double longitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05003196 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04003197 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05003198 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
3199 params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003200 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04003201 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003202 }
3203
Mike Lockwooda55c3212009-04-15 11:10:11 -04003204
Nick Pellye0fd6932012-07-11 10:26:13 -07003205 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003206 public String getFromLocationName(String locationName,
Mike Lockwooda55c3212009-04-15 11:10:11 -04003207 double lowerLeftLatitude, double lowerLeftLongitude,
3208 double upperRightLatitude, double upperRightLongitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05003209 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04003210
3211 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05003212 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
3213 lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
3214 maxResults, params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003215 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04003216 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003217 }
3218
3219 // Mock Providers
3220
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003221 private boolean canCallerAccessMockLocation(String opPackageName) {
3222 return mAppOps.noteOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(),
3223 opPackageName) == AppOpsManager.MODE_ALLOWED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003224 }
3225
Nick Pellye0fd6932012-07-11 10:26:13 -07003226 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003227 public void addTestProvider(String name, ProviderProperties properties, String opPackageName) {
3228 if (!canCallerAccessMockLocation(opPackageName)) {
3229 return;
3230 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003231
Mike Lockwooda4903f22010-02-17 06:42:23 -05003232 if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
3233 throw new IllegalArgumentException("Cannot mock the passive location provider");
3234 }
3235
Mike Lockwood86328a92009-10-23 08:38:25 -04003236 long identity = Binder.clearCallingIdentity();
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003237 synchronized (mLock) {
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003238 // remove the real provider if we are replacing GPS or network provider
3239 if (LocationManager.GPS_PROVIDER.equals(name)
Nick Pelly1332b532012-08-21 16:25:47 -07003240 || LocationManager.NETWORK_PROVIDER.equals(name)
3241 || LocationManager.FUSED_PROVIDER.equals(name)) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05003242 LocationProviderInterface p = mProvidersByName.get(name);
3243 if (p != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003244 removeProviderLocked(p);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003245 }
3246 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09003247 addTestProviderLocked(name, properties);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003248 updateProvidersLocked();
3249 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003250 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003251 }
3252
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09003253 private void addTestProviderLocked(String name, ProviderProperties properties) {
3254 if (mProvidersByName.get(name) != null) {
3255 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
3256 }
3257 MockProvider provider = new MockProvider(name, this, properties);
3258 addProviderLocked(provider);
3259 mMockProviders.put(name, provider);
3260 mLastLocation.put(name, null);
3261 mLastLocationCoarseInterval.put(name, null);
3262 }
3263
Nick Pellye0fd6932012-07-11 10:26:13 -07003264 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003265 public void removeTestProvider(String provider, String opPackageName) {
3266 if (!canCallerAccessMockLocation(opPackageName)) {
3267 return;
3268 }
3269
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003270 synchronized (mLock) {
Tom O'Neill07ee5d12014-03-03 17:48:35 -08003271
3272 // These methods can't be called after removing the test provider, so first make sure
Tom O'Neillfe6d3c52014-03-04 08:26:17 -08003273 // we don't leave anything dangling.
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003274 clearTestProviderEnabled(provider, opPackageName);
3275 clearTestProviderLocation(provider, opPackageName);
3276 clearTestProviderStatus(provider, opPackageName);
Tom O'Neill07ee5d12014-03-03 17:48:35 -08003277
You Kima6d0b6f2012-10-28 03:58:44 +09003278 MockProvider mockProvider = mMockProviders.remove(provider);
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003279 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003280 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3281 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003282 long identity = Binder.clearCallingIdentity();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003283 removeProviderLocked(mProvidersByName.get(provider));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003284
3285 // reinstate real provider if available
3286 LocationProviderInterface realProvider = mRealProviders.get(provider);
3287 if (realProvider != null) {
3288 addProviderLocked(realProvider);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003289 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003290 mLastLocation.put(provider, null);
David Christie1b9b7b12013-04-15 15:31:11 -07003291 mLastLocationCoarseInterval.put(provider, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003292 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003293 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003294 }
3295 }
3296
Nick Pellye0fd6932012-07-11 10:26:13 -07003297 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003298 public void setTestProviderLocation(String provider, Location loc, String opPackageName) {
3299 if (!canCallerAccessMockLocation(opPackageName)) {
3300 return;
3301 }
3302
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003303 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003304 MockProvider mockProvider = mMockProviders.get(provider);
3305 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003306 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3307 }
Tom O'Neilla206a0f2016-12-15 10:26:28 -08003308
3309 // Ensure that the location is marked as being mock. There's some logic to do this in
3310 // handleLocationChanged(), but it fails if loc has the wrong provider (bug 33091107).
3311 Location mock = new Location(loc);
3312 mock.setIsFromMockProvider(true);
3313
3314 if (!TextUtils.isEmpty(loc.getProvider()) && !provider.equals(loc.getProvider())) {
3315 // The location has an explicit provider that is different from the mock provider
3316 // name. The caller may be trying to fool us via bug 33091107.
3317 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
3318 provider + "!=" + loc.getProvider());
3319 }
3320
Mike Lockwood95427cd2009-05-07 13:27:54 -04003321 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
3322 long identity = Binder.clearCallingIdentity();
Tom O'Neilla206a0f2016-12-15 10:26:28 -08003323 mockProvider.setLocation(mock);
Mike Lockwood95427cd2009-05-07 13:27:54 -04003324 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003325 }
3326 }
3327
Nick Pellye0fd6932012-07-11 10:26:13 -07003328 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003329 public void clearTestProviderLocation(String provider, String opPackageName) {
3330 if (!canCallerAccessMockLocation(opPackageName)) {
3331 return;
3332 }
3333
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003334 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003335 MockProvider mockProvider = mMockProviders.get(provider);
3336 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003337 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3338 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003339 mockProvider.clearLocation();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003340 }
3341 }
3342
Nick Pellye0fd6932012-07-11 10:26:13 -07003343 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003344 public void setTestProviderEnabled(String provider, boolean enabled, String opPackageName) {
3345 if (!canCallerAccessMockLocation(opPackageName)) {
3346 return;
3347 }
Maggie2a9409e2018-03-21 11:47:28 -07003348 setTestProviderEnabled(provider, enabled);
3349 }
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003350
Maggie2a9409e2018-03-21 11:47:28 -07003351 /** Enable or disable a test location provider. */
3352 private void setTestProviderEnabled(String provider, boolean enabled) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003353 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003354 MockProvider mockProvider = mMockProviders.get(provider);
3355 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003356 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3357 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003358 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 if (enabled) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003360 mockProvider.enable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003361 mEnabledProviders.add(provider);
3362 mDisabledProviders.remove(provider);
3363 } else {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003364 mockProvider.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003365 mEnabledProviders.remove(provider);
3366 mDisabledProviders.add(provider);
3367 }
3368 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003369 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003370 }
3371 }
3372
Nick Pellye0fd6932012-07-11 10:26:13 -07003373 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003374 public void clearTestProviderEnabled(String provider, String opPackageName) {
3375 if (!canCallerAccessMockLocation(opPackageName)) {
3376 return;
3377 }
3378
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003379 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003380 MockProvider mockProvider = mMockProviders.get(provider);
3381 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003382 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3383 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003384 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003385 mEnabledProviders.remove(provider);
3386 mDisabledProviders.remove(provider);
3387 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003388 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003389 }
3390 }
3391
Nick Pellye0fd6932012-07-11 10:26:13 -07003392 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003393 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime,
3394 String opPackageName) {
3395 if (!canCallerAccessMockLocation(opPackageName)) {
3396 return;
3397 }
3398
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003399 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003400 MockProvider mockProvider = mMockProviders.get(provider);
3401 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003402 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3403 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003404 mockProvider.setStatus(status, extras, updateTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003405 }
3406 }
3407
Nick Pellye0fd6932012-07-11 10:26:13 -07003408 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003409 public void clearTestProviderStatus(String provider, String opPackageName) {
3410 if (!canCallerAccessMockLocation(opPackageName)) {
3411 return;
3412 }
3413
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003414 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003415 MockProvider mockProvider = mMockProviders.get(provider);
3416 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003417 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3418 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003419 mockProvider.clearStatus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003420 }
3421 }
3422
3423 private void log(String log) {
3424 if (Log.isLoggable(TAG, Log.VERBOSE)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003425 Slog.d(TAG, log);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003426 }
3427 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003428
3429 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003430 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003431 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Nick Pellye0fd6932012-07-11 10:26:13 -07003432
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003433 synchronized (mLock) {
Siddharth Raybb608c82017-03-16 11:33:34 -07003434 if (args.length > 0 && args[0].equals("--gnssmetrics")) {
3435 if (mGnssMetricsProvider != null) {
3436 pw.append(mGnssMetricsProvider.getGnssMetricsAsProtoString());
3437 }
3438 return;
3439 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003440 pw.println("Current Location Manager state:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003441 pw.println(" Location Listeners:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003442 for (Receiver receiver : mReceivers.values()) {
3443 pw.println(" " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003444 }
David Christie2ff96af2014-01-30 16:09:37 -08003445 pw.println(" Active Records by Provider:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003446 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
3447 pw.println(" " + entry.getKey() + ":");
3448 for (UpdateRecord record : entry.getValue()) {
3449 pw.println(" " + record);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003450 }
3451 }
Wyatt Riley11cc7492018-01-17 08:48:27 -08003452 pw.println(" Active GnssMeasurement Listeners:");
3453 for (Identity identity : mGnssMeasurementsListeners.values()) {
3454 pw.println(" " + identity.mPid + " " + identity.mUid + " "
3455 + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
3456 }
3457 pw.println(" Active GnssNavigationMessage Listeners:");
3458 for (Identity identity : mGnssNavigationMessageListeners.values()) {
3459 pw.println(" " + identity.mPid + " " + identity.mUid + " "
3460 + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
3461 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003462 pw.println(" Overlay Provider Packages:");
3463 for (LocationProviderInterface provider : mProviders) {
3464 if (provider instanceof LocationProviderProxy) {
3465 pw.println(" " + provider.getName() + ": "
3466 + ((LocationProviderProxy) provider).getConnectedPackageName());
3467 }
3468 }
David Christie2ff96af2014-01-30 16:09:37 -08003469 pw.println(" Historical Records by Provider:");
3470 for (Map.Entry<PackageProviderKey, PackageStatistics> entry
3471 : mRequestStatistics.statistics.entrySet()) {
3472 PackageProviderKey key = entry.getKey();
3473 PackageStatistics stats = entry.getValue();
3474 pw.println(" " + key.packageName + ": " + key.providerName + ": " + stats);
3475 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003476 pw.println(" Last Known Locations:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003477 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
3478 String provider = entry.getKey();
3479 Location location = entry.getValue();
3480 pw.println(" " + provider + ": " + location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003481 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003482
David Christie1b9b7b12013-04-15 15:31:11 -07003483 pw.println(" Last Known Locations Coarse Intervals:");
3484 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
3485 String provider = entry.getKey();
3486 Location location = entry.getValue();
3487 pw.println(" " + provider + ": " + location);
3488 }
3489
Nick Pellye0fd6932012-07-11 10:26:13 -07003490 mGeofenceManager.dump(pw);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003491
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003492 if (mEnabledProviders.size() > 0) {
3493 pw.println(" Enabled Providers:");
3494 for (String i : mEnabledProviders) {
3495 pw.println(" " + i);
3496 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003498 }
3499 if (mDisabledProviders.size() > 0) {
3500 pw.println(" Disabled Providers:");
3501 for (String i : mDisabledProviders) {
3502 pw.println(" " + i);
3503 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07003505 pw.append(" ");
3506 mBlacklist.dump(pw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003507 if (mMockProviders.size() > 0) {
3508 pw.println(" Mock Providers:");
3509 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003510 i.getValue().dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003511 }
3512 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003513
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08003514 if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
3515 pw.println(" Throttling Whitelisted Packages:");
3516 for (String packageName : mBackgroundThrottlePackageWhitelist) {
3517 pw.println(" " + packageName);
3518 }
3519 }
3520
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003521 pw.append(" fudger: ");
gomo48f1a642017-11-10 20:35:46 -08003522 mLocationFudger.dump(fd, pw, args);
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003523
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003524 if (args.length > 0 && "short".equals(args[0])) {
3525 return;
3526 }
gomo48f1a642017-11-10 20:35:46 -08003527 for (LocationProviderInterface provider : mProviders) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003528 pw.print(provider.getName() + " Internal State");
3529 if (provider instanceof LocationProviderProxy) {
3530 LocationProviderProxy proxy = (LocationProviderProxy) provider;
3531 pw.print(" (" + proxy.getConnectedPackageName() + ")");
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003532 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003533 pw.println(":");
3534 provider.dump(fd, pw, args);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003535 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08003536 if (mGnssBatchingInProgress) {
3537 pw.println(" GNSS batching in progress");
3538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003539 }
3540 }
3541}