blob: 93bdcbbb718efded7d73755940ad78fbd7d53ac0 [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
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500544 private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) {
545 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();
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800649 ArrayList<String> providerPackageNames = new ArrayList<>();
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500650 String[] pkgs = resources.getStringArray(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700651 com.android.internal.R.array.config_locationProviderPackageNames);
gomo48f1a642017-11-10 20:35:46 -0800652 if (D) {
653 Log.d(TAG, "certificates for location providers pulled from: " +
654 Arrays.toString(pkgs));
655 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500656 if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));
657
658 ensureFallbackFusedProviderPresentLocked(providerPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700659
660 // bind to network provider
661 LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
662 mContext,
663 LocationManager.NETWORK_PROVIDER,
664 NETWORK_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700665 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
666 com.android.internal.R.string.config_networkLocationProviderPackageName,
667 com.android.internal.R.array.config_locationProviderPackageNames,
668 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700669 if (networkProvider != null) {
670 mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
671 mProxyProviders.add(networkProvider);
672 addProviderLocked(networkProvider);
673 } else {
gomo48f1a642017-11-10 20:35:46 -0800674 Slog.w(TAG, "no network location provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700675 }
676
677 // bind to fused provider
678 LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind(
679 mContext,
680 LocationManager.FUSED_PROVIDER,
681 FUSED_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700682 com.android.internal.R.bool.config_enableFusedLocationOverlay,
683 com.android.internal.R.string.config_fusedLocationProviderPackageName,
684 com.android.internal.R.array.config_locationProviderPackageNames,
685 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700686 if (fusedLocationProvider != null) {
687 addProviderLocked(fusedLocationProvider);
688 mProxyProviders.add(fusedLocationProvider);
689 mEnabledProviders.add(fusedLocationProvider.getName());
Kenny Rootc3575182012-10-09 12:44:40 -0700690 mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700691 } else {
692 Slog.e(TAG, "no fused location provider found",
693 new IllegalStateException("Location service needs a fused location provider"));
694 }
695
696 // bind to geocoder provider
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700697 mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
698 com.android.internal.R.bool.config_enableGeocoderOverlay,
699 com.android.internal.R.string.config_geocoderProviderPackageName,
700 com.android.internal.R.array.config_locationProviderPackageNames,
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800701 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700702 if (mGeocodeProvider == null) {
gomo48f1a642017-11-10 20:35:46 -0800703 Slog.e(TAG, "no geocoder provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700704 }
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700705
destradaaf9a274c2014-07-25 15:11:56 -0700706 // bind to geofence provider
707 GeofenceProxy provider = GeofenceProxy.createAndBind(
gomo48f1a642017-11-10 20:35:46 -0800708 mContext, com.android.internal.R.bool.config_enableGeofenceOverlay,
destradaaf9a274c2014-07-25 15:11:56 -0700709 com.android.internal.R.string.config_geofenceProviderPackageName,
710 com.android.internal.R.array.config_locationProviderPackageNames,
711 mLocationHandler,
Wei Liu5241a4c2015-05-11 14:00:36 -0700712 mGpsGeofenceProxy,
Jiyong Park4cc3a1c2018-03-08 16:43:07 +0900713 null);
destradaaf9a274c2014-07-25 15:11:56 -0700714 if (provider == null) {
gomo48f1a642017-11-10 20:35:46 -0800715 Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
destradaa0682809a2013-08-12 18:50:30 -0700716 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900717
destradaa6e2fe752015-06-23 17:25:53 -0700718 // bind to hardware activity recognition
719 boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
720 ActivityRecognitionHardware activityRecognitionHardware = null;
721 if (activityRecognitionHardwareIsSupported) {
722 activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
destradaaa4fa3b52014-07-09 10:46:39 -0700723 } else {
destradaa6b4893a2016-05-03 15:33:43 -0700724 Slog.d(TAG, "Hardware Activity-Recognition not supported.");
destradaaa4fa3b52014-07-09 10:46:39 -0700725 }
destradaa6e2fe752015-06-23 17:25:53 -0700726 ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
727 mContext,
728 mLocationHandler,
729 activityRecognitionHardwareIsSupported,
730 activityRecognitionHardware,
731 com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
732 com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
733 com.android.internal.R.array.config_locationProviderPackageNames);
734 if (proxy == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700735 Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
destradaa6e2fe752015-06-23 17:25:53 -0700736 }
destradaaa4fa3b52014-07-09 10:46:39 -0700737
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900738 String[] testProviderStrings = resources.getStringArray(
739 com.android.internal.R.array.config_testLocationProviders);
740 for (String testProviderString : testProviderStrings) {
741 String fragments[] = testProviderString.split(",");
742 String name = fragments[0].trim();
743 if (mProvidersByName.get(name) != null) {
744 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
745 }
746 ProviderProperties properties = new ProviderProperties(
747 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
748 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
749 Boolean.parseBoolean(fragments[3]) /* requiresCell */,
750 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
751 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
752 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
753 Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
754 Integer.parseInt(fragments[8]) /* powerRequirement */,
755 Integer.parseInt(fragments[9]) /* accuracy */);
756 addTestProviderLocked(name, properties);
757 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700758 }
Mike Lockwood9637d472009-04-02 21:41:57 -0700759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 /**
Victoria Lease38389b62012-09-30 11:44:22 -0700761 * Called when the device's active user changes.
gomo48f1a642017-11-10 20:35:46 -0800762 *
Victoria Lease38389b62012-09-30 11:44:22 -0700763 * @param userId the new active user's UserId
764 */
765 private void switchUser(int userId) {
Jianzheng Zhoud5c69462013-10-10 14:02:09 +0800766 if (mCurrentUserId == userId) {
767 return;
768 }
Victoria Lease83762d22012-10-03 13:51:17 -0700769 mBlacklist.switchUser(userId);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800770 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED);
Victoria Lease38389b62012-09-30 11:44:22 -0700771 synchronized (mLock) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700772 mLastLocation.clear();
David Christie1b9b7b12013-04-15 15:31:11 -0700773 mLastLocationCoarseInterval.clear();
Victoria Leaseb711d572012-10-02 13:14:11 -0700774 for (LocationProviderInterface p : mProviders) {
Amith Yamasanib27528d2014-06-05 15:02:10 -0700775 updateProviderListenersLocked(p.getName(), false);
Victoria Leaseb711d572012-10-02 13:14:11 -0700776 }
Victoria Lease38389b62012-09-30 11:44:22 -0700777 mCurrentUserId = userId;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700778 updateUserProfiles(userId);
Victoria Leaseb711d572012-10-02 13:14:11 -0700779 updateProvidersLocked();
Victoria Lease38389b62012-09-30 11:44:22 -0700780 }
781 }
782
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800783 private static final class Identity {
784 final int mUid;
785 final int mPid;
786 final String mPackageName;
787
788 Identity(int uid, int pid, String packageName) {
789 mUid = uid;
790 mPid = pid;
791 mPackageName = packageName;
792 }
793 }
794
Victoria Lease38389b62012-09-30 11:44:22 -0700795 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796 * A wrapper class holding either an ILocationListener or a PendingIntent to receive
797 * location updates.
798 */
Mike Lockwood48f17512009-04-23 09:12:08 -0700799 private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
Yu-Han Yang24189822018-07-11 15:24:11 -0700800 private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800801 final Identity mIdentity;
Victoria Lease37425c32012-10-16 16:08:48 -0700802 final int mAllowedResolutionLevel; // resolution level allowed to receiver
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700803
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804 final ILocationListener mListener;
805 final PendingIntent mPendingIntent;
David Christie82edc9b2013-07-19 11:31:42 -0700806 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
David Christie40e57822013-07-30 11:36:48 -0700807 final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800808 final Object mKey;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700809
gomo48f1a642017-11-10 20:35:46 -0800810 final HashMap<String, UpdateRecord> mUpdateRecords = new HashMap<>();
Nick Pellyf1be6862012-05-15 10:53:42 -0700811
David Christie0b837452013-07-29 16:02:13 -0700812 // True if app ops has started monitoring this receiver for locations.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700813 boolean mOpMonitoring;
David Christie0b837452013-07-29 16:02:13 -0700814 // True if app ops has started monitoring this receiver for high power (gps) locations.
815 boolean mOpHighPowerMonitoring;
Mike Lockwood48f17512009-04-23 09:12:08 -0700816 int mPendingBroadcasts;
Victoria Lease0aa28602013-05-29 15:28:26 -0700817 PowerManager.WakeLock mWakeLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800818
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700819 Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -0700820 String packageName, WorkSource workSource, boolean hideFromAppOps) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800821 mListener = listener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822 mPendingIntent = intent;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700823 if (listener != null) {
824 mKey = listener.asBinder();
825 } else {
826 mKey = intent;
827 }
Victoria Lease37425c32012-10-16 16:08:48 -0700828 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800829 mIdentity = new Identity(uid, pid, packageName);
Narayan Kamath32684dd2018-01-08 17:32:51 +0000830 if (workSource != null && workSource.isEmpty()) {
David Christie82edc9b2013-07-19 11:31:42 -0700831 workSource = null;
832 }
833 mWorkSource = workSource;
David Christie40e57822013-07-30 11:36:48 -0700834 mHideFromAppOps = hideFromAppOps;
Victoria Lease0aa28602013-05-29 15:28:26 -0700835
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700836 updateMonitoring(true);
837
Victoria Lease0aa28602013-05-29 15:28:26 -0700838 // construct/configure wakelock
839 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
David Christie82edc9b2013-07-19 11:31:42 -0700840 if (workSource == null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800841 workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -0700842 }
843 mWakeLock.setWorkSource(workSource);
Yu-Han Yang24189822018-07-11 15:24:11 -0700844
845 // For a non-reference counted wakelock, each acquire will reset the timeout, and we
846 // only need to release it once.
847 mWakeLock.setReferenceCounted(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848 }
849
850 @Override
851 public boolean equals(Object otherObj) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800852 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 }
854
855 @Override
856 public int hashCode() {
857 return mKey.hashCode();
858 }
Mike Lockwood3681f262009-05-12 10:52:03 -0400859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 @Override
861 public String toString() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700862 StringBuilder s = new StringBuilder();
863 s.append("Reciever[");
864 s.append(Integer.toHexString(System.identityHashCode(this)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 if (mListener != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700866 s.append(" listener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700868 s.append(" intent");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700870 for (String p : mUpdateRecords.keySet()) {
871 s.append(" ").append(mUpdateRecords.get(p).toString());
872 }
Wei Wangdd070f22018-06-21 11:29:40 -0700873 s.append(" monitoring location: ").append(mOpMonitoring);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700874 s.append("]");
875 return s.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876 }
877
David Christie15b31912013-08-13 15:54:32 -0700878 /**
879 * Update AppOp monitoring for this receiver.
880 *
881 * @param allow If true receiver is currently active, if false it's been removed.
882 */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700883 public void updateMonitoring(boolean allow) {
David Christie40e57822013-07-30 11:36:48 -0700884 if (mHideFromAppOps) {
885 return;
886 }
887
David Christie15b31912013-08-13 15:54:32 -0700888 boolean requestingLocation = false;
889 boolean requestingHighPowerLocation = false;
890 if (allow) {
891 // See if receiver has any enabled update records. Also note if any update records
892 // are high power (has a high power provider with an interval under a threshold).
893 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
894 if (isAllowedByCurrentUserSettingsLocked(updateRecord.mProvider)) {
895 requestingLocation = true;
896 LocationProviderInterface locationProvider
David Christie2ff96af2014-01-30 16:09:37 -0800897 = mProvidersByName.get(updateRecord.mProvider);
David Christie15b31912013-08-13 15:54:32 -0700898 ProviderProperties properties = locationProvider != null
899 ? locationProvider.getProperties() : null;
900 if (properties != null
901 && properties.mPowerRequirement == Criteria.POWER_HIGH
902 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
903 requestingHighPowerLocation = true;
904 break;
905 }
906 }
907 }
908 }
909
David Christie0b837452013-07-29 16:02:13 -0700910 // First update monitoring of any location request (including high power).
David Christie15b31912013-08-13 15:54:32 -0700911 mOpMonitoring = updateMonitoring(
912 requestingLocation,
913 mOpMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700914 AppOpsManager.OP_MONITOR_LOCATION);
915
916 // Now update monitoring of high power requests only.
David Christiec750c1f2013-08-08 12:56:57 -0700917 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
David Christie15b31912013-08-13 15:54:32 -0700918 mOpHighPowerMonitoring = updateMonitoring(
919 requestingHighPowerLocation,
920 mOpHighPowerMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700921 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
David Christiec750c1f2013-08-08 12:56:57 -0700922 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
David Christie15b31912013-08-13 15:54:32 -0700923 // Send an intent to notify that a high power request has been added/removed.
David Christiec750c1f2013-08-08 12:56:57 -0700924 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
925 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
926 }
David Christie0b837452013-07-29 16:02:13 -0700927 }
928
929 /**
930 * Update AppOps monitoring for a single location request and op type.
931 *
gomo48f1a642017-11-10 20:35:46 -0800932 * @param allowMonitoring True if monitoring is allowed for this request/op.
David Christie0b837452013-07-29 16:02:13 -0700933 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
gomo48f1a642017-11-10 20:35:46 -0800934 * @param op AppOps code for the op to update.
David Christie0b837452013-07-29 16:02:13 -0700935 * @return True if monitoring is on for this request/op after updating.
936 */
937 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
938 int op) {
939 if (!currentlyMonitoring) {
940 if (allowMonitoring) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800941 return mAppOps.startOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700942 == AppOpsManager.MODE_ALLOWED;
943 }
944 } else {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800945 if (!allowMonitoring
Wei Wangdd070f22018-06-21 11:29:40 -0700946 || mAppOps.noteOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700947 != AppOpsManager.MODE_ALLOWED) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800948 mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName);
David Christie0b837452013-07-29 16:02:13 -0700949 return false;
950 }
951 }
952
953 return currentlyMonitoring;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700954 }
955
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 public boolean isListener() {
957 return mListener != null;
958 }
959
960 public boolean isPendingIntent() {
961 return mPendingIntent != null;
962 }
963
964 public ILocationListener getListener() {
965 if (mListener != null) {
966 return mListener;
967 }
968 throw new IllegalStateException("Request for non-existent listener");
969 }
970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800971 public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
972 if (mListener != null) {
973 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700974 synchronized (this) {
975 // synchronize to ensure incrementPendingBroadcastsLocked()
976 // is called before decrementPendingBroadcasts()
977 mListener.onStatusChanged(provider, status, extras);
Nick Pellye0fd6932012-07-11 10:26:13 -0700978 // call this after broadcasting so we do not increment
979 // if we throw an exeption.
980 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -0700981 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982 } catch (RemoteException e) {
983 return false;
984 }
985 } else {
986 Intent statusChanged = new Intent();
Victoria Lease61ecb022012-11-13 15:12:51 -0800987 statusChanged.putExtras(new Bundle(extras));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
989 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700990 synchronized (this) {
991 // synchronize to ensure incrementPendingBroadcastsLocked()
992 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700993 mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
Lifu Tang519f0d02018-04-12 16:39:39 -0700994 getResolutionPermission(mAllowedResolutionLevel),
995 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
Mike Lockwood48f17512009-04-23 09:12:08 -0700996 // call this after broadcasting so we do not increment
997 // if we throw an exeption.
998 incrementPendingBroadcastsLocked();
999 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 } catch (PendingIntent.CanceledException e) {
1001 return false;
1002 }
1003 }
1004 return true;
1005 }
1006
1007 public boolean callLocationChangedLocked(Location location) {
1008 if (mListener != null) {
1009 try {
Mike Lockwood48f17512009-04-23 09:12:08 -07001010 synchronized (this) {
1011 // synchronize to ensure incrementPendingBroadcastsLocked()
1012 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08001013 mListener.onLocationChanged(new Location(location));
Nick Pellye0fd6932012-07-11 10:26:13 -07001014 // call this after broadcasting so we do not increment
1015 // if we throw an exeption.
1016 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 } catch (RemoteException e) {
1019 return false;
1020 }
1021 } else {
1022 Intent locationChanged = new Intent();
gomo48f1a642017-11-10 20:35:46 -08001023 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED,
1024 new Location(location));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 try {
Mike Lockwood48f17512009-04-23 09:12:08 -07001026 synchronized (this) {
1027 // synchronize to ensure incrementPendingBroadcastsLocked()
1028 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001029 mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
Lifu Tang519f0d02018-04-12 16:39:39 -07001030 getResolutionPermission(mAllowedResolutionLevel),
1031 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
Mike Lockwood48f17512009-04-23 09:12:08 -07001032 // call this after broadcasting so we do not increment
1033 // if we throw an exeption.
1034 incrementPendingBroadcastsLocked();
1035 }
1036 } catch (PendingIntent.CanceledException e) {
1037 return false;
1038 }
1039 }
1040 return true;
1041 }
1042
1043 public boolean callProviderEnabledLocked(String provider, boolean enabled) {
David Christie15b31912013-08-13 15:54:32 -07001044 // First update AppOp monitoring.
1045 // An app may get/lose location access as providers are enabled/disabled.
1046 updateMonitoring(true);
1047
Mike Lockwood48f17512009-04-23 09:12:08 -07001048 if (mListener != null) {
1049 try {
1050 synchronized (this) {
1051 // synchronize to ensure incrementPendingBroadcastsLocked()
1052 // is called before decrementPendingBroadcasts()
1053 if (enabled) {
1054 mListener.onProviderEnabled(provider);
1055 } else {
1056 mListener.onProviderDisabled(provider);
1057 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001058 // call this after broadcasting so we do not increment
1059 // if we throw an exeption.
1060 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001061 }
1062 } catch (RemoteException e) {
1063 return false;
1064 }
1065 } else {
1066 Intent providerIntent = new Intent();
1067 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1068 try {
1069 synchronized (this) {
1070 // synchronize to ensure incrementPendingBroadcastsLocked()
1071 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001072 mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
Lifu Tang519f0d02018-04-12 16:39:39 -07001073 getResolutionPermission(mAllowedResolutionLevel),
1074 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
Mike Lockwood48f17512009-04-23 09:12:08 -07001075 // call this after broadcasting so we do not increment
1076 // if we throw an exeption.
1077 incrementPendingBroadcastsLocked();
1078 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001079 } catch (PendingIntent.CanceledException e) {
1080 return false;
1081 }
1082 }
1083 return true;
1084 }
1085
Nick Pellyf1be6862012-05-15 10:53:42 -07001086 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 public void binderDied() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001088 if (D) Log.d(TAG, "Location listener died");
1089
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001090 synchronized (mLock) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 removeUpdatesLocked(this);
1092 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001093 synchronized (this) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001094 clearPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001095 }
1096 }
1097
Nick Pellye0fd6932012-07-11 10:26:13 -07001098 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001099 public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1100 int resultCode, String resultData, Bundle resultExtras) {
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001101 synchronized (this) {
1102 decrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001103 }
1104 }
1105
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001106 // this must be called while synchronized by caller in a synchronized block
1107 // containing the sending of the broadcaset
1108 private void incrementPendingBroadcastsLocked() {
Yu-Han Yang24189822018-07-11 15:24:11 -07001109 mPendingBroadcasts++;
1110 mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001111 }
1112
1113 private void decrementPendingBroadcastsLocked() {
1114 if (--mPendingBroadcasts == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001115 if (mWakeLock.isHeld()) {
1116 mWakeLock.release();
1117 }
1118 }
1119 }
1120
1121 public void clearPendingBroadcastsLocked() {
1122 if (mPendingBroadcasts > 0) {
1123 mPendingBroadcasts = 0;
1124 if (mWakeLock.isHeld()) {
1125 mWakeLock.release();
1126 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001127 }
1128 }
1129 }
1130
Nick Pellye0fd6932012-07-11 10:26:13 -07001131 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001132 public void locationCallbackFinished(ILocationListener listener) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001133 //Do not use getReceiverLocked here as that will add the ILocationListener to
Joshua Bartel080b61b2009-10-05 12:44:46 -04001134 //the receiver list if it is not found. If it is not found then the
1135 //LocationListener was removed when it had a pending broadcast and should
1136 //not be added back.
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001137 synchronized (mLock) {
1138 IBinder binder = listener.asBinder();
1139 Receiver receiver = mReceivers.get(binder);
1140 if (receiver != null) {
1141 synchronized (receiver) {
1142 // so wakelock calls will succeed
1143 long identity = Binder.clearCallingIdentity();
1144 receiver.decrementPendingBroadcastsLocked();
1145 Binder.restoreCallingIdentity(identity);
David Christie2ff96af2014-01-30 16:09:37 -08001146 }
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001147 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001148 }
1149 }
1150
Lifu Tang82f893d2016-01-21 18:15:33 -08001151 /**
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001152 * Returns the year of the GNSS hardware.
Lifu Tang82f893d2016-01-21 18:15:33 -08001153 */
1154 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001155 public int getGnssYearOfHardware() {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001156 if (mGnssSystemInfoProvider != null) {
Lifu Tang9363b942016-02-16 18:07:00 -08001157 return mGnssSystemInfoProvider.getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001158 } else {
1159 return 0;
1160 }
1161 }
1162
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001163
1164 /**
1165 * Returns the model name of the GNSS hardware.
1166 */
1167 @Override
Wyatt Riley49097c02018-03-15 09:14:43 -07001168 @Nullable
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001169 public String getGnssHardwareModelName() {
1170 if (mGnssSystemInfoProvider != null) {
1171 return mGnssSystemInfoProvider.getGnssHardwareModelName();
1172 } else {
Wyatt Riley49097c02018-03-15 09:14:43 -07001173 return null;
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001174 }
1175 }
1176
Wyatt Rileycf879db2017-01-12 13:57:38 -08001177 /**
1178 * Runs some checks for GNSS (FINE) level permissions, used by several methods which directly
1179 * (try to) access GNSS information at this layer.
1180 */
1181 private boolean hasGnssPermissions(String packageName) {
1182 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
1183 checkResolutionLevelIsSufficientForProviderUse(
1184 allowedResolutionLevel,
1185 LocationManager.GPS_PROVIDER);
1186
1187 int pid = Binder.getCallingPid();
1188 int uid = Binder.getCallingUid();
1189 long identity = Binder.clearCallingIdentity();
1190 boolean hasLocationAccess;
1191 try {
1192 hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
1193 } finally {
1194 Binder.restoreCallingIdentity(identity);
1195 }
1196
1197 return hasLocationAccess;
1198 }
1199
1200 /**
1201 * Returns the GNSS batching size, if available.
1202 */
1203 @Override
1204 public int getGnssBatchSize(String packageName) {
1205 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1206 "Location Hardware permission not granted to access hardware batching");
1207
1208 if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
Yu-Han Yang3557cc72018-03-21 12:48:36 -07001209 return mGnssBatchingProvider.getBatchSize();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001210 } else {
1211 return 0;
1212 }
1213 }
1214
1215 /**
1216 * Adds a callback for GNSS Batching events, if permissions allow, which are transported
1217 * to potentially multiple listeners by the BatchedLocationCallbackTransport above this.
1218 */
1219 @Override
1220 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) {
1221 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1222 "Location Hardware permission not granted to access hardware batching");
1223
1224 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1225 return false;
1226 }
1227
1228 mGnssBatchingCallback = callback;
1229 mGnssBatchingDeathCallback = new LinkedCallback(callback);
1230 try {
1231 callback.asBinder().linkToDeath(mGnssBatchingDeathCallback, 0 /* flags */);
1232 } catch (RemoteException e) {
1233 // if the remote process registering the listener is already dead, just swallow the
1234 // exception and return
1235 Log.e(TAG, "Remote listener already died.", e);
1236 return false;
1237 }
1238
1239 return true;
1240 }
1241
1242 private class LinkedCallback implements IBinder.DeathRecipient {
1243 private final IBatchedLocationCallback mCallback;
1244
1245 public LinkedCallback(@NonNull IBatchedLocationCallback callback) {
1246 mCallback = callback;
1247 }
1248
1249 @NonNull
1250 public IBatchedLocationCallback getUnderlyingListener() {
1251 return mCallback;
1252 }
1253
1254 @Override
1255 public void binderDied() {
1256 Log.d(TAG, "Remote Batching Callback died: " + mCallback);
1257 stopGnssBatch();
1258 removeGnssBatchingCallback();
1259 }
1260 }
1261
1262 /**
1263 * Removes callback for GNSS batching
1264 */
1265 @Override
1266 public void removeGnssBatchingCallback() {
1267 try {
1268 mGnssBatchingCallback.asBinder().unlinkToDeath(mGnssBatchingDeathCallback,
1269 0 /* flags */);
1270 } catch (NoSuchElementException e) {
1271 // if the death callback isn't connected (it should be...), log error, swallow the
1272 // exception and return
1273 Log.e(TAG, "Couldn't unlink death callback.", e);
1274 }
1275 mGnssBatchingCallback = null;
1276 mGnssBatchingDeathCallback = null;
1277 }
1278
1279
1280 /**
1281 * Starts GNSS batching, if available.
1282 */
1283 @Override
1284 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
1285 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1286 "Location Hardware permission not granted to access hardware batching");
1287
1288 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1289 return false;
1290 }
1291
1292 if (mGnssBatchingInProgress) {
1293 // Current design does not expect multiple starts to be called repeatedly
1294 Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch");
1295 // Try to clean up anyway, and continue
1296 stopGnssBatch();
1297 }
1298
1299 mGnssBatchingInProgress = true;
1300 return mGnssBatchingProvider.start(periodNanos, wakeOnFifoFull);
1301 }
1302
1303 /**
1304 * Flushes a GNSS batch in progress
1305 */
1306 @Override
1307 public void flushGnssBatch(String packageName) {
1308 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1309 "Location Hardware permission not granted to access hardware batching");
1310
1311 if (!hasGnssPermissions(packageName)) {
1312 Log.e(TAG, "flushGnssBatch called without GNSS permissions");
1313 return;
1314 }
1315
1316 if (!mGnssBatchingInProgress) {
1317 Log.w(TAG, "flushGnssBatch called with no batch in progress");
1318 }
1319
1320 if (mGnssBatchingProvider != null) {
gomo48f1a642017-11-10 20:35:46 -08001321 mGnssBatchingProvider.flush();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001322 }
1323 }
1324
1325 /**
1326 * Stops GNSS batching
1327 */
1328 @Override
1329 public boolean stopGnssBatch() {
1330 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1331 "Location Hardware permission not granted to access hardware batching");
1332
1333 if (mGnssBatchingProvider != null) {
1334 mGnssBatchingInProgress = false;
1335 return mGnssBatchingProvider.stop();
gomo48f1a642017-11-10 20:35:46 -08001336 } else {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001337 return false;
1338 }
1339 }
1340
1341 @Override
1342 public void reportLocationBatch(List<Location> locations) {
1343 checkCallerIsProvider();
1344
1345 // Currently used only for GNSS locations - update permissions check if changed
1346 if (isAllowedByCurrentUserSettingsLocked(LocationManager.GPS_PROVIDER)) {
1347 if (mGnssBatchingCallback == null) {
1348 Slog.e(TAG, "reportLocationBatch() called without active Callback");
1349 return;
1350 }
1351 try {
1352 mGnssBatchingCallback.onLocationBatch(locations);
1353 } catch (RemoteException e) {
1354 Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e);
1355 }
1356 } else {
1357 Slog.w(TAG, "reportLocationBatch() called without user permission, locations blocked");
1358 }
1359 }
1360
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001361 private void addProviderLocked(LocationProviderInterface provider) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001362 mProviders.add(provider);
1363 mProvidersByName.put(provider.getName(), provider);
1364 }
1365
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001366 private void removeProviderLocked(LocationProviderInterface provider) {
1367 provider.disable();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001368 mProviders.remove(provider);
1369 mProvidersByName.remove(provider.getName());
1370 }
1371
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001372 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001373 * Returns "true" if access to the specified location provider is allowed by the current
1374 * user's settings. Access to all location providers is forbidden to non-location-provider
1375 * processes belonging to background users.
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001376 *
1377 * @param provider the name of the location provider
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001378 */
Victoria Lease09eeaec2013-02-05 11:34:13 -08001379 private boolean isAllowedByCurrentUserSettingsLocked(String provider) {
Maggie2a9409e2018-03-21 11:47:28 -07001380 return isAllowedByUserSettingsLockedForUser(provider, mCurrentUserId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 }
1382
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001383 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001384 * Returns "true" if access to the specified location provider is allowed by the specified
1385 * user's settings. Access to all location providers is forbidden to non-location-provider
1386 * processes belonging to background users.
1387 *
1388 * @param provider the name of the location provider
Maggie2a9409e2018-03-21 11:47:28 -07001389 * @param userId the user id to query
Victoria Lease09eeaec2013-02-05 11:34:13 -08001390 */
Maggie2a9409e2018-03-21 11:47:28 -07001391 private boolean isAllowedByUserSettingsLockedForUser(String provider, int userId) {
1392 if (mEnabledProviders.contains(provider)) {
1393 return true;
1394 }
1395 if (mDisabledProviders.contains(provider)) {
1396 return false;
1397 }
1398 return isLocationProviderEnabledForUser(provider, userId);
1399 }
1400
1401
1402 /**
1403 * Returns "true" if access to the specified location provider is allowed by the specified
1404 * user's settings. Access to all location providers is forbidden to non-location-provider
1405 * processes belonging to background users.
1406 *
1407 * @param provider the name of the location provider
1408 * @param uid the requestor's UID
1409 * @param userId the user id to query
1410 */
1411 private boolean isAllowedByUserSettingsLocked(String provider, int uid, int userId) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001412 if (!isCurrentProfile(UserHandle.getUserId(uid)) && !isUidALocationProvider(uid)) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08001413 return false;
1414 }
Maggie2a9409e2018-03-21 11:47:28 -07001415 return isAllowedByUserSettingsLockedForUser(provider, userId);
Victoria Lease09eeaec2013-02-05 11:34:13 -08001416 }
1417
1418 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001419 * Returns the permission string associated with the specified resolution level.
1420 *
1421 * @param resolutionLevel the resolution level
1422 * @return the permission string
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001423 */
Victoria Lease37425c32012-10-16 16:08:48 -07001424 private String getResolutionPermission(int resolutionLevel) {
1425 switch (resolutionLevel) {
1426 case RESOLUTION_LEVEL_FINE:
1427 return android.Manifest.permission.ACCESS_FINE_LOCATION;
1428 case RESOLUTION_LEVEL_COARSE:
1429 return android.Manifest.permission.ACCESS_COARSE_LOCATION;
1430 default:
1431 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001432 }
Victoria Leaseda479c52012-10-15 15:24:16 -07001433 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001434
Victoria Leaseda479c52012-10-15 15:24:16 -07001435 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001436 * Returns the resolution level allowed to the given PID/UID pair.
1437 *
1438 * @param pid the PID
1439 * @param uid the UID
1440 * @return resolution level allowed to the pid/uid pair
Victoria Leaseda479c52012-10-15 15:24:16 -07001441 */
Victoria Lease37425c32012-10-16 16:08:48 -07001442 private int getAllowedResolutionLevel(int pid, int uid) {
1443 if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001444 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001445 return RESOLUTION_LEVEL_FINE;
1446 } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001447 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001448 return RESOLUTION_LEVEL_COARSE;
1449 } else {
1450 return RESOLUTION_LEVEL_NONE;
Victoria Leaseda479c52012-10-15 15:24:16 -07001451 }
Victoria Lease4fab68b2012-09-13 13:20:59 -07001452 }
1453
1454 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001455 * Returns the resolution level allowed to the caller
1456 *
1457 * @return resolution level allowed to caller
Victoria Lease4fab68b2012-09-13 13:20:59 -07001458 */
Victoria Lease37425c32012-10-16 16:08:48 -07001459 private int getCallerAllowedResolutionLevel() {
1460 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
1461 }
1462
1463 /**
1464 * Throw SecurityException if specified resolution level is insufficient to use geofences.
1465 *
1466 * @param allowedResolutionLevel resolution level allowed to caller
1467 */
1468 private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
1469 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Lease4fab68b2012-09-13 13:20:59 -07001470 throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
1471 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001472 }
1473
Victoria Lease37425c32012-10-16 16:08:48 -07001474 /**
1475 * Return the minimum resolution level required to use the specified location provider.
1476 *
1477 * @param provider the name of the location provider
1478 * @return minimum resolution level required for provider
1479 */
1480 private int getMinimumResolutionLevelForProviderUse(String provider) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001481 if (LocationManager.GPS_PROVIDER.equals(provider) ||
1482 LocationManager.PASSIVE_PROVIDER.equals(provider)) {
1483 // gps and passive providers require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001484 return RESOLUTION_LEVEL_FINE;
Victoria Lease8dbb6342012-09-21 16:55:53 -07001485 } else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
1486 LocationManager.FUSED_PROVIDER.equals(provider)) {
1487 // network and fused providers are ok with COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001488 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001489 } else {
1490 // mock providers
1491 LocationProviderInterface lp = mMockProviders.get(provider);
1492 if (lp != null) {
1493 ProviderProperties properties = lp.getProperties();
1494 if (properties != null) {
1495 if (properties.mRequiresSatellite) {
1496 // provider requiring satellites require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001497 return RESOLUTION_LEVEL_FINE;
Laurent Tu941221c2012-10-04 14:21:52 -07001498 } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
1499 // provider requiring network and or cell require COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001500 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001501 }
1502 }
1503 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001504 }
Victoria Lease37425c32012-10-16 16:08:48 -07001505 return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
Victoria Leaseda479c52012-10-15 15:24:16 -07001506 }
1507
Victoria Lease37425c32012-10-16 16:08:48 -07001508 /**
1509 * Throw SecurityException if specified resolution level is insufficient to use the named
1510 * location provider.
1511 *
1512 * @param allowedResolutionLevel resolution level allowed to caller
gomo48f1a642017-11-10 20:35:46 -08001513 * @param providerName the name of the location provider
Victoria Lease37425c32012-10-16 16:08:48 -07001514 */
1515 private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel,
1516 String providerName) {
1517 int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName);
1518 if (allowedResolutionLevel < requiredResolutionLevel) {
1519 switch (requiredResolutionLevel) {
1520 case RESOLUTION_LEVEL_FINE:
1521 throw new SecurityException("\"" + providerName + "\" location provider " +
1522 "requires ACCESS_FINE_LOCATION permission.");
1523 case RESOLUTION_LEVEL_COARSE:
1524 throw new SecurityException("\"" + providerName + "\" location provider " +
1525 "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
1526 default:
1527 throw new SecurityException("Insufficient permission for \"" + providerName +
1528 "\" location provider.");
Victoria Leaseda479c52012-10-15 15:24:16 -07001529 }
1530 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001531 }
1532
David Christie82edc9b2013-07-19 11:31:42 -07001533 /**
1534 * Throw SecurityException if WorkSource use is not allowed (i.e. can't blame other packages
1535 * for battery).
1536 */
David Christie40e57822013-07-30 11:36:48 -07001537 private void checkDeviceStatsAllowed() {
David Christie82edc9b2013-07-19 11:31:42 -07001538 mContext.enforceCallingOrSelfPermission(
1539 android.Manifest.permission.UPDATE_DEVICE_STATS, null);
1540 }
1541
David Christie40e57822013-07-30 11:36:48 -07001542 private void checkUpdateAppOpsAllowed() {
1543 mContext.enforceCallingOrSelfPermission(
1544 android.Manifest.permission.UPDATE_APP_OPS_STATS, null);
1545 }
1546
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001547 public static int resolutionLevelToOp(int allowedResolutionLevel) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001548 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
1549 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001550 return AppOpsManager.OP_COARSE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001551 } else {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001552 return AppOpsManager.OP_FINE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001553 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001554 }
1555 return -1;
1556 }
1557
Wei Wangb86334f2018-07-03 16:33:24 -07001558 private static String resolutionLevelToOpStr(int allowedResolutionLevel) {
1559 switch(allowedResolutionLevel) {
1560 case RESOLUTION_LEVEL_COARSE:
1561 return AppOpsManager.OPSTR_COARSE_LOCATION;
1562 case RESOLUTION_LEVEL_FINE:
1563 return AppOpsManager.OPSTR_FINE_LOCATION;
1564 case RESOLUTION_LEVEL_NONE:
1565 // The client is not allowed to get any location, so both FINE and COARSE ops will
1566 // be denied. Pick the most restrictive one to be safe.
1567 return AppOpsManager.OPSTR_FINE_LOCATION;
1568 default:
1569 // Use the most restrictive ops if not sure.
1570 return AppOpsManager.OPSTR_FINE_LOCATION;
1571 }
1572 }
1573
David Christieb870dbf2015-06-22 12:42:53 -07001574 boolean reportLocationAccessNoThrow(
1575 int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001576 int op = resolutionLevelToOp(allowedResolutionLevel);
1577 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001578 if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1579 return false;
1580 }
1581 }
David Christieb870dbf2015-06-22 12:42:53 -07001582
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001583 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001584 }
1585
David Christieb870dbf2015-06-22 12:42:53 -07001586 boolean checkLocationAccess(int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001587 int op = resolutionLevelToOp(allowedResolutionLevel);
1588 if (op >= 0) {
Wei Wangdd070f22018-06-21 11:29:40 -07001589 if (mAppOps.noteOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001590 return false;
1591 }
1592 }
David Christieb870dbf2015-06-22 12:42:53 -07001593
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001594 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001595 }
1596
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001597 /**
Maggie91e630c2018-01-24 17:31:46 -08001598 * Returns all providers by name, including passive and the ones that are not permitted to
1599 * be accessed by the calling activity or are currently disabled, but excluding fused.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001600 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001601 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001602 public List<String> getAllProviders() {
Maggie91e630c2018-01-24 17:31:46 -08001603 ArrayList<String> out;
1604 synchronized (mLock) {
1605 out = new ArrayList<>(mProviders.size());
1606 for (LocationProviderInterface provider : mProviders) {
1607 String name = provider.getName();
1608 if (LocationManager.FUSED_PROVIDER.equals(name)) {
1609 continue;
1610 }
1611 out.add(name);
1612 }
1613 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001614 if (D) Log.d(TAG, "getAllProviders()=" + out);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615 return out;
1616 }
1617
Mike Lockwood03ca2162010-04-01 08:10:09 -07001618 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001619 * Return all providers by name, that match criteria and are optionally
1620 * enabled.
1621 * Can return passive provider, but never returns fused provider.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001622 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001623 @Override
1624 public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
Victoria Lease37425c32012-10-16 16:08:48 -07001625 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001626 ArrayList<String> out;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001627 int uid = Binder.getCallingUid();
Victoria Lease269518e2012-10-29 08:25:39 -07001628 long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07001629 try {
1630 synchronized (mLock) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001631 out = new ArrayList<>(mProviders.size());
Victoria Leaseb711d572012-10-02 13:14:11 -07001632 for (LocationProviderInterface provider : mProviders) {
1633 String name = provider.getName();
1634 if (LocationManager.FUSED_PROVIDER.equals(name)) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001635 continue;
1636 }
Victoria Lease37425c32012-10-16 16:08:48 -07001637 if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
Maggie2a9409e2018-03-21 11:47:28 -07001638 if (enabledOnly
1639 && !isAllowedByUserSettingsLocked(name, uid, mCurrentUserId)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001640 continue;
1641 }
1642 if (criteria != null && !LocationProvider.propertiesMeetCriteria(
1643 name, provider.getProperties(), criteria)) {
1644 continue;
1645 }
1646 out.add(name);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001647 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001648 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001649 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001650 } finally {
1651 Binder.restoreCallingIdentity(identity);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001652 }
1653
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001654 if (D) Log.d(TAG, "getProviders()=" + out);
1655 return out;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001656 }
1657
1658 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001659 * Return the name of the best provider given a Criteria object.
1660 * This method has been deprecated from the public API,
Victoria Lease8dbb6342012-09-21 16:55:53 -07001661 * and the whole LocationProvider (including #meetsCriteria)
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001662 * has been deprecated as well. So this method now uses
1663 * some simplified logic.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001664 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001665 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001666 public String getBestProvider(Criteria criteria, boolean enabledOnly) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001667 String result = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001668
1669 List<String> providers = getProviders(criteria, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001670 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001671 result = pickBest(providers);
1672 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1673 return result;
1674 }
1675 providers = getProviders(null, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001676 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001677 result = pickBest(providers);
1678 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1679 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001680 }
1681
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001682 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001683 return null;
1684 }
1685
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001686 private String pickBest(List<String> providers) {
Victoria Lease1925e292012-09-24 17:00:18 -07001687 if (providers.contains(LocationManager.GPS_PROVIDER)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001688 return LocationManager.GPS_PROVIDER;
Victoria Lease1925e292012-09-24 17:00:18 -07001689 } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
1690 return LocationManager.NETWORK_PROVIDER;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001691 } else {
1692 return providers.get(0);
1693 }
1694 }
1695
Nick Pellye0fd6932012-07-11 10:26:13 -07001696 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001697 public boolean providerMeetsCriteria(String provider, Criteria criteria) {
1698 LocationProviderInterface p = mProvidersByName.get(provider);
1699 if (p == null) {
1700 throw new IllegalArgumentException("provider=" + provider);
1701 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001702
1703 boolean result = LocationProvider.propertiesMeetCriteria(
1704 p.getName(), p.getProperties(), criteria);
1705 if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result);
1706 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001707 }
1708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 private void updateProvidersLocked() {
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001710 boolean changesMade = false;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001711 for (int i = mProviders.size() - 1; i >= 0; i--) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001712 LocationProviderInterface p = mProviders.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 boolean isEnabled = p.isEnabled();
1714 String name = p.getName();
Victoria Lease09eeaec2013-02-05 11:34:13 -08001715 boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001716 if (isEnabled && !shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001717 updateProviderListenersLocked(name, false);
David Christieb084fef2013-12-18 14:33:57 -08001718 // If any provider has been disabled, clear all last locations for all providers.
1719 // This is to be on the safe side in case a provider has location derived from
1720 // this disabled provider.
1721 mLastLocation.clear();
1722 mLastLocationCoarseInterval.clear();
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001723 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001724 } else if (!isEnabled && shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001725 updateProviderListenersLocked(name, true);
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001726 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001727 }
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001728 }
1729 if (changesMade) {
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001730 mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
1731 UserHandle.ALL);
Tom O'Neill40a86c22013-09-03 18:05:13 -07001732 mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
1733 UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001734 }
1735 }
1736
Amith Yamasanib27528d2014-06-05 15:02:10 -07001737 private void updateProviderListenersLocked(String provider, boolean enabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 int listeners = 0;
1739
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001740 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001741 if (p == null) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001742
1743 ArrayList<Receiver> deadReceivers = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07001744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1746 if (records != null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001747 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001748 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001749 // Sends a notification message to the receiver
1750 if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
1751 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001752 deadReceivers = new ArrayList<>();
Victoria Leaseb711d572012-10-02 13:14:11 -07001753 }
1754 deadReceivers.add(record.mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001755 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001756 listeners++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001757 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001758 }
1759 }
1760
1761 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001762 for (int i = deadReceivers.size() - 1; i >= 0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001763 removeUpdatesLocked(deadReceivers.get(i));
1764 }
1765 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001767 if (enabled) {
1768 p.enable();
Yu-Han Yanga4d250e2018-10-02 21:29:20 -07001769 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771 p.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001773 }
1774
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001775 private void applyRequirementsLocked(String provider) {
1776 LocationProviderInterface p = mProvidersByName.get(provider);
1777 if (p == null) return;
1778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001779 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001780 WorkSource worksource = new WorkSource();
1781 ProviderRequest providerRequest = new ProviderRequest();
1782
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001783 ContentResolver resolver = mContext.getContentResolver();
1784 long backgroundThrottleInterval = Settings.Global.getLong(
1785 resolver,
1786 Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
1787 DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
gomo48f1a642017-11-10 20:35:46 -08001788 // initialize the low power mode to true and set to false if any of the records requires
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001789
gomo48f1a642017-11-10 20:35:46 -08001790 providerRequest.lowPowerMode = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001791 if (records != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001792 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001793 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
David Christieb870dbf2015-06-22 12:42:53 -07001794 if (checkLocationAccess(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001795 record.mReceiver.mIdentity.mPid,
1796 record.mReceiver.mIdentity.mUid,
1797 record.mReceiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001798 record.mReceiver.mAllowedResolutionLevel)) {
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001799 LocationRequest locationRequest = record.mRealRequest;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001800 long interval = locationRequest.getInterval();
1801
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001802 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001803 if (!record.mIsForegroundUid) {
1804 interval = Math.max(interval, backgroundThrottleInterval);
1805 }
1806 if (interval != locationRequest.getInterval()) {
1807 locationRequest = new LocationRequest(locationRequest);
1808 locationRequest.setInterval(interval);
1809 }
1810 }
1811
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001812 record.mRequest = locationRequest;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001813 providerRequest.locationRequests.add(locationRequest);
gomo48f1a642017-11-10 20:35:46 -08001814 if (!locationRequest.isLowPowerMode()) {
1815 providerRequest.lowPowerMode = false;
1816 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001817 if (interval < providerRequest.interval) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001818 providerRequest.reportLocation = true;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001819 providerRequest.interval = interval;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001820 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001821 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001822 }
1823 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001824
1825 if (providerRequest.reportLocation) {
1826 // calculate who to blame for power
1827 // This is somewhat arbitrary. We pick a threshold interval
1828 // that is slightly higher that the minimum interval, and
1829 // spread the blame across all applications with a request
1830 // under that threshold.
1831 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
1832 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001833 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001834 LocationRequest locationRequest = record.mRequest;
Svet Ganove998c732016-06-10 00:12:38 -07001835
1836 // Don't assign battery blame for update records whose
1837 // client has no permission to receive location data.
1838 if (!providerRequest.locationRequests.contains(locationRequest)) {
1839 continue;
1840 }
1841
Victoria Leaseb711d572012-10-02 13:14:11 -07001842 if (locationRequest.getInterval() <= thresholdInterval) {
David Christiee55c9682013-08-22 10:10:34 -07001843 if (record.mReceiver.mWorkSource != null
Narayan Kamath32684dd2018-01-08 17:32:51 +00001844 && isValidWorkSource(record.mReceiver.mWorkSource)) {
David Christie82edc9b2013-07-19 11:31:42 -07001845 worksource.add(record.mReceiver.mWorkSource);
1846 } else {
Narayan Kamath32684dd2018-01-08 17:32:51 +00001847 // Assign blame to caller if there's no WorkSource associated with
1848 // the request or if it's invalid.
David Christie82edc9b2013-07-19 11:31:42 -07001849 worksource.add(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001850 record.mReceiver.mIdentity.mUid,
1851 record.mReceiver.mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001852 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001853 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001854 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 }
1857 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001858
1859 if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
1860 p.setRequest(providerRequest, worksource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001861 }
1862
Narayan Kamath32684dd2018-01-08 17:32:51 +00001863 /**
1864 * Whether a given {@code WorkSource} associated with a Location request is valid.
1865 */
1866 private static boolean isValidWorkSource(WorkSource workSource) {
1867 if (workSource.size() > 0) {
1868 // If the WorkSource has one or more non-chained UIDs, make sure they're accompanied
1869 // by tags.
1870 return workSource.getName(0) != null;
1871 } else {
1872 // For now, make sure callers have supplied an attribution tag for use with
1873 // AppOpsManager. This might be relaxed in the future.
1874 final ArrayList<WorkChain> workChains = workSource.getWorkChains();
1875 return workChains != null && !workChains.isEmpty() &&
1876 workChains.get(0).getAttributionTag() != null;
1877 }
1878 }
1879
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001880 @Override
1881 public String[] getBackgroundThrottlingWhitelist() {
1882 synchronized (mLock) {
1883 return mBackgroundThrottlePackageWhitelist.toArray(
gomo48f1a642017-11-10 20:35:46 -08001884 new String[mBackgroundThrottlePackageWhitelist.size()]);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001885 }
1886 }
1887
1888 private void updateBackgroundThrottlingWhitelistLocked() {
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001889 String setting = Settings.Global.getString(
gomo48f1a642017-11-10 20:35:46 -08001890 mContext.getContentResolver(),
1891 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001892 if (setting == null) {
1893 setting = "";
1894 }
1895
1896 mBackgroundThrottlePackageWhitelist.clear();
1897 mBackgroundThrottlePackageWhitelist.addAll(
gomo48f1a642017-11-10 20:35:46 -08001898 SystemConfig.getInstance().getAllowUnthrottledLocation());
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001899 mBackgroundThrottlePackageWhitelist.addAll(
gomo48f1a642017-11-10 20:35:46 -08001900 Arrays.asList(setting.split(",")));
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001901 }
1902
Wei Wangdd070f22018-06-21 11:29:40 -07001903 private void updateLastLocationMaxAgeLocked() {
1904 mLastLocationMaxAgeMs =
1905 Settings.Global.getLong(
1906 mContext.getContentResolver(),
1907 Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
1908 DEFAULT_LAST_LOCATION_MAX_AGE_MS);
1909 }
1910
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001911 private boolean isThrottlingExemptLocked(Identity identity) {
1912 if (identity.mUid == Process.SYSTEM_UID) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001913 return true;
1914 }
1915
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001916 if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001917 return true;
1918 }
1919
1920 for (LocationProviderProxy provider : mProxyProviders) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001921 if (identity.mPackageName.equals(provider.getConnectedPackageName())) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001922 return true;
1923 }
1924 }
1925
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001926 return false;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001927 }
1928
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001929 private class UpdateRecord {
1930 final String mProvider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001931 final LocationRequest mRealRequest; // original request from client
1932 LocationRequest mRequest; // possibly throttled version of the request
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001933 final Receiver mReceiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001934 boolean mIsForegroundUid;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001935 Location mLastFixBroadcast;
1936 long mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937
1938 /**
1939 * Note: must be constructed with lock held.
1940 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001941 UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001942 mProvider = provider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001943 mRealRequest = request;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001944 mRequest = request;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001945 mReceiver = receiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001946 mIsForegroundUid = isImportanceForeground(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001947 mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001948
1949 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1950 if (records == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001951 records = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001952 mRecordsByProvider.put(provider, records);
1953 }
1954 if (!records.contains(this)) {
1955 records.add(this);
1956 }
David Christie2ff96af2014-01-30 16:09:37 -08001957
1958 // Update statistics for historical location requests by package/provider
1959 mRequestStatistics.startRequesting(
Wyatt Rileyf7075e02018-04-12 17:54:26 -07001960 mReceiver.mIdentity.mPackageName, provider, request.getInterval(),
1961 mIsForegroundUid);
1962 }
1963
1964 /**
1965 * Method to be called when record changes foreground/background
1966 */
1967 void updateForeground(boolean isForeground){
1968 mIsForegroundUid = isForeground;
1969 mRequestStatistics.updateForeground(
1970 mReceiver.mIdentity.mPackageName, mProvider, isForeground);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001971 }
1972
1973 /**
David Christie2ff96af2014-01-30 16:09:37 -08001974 * Method to be called when a record will no longer be used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001975 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001976 void disposeLocked(boolean removeReceiver) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001977 mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider);
David Christie2ff96af2014-01-30 16:09:37 -08001978
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001979 // remove from mRecordsByProvider
1980 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
1981 if (globalRecords != null) {
1982 globalRecords.remove(this);
1983 }
1984
1985 if (!removeReceiver) return; // the caller will handle the rest
1986
1987 // remove from Receiver#mUpdateRecords
1988 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
1989 if (receiverRecords != null) {
1990 receiverRecords.remove(this.mProvider);
1991
1992 // and also remove the Receiver if it has no more update records
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001993 if (receiverRecords.size() == 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001994 removeUpdatesLocked(mReceiver);
1995 }
Mike Lockwood3a76fd62009-09-01 07:26:56 -04001996 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001997 }
1998
1999 @Override
2000 public String toString() {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002001 return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
gomo48f1a642017-11-10 20:35:46 -08002002 + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground"
2003 : " background")
Wyatt Riley19adc022018-05-22 13:30:51 -07002004 + ")" + " " + mRealRequest + " "
2005 + mReceiver.mWorkSource + "]";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002006 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002007 }
2008
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002009 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -07002010 String packageName, WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002011 IBinder binder = listener.asBinder();
2012 Receiver receiver = mReceivers.get(binder);
2013 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07002014 receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
2015 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002016 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002017 receiver.getListener().asBinder().linkToDeath(receiver, 0);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002018 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002019 Slog.e(TAG, "linkToDeath failed:", e);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002020 return null;
2021 }
Wen Jingcb3ab222014-03-27 13:42:59 +08002022 mReceivers.put(binder, receiver);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002023 }
2024 return receiver;
2025 }
2026
David Christie82edc9b2013-07-19 11:31:42 -07002027 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
David Christie40e57822013-07-30 11:36:48 -07002028 WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002029 Receiver receiver = mReceivers.get(intent);
2030 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07002031 receiver = new Receiver(null, intent, pid, uid, packageName, workSource,
2032 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002033 mReceivers.put(intent, receiver);
2034 }
2035 return receiver;
2036 }
2037
Victoria Lease37425c32012-10-16 16:08:48 -07002038 /**
2039 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
2040 * and consistency requirements.
2041 *
2042 * @param request the LocationRequest from which to create a sanitized version
Victoria Lease37425c32012-10-16 16:08:48 -07002043 * @return a version of request that meets the given resolution and consistency requirements
2044 * @hide
2045 */
gomo48f1a642017-11-10 20:35:46 -08002046 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel,
2047 boolean callerHasLocationHardwarePermission) {
Victoria Lease37425c32012-10-16 16:08:48 -07002048 LocationRequest sanitizedRequest = new LocationRequest(request);
gomo48f1a642017-11-10 20:35:46 -08002049 if (!callerHasLocationHardwarePermission) {
2050 // allow setting low power mode only for callers with location hardware permission
2051 sanitizedRequest.setLowPowerMode(false);
2052 }
Victoria Lease37425c32012-10-16 16:08:48 -07002053 if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
2054 switch (sanitizedRequest.getQuality()) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002055 case LocationRequest.ACCURACY_FINE:
Victoria Lease37425c32012-10-16 16:08:48 -07002056 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
Victoria Lease09016ab2012-09-16 12:33:15 -07002057 break;
2058 case LocationRequest.POWER_HIGH:
Victoria Lease37425c32012-10-16 16:08:48 -07002059 sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
Victoria Lease09016ab2012-09-16 12:33:15 -07002060 break;
2061 }
2062 // throttle
Victoria Lease37425c32012-10-16 16:08:48 -07002063 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
2064 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07002065 }
Victoria Lease37425c32012-10-16 16:08:48 -07002066 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
2067 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07002068 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07002069 }
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002070 // make getFastestInterval() the minimum of interval and fastest interval
Victoria Lease37425c32012-10-16 16:08:48 -07002071 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002072 request.setFastestInterval(request.getInterval());
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002073 }
Victoria Lease37425c32012-10-16 16:08:48 -07002074 return sanitizedRequest;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002075 }
2076
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002077 private void checkPackageName(String packageName) {
Nick Pellye0fd6932012-07-11 10:26:13 -07002078 if (packageName == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002079 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002080 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002081 int uid = Binder.getCallingUid();
Nick Pellye0fd6932012-07-11 10:26:13 -07002082 String[] packages = mPackageManager.getPackagesForUid(uid);
2083 if (packages == null) {
2084 throw new SecurityException("invalid UID " + uid);
2085 }
2086 for (String pkg : packages) {
2087 if (packageName.equals(pkg)) return;
2088 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002089 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002090 }
2091
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002092 private void checkPendingIntent(PendingIntent intent) {
2093 if (intent == null) {
2094 throw new IllegalArgumentException("invalid pending intent: " + intent);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002095 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002096 }
2097
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002098 private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent,
David Christie40e57822013-07-30 11:36:48 -07002099 int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002100 if (intent == null && listener == null) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002101 throw new IllegalArgumentException("need either listener or intent");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002102 } else if (intent != null && listener != null) {
2103 throw new IllegalArgumentException("cannot register both listener and intent");
2104 } else if (intent != null) {
2105 checkPendingIntent(intent);
David Christie40e57822013-07-30 11:36:48 -07002106 return getReceiverLocked(intent, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002107 } else {
David Christie40e57822013-07-30 11:36:48 -07002108 return getReceiverLocked(listener, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002109 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002110 }
2111
Nick Pellye0fd6932012-07-11 10:26:13 -07002112 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002113 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
2114 PendingIntent intent, String packageName) {
2115 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2116 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002117 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2118 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2119 request.getProvider());
David Christie82edc9b2013-07-19 11:31:42 -07002120 WorkSource workSource = request.getWorkSource();
Narayan Kamath32684dd2018-01-08 17:32:51 +00002121 if (workSource != null && !workSource.isEmpty()) {
David Christie40e57822013-07-30 11:36:48 -07002122 checkDeviceStatsAllowed();
2123 }
2124 boolean hideFromAppOps = request.getHideFromAppOps();
2125 if (hideFromAppOps) {
2126 checkUpdateAppOpsAllowed();
David Christie82edc9b2013-07-19 11:31:42 -07002127 }
gomo48f1a642017-11-10 20:35:46 -08002128 boolean callerHasLocationHardwarePermission =
2129 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
Maggieaa080f92018-01-04 15:35:11 -08002130 == PERMISSION_GRANTED;
gomo48f1a642017-11-10 20:35:46 -08002131 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel,
2132 callerHasLocationHardwarePermission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002133
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002134 final int pid = Binder.getCallingPid();
2135 final int uid = Binder.getCallingUid();
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002136 // providers may use public location API's, need to clear identity
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002137 long identity = Binder.clearCallingIdentity();
2138 try {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002139 // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2140 // a location.
David Christieb870dbf2015-06-22 12:42:53 -07002141 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002142
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002143 synchronized (mLock) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002144 Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
David Christie40e57822013-07-30 11:36:48 -07002145 packageName, workSource, hideFromAppOps);
Victoria Lease37425c32012-10-16 16:08:48 -07002146 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
Mike Lockwood2d4d1bf2010-10-18 17:06:26 -04002147 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002148 } finally {
2149 Binder.restoreCallingIdentity(identity);
2150 }
2151 }
2152
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002153 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
2154 int pid, int uid, String packageName) {
2155 // Figure out the provider. Either its explicitly request (legacy use cases), or
2156 // use the fused provider
2157 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2158 String name = request.getProvider();
Victoria Lease09016ab2012-09-16 12:33:15 -07002159 if (name == null) {
2160 throw new IllegalArgumentException("provider name must not be null");
2161 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -07002162
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002163 LocationProviderInterface provider = mProvidersByName.get(name);
2164 if (provider == null) {
Victoria Leaseb30f3832013-10-13 12:15:40 -07002165 throw new IllegalArgumentException("provider doesn't exist: " + name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002166 }
2167
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002168 UpdateRecord record = new UpdateRecord(name, request, receiver);
gomo48f1a642017-11-10 20:35:46 -08002169 if (D) {
2170 Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
2171 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
2172 + (record.mIsForegroundUid ? "foreground" : "background")
2173 + (isThrottlingExemptLocked(receiver.mIdentity)
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002174 ? " [whitelisted]" : "") + ")");
gomo48f1a642017-11-10 20:35:46 -08002175 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002176
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002177 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
2178 if (oldRecord != null) {
2179 oldRecord.disposeLocked(false);
2180 }
2181
Maggie2a9409e2018-03-21 11:47:28 -07002182 boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid, mCurrentUserId);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002183 if (isProviderEnabled) {
2184 applyRequirementsLocked(name);
2185 } else {
2186 // Notify the listener that updates are currently disabled
2187 receiver.callProviderEnabledLocked(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188 }
David Christie0b837452013-07-29 16:02:13 -07002189 // Update the monitoring here just in case multiple location requests were added to the
2190 // same receiver (this request may be high power and the initial might not have been).
2191 receiver.updateMonitoring(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192 }
2193
Nick Pellye0fd6932012-07-11 10:26:13 -07002194 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002195 public void removeUpdates(ILocationListener listener, PendingIntent intent,
2196 String packageName) {
2197 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002198
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002199 final int pid = Binder.getCallingPid();
2200 final int uid = Binder.getCallingUid();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002201
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002202 synchronized (mLock) {
David Christie82edc9b2013-07-19 11:31:42 -07002203 WorkSource workSource = null;
David Christie40e57822013-07-30 11:36:48 -07002204 boolean hideFromAppOps = false;
2205 Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid,
2206 packageName, workSource, hideFromAppOps);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002207
2208 // providers may use public location API's, need to clear identity
2209 long identity = Binder.clearCallingIdentity();
2210 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002211 removeUpdatesLocked(receiver);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002212 } finally {
2213 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002214 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002215 }
2216 }
2217
2218 private void removeUpdatesLocked(Receiver receiver) {
Dianne Hackborn7ff30112012-11-08 11:12:09 -08002219 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002220
2221 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
2222 receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
2223 synchronized (receiver) {
Victoria Lease0aa28602013-05-29 15:28:26 -07002224 receiver.clearPendingBroadcastsLocked();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002225 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002226 }
2227
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07002228 receiver.updateMonitoring(false);
2229
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002230 // Record which providers were associated with this listener
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002231 HashSet<String> providers = new HashSet<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002232 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2233 if (oldRecords != null) {
2234 // Call dispose() on the obsolete update records.
2235 for (UpdateRecord record : oldRecords.values()) {
David Christie2ff96af2014-01-30 16:09:37 -08002236 // Update statistics for historical location requests by package/provider
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002237 record.disposeLocked(false);
2238 }
2239 // Accumulate providers
2240 providers.addAll(oldRecords.keySet());
2241 }
2242
2243 // update provider
2244 for (String provider : providers) {
2245 // If provider is already disabled, don't need to do anything
Victoria Lease09eeaec2013-02-05 11:34:13 -08002246 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002247 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002248 }
2249
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002250 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002251 }
2252 }
2253
Dianne Hackbornc2293022013-02-06 23:14:49 -08002254 private void applyAllProviderRequirementsLocked() {
2255 for (LocationProviderInterface p : mProviders) {
2256 // If provider is already disabled, don't need to do anything
Dianne Hackborn64d41d72013-02-07 00:33:31 -08002257 if (!isAllowedByCurrentUserSettingsLocked(p.getName())) {
Dianne Hackbornc2293022013-02-06 23:14:49 -08002258 continue;
2259 }
2260
2261 applyRequirementsLocked(p.getName());
2262 }
2263 }
2264
Nick Pellye0fd6932012-07-11 10:26:13 -07002265 @Override
Nick Pelly4035f5a2012-08-17 14:43:49 -07002266 public Location getLastLocation(LocationRequest request, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002267 if (D) Log.d(TAG, "getLastLocation: " + request);
2268 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002269 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly4035f5a2012-08-17 14:43:49 -07002270 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002271 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2272 request.getProvider());
2273 // no need to sanitize this request, as only the provider name is used
Nick Pelly4035f5a2012-08-17 14:43:49 -07002274
David Christieb870dbf2015-06-22 12:42:53 -07002275 final int pid = Binder.getCallingPid();
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002276 final int uid = Binder.getCallingUid();
2277 final long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07002278 try {
2279 if (mBlacklist.isBlacklisted(packageName)) {
gomo48f1a642017-11-10 20:35:46 -08002280 if (D) {
2281 Log.d(TAG, "not returning last loc for blacklisted app: " +
2282 packageName);
2283 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002284 return null;
2285 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002286
David Christieb870dbf2015-06-22 12:42:53 -07002287 if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel)) {
gomo48f1a642017-11-10 20:35:46 -08002288 if (D) {
2289 Log.d(TAG, "not returning last loc for no op app: " +
2290 packageName);
2291 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002292 return null;
2293 }
2294
Victoria Leaseb711d572012-10-02 13:14:11 -07002295 synchronized (mLock) {
2296 // Figure out the provider. Either its explicitly request (deprecated API's),
2297 // or use the fused provider
2298 String name = request.getProvider();
2299 if (name == null) name = LocationManager.FUSED_PROVIDER;
2300 LocationProviderInterface provider = mProvidersByName.get(name);
2301 if (provider == null) return null;
2302
Maggie2a9409e2018-03-21 11:47:28 -07002303 if (!isAllowedByUserSettingsLocked(name, uid, mCurrentUserId)) return null;
Victoria Leaseb711d572012-10-02 13:14:11 -07002304
David Christie1b9b7b12013-04-15 15:31:11 -07002305 Location location;
2306 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2307 // Make sure that an app with coarse permissions can't get frequent location
2308 // updates by calling LocationManager.getLastKnownLocation repeatedly.
2309 location = mLastLocationCoarseInterval.get(name);
2310 } else {
2311 location = mLastLocation.get(name);
2312 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002313 if (location == null) {
2314 return null;
2315 }
Wei Wangdd070f22018-06-21 11:29:40 -07002316
2317 // Don't return stale location to apps with foreground-only location permission.
Wei Wangb86334f2018-07-03 16:33:24 -07002318 String op = resolutionLevelToOpStr(allowedResolutionLevel);
Wei Wangdd070f22018-06-21 11:29:40 -07002319 long locationAgeMs = SystemClock.elapsedRealtime() -
2320 location.getElapsedRealtimeNanos() / NANOS_PER_MILLI;
2321 if ((locationAgeMs > mLastLocationMaxAgeMs)
2322 && (mAppOps.unsafeCheckOp(op, uid, packageName)
2323 == AppOpsManager.MODE_FOREGROUND)) {
2324 return null;
2325 }
2326
Victoria Lease37425c32012-10-16 16:08:48 -07002327 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
gomo48f1a642017-11-10 20:35:46 -08002328 Location noGPSLocation = location.getExtraLocation(
2329 Location.EXTRA_NO_GPS_LOCATION);
Victoria Leaseb711d572012-10-02 13:14:11 -07002330 if (noGPSLocation != null) {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002331 return new Location(mLocationFudger.getOrCreate(noGPSLocation));
Victoria Leaseb711d572012-10-02 13:14:11 -07002332 }
Victoria Lease37425c32012-10-16 16:08:48 -07002333 } else {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002334 return new Location(location);
Victoria Lease09016ab2012-09-16 12:33:15 -07002335 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002336 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002337 return null;
2338 } finally {
2339 Binder.restoreCallingIdentity(identity);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002340 }
2341 }
2342
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002343 /**
2344 * Provides an interface to inject and set the last location if location is not available
2345 * currently.
2346 *
2347 * This helps in cases where the product (Cars for example) has saved the last known location
2348 * before powering off. This interface lets the client inject the saved location while the GPS
2349 * chipset is getting its first fix, there by improving user experience.
2350 *
2351 * @param location - Location object to inject
2352 * @return true if update was successful, false if not
2353 */
2354 @Override
2355 public boolean injectLocation(Location location) {
2356 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
2357 "Location Hardware permission not granted to inject location");
2358 mContext.enforceCallingPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
2359 "Access Fine Location permission not granted to inject Location");
2360
2361 if (location == null) {
2362 if (D) {
2363 Log.d(TAG, "injectLocation(): called with null location");
2364 }
2365 return false;
2366 }
2367 LocationProviderInterface p = null;
2368 String provider = location.getProvider();
2369 if (provider != null) {
2370 p = mProvidersByName.get(provider);
2371 }
2372 if (p == null) {
2373 if (D) {
2374 Log.d(TAG, "injectLocation(): unknown provider");
2375 }
2376 return false;
2377 }
2378 synchronized (mLock) {
2379 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
2380 if (D) {
2381 Log.d(TAG, "Location disabled in Settings for current user:" + mCurrentUserId);
2382 }
2383 return false;
2384 } else {
2385 // NOTE: If last location is already available, location is not injected. If
2386 // provider's normal source (like a GPS chipset) have already provided an output,
2387 // there is no need to inject this location.
2388 if (mLastLocation.get(provider) == null) {
2389 updateLastLocationLocked(location, provider);
2390 } else {
2391 if (D) {
2392 Log.d(TAG, "injectLocation(): Location exists. Not updating");
2393 }
2394 return false;
2395 }
2396 }
2397 }
2398 return true;
2399 }
2400
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002401 @Override
2402 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
2403 String packageName) {
2404 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002405 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2406 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002407 checkPendingIntent(intent);
2408 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002409 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2410 request.getProvider());
gomo48f1a642017-11-10 20:35:46 -08002411 // Require that caller can manage given document
2412 boolean callerHasLocationHardwarePermission =
2413 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
Maggieaa080f92018-01-04 15:35:11 -08002414 == PERMISSION_GRANTED;
gomo48f1a642017-11-10 20:35:46 -08002415 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel,
2416 callerHasLocationHardwarePermission);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002417
Victoria Lease37425c32012-10-16 16:08:48 -07002418 if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002419
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002420 // geo-fence manager uses the public location API, need to clear identity
2421 int uid = Binder.getCallingUid();
Xiaohui Chena4490622015-09-22 15:29:31 -07002422 // TODO: http://b/23822629
2423 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
Victoria Lease56e675b2012-11-05 19:25:06 -08002424 // temporary measure until geofences work for secondary users
2425 Log.w(TAG, "proximity alerts are currently available only to the primary user");
2426 return;
2427 }
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002428 long identity = Binder.clearCallingIdentity();
2429 try {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002430 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
2431 uid, packageName);
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002432 } finally {
2433 Binder.restoreCallingIdentity(identity);
2434 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002435 }
2436
2437 @Override
2438 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002439 checkPendingIntent(intent);
2440 checkPackageName(packageName);
2441
2442 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2443
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002444 // geo-fence manager uses the public location API, need to clear identity
2445 long identity = Binder.clearCallingIdentity();
2446 try {
2447 mGeofenceManager.removeFence(geofence, intent);
2448 } finally {
2449 Binder.restoreCallingIdentity(identity);
2450 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002451 }
2452
2453
2454 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002455 public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002456 if (!hasGnssPermissions(packageName) || mGnssStatusProvider == null) {
Takayuki Hoshib254ab6a2014-10-23 16:46:02 +09002457 return false;
2458 }
2459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002460 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002461 mGnssStatusProvider.registerGnssStatusCallback(callback);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002462 } catch (RemoteException e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002463 Slog.e(TAG, "mGpsStatusProvider.registerGnssStatusCallback failed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002464 return false;
2465 }
2466 return true;
2467 }
2468
Nick Pellye0fd6932012-07-11 10:26:13 -07002469 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002470 public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002471 synchronized (mLock) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002472 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002473 mGnssStatusProvider.unregisterGnssStatusCallback(callback);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002474 } catch (Exception e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002475 Slog.e(TAG, "mGpsStatusProvider.unregisterGnssStatusCallback failed", e);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002476 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002477 }
2478 }
2479
Nick Pellye0fd6932012-07-11 10:26:13 -07002480 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002481 public boolean addGnssMeasurementsListener(
gomo48f1a642017-11-10 20:35:46 -08002482 IGnssMeasurementsListener listener, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002483 if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
destradaaea8a8a62014-06-23 18:19:03 -07002484 return false;
2485 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002486
2487 synchronized (mLock) {
2488 Identity callerIdentity
2489 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
Wyatt Riley11cc7492018-01-17 08:48:27 -08002490 mGnssMeasurementsListeners.put(listener.asBinder(), callerIdentity);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002491 long identity = Binder.clearCallingIdentity();
2492 try {
2493 if (isThrottlingExemptLocked(callerIdentity)
2494 || isImportanceForeground(
gomo48f1a642017-11-10 20:35:46 -08002495 mActivityManager.getPackageImportance(packageName))) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002496 return mGnssMeasurementsProvider.addListener(listener);
2497 }
2498 } finally {
2499 Binder.restoreCallingIdentity(identity);
2500 }
2501
2502 return true;
2503 }
destradaaea8a8a62014-06-23 18:19:03 -07002504 }
2505
2506 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002507 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
2508 if (mGnssMeasurementsProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002509 synchronized (mLock) {
Wyatt Riley11cc7492018-01-17 08:48:27 -08002510 mGnssMeasurementsListeners.remove(listener.asBinder());
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002511 mGnssMeasurementsProvider.removeListener(listener);
2512 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002513 }
destradaaea8a8a62014-06-23 18:19:03 -07002514 }
2515
2516 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002517 public boolean addGnssNavigationMessageListener(
2518 IGnssNavigationMessageListener listener,
destradaa4b3e3932014-07-21 18:01:47 -07002519 String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002520 if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) {
destradaa4b3e3932014-07-21 18:01:47 -07002521 return false;
2522 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002523
2524 synchronized (mLock) {
2525 Identity callerIdentity
gomo48f1a642017-11-10 20:35:46 -08002526 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
Wyatt Riley11cc7492018-01-17 08:48:27 -08002527 mGnssNavigationMessageListeners.put(listener.asBinder(), callerIdentity);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002528 long identity = Binder.clearCallingIdentity();
2529 try {
2530 if (isThrottlingExemptLocked(callerIdentity)
2531 || isImportanceForeground(
gomo48f1a642017-11-10 20:35:46 -08002532 mActivityManager.getPackageImportance(packageName))) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002533 return mGnssNavigationMessageProvider.addListener(listener);
2534 }
2535 } finally {
2536 Binder.restoreCallingIdentity(identity);
2537 }
2538
2539 return true;
2540 }
destradaa4b3e3932014-07-21 18:01:47 -07002541 }
2542
2543 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002544 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
2545 if (mGnssNavigationMessageProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002546 synchronized (mLock) {
Wyatt Riley11cc7492018-01-17 08:48:27 -08002547 mGnssNavigationMessageListeners.remove(listener.asBinder());
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002548 mGnssNavigationMessageProvider.removeListener(listener);
2549 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002550 }
destradaa4b3e3932014-07-21 18:01:47 -07002551 }
2552
2553 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002554 public boolean sendExtraCommand(String provider, String command, Bundle extras) {
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002555 if (provider == null) {
2556 // throw NullPointerException to remain compatible with previous implementation
2557 throw new NullPointerException();
2558 }
Victoria Lease37425c32012-10-16 16:08:48 -07002559 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2560 provider);
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002562 // and check for ACCESS_LOCATION_EXTRA_COMMANDS
Mike Lockwoodb7e99222009-07-07 13:18:21 -04002563 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
Maggieaa080f92018-01-04 15:35:11 -08002564 != PERMISSION_GRANTED)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002565 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
2566 }
2567
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002568 synchronized (mLock) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002569 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002570 if (p == null) return false;
Nick Pellye0fd6932012-07-11 10:26:13 -07002571
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002572 return p.sendExtraCommand(command, extras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002573 }
2574 }
2575
Nick Pellye0fd6932012-07-11 10:26:13 -07002576 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002577 public boolean sendNiResponse(int notifId, int userResponse) {
Mike Lockwood18ad9f62009-08-27 14:01:23 -07002578 if (Binder.getCallingUid() != Process.myUid()) {
2579 throw new SecurityException(
2580 "calling sendNiResponse from outside of the system is not allowed");
2581 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002582 try {
2583 return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002584 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002585 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
Danke Xie22d1f9f2009-08-18 18:28:45 -04002586 return false;
2587 }
2588 }
2589
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002590 /**
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002591 * @return null if the provider does not exist
Alexey Tarasovf2db9fb2009-09-01 02:37:07 +11002592 * @throws SecurityException if the provider is not allowed to be
gomo48f1a642017-11-10 20:35:46 -08002593 * accessed by the caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002594 */
Nick Pellye0fd6932012-07-11 10:26:13 -07002595 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002596 public ProviderProperties getProviderProperties(String provider) {
Laurent Tub7f9d252012-10-16 14:25:00 -07002597 if (mProvidersByName.get(provider) == null) {
David Christie2ff96af2014-01-30 16:09:37 -08002598 return null;
Laurent Tub7f9d252012-10-16 14:25:00 -07002599 }
2600
Victoria Lease37425c32012-10-16 16:08:48 -07002601 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2602 provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002603
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002604 LocationProviderInterface p;
2605 synchronized (mLock) {
2606 p = mProvidersByName.get(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002607 }
2608
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002609 if (p == null) return null;
2610 return p.getProperties();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002611 }
2612
Jason Monkb71218a2015-06-17 14:44:39 -04002613 /**
2614 * @return null if the provider does not exist
2615 * @throws SecurityException if the provider is not allowed to be
gomo48f1a642017-11-10 20:35:46 -08002616 * accessed by the caller
Jason Monkb71218a2015-06-17 14:44:39 -04002617 */
2618 @Override
2619 public String getNetworkProviderPackage() {
2620 LocationProviderInterface p;
2621 synchronized (mLock) {
2622 if (mProvidersByName.get(LocationManager.NETWORK_PROVIDER) == null) {
2623 return null;
2624 }
2625 p = mProvidersByName.get(LocationManager.NETWORK_PROVIDER);
2626 }
2627
2628 if (p instanceof LocationProviderProxy) {
2629 return ((LocationProviderProxy) p).getConnectedPackageName();
2630 }
2631 return null;
2632 }
2633
Maggieaa080f92018-01-04 15:35:11 -08002634 /**
Maggie2a9409e2018-03-21 11:47:28 -07002635 * Returns the current location enabled/disabled status for a user
2636 *
2637 * @param userId the id of the user
2638 * @return true if location is enabled
2639 */
2640 @Override
2641 public boolean isLocationEnabledForUser(int userId) {
2642 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2643 checkInteractAcrossUsersPermission(userId);
2644
2645 long identity = Binder.clearCallingIdentity();
2646 try {
2647 synchronized (mLock) {
2648 final String allowedProviders = Settings.Secure.getStringForUser(
2649 mContext.getContentResolver(),
2650 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
2651 userId);
2652 if (allowedProviders == null) {
2653 return false;
2654 }
2655 final List<String> providerList = Arrays.asList(allowedProviders.split(","));
2656 for(String provider : mRealProviders.keySet()) {
2657 if (provider.equals(LocationManager.PASSIVE_PROVIDER)
2658 || provider.equals(LocationManager.FUSED_PROVIDER)) {
2659 continue;
2660 }
2661 if (providerList.contains(provider)) {
2662 return true;
2663 }
2664 }
2665 return false;
2666 }
2667 } finally {
2668 Binder.restoreCallingIdentity(identity);
2669 }
2670 }
2671
2672 /**
2673 * Enable or disable location for a user
2674 *
2675 * @param enabled true to enable location, false to disable location
2676 * @param userId the id of the user
2677 */
2678 @Override
2679 public void setLocationEnabledForUser(boolean enabled, int userId) {
2680 mContext.enforceCallingPermission(
2681 android.Manifest.permission.WRITE_SECURE_SETTINGS,
2682 "Requires WRITE_SECURE_SETTINGS permission");
2683
2684 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2685 checkInteractAcrossUsersPermission(userId);
2686
2687 long identity = Binder.clearCallingIdentity();
2688 try {
2689 synchronized (mLock) {
2690 final Set<String> allRealProviders = mRealProviders.keySet();
2691 // Update all providers on device plus gps and network provider when disabling
2692 // location
2693 Set<String> allProvidersSet = new ArraySet<>(allRealProviders.size() + 2);
2694 allProvidersSet.addAll(allRealProviders);
2695 // When disabling location, disable gps and network provider that could have been
2696 // enabled by location mode api.
2697 if (enabled == false) {
2698 allProvidersSet.add(LocationManager.GPS_PROVIDER);
2699 allProvidersSet.add(LocationManager.NETWORK_PROVIDER);
2700 }
2701 if (allProvidersSet.isEmpty()) {
2702 return;
2703 }
2704 // to ensure thread safety, we write the provider name with a '+' or '-'
2705 // and let the SettingsProvider handle it rather than reading and modifying
2706 // the list of enabled providers.
2707 final String prefix = enabled ? "+" : "-";
2708 StringBuilder locationProvidersAllowed = new StringBuilder();
2709 for (String provider : allProvidersSet) {
2710 if (provider.equals(LocationManager.PASSIVE_PROVIDER)
2711 || provider.equals(LocationManager.FUSED_PROVIDER)) {
2712 continue;
2713 }
2714 locationProvidersAllowed.append(prefix);
2715 locationProvidersAllowed.append(provider);
2716 locationProvidersAllowed.append(",");
2717 }
2718 // Remove the trailing comma
2719 locationProvidersAllowed.setLength(locationProvidersAllowed.length() - 1);
2720 Settings.Secure.putStringForUser(
2721 mContext.getContentResolver(),
2722 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
2723 locationProvidersAllowed.toString(),
2724 userId);
2725 }
2726 } finally {
2727 Binder.restoreCallingIdentity(identity);
2728 }
2729 }
2730
2731 /**
2732 * Returns the current enabled/disabled status of a location provider and user
2733 *
2734 * @param provider name of the provider
2735 * @param userId the id of the user
2736 * @return true if the provider exists and is enabled
2737 */
2738 @Override
2739 public boolean isProviderEnabledForUser(String provider, int userId) {
2740 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2741 checkInteractAcrossUsersPermission(userId);
2742
2743 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2744 // so we discourage its use
2745 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
2746
2747 int uid = Binder.getCallingUid();
2748 synchronized (mLock) {
2749 LocationProviderInterface p = mProvidersByName.get(provider);
2750 return p != null
2751 && isAllowedByUserSettingsLocked(provider, uid, userId);
2752 }
2753 }
2754
2755 /**
2756 * Enable or disable a single location provider.
2757 *
2758 * @param provider name of the provider
2759 * @param enabled true to enable the provider. False to disable the provider
2760 * @param userId the id of the user to set
2761 * @return true if the value was set, false on errors
2762 */
2763 @Override
2764 public boolean setProviderEnabledForUser(String provider, boolean enabled, int userId) {
2765 mContext.enforceCallingPermission(
2766 android.Manifest.permission.WRITE_SECURE_SETTINGS,
2767 "Requires WRITE_SECURE_SETTINGS permission");
2768
2769 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2770 checkInteractAcrossUsersPermission(userId);
2771
2772 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2773 // so we discourage its use
2774 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
2775
2776 long identity = Binder.clearCallingIdentity();
2777 try {
2778 synchronized (mLock) {
2779 // No such provider exists
2780 if (!mProvidersByName.containsKey(provider)) return false;
2781
2782 // If it is a test provider, do not write to Settings.Secure
2783 if (mMockProviders.containsKey(provider)) {
2784 setTestProviderEnabled(provider, enabled);
2785 return true;
2786 }
2787
2788 // to ensure thread safety, we write the provider name with a '+' or '-'
2789 // and let the SettingsProvider handle it rather than reading and modifying
2790 // the list of enabled providers.
2791 String providerChange = (enabled ? "+" : "-") + provider;
2792 return Settings.Secure.putStringForUser(
2793 mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
2794 providerChange, userId);
2795 }
2796 } finally {
2797 Binder.restoreCallingIdentity(identity);
2798 }
2799 }
2800
2801 /**
Maggieaa080f92018-01-04 15:35:11 -08002802 * Read location provider status from Settings.Secure
2803 *
2804 * @param provider the location provider to query
2805 * @param userId the user id to query
2806 * @return true if the provider is enabled
2807 */
2808 private boolean isLocationProviderEnabledForUser(String provider, int userId) {
2809 long identity = Binder.clearCallingIdentity();
2810 try {
2811 // Use system settings
2812 ContentResolver cr = mContext.getContentResolver();
2813 String allowedProviders = Settings.Secure.getStringForUser(
2814 cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userId);
2815 return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
2816 } finally {
2817 Binder.restoreCallingIdentity(identity);
2818 }
2819 }
2820
2821 /**
Maggie2a9409e2018-03-21 11:47:28 -07002822 * Method for checking INTERACT_ACROSS_USERS permission if specified user id is not the same as
2823 * current user id
2824 *
2825 * @param userId the user id to get or set value
2826 */
2827 private void checkInteractAcrossUsersPermission(int userId) {
2828 int uid = Binder.getCallingUid();
2829 if (UserHandle.getUserId(uid) != userId) {
2830 if (ActivityManager.checkComponentPermission(
2831 android.Manifest.permission.INTERACT_ACROSS_USERS, uid, -1, true)
2832 != PERMISSION_GRANTED) {
2833 throw new SecurityException("Requires INTERACT_ACROSS_USERS permission");
2834 }
2835 }
2836 }
2837
2838 /**
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002839 * Returns "true" if the UID belongs to a bound location provider.
2840 *
2841 * @param uid the uid
2842 * @return true if uid belongs to a bound location provider
2843 */
2844 private boolean isUidALocationProvider(int uid) {
2845 if (uid == Process.SYSTEM_UID) {
2846 return true;
2847 }
2848 if (mGeocodeProvider != null) {
David Christie1f141c12014-05-14 15:11:15 -07002849 if (doesUidHavePackage(uid, mGeocodeProvider.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002850 }
2851 for (LocationProviderProxy proxy : mProxyProviders) {
David Christie1f141c12014-05-14 15:11:15 -07002852 if (doesUidHavePackage(uid, proxy.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002853 }
2854 return false;
2855 }
2856
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002857 private void checkCallerIsProvider() {
2858 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
Maggieaa080f92018-01-04 15:35:11 -08002859 == PERMISSION_GRANTED) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002860 return;
2861 }
2862
2863 // Previously we only used the INSTALL_LOCATION_PROVIDER
2864 // check. But that is system or signature
2865 // protection level which is not flexible enough for
2866 // providers installed oustide the system image. So
2867 // also allow providers with a UID matching the
2868 // currently bound package name
2869
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002870 if (isUidALocationProvider(Binder.getCallingUid())) {
2871 return;
2872 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002873
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002874 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
2875 "or UID of a currently bound location provider");
2876 }
2877
David Christie1f141c12014-05-14 15:11:15 -07002878 /**
2879 * Returns true if the given package belongs to the given uid.
2880 */
2881 private boolean doesUidHavePackage(int uid, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002882 if (packageName == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002883 return false;
2884 }
David Christie1f141c12014-05-14 15:11:15 -07002885 String[] packageNames = mPackageManager.getPackagesForUid(uid);
2886 if (packageNames == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002887 return false;
2888 }
David Christie1f141c12014-05-14 15:11:15 -07002889 for (String name : packageNames) {
2890 if (packageName.equals(name)) {
2891 return true;
2892 }
2893 }
2894 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002895 }
2896
Nick Pellye0fd6932012-07-11 10:26:13 -07002897 @Override
Mike Lockwooda4903f22010-02-17 06:42:23 -05002898 public void reportLocation(Location location, boolean passive) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002899 checkCallerIsProvider();
Mike Lockwood275555c2009-05-01 11:30:34 -04002900
Nick Pelly2eeeec22012-07-18 13:13:37 -07002901 if (!location.isComplete()) {
2902 Log.w(TAG, "Dropping incomplete location: " + location);
2903 return;
2904 }
2905
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002906 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location);
2907 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location);
Mike Lockwooda4903f22010-02-17 06:42:23 -05002908 m.arg1 = (passive ? 1 : 0);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002909 mLocationHandler.sendMessageAtFrontOfQueue(m);
2910 }
2911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002912
Laurent Tu75defb62012-11-01 16:21:52 -07002913 private static boolean shouldBroadcastSafe(
2914 Location loc, Location lastLoc, UpdateRecord record, long now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002915 // Always broadcast the first update
2916 if (lastLoc == null) {
2917 return true;
2918 }
2919
Nick Pellyf1be6862012-05-15 10:53:42 -07002920 // Check whether sufficient time has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002921 long minTime = record.mRealRequest.getFastestInterval();
David Christie1b9b7b12013-04-15 15:31:11 -07002922 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
2923 / NANOS_PER_MILLI;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002924 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002925 return false;
2926 }
2927
2928 // Check whether sufficient distance has been traveled
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002929 double minDistance = record.mRealRequest.getSmallestDisplacement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002930 if (minDistance > 0.0) {
2931 if (loc.distanceTo(lastLoc) <= minDistance) {
2932 return false;
2933 }
2934 }
2935
Laurent Tu75defb62012-11-01 16:21:52 -07002936 // Check whether sufficient number of udpates is left
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002937 if (record.mRealRequest.getNumUpdates() <= 0) {
Laurent Tu75defb62012-11-01 16:21:52 -07002938 return false;
2939 }
2940
2941 // Check whether the expiry date has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002942 return record.mRealRequest.getExpireAt() >= now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002943 }
2944
Mike Lockwooda4903f22010-02-17 06:42:23 -05002945 private void handleLocationChangedLocked(Location location, boolean passive) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002946 if (D) Log.d(TAG, "incoming location: " + location);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002947 long now = SystemClock.elapsedRealtime();
Mike Lockwooda4903f22010-02-17 06:42:23 -05002948 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
Laurent Tu60ec50a2012-10-04 17:00:10 -07002949 // Skip if the provider is unknown.
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002950 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002951 if (p == null) return;
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002952 updateLastLocationLocked(location, provider);
2953 // mLastLocation should have been updated from the updateLastLocationLocked call above.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002954 Location lastLocation = mLastLocation.get(provider);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002955 if (lastLocation == null) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002956 Log.e(TAG, "handleLocationChangedLocked() updateLastLocation failed");
2957 return;
Mike Lockwood4e50b782009-04-03 08:24:43 -07002958 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002959
David Christie1b9b7b12013-04-15 15:31:11 -07002960 // Update last known coarse interval location if enough time has passed.
2961 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider);
2962 if (lastLocationCoarseInterval == null) {
2963 lastLocationCoarseInterval = new Location(location);
2964 mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval);
2965 }
2966 long timeDiffNanos = location.getElapsedRealtimeNanos()
2967 - lastLocationCoarseInterval.getElapsedRealtimeNanos();
2968 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
2969 lastLocationCoarseInterval.set(location);
2970 }
2971 // Don't ever return a coarse location that is more recent than the allowed update
2972 // interval (i.e. don't allow an app to keep registering and unregistering for
2973 // location updates to overcome the minimum interval).
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002974 Location noGPSLocation =
David Christie1b9b7b12013-04-15 15:31:11 -07002975 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2976
Laurent Tu60ec50a2012-10-04 17:00:10 -07002977 // Skip if there are no UpdateRecords for this provider.
2978 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
2979 if (records == null || records.size() == 0) return;
2980
Victoria Lease09016ab2012-09-16 12:33:15 -07002981 // Fetch coarse location
2982 Location coarseLocation = null;
David Christie1b9b7b12013-04-15 15:31:11 -07002983 if (noGPSLocation != null) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002984 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
2985 }
2986
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002987 // Fetch latest status update time
2988 long newStatusUpdateTime = p.getStatusUpdateTime();
2989
David Christie2ff96af2014-01-30 16:09:37 -08002990 // Get latest status
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002991 Bundle extras = new Bundle();
2992 int status = p.getStatus(extras);
2993
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002994 ArrayList<Receiver> deadReceivers = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002995 ArrayList<UpdateRecord> deadUpdateRecords = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07002996
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002997 // Broadcast location or status to all listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002998 for (UpdateRecord r : records) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002999 Receiver receiver = r.mReceiver;
Mike Lockwood03ca2162010-04-01 08:10:09 -07003000 boolean receiverDead = false;
Nick Pelly4035f5a2012-08-17 14:43:49 -07003001
Soonil Nagarkar681d7112017-02-23 17:14:16 -08003002 int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid);
3003 if (!isCurrentProfile(receiverUserId)
3004 && !isUidALocationProvider(receiver.mIdentity.mUid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07003005 if (D) {
Victoria Lease269518e2012-10-29 08:25:39 -07003006 Log.d(TAG, "skipping loc update for background user " + receiverUserId +
Victoria Leaseb711d572012-10-02 13:14:11 -07003007 " (current user: " + mCurrentUserId + ", app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08003008 receiver.mIdentity.mPackageName + ")");
Victoria Leaseb711d572012-10-02 13:14:11 -07003009 }
3010 continue;
3011 }
3012
Soonil Nagarkar681d7112017-02-23 17:14:16 -08003013 if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) {
gomo48f1a642017-11-10 20:35:46 -08003014 if (D) {
3015 Log.d(TAG, "skipping loc update for blacklisted app: " +
3016 receiver.mIdentity.mPackageName);
3017 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07003018 continue;
3019 }
3020
Soonil Nagarkar681d7112017-02-23 17:14:16 -08003021 if (!reportLocationAccessNoThrow(
3022 receiver.mIdentity.mPid,
3023 receiver.mIdentity.mUid,
3024 receiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08003025 receiver.mAllowedResolutionLevel)) {
gomo48f1a642017-11-10 20:35:46 -08003026 if (D) {
3027 Log.d(TAG, "skipping loc update for no op app: " +
3028 receiver.mIdentity.mPackageName);
3029 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08003030 continue;
3031 }
3032
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003033 Location notifyLocation;
Victoria Lease37425c32012-10-16 16:08:48 -07003034 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
3035 notifyLocation = coarseLocation; // use coarse location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003036 } else {
Victoria Lease37425c32012-10-16 16:08:48 -07003037 notifyLocation = lastLocation; // use fine location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003038 }
Victoria Lease09016ab2012-09-16 12:33:15 -07003039 if (notifyLocation != null) {
3040 Location lastLoc = r.mLastFixBroadcast;
Laurent Tu75defb62012-11-01 16:21:52 -07003041 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) {
Victoria Lease09016ab2012-09-16 12:33:15 -07003042 if (lastLoc == null) {
3043 lastLoc = new Location(notifyLocation);
3044 r.mLastFixBroadcast = lastLoc;
3045 } else {
3046 lastLoc.set(notifyLocation);
3047 }
3048 if (!receiver.callLocationChangedLocked(notifyLocation)) {
3049 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
3050 receiverDead = true;
3051 }
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07003052 r.mRealRequest.decrementNumUpdates();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003053 }
3054 }
3055
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003056 long prevStatusUpdateTime = r.mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003057 if ((newStatusUpdateTime > prevStatusUpdateTime) &&
Victoria Lease09016ab2012-09-16 12:33:15 -07003058 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003059
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003060 r.mLastStatusBroadcast = newStatusUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003061 if (!receiver.callStatusChangedLocked(provider, status, extras)) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07003062 receiverDead = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003063 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
Mike Lockwood03ca2162010-04-01 08:10:09 -07003064 }
3065 }
3066
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003067 // track expired records
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07003068 if (r.mRealRequest.getNumUpdates() <= 0 || r.mRealRequest.getExpireAt() < now) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003069 if (deadUpdateRecords == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003070 deadUpdateRecords = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003071 }
3072 deadUpdateRecords.add(r);
3073 }
3074 // track dead receivers
3075 if (receiverDead) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07003076 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003077 deadReceivers = new ArrayList<>();
Mike Lockwood03ca2162010-04-01 08:10:09 -07003078 }
3079 if (!deadReceivers.contains(receiver)) {
3080 deadReceivers.add(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003081 }
3082 }
3083 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003084
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003085 // remove dead records and receivers outside the loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003087 for (Receiver receiver : deadReceivers) {
3088 removeUpdatesLocked(receiver);
3089 }
3090 }
3091 if (deadUpdateRecords != null) {
3092 for (UpdateRecord r : deadUpdateRecords) {
3093 r.disposeLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003094 }
Victoria Lease8b38b292012-12-04 15:04:43 -08003095 applyRequirementsLocked(provider);
3096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003097 }
3098
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08003099 /**
3100 * Updates last location with the given location
3101 *
3102 * @param location new location to update
3103 * @param provider Location provider to update for
3104 */
3105 private void updateLastLocationLocked(Location location, String provider) {
3106 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
3107 Location lastNoGPSLocation;
3108 Location lastLocation = mLastLocation.get(provider);
3109 if (lastLocation == null) {
3110 lastLocation = new Location(provider);
3111 mLastLocation.put(provider, lastLocation);
3112 } else {
3113 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
3114 if (noGPSLocation == null && lastNoGPSLocation != null) {
3115 // New location has no no-GPS location: adopt last no-GPS location. This is set
3116 // directly into location because we do not want to notify COARSE clients.
3117 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
3118 }
3119 }
3120 lastLocation.set(location);
3121 }
3122
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003123 private class LocationWorkerHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08003124 public LocationWorkerHandler(Looper looper) {
3125 super(looper, null, true);
3126 }
3127
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003128 @Override
3129 public void handleMessage(Message msg) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003130 switch (msg.what) {
3131 case MSG_LOCATION_CHANGED:
3132 handleLocationChanged((Location) msg.obj, msg.arg1 == 1);
3133 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003134 }
3135 }
3136 }
3137
Victoria Lease54ca7ae2013-01-08 09:39:50 -08003138 private boolean isMockProvider(String provider) {
3139 synchronized (mLock) {
3140 return mMockProviders.containsKey(provider);
3141 }
3142 }
3143
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003144 private void handleLocationChanged(Location location, boolean passive) {
Victoria Lease54ca7ae2013-01-08 09:39:50 -08003145 // create a working copy of the incoming Location so that the service can modify it without
3146 // disturbing the caller's copy
3147 Location myLocation = new Location(location);
3148 String provider = myLocation.getProvider();
3149
3150 // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this
3151 // bit if location did not come from a mock provider because passive/fused providers can
3152 // forward locations from mock providers, and should not grant them legitimacy in doing so.
3153 if (!myLocation.isFromMockProvider() && isMockProvider(provider)) {
3154 myLocation.setIsFromMockProvider(true);
3155 }
Jeff Sharkey5e613312012-01-30 11:16:20 -08003156
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003157 synchronized (mLock) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08003158 if (isAllowedByCurrentUserSettingsLocked(provider)) {
3159 if (!passive) {
3160 // notify passive provider of the new location
3161 mPassiveProvider.updateLocation(myLocation);
3162 }
Victoria Lease54ca7ae2013-01-08 09:39:50 -08003163 handleLocationChangedLocked(myLocation, passive);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003164 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003165 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003166 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003167
Mike Lockwoode97ae402010-09-29 15:23:46 -04003168 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
3169 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003170 public void onPackageDisappeared(String packageName, int reason) {
3171 // remove all receivers associated with this package name
3172 synchronized (mLock) {
3173 ArrayList<Receiver> deadReceivers = null;
3174
3175 for (Receiver receiver : mReceivers.values()) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08003176 if (receiver.mIdentity.mPackageName.equals(packageName)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003177 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003178 deadReceivers = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003179 }
3180 deadReceivers.add(receiver);
3181 }
3182 }
3183
3184 // perform removal outside of mReceivers loop
3185 if (deadReceivers != null) {
3186 for (Receiver receiver : deadReceivers) {
3187 removeUpdatesLocked(receiver);
3188 }
3189 }
3190 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003191 }
Mike Lockwoode97ae402010-09-29 15:23:46 -04003192 };
3193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003194 // Geocoder
3195
Nick Pellye0fd6932012-07-11 10:26:13 -07003196 @Override
Mike Lockwoode15735a2010-09-20 17:48:47 -04003197 public boolean geocoderIsPresent() {
Mark Vandevoorde01ac80b2010-05-21 15:43:26 -07003198 return mGeocodeProvider != null;
3199 }
3200
Nick Pellye0fd6932012-07-11 10:26:13 -07003201 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003202 public String getFromLocation(double latitude, double longitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05003203 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04003204 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05003205 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
3206 params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003207 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04003208 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003209 }
3210
Mike Lockwooda55c3212009-04-15 11:10:11 -04003211
Nick Pellye0fd6932012-07-11 10:26:13 -07003212 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003213 public String getFromLocationName(String locationName,
Mike Lockwooda55c3212009-04-15 11:10:11 -04003214 double lowerLeftLatitude, double lowerLeftLongitude,
3215 double upperRightLatitude, double upperRightLongitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05003216 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04003217
3218 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05003219 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
3220 lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
3221 maxResults, params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003222 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04003223 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003224 }
3225
3226 // Mock Providers
3227
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003228 private boolean canCallerAccessMockLocation(String opPackageName) {
3229 return mAppOps.noteOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(),
3230 opPackageName) == AppOpsManager.MODE_ALLOWED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003231 }
3232
Nick Pellye0fd6932012-07-11 10:26:13 -07003233 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003234 public void addTestProvider(String name, ProviderProperties properties, String opPackageName) {
3235 if (!canCallerAccessMockLocation(opPackageName)) {
3236 return;
3237 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003238
Mike Lockwooda4903f22010-02-17 06:42:23 -05003239 if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
3240 throw new IllegalArgumentException("Cannot mock the passive location provider");
3241 }
3242
Mike Lockwood86328a92009-10-23 08:38:25 -04003243 long identity = Binder.clearCallingIdentity();
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003244 synchronized (mLock) {
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003245 // remove the real provider if we are replacing GPS or network provider
3246 if (LocationManager.GPS_PROVIDER.equals(name)
Nick Pelly1332b532012-08-21 16:25:47 -07003247 || LocationManager.NETWORK_PROVIDER.equals(name)
3248 || LocationManager.FUSED_PROVIDER.equals(name)) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05003249 LocationProviderInterface p = mProvidersByName.get(name);
3250 if (p != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003251 removeProviderLocked(p);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003252 }
3253 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09003254 addTestProviderLocked(name, properties);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003255 updateProvidersLocked();
3256 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003257 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003258 }
3259
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09003260 private void addTestProviderLocked(String name, ProviderProperties properties) {
3261 if (mProvidersByName.get(name) != null) {
3262 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
3263 }
3264 MockProvider provider = new MockProvider(name, this, properties);
3265 addProviderLocked(provider);
3266 mMockProviders.put(name, provider);
3267 mLastLocation.put(name, null);
3268 mLastLocationCoarseInterval.put(name, null);
3269 }
3270
Nick Pellye0fd6932012-07-11 10:26:13 -07003271 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003272 public void removeTestProvider(String provider, String opPackageName) {
3273 if (!canCallerAccessMockLocation(opPackageName)) {
3274 return;
3275 }
3276
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003277 synchronized (mLock) {
Tom O'Neill07ee5d12014-03-03 17:48:35 -08003278
3279 // These methods can't be called after removing the test provider, so first make sure
Tom O'Neillfe6d3c52014-03-04 08:26:17 -08003280 // we don't leave anything dangling.
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003281 clearTestProviderEnabled(provider, opPackageName);
3282 clearTestProviderLocation(provider, opPackageName);
3283 clearTestProviderStatus(provider, opPackageName);
Tom O'Neill07ee5d12014-03-03 17:48:35 -08003284
You Kima6d0b6f2012-10-28 03:58:44 +09003285 MockProvider mockProvider = mMockProviders.remove(provider);
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003286 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003287 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3288 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003289 long identity = Binder.clearCallingIdentity();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003290 removeProviderLocked(mProvidersByName.get(provider));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003291
3292 // reinstate real provider if available
3293 LocationProviderInterface realProvider = mRealProviders.get(provider);
3294 if (realProvider != null) {
3295 addProviderLocked(realProvider);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003296 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003297 mLastLocation.put(provider, null);
David Christie1b9b7b12013-04-15 15:31:11 -07003298 mLastLocationCoarseInterval.put(provider, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003299 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003300 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003301 }
3302 }
3303
Nick Pellye0fd6932012-07-11 10:26:13 -07003304 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003305 public void setTestProviderLocation(String provider, Location loc, String opPackageName) {
3306 if (!canCallerAccessMockLocation(opPackageName)) {
3307 return;
3308 }
3309
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003310 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003311 MockProvider mockProvider = mMockProviders.get(provider);
3312 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003313 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3314 }
Tom O'Neilla206a0f2016-12-15 10:26:28 -08003315
3316 // Ensure that the location is marked as being mock. There's some logic to do this in
3317 // handleLocationChanged(), but it fails if loc has the wrong provider (bug 33091107).
3318 Location mock = new Location(loc);
3319 mock.setIsFromMockProvider(true);
3320
3321 if (!TextUtils.isEmpty(loc.getProvider()) && !provider.equals(loc.getProvider())) {
3322 // The location has an explicit provider that is different from the mock provider
3323 // name. The caller may be trying to fool us via bug 33091107.
3324 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
3325 provider + "!=" + loc.getProvider());
3326 }
3327
Mike Lockwood95427cd2009-05-07 13:27:54 -04003328 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
3329 long identity = Binder.clearCallingIdentity();
Tom O'Neilla206a0f2016-12-15 10:26:28 -08003330 mockProvider.setLocation(mock);
Mike Lockwood95427cd2009-05-07 13:27:54 -04003331 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003332 }
3333 }
3334
Nick Pellye0fd6932012-07-11 10:26:13 -07003335 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003336 public void clearTestProviderLocation(String provider, String opPackageName) {
3337 if (!canCallerAccessMockLocation(opPackageName)) {
3338 return;
3339 }
3340
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003341 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003342 MockProvider mockProvider = mMockProviders.get(provider);
3343 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003344 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3345 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003346 mockProvider.clearLocation();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003347 }
3348 }
3349
Nick Pellye0fd6932012-07-11 10:26:13 -07003350 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003351 public void setTestProviderEnabled(String provider, boolean enabled, String opPackageName) {
3352 if (!canCallerAccessMockLocation(opPackageName)) {
3353 return;
3354 }
Maggie2a9409e2018-03-21 11:47:28 -07003355 setTestProviderEnabled(provider, enabled);
3356 }
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003357
Maggie2a9409e2018-03-21 11:47:28 -07003358 /** Enable or disable a test location provider. */
3359 private void setTestProviderEnabled(String provider, boolean enabled) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003360 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003361 MockProvider mockProvider = mMockProviders.get(provider);
3362 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003363 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3364 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003365 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003366 if (enabled) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003367 mockProvider.enable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003368 mEnabledProviders.add(provider);
3369 mDisabledProviders.remove(provider);
3370 } else {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003371 mockProvider.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003372 mEnabledProviders.remove(provider);
3373 mDisabledProviders.add(provider);
3374 }
3375 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003376 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003377 }
3378 }
3379
Nick Pellye0fd6932012-07-11 10:26:13 -07003380 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003381 public void clearTestProviderEnabled(String provider, String opPackageName) {
3382 if (!canCallerAccessMockLocation(opPackageName)) {
3383 return;
3384 }
3385
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003386 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003387 MockProvider mockProvider = mMockProviders.get(provider);
3388 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003389 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3390 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003391 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003392 mEnabledProviders.remove(provider);
3393 mDisabledProviders.remove(provider);
3394 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003395 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003396 }
3397 }
3398
Nick Pellye0fd6932012-07-11 10:26:13 -07003399 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003400 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime,
3401 String opPackageName) {
3402 if (!canCallerAccessMockLocation(opPackageName)) {
3403 return;
3404 }
3405
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003406 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003407 MockProvider mockProvider = mMockProviders.get(provider);
3408 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003409 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3410 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003411 mockProvider.setStatus(status, extras, updateTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003412 }
3413 }
3414
Nick Pellye0fd6932012-07-11 10:26:13 -07003415 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003416 public void clearTestProviderStatus(String provider, String opPackageName) {
3417 if (!canCallerAccessMockLocation(opPackageName)) {
3418 return;
3419 }
3420
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003421 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003422 MockProvider mockProvider = mMockProviders.get(provider);
3423 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003424 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3425 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003426 mockProvider.clearStatus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003427 }
3428 }
3429
3430 private void log(String log) {
3431 if (Log.isLoggable(TAG, Log.VERBOSE)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003432 Slog.d(TAG, log);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003433 }
3434 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003435
3436 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003437 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003438 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Nick Pellye0fd6932012-07-11 10:26:13 -07003439
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003440 synchronized (mLock) {
Siddharth Raybb608c82017-03-16 11:33:34 -07003441 if (args.length > 0 && args[0].equals("--gnssmetrics")) {
3442 if (mGnssMetricsProvider != null) {
3443 pw.append(mGnssMetricsProvider.getGnssMetricsAsProtoString());
3444 }
3445 return;
3446 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003447 pw.println("Current Location Manager state:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003448 pw.println(" Location Listeners:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003449 for (Receiver receiver : mReceivers.values()) {
3450 pw.println(" " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003451 }
David Christie2ff96af2014-01-30 16:09:37 -08003452 pw.println(" Active Records by Provider:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003453 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
3454 pw.println(" " + entry.getKey() + ":");
3455 for (UpdateRecord record : entry.getValue()) {
3456 pw.println(" " + record);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003457 }
3458 }
Wyatt Riley11cc7492018-01-17 08:48:27 -08003459 pw.println(" Active GnssMeasurement Listeners:");
3460 for (Identity identity : mGnssMeasurementsListeners.values()) {
3461 pw.println(" " + identity.mPid + " " + identity.mUid + " "
3462 + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
3463 }
3464 pw.println(" Active GnssNavigationMessage Listeners:");
3465 for (Identity identity : mGnssNavigationMessageListeners.values()) {
3466 pw.println(" " + identity.mPid + " " + identity.mUid + " "
3467 + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
3468 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003469 pw.println(" Overlay Provider Packages:");
3470 for (LocationProviderInterface provider : mProviders) {
3471 if (provider instanceof LocationProviderProxy) {
3472 pw.println(" " + provider.getName() + ": "
3473 + ((LocationProviderProxy) provider).getConnectedPackageName());
3474 }
3475 }
David Christie2ff96af2014-01-30 16:09:37 -08003476 pw.println(" Historical Records by Provider:");
3477 for (Map.Entry<PackageProviderKey, PackageStatistics> entry
3478 : mRequestStatistics.statistics.entrySet()) {
3479 PackageProviderKey key = entry.getKey();
3480 PackageStatistics stats = entry.getValue();
3481 pw.println(" " + key.packageName + ": " + key.providerName + ": " + stats);
3482 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003483 pw.println(" Last Known Locations:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003484 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
3485 String provider = entry.getKey();
3486 Location location = entry.getValue();
3487 pw.println(" " + provider + ": " + location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003488 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003489
David Christie1b9b7b12013-04-15 15:31:11 -07003490 pw.println(" Last Known Locations Coarse Intervals:");
3491 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
3492 String provider = entry.getKey();
3493 Location location = entry.getValue();
3494 pw.println(" " + provider + ": " + location);
3495 }
3496
Nick Pellye0fd6932012-07-11 10:26:13 -07003497 mGeofenceManager.dump(pw);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003498
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003499 if (mEnabledProviders.size() > 0) {
3500 pw.println(" Enabled Providers:");
3501 for (String i : mEnabledProviders) {
3502 pw.println(" " + i);
3503 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003504
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003505 }
3506 if (mDisabledProviders.size() > 0) {
3507 pw.println(" Disabled Providers:");
3508 for (String i : mDisabledProviders) {
3509 pw.println(" " + i);
3510 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003511 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07003512 pw.append(" ");
3513 mBlacklist.dump(pw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003514 if (mMockProviders.size() > 0) {
3515 pw.println(" Mock Providers:");
3516 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003517 i.getValue().dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003518 }
3519 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003520
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08003521 if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
3522 pw.println(" Throttling Whitelisted Packages:");
3523 for (String packageName : mBackgroundThrottlePackageWhitelist) {
3524 pw.println(" " + packageName);
3525 }
3526 }
3527
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003528 pw.append(" fudger: ");
gomo48f1a642017-11-10 20:35:46 -08003529 mLocationFudger.dump(fd, pw, args);
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003530
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003531 if (args.length > 0 && "short".equals(args[0])) {
3532 return;
3533 }
gomo48f1a642017-11-10 20:35:46 -08003534 for (LocationProviderInterface provider : mProviders) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003535 pw.print(provider.getName() + " Internal State");
3536 if (provider instanceof LocationProviderProxy) {
3537 LocationProviderProxy proxy = (LocationProviderProxy) provider;
3538 pw.print(" (" + proxy.getConnectedPackageName() + ")");
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003539 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003540 pw.println(":");
3541 provider.dump(fd, pw, args);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003542 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08003543 if (mGnssBatchingInProgress) {
3544 pw.println(" GNSS batching in progress");
3545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003546 }
3547 }
3548}