blob: de02e81a00c4e9e050be25ad0599e6c713849ca6 [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;
destradaaea8a8a62014-06-23 18:19:03 -070079import com.android.internal.content.PackageMonitor;
80import com.android.internal.location.ProviderProperties;
81import com.android.internal.location.ProviderRequest;
82import com.android.internal.os.BackgroundThread;
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -070083import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060084import com.android.internal.util.DumpUtils;
destradaaa4fa3b52014-07-09 10:46:39 -070085import com.android.server.location.ActivityRecognitionProxy;
destradaaea8a8a62014-06-23 18:19:03 -070086import com.android.server.location.GeocoderProxy;
87import com.android.server.location.GeofenceManager;
88import com.android.server.location.GeofenceProxy;
Yu-Han Yang3557cc72018-03-21 12:48:36 -070089import com.android.server.location.GnssBatchingProvider;
Lifu Tang818aa2c2016-02-01 01:52:00 -080090import com.android.server.location.GnssLocationProvider;
91import com.android.server.location.GnssMeasurementsProvider;
92import com.android.server.location.GnssNavigationMessageProvider;
destradaaea8a8a62014-06-23 18:19:03 -070093import com.android.server.location.LocationBlacklist;
94import com.android.server.location.LocationFudger;
95import com.android.server.location.LocationProviderInterface;
96import com.android.server.location.LocationProviderProxy;
97import com.android.server.location.LocationRequestStatistics;
98import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
99import com.android.server.location.LocationRequestStatistics.PackageStatistics;
100import com.android.server.location.MockProvider;
101import com.android.server.location.PassiveProvider;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400102import java.io.FileDescriptor;
103import java.io.PrintWriter;
104import java.util.ArrayList;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700105import java.util.Arrays;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400106import java.util.HashMap;
107import java.util.HashSet;
108import java.util.List;
109import java.util.Map;
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800110import java.util.Map.Entry;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800111import java.util.NoSuchElementException;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400112import java.util.Set;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113
114/**
115 * The service class that manages LocationProviders and issues location
116 * updates and alerts.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117 */
Victoria Lease5cd731a2012-12-19 15:04:21 -0800118public class LocationManagerService extends ILocationManager.Stub {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119 private static final String TAG = "LocationManagerService";
JP Abgrallf79811e72013-02-01 18:45:05 -0800120 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700121
Olivier Gaillard7a222662017-11-20 16:07:24 +0000122 private static final String WAKELOCK_KEY = "*location*";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123
Victoria Lease37425c32012-10-16 16:08:48 -0700124 // Location resolution level: no location data whatsoever
125 private static final int RESOLUTION_LEVEL_NONE = 0;
126 // Location resolution level: coarse location data only
127 private static final int RESOLUTION_LEVEL_COARSE = 1;
128 // Location resolution level: fine location data
129 private static final int RESOLUTION_LEVEL_FINE = 2;
130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131 private static final String ACCESS_MOCK_LOCATION =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700132 android.Manifest.permission.ACCESS_MOCK_LOCATION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700134 android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
Mike Lockwood275555c2009-05-01 11:30:34 -0400135 private static final String INSTALL_LOCATION_PROVIDER =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700136 android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
137
138 private static final String NETWORK_LOCATION_SERVICE_ACTION =
Stan Chesnutt39062dd2013-07-22 14:33:30 -0700139 "com.android.location.service.v3.NetworkLocationProvider";
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700140 private static final String FUSED_LOCATION_SERVICE_ACTION =
141 "com.android.location.service.FusedLocationProvider";
142
143 private static final int MSG_LOCATION_CHANGED = 1;
144
David Christie1b9b7b12013-04-15 15:31:11 -0700145 private static final long NANOS_PER_MILLI = 1000000L;
146
David Christie0b837452013-07-29 16:02:13 -0700147 // The maximum interval a location request can have and still be considered "high power".
148 private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
149
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700150 private static final int FOREGROUND_IMPORTANCE_CUTOFF
gomo48f1a642017-11-10 20:35:46 -0800151 = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700152
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800153 // default background throttling interval if not overriden in settings
Soonil Nagarkarde6780a2017-02-07 10:39:41 -0800154 private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800155
Wei Wangdd070f22018-06-21 11:29:40 -0700156 // Default value for maximum age of last location returned to applications with foreground-only
157 // location permissions.
158 private static final long DEFAULT_LAST_LOCATION_MAX_AGE_MS = 20 * 60 * 1000;
159
Nick Pellyf1be6862012-05-15 10:53:42 -0700160 // Location Providers may sometimes deliver location updates
161 // slightly faster that requested - provide grace period so
162 // we don't unnecessarily filter events that are otherwise on
163 // time
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700164 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
Nick Pellyf1be6862012-05-15 10:53:42 -0700165
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700166 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
167
168 private final Context mContext;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800169 private final AppOpsManager mAppOps;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700170
171 // used internally for synchronization
172 private final Object mLock = new Object();
173
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700174 // --- fields below are final after systemRunning() ---
Nick Pelly74fa7ea2012-08-13 19:36:38 -0700175 private LocationFudger mLocationFudger;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700176 private GeofenceManager mGeofenceManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700177 private PackageManager mPackageManager;
Victoria Lease0aa28602013-05-29 15:28:26 -0700178 private PowerManager mPowerManager;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800179 private ActivityManager mActivityManager;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700180 private UserManager mUserManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700181 private GeocoderProxy mGeocodeProvider;
Lifu Tang30f95a72016-01-07 23:20:38 -0800182 private IGnssStatusProvider mGnssStatusProvider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700183 private INetInitiatedListener mNetInitiatedListener;
184 private LocationWorkerHandler mLocationHandler;
Nick Pelly4035f5a2012-08-17 14:43:49 -0700185 private PassiveProvider mPassiveProvider; // track passive provider for special cases
186 private LocationBlacklist mBlacklist;
Lifu Tang818aa2c2016-02-01 01:52:00 -0800187 private GnssMeasurementsProvider mGnssMeasurementsProvider;
188 private GnssNavigationMessageProvider mGnssNavigationMessageProvider;
Wei Liu5241a4c2015-05-11 14:00:36 -0700189 private IGpsGeofenceHardware mGpsGeofenceProxy;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700190
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700191 // --- fields below are protected by mLock ---
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 // Set of providers that are explicitly enabled
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700193 // Only used by passive, fused & test. Network & GPS are controlled separately, and not listed.
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800194 private final Set<String> mEnabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195
196 // Set of providers that are explicitly disabled
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800197 private final Set<String> mDisabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700199 // Mock (test) providers
200 private final HashMap<String, MockProvider> mMockProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800201 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700203 // all receivers
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800204 private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700206 // currently installed providers (with mocks replacing real providers)
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500207 private final ArrayList<LocationProviderInterface> mProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800208 new ArrayList<>();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400209
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700210 // real providers, saved here when mocked out
211 private final HashMap<String, LocationProviderInterface> mRealProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800212 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700214 // mapping from provider name to provider
215 private final HashMap<String, LocationProviderInterface> mProvidersByName =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800216 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700218 // mapping from provider name to all its UpdateRecords
219 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800220 new HashMap<>();
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700221
David Christie2ff96af2014-01-30 16:09:37 -0800222 private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics();
223
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700224 // mapping from provider name to last known location
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800225 private final HashMap<String, Location> mLastLocation = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226
David Christie1b9b7b12013-04-15 15:31:11 -0700227 // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
228 // locations stored here are not fudged for coarse permissions.
229 private final HashMap<String, Location> mLastLocationCoarseInterval =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800230 new HashMap<>();
David Christie1b9b7b12013-04-15 15:31:11 -0700231
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800232 // all providers that operate over proxy, for authorizing incoming location and whitelisting
233 // throttling
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700234 private final ArrayList<LocationProviderProxy> mProxyProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800235 new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800237 private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800238
Wyatt Riley11cc7492018-01-17 08:48:27 -0800239 private final ArrayMap<IBinder, Identity> mGnssMeasurementsListeners = new ArrayMap<>();
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800240
Wyatt Riley11cc7492018-01-17 08:48:27 -0800241 private final ArrayMap<IBinder, Identity>
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800242 mGnssNavigationMessageListeners = new ArrayMap<>();
243
Victoria Lease38389b62012-09-30 11:44:22 -0700244 // current active user on the device - other users are denied location data
Xiaohui Chena4490622015-09-22 15:29:31 -0700245 private int mCurrentUserId = UserHandle.USER_SYSTEM;
gomo48f1a642017-11-10 20:35:46 -0800246 private int[] mCurrentUserProfiles = new int[]{UserHandle.USER_SYSTEM};
Victoria Lease38389b62012-09-30 11:44:22 -0700247
Wei Wangdd070f22018-06-21 11:29:40 -0700248 // Maximum age of last location returned to clients with foreground-only location permissions.
249 private long mLastLocationMaxAgeMs;
250
Lifu Tang9363b942016-02-16 18:07:00 -0800251 private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;
Lifu Tang82f893d2016-01-21 18:15:33 -0800252
Siddharth Raybb608c82017-03-16 11:33:34 -0700253 private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;
Wyatt Rileyaa420d52017-07-03 15:14:42 -0700254
Yu-Han Yang3557cc72018-03-21 12:48:36 -0700255 private GnssBatchingProvider mGnssBatchingProvider;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800256 private IBatchedLocationCallback mGnssBatchingCallback;
257 private LinkedCallback mGnssBatchingDeathCallback;
258 private boolean mGnssBatchingInProgress = false;
259
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700260 public LocationManagerService(Context context) {
261 super();
262 mContext = context;
gomo48f1a642017-11-10 20:35:46 -0800263 mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800264
Svet Ganovadc1cf42015-06-15 16:36:24 -0700265 // Let the package manager query which are the default location
266 // providers as they get certain permissions granted by default.
267 PackageManagerInternal packageManagerInternal = LocalServices.getService(
268 PackageManagerInternal.class);
269 packageManagerInternal.setLocationPackagesProvider(
270 new PackageManagerInternal.PackagesProvider() {
271 @Override
272 public String[] getPackages(int userId) {
273 return mContext.getResources().getStringArray(
274 com.android.internal.R.array.config_locationProviderPackageNames);
275 }
276 });
277
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700278 if (D) Log.d(TAG, "Constructed");
279
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700280 // most startup is deferred until systemRunning()
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700281 }
282
Svetoslav Ganova0027152013-06-25 14:59:53 -0700283 public void systemRunning() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700284 synchronized (mLock) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700285 if (D) Log.d(TAG, "systemRunning()");
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700286
Victoria Lease5cd731a2012-12-19 15:04:21 -0800287 // fetch package manager
288 mPackageManager = mContext.getPackageManager();
289
Victoria Lease0aa28602013-05-29 15:28:26 -0700290 // fetch power manager
291 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
Victoria Lease5cd731a2012-12-19 15:04:21 -0800292
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800293 // fetch activity manager
294 mActivityManager
295 = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
296
Victoria Lease5cd731a2012-12-19 15:04:21 -0800297 // prepare worker thread
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700298 mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper());
Victoria Lease5cd731a2012-12-19 15:04:21 -0800299
300 // prepare mLocationHandler's dependents
301 mLocationFudger = new LocationFudger(mContext, mLocationHandler);
302 mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
303 mBlacklist.init();
304 mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
305
Dianne Hackbornc2293022013-02-06 23:14:49 -0800306 // Monitor for app ops mode changes.
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700307 AppOpsManager.OnOpChangedListener callback
308 = new AppOpsManager.OnOpChangedInternalListener() {
309 public void onOpChanged(int op, String packageName) {
Dianne Hackbornc2293022013-02-06 23:14:49 -0800310 synchronized (mLock) {
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700311 for (Receiver receiver : mReceivers.values()) {
312 receiver.updateMonitoring(true);
313 }
Dianne Hackbornc2293022013-02-06 23:14:49 -0800314 applyAllProviderRequirementsLocked();
315 }
316 }
317 };
Wei Wangdd070f22018-06-21 11:29:40 -0700318 mAppOps.startWatchingMode(AppOpsManager.OP_COARSE_LOCATION, null,
319 AppOpsManager.WATCH_FOREGROUND_CHANGES, callback);
Dianne Hackbornc2293022013-02-06 23:14:49 -0800320
David Christieb870dbf2015-06-22 12:42:53 -0700321 PackageManager.OnPermissionsChangedListener permissionListener
322 = new PackageManager.OnPermissionsChangedListener() {
323 @Override
324 public void onPermissionsChanged(final int uid) {
325 synchronized (mLock) {
326 applyAllProviderRequirementsLocked();
327 }
328 }
329 };
330 mPackageManager.addOnPermissionsChangeListener(permissionListener);
331
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800332 // listen for background/foreground changes
333 ActivityManager.OnUidImportanceListener uidImportanceListener
334 = new ActivityManager.OnUidImportanceListener() {
335 @Override
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700336 public void onUidImportance(final int uid, final int importance) {
337 mLocationHandler.post(new Runnable() {
338 @Override
339 public void run() {
340 onUidImportanceChanged(uid, importance);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800341 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700342 });
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800343 }
344 };
345 mActivityManager.addOnUidImportanceListener(uidImportanceListener,
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700346 FOREGROUND_IMPORTANCE_CUTOFF);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800347
Amith Yamasanib27528d2014-06-05 15:02:10 -0700348 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
349 updateUserProfiles(mCurrentUserId);
350
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800351 updateBackgroundThrottlingWhitelistLocked();
Wei Wangdd070f22018-06-21 11:29:40 -0700352 updateLastLocationMaxAgeLocked();
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800353
Victoria Lease5cd731a2012-12-19 15:04:21 -0800354 // prepare providers
355 loadProvidersLocked();
356 updateProvidersLocked();
357 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700358
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700359 // listen for settings changes
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700360 mContext.getContentResolver().registerContentObserver(
Laurent Tu75defb62012-11-01 16:21:52 -0700361 Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700362 new ContentObserver(mLocationHandler) {
Victoria Lease5cd731a2012-12-19 15:04:21 -0800363 @Override
364 public void onChange(boolean selfChange) {
365 synchronized (mLock) {
366 updateProvidersLocked();
367 }
368 }
369 }, UserHandle.USER_ALL);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800370 mContext.getContentResolver().registerContentObserver(
371 Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS),
372 true,
373 new ContentObserver(mLocationHandler) {
374 @Override
375 public void onChange(boolean selfChange) {
376 synchronized (mLock) {
377 updateProvidersLocked();
378 }
379 }
380 }, UserHandle.USER_ALL);
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800381 mContext.getContentResolver().registerContentObserver(
Wei Wangdd070f22018-06-21 11:29:40 -0700382 Settings.Global.getUriFor(Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS),
383 true,
384 new ContentObserver(mLocationHandler) {
385 @Override
386 public void onChange(boolean selfChange) {
387 synchronized (mLock) {
388 updateLastLocationMaxAgeLocked();
389 }
390 }
391 }
392 );
393 mContext.getContentResolver().registerContentObserver(
gomo48f1a642017-11-10 20:35:46 -0800394 Settings.Global.getUriFor(
395 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
396 true,
397 new ContentObserver(mLocationHandler) {
398 @Override
399 public void onChange(boolean selfChange) {
400 synchronized (mLock) {
401 updateBackgroundThrottlingWhitelistLocked();
402 updateProvidersLocked();
403 }
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800404 }
gomo48f1a642017-11-10 20:35:46 -0800405 }, UserHandle.USER_ALL);
Wei Wangdd070f22018-06-21 11:29:40 -0700406
Victoria Lease5cd731a2012-12-19 15:04:21 -0800407 mPackageMonitor.register(mContext, mLocationHandler.getLooper(), true);
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700408
Victoria Lease38389b62012-09-30 11:44:22 -0700409 // listen for user change
410 IntentFilter intentFilter = new IntentFilter();
411 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700412 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
413 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
destradaab9026982015-08-27 17:34:54 -0700414 intentFilter.addAction(Intent.ACTION_SHUTDOWN);
Victoria Lease38389b62012-09-30 11:44:22 -0700415
416 mContext.registerReceiverAsUser(new BroadcastReceiver() {
417 @Override
418 public void onReceive(Context context, Intent intent) {
419 String action = intent.getAction();
420 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
421 switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
Amith Yamasanib27528d2014-06-05 15:02:10 -0700422 } else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)
423 || Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
424 updateUserProfiles(mCurrentUserId);
destradaab9026982015-08-27 17:34:54 -0700425 } else if (Intent.ACTION_SHUTDOWN.equals(action)) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700426 // shutdown only if UserId indicates whole system, not just one user
gomo48f1a642017-11-10 20:35:46 -0800427 if (D) Log.d(TAG, "Shutdown received with UserId: " + getSendingUserId());
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700428 if (getSendingUserId() == UserHandle.USER_ALL) {
429 shutdownComponents();
430 }
Victoria Lease38389b62012-09-30 11:44:22 -0700431 }
432 }
Victoria Lease5cd731a2012-12-19 15:04:21 -0800433 }, UserHandle.ALL, intentFilter, null, mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700434 }
435
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700436 private void onUidImportanceChanged(int uid, int importance) {
437 boolean foreground = isImportanceForeground(importance);
438 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
439 synchronized (mLock) {
440 for (Entry<String, ArrayList<UpdateRecord>> entry
gomo48f1a642017-11-10 20:35:46 -0800441 : mRecordsByProvider.entrySet()) {
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700442 String provider = entry.getKey();
443 for (UpdateRecord record : entry.getValue()) {
444 if (record.mReceiver.mIdentity.mUid == uid
gomo48f1a642017-11-10 20:35:46 -0800445 && record.mIsForegroundUid != foreground) {
446 if (D) {
447 Log.d(TAG, "request from uid " + uid + " is now "
448 + (foreground ? "foreground" : "background)"));
449 }
Wyatt Rileyf7075e02018-04-12 17:54:26 -0700450 record.updateForeground(foreground);
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700451
452 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
453 affectedProviders.add(provider);
454 }
455 }
456 }
457 }
458 for (String provider : affectedProviders) {
459 applyRequirementsLocked(provider);
460 }
461
Wyatt Riley11cc7492018-01-17 08:48:27 -0800462 for (Entry<IBinder, Identity> entry : mGnssMeasurementsListeners.entrySet()) {
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700463 if (entry.getValue().mUid == uid) {
gomo48f1a642017-11-10 20:35:46 -0800464 if (D) {
465 Log.d(TAG, "gnss measurements listener from uid " + uid
466 + " is now " + (foreground ? "foreground" : "background)"));
467 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700468 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800469 mGnssMeasurementsProvider.addListener(
470 IGnssMeasurementsListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700471 } else {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800472 mGnssMeasurementsProvider.removeListener(
473 IGnssMeasurementsListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700474 }
475 }
476 }
477
Wyatt Riley11cc7492018-01-17 08:48:27 -0800478 for (Entry<IBinder, Identity> entry : mGnssNavigationMessageListeners.entrySet()) {
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700479 if (entry.getValue().mUid == uid) {
gomo48f1a642017-11-10 20:35:46 -0800480 if (D) {
481 Log.d(TAG, "gnss navigation message listener from uid "
482 + uid + " is now "
483 + (foreground ? "foreground" : "background)"));
484 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700485 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800486 mGnssNavigationMessageProvider.addListener(
487 IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700488 } else {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800489 mGnssNavigationMessageProvider.removeListener(
490 IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700491 }
492 }
493 }
494 }
495 }
496
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800497 private static boolean isImportanceForeground(int importance) {
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700498 return importance <= FOREGROUND_IMPORTANCE_CUTOFF;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800499 }
500
Amith Yamasanib27528d2014-06-05 15:02:10 -0700501 /**
destradaab9026982015-08-27 17:34:54 -0700502 * Provides a way for components held by the {@link LocationManagerService} to clean-up
503 * gracefully on system's shutdown.
504 *
505 * NOTES:
506 * 1) Only provides a chance to clean-up on an opt-in basis. This guarantees back-compat
507 * support for components that do not wish to handle such event.
508 */
509 private void shutdownComponents() {
gomo48f1a642017-11-10 20:35:46 -0800510 if (D) Log.d(TAG, "Shutting down components...");
destradaab9026982015-08-27 17:34:54 -0700511
512 LocationProviderInterface gpsProvider = mProvidersByName.get(LocationManager.GPS_PROVIDER);
513 if (gpsProvider != null && gpsProvider.isEnabled()) {
514 gpsProvider.disable();
515 }
destradaab9026982015-08-27 17:34:54 -0700516 }
517
518 /**
Amith Yamasanib27528d2014-06-05 15:02:10 -0700519 * Makes a list of userids that are related to the current user. This is
520 * relevant when using managed profiles. Otherwise the list only contains
521 * the current user.
522 *
523 * @param currentUserId the current user, who might have an alter-ego.
524 */
525 void updateUserProfiles(int currentUserId) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700526 int[] profileIds = mUserManager.getProfileIdsWithDisabled(currentUserId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700527 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700528 mCurrentUserProfiles = profileIds;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700529 }
530 }
531
532 /**
533 * Checks if the specified userId matches any of the current foreground
534 * users stored in mCurrentUserProfiles.
535 */
536 private boolean isCurrentProfile(int userId) {
537 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700538 return ArrayUtils.contains(mCurrentUserProfiles, userId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700539 }
540 }
541
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500542 private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) {
543 PackageManager pm = mContext.getPackageManager();
544 String systemPackageName = mContext.getPackageName();
545 ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
546
547 List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
548 new Intent(FUSED_LOCATION_SERVICE_ACTION),
549 PackageManager.GET_META_DATA, mCurrentUserId);
550 for (ResolveInfo rInfo : rInfos) {
551 String packageName = rInfo.serviceInfo.packageName;
552
553 // Check that the signature is in the list of supported sigs. If it's not in
554 // this list the standard provider binding logic won't bind to it.
555 try {
556 PackageInfo pInfo;
557 pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
558 if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
559 Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
560 ", but has wrong signature, ignoring");
561 continue;
562 }
563 } catch (NameNotFoundException e) {
564 Log.e(TAG, "missing package: " + packageName);
565 continue;
566 }
567
568 // Get the version info
569 if (rInfo.serviceInfo.metaData == null) {
570 Log.w(TAG, "Found fused provider without metadata: " + packageName);
571 continue;
572 }
573
574 int version = rInfo.serviceInfo.metaData.getInt(
575 ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
576 if (version == 0) {
577 // This should be the fallback fused location provider.
578
579 // Make sure it's in the system partition.
580 if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
581 if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
582 continue;
583 }
584
585 // Check that the fallback is signed the same as the OS
586 // as a proxy for coreApp="true"
587 if (pm.checkSignatures(systemPackageName, packageName)
588 != PackageManager.SIGNATURE_MATCH) {
gomo48f1a642017-11-10 20:35:46 -0800589 if (D) {
590 Log.d(TAG, "Fallback candidate not signed the same as system: "
591 + packageName);
592 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500593 continue;
594 }
595
596 // Found a valid fallback.
597 if (D) Log.d(TAG, "Found fallback provider: " + packageName);
598 return;
599 } else {
600 if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
601 }
602 }
603
604 throw new IllegalStateException("Unable to find a fused location provider that is in the "
605 + "system partition with version 0 and signed with the platform certificate. "
606 + "Such a package is needed to provide a default fused location provider in the "
607 + "event that no other fused location provider has been installed or is currently "
608 + "available. For example, coreOnly boot mode when decrypting the data "
609 + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
610 }
611
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700612 private void loadProvidersLocked() {
Victoria Lease5c24fd02012-10-01 11:00:50 -0700613 // create a passive location provider, which is always enabled
614 PassiveProvider passiveProvider = new PassiveProvider(this);
615 addProviderLocked(passiveProvider);
616 mEnabledProviders.add(passiveProvider.getName());
617 mPassiveProvider = passiveProvider;
618
Lifu Tang30f95a72016-01-07 23:20:38 -0800619 if (GnssLocationProvider.isSupported()) {
Wei Liu5241a4c2015-05-11 14:00:36 -0700620 // Create a gps location provider
Lifu Tang30f95a72016-01-07 23:20:38 -0800621 GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this,
Wei Liu5241a4c2015-05-11 14:00:36 -0700622 mLocationHandler.getLooper());
Lifu Tang9363b942016-02-16 18:07:00 -0800623 mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
Wyatt Rileycf879db2017-01-12 13:57:38 -0800624 mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider();
Siddharth Raybb608c82017-03-16 11:33:34 -0700625 mGnssMetricsProvider = gnssProvider.getGnssMetricsProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800626 mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
627 mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
628 addProviderLocked(gnssProvider);
629 mRealProviders.put(LocationManager.GPS_PROVIDER, gnssProvider);
Lifu Tang818aa2c2016-02-01 01:52:00 -0800630 mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
631 mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800632 mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700633 }
634
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700635 /*
636 Load package name(s) containing location provider support.
637 These packages can contain services implementing location providers:
638 Geocoder Provider, Network Location Provider, and
639 Fused Location Provider. They will each be searched for
640 service components implementing these providers.
641 The location framework also has support for installation
642 of new location providers at run-time. The new package does not
643 have to be explicitly listed here, however it must have a signature
644 that matches the signature of at least one package on this list.
645 */
646 Resources resources = mContext.getResources();
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800647 ArrayList<String> providerPackageNames = new ArrayList<>();
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500648 String[] pkgs = resources.getStringArray(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700649 com.android.internal.R.array.config_locationProviderPackageNames);
gomo48f1a642017-11-10 20:35:46 -0800650 if (D) {
651 Log.d(TAG, "certificates for location providers pulled from: " +
652 Arrays.toString(pkgs));
653 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500654 if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));
655
656 ensureFallbackFusedProviderPresentLocked(providerPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700657
658 // bind to network provider
659 LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
660 mContext,
661 LocationManager.NETWORK_PROVIDER,
662 NETWORK_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700663 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
664 com.android.internal.R.string.config_networkLocationProviderPackageName,
665 com.android.internal.R.array.config_locationProviderPackageNames,
666 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700667 if (networkProvider != null) {
668 mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
669 mProxyProviders.add(networkProvider);
670 addProviderLocked(networkProvider);
671 } else {
gomo48f1a642017-11-10 20:35:46 -0800672 Slog.w(TAG, "no network location provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700673 }
674
675 // bind to fused provider
676 LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind(
677 mContext,
678 LocationManager.FUSED_PROVIDER,
679 FUSED_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700680 com.android.internal.R.bool.config_enableFusedLocationOverlay,
681 com.android.internal.R.string.config_fusedLocationProviderPackageName,
682 com.android.internal.R.array.config_locationProviderPackageNames,
683 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700684 if (fusedLocationProvider != null) {
685 addProviderLocked(fusedLocationProvider);
686 mProxyProviders.add(fusedLocationProvider);
687 mEnabledProviders.add(fusedLocationProvider.getName());
Kenny Rootc3575182012-10-09 12:44:40 -0700688 mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700689 } else {
690 Slog.e(TAG, "no fused location provider found",
691 new IllegalStateException("Location service needs a fused location provider"));
692 }
693
694 // bind to geocoder provider
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700695 mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
696 com.android.internal.R.bool.config_enableGeocoderOverlay,
697 com.android.internal.R.string.config_geocoderProviderPackageName,
698 com.android.internal.R.array.config_locationProviderPackageNames,
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800699 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700700 if (mGeocodeProvider == null) {
gomo48f1a642017-11-10 20:35:46 -0800701 Slog.e(TAG, "no geocoder provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700702 }
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700703
destradaaf9a274c2014-07-25 15:11:56 -0700704 // bind to geofence provider
705 GeofenceProxy provider = GeofenceProxy.createAndBind(
gomo48f1a642017-11-10 20:35:46 -0800706 mContext, com.android.internal.R.bool.config_enableGeofenceOverlay,
destradaaf9a274c2014-07-25 15:11:56 -0700707 com.android.internal.R.string.config_geofenceProviderPackageName,
708 com.android.internal.R.array.config_locationProviderPackageNames,
709 mLocationHandler,
Wei Liu5241a4c2015-05-11 14:00:36 -0700710 mGpsGeofenceProxy,
Jiyong Park4cc3a1c2018-03-08 16:43:07 +0900711 null);
destradaaf9a274c2014-07-25 15:11:56 -0700712 if (provider == null) {
gomo48f1a642017-11-10 20:35:46 -0800713 Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
destradaa0682809a2013-08-12 18:50:30 -0700714 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900715
destradaa6e2fe752015-06-23 17:25:53 -0700716 // bind to hardware activity recognition
717 boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
718 ActivityRecognitionHardware activityRecognitionHardware = null;
719 if (activityRecognitionHardwareIsSupported) {
720 activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
destradaaa4fa3b52014-07-09 10:46:39 -0700721 } else {
destradaa6b4893a2016-05-03 15:33:43 -0700722 Slog.d(TAG, "Hardware Activity-Recognition not supported.");
destradaaa4fa3b52014-07-09 10:46:39 -0700723 }
destradaa6e2fe752015-06-23 17:25:53 -0700724 ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
725 mContext,
726 mLocationHandler,
727 activityRecognitionHardwareIsSupported,
728 activityRecognitionHardware,
729 com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
730 com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
731 com.android.internal.R.array.config_locationProviderPackageNames);
732 if (proxy == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700733 Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
destradaa6e2fe752015-06-23 17:25:53 -0700734 }
destradaaa4fa3b52014-07-09 10:46:39 -0700735
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900736 String[] testProviderStrings = resources.getStringArray(
737 com.android.internal.R.array.config_testLocationProviders);
738 for (String testProviderString : testProviderStrings) {
739 String fragments[] = testProviderString.split(",");
740 String name = fragments[0].trim();
741 if (mProvidersByName.get(name) != null) {
742 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
743 }
744 ProviderProperties properties = new ProviderProperties(
745 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
746 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
747 Boolean.parseBoolean(fragments[3]) /* requiresCell */,
748 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
749 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
750 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
751 Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
752 Integer.parseInt(fragments[8]) /* powerRequirement */,
753 Integer.parseInt(fragments[9]) /* accuracy */);
754 addTestProviderLocked(name, properties);
755 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700756 }
Mike Lockwood9637d472009-04-02 21:41:57 -0700757
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800758 /**
Victoria Lease38389b62012-09-30 11:44:22 -0700759 * Called when the device's active user changes.
gomo48f1a642017-11-10 20:35:46 -0800760 *
Victoria Lease38389b62012-09-30 11:44:22 -0700761 * @param userId the new active user's UserId
762 */
763 private void switchUser(int userId) {
Jianzheng Zhoud5c69462013-10-10 14:02:09 +0800764 if (mCurrentUserId == userId) {
765 return;
766 }
Victoria Lease83762d22012-10-03 13:51:17 -0700767 mBlacklist.switchUser(userId);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800768 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED);
Victoria Lease38389b62012-09-30 11:44:22 -0700769 synchronized (mLock) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700770 mLastLocation.clear();
David Christie1b9b7b12013-04-15 15:31:11 -0700771 mLastLocationCoarseInterval.clear();
Victoria Leaseb711d572012-10-02 13:14:11 -0700772 for (LocationProviderInterface p : mProviders) {
Amith Yamasanib27528d2014-06-05 15:02:10 -0700773 updateProviderListenersLocked(p.getName(), false);
Victoria Leaseb711d572012-10-02 13:14:11 -0700774 }
Victoria Lease38389b62012-09-30 11:44:22 -0700775 mCurrentUserId = userId;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700776 updateUserProfiles(userId);
Victoria Leaseb711d572012-10-02 13:14:11 -0700777 updateProvidersLocked();
Victoria Lease38389b62012-09-30 11:44:22 -0700778 }
779 }
780
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800781 private static final class Identity {
782 final int mUid;
783 final int mPid;
784 final String mPackageName;
785
786 Identity(int uid, int pid, String packageName) {
787 mUid = uid;
788 mPid = pid;
789 mPackageName = packageName;
790 }
791 }
792
Victoria Lease38389b62012-09-30 11:44:22 -0700793 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 * A wrapper class holding either an ILocationListener or a PendingIntent to receive
795 * location updates.
796 */
Mike Lockwood48f17512009-04-23 09:12:08 -0700797 private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800798 final Identity mIdentity;
Victoria Lease37425c32012-10-16 16:08:48 -0700799 final int mAllowedResolutionLevel; // resolution level allowed to receiver
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801 final ILocationListener mListener;
802 final PendingIntent mPendingIntent;
David Christie82edc9b2013-07-19 11:31:42 -0700803 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
David Christie40e57822013-07-30 11:36:48 -0700804 final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805 final Object mKey;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700806
gomo48f1a642017-11-10 20:35:46 -0800807 final HashMap<String, UpdateRecord> mUpdateRecords = new HashMap<>();
Nick Pellyf1be6862012-05-15 10:53:42 -0700808
David Christie0b837452013-07-29 16:02:13 -0700809 // True if app ops has started monitoring this receiver for locations.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700810 boolean mOpMonitoring;
David Christie0b837452013-07-29 16:02:13 -0700811 // True if app ops has started monitoring this receiver for high power (gps) locations.
812 boolean mOpHighPowerMonitoring;
Mike Lockwood48f17512009-04-23 09:12:08 -0700813 int mPendingBroadcasts;
Victoria Lease0aa28602013-05-29 15:28:26 -0700814 PowerManager.WakeLock mWakeLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700816 Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -0700817 String packageName, WorkSource workSource, boolean hideFromAppOps) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800818 mListener = listener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 mPendingIntent = intent;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700820 if (listener != null) {
821 mKey = listener.asBinder();
822 } else {
823 mKey = intent;
824 }
Victoria Lease37425c32012-10-16 16:08:48 -0700825 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800826 mIdentity = new Identity(uid, pid, packageName);
Narayan Kamath32684dd2018-01-08 17:32:51 +0000827 if (workSource != null && workSource.isEmpty()) {
David Christie82edc9b2013-07-19 11:31:42 -0700828 workSource = null;
829 }
830 mWorkSource = workSource;
David Christie40e57822013-07-30 11:36:48 -0700831 mHideFromAppOps = hideFromAppOps;
Victoria Lease0aa28602013-05-29 15:28:26 -0700832
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700833 updateMonitoring(true);
834
Victoria Lease0aa28602013-05-29 15:28:26 -0700835 // construct/configure wakelock
836 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
David Christie82edc9b2013-07-19 11:31:42 -0700837 if (workSource == null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800838 workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -0700839 }
840 mWakeLock.setWorkSource(workSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800841 }
842
843 @Override
844 public boolean equals(Object otherObj) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800845 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846 }
847
848 @Override
849 public int hashCode() {
850 return mKey.hashCode();
851 }
Mike Lockwood3681f262009-05-12 10:52:03 -0400852
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 @Override
854 public String toString() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700855 StringBuilder s = new StringBuilder();
856 s.append("Reciever[");
857 s.append(Integer.toHexString(System.identityHashCode(this)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800858 if (mListener != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700859 s.append(" listener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700861 s.append(" intent");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800862 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700863 for (String p : mUpdateRecords.keySet()) {
864 s.append(" ").append(mUpdateRecords.get(p).toString());
865 }
Wei Wangdd070f22018-06-21 11:29:40 -0700866 s.append(" monitoring location: ").append(mOpMonitoring);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700867 s.append("]");
868 return s.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 }
870
David Christie15b31912013-08-13 15:54:32 -0700871 /**
872 * Update AppOp monitoring for this receiver.
873 *
874 * @param allow If true receiver is currently active, if false it's been removed.
875 */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700876 public void updateMonitoring(boolean allow) {
David Christie40e57822013-07-30 11:36:48 -0700877 if (mHideFromAppOps) {
878 return;
879 }
880
David Christie15b31912013-08-13 15:54:32 -0700881 boolean requestingLocation = false;
882 boolean requestingHighPowerLocation = false;
883 if (allow) {
884 // See if receiver has any enabled update records. Also note if any update records
885 // are high power (has a high power provider with an interval under a threshold).
886 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
887 if (isAllowedByCurrentUserSettingsLocked(updateRecord.mProvider)) {
888 requestingLocation = true;
889 LocationProviderInterface locationProvider
David Christie2ff96af2014-01-30 16:09:37 -0800890 = mProvidersByName.get(updateRecord.mProvider);
David Christie15b31912013-08-13 15:54:32 -0700891 ProviderProperties properties = locationProvider != null
892 ? locationProvider.getProperties() : null;
893 if (properties != null
894 && properties.mPowerRequirement == Criteria.POWER_HIGH
895 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
896 requestingHighPowerLocation = true;
897 break;
898 }
899 }
900 }
901 }
902
David Christie0b837452013-07-29 16:02:13 -0700903 // First update monitoring of any location request (including high power).
David Christie15b31912013-08-13 15:54:32 -0700904 mOpMonitoring = updateMonitoring(
905 requestingLocation,
906 mOpMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700907 AppOpsManager.OP_MONITOR_LOCATION);
908
909 // Now update monitoring of high power requests only.
David Christiec750c1f2013-08-08 12:56:57 -0700910 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
David Christie15b31912013-08-13 15:54:32 -0700911 mOpHighPowerMonitoring = updateMonitoring(
912 requestingHighPowerLocation,
913 mOpHighPowerMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700914 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
David Christiec750c1f2013-08-08 12:56:57 -0700915 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
David Christie15b31912013-08-13 15:54:32 -0700916 // Send an intent to notify that a high power request has been added/removed.
David Christiec750c1f2013-08-08 12:56:57 -0700917 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
918 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
919 }
David Christie0b837452013-07-29 16:02:13 -0700920 }
921
922 /**
923 * Update AppOps monitoring for a single location request and op type.
924 *
gomo48f1a642017-11-10 20:35:46 -0800925 * @param allowMonitoring True if monitoring is allowed for this request/op.
David Christie0b837452013-07-29 16:02:13 -0700926 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
gomo48f1a642017-11-10 20:35:46 -0800927 * @param op AppOps code for the op to update.
David Christie0b837452013-07-29 16:02:13 -0700928 * @return True if monitoring is on for this request/op after updating.
929 */
930 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
931 int op) {
932 if (!currentlyMonitoring) {
933 if (allowMonitoring) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800934 return mAppOps.startOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700935 == AppOpsManager.MODE_ALLOWED;
936 }
937 } else {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800938 if (!allowMonitoring
Wei Wangdd070f22018-06-21 11:29:40 -0700939 || mAppOps.noteOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700940 != AppOpsManager.MODE_ALLOWED) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800941 mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName);
David Christie0b837452013-07-29 16:02:13 -0700942 return false;
943 }
944 }
945
946 return currentlyMonitoring;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700947 }
948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800949 public boolean isListener() {
950 return mListener != null;
951 }
952
953 public boolean isPendingIntent() {
954 return mPendingIntent != null;
955 }
956
957 public ILocationListener getListener() {
958 if (mListener != null) {
959 return mListener;
960 }
961 throw new IllegalStateException("Request for non-existent listener");
962 }
963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
965 if (mListener != null) {
966 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700967 synchronized (this) {
968 // synchronize to ensure incrementPendingBroadcastsLocked()
969 // is called before decrementPendingBroadcasts()
970 mListener.onStatusChanged(provider, status, extras);
Nick Pellye0fd6932012-07-11 10:26:13 -0700971 // call this after broadcasting so we do not increment
972 // if we throw an exeption.
973 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -0700974 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 } catch (RemoteException e) {
976 return false;
977 }
978 } else {
979 Intent statusChanged = new Intent();
Victoria Lease61ecb022012-11-13 15:12:51 -0800980 statusChanged.putExtras(new Bundle(extras));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800981 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
982 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700983 synchronized (this) {
984 // synchronize to ensure incrementPendingBroadcastsLocked()
985 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700986 mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
Lifu Tang519f0d02018-04-12 16:39:39 -0700987 getResolutionPermission(mAllowedResolutionLevel),
988 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
Mike Lockwood48f17512009-04-23 09:12:08 -0700989 // call this after broadcasting so we do not increment
990 // if we throw an exeption.
991 incrementPendingBroadcastsLocked();
992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 } catch (PendingIntent.CanceledException e) {
994 return false;
995 }
996 }
997 return true;
998 }
999
1000 public boolean callLocationChangedLocked(Location location) {
1001 if (mListener != null) {
1002 try {
Mike Lockwood48f17512009-04-23 09:12:08 -07001003 synchronized (this) {
1004 // synchronize to ensure incrementPendingBroadcastsLocked()
1005 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08001006 mListener.onLocationChanged(new Location(location));
Nick Pellye0fd6932012-07-11 10:26:13 -07001007 // call this after broadcasting so we do not increment
1008 // if we throw an exeption.
1009 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001010 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 } catch (RemoteException e) {
1012 return false;
1013 }
1014 } else {
1015 Intent locationChanged = new Intent();
gomo48f1a642017-11-10 20:35:46 -08001016 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED,
1017 new Location(location));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 try {
Mike Lockwood48f17512009-04-23 09:12:08 -07001019 synchronized (this) {
1020 // synchronize to ensure incrementPendingBroadcastsLocked()
1021 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001022 mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
Lifu Tang519f0d02018-04-12 16:39:39 -07001023 getResolutionPermission(mAllowedResolutionLevel),
1024 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
Mike Lockwood48f17512009-04-23 09:12:08 -07001025 // call this after broadcasting so we do not increment
1026 // if we throw an exeption.
1027 incrementPendingBroadcastsLocked();
1028 }
1029 } catch (PendingIntent.CanceledException e) {
1030 return false;
1031 }
1032 }
1033 return true;
1034 }
1035
1036 public boolean callProviderEnabledLocked(String provider, boolean enabled) {
David Christie15b31912013-08-13 15:54:32 -07001037 // First update AppOp monitoring.
1038 // An app may get/lose location access as providers are enabled/disabled.
1039 updateMonitoring(true);
1040
Mike Lockwood48f17512009-04-23 09:12:08 -07001041 if (mListener != null) {
1042 try {
1043 synchronized (this) {
1044 // synchronize to ensure incrementPendingBroadcastsLocked()
1045 // is called before decrementPendingBroadcasts()
1046 if (enabled) {
1047 mListener.onProviderEnabled(provider);
1048 } else {
1049 mListener.onProviderDisabled(provider);
1050 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001051 // call this after broadcasting so we do not increment
1052 // if we throw an exeption.
1053 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001054 }
1055 } catch (RemoteException e) {
1056 return false;
1057 }
1058 } else {
1059 Intent providerIntent = new Intent();
1060 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1061 try {
1062 synchronized (this) {
1063 // synchronize to ensure incrementPendingBroadcastsLocked()
1064 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001065 mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
Lifu Tang519f0d02018-04-12 16:39:39 -07001066 getResolutionPermission(mAllowedResolutionLevel),
1067 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
Mike Lockwood48f17512009-04-23 09:12:08 -07001068 // call this after broadcasting so we do not increment
1069 // if we throw an exeption.
1070 incrementPendingBroadcastsLocked();
1071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 } catch (PendingIntent.CanceledException e) {
1073 return false;
1074 }
1075 }
1076 return true;
1077 }
1078
Nick Pellyf1be6862012-05-15 10:53:42 -07001079 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001080 public void binderDied() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001081 if (D) Log.d(TAG, "Location listener died");
1082
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001083 synchronized (mLock) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084 removeUpdatesLocked(this);
1085 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001086 synchronized (this) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001087 clearPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001088 }
1089 }
1090
Nick Pellye0fd6932012-07-11 10:26:13 -07001091 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001092 public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1093 int resultCode, String resultData, Bundle resultExtras) {
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001094 synchronized (this) {
1095 decrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001096 }
1097 }
1098
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001099 // this must be called while synchronized by caller in a synchronized block
1100 // containing the sending of the broadcaset
1101 private void incrementPendingBroadcastsLocked() {
1102 if (mPendingBroadcasts++ == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001103 mWakeLock.acquire();
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001104 }
1105 }
1106
1107 private void decrementPendingBroadcastsLocked() {
1108 if (--mPendingBroadcasts == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001109 if (mWakeLock.isHeld()) {
1110 mWakeLock.release();
1111 }
1112 }
1113 }
1114
1115 public void clearPendingBroadcastsLocked() {
1116 if (mPendingBroadcasts > 0) {
1117 mPendingBroadcasts = 0;
1118 if (mWakeLock.isHeld()) {
1119 mWakeLock.release();
1120 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001121 }
1122 }
1123 }
1124
Nick Pellye0fd6932012-07-11 10:26:13 -07001125 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001126 public void locationCallbackFinished(ILocationListener listener) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001127 //Do not use getReceiverLocked here as that will add the ILocationListener to
Joshua Bartel080b61b2009-10-05 12:44:46 -04001128 //the receiver list if it is not found. If it is not found then the
1129 //LocationListener was removed when it had a pending broadcast and should
1130 //not be added back.
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001131 synchronized (mLock) {
1132 IBinder binder = listener.asBinder();
1133 Receiver receiver = mReceivers.get(binder);
1134 if (receiver != null) {
1135 synchronized (receiver) {
1136 // so wakelock calls will succeed
1137 long identity = Binder.clearCallingIdentity();
1138 receiver.decrementPendingBroadcastsLocked();
1139 Binder.restoreCallingIdentity(identity);
David Christie2ff96af2014-01-30 16:09:37 -08001140 }
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001141 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001142 }
1143 }
1144
Lifu Tang82f893d2016-01-21 18:15:33 -08001145 /**
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001146 * Returns the year of the GNSS hardware.
Lifu Tang82f893d2016-01-21 18:15:33 -08001147 */
1148 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001149 public int getGnssYearOfHardware() {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001150 if (mGnssSystemInfoProvider != null) {
Lifu Tang9363b942016-02-16 18:07:00 -08001151 return mGnssSystemInfoProvider.getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001152 } else {
1153 return 0;
1154 }
1155 }
1156
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001157
1158 /**
1159 * Returns the model name of the GNSS hardware.
1160 */
1161 @Override
Wyatt Riley49097c02018-03-15 09:14:43 -07001162 @Nullable
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001163 public String getGnssHardwareModelName() {
1164 if (mGnssSystemInfoProvider != null) {
1165 return mGnssSystemInfoProvider.getGnssHardwareModelName();
1166 } else {
Wyatt Riley49097c02018-03-15 09:14:43 -07001167 return null;
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001168 }
1169 }
1170
Wyatt Rileycf879db2017-01-12 13:57:38 -08001171 /**
1172 * Runs some checks for GNSS (FINE) level permissions, used by several methods which directly
1173 * (try to) access GNSS information at this layer.
1174 */
1175 private boolean hasGnssPermissions(String packageName) {
1176 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
1177 checkResolutionLevelIsSufficientForProviderUse(
1178 allowedResolutionLevel,
1179 LocationManager.GPS_PROVIDER);
1180
1181 int pid = Binder.getCallingPid();
1182 int uid = Binder.getCallingUid();
1183 long identity = Binder.clearCallingIdentity();
1184 boolean hasLocationAccess;
1185 try {
1186 hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
1187 } finally {
1188 Binder.restoreCallingIdentity(identity);
1189 }
1190
1191 return hasLocationAccess;
1192 }
1193
1194 /**
1195 * Returns the GNSS batching size, if available.
1196 */
1197 @Override
1198 public int getGnssBatchSize(String packageName) {
1199 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1200 "Location Hardware permission not granted to access hardware batching");
1201
1202 if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
Yu-Han Yang3557cc72018-03-21 12:48:36 -07001203 return mGnssBatchingProvider.getBatchSize();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001204 } else {
1205 return 0;
1206 }
1207 }
1208
1209 /**
1210 * Adds a callback for GNSS Batching events, if permissions allow, which are transported
1211 * to potentially multiple listeners by the BatchedLocationCallbackTransport above this.
1212 */
1213 @Override
1214 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) {
1215 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1216 "Location Hardware permission not granted to access hardware batching");
1217
1218 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1219 return false;
1220 }
1221
1222 mGnssBatchingCallback = callback;
1223 mGnssBatchingDeathCallback = new LinkedCallback(callback);
1224 try {
1225 callback.asBinder().linkToDeath(mGnssBatchingDeathCallback, 0 /* flags */);
1226 } catch (RemoteException e) {
1227 // if the remote process registering the listener is already dead, just swallow the
1228 // exception and return
1229 Log.e(TAG, "Remote listener already died.", e);
1230 return false;
1231 }
1232
1233 return true;
1234 }
1235
1236 private class LinkedCallback implements IBinder.DeathRecipient {
1237 private final IBatchedLocationCallback mCallback;
1238
1239 public LinkedCallback(@NonNull IBatchedLocationCallback callback) {
1240 mCallback = callback;
1241 }
1242
1243 @NonNull
1244 public IBatchedLocationCallback getUnderlyingListener() {
1245 return mCallback;
1246 }
1247
1248 @Override
1249 public void binderDied() {
1250 Log.d(TAG, "Remote Batching Callback died: " + mCallback);
1251 stopGnssBatch();
1252 removeGnssBatchingCallback();
1253 }
1254 }
1255
1256 /**
1257 * Removes callback for GNSS batching
1258 */
1259 @Override
1260 public void removeGnssBatchingCallback() {
1261 try {
1262 mGnssBatchingCallback.asBinder().unlinkToDeath(mGnssBatchingDeathCallback,
1263 0 /* flags */);
1264 } catch (NoSuchElementException e) {
1265 // if the death callback isn't connected (it should be...), log error, swallow the
1266 // exception and return
1267 Log.e(TAG, "Couldn't unlink death callback.", e);
1268 }
1269 mGnssBatchingCallback = null;
1270 mGnssBatchingDeathCallback = null;
1271 }
1272
1273
1274 /**
1275 * Starts GNSS batching, if available.
1276 */
1277 @Override
1278 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
1279 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1280 "Location Hardware permission not granted to access hardware batching");
1281
1282 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1283 return false;
1284 }
1285
1286 if (mGnssBatchingInProgress) {
1287 // Current design does not expect multiple starts to be called repeatedly
1288 Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch");
1289 // Try to clean up anyway, and continue
1290 stopGnssBatch();
1291 }
1292
1293 mGnssBatchingInProgress = true;
1294 return mGnssBatchingProvider.start(periodNanos, wakeOnFifoFull);
1295 }
1296
1297 /**
1298 * Flushes a GNSS batch in progress
1299 */
1300 @Override
1301 public void flushGnssBatch(String packageName) {
1302 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1303 "Location Hardware permission not granted to access hardware batching");
1304
1305 if (!hasGnssPermissions(packageName)) {
1306 Log.e(TAG, "flushGnssBatch called without GNSS permissions");
1307 return;
1308 }
1309
1310 if (!mGnssBatchingInProgress) {
1311 Log.w(TAG, "flushGnssBatch called with no batch in progress");
1312 }
1313
1314 if (mGnssBatchingProvider != null) {
gomo48f1a642017-11-10 20:35:46 -08001315 mGnssBatchingProvider.flush();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001316 }
1317 }
1318
1319 /**
1320 * Stops GNSS batching
1321 */
1322 @Override
1323 public boolean stopGnssBatch() {
1324 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1325 "Location Hardware permission not granted to access hardware batching");
1326
1327 if (mGnssBatchingProvider != null) {
1328 mGnssBatchingInProgress = false;
1329 return mGnssBatchingProvider.stop();
gomo48f1a642017-11-10 20:35:46 -08001330 } else {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001331 return false;
1332 }
1333 }
1334
1335 @Override
1336 public void reportLocationBatch(List<Location> locations) {
1337 checkCallerIsProvider();
1338
1339 // Currently used only for GNSS locations - update permissions check if changed
1340 if (isAllowedByCurrentUserSettingsLocked(LocationManager.GPS_PROVIDER)) {
1341 if (mGnssBatchingCallback == null) {
1342 Slog.e(TAG, "reportLocationBatch() called without active Callback");
1343 return;
1344 }
1345 try {
1346 mGnssBatchingCallback.onLocationBatch(locations);
1347 } catch (RemoteException e) {
1348 Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e);
1349 }
1350 } else {
1351 Slog.w(TAG, "reportLocationBatch() called without user permission, locations blocked");
1352 }
1353 }
1354
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001355 private void addProviderLocked(LocationProviderInterface provider) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001356 mProviders.add(provider);
1357 mProvidersByName.put(provider.getName(), provider);
1358 }
1359
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001360 private void removeProviderLocked(LocationProviderInterface provider) {
1361 provider.disable();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001362 mProviders.remove(provider);
1363 mProvidersByName.remove(provider.getName());
1364 }
1365
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001366 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001367 * Returns "true" if access to the specified location provider is allowed by the current
1368 * user's settings. Access to all location providers is forbidden to non-location-provider
1369 * processes belonging to background users.
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001370 *
1371 * @param provider the name of the location provider
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001372 */
Victoria Lease09eeaec2013-02-05 11:34:13 -08001373 private boolean isAllowedByCurrentUserSettingsLocked(String provider) {
Maggie2a9409e2018-03-21 11:47:28 -07001374 return isAllowedByUserSettingsLockedForUser(provider, mCurrentUserId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 }
1376
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001377 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001378 * Returns "true" if access to the specified location provider is allowed by the specified
1379 * user's settings. Access to all location providers is forbidden to non-location-provider
1380 * processes belonging to background users.
1381 *
1382 * @param provider the name of the location provider
Maggie2a9409e2018-03-21 11:47:28 -07001383 * @param userId the user id to query
Victoria Lease09eeaec2013-02-05 11:34:13 -08001384 */
Maggie2a9409e2018-03-21 11:47:28 -07001385 private boolean isAllowedByUserSettingsLockedForUser(String provider, int userId) {
1386 if (mEnabledProviders.contains(provider)) {
1387 return true;
1388 }
1389 if (mDisabledProviders.contains(provider)) {
1390 return false;
1391 }
1392 return isLocationProviderEnabledForUser(provider, userId);
1393 }
1394
1395
1396 /**
1397 * Returns "true" if access to the specified location provider is allowed by the specified
1398 * user's settings. Access to all location providers is forbidden to non-location-provider
1399 * processes belonging to background users.
1400 *
1401 * @param provider the name of the location provider
1402 * @param uid the requestor's UID
1403 * @param userId the user id to query
1404 */
1405 private boolean isAllowedByUserSettingsLocked(String provider, int uid, int userId) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001406 if (!isCurrentProfile(UserHandle.getUserId(uid)) && !isUidALocationProvider(uid)) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08001407 return false;
1408 }
Maggie2a9409e2018-03-21 11:47:28 -07001409 return isAllowedByUserSettingsLockedForUser(provider, userId);
Victoria Lease09eeaec2013-02-05 11:34:13 -08001410 }
1411
1412 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001413 * Returns the permission string associated with the specified resolution level.
1414 *
1415 * @param resolutionLevel the resolution level
1416 * @return the permission string
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001417 */
Victoria Lease37425c32012-10-16 16:08:48 -07001418 private String getResolutionPermission(int resolutionLevel) {
1419 switch (resolutionLevel) {
1420 case RESOLUTION_LEVEL_FINE:
1421 return android.Manifest.permission.ACCESS_FINE_LOCATION;
1422 case RESOLUTION_LEVEL_COARSE:
1423 return android.Manifest.permission.ACCESS_COARSE_LOCATION;
1424 default:
1425 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001426 }
Victoria Leaseda479c52012-10-15 15:24:16 -07001427 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001428
Victoria Leaseda479c52012-10-15 15:24:16 -07001429 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001430 * Returns the resolution level allowed to the given PID/UID pair.
1431 *
1432 * @param pid the PID
1433 * @param uid the UID
1434 * @return resolution level allowed to the pid/uid pair
Victoria Leaseda479c52012-10-15 15:24:16 -07001435 */
Victoria Lease37425c32012-10-16 16:08:48 -07001436 private int getAllowedResolutionLevel(int pid, int uid) {
1437 if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001438 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001439 return RESOLUTION_LEVEL_FINE;
1440 } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001441 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001442 return RESOLUTION_LEVEL_COARSE;
1443 } else {
1444 return RESOLUTION_LEVEL_NONE;
Victoria Leaseda479c52012-10-15 15:24:16 -07001445 }
Victoria Lease4fab68b2012-09-13 13:20:59 -07001446 }
1447
1448 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001449 * Returns the resolution level allowed to the caller
1450 *
1451 * @return resolution level allowed to caller
Victoria Lease4fab68b2012-09-13 13:20:59 -07001452 */
Victoria Lease37425c32012-10-16 16:08:48 -07001453 private int getCallerAllowedResolutionLevel() {
1454 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
1455 }
1456
1457 /**
1458 * Throw SecurityException if specified resolution level is insufficient to use geofences.
1459 *
1460 * @param allowedResolutionLevel resolution level allowed to caller
1461 */
1462 private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
1463 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Lease4fab68b2012-09-13 13:20:59 -07001464 throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
1465 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001466 }
1467
Victoria Lease37425c32012-10-16 16:08:48 -07001468 /**
1469 * Return the minimum resolution level required to use the specified location provider.
1470 *
1471 * @param provider the name of the location provider
1472 * @return minimum resolution level required for provider
1473 */
1474 private int getMinimumResolutionLevelForProviderUse(String provider) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001475 if (LocationManager.GPS_PROVIDER.equals(provider) ||
1476 LocationManager.PASSIVE_PROVIDER.equals(provider)) {
1477 // gps and passive providers require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001478 return RESOLUTION_LEVEL_FINE;
Victoria Lease8dbb6342012-09-21 16:55:53 -07001479 } else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
1480 LocationManager.FUSED_PROVIDER.equals(provider)) {
1481 // network and fused providers are ok with COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001482 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001483 } else {
1484 // mock providers
1485 LocationProviderInterface lp = mMockProviders.get(provider);
1486 if (lp != null) {
1487 ProviderProperties properties = lp.getProperties();
1488 if (properties != null) {
1489 if (properties.mRequiresSatellite) {
1490 // provider requiring satellites require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001491 return RESOLUTION_LEVEL_FINE;
Laurent Tu941221c2012-10-04 14:21:52 -07001492 } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
1493 // provider requiring network and or cell require COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001494 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001495 }
1496 }
1497 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001498 }
Victoria Lease37425c32012-10-16 16:08:48 -07001499 return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
Victoria Leaseda479c52012-10-15 15:24:16 -07001500 }
1501
Victoria Lease37425c32012-10-16 16:08:48 -07001502 /**
1503 * Throw SecurityException if specified resolution level is insufficient to use the named
1504 * location provider.
1505 *
1506 * @param allowedResolutionLevel resolution level allowed to caller
gomo48f1a642017-11-10 20:35:46 -08001507 * @param providerName the name of the location provider
Victoria Lease37425c32012-10-16 16:08:48 -07001508 */
1509 private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel,
1510 String providerName) {
1511 int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName);
1512 if (allowedResolutionLevel < requiredResolutionLevel) {
1513 switch (requiredResolutionLevel) {
1514 case RESOLUTION_LEVEL_FINE:
1515 throw new SecurityException("\"" + providerName + "\" location provider " +
1516 "requires ACCESS_FINE_LOCATION permission.");
1517 case RESOLUTION_LEVEL_COARSE:
1518 throw new SecurityException("\"" + providerName + "\" location provider " +
1519 "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
1520 default:
1521 throw new SecurityException("Insufficient permission for \"" + providerName +
1522 "\" location provider.");
Victoria Leaseda479c52012-10-15 15:24:16 -07001523 }
1524 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001525 }
1526
David Christie82edc9b2013-07-19 11:31:42 -07001527 /**
1528 * Throw SecurityException if WorkSource use is not allowed (i.e. can't blame other packages
1529 * for battery).
1530 */
David Christie40e57822013-07-30 11:36:48 -07001531 private void checkDeviceStatsAllowed() {
David Christie82edc9b2013-07-19 11:31:42 -07001532 mContext.enforceCallingOrSelfPermission(
1533 android.Manifest.permission.UPDATE_DEVICE_STATS, null);
1534 }
1535
David Christie40e57822013-07-30 11:36:48 -07001536 private void checkUpdateAppOpsAllowed() {
1537 mContext.enforceCallingOrSelfPermission(
1538 android.Manifest.permission.UPDATE_APP_OPS_STATS, null);
1539 }
1540
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001541 public static int resolutionLevelToOp(int allowedResolutionLevel) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001542 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
1543 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001544 return AppOpsManager.OP_COARSE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001545 } else {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001546 return AppOpsManager.OP_FINE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001547 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001548 }
1549 return -1;
1550 }
1551
David Christieb870dbf2015-06-22 12:42:53 -07001552 boolean reportLocationAccessNoThrow(
1553 int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001554 int op = resolutionLevelToOp(allowedResolutionLevel);
1555 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001556 if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1557 return false;
1558 }
1559 }
David Christieb870dbf2015-06-22 12:42:53 -07001560
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001561 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001562 }
1563
David Christieb870dbf2015-06-22 12:42:53 -07001564 boolean checkLocationAccess(int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001565 int op = resolutionLevelToOp(allowedResolutionLevel);
1566 if (op >= 0) {
Wei Wangdd070f22018-06-21 11:29:40 -07001567 if (mAppOps.noteOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001568 return false;
1569 }
1570 }
David Christieb870dbf2015-06-22 12:42:53 -07001571
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001572 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001573 }
1574
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001575 /**
Maggie91e630c2018-01-24 17:31:46 -08001576 * Returns all providers by name, including passive and the ones that are not permitted to
1577 * be accessed by the calling activity or are currently disabled, but excluding fused.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001578 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001579 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 public List<String> getAllProviders() {
Maggie91e630c2018-01-24 17:31:46 -08001581 ArrayList<String> out;
1582 synchronized (mLock) {
1583 out = new ArrayList<>(mProviders.size());
1584 for (LocationProviderInterface provider : mProviders) {
1585 String name = provider.getName();
1586 if (LocationManager.FUSED_PROVIDER.equals(name)) {
1587 continue;
1588 }
1589 out.add(name);
1590 }
1591 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001592 if (D) Log.d(TAG, "getAllProviders()=" + out);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001593 return out;
1594 }
1595
Mike Lockwood03ca2162010-04-01 08:10:09 -07001596 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001597 * Return all providers by name, that match criteria and are optionally
1598 * enabled.
1599 * Can return passive provider, but never returns fused provider.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001600 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001601 @Override
1602 public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
Victoria Lease37425c32012-10-16 16:08:48 -07001603 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001604 ArrayList<String> out;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001605 int uid = Binder.getCallingUid();
Victoria Lease269518e2012-10-29 08:25:39 -07001606 long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07001607 try {
1608 synchronized (mLock) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001609 out = new ArrayList<>(mProviders.size());
Victoria Leaseb711d572012-10-02 13:14:11 -07001610 for (LocationProviderInterface provider : mProviders) {
1611 String name = provider.getName();
1612 if (LocationManager.FUSED_PROVIDER.equals(name)) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001613 continue;
1614 }
Victoria Lease37425c32012-10-16 16:08:48 -07001615 if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
Maggie2a9409e2018-03-21 11:47:28 -07001616 if (enabledOnly
1617 && !isAllowedByUserSettingsLocked(name, uid, mCurrentUserId)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001618 continue;
1619 }
1620 if (criteria != null && !LocationProvider.propertiesMeetCriteria(
1621 name, provider.getProperties(), criteria)) {
1622 continue;
1623 }
1624 out.add(name);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001625 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001626 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001627 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001628 } finally {
1629 Binder.restoreCallingIdentity(identity);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001630 }
1631
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001632 if (D) Log.d(TAG, "getProviders()=" + out);
1633 return out;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001634 }
1635
1636 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001637 * Return the name of the best provider given a Criteria object.
1638 * This method has been deprecated from the public API,
Victoria Lease8dbb6342012-09-21 16:55:53 -07001639 * and the whole LocationProvider (including #meetsCriteria)
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001640 * has been deprecated as well. So this method now uses
1641 * some simplified logic.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001642 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001643 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001644 public String getBestProvider(Criteria criteria, boolean enabledOnly) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001645 String result = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001646
1647 List<String> providers = getProviders(criteria, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001648 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001649 result = pickBest(providers);
1650 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1651 return result;
1652 }
1653 providers = getProviders(null, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001654 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001655 result = pickBest(providers);
1656 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1657 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001658 }
1659
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001660 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001661 return null;
1662 }
1663
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001664 private String pickBest(List<String> providers) {
Victoria Lease1925e292012-09-24 17:00:18 -07001665 if (providers.contains(LocationManager.GPS_PROVIDER)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001666 return LocationManager.GPS_PROVIDER;
Victoria Lease1925e292012-09-24 17:00:18 -07001667 } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
1668 return LocationManager.NETWORK_PROVIDER;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001669 } else {
1670 return providers.get(0);
1671 }
1672 }
1673
Nick Pellye0fd6932012-07-11 10:26:13 -07001674 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001675 public boolean providerMeetsCriteria(String provider, Criteria criteria) {
1676 LocationProviderInterface p = mProvidersByName.get(provider);
1677 if (p == null) {
1678 throw new IllegalArgumentException("provider=" + provider);
1679 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001680
1681 boolean result = LocationProvider.propertiesMeetCriteria(
1682 p.getName(), p.getProperties(), criteria);
1683 if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result);
1684 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001685 }
1686
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 private void updateProvidersLocked() {
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001688 boolean changesMade = false;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001689 for (int i = mProviders.size() - 1; i >= 0; i--) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001690 LocationProviderInterface p = mProviders.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001691 boolean isEnabled = p.isEnabled();
1692 String name = p.getName();
Victoria Lease09eeaec2013-02-05 11:34:13 -08001693 boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001694 if (isEnabled && !shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001695 updateProviderListenersLocked(name, false);
David Christieb084fef2013-12-18 14:33:57 -08001696 // If any provider has been disabled, clear all last locations for all providers.
1697 // This is to be on the safe side in case a provider has location derived from
1698 // this disabled provider.
1699 mLastLocation.clear();
1700 mLastLocationCoarseInterval.clear();
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001701 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 } else if (!isEnabled && shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001703 updateProviderListenersLocked(name, true);
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001704 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001705 }
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001706 }
1707 if (changesMade) {
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001708 mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
1709 UserHandle.ALL);
Tom O'Neill40a86c22013-09-03 18:05:13 -07001710 mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
1711 UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001712 }
1713 }
1714
Amith Yamasanib27528d2014-06-05 15:02:10 -07001715 private void updateProviderListenersLocked(String provider, boolean enabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001716 int listeners = 0;
1717
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001718 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001719 if (p == null) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720
1721 ArrayList<Receiver> deadReceivers = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07001722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001723 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1724 if (records != null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001725 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001726 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001727 // Sends a notification message to the receiver
1728 if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
1729 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001730 deadReceivers = new ArrayList<>();
Victoria Leaseb711d572012-10-02 13:14:11 -07001731 }
1732 deadReceivers.add(record.mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001733 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001734 listeners++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001735 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736 }
1737 }
1738
1739 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001740 for (int i = deadReceivers.size() - 1; i >= 0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001741 removeUpdatesLocked(deadReceivers.get(i));
1742 }
1743 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 if (enabled) {
1746 p.enable();
1747 if (listeners > 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001748 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001749 }
1750 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001751 p.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001752 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001753 }
1754
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001755 private void applyRequirementsLocked(String provider) {
1756 LocationProviderInterface p = mProvidersByName.get(provider);
1757 if (p == null) return;
1758
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001759 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001760 WorkSource worksource = new WorkSource();
1761 ProviderRequest providerRequest = new ProviderRequest();
1762
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001763 ContentResolver resolver = mContext.getContentResolver();
1764 long backgroundThrottleInterval = Settings.Global.getLong(
1765 resolver,
1766 Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
1767 DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
gomo48f1a642017-11-10 20:35:46 -08001768 // initialize the low power mode to true and set to false if any of the records requires
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001769
gomo48f1a642017-11-10 20:35:46 -08001770 providerRequest.lowPowerMode = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771 if (records != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001772 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001773 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
David Christieb870dbf2015-06-22 12:42:53 -07001774 if (checkLocationAccess(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001775 record.mReceiver.mIdentity.mPid,
1776 record.mReceiver.mIdentity.mUid,
1777 record.mReceiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001778 record.mReceiver.mAllowedResolutionLevel)) {
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001779 LocationRequest locationRequest = record.mRealRequest;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001780 long interval = locationRequest.getInterval();
1781
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001782 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001783 if (!record.mIsForegroundUid) {
1784 interval = Math.max(interval, backgroundThrottleInterval);
1785 }
1786 if (interval != locationRequest.getInterval()) {
1787 locationRequest = new LocationRequest(locationRequest);
1788 locationRequest.setInterval(interval);
1789 }
1790 }
1791
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001792 record.mRequest = locationRequest;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001793 providerRequest.locationRequests.add(locationRequest);
gomo48f1a642017-11-10 20:35:46 -08001794 if (!locationRequest.isLowPowerMode()) {
1795 providerRequest.lowPowerMode = false;
1796 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001797 if (interval < providerRequest.interval) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001798 providerRequest.reportLocation = true;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001799 providerRequest.interval = interval;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001800 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001801 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001802 }
1803 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001804
1805 if (providerRequest.reportLocation) {
1806 // calculate who to blame for power
1807 // This is somewhat arbitrary. We pick a threshold interval
1808 // that is slightly higher that the minimum interval, and
1809 // spread the blame across all applications with a request
1810 // under that threshold.
1811 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
1812 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001813 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001814 LocationRequest locationRequest = record.mRequest;
Svet Ganove998c732016-06-10 00:12:38 -07001815
1816 // Don't assign battery blame for update records whose
1817 // client has no permission to receive location data.
1818 if (!providerRequest.locationRequests.contains(locationRequest)) {
1819 continue;
1820 }
1821
Victoria Leaseb711d572012-10-02 13:14:11 -07001822 if (locationRequest.getInterval() <= thresholdInterval) {
David Christiee55c9682013-08-22 10:10:34 -07001823 if (record.mReceiver.mWorkSource != null
Narayan Kamath32684dd2018-01-08 17:32:51 +00001824 && isValidWorkSource(record.mReceiver.mWorkSource)) {
David Christie82edc9b2013-07-19 11:31:42 -07001825 worksource.add(record.mReceiver.mWorkSource);
1826 } else {
Narayan Kamath32684dd2018-01-08 17:32:51 +00001827 // Assign blame to caller if there's no WorkSource associated with
1828 // the request or if it's invalid.
David Christie82edc9b2013-07-19 11:31:42 -07001829 worksource.add(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001830 record.mReceiver.mIdentity.mUid,
1831 record.mReceiver.mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001832 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001833 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001834 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001835 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001836 }
1837 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001838
1839 if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
1840 p.setRequest(providerRequest, worksource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001841 }
1842
Narayan Kamath32684dd2018-01-08 17:32:51 +00001843 /**
1844 * Whether a given {@code WorkSource} associated with a Location request is valid.
1845 */
1846 private static boolean isValidWorkSource(WorkSource workSource) {
1847 if (workSource.size() > 0) {
1848 // If the WorkSource has one or more non-chained UIDs, make sure they're accompanied
1849 // by tags.
1850 return workSource.getName(0) != null;
1851 } else {
1852 // For now, make sure callers have supplied an attribution tag for use with
1853 // AppOpsManager. This might be relaxed in the future.
1854 final ArrayList<WorkChain> workChains = workSource.getWorkChains();
1855 return workChains != null && !workChains.isEmpty() &&
1856 workChains.get(0).getAttributionTag() != null;
1857 }
1858 }
1859
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001860 @Override
1861 public String[] getBackgroundThrottlingWhitelist() {
1862 synchronized (mLock) {
1863 return mBackgroundThrottlePackageWhitelist.toArray(
gomo48f1a642017-11-10 20:35:46 -08001864 new String[mBackgroundThrottlePackageWhitelist.size()]);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001865 }
1866 }
1867
1868 private void updateBackgroundThrottlingWhitelistLocked() {
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001869 String setting = Settings.Global.getString(
gomo48f1a642017-11-10 20:35:46 -08001870 mContext.getContentResolver(),
1871 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001872 if (setting == null) {
1873 setting = "";
1874 }
1875
1876 mBackgroundThrottlePackageWhitelist.clear();
1877 mBackgroundThrottlePackageWhitelist.addAll(
gomo48f1a642017-11-10 20:35:46 -08001878 SystemConfig.getInstance().getAllowUnthrottledLocation());
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001879 mBackgroundThrottlePackageWhitelist.addAll(
gomo48f1a642017-11-10 20:35:46 -08001880 Arrays.asList(setting.split(",")));
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001881 }
1882
Wei Wangdd070f22018-06-21 11:29:40 -07001883 private void updateLastLocationMaxAgeLocked() {
1884 mLastLocationMaxAgeMs =
1885 Settings.Global.getLong(
1886 mContext.getContentResolver(),
1887 Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
1888 DEFAULT_LAST_LOCATION_MAX_AGE_MS);
1889 }
1890
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001891 private boolean isThrottlingExemptLocked(Identity identity) {
1892 if (identity.mUid == Process.SYSTEM_UID) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001893 return true;
1894 }
1895
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001896 if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001897 return true;
1898 }
1899
1900 for (LocationProviderProxy provider : mProxyProviders) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001901 if (identity.mPackageName.equals(provider.getConnectedPackageName())) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001902 return true;
1903 }
1904 }
1905
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001906 return false;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001907 }
1908
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001909 private class UpdateRecord {
1910 final String mProvider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001911 final LocationRequest mRealRequest; // original request from client
1912 LocationRequest mRequest; // possibly throttled version of the request
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001913 final Receiver mReceiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001914 boolean mIsForegroundUid;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001915 Location mLastFixBroadcast;
1916 long mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001917
1918 /**
1919 * Note: must be constructed with lock held.
1920 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001921 UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001922 mProvider = provider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001923 mRealRequest = request;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001924 mRequest = request;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001925 mReceiver = receiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001926 mIsForegroundUid = isImportanceForeground(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001927 mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001928
1929 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1930 if (records == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001931 records = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001932 mRecordsByProvider.put(provider, records);
1933 }
1934 if (!records.contains(this)) {
1935 records.add(this);
1936 }
David Christie2ff96af2014-01-30 16:09:37 -08001937
1938 // Update statistics for historical location requests by package/provider
1939 mRequestStatistics.startRequesting(
Wyatt Rileyf7075e02018-04-12 17:54:26 -07001940 mReceiver.mIdentity.mPackageName, provider, request.getInterval(),
1941 mIsForegroundUid);
1942 }
1943
1944 /**
1945 * Method to be called when record changes foreground/background
1946 */
1947 void updateForeground(boolean isForeground){
1948 mIsForegroundUid = isForeground;
1949 mRequestStatistics.updateForeground(
1950 mReceiver.mIdentity.mPackageName, mProvider, isForeground);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001951 }
1952
1953 /**
David Christie2ff96af2014-01-30 16:09:37 -08001954 * Method to be called when a record will no longer be used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001955 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001956 void disposeLocked(boolean removeReceiver) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001957 mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider);
David Christie2ff96af2014-01-30 16:09:37 -08001958
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001959 // remove from mRecordsByProvider
1960 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
1961 if (globalRecords != null) {
1962 globalRecords.remove(this);
1963 }
1964
1965 if (!removeReceiver) return; // the caller will handle the rest
1966
1967 // remove from Receiver#mUpdateRecords
1968 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
1969 if (receiverRecords != null) {
1970 receiverRecords.remove(this.mProvider);
1971
1972 // and also remove the Receiver if it has no more update records
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001973 if (receiverRecords.size() == 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001974 removeUpdatesLocked(mReceiver);
1975 }
Mike Lockwood3a76fd62009-09-01 07:26:56 -04001976 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001977 }
1978
1979 @Override
1980 public String toString() {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001981 return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
gomo48f1a642017-11-10 20:35:46 -08001982 + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground"
1983 : " background")
Wyatt Riley19adc022018-05-22 13:30:51 -07001984 + ")" + " " + mRealRequest + " "
1985 + mReceiver.mWorkSource + "]";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001986 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001987 }
1988
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001989 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -07001990 String packageName, WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001991 IBinder binder = listener.asBinder();
1992 Receiver receiver = mReceivers.get(binder);
1993 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07001994 receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
1995 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001996 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001997 receiver.getListener().asBinder().linkToDeath(receiver, 0);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001998 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001999 Slog.e(TAG, "linkToDeath failed:", e);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002000 return null;
2001 }
Wen Jingcb3ab222014-03-27 13:42:59 +08002002 mReceivers.put(binder, receiver);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002003 }
2004 return receiver;
2005 }
2006
David Christie82edc9b2013-07-19 11:31:42 -07002007 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
David Christie40e57822013-07-30 11:36:48 -07002008 WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002009 Receiver receiver = mReceivers.get(intent);
2010 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07002011 receiver = new Receiver(null, intent, pid, uid, packageName, workSource,
2012 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002013 mReceivers.put(intent, receiver);
2014 }
2015 return receiver;
2016 }
2017
Victoria Lease37425c32012-10-16 16:08:48 -07002018 /**
2019 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
2020 * and consistency requirements.
2021 *
2022 * @param request the LocationRequest from which to create a sanitized version
Victoria Lease37425c32012-10-16 16:08:48 -07002023 * @return a version of request that meets the given resolution and consistency requirements
2024 * @hide
2025 */
gomo48f1a642017-11-10 20:35:46 -08002026 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel,
2027 boolean callerHasLocationHardwarePermission) {
Victoria Lease37425c32012-10-16 16:08:48 -07002028 LocationRequest sanitizedRequest = new LocationRequest(request);
gomo48f1a642017-11-10 20:35:46 -08002029 if (!callerHasLocationHardwarePermission) {
2030 // allow setting low power mode only for callers with location hardware permission
2031 sanitizedRequest.setLowPowerMode(false);
2032 }
Victoria Lease37425c32012-10-16 16:08:48 -07002033 if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
2034 switch (sanitizedRequest.getQuality()) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002035 case LocationRequest.ACCURACY_FINE:
Victoria Lease37425c32012-10-16 16:08:48 -07002036 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
Victoria Lease09016ab2012-09-16 12:33:15 -07002037 break;
2038 case LocationRequest.POWER_HIGH:
Victoria Lease37425c32012-10-16 16:08:48 -07002039 sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
Victoria Lease09016ab2012-09-16 12:33:15 -07002040 break;
2041 }
2042 // throttle
Victoria Lease37425c32012-10-16 16:08:48 -07002043 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
2044 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07002045 }
Victoria Lease37425c32012-10-16 16:08:48 -07002046 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
2047 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07002048 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07002049 }
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002050 // make getFastestInterval() the minimum of interval and fastest interval
Victoria Lease37425c32012-10-16 16:08:48 -07002051 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002052 request.setFastestInterval(request.getInterval());
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002053 }
Victoria Lease37425c32012-10-16 16:08:48 -07002054 return sanitizedRequest;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002055 }
2056
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002057 private void checkPackageName(String packageName) {
Nick Pellye0fd6932012-07-11 10:26:13 -07002058 if (packageName == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002059 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002060 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002061 int uid = Binder.getCallingUid();
Nick Pellye0fd6932012-07-11 10:26:13 -07002062 String[] packages = mPackageManager.getPackagesForUid(uid);
2063 if (packages == null) {
2064 throw new SecurityException("invalid UID " + uid);
2065 }
2066 for (String pkg : packages) {
2067 if (packageName.equals(pkg)) return;
2068 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002069 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002070 }
2071
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002072 private void checkPendingIntent(PendingIntent intent) {
2073 if (intent == null) {
2074 throw new IllegalArgumentException("invalid pending intent: " + intent);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002075 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002076 }
2077
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002078 private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent,
David Christie40e57822013-07-30 11:36:48 -07002079 int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002080 if (intent == null && listener == null) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002081 throw new IllegalArgumentException("need either listener or intent");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002082 } else if (intent != null && listener != null) {
2083 throw new IllegalArgumentException("cannot register both listener and intent");
2084 } else if (intent != null) {
2085 checkPendingIntent(intent);
David Christie40e57822013-07-30 11:36:48 -07002086 return getReceiverLocked(intent, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002087 } else {
David Christie40e57822013-07-30 11:36:48 -07002088 return getReceiverLocked(listener, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002089 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002090 }
2091
Nick Pellye0fd6932012-07-11 10:26:13 -07002092 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002093 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
2094 PendingIntent intent, String packageName) {
2095 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2096 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002097 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2098 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2099 request.getProvider());
David Christie82edc9b2013-07-19 11:31:42 -07002100 WorkSource workSource = request.getWorkSource();
Narayan Kamath32684dd2018-01-08 17:32:51 +00002101 if (workSource != null && !workSource.isEmpty()) {
David Christie40e57822013-07-30 11:36:48 -07002102 checkDeviceStatsAllowed();
2103 }
2104 boolean hideFromAppOps = request.getHideFromAppOps();
2105 if (hideFromAppOps) {
2106 checkUpdateAppOpsAllowed();
David Christie82edc9b2013-07-19 11:31:42 -07002107 }
gomo48f1a642017-11-10 20:35:46 -08002108 boolean callerHasLocationHardwarePermission =
2109 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
Maggieaa080f92018-01-04 15:35:11 -08002110 == PERMISSION_GRANTED;
gomo48f1a642017-11-10 20:35:46 -08002111 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel,
2112 callerHasLocationHardwarePermission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002113
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002114 final int pid = Binder.getCallingPid();
2115 final int uid = Binder.getCallingUid();
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002116 // providers may use public location API's, need to clear identity
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002117 long identity = Binder.clearCallingIdentity();
2118 try {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002119 // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2120 // a location.
David Christieb870dbf2015-06-22 12:42:53 -07002121 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002122
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002123 synchronized (mLock) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002124 Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
David Christie40e57822013-07-30 11:36:48 -07002125 packageName, workSource, hideFromAppOps);
Victoria Lease37425c32012-10-16 16:08:48 -07002126 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
Mike Lockwood2d4d1bf2010-10-18 17:06:26 -04002127 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002128 } finally {
2129 Binder.restoreCallingIdentity(identity);
2130 }
2131 }
2132
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002133 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
2134 int pid, int uid, String packageName) {
2135 // Figure out the provider. Either its explicitly request (legacy use cases), or
2136 // use the fused provider
2137 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2138 String name = request.getProvider();
Victoria Lease09016ab2012-09-16 12:33:15 -07002139 if (name == null) {
2140 throw new IllegalArgumentException("provider name must not be null");
2141 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -07002142
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002143 LocationProviderInterface provider = mProvidersByName.get(name);
2144 if (provider == null) {
Victoria Leaseb30f3832013-10-13 12:15:40 -07002145 throw new IllegalArgumentException("provider doesn't exist: " + name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002146 }
2147
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002148 UpdateRecord record = new UpdateRecord(name, request, receiver);
gomo48f1a642017-11-10 20:35:46 -08002149 if (D) {
2150 Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
2151 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
2152 + (record.mIsForegroundUid ? "foreground" : "background")
2153 + (isThrottlingExemptLocked(receiver.mIdentity)
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002154 ? " [whitelisted]" : "") + ")");
gomo48f1a642017-11-10 20:35:46 -08002155 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002156
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002157 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
2158 if (oldRecord != null) {
2159 oldRecord.disposeLocked(false);
2160 }
2161
Maggie2a9409e2018-03-21 11:47:28 -07002162 boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid, mCurrentUserId);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002163 if (isProviderEnabled) {
2164 applyRequirementsLocked(name);
2165 } else {
2166 // Notify the listener that updates are currently disabled
2167 receiver.callProviderEnabledLocked(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002168 }
David Christie0b837452013-07-29 16:02:13 -07002169 // Update the monitoring here just in case multiple location requests were added to the
2170 // same receiver (this request may be high power and the initial might not have been).
2171 receiver.updateMonitoring(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002172 }
2173
Nick Pellye0fd6932012-07-11 10:26:13 -07002174 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002175 public void removeUpdates(ILocationListener listener, PendingIntent intent,
2176 String packageName) {
2177 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002178
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002179 final int pid = Binder.getCallingPid();
2180 final int uid = Binder.getCallingUid();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002181
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002182 synchronized (mLock) {
David Christie82edc9b2013-07-19 11:31:42 -07002183 WorkSource workSource = null;
David Christie40e57822013-07-30 11:36:48 -07002184 boolean hideFromAppOps = false;
2185 Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid,
2186 packageName, workSource, hideFromAppOps);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002187
2188 // providers may use public location API's, need to clear identity
2189 long identity = Binder.clearCallingIdentity();
2190 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002191 removeUpdatesLocked(receiver);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002192 } finally {
2193 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002194 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002195 }
2196 }
2197
2198 private void removeUpdatesLocked(Receiver receiver) {
Dianne Hackborn7ff30112012-11-08 11:12:09 -08002199 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002200
2201 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
2202 receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
2203 synchronized (receiver) {
Victoria Lease0aa28602013-05-29 15:28:26 -07002204 receiver.clearPendingBroadcastsLocked();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002205 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002206 }
2207
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07002208 receiver.updateMonitoring(false);
2209
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002210 // Record which providers were associated with this listener
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002211 HashSet<String> providers = new HashSet<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002212 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2213 if (oldRecords != null) {
2214 // Call dispose() on the obsolete update records.
2215 for (UpdateRecord record : oldRecords.values()) {
David Christie2ff96af2014-01-30 16:09:37 -08002216 // Update statistics for historical location requests by package/provider
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002217 record.disposeLocked(false);
2218 }
2219 // Accumulate providers
2220 providers.addAll(oldRecords.keySet());
2221 }
2222
2223 // update provider
2224 for (String provider : providers) {
2225 // If provider is already disabled, don't need to do anything
Victoria Lease09eeaec2013-02-05 11:34:13 -08002226 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002227 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002228 }
2229
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002230 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002231 }
2232 }
2233
Dianne Hackbornc2293022013-02-06 23:14:49 -08002234 private void applyAllProviderRequirementsLocked() {
2235 for (LocationProviderInterface p : mProviders) {
2236 // If provider is already disabled, don't need to do anything
Dianne Hackborn64d41d72013-02-07 00:33:31 -08002237 if (!isAllowedByCurrentUserSettingsLocked(p.getName())) {
Dianne Hackbornc2293022013-02-06 23:14:49 -08002238 continue;
2239 }
2240
2241 applyRequirementsLocked(p.getName());
2242 }
2243 }
2244
Nick Pellye0fd6932012-07-11 10:26:13 -07002245 @Override
Nick Pelly4035f5a2012-08-17 14:43:49 -07002246 public Location getLastLocation(LocationRequest request, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002247 if (D) Log.d(TAG, "getLastLocation: " + request);
2248 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002249 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly4035f5a2012-08-17 14:43:49 -07002250 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002251 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2252 request.getProvider());
2253 // no need to sanitize this request, as only the provider name is used
Nick Pelly4035f5a2012-08-17 14:43:49 -07002254
David Christieb870dbf2015-06-22 12:42:53 -07002255 final int pid = Binder.getCallingPid();
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002256 final int uid = Binder.getCallingUid();
2257 final long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07002258 try {
2259 if (mBlacklist.isBlacklisted(packageName)) {
gomo48f1a642017-11-10 20:35:46 -08002260 if (D) {
2261 Log.d(TAG, "not returning last loc for blacklisted app: " +
2262 packageName);
2263 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002264 return null;
2265 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002266
David Christieb870dbf2015-06-22 12:42:53 -07002267 if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel)) {
gomo48f1a642017-11-10 20:35:46 -08002268 if (D) {
2269 Log.d(TAG, "not returning last loc for no op app: " +
2270 packageName);
2271 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002272 return null;
2273 }
2274
Victoria Leaseb711d572012-10-02 13:14:11 -07002275 synchronized (mLock) {
2276 // Figure out the provider. Either its explicitly request (deprecated API's),
2277 // or use the fused provider
2278 String name = request.getProvider();
2279 if (name == null) name = LocationManager.FUSED_PROVIDER;
2280 LocationProviderInterface provider = mProvidersByName.get(name);
2281 if (provider == null) return null;
2282
Maggie2a9409e2018-03-21 11:47:28 -07002283 if (!isAllowedByUserSettingsLocked(name, uid, mCurrentUserId)) return null;
Victoria Leaseb711d572012-10-02 13:14:11 -07002284
David Christie1b9b7b12013-04-15 15:31:11 -07002285 Location location;
2286 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2287 // Make sure that an app with coarse permissions can't get frequent location
2288 // updates by calling LocationManager.getLastKnownLocation repeatedly.
2289 location = mLastLocationCoarseInterval.get(name);
2290 } else {
2291 location = mLastLocation.get(name);
2292 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002293 if (location == null) {
2294 return null;
2295 }
Wei Wangdd070f22018-06-21 11:29:40 -07002296
2297 // Don't return stale location to apps with foreground-only location permission.
2298 String op = getResolutionPermission(allowedResolutionLevel);
2299 long locationAgeMs = SystemClock.elapsedRealtime() -
2300 location.getElapsedRealtimeNanos() / NANOS_PER_MILLI;
2301 if ((locationAgeMs > mLastLocationMaxAgeMs)
2302 && (mAppOps.unsafeCheckOp(op, uid, packageName)
2303 == AppOpsManager.MODE_FOREGROUND)) {
2304 return null;
2305 }
2306
Victoria Lease37425c32012-10-16 16:08:48 -07002307 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
gomo48f1a642017-11-10 20:35:46 -08002308 Location noGPSLocation = location.getExtraLocation(
2309 Location.EXTRA_NO_GPS_LOCATION);
Victoria Leaseb711d572012-10-02 13:14:11 -07002310 if (noGPSLocation != null) {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002311 return new Location(mLocationFudger.getOrCreate(noGPSLocation));
Victoria Leaseb711d572012-10-02 13:14:11 -07002312 }
Victoria Lease37425c32012-10-16 16:08:48 -07002313 } else {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002314 return new Location(location);
Victoria Lease09016ab2012-09-16 12:33:15 -07002315 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002316 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002317 return null;
2318 } finally {
2319 Binder.restoreCallingIdentity(identity);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002320 }
2321 }
2322
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002323 /**
2324 * Provides an interface to inject and set the last location if location is not available
2325 * currently.
2326 *
2327 * This helps in cases where the product (Cars for example) has saved the last known location
2328 * before powering off. This interface lets the client inject the saved location while the GPS
2329 * chipset is getting its first fix, there by improving user experience.
2330 *
2331 * @param location - Location object to inject
2332 * @return true if update was successful, false if not
2333 */
2334 @Override
2335 public boolean injectLocation(Location location) {
2336 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
2337 "Location Hardware permission not granted to inject location");
2338 mContext.enforceCallingPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
2339 "Access Fine Location permission not granted to inject Location");
2340
2341 if (location == null) {
2342 if (D) {
2343 Log.d(TAG, "injectLocation(): called with null location");
2344 }
2345 return false;
2346 }
2347 LocationProviderInterface p = null;
2348 String provider = location.getProvider();
2349 if (provider != null) {
2350 p = mProvidersByName.get(provider);
2351 }
2352 if (p == null) {
2353 if (D) {
2354 Log.d(TAG, "injectLocation(): unknown provider");
2355 }
2356 return false;
2357 }
2358 synchronized (mLock) {
2359 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
2360 if (D) {
2361 Log.d(TAG, "Location disabled in Settings for current user:" + mCurrentUserId);
2362 }
2363 return false;
2364 } else {
2365 // NOTE: If last location is already available, location is not injected. If
2366 // provider's normal source (like a GPS chipset) have already provided an output,
2367 // there is no need to inject this location.
2368 if (mLastLocation.get(provider) == null) {
2369 updateLastLocationLocked(location, provider);
2370 } else {
2371 if (D) {
2372 Log.d(TAG, "injectLocation(): Location exists. Not updating");
2373 }
2374 return false;
2375 }
2376 }
2377 }
2378 return true;
2379 }
2380
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002381 @Override
2382 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
2383 String packageName) {
2384 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002385 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2386 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002387 checkPendingIntent(intent);
2388 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002389 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2390 request.getProvider());
gomo48f1a642017-11-10 20:35:46 -08002391 // Require that caller can manage given document
2392 boolean callerHasLocationHardwarePermission =
2393 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
Maggieaa080f92018-01-04 15:35:11 -08002394 == PERMISSION_GRANTED;
gomo48f1a642017-11-10 20:35:46 -08002395 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel,
2396 callerHasLocationHardwarePermission);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002397
Victoria Lease37425c32012-10-16 16:08:48 -07002398 if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002399
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002400 // geo-fence manager uses the public location API, need to clear identity
2401 int uid = Binder.getCallingUid();
Xiaohui Chena4490622015-09-22 15:29:31 -07002402 // TODO: http://b/23822629
2403 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
Victoria Lease56e675b2012-11-05 19:25:06 -08002404 // temporary measure until geofences work for secondary users
2405 Log.w(TAG, "proximity alerts are currently available only to the primary user");
2406 return;
2407 }
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002408 long identity = Binder.clearCallingIdentity();
2409 try {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002410 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
2411 uid, packageName);
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002412 } finally {
2413 Binder.restoreCallingIdentity(identity);
2414 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002415 }
2416
2417 @Override
2418 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002419 checkPendingIntent(intent);
2420 checkPackageName(packageName);
2421
2422 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2423
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002424 // geo-fence manager uses the public location API, need to clear identity
2425 long identity = Binder.clearCallingIdentity();
2426 try {
2427 mGeofenceManager.removeFence(geofence, intent);
2428 } finally {
2429 Binder.restoreCallingIdentity(identity);
2430 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002431 }
2432
2433
2434 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002435 public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002436 if (!hasGnssPermissions(packageName) || mGnssStatusProvider == null) {
Takayuki Hoshib254ab6a2014-10-23 16:46:02 +09002437 return false;
2438 }
2439
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002440 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002441 mGnssStatusProvider.registerGnssStatusCallback(callback);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002442 } catch (RemoteException e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002443 Slog.e(TAG, "mGpsStatusProvider.registerGnssStatusCallback failed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002444 return false;
2445 }
2446 return true;
2447 }
2448
Nick Pellye0fd6932012-07-11 10:26:13 -07002449 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002450 public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002451 synchronized (mLock) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002452 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002453 mGnssStatusProvider.unregisterGnssStatusCallback(callback);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002454 } catch (Exception e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002455 Slog.e(TAG, "mGpsStatusProvider.unregisterGnssStatusCallback failed", e);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002457 }
2458 }
2459
Nick Pellye0fd6932012-07-11 10:26:13 -07002460 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002461 public boolean addGnssMeasurementsListener(
gomo48f1a642017-11-10 20:35:46 -08002462 IGnssMeasurementsListener listener, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002463 if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
destradaaea8a8a62014-06-23 18:19:03 -07002464 return false;
2465 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002466
2467 synchronized (mLock) {
2468 Identity callerIdentity
2469 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
Wyatt Riley11cc7492018-01-17 08:48:27 -08002470 mGnssMeasurementsListeners.put(listener.asBinder(), callerIdentity);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002471 long identity = Binder.clearCallingIdentity();
2472 try {
2473 if (isThrottlingExemptLocked(callerIdentity)
2474 || isImportanceForeground(
gomo48f1a642017-11-10 20:35:46 -08002475 mActivityManager.getPackageImportance(packageName))) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002476 return mGnssMeasurementsProvider.addListener(listener);
2477 }
2478 } finally {
2479 Binder.restoreCallingIdentity(identity);
2480 }
2481
2482 return true;
2483 }
destradaaea8a8a62014-06-23 18:19:03 -07002484 }
2485
2486 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002487 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
2488 if (mGnssMeasurementsProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002489 synchronized (mLock) {
Wyatt Riley11cc7492018-01-17 08:48:27 -08002490 mGnssMeasurementsListeners.remove(listener.asBinder());
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002491 mGnssMeasurementsProvider.removeListener(listener);
2492 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002493 }
destradaaea8a8a62014-06-23 18:19:03 -07002494 }
2495
2496 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002497 public boolean addGnssNavigationMessageListener(
2498 IGnssNavigationMessageListener listener,
destradaa4b3e3932014-07-21 18:01:47 -07002499 String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002500 if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) {
destradaa4b3e3932014-07-21 18:01:47 -07002501 return false;
2502 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002503
2504 synchronized (mLock) {
2505 Identity callerIdentity
gomo48f1a642017-11-10 20:35:46 -08002506 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
Wyatt Riley11cc7492018-01-17 08:48:27 -08002507 mGnssNavigationMessageListeners.put(listener.asBinder(), callerIdentity);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002508 long identity = Binder.clearCallingIdentity();
2509 try {
2510 if (isThrottlingExemptLocked(callerIdentity)
2511 || isImportanceForeground(
gomo48f1a642017-11-10 20:35:46 -08002512 mActivityManager.getPackageImportance(packageName))) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002513 return mGnssNavigationMessageProvider.addListener(listener);
2514 }
2515 } finally {
2516 Binder.restoreCallingIdentity(identity);
2517 }
2518
2519 return true;
2520 }
destradaa4b3e3932014-07-21 18:01:47 -07002521 }
2522
2523 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002524 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
2525 if (mGnssNavigationMessageProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002526 synchronized (mLock) {
Wyatt Riley11cc7492018-01-17 08:48:27 -08002527 mGnssNavigationMessageListeners.remove(listener.asBinder());
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002528 mGnssNavigationMessageProvider.removeListener(listener);
2529 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002530 }
destradaa4b3e3932014-07-21 18:01:47 -07002531 }
2532
2533 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002534 public boolean sendExtraCommand(String provider, String command, Bundle extras) {
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002535 if (provider == null) {
2536 // throw NullPointerException to remain compatible with previous implementation
2537 throw new NullPointerException();
2538 }
Victoria Lease37425c32012-10-16 16:08:48 -07002539 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2540 provider);
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002542 // and check for ACCESS_LOCATION_EXTRA_COMMANDS
Mike Lockwoodb7e99222009-07-07 13:18:21 -04002543 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
Maggieaa080f92018-01-04 15:35:11 -08002544 != PERMISSION_GRANTED)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002545 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
2546 }
2547
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002548 synchronized (mLock) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002549 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002550 if (p == null) return false;
Nick Pellye0fd6932012-07-11 10:26:13 -07002551
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002552 return p.sendExtraCommand(command, extras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002553 }
2554 }
2555
Nick Pellye0fd6932012-07-11 10:26:13 -07002556 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002557 public boolean sendNiResponse(int notifId, int userResponse) {
Mike Lockwood18ad9f62009-08-27 14:01:23 -07002558 if (Binder.getCallingUid() != Process.myUid()) {
2559 throw new SecurityException(
2560 "calling sendNiResponse from outside of the system is not allowed");
2561 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002562 try {
2563 return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002564 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002565 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
Danke Xie22d1f9f2009-08-18 18:28:45 -04002566 return false;
2567 }
2568 }
2569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 /**
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002571 * @return null if the provider does not exist
Alexey Tarasovf2db9fb2009-09-01 02:37:07 +11002572 * @throws SecurityException if the provider is not allowed to be
gomo48f1a642017-11-10 20:35:46 -08002573 * accessed by the caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002574 */
Nick Pellye0fd6932012-07-11 10:26:13 -07002575 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002576 public ProviderProperties getProviderProperties(String provider) {
Laurent Tub7f9d252012-10-16 14:25:00 -07002577 if (mProvidersByName.get(provider) == null) {
David Christie2ff96af2014-01-30 16:09:37 -08002578 return null;
Laurent Tub7f9d252012-10-16 14:25:00 -07002579 }
2580
Victoria Lease37425c32012-10-16 16:08:48 -07002581 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2582 provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002583
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002584 LocationProviderInterface p;
2585 synchronized (mLock) {
2586 p = mProvidersByName.get(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002587 }
2588
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002589 if (p == null) return null;
2590 return p.getProperties();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002591 }
2592
Jason Monkb71218a2015-06-17 14:44:39 -04002593 /**
2594 * @return null if the provider does not exist
2595 * @throws SecurityException if the provider is not allowed to be
gomo48f1a642017-11-10 20:35:46 -08002596 * accessed by the caller
Jason Monkb71218a2015-06-17 14:44:39 -04002597 */
2598 @Override
2599 public String getNetworkProviderPackage() {
2600 LocationProviderInterface p;
2601 synchronized (mLock) {
2602 if (mProvidersByName.get(LocationManager.NETWORK_PROVIDER) == null) {
2603 return null;
2604 }
2605 p = mProvidersByName.get(LocationManager.NETWORK_PROVIDER);
2606 }
2607
2608 if (p instanceof LocationProviderProxy) {
2609 return ((LocationProviderProxy) p).getConnectedPackageName();
2610 }
2611 return null;
2612 }
2613
Maggieaa080f92018-01-04 15:35:11 -08002614 /**
Maggie2a9409e2018-03-21 11:47:28 -07002615 * Returns the current location enabled/disabled status for a user
2616 *
2617 * @param userId the id of the user
2618 * @return true if location is enabled
2619 */
2620 @Override
2621 public boolean isLocationEnabledForUser(int userId) {
2622 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2623 checkInteractAcrossUsersPermission(userId);
2624
2625 long identity = Binder.clearCallingIdentity();
2626 try {
2627 synchronized (mLock) {
2628 final String allowedProviders = Settings.Secure.getStringForUser(
2629 mContext.getContentResolver(),
2630 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
2631 userId);
2632 if (allowedProviders == null) {
2633 return false;
2634 }
2635 final List<String> providerList = Arrays.asList(allowedProviders.split(","));
2636 for(String provider : mRealProviders.keySet()) {
2637 if (provider.equals(LocationManager.PASSIVE_PROVIDER)
2638 || provider.equals(LocationManager.FUSED_PROVIDER)) {
2639 continue;
2640 }
2641 if (providerList.contains(provider)) {
2642 return true;
2643 }
2644 }
2645 return false;
2646 }
2647 } finally {
2648 Binder.restoreCallingIdentity(identity);
2649 }
2650 }
2651
2652 /**
2653 * Enable or disable location for a user
2654 *
2655 * @param enabled true to enable location, false to disable location
2656 * @param userId the id of the user
2657 */
2658 @Override
2659 public void setLocationEnabledForUser(boolean enabled, int userId) {
2660 mContext.enforceCallingPermission(
2661 android.Manifest.permission.WRITE_SECURE_SETTINGS,
2662 "Requires WRITE_SECURE_SETTINGS permission");
2663
2664 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2665 checkInteractAcrossUsersPermission(userId);
2666
2667 long identity = Binder.clearCallingIdentity();
2668 try {
2669 synchronized (mLock) {
2670 final Set<String> allRealProviders = mRealProviders.keySet();
2671 // Update all providers on device plus gps and network provider when disabling
2672 // location
2673 Set<String> allProvidersSet = new ArraySet<>(allRealProviders.size() + 2);
2674 allProvidersSet.addAll(allRealProviders);
2675 // When disabling location, disable gps and network provider that could have been
2676 // enabled by location mode api.
2677 if (enabled == false) {
2678 allProvidersSet.add(LocationManager.GPS_PROVIDER);
2679 allProvidersSet.add(LocationManager.NETWORK_PROVIDER);
2680 }
2681 if (allProvidersSet.isEmpty()) {
2682 return;
2683 }
2684 // to ensure thread safety, we write the provider name with a '+' or '-'
2685 // and let the SettingsProvider handle it rather than reading and modifying
2686 // the list of enabled providers.
2687 final String prefix = enabled ? "+" : "-";
2688 StringBuilder locationProvidersAllowed = new StringBuilder();
2689 for (String provider : allProvidersSet) {
2690 if (provider.equals(LocationManager.PASSIVE_PROVIDER)
2691 || provider.equals(LocationManager.FUSED_PROVIDER)) {
2692 continue;
2693 }
2694 locationProvidersAllowed.append(prefix);
2695 locationProvidersAllowed.append(provider);
2696 locationProvidersAllowed.append(",");
2697 }
2698 // Remove the trailing comma
2699 locationProvidersAllowed.setLength(locationProvidersAllowed.length() - 1);
2700 Settings.Secure.putStringForUser(
2701 mContext.getContentResolver(),
2702 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
2703 locationProvidersAllowed.toString(),
2704 userId);
2705 }
2706 } finally {
2707 Binder.restoreCallingIdentity(identity);
2708 }
2709 }
2710
2711 /**
2712 * Returns the current enabled/disabled status of a location provider and user
2713 *
2714 * @param provider name of the provider
2715 * @param userId the id of the user
2716 * @return true if the provider exists and is enabled
2717 */
2718 @Override
2719 public boolean isProviderEnabledForUser(String provider, int userId) {
2720 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2721 checkInteractAcrossUsersPermission(userId);
2722
2723 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2724 // so we discourage its use
2725 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
2726
2727 int uid = Binder.getCallingUid();
2728 synchronized (mLock) {
2729 LocationProviderInterface p = mProvidersByName.get(provider);
2730 return p != null
2731 && isAllowedByUserSettingsLocked(provider, uid, userId);
2732 }
2733 }
2734
2735 /**
2736 * Enable or disable a single location provider.
2737 *
2738 * @param provider name of the provider
2739 * @param enabled true to enable the provider. False to disable the provider
2740 * @param userId the id of the user to set
2741 * @return true if the value was set, false on errors
2742 */
2743 @Override
2744 public boolean setProviderEnabledForUser(String provider, boolean enabled, int userId) {
2745 mContext.enforceCallingPermission(
2746 android.Manifest.permission.WRITE_SECURE_SETTINGS,
2747 "Requires WRITE_SECURE_SETTINGS permission");
2748
2749 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2750 checkInteractAcrossUsersPermission(userId);
2751
2752 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2753 // so we discourage its use
2754 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
2755
2756 long identity = Binder.clearCallingIdentity();
2757 try {
2758 synchronized (mLock) {
2759 // No such provider exists
2760 if (!mProvidersByName.containsKey(provider)) return false;
2761
2762 // If it is a test provider, do not write to Settings.Secure
2763 if (mMockProviders.containsKey(provider)) {
2764 setTestProviderEnabled(provider, enabled);
2765 return true;
2766 }
2767
2768 // to ensure thread safety, we write the provider name with a '+' or '-'
2769 // and let the SettingsProvider handle it rather than reading and modifying
2770 // the list of enabled providers.
2771 String providerChange = (enabled ? "+" : "-") + provider;
2772 return Settings.Secure.putStringForUser(
2773 mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
2774 providerChange, userId);
2775 }
2776 } finally {
2777 Binder.restoreCallingIdentity(identity);
2778 }
2779 }
2780
2781 /**
Maggieaa080f92018-01-04 15:35:11 -08002782 * Read location provider status from Settings.Secure
2783 *
2784 * @param provider the location provider to query
2785 * @param userId the user id to query
2786 * @return true if the provider is enabled
2787 */
2788 private boolean isLocationProviderEnabledForUser(String provider, int userId) {
2789 long identity = Binder.clearCallingIdentity();
2790 try {
2791 // Use system settings
2792 ContentResolver cr = mContext.getContentResolver();
2793 String allowedProviders = Settings.Secure.getStringForUser(
2794 cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userId);
2795 return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
2796 } finally {
2797 Binder.restoreCallingIdentity(identity);
2798 }
2799 }
2800
2801 /**
Maggie2a9409e2018-03-21 11:47:28 -07002802 * Method for checking INTERACT_ACROSS_USERS permission if specified user id is not the same as
2803 * current user id
2804 *
2805 * @param userId the user id to get or set value
2806 */
2807 private void checkInteractAcrossUsersPermission(int userId) {
2808 int uid = Binder.getCallingUid();
2809 if (UserHandle.getUserId(uid) != userId) {
2810 if (ActivityManager.checkComponentPermission(
2811 android.Manifest.permission.INTERACT_ACROSS_USERS, uid, -1, true)
2812 != PERMISSION_GRANTED) {
2813 throw new SecurityException("Requires INTERACT_ACROSS_USERS permission");
2814 }
2815 }
2816 }
2817
2818 /**
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002819 * Returns "true" if the UID belongs to a bound location provider.
2820 *
2821 * @param uid the uid
2822 * @return true if uid belongs to a bound location provider
2823 */
2824 private boolean isUidALocationProvider(int uid) {
2825 if (uid == Process.SYSTEM_UID) {
2826 return true;
2827 }
2828 if (mGeocodeProvider != null) {
David Christie1f141c12014-05-14 15:11:15 -07002829 if (doesUidHavePackage(uid, mGeocodeProvider.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002830 }
2831 for (LocationProviderProxy proxy : mProxyProviders) {
David Christie1f141c12014-05-14 15:11:15 -07002832 if (doesUidHavePackage(uid, proxy.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002833 }
2834 return false;
2835 }
2836
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002837 private void checkCallerIsProvider() {
2838 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
Maggieaa080f92018-01-04 15:35:11 -08002839 == PERMISSION_GRANTED) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002840 return;
2841 }
2842
2843 // Previously we only used the INSTALL_LOCATION_PROVIDER
2844 // check. But that is system or signature
2845 // protection level which is not flexible enough for
2846 // providers installed oustide the system image. So
2847 // also allow providers with a UID matching the
2848 // currently bound package name
2849
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002850 if (isUidALocationProvider(Binder.getCallingUid())) {
2851 return;
2852 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002853
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002854 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
2855 "or UID of a currently bound location provider");
2856 }
2857
David Christie1f141c12014-05-14 15:11:15 -07002858 /**
2859 * Returns true if the given package belongs to the given uid.
2860 */
2861 private boolean doesUidHavePackage(int uid, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002862 if (packageName == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002863 return false;
2864 }
David Christie1f141c12014-05-14 15:11:15 -07002865 String[] packageNames = mPackageManager.getPackagesForUid(uid);
2866 if (packageNames == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002867 return false;
2868 }
David Christie1f141c12014-05-14 15:11:15 -07002869 for (String name : packageNames) {
2870 if (packageName.equals(name)) {
2871 return true;
2872 }
2873 }
2874 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002875 }
2876
Nick Pellye0fd6932012-07-11 10:26:13 -07002877 @Override
Mike Lockwooda4903f22010-02-17 06:42:23 -05002878 public void reportLocation(Location location, boolean passive) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002879 checkCallerIsProvider();
Mike Lockwood275555c2009-05-01 11:30:34 -04002880
Nick Pelly2eeeec22012-07-18 13:13:37 -07002881 if (!location.isComplete()) {
2882 Log.w(TAG, "Dropping incomplete location: " + location);
2883 return;
2884 }
2885
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002886 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location);
2887 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location);
Mike Lockwooda4903f22010-02-17 06:42:23 -05002888 m.arg1 = (passive ? 1 : 0);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002889 mLocationHandler.sendMessageAtFrontOfQueue(m);
2890 }
2891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002892
Laurent Tu75defb62012-11-01 16:21:52 -07002893 private static boolean shouldBroadcastSafe(
2894 Location loc, Location lastLoc, UpdateRecord record, long now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002895 // Always broadcast the first update
2896 if (lastLoc == null) {
2897 return true;
2898 }
2899
Nick Pellyf1be6862012-05-15 10:53:42 -07002900 // Check whether sufficient time has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002901 long minTime = record.mRealRequest.getFastestInterval();
David Christie1b9b7b12013-04-15 15:31:11 -07002902 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
2903 / NANOS_PER_MILLI;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002904 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002905 return false;
2906 }
2907
2908 // Check whether sufficient distance has been traveled
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002909 double minDistance = record.mRealRequest.getSmallestDisplacement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002910 if (minDistance > 0.0) {
2911 if (loc.distanceTo(lastLoc) <= minDistance) {
2912 return false;
2913 }
2914 }
2915
Laurent Tu75defb62012-11-01 16:21:52 -07002916 // Check whether sufficient number of udpates is left
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002917 if (record.mRealRequest.getNumUpdates() <= 0) {
Laurent Tu75defb62012-11-01 16:21:52 -07002918 return false;
2919 }
2920
2921 // Check whether the expiry date has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002922 return record.mRealRequest.getExpireAt() >= now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002923 }
2924
Mike Lockwooda4903f22010-02-17 06:42:23 -05002925 private void handleLocationChangedLocked(Location location, boolean passive) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002926 if (D) Log.d(TAG, "incoming location: " + location);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002927 long now = SystemClock.elapsedRealtime();
Mike Lockwooda4903f22010-02-17 06:42:23 -05002928 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
Laurent Tu60ec50a2012-10-04 17:00:10 -07002929 // Skip if the provider is unknown.
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002930 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002931 if (p == null) return;
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002932 updateLastLocationLocked(location, provider);
2933 // mLastLocation should have been updated from the updateLastLocationLocked call above.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002934 Location lastLocation = mLastLocation.get(provider);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002935 if (lastLocation == null) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002936 Log.e(TAG, "handleLocationChangedLocked() updateLastLocation failed");
2937 return;
Mike Lockwood4e50b782009-04-03 08:24:43 -07002938 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002939
David Christie1b9b7b12013-04-15 15:31:11 -07002940 // Update last known coarse interval location if enough time has passed.
2941 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider);
2942 if (lastLocationCoarseInterval == null) {
2943 lastLocationCoarseInterval = new Location(location);
2944 mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval);
2945 }
2946 long timeDiffNanos = location.getElapsedRealtimeNanos()
2947 - lastLocationCoarseInterval.getElapsedRealtimeNanos();
2948 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
2949 lastLocationCoarseInterval.set(location);
2950 }
2951 // Don't ever return a coarse location that is more recent than the allowed update
2952 // interval (i.e. don't allow an app to keep registering and unregistering for
2953 // location updates to overcome the minimum interval).
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002954 Location noGPSLocation =
David Christie1b9b7b12013-04-15 15:31:11 -07002955 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2956
Laurent Tu60ec50a2012-10-04 17:00:10 -07002957 // Skip if there are no UpdateRecords for this provider.
2958 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
2959 if (records == null || records.size() == 0) return;
2960
Victoria Lease09016ab2012-09-16 12:33:15 -07002961 // Fetch coarse location
2962 Location coarseLocation = null;
David Christie1b9b7b12013-04-15 15:31:11 -07002963 if (noGPSLocation != null) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002964 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
2965 }
2966
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002967 // Fetch latest status update time
2968 long newStatusUpdateTime = p.getStatusUpdateTime();
2969
David Christie2ff96af2014-01-30 16:09:37 -08002970 // Get latest status
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002971 Bundle extras = new Bundle();
2972 int status = p.getStatus(extras);
2973
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002974 ArrayList<Receiver> deadReceivers = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002975 ArrayList<UpdateRecord> deadUpdateRecords = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07002976
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002977 // Broadcast location or status to all listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002978 for (UpdateRecord r : records) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002979 Receiver receiver = r.mReceiver;
Mike Lockwood03ca2162010-04-01 08:10:09 -07002980 boolean receiverDead = false;
Nick Pelly4035f5a2012-08-17 14:43:49 -07002981
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002982 int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid);
2983 if (!isCurrentProfile(receiverUserId)
2984 && !isUidALocationProvider(receiver.mIdentity.mUid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002985 if (D) {
Victoria Lease269518e2012-10-29 08:25:39 -07002986 Log.d(TAG, "skipping loc update for background user " + receiverUserId +
Victoria Leaseb711d572012-10-02 13:14:11 -07002987 " (current user: " + mCurrentUserId + ", app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002988 receiver.mIdentity.mPackageName + ")");
Victoria Leaseb711d572012-10-02 13:14:11 -07002989 }
2990 continue;
2991 }
2992
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002993 if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) {
gomo48f1a642017-11-10 20:35:46 -08002994 if (D) {
2995 Log.d(TAG, "skipping loc update for blacklisted app: " +
2996 receiver.mIdentity.mPackageName);
2997 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07002998 continue;
2999 }
3000
Soonil Nagarkar681d7112017-02-23 17:14:16 -08003001 if (!reportLocationAccessNoThrow(
3002 receiver.mIdentity.mPid,
3003 receiver.mIdentity.mUid,
3004 receiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08003005 receiver.mAllowedResolutionLevel)) {
gomo48f1a642017-11-10 20:35:46 -08003006 if (D) {
3007 Log.d(TAG, "skipping loc update for no op app: " +
3008 receiver.mIdentity.mPackageName);
3009 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08003010 continue;
3011 }
3012
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003013 Location notifyLocation;
Victoria Lease37425c32012-10-16 16:08:48 -07003014 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
3015 notifyLocation = coarseLocation; // use coarse location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003016 } else {
Victoria Lease37425c32012-10-16 16:08:48 -07003017 notifyLocation = lastLocation; // use fine location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003018 }
Victoria Lease09016ab2012-09-16 12:33:15 -07003019 if (notifyLocation != null) {
3020 Location lastLoc = r.mLastFixBroadcast;
Laurent Tu75defb62012-11-01 16:21:52 -07003021 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) {
Victoria Lease09016ab2012-09-16 12:33:15 -07003022 if (lastLoc == null) {
3023 lastLoc = new Location(notifyLocation);
3024 r.mLastFixBroadcast = lastLoc;
3025 } else {
3026 lastLoc.set(notifyLocation);
3027 }
3028 if (!receiver.callLocationChangedLocked(notifyLocation)) {
3029 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
3030 receiverDead = true;
3031 }
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07003032 r.mRealRequest.decrementNumUpdates();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003033 }
3034 }
3035
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003036 long prevStatusUpdateTime = r.mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003037 if ((newStatusUpdateTime > prevStatusUpdateTime) &&
Victoria Lease09016ab2012-09-16 12:33:15 -07003038 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003039
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003040 r.mLastStatusBroadcast = newStatusUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003041 if (!receiver.callStatusChangedLocked(provider, status, extras)) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07003042 receiverDead = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003043 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
Mike Lockwood03ca2162010-04-01 08:10:09 -07003044 }
3045 }
3046
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003047 // track expired records
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07003048 if (r.mRealRequest.getNumUpdates() <= 0 || r.mRealRequest.getExpireAt() < now) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003049 if (deadUpdateRecords == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003050 deadUpdateRecords = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003051 }
3052 deadUpdateRecords.add(r);
3053 }
3054 // track dead receivers
3055 if (receiverDead) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07003056 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003057 deadReceivers = new ArrayList<>();
Mike Lockwood03ca2162010-04-01 08:10:09 -07003058 }
3059 if (!deadReceivers.contains(receiver)) {
3060 deadReceivers.add(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003061 }
3062 }
3063 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003064
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003065 // remove dead records and receivers outside the loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003067 for (Receiver receiver : deadReceivers) {
3068 removeUpdatesLocked(receiver);
3069 }
3070 }
3071 if (deadUpdateRecords != null) {
3072 for (UpdateRecord r : deadUpdateRecords) {
3073 r.disposeLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003074 }
Victoria Lease8b38b292012-12-04 15:04:43 -08003075 applyRequirementsLocked(provider);
3076 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003077 }
3078
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08003079 /**
3080 * Updates last location with the given location
3081 *
3082 * @param location new location to update
3083 * @param provider Location provider to update for
3084 */
3085 private void updateLastLocationLocked(Location location, String provider) {
3086 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
3087 Location lastNoGPSLocation;
3088 Location lastLocation = mLastLocation.get(provider);
3089 if (lastLocation == null) {
3090 lastLocation = new Location(provider);
3091 mLastLocation.put(provider, lastLocation);
3092 } else {
3093 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
3094 if (noGPSLocation == null && lastNoGPSLocation != null) {
3095 // New location has no no-GPS location: adopt last no-GPS location. This is set
3096 // directly into location because we do not want to notify COARSE clients.
3097 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
3098 }
3099 }
3100 lastLocation.set(location);
3101 }
3102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003103 private class LocationWorkerHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08003104 public LocationWorkerHandler(Looper looper) {
3105 super(looper, null, true);
3106 }
3107
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003108 @Override
3109 public void handleMessage(Message msg) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003110 switch (msg.what) {
3111 case MSG_LOCATION_CHANGED:
3112 handleLocationChanged((Location) msg.obj, msg.arg1 == 1);
3113 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003114 }
3115 }
3116 }
3117
Victoria Lease54ca7ae2013-01-08 09:39:50 -08003118 private boolean isMockProvider(String provider) {
3119 synchronized (mLock) {
3120 return mMockProviders.containsKey(provider);
3121 }
3122 }
3123
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003124 private void handleLocationChanged(Location location, boolean passive) {
Victoria Lease54ca7ae2013-01-08 09:39:50 -08003125 // create a working copy of the incoming Location so that the service can modify it without
3126 // disturbing the caller's copy
3127 Location myLocation = new Location(location);
3128 String provider = myLocation.getProvider();
3129
3130 // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this
3131 // bit if location did not come from a mock provider because passive/fused providers can
3132 // forward locations from mock providers, and should not grant them legitimacy in doing so.
3133 if (!myLocation.isFromMockProvider() && isMockProvider(provider)) {
3134 myLocation.setIsFromMockProvider(true);
3135 }
Jeff Sharkey5e613312012-01-30 11:16:20 -08003136
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003137 synchronized (mLock) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08003138 if (isAllowedByCurrentUserSettingsLocked(provider)) {
3139 if (!passive) {
3140 // notify passive provider of the new location
3141 mPassiveProvider.updateLocation(myLocation);
3142 }
Victoria Lease54ca7ae2013-01-08 09:39:50 -08003143 handleLocationChangedLocked(myLocation, passive);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003144 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003145 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003146 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003147
Mike Lockwoode97ae402010-09-29 15:23:46 -04003148 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
3149 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003150 public void onPackageDisappeared(String packageName, int reason) {
3151 // remove all receivers associated with this package name
3152 synchronized (mLock) {
3153 ArrayList<Receiver> deadReceivers = null;
3154
3155 for (Receiver receiver : mReceivers.values()) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08003156 if (receiver.mIdentity.mPackageName.equals(packageName)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003157 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003158 deadReceivers = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003159 }
3160 deadReceivers.add(receiver);
3161 }
3162 }
3163
3164 // perform removal outside of mReceivers loop
3165 if (deadReceivers != null) {
3166 for (Receiver receiver : deadReceivers) {
3167 removeUpdatesLocked(receiver);
3168 }
3169 }
3170 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003171 }
Mike Lockwoode97ae402010-09-29 15:23:46 -04003172 };
3173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003174 // Geocoder
3175
Nick Pellye0fd6932012-07-11 10:26:13 -07003176 @Override
Mike Lockwoode15735a2010-09-20 17:48:47 -04003177 public boolean geocoderIsPresent() {
Mark Vandevoorde01ac80b2010-05-21 15:43:26 -07003178 return mGeocodeProvider != null;
3179 }
3180
Nick Pellye0fd6932012-07-11 10:26:13 -07003181 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003182 public String getFromLocation(double latitude, double longitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05003183 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04003184 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05003185 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
3186 params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003187 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04003188 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003189 }
3190
Mike Lockwooda55c3212009-04-15 11:10:11 -04003191
Nick Pellye0fd6932012-07-11 10:26:13 -07003192 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003193 public String getFromLocationName(String locationName,
Mike Lockwooda55c3212009-04-15 11:10:11 -04003194 double lowerLeftLatitude, double lowerLeftLongitude,
3195 double upperRightLatitude, double upperRightLongitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05003196 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04003197
3198 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05003199 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
3200 lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
3201 maxResults, params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003202 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04003203 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003204 }
3205
3206 // Mock Providers
3207
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003208 private boolean canCallerAccessMockLocation(String opPackageName) {
3209 return mAppOps.noteOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(),
3210 opPackageName) == AppOpsManager.MODE_ALLOWED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003211 }
3212
Nick Pellye0fd6932012-07-11 10:26:13 -07003213 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003214 public void addTestProvider(String name, ProviderProperties properties, String opPackageName) {
3215 if (!canCallerAccessMockLocation(opPackageName)) {
3216 return;
3217 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003218
Mike Lockwooda4903f22010-02-17 06:42:23 -05003219 if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
3220 throw new IllegalArgumentException("Cannot mock the passive location provider");
3221 }
3222
Mike Lockwood86328a92009-10-23 08:38:25 -04003223 long identity = Binder.clearCallingIdentity();
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003224 synchronized (mLock) {
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003225 // remove the real provider if we are replacing GPS or network provider
3226 if (LocationManager.GPS_PROVIDER.equals(name)
Nick Pelly1332b532012-08-21 16:25:47 -07003227 || LocationManager.NETWORK_PROVIDER.equals(name)
3228 || LocationManager.FUSED_PROVIDER.equals(name)) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05003229 LocationProviderInterface p = mProvidersByName.get(name);
3230 if (p != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003231 removeProviderLocked(p);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003232 }
3233 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09003234 addTestProviderLocked(name, properties);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003235 updateProvidersLocked();
3236 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003237 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003238 }
3239
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09003240 private void addTestProviderLocked(String name, ProviderProperties properties) {
3241 if (mProvidersByName.get(name) != null) {
3242 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
3243 }
3244 MockProvider provider = new MockProvider(name, this, properties);
3245 addProviderLocked(provider);
3246 mMockProviders.put(name, provider);
3247 mLastLocation.put(name, null);
3248 mLastLocationCoarseInterval.put(name, null);
3249 }
3250
Nick Pellye0fd6932012-07-11 10:26:13 -07003251 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003252 public void removeTestProvider(String provider, String opPackageName) {
3253 if (!canCallerAccessMockLocation(opPackageName)) {
3254 return;
3255 }
3256
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003257 synchronized (mLock) {
Tom O'Neill07ee5d12014-03-03 17:48:35 -08003258
3259 // These methods can't be called after removing the test provider, so first make sure
Tom O'Neillfe6d3c52014-03-04 08:26:17 -08003260 // we don't leave anything dangling.
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003261 clearTestProviderEnabled(provider, opPackageName);
3262 clearTestProviderLocation(provider, opPackageName);
3263 clearTestProviderStatus(provider, opPackageName);
Tom O'Neill07ee5d12014-03-03 17:48:35 -08003264
You Kima6d0b6f2012-10-28 03:58:44 +09003265 MockProvider mockProvider = mMockProviders.remove(provider);
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003266 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003267 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3268 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003269 long identity = Binder.clearCallingIdentity();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003270 removeProviderLocked(mProvidersByName.get(provider));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003271
3272 // reinstate real provider if available
3273 LocationProviderInterface realProvider = mRealProviders.get(provider);
3274 if (realProvider != null) {
3275 addProviderLocked(realProvider);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003276 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003277 mLastLocation.put(provider, null);
David Christie1b9b7b12013-04-15 15:31:11 -07003278 mLastLocationCoarseInterval.put(provider, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003279 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003280 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003281 }
3282 }
3283
Nick Pellye0fd6932012-07-11 10:26:13 -07003284 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003285 public void setTestProviderLocation(String provider, Location loc, String opPackageName) {
3286 if (!canCallerAccessMockLocation(opPackageName)) {
3287 return;
3288 }
3289
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003290 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003291 MockProvider mockProvider = mMockProviders.get(provider);
3292 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003293 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3294 }
Tom O'Neilla206a0f2016-12-15 10:26:28 -08003295
3296 // Ensure that the location is marked as being mock. There's some logic to do this in
3297 // handleLocationChanged(), but it fails if loc has the wrong provider (bug 33091107).
3298 Location mock = new Location(loc);
3299 mock.setIsFromMockProvider(true);
3300
3301 if (!TextUtils.isEmpty(loc.getProvider()) && !provider.equals(loc.getProvider())) {
3302 // The location has an explicit provider that is different from the mock provider
3303 // name. The caller may be trying to fool us via bug 33091107.
3304 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
3305 provider + "!=" + loc.getProvider());
3306 }
3307
Mike Lockwood95427cd2009-05-07 13:27:54 -04003308 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
3309 long identity = Binder.clearCallingIdentity();
Tom O'Neilla206a0f2016-12-15 10:26:28 -08003310 mockProvider.setLocation(mock);
Mike Lockwood95427cd2009-05-07 13:27:54 -04003311 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003312 }
3313 }
3314
Nick Pellye0fd6932012-07-11 10:26:13 -07003315 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003316 public void clearTestProviderLocation(String provider, String opPackageName) {
3317 if (!canCallerAccessMockLocation(opPackageName)) {
3318 return;
3319 }
3320
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003321 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003322 MockProvider mockProvider = mMockProviders.get(provider);
3323 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003324 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3325 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003326 mockProvider.clearLocation();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003327 }
3328 }
3329
Nick Pellye0fd6932012-07-11 10:26:13 -07003330 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003331 public void setTestProviderEnabled(String provider, boolean enabled, String opPackageName) {
3332 if (!canCallerAccessMockLocation(opPackageName)) {
3333 return;
3334 }
Maggie2a9409e2018-03-21 11:47:28 -07003335 setTestProviderEnabled(provider, enabled);
3336 }
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003337
Maggie2a9409e2018-03-21 11:47:28 -07003338 /** Enable or disable a test location provider. */
3339 private void setTestProviderEnabled(String provider, boolean enabled) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003340 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003341 MockProvider mockProvider = mMockProviders.get(provider);
3342 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003343 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3344 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003345 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003346 if (enabled) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003347 mockProvider.enable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003348 mEnabledProviders.add(provider);
3349 mDisabledProviders.remove(provider);
3350 } else {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003351 mockProvider.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003352 mEnabledProviders.remove(provider);
3353 mDisabledProviders.add(provider);
3354 }
3355 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003356 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003357 }
3358 }
3359
Nick Pellye0fd6932012-07-11 10:26:13 -07003360 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003361 public void clearTestProviderEnabled(String provider, String opPackageName) {
3362 if (!canCallerAccessMockLocation(opPackageName)) {
3363 return;
3364 }
3365
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003366 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003367 MockProvider mockProvider = mMockProviders.get(provider);
3368 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003369 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3370 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003371 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003372 mEnabledProviders.remove(provider);
3373 mDisabledProviders.remove(provider);
3374 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003375 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003376 }
3377 }
3378
Nick Pellye0fd6932012-07-11 10:26:13 -07003379 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003380 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime,
3381 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 Lockwood7ec434e2009-03-27 07:46:48 -07003391 mockProvider.setStatus(status, extras, updateTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003392 }
3393 }
3394
Nick Pellye0fd6932012-07-11 10:26:13 -07003395 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003396 public void clearTestProviderStatus(String provider, String opPackageName) {
3397 if (!canCallerAccessMockLocation(opPackageName)) {
3398 return;
3399 }
3400
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003401 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003402 MockProvider mockProvider = mMockProviders.get(provider);
3403 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003404 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3405 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003406 mockProvider.clearStatus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003407 }
3408 }
3409
3410 private void log(String log) {
3411 if (Log.isLoggable(TAG, Log.VERBOSE)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003412 Slog.d(TAG, log);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003413 }
3414 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003415
3416 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003417 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003418 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Nick Pellye0fd6932012-07-11 10:26:13 -07003419
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003420 synchronized (mLock) {
Siddharth Raybb608c82017-03-16 11:33:34 -07003421 if (args.length > 0 && args[0].equals("--gnssmetrics")) {
3422 if (mGnssMetricsProvider != null) {
3423 pw.append(mGnssMetricsProvider.getGnssMetricsAsProtoString());
3424 }
3425 return;
3426 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003427 pw.println("Current Location Manager state:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003428 pw.println(" Location Listeners:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003429 for (Receiver receiver : mReceivers.values()) {
3430 pw.println(" " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003431 }
David Christie2ff96af2014-01-30 16:09:37 -08003432 pw.println(" Active Records by Provider:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003433 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
3434 pw.println(" " + entry.getKey() + ":");
3435 for (UpdateRecord record : entry.getValue()) {
3436 pw.println(" " + record);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003437 }
3438 }
Wyatt Riley11cc7492018-01-17 08:48:27 -08003439 pw.println(" Active GnssMeasurement Listeners:");
3440 for (Identity identity : mGnssMeasurementsListeners.values()) {
3441 pw.println(" " + identity.mPid + " " + identity.mUid + " "
3442 + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
3443 }
3444 pw.println(" Active GnssNavigationMessage Listeners:");
3445 for (Identity identity : mGnssNavigationMessageListeners.values()) {
3446 pw.println(" " + identity.mPid + " " + identity.mUid + " "
3447 + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
3448 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003449 pw.println(" Overlay Provider Packages:");
3450 for (LocationProviderInterface provider : mProviders) {
3451 if (provider instanceof LocationProviderProxy) {
3452 pw.println(" " + provider.getName() + ": "
3453 + ((LocationProviderProxy) provider).getConnectedPackageName());
3454 }
3455 }
David Christie2ff96af2014-01-30 16:09:37 -08003456 pw.println(" Historical Records by Provider:");
3457 for (Map.Entry<PackageProviderKey, PackageStatistics> entry
3458 : mRequestStatistics.statistics.entrySet()) {
3459 PackageProviderKey key = entry.getKey();
3460 PackageStatistics stats = entry.getValue();
3461 pw.println(" " + key.packageName + ": " + key.providerName + ": " + stats);
3462 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003463 pw.println(" Last Known Locations:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003464 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
3465 String provider = entry.getKey();
3466 Location location = entry.getValue();
3467 pw.println(" " + provider + ": " + location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003469
David Christie1b9b7b12013-04-15 15:31:11 -07003470 pw.println(" Last Known Locations Coarse Intervals:");
3471 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
3472 String provider = entry.getKey();
3473 Location location = entry.getValue();
3474 pw.println(" " + provider + ": " + location);
3475 }
3476
Nick Pellye0fd6932012-07-11 10:26:13 -07003477 mGeofenceManager.dump(pw);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003479 if (mEnabledProviders.size() > 0) {
3480 pw.println(" Enabled Providers:");
3481 for (String i : mEnabledProviders) {
3482 pw.println(" " + i);
3483 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003485 }
3486 if (mDisabledProviders.size() > 0) {
3487 pw.println(" Disabled Providers:");
3488 for (String i : mDisabledProviders) {
3489 pw.println(" " + i);
3490 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003491 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07003492 pw.append(" ");
3493 mBlacklist.dump(pw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003494 if (mMockProviders.size() > 0) {
3495 pw.println(" Mock Providers:");
3496 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003497 i.getValue().dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003498 }
3499 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003500
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08003501 if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
3502 pw.println(" Throttling Whitelisted Packages:");
3503 for (String packageName : mBackgroundThrottlePackageWhitelist) {
3504 pw.println(" " + packageName);
3505 }
3506 }
3507
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003508 pw.append(" fudger: ");
gomo48f1a642017-11-10 20:35:46 -08003509 mLocationFudger.dump(fd, pw, args);
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003510
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003511 if (args.length > 0 && "short".equals(args[0])) {
3512 return;
3513 }
gomo48f1a642017-11-10 20:35:46 -08003514 for (LocationProviderInterface provider : mProviders) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003515 pw.print(provider.getName() + " Internal State");
3516 if (provider instanceof LocationProviderProxy) {
3517 LocationProviderProxy proxy = (LocationProviderProxy) provider;
3518 pw.print(" (" + proxy.getConnectedPackageName() + ")");
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003519 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003520 pw.println(":");
3521 provider.dump(fd, pw, args);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003522 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08003523 if (mGnssBatchingInProgress) {
3524 pw.println(" GNSS batching in progress");
3525 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003526 }
3527 }
3528}