blob: d5cbfd4a70cb519f103867f42afa95fed40bfe0d [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;
Maggieaa080f92018-01-04 15:35:11 -080022import android.app.ActivityManager;
23import android.app.AppOpsManager;
24import android.app.PendingIntent;
25import android.content.BroadcastReceiver;
26import android.content.ContentResolver;
27import android.content.Context;
28import android.content.Intent;
29import android.content.IntentFilter;
30import android.content.pm.ApplicationInfo;
31import android.content.pm.PackageInfo;
32import android.content.pm.PackageManager;
33import android.content.pm.PackageManager.NameNotFoundException;
34import android.content.pm.PackageManagerInternal;
35import android.content.pm.ResolveInfo;
36import android.content.pm.Signature;
37import android.content.res.Resources;
38import android.database.ContentObserver;
39import android.hardware.location.ActivityRecognitionHardware;
40import android.location.Address;
41import android.location.Criteria;
42import android.location.GeocoderParams;
43import android.location.Geofence;
44import android.location.IBatchedLocationCallback;
45import android.location.IGnssMeasurementsListener;
46import android.location.IGnssNavigationMessageListener;
47import android.location.IGnssStatusListener;
48import android.location.IGnssStatusProvider;
49import android.location.IGpsGeofenceHardware;
50import android.location.ILocationListener;
51import android.location.ILocationManager;
52import android.location.INetInitiatedListener;
53import android.location.Location;
54import android.location.LocationManager;
55import android.location.LocationProvider;
56import android.location.LocationRequest;
57import android.os.Binder;
58import android.os.Bundle;
59import android.os.Handler;
60import android.os.IBinder;
61import android.os.Looper;
62import android.os.Message;
63import android.os.PowerManager;
64import android.os.Process;
65import android.os.RemoteException;
66import android.os.SystemClock;
67import android.os.UserHandle;
68import android.os.UserManager;
69import android.os.WorkSource;
Narayan Kamath32684dd2018-01-08 17:32:51 +000070import android.os.WorkSource.WorkChain;
Maggieaa080f92018-01-04 15:35:11 -080071import android.provider.Settings;
72import android.text.TextUtils;
Soonil Nagarkar681d7112017-02-23 17:14:16 -080073import android.util.ArrayMap;
Soonil Nagarkar2b565df2017-02-14 13:33:23 -080074import android.util.ArraySet;
Maggieaa080f92018-01-04 15:35:11 -080075import android.util.EventLog;
76import android.util.Log;
77import android.util.Slog;
destradaaea8a8a62014-06-23 18:19:03 -070078import com.android.internal.content.PackageMonitor;
79import com.android.internal.location.ProviderProperties;
80import com.android.internal.location.ProviderRequest;
81import com.android.internal.os.BackgroundThread;
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -070082import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060083import com.android.internal.util.DumpUtils;
destradaaa4fa3b52014-07-09 10:46:39 -070084import com.android.server.location.ActivityRecognitionProxy;
destradaaea8a8a62014-06-23 18:19:03 -070085import com.android.server.location.GeocoderProxy;
86import com.android.server.location.GeofenceManager;
87import com.android.server.location.GeofenceProxy;
Lifu Tang818aa2c2016-02-01 01:52:00 -080088import com.android.server.location.GnssLocationProvider;
89import com.android.server.location.GnssMeasurementsProvider;
90import com.android.server.location.GnssNavigationMessageProvider;
destradaaea8a8a62014-06-23 18:19:03 -070091import com.android.server.location.LocationBlacklist;
92import com.android.server.location.LocationFudger;
93import com.android.server.location.LocationProviderInterface;
94import com.android.server.location.LocationProviderProxy;
95import com.android.server.location.LocationRequestStatistics;
96import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
97import com.android.server.location.LocationRequestStatistics.PackageStatistics;
98import com.android.server.location.MockProvider;
99import com.android.server.location.PassiveProvider;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400100import java.io.FileDescriptor;
101import java.io.PrintWriter;
102import java.util.ArrayList;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700103import java.util.Arrays;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400104import java.util.HashMap;
105import java.util.HashSet;
106import java.util.List;
107import java.util.Map;
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800108import java.util.Map.Entry;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800109import java.util.NoSuchElementException;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400110import java.util.Set;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111
112/**
113 * The service class that manages LocationProviders and issues location
114 * updates and alerts.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 */
Victoria Lease5cd731a2012-12-19 15:04:21 -0800116public class LocationManagerService extends ILocationManager.Stub {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117 private static final String TAG = "LocationManagerService";
JP Abgrallf79811e72013-02-01 18:45:05 -0800118 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700119
Olivier Gaillard7a222662017-11-20 16:07:24 +0000120 private static final String WAKELOCK_KEY = "*location*";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121
Victoria Lease37425c32012-10-16 16:08:48 -0700122 // Location resolution level: no location data whatsoever
123 private static final int RESOLUTION_LEVEL_NONE = 0;
124 // Location resolution level: coarse location data only
125 private static final int RESOLUTION_LEVEL_COARSE = 1;
126 // Location resolution level: fine location data
127 private static final int RESOLUTION_LEVEL_FINE = 2;
128
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129 private static final String ACCESS_MOCK_LOCATION =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700130 android.Manifest.permission.ACCESS_MOCK_LOCATION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131 private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700132 android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
Mike Lockwood275555c2009-05-01 11:30:34 -0400133 private static final String INSTALL_LOCATION_PROVIDER =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700134 android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
135
136 private static final String NETWORK_LOCATION_SERVICE_ACTION =
Stan Chesnutt39062dd2013-07-22 14:33:30 -0700137 "com.android.location.service.v3.NetworkLocationProvider";
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700138 private static final String FUSED_LOCATION_SERVICE_ACTION =
139 "com.android.location.service.FusedLocationProvider";
140
141 private static final int MSG_LOCATION_CHANGED = 1;
142
David Christie1b9b7b12013-04-15 15:31:11 -0700143 private static final long NANOS_PER_MILLI = 1000000L;
144
David Christie0b837452013-07-29 16:02:13 -0700145 // The maximum interval a location request can have and still be considered "high power".
146 private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
147
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700148 private static final int FOREGROUND_IMPORTANCE_CUTOFF
gomo48f1a642017-11-10 20:35:46 -0800149 = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700150
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800151 // default background throttling interval if not overriden in settings
Soonil Nagarkarde6780a2017-02-07 10:39:41 -0800152 private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800153
Nick Pellyf1be6862012-05-15 10:53:42 -0700154 // Location Providers may sometimes deliver location updates
155 // slightly faster that requested - provide grace period so
156 // we don't unnecessarily filter events that are otherwise on
157 // time
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700158 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
Nick Pellyf1be6862012-05-15 10:53:42 -0700159
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700160 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
161
162 private final Context mContext;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800163 private final AppOpsManager mAppOps;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700164
165 // used internally for synchronization
166 private final Object mLock = new Object();
167
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700168 // --- fields below are final after systemRunning() ---
Nick Pelly74fa7ea2012-08-13 19:36:38 -0700169 private LocationFudger mLocationFudger;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700170 private GeofenceManager mGeofenceManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700171 private PackageManager mPackageManager;
Victoria Lease0aa28602013-05-29 15:28:26 -0700172 private PowerManager mPowerManager;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800173 private ActivityManager mActivityManager;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700174 private UserManager mUserManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700175 private GeocoderProxy mGeocodeProvider;
Lifu Tang30f95a72016-01-07 23:20:38 -0800176 private IGnssStatusProvider mGnssStatusProvider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700177 private INetInitiatedListener mNetInitiatedListener;
178 private LocationWorkerHandler mLocationHandler;
Nick Pelly4035f5a2012-08-17 14:43:49 -0700179 private PassiveProvider mPassiveProvider; // track passive provider for special cases
180 private LocationBlacklist mBlacklist;
Lifu Tang818aa2c2016-02-01 01:52:00 -0800181 private GnssMeasurementsProvider mGnssMeasurementsProvider;
182 private GnssNavigationMessageProvider mGnssNavigationMessageProvider;
Wei Liu5241a4c2015-05-11 14:00:36 -0700183 private IGpsGeofenceHardware mGpsGeofenceProxy;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700184
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700185 // --- fields below are protected by mLock ---
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186 // Set of providers that are explicitly enabled
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700187 // Only used by passive, fused & test. Network & GPS are controlled separately, and not listed.
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800188 private final Set<String> mEnabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189
190 // Set of providers that are explicitly disabled
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800191 private final Set<String> mDisabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700193 // Mock (test) providers
194 private final HashMap<String, MockProvider> mMockProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800195 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700197 // all receivers
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800198 private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700200 // currently installed providers (with mocks replacing real providers)
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500201 private final ArrayList<LocationProviderInterface> mProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800202 new ArrayList<>();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400203
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700204 // real providers, saved here when mocked out
205 private final HashMap<String, LocationProviderInterface> mRealProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800206 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700208 // mapping from provider name to provider
209 private final HashMap<String, LocationProviderInterface> mProvidersByName =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800210 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700212 // mapping from provider name to all its UpdateRecords
213 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800214 new HashMap<>();
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700215
David Christie2ff96af2014-01-30 16:09:37 -0800216 private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics();
217
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700218 // mapping from provider name to last known location
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800219 private final HashMap<String, Location> mLastLocation = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220
David Christie1b9b7b12013-04-15 15:31:11 -0700221 // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
222 // locations stored here are not fudged for coarse permissions.
223 private final HashMap<String, Location> mLastLocationCoarseInterval =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800224 new HashMap<>();
David Christie1b9b7b12013-04-15 15:31:11 -0700225
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800226 // all providers that operate over proxy, for authorizing incoming location and whitelisting
227 // throttling
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700228 private final ArrayList<LocationProviderProxy> mProxyProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800229 new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800231 private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800232
Wyatt Riley11cc7492018-01-17 08:48:27 -0800233 private final ArrayMap<IBinder, Identity> mGnssMeasurementsListeners = new ArrayMap<>();
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800234
Wyatt Riley11cc7492018-01-17 08:48:27 -0800235 private final ArrayMap<IBinder, Identity>
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800236 mGnssNavigationMessageListeners = new ArrayMap<>();
237
Victoria Lease38389b62012-09-30 11:44:22 -0700238 // current active user on the device - other users are denied location data
Xiaohui Chena4490622015-09-22 15:29:31 -0700239 private int mCurrentUserId = UserHandle.USER_SYSTEM;
gomo48f1a642017-11-10 20:35:46 -0800240 private int[] mCurrentUserProfiles = new int[]{UserHandle.USER_SYSTEM};
Victoria Lease38389b62012-09-30 11:44:22 -0700241
Lifu Tang9363b942016-02-16 18:07:00 -0800242 private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;
Lifu Tang82f893d2016-01-21 18:15:33 -0800243
Siddharth Raybb608c82017-03-16 11:33:34 -0700244 private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;
Wyatt Rileyaa420d52017-07-03 15:14:42 -0700245
246 private GnssLocationProvider.GnssBatchingProvider mGnssBatchingProvider;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800247 private IBatchedLocationCallback mGnssBatchingCallback;
248 private LinkedCallback mGnssBatchingDeathCallback;
249 private boolean mGnssBatchingInProgress = false;
250
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700251 public LocationManagerService(Context context) {
252 super();
253 mContext = context;
gomo48f1a642017-11-10 20:35:46 -0800254 mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800255
Svet Ganovadc1cf42015-06-15 16:36:24 -0700256 // Let the package manager query which are the default location
257 // providers as they get certain permissions granted by default.
258 PackageManagerInternal packageManagerInternal = LocalServices.getService(
259 PackageManagerInternal.class);
260 packageManagerInternal.setLocationPackagesProvider(
261 new PackageManagerInternal.PackagesProvider() {
262 @Override
263 public String[] getPackages(int userId) {
264 return mContext.getResources().getStringArray(
265 com.android.internal.R.array.config_locationProviderPackageNames);
266 }
267 });
268
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700269 if (D) Log.d(TAG, "Constructed");
270
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700271 // most startup is deferred until systemRunning()
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700272 }
273
Svetoslav Ganova0027152013-06-25 14:59:53 -0700274 public void systemRunning() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700275 synchronized (mLock) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700276 if (D) Log.d(TAG, "systemRunning()");
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700277
Victoria Lease5cd731a2012-12-19 15:04:21 -0800278 // fetch package manager
279 mPackageManager = mContext.getPackageManager();
280
Victoria Lease0aa28602013-05-29 15:28:26 -0700281 // fetch power manager
282 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
Victoria Lease5cd731a2012-12-19 15:04:21 -0800283
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800284 // fetch activity manager
285 mActivityManager
286 = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
287
Victoria Lease5cd731a2012-12-19 15:04:21 -0800288 // prepare worker thread
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700289 mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper());
Victoria Lease5cd731a2012-12-19 15:04:21 -0800290
291 // prepare mLocationHandler's dependents
292 mLocationFudger = new LocationFudger(mContext, mLocationHandler);
293 mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
294 mBlacklist.init();
295 mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
296
Dianne Hackbornc2293022013-02-06 23:14:49 -0800297 // Monitor for app ops mode changes.
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700298 AppOpsManager.OnOpChangedListener callback
299 = new AppOpsManager.OnOpChangedInternalListener() {
300 public void onOpChanged(int op, String packageName) {
Dianne Hackbornc2293022013-02-06 23:14:49 -0800301 synchronized (mLock) {
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700302 for (Receiver receiver : mReceivers.values()) {
303 receiver.updateMonitoring(true);
304 }
Dianne Hackbornc2293022013-02-06 23:14:49 -0800305 applyAllProviderRequirementsLocked();
306 }
307 }
308 };
309 mAppOps.startWatchingMode(AppOpsManager.OP_COARSE_LOCATION, null, callback);
310
David Christieb870dbf2015-06-22 12:42:53 -0700311 PackageManager.OnPermissionsChangedListener permissionListener
312 = new PackageManager.OnPermissionsChangedListener() {
313 @Override
314 public void onPermissionsChanged(final int uid) {
315 synchronized (mLock) {
316 applyAllProviderRequirementsLocked();
317 }
318 }
319 };
320 mPackageManager.addOnPermissionsChangeListener(permissionListener);
321
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800322 // listen for background/foreground changes
323 ActivityManager.OnUidImportanceListener uidImportanceListener
324 = new ActivityManager.OnUidImportanceListener() {
325 @Override
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700326 public void onUidImportance(final int uid, final int importance) {
327 mLocationHandler.post(new Runnable() {
328 @Override
329 public void run() {
330 onUidImportanceChanged(uid, importance);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800331 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700332 });
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800333 }
334 };
335 mActivityManager.addOnUidImportanceListener(uidImportanceListener,
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700336 FOREGROUND_IMPORTANCE_CUTOFF);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800337
Amith Yamasanib27528d2014-06-05 15:02:10 -0700338 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
339 updateUserProfiles(mCurrentUserId);
340
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800341 updateBackgroundThrottlingWhitelistLocked();
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800342
Victoria Lease5cd731a2012-12-19 15:04:21 -0800343 // prepare providers
344 loadProvidersLocked();
345 updateProvidersLocked();
346 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700347
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700348 // listen for settings changes
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700349 mContext.getContentResolver().registerContentObserver(
Laurent Tu75defb62012-11-01 16:21:52 -0700350 Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700351 new ContentObserver(mLocationHandler) {
Victoria Lease5cd731a2012-12-19 15:04:21 -0800352 @Override
353 public void onChange(boolean selfChange) {
354 synchronized (mLock) {
355 updateProvidersLocked();
356 }
357 }
358 }, UserHandle.USER_ALL);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800359 mContext.getContentResolver().registerContentObserver(
360 Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS),
361 true,
362 new ContentObserver(mLocationHandler) {
363 @Override
364 public void onChange(boolean selfChange) {
365 synchronized (mLock) {
366 updateProvidersLocked();
367 }
368 }
369 }, UserHandle.USER_ALL);
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800370 mContext.getContentResolver().registerContentObserver(
gomo48f1a642017-11-10 20:35:46 -0800371 Settings.Global.getUriFor(
372 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
373 true,
374 new ContentObserver(mLocationHandler) {
375 @Override
376 public void onChange(boolean selfChange) {
377 synchronized (mLock) {
378 updateBackgroundThrottlingWhitelistLocked();
379 updateProvidersLocked();
380 }
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800381 }
gomo48f1a642017-11-10 20:35:46 -0800382 }, UserHandle.USER_ALL);
Victoria Lease5cd731a2012-12-19 15:04:21 -0800383 mPackageMonitor.register(mContext, mLocationHandler.getLooper(), true);
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700384
Victoria Lease38389b62012-09-30 11:44:22 -0700385 // listen for user change
386 IntentFilter intentFilter = new IntentFilter();
387 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700388 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
389 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
destradaab9026982015-08-27 17:34:54 -0700390 intentFilter.addAction(Intent.ACTION_SHUTDOWN);
Victoria Lease38389b62012-09-30 11:44:22 -0700391
392 mContext.registerReceiverAsUser(new BroadcastReceiver() {
393 @Override
394 public void onReceive(Context context, Intent intent) {
395 String action = intent.getAction();
396 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
397 switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
Amith Yamasanib27528d2014-06-05 15:02:10 -0700398 } else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)
399 || Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
400 updateUserProfiles(mCurrentUserId);
destradaab9026982015-08-27 17:34:54 -0700401 } else if (Intent.ACTION_SHUTDOWN.equals(action)) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700402 // shutdown only if UserId indicates whole system, not just one user
gomo48f1a642017-11-10 20:35:46 -0800403 if (D) Log.d(TAG, "Shutdown received with UserId: " + getSendingUserId());
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700404 if (getSendingUserId() == UserHandle.USER_ALL) {
405 shutdownComponents();
406 }
Victoria Lease38389b62012-09-30 11:44:22 -0700407 }
408 }
Victoria Lease5cd731a2012-12-19 15:04:21 -0800409 }, UserHandle.ALL, intentFilter, null, mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700410 }
411
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700412 private void onUidImportanceChanged(int uid, int importance) {
413 boolean foreground = isImportanceForeground(importance);
414 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
415 synchronized (mLock) {
416 for (Entry<String, ArrayList<UpdateRecord>> entry
gomo48f1a642017-11-10 20:35:46 -0800417 : mRecordsByProvider.entrySet()) {
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700418 String provider = entry.getKey();
419 for (UpdateRecord record : entry.getValue()) {
420 if (record.mReceiver.mIdentity.mUid == uid
gomo48f1a642017-11-10 20:35:46 -0800421 && record.mIsForegroundUid != foreground) {
422 if (D) {
423 Log.d(TAG, "request from uid " + uid + " is now "
424 + (foreground ? "foreground" : "background)"));
425 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700426 record.mIsForegroundUid = foreground;
427
428 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
429 affectedProviders.add(provider);
430 }
431 }
432 }
433 }
434 for (String provider : affectedProviders) {
435 applyRequirementsLocked(provider);
436 }
437
Wyatt Riley11cc7492018-01-17 08:48:27 -0800438 for (Entry<IBinder, Identity> entry : mGnssMeasurementsListeners.entrySet()) {
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700439 if (entry.getValue().mUid == uid) {
gomo48f1a642017-11-10 20:35:46 -0800440 if (D) {
441 Log.d(TAG, "gnss measurements listener from uid " + uid
442 + " is now " + (foreground ? "foreground" : "background)"));
443 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700444 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800445 mGnssMeasurementsProvider.addListener(
446 IGnssMeasurementsListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700447 } else {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800448 mGnssMeasurementsProvider.removeListener(
449 IGnssMeasurementsListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700450 }
451 }
452 }
453
Wyatt Riley11cc7492018-01-17 08:48:27 -0800454 for (Entry<IBinder, Identity> entry : mGnssNavigationMessageListeners.entrySet()) {
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700455 if (entry.getValue().mUid == uid) {
gomo48f1a642017-11-10 20:35:46 -0800456 if (D) {
457 Log.d(TAG, "gnss navigation message listener from uid "
458 + uid + " is now "
459 + (foreground ? "foreground" : "background)"));
460 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700461 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800462 mGnssNavigationMessageProvider.addListener(
463 IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700464 } else {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800465 mGnssNavigationMessageProvider.removeListener(
466 IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700467 }
468 }
469 }
470 }
471 }
472
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800473 private static boolean isImportanceForeground(int importance) {
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700474 return importance <= FOREGROUND_IMPORTANCE_CUTOFF;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800475 }
476
Amith Yamasanib27528d2014-06-05 15:02:10 -0700477 /**
destradaab9026982015-08-27 17:34:54 -0700478 * Provides a way for components held by the {@link LocationManagerService} to clean-up
479 * gracefully on system's shutdown.
480 *
481 * NOTES:
482 * 1) Only provides a chance to clean-up on an opt-in basis. This guarantees back-compat
483 * support for components that do not wish to handle such event.
484 */
485 private void shutdownComponents() {
gomo48f1a642017-11-10 20:35:46 -0800486 if (D) Log.d(TAG, "Shutting down components...");
destradaab9026982015-08-27 17:34:54 -0700487
488 LocationProviderInterface gpsProvider = mProvidersByName.get(LocationManager.GPS_PROVIDER);
489 if (gpsProvider != null && gpsProvider.isEnabled()) {
490 gpsProvider.disable();
491 }
destradaab9026982015-08-27 17:34:54 -0700492 }
493
494 /**
Amith Yamasanib27528d2014-06-05 15:02:10 -0700495 * Makes a list of userids that are related to the current user. This is
496 * relevant when using managed profiles. Otherwise the list only contains
497 * the current user.
498 *
499 * @param currentUserId the current user, who might have an alter-ego.
500 */
501 void updateUserProfiles(int currentUserId) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700502 int[] profileIds = mUserManager.getProfileIdsWithDisabled(currentUserId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700503 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700504 mCurrentUserProfiles = profileIds;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700505 }
506 }
507
508 /**
509 * Checks if the specified userId matches any of the current foreground
510 * users stored in mCurrentUserProfiles.
511 */
512 private boolean isCurrentProfile(int userId) {
513 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700514 return ArrayUtils.contains(mCurrentUserProfiles, userId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700515 }
516 }
517
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500518 private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) {
519 PackageManager pm = mContext.getPackageManager();
520 String systemPackageName = mContext.getPackageName();
521 ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
522
523 List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
524 new Intent(FUSED_LOCATION_SERVICE_ACTION),
525 PackageManager.GET_META_DATA, mCurrentUserId);
526 for (ResolveInfo rInfo : rInfos) {
527 String packageName = rInfo.serviceInfo.packageName;
528
529 // Check that the signature is in the list of supported sigs. If it's not in
530 // this list the standard provider binding logic won't bind to it.
531 try {
532 PackageInfo pInfo;
533 pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
534 if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
535 Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
536 ", but has wrong signature, ignoring");
537 continue;
538 }
539 } catch (NameNotFoundException e) {
540 Log.e(TAG, "missing package: " + packageName);
541 continue;
542 }
543
544 // Get the version info
545 if (rInfo.serviceInfo.metaData == null) {
546 Log.w(TAG, "Found fused provider without metadata: " + packageName);
547 continue;
548 }
549
550 int version = rInfo.serviceInfo.metaData.getInt(
551 ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
552 if (version == 0) {
553 // This should be the fallback fused location provider.
554
555 // Make sure it's in the system partition.
556 if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
557 if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
558 continue;
559 }
560
561 // Check that the fallback is signed the same as the OS
562 // as a proxy for coreApp="true"
563 if (pm.checkSignatures(systemPackageName, packageName)
564 != PackageManager.SIGNATURE_MATCH) {
gomo48f1a642017-11-10 20:35:46 -0800565 if (D) {
566 Log.d(TAG, "Fallback candidate not signed the same as system: "
567 + packageName);
568 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500569 continue;
570 }
571
572 // Found a valid fallback.
573 if (D) Log.d(TAG, "Found fallback provider: " + packageName);
574 return;
575 } else {
576 if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
577 }
578 }
579
580 throw new IllegalStateException("Unable to find a fused location provider that is in the "
581 + "system partition with version 0 and signed with the platform certificate. "
582 + "Such a package is needed to provide a default fused location provider in the "
583 + "event that no other fused location provider has been installed or is currently "
584 + "available. For example, coreOnly boot mode when decrypting the data "
585 + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
586 }
587
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700588 private void loadProvidersLocked() {
Victoria Lease5c24fd02012-10-01 11:00:50 -0700589 // create a passive location provider, which is always enabled
590 PassiveProvider passiveProvider = new PassiveProvider(this);
591 addProviderLocked(passiveProvider);
592 mEnabledProviders.add(passiveProvider.getName());
593 mPassiveProvider = passiveProvider;
594
Lifu Tang30f95a72016-01-07 23:20:38 -0800595 if (GnssLocationProvider.isSupported()) {
Wei Liu5241a4c2015-05-11 14:00:36 -0700596 // Create a gps location provider
Lifu Tang30f95a72016-01-07 23:20:38 -0800597 GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this,
Wei Liu5241a4c2015-05-11 14:00:36 -0700598 mLocationHandler.getLooper());
Lifu Tang9363b942016-02-16 18:07:00 -0800599 mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
Wyatt Rileycf879db2017-01-12 13:57:38 -0800600 mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider();
Siddharth Raybb608c82017-03-16 11:33:34 -0700601 mGnssMetricsProvider = gnssProvider.getGnssMetricsProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800602 mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
603 mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
604 addProviderLocked(gnssProvider);
605 mRealProviders.put(LocationManager.GPS_PROVIDER, gnssProvider);
Lifu Tang818aa2c2016-02-01 01:52:00 -0800606 mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
607 mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800608 mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700609 }
610
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700611 /*
612 Load package name(s) containing location provider support.
613 These packages can contain services implementing location providers:
614 Geocoder Provider, Network Location Provider, and
615 Fused Location Provider. They will each be searched for
616 service components implementing these providers.
617 The location framework also has support for installation
618 of new location providers at run-time. The new package does not
619 have to be explicitly listed here, however it must have a signature
620 that matches the signature of at least one package on this list.
621 */
622 Resources resources = mContext.getResources();
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800623 ArrayList<String> providerPackageNames = new ArrayList<>();
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500624 String[] pkgs = resources.getStringArray(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700625 com.android.internal.R.array.config_locationProviderPackageNames);
gomo48f1a642017-11-10 20:35:46 -0800626 if (D) {
627 Log.d(TAG, "certificates for location providers pulled from: " +
628 Arrays.toString(pkgs));
629 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500630 if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));
631
632 ensureFallbackFusedProviderPresentLocked(providerPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700633
634 // bind to network provider
635 LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
636 mContext,
637 LocationManager.NETWORK_PROVIDER,
638 NETWORK_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700639 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
640 com.android.internal.R.string.config_networkLocationProviderPackageName,
641 com.android.internal.R.array.config_locationProviderPackageNames,
642 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700643 if (networkProvider != null) {
644 mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
645 mProxyProviders.add(networkProvider);
646 addProviderLocked(networkProvider);
647 } else {
gomo48f1a642017-11-10 20:35:46 -0800648 Slog.w(TAG, "no network location provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700649 }
650
651 // bind to fused provider
652 LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind(
653 mContext,
654 LocationManager.FUSED_PROVIDER,
655 FUSED_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700656 com.android.internal.R.bool.config_enableFusedLocationOverlay,
657 com.android.internal.R.string.config_fusedLocationProviderPackageName,
658 com.android.internal.R.array.config_locationProviderPackageNames,
659 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700660 if (fusedLocationProvider != null) {
661 addProviderLocked(fusedLocationProvider);
662 mProxyProviders.add(fusedLocationProvider);
663 mEnabledProviders.add(fusedLocationProvider.getName());
Kenny Rootc3575182012-10-09 12:44:40 -0700664 mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700665 } else {
666 Slog.e(TAG, "no fused location provider found",
667 new IllegalStateException("Location service needs a fused location provider"));
668 }
669
670 // bind to geocoder provider
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700671 mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
672 com.android.internal.R.bool.config_enableGeocoderOverlay,
673 com.android.internal.R.string.config_geocoderProviderPackageName,
674 com.android.internal.R.array.config_locationProviderPackageNames,
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800675 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700676 if (mGeocodeProvider == null) {
gomo48f1a642017-11-10 20:35:46 -0800677 Slog.e(TAG, "no geocoder provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700678 }
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700679
destradaaf9a274c2014-07-25 15:11:56 -0700680 // bind to geofence provider
681 GeofenceProxy provider = GeofenceProxy.createAndBind(
gomo48f1a642017-11-10 20:35:46 -0800682 mContext, com.android.internal.R.bool.config_enableGeofenceOverlay,
destradaaf9a274c2014-07-25 15:11:56 -0700683 com.android.internal.R.string.config_geofenceProviderPackageName,
684 com.android.internal.R.array.config_locationProviderPackageNames,
685 mLocationHandler,
Wei Liu5241a4c2015-05-11 14:00:36 -0700686 mGpsGeofenceProxy,
Jiyong Park4cc3a1c2018-03-08 16:43:07 +0900687 null);
destradaaf9a274c2014-07-25 15:11:56 -0700688 if (provider == null) {
gomo48f1a642017-11-10 20:35:46 -0800689 Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
destradaa0682809a2013-08-12 18:50:30 -0700690 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900691
destradaa6e2fe752015-06-23 17:25:53 -0700692 // bind to hardware activity recognition
693 boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
694 ActivityRecognitionHardware activityRecognitionHardware = null;
695 if (activityRecognitionHardwareIsSupported) {
696 activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
destradaaa4fa3b52014-07-09 10:46:39 -0700697 } else {
destradaa6b4893a2016-05-03 15:33:43 -0700698 Slog.d(TAG, "Hardware Activity-Recognition not supported.");
destradaaa4fa3b52014-07-09 10:46:39 -0700699 }
destradaa6e2fe752015-06-23 17:25:53 -0700700 ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
701 mContext,
702 mLocationHandler,
703 activityRecognitionHardwareIsSupported,
704 activityRecognitionHardware,
705 com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
706 com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
707 com.android.internal.R.array.config_locationProviderPackageNames);
708 if (proxy == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700709 Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
destradaa6e2fe752015-06-23 17:25:53 -0700710 }
destradaaa4fa3b52014-07-09 10:46:39 -0700711
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900712 String[] testProviderStrings = resources.getStringArray(
713 com.android.internal.R.array.config_testLocationProviders);
714 for (String testProviderString : testProviderStrings) {
715 String fragments[] = testProviderString.split(",");
716 String name = fragments[0].trim();
717 if (mProvidersByName.get(name) != null) {
718 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
719 }
720 ProviderProperties properties = new ProviderProperties(
721 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
722 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
723 Boolean.parseBoolean(fragments[3]) /* requiresCell */,
724 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
725 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
726 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
727 Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
728 Integer.parseInt(fragments[8]) /* powerRequirement */,
729 Integer.parseInt(fragments[9]) /* accuracy */);
730 addTestProviderLocked(name, properties);
731 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700732 }
Mike Lockwood9637d472009-04-02 21:41:57 -0700733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 /**
Victoria Lease38389b62012-09-30 11:44:22 -0700735 * Called when the device's active user changes.
gomo48f1a642017-11-10 20:35:46 -0800736 *
Victoria Lease38389b62012-09-30 11:44:22 -0700737 * @param userId the new active user's UserId
738 */
739 private void switchUser(int userId) {
Jianzheng Zhoud5c69462013-10-10 14:02:09 +0800740 if (mCurrentUserId == userId) {
741 return;
742 }
Victoria Lease83762d22012-10-03 13:51:17 -0700743 mBlacklist.switchUser(userId);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800744 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED);
Victoria Lease38389b62012-09-30 11:44:22 -0700745 synchronized (mLock) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700746 mLastLocation.clear();
David Christie1b9b7b12013-04-15 15:31:11 -0700747 mLastLocationCoarseInterval.clear();
Victoria Leaseb711d572012-10-02 13:14:11 -0700748 for (LocationProviderInterface p : mProviders) {
Amith Yamasanib27528d2014-06-05 15:02:10 -0700749 updateProviderListenersLocked(p.getName(), false);
Victoria Leaseb711d572012-10-02 13:14:11 -0700750 }
Victoria Lease38389b62012-09-30 11:44:22 -0700751 mCurrentUserId = userId;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700752 updateUserProfiles(userId);
Victoria Leaseb711d572012-10-02 13:14:11 -0700753 updateProvidersLocked();
Victoria Lease38389b62012-09-30 11:44:22 -0700754 }
755 }
756
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800757 private static final class Identity {
758 final int mUid;
759 final int mPid;
760 final String mPackageName;
761
762 Identity(int uid, int pid, String packageName) {
763 mUid = uid;
764 mPid = pid;
765 mPackageName = packageName;
766 }
767 }
768
Victoria Lease38389b62012-09-30 11:44:22 -0700769 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800770 * A wrapper class holding either an ILocationListener or a PendingIntent to receive
771 * location updates.
772 */
Mike Lockwood48f17512009-04-23 09:12:08 -0700773 private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800774 final Identity mIdentity;
Victoria Lease37425c32012-10-16 16:08:48 -0700775 final int mAllowedResolutionLevel; // resolution level allowed to receiver
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700776
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777 final ILocationListener mListener;
778 final PendingIntent mPendingIntent;
David Christie82edc9b2013-07-19 11:31:42 -0700779 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
David Christie40e57822013-07-30 11:36:48 -0700780 final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800781 final Object mKey;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700782
gomo48f1a642017-11-10 20:35:46 -0800783 final HashMap<String, UpdateRecord> mUpdateRecords = new HashMap<>();
Nick Pellyf1be6862012-05-15 10:53:42 -0700784
David Christie0b837452013-07-29 16:02:13 -0700785 // True if app ops has started monitoring this receiver for locations.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700786 boolean mOpMonitoring;
David Christie0b837452013-07-29 16:02:13 -0700787 // True if app ops has started monitoring this receiver for high power (gps) locations.
788 boolean mOpHighPowerMonitoring;
Mike Lockwood48f17512009-04-23 09:12:08 -0700789 int mPendingBroadcasts;
Victoria Lease0aa28602013-05-29 15:28:26 -0700790 PowerManager.WakeLock mWakeLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700792 Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -0700793 String packageName, WorkSource workSource, boolean hideFromAppOps) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 mListener = listener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800795 mPendingIntent = intent;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700796 if (listener != null) {
797 mKey = listener.asBinder();
798 } else {
799 mKey = intent;
800 }
Victoria Lease37425c32012-10-16 16:08:48 -0700801 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800802 mIdentity = new Identity(uid, pid, packageName);
Narayan Kamath32684dd2018-01-08 17:32:51 +0000803 if (workSource != null && workSource.isEmpty()) {
David Christie82edc9b2013-07-19 11:31:42 -0700804 workSource = null;
805 }
806 mWorkSource = workSource;
David Christie40e57822013-07-30 11:36:48 -0700807 mHideFromAppOps = hideFromAppOps;
Victoria Lease0aa28602013-05-29 15:28:26 -0700808
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700809 updateMonitoring(true);
810
Victoria Lease0aa28602013-05-29 15:28:26 -0700811 // construct/configure wakelock
812 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
David Christie82edc9b2013-07-19 11:31:42 -0700813 if (workSource == null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800814 workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -0700815 }
816 mWakeLock.setWorkSource(workSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 }
818
819 @Override
820 public boolean equals(Object otherObj) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800821 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822 }
823
824 @Override
825 public int hashCode() {
826 return mKey.hashCode();
827 }
Mike Lockwood3681f262009-05-12 10:52:03 -0400828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 @Override
830 public String toString() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700831 StringBuilder s = new StringBuilder();
832 s.append("Reciever[");
833 s.append(Integer.toHexString(System.identityHashCode(this)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800834 if (mListener != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700835 s.append(" listener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700837 s.append(" intent");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800838 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700839 for (String p : mUpdateRecords.keySet()) {
840 s.append(" ").append(mUpdateRecords.get(p).toString());
841 }
842 s.append("]");
843 return s.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800844 }
845
David Christie15b31912013-08-13 15:54:32 -0700846 /**
847 * Update AppOp monitoring for this receiver.
848 *
849 * @param allow If true receiver is currently active, if false it's been removed.
850 */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700851 public void updateMonitoring(boolean allow) {
David Christie40e57822013-07-30 11:36:48 -0700852 if (mHideFromAppOps) {
853 return;
854 }
855
David Christie15b31912013-08-13 15:54:32 -0700856 boolean requestingLocation = false;
857 boolean requestingHighPowerLocation = false;
858 if (allow) {
859 // See if receiver has any enabled update records. Also note if any update records
860 // are high power (has a high power provider with an interval under a threshold).
861 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
862 if (isAllowedByCurrentUserSettingsLocked(updateRecord.mProvider)) {
863 requestingLocation = true;
864 LocationProviderInterface locationProvider
David Christie2ff96af2014-01-30 16:09:37 -0800865 = mProvidersByName.get(updateRecord.mProvider);
David Christie15b31912013-08-13 15:54:32 -0700866 ProviderProperties properties = locationProvider != null
867 ? locationProvider.getProperties() : null;
868 if (properties != null
869 && properties.mPowerRequirement == Criteria.POWER_HIGH
870 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
871 requestingHighPowerLocation = true;
872 break;
873 }
874 }
875 }
876 }
877
David Christie0b837452013-07-29 16:02:13 -0700878 // First update monitoring of any location request (including high power).
David Christie15b31912013-08-13 15:54:32 -0700879 mOpMonitoring = updateMonitoring(
880 requestingLocation,
881 mOpMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700882 AppOpsManager.OP_MONITOR_LOCATION);
883
884 // Now update monitoring of high power requests only.
David Christiec750c1f2013-08-08 12:56:57 -0700885 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
David Christie15b31912013-08-13 15:54:32 -0700886 mOpHighPowerMonitoring = updateMonitoring(
887 requestingHighPowerLocation,
888 mOpHighPowerMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700889 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
David Christiec750c1f2013-08-08 12:56:57 -0700890 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
David Christie15b31912013-08-13 15:54:32 -0700891 // Send an intent to notify that a high power request has been added/removed.
David Christiec750c1f2013-08-08 12:56:57 -0700892 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
893 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
894 }
David Christie0b837452013-07-29 16:02:13 -0700895 }
896
897 /**
898 * Update AppOps monitoring for a single location request and op type.
899 *
gomo48f1a642017-11-10 20:35:46 -0800900 * @param allowMonitoring True if monitoring is allowed for this request/op.
David Christie0b837452013-07-29 16:02:13 -0700901 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
gomo48f1a642017-11-10 20:35:46 -0800902 * @param op AppOps code for the op to update.
David Christie0b837452013-07-29 16:02:13 -0700903 * @return True if monitoring is on for this request/op after updating.
904 */
905 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
906 int op) {
907 if (!currentlyMonitoring) {
908 if (allowMonitoring) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800909 return mAppOps.startOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700910 == AppOpsManager.MODE_ALLOWED;
911 }
912 } else {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800913 if (!allowMonitoring
914 || mAppOps.checkOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700915 != AppOpsManager.MODE_ALLOWED) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800916 mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName);
David Christie0b837452013-07-29 16:02:13 -0700917 return false;
918 }
919 }
920
921 return currentlyMonitoring;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700922 }
923
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800924 public boolean isListener() {
925 return mListener != null;
926 }
927
928 public boolean isPendingIntent() {
929 return mPendingIntent != null;
930 }
931
932 public ILocationListener getListener() {
933 if (mListener != null) {
934 return mListener;
935 }
936 throw new IllegalStateException("Request for non-existent listener");
937 }
938
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
940 if (mListener != null) {
941 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700942 synchronized (this) {
943 // synchronize to ensure incrementPendingBroadcastsLocked()
944 // is called before decrementPendingBroadcasts()
945 mListener.onStatusChanged(provider, status, extras);
Nick Pellye0fd6932012-07-11 10:26:13 -0700946 // call this after broadcasting so we do not increment
947 // if we throw an exeption.
948 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -0700949 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950 } catch (RemoteException e) {
951 return false;
952 }
953 } else {
954 Intent statusChanged = new Intent();
Victoria Lease61ecb022012-11-13 15:12:51 -0800955 statusChanged.putExtras(new Bundle(extras));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
957 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700958 synchronized (this) {
959 // synchronize to ensure incrementPendingBroadcastsLocked()
960 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700961 mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -0700962 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -0700963 // call this after broadcasting so we do not increment
964 // if we throw an exeption.
965 incrementPendingBroadcastsLocked();
966 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967 } catch (PendingIntent.CanceledException e) {
968 return false;
969 }
970 }
971 return true;
972 }
973
974 public boolean callLocationChangedLocked(Location location) {
975 if (mListener != null) {
976 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700977 synchronized (this) {
978 // synchronize to ensure incrementPendingBroadcastsLocked()
979 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c5406a2012-11-29 16:18:01 -0800980 mListener.onLocationChanged(new Location(location));
Nick Pellye0fd6932012-07-11 10:26:13 -0700981 // call this after broadcasting so we do not increment
982 // if we throw an exeption.
983 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -0700984 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800985 } catch (RemoteException e) {
986 return false;
987 }
988 } else {
989 Intent locationChanged = new Intent();
gomo48f1a642017-11-10 20:35:46 -0800990 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED,
991 new Location(location));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800992 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700993 synchronized (this) {
994 // synchronize to ensure incrementPendingBroadcastsLocked()
995 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700996 mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -0700997 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -0700998 // call this after broadcasting so we do not increment
999 // if we throw an exeption.
1000 incrementPendingBroadcastsLocked();
1001 }
1002 } catch (PendingIntent.CanceledException e) {
1003 return false;
1004 }
1005 }
1006 return true;
1007 }
1008
1009 public boolean callProviderEnabledLocked(String provider, boolean enabled) {
David Christie15b31912013-08-13 15:54:32 -07001010 // First update AppOp monitoring.
1011 // An app may get/lose location access as providers are enabled/disabled.
1012 updateMonitoring(true);
1013
Mike Lockwood48f17512009-04-23 09:12:08 -07001014 if (mListener != null) {
1015 try {
1016 synchronized (this) {
1017 // synchronize to ensure incrementPendingBroadcastsLocked()
1018 // is called before decrementPendingBroadcasts()
1019 if (enabled) {
1020 mListener.onProviderEnabled(provider);
1021 } else {
1022 mListener.onProviderDisabled(provider);
1023 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001024 // call this after broadcasting so we do not increment
1025 // if we throw an exeption.
1026 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001027 }
1028 } catch (RemoteException e) {
1029 return false;
1030 }
1031 } else {
1032 Intent providerIntent = new Intent();
1033 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1034 try {
1035 synchronized (this) {
1036 // synchronize to ensure incrementPendingBroadcastsLocked()
1037 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001038 mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -07001039 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -07001040 // call this after broadcasting so we do not increment
1041 // if we throw an exeption.
1042 incrementPendingBroadcastsLocked();
1043 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044 } catch (PendingIntent.CanceledException e) {
1045 return false;
1046 }
1047 }
1048 return true;
1049 }
1050
Nick Pellyf1be6862012-05-15 10:53:42 -07001051 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001052 public void binderDied() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001053 if (D) Log.d(TAG, "Location listener died");
1054
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001055 synchronized (mLock) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001056 removeUpdatesLocked(this);
1057 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001058 synchronized (this) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001059 clearPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001060 }
1061 }
1062
Nick Pellye0fd6932012-07-11 10:26:13 -07001063 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001064 public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1065 int resultCode, String resultData, Bundle resultExtras) {
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001066 synchronized (this) {
1067 decrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001068 }
1069 }
1070
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001071 // this must be called while synchronized by caller in a synchronized block
1072 // containing the sending of the broadcaset
1073 private void incrementPendingBroadcastsLocked() {
1074 if (mPendingBroadcasts++ == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001075 mWakeLock.acquire();
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001076 }
1077 }
1078
1079 private void decrementPendingBroadcastsLocked() {
1080 if (--mPendingBroadcasts == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001081 if (mWakeLock.isHeld()) {
1082 mWakeLock.release();
1083 }
1084 }
1085 }
1086
1087 public void clearPendingBroadcastsLocked() {
1088 if (mPendingBroadcasts > 0) {
1089 mPendingBroadcasts = 0;
1090 if (mWakeLock.isHeld()) {
1091 mWakeLock.release();
1092 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001093 }
1094 }
1095 }
1096
Nick Pellye0fd6932012-07-11 10:26:13 -07001097 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001098 public void locationCallbackFinished(ILocationListener listener) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001099 //Do not use getReceiverLocked here as that will add the ILocationListener to
Joshua Bartel080b61b2009-10-05 12:44:46 -04001100 //the receiver list if it is not found. If it is not found then the
1101 //LocationListener was removed when it had a pending broadcast and should
1102 //not be added back.
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001103 synchronized (mLock) {
1104 IBinder binder = listener.asBinder();
1105 Receiver receiver = mReceivers.get(binder);
1106 if (receiver != null) {
1107 synchronized (receiver) {
1108 // so wakelock calls will succeed
1109 long identity = Binder.clearCallingIdentity();
1110 receiver.decrementPendingBroadcastsLocked();
1111 Binder.restoreCallingIdentity(identity);
David Christie2ff96af2014-01-30 16:09:37 -08001112 }
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001113 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001114 }
1115 }
1116
Lifu Tang82f893d2016-01-21 18:15:33 -08001117 /**
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001118 * Returns the year of the GNSS hardware.
Lifu Tang82f893d2016-01-21 18:15:33 -08001119 */
1120 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001121 public int getGnssYearOfHardware() {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001122 if (mGnssSystemInfoProvider != null) {
Lifu Tang9363b942016-02-16 18:07:00 -08001123 return mGnssSystemInfoProvider.getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001124 } else {
1125 return 0;
1126 }
1127 }
1128
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001129
1130 /**
1131 * Returns the model name of the GNSS hardware.
1132 */
1133 @Override
1134 public String getGnssHardwareModelName() {
1135 if (mGnssSystemInfoProvider != null) {
1136 return mGnssSystemInfoProvider.getGnssHardwareModelName();
1137 } else {
1138 return LocationManager.GNSS_HARDWARE_MODEL_NAME_UNKNOWN;
1139 }
1140 }
1141
Wyatt Rileycf879db2017-01-12 13:57:38 -08001142 /**
1143 * Runs some checks for GNSS (FINE) level permissions, used by several methods which directly
1144 * (try to) access GNSS information at this layer.
1145 */
1146 private boolean hasGnssPermissions(String packageName) {
1147 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
1148 checkResolutionLevelIsSufficientForProviderUse(
1149 allowedResolutionLevel,
1150 LocationManager.GPS_PROVIDER);
1151
1152 int pid = Binder.getCallingPid();
1153 int uid = Binder.getCallingUid();
1154 long identity = Binder.clearCallingIdentity();
1155 boolean hasLocationAccess;
1156 try {
1157 hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
1158 } finally {
1159 Binder.restoreCallingIdentity(identity);
1160 }
1161
1162 return hasLocationAccess;
1163 }
1164
1165 /**
1166 * Returns the GNSS batching size, if available.
1167 */
1168 @Override
1169 public int getGnssBatchSize(String packageName) {
1170 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1171 "Location Hardware permission not granted to access hardware batching");
1172
1173 if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
1174 return mGnssBatchingProvider.getSize();
1175 } else {
1176 return 0;
1177 }
1178 }
1179
1180 /**
1181 * Adds a callback for GNSS Batching events, if permissions allow, which are transported
1182 * to potentially multiple listeners by the BatchedLocationCallbackTransport above this.
1183 */
1184 @Override
1185 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) {
1186 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1187 "Location Hardware permission not granted to access hardware batching");
1188
1189 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1190 return false;
1191 }
1192
1193 mGnssBatchingCallback = callback;
1194 mGnssBatchingDeathCallback = new LinkedCallback(callback);
1195 try {
1196 callback.asBinder().linkToDeath(mGnssBatchingDeathCallback, 0 /* flags */);
1197 } catch (RemoteException e) {
1198 // if the remote process registering the listener is already dead, just swallow the
1199 // exception and return
1200 Log.e(TAG, "Remote listener already died.", e);
1201 return false;
1202 }
1203
1204 return true;
1205 }
1206
1207 private class LinkedCallback implements IBinder.DeathRecipient {
1208 private final IBatchedLocationCallback mCallback;
1209
1210 public LinkedCallback(@NonNull IBatchedLocationCallback callback) {
1211 mCallback = callback;
1212 }
1213
1214 @NonNull
1215 public IBatchedLocationCallback getUnderlyingListener() {
1216 return mCallback;
1217 }
1218
1219 @Override
1220 public void binderDied() {
1221 Log.d(TAG, "Remote Batching Callback died: " + mCallback);
1222 stopGnssBatch();
1223 removeGnssBatchingCallback();
1224 }
1225 }
1226
1227 /**
1228 * Removes callback for GNSS batching
1229 */
1230 @Override
1231 public void removeGnssBatchingCallback() {
1232 try {
1233 mGnssBatchingCallback.asBinder().unlinkToDeath(mGnssBatchingDeathCallback,
1234 0 /* flags */);
1235 } catch (NoSuchElementException e) {
1236 // if the death callback isn't connected (it should be...), log error, swallow the
1237 // exception and return
1238 Log.e(TAG, "Couldn't unlink death callback.", e);
1239 }
1240 mGnssBatchingCallback = null;
1241 mGnssBatchingDeathCallback = null;
1242 }
1243
1244
1245 /**
1246 * Starts GNSS batching, if available.
1247 */
1248 @Override
1249 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
1250 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1251 "Location Hardware permission not granted to access hardware batching");
1252
1253 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1254 return false;
1255 }
1256
1257 if (mGnssBatchingInProgress) {
1258 // Current design does not expect multiple starts to be called repeatedly
1259 Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch");
1260 // Try to clean up anyway, and continue
1261 stopGnssBatch();
1262 }
1263
1264 mGnssBatchingInProgress = true;
1265 return mGnssBatchingProvider.start(periodNanos, wakeOnFifoFull);
1266 }
1267
1268 /**
1269 * Flushes a GNSS batch in progress
1270 */
1271 @Override
1272 public void flushGnssBatch(String packageName) {
1273 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1274 "Location Hardware permission not granted to access hardware batching");
1275
1276 if (!hasGnssPermissions(packageName)) {
1277 Log.e(TAG, "flushGnssBatch called without GNSS permissions");
1278 return;
1279 }
1280
1281 if (!mGnssBatchingInProgress) {
1282 Log.w(TAG, "flushGnssBatch called with no batch in progress");
1283 }
1284
1285 if (mGnssBatchingProvider != null) {
gomo48f1a642017-11-10 20:35:46 -08001286 mGnssBatchingProvider.flush();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001287 }
1288 }
1289
1290 /**
1291 * Stops GNSS batching
1292 */
1293 @Override
1294 public boolean stopGnssBatch() {
1295 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1296 "Location Hardware permission not granted to access hardware batching");
1297
1298 if (mGnssBatchingProvider != null) {
1299 mGnssBatchingInProgress = false;
1300 return mGnssBatchingProvider.stop();
gomo48f1a642017-11-10 20:35:46 -08001301 } else {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001302 return false;
1303 }
1304 }
1305
1306 @Override
1307 public void reportLocationBatch(List<Location> locations) {
1308 checkCallerIsProvider();
1309
1310 // Currently used only for GNSS locations - update permissions check if changed
1311 if (isAllowedByCurrentUserSettingsLocked(LocationManager.GPS_PROVIDER)) {
1312 if (mGnssBatchingCallback == null) {
1313 Slog.e(TAG, "reportLocationBatch() called without active Callback");
1314 return;
1315 }
1316 try {
1317 mGnssBatchingCallback.onLocationBatch(locations);
1318 } catch (RemoteException e) {
1319 Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e);
1320 }
1321 } else {
1322 Slog.w(TAG, "reportLocationBatch() called without user permission, locations blocked");
1323 }
1324 }
1325
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001326 private void addProviderLocked(LocationProviderInterface provider) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001327 mProviders.add(provider);
1328 mProvidersByName.put(provider.getName(), provider);
1329 }
1330
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001331 private void removeProviderLocked(LocationProviderInterface provider) {
1332 provider.disable();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001333 mProviders.remove(provider);
1334 mProvidersByName.remove(provider.getName());
1335 }
1336
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001337 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001338 * Returns "true" if access to the specified location provider is allowed by the current
1339 * user's settings. Access to all location providers is forbidden to non-location-provider
1340 * processes belonging to background users.
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001341 *
1342 * @param provider the name of the location provider
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001343 */
Victoria Lease09eeaec2013-02-05 11:34:13 -08001344 private boolean isAllowedByCurrentUserSettingsLocked(String provider) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001345 if (mEnabledProviders.contains(provider)) {
1346 return true;
1347 }
1348 if (mDisabledProviders.contains(provider)) {
1349 return false;
1350 }
Maggieaa080f92018-01-04 15:35:11 -08001351 return isLocationProviderEnabledForUser(provider, mCurrentUserId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001352 }
1353
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001354 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001355 * Returns "true" if access to the specified location provider is allowed by the specified
1356 * user's settings. Access to all location providers is forbidden to non-location-provider
1357 * processes belonging to background users.
1358 *
1359 * @param provider the name of the location provider
gomo48f1a642017-11-10 20:35:46 -08001360 * @param uid the requestor's UID
Victoria Lease09eeaec2013-02-05 11:34:13 -08001361 */
1362 private boolean isAllowedByUserSettingsLocked(String provider, int uid) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001363 if (!isCurrentProfile(UserHandle.getUserId(uid)) && !isUidALocationProvider(uid)) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08001364 return false;
1365 }
1366 return isAllowedByCurrentUserSettingsLocked(provider);
1367 }
1368
1369 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001370 * Returns the permission string associated with the specified resolution level.
1371 *
1372 * @param resolutionLevel the resolution level
1373 * @return the permission string
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001374 */
Victoria Lease37425c32012-10-16 16:08:48 -07001375 private String getResolutionPermission(int resolutionLevel) {
1376 switch (resolutionLevel) {
1377 case RESOLUTION_LEVEL_FINE:
1378 return android.Manifest.permission.ACCESS_FINE_LOCATION;
1379 case RESOLUTION_LEVEL_COARSE:
1380 return android.Manifest.permission.ACCESS_COARSE_LOCATION;
1381 default:
1382 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001383 }
Victoria Leaseda479c52012-10-15 15:24:16 -07001384 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001385
Victoria Leaseda479c52012-10-15 15:24:16 -07001386 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001387 * Returns the resolution level allowed to the given PID/UID pair.
1388 *
1389 * @param pid the PID
1390 * @param uid the UID
1391 * @return resolution level allowed to the pid/uid pair
Victoria Leaseda479c52012-10-15 15:24:16 -07001392 */
Victoria Lease37425c32012-10-16 16:08:48 -07001393 private int getAllowedResolutionLevel(int pid, int uid) {
1394 if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001395 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001396 return RESOLUTION_LEVEL_FINE;
1397 } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001398 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001399 return RESOLUTION_LEVEL_COARSE;
1400 } else {
1401 return RESOLUTION_LEVEL_NONE;
Victoria Leaseda479c52012-10-15 15:24:16 -07001402 }
Victoria Lease4fab68b2012-09-13 13:20:59 -07001403 }
1404
1405 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001406 * Returns the resolution level allowed to the caller
1407 *
1408 * @return resolution level allowed to caller
Victoria Lease4fab68b2012-09-13 13:20:59 -07001409 */
Victoria Lease37425c32012-10-16 16:08:48 -07001410 private int getCallerAllowedResolutionLevel() {
1411 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
1412 }
1413
1414 /**
1415 * Throw SecurityException if specified resolution level is insufficient to use geofences.
1416 *
1417 * @param allowedResolutionLevel resolution level allowed to caller
1418 */
1419 private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
1420 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Lease4fab68b2012-09-13 13:20:59 -07001421 throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
1422 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 }
1424
Victoria Lease37425c32012-10-16 16:08:48 -07001425 /**
1426 * Return the minimum resolution level required to use the specified location provider.
1427 *
1428 * @param provider the name of the location provider
1429 * @return minimum resolution level required for provider
1430 */
1431 private int getMinimumResolutionLevelForProviderUse(String provider) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001432 if (LocationManager.GPS_PROVIDER.equals(provider) ||
1433 LocationManager.PASSIVE_PROVIDER.equals(provider)) {
1434 // gps and passive providers require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001435 return RESOLUTION_LEVEL_FINE;
Victoria Lease8dbb6342012-09-21 16:55:53 -07001436 } else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
1437 LocationManager.FUSED_PROVIDER.equals(provider)) {
1438 // network and fused providers are ok with COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001439 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001440 } else {
1441 // mock providers
1442 LocationProviderInterface lp = mMockProviders.get(provider);
1443 if (lp != null) {
1444 ProviderProperties properties = lp.getProperties();
1445 if (properties != null) {
1446 if (properties.mRequiresSatellite) {
1447 // provider requiring satellites require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001448 return RESOLUTION_LEVEL_FINE;
Laurent Tu941221c2012-10-04 14:21:52 -07001449 } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
1450 // provider requiring network and or cell require COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001451 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001452 }
1453 }
1454 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001455 }
Victoria Lease37425c32012-10-16 16:08:48 -07001456 return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
Victoria Leaseda479c52012-10-15 15:24:16 -07001457 }
1458
Victoria Lease37425c32012-10-16 16:08:48 -07001459 /**
1460 * Throw SecurityException if specified resolution level is insufficient to use the named
1461 * location provider.
1462 *
1463 * @param allowedResolutionLevel resolution level allowed to caller
gomo48f1a642017-11-10 20:35:46 -08001464 * @param providerName the name of the location provider
Victoria Lease37425c32012-10-16 16:08:48 -07001465 */
1466 private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel,
1467 String providerName) {
1468 int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName);
1469 if (allowedResolutionLevel < requiredResolutionLevel) {
1470 switch (requiredResolutionLevel) {
1471 case RESOLUTION_LEVEL_FINE:
1472 throw new SecurityException("\"" + providerName + "\" location provider " +
1473 "requires ACCESS_FINE_LOCATION permission.");
1474 case RESOLUTION_LEVEL_COARSE:
1475 throw new SecurityException("\"" + providerName + "\" location provider " +
1476 "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
1477 default:
1478 throw new SecurityException("Insufficient permission for \"" + providerName +
1479 "\" location provider.");
Victoria Leaseda479c52012-10-15 15:24:16 -07001480 }
1481 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001482 }
1483
David Christie82edc9b2013-07-19 11:31:42 -07001484 /**
1485 * Throw SecurityException if WorkSource use is not allowed (i.e. can't blame other packages
1486 * for battery).
1487 */
David Christie40e57822013-07-30 11:36:48 -07001488 private void checkDeviceStatsAllowed() {
David Christie82edc9b2013-07-19 11:31:42 -07001489 mContext.enforceCallingOrSelfPermission(
1490 android.Manifest.permission.UPDATE_DEVICE_STATS, null);
1491 }
1492
David Christie40e57822013-07-30 11:36:48 -07001493 private void checkUpdateAppOpsAllowed() {
1494 mContext.enforceCallingOrSelfPermission(
1495 android.Manifest.permission.UPDATE_APP_OPS_STATS, null);
1496 }
1497
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001498 public static int resolutionLevelToOp(int allowedResolutionLevel) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001499 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
1500 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001501 return AppOpsManager.OP_COARSE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001502 } else {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001503 return AppOpsManager.OP_FINE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001504 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001505 }
1506 return -1;
1507 }
1508
David Christieb870dbf2015-06-22 12:42:53 -07001509 boolean reportLocationAccessNoThrow(
1510 int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001511 int op = resolutionLevelToOp(allowedResolutionLevel);
1512 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001513 if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1514 return false;
1515 }
1516 }
David Christieb870dbf2015-06-22 12:42:53 -07001517
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001518 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001519 }
1520
David Christieb870dbf2015-06-22 12:42:53 -07001521 boolean checkLocationAccess(int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001522 int op = resolutionLevelToOp(allowedResolutionLevel);
1523 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001524 if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1525 return false;
1526 }
1527 }
David Christieb870dbf2015-06-22 12:42:53 -07001528
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001529 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001530 }
1531
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001532 /**
Maggie91e630c2018-01-24 17:31:46 -08001533 * Returns all providers by name, including passive and the ones that are not permitted to
1534 * be accessed by the calling activity or are currently disabled, but excluding fused.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001535 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001536 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 public List<String> getAllProviders() {
Maggie91e630c2018-01-24 17:31:46 -08001538 ArrayList<String> out;
1539 synchronized (mLock) {
1540 out = new ArrayList<>(mProviders.size());
1541 for (LocationProviderInterface provider : mProviders) {
1542 String name = provider.getName();
1543 if (LocationManager.FUSED_PROVIDER.equals(name)) {
1544 continue;
1545 }
1546 out.add(name);
1547 }
1548 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001549 if (D) Log.d(TAG, "getAllProviders()=" + out);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550 return out;
1551 }
1552
Mike Lockwood03ca2162010-04-01 08:10:09 -07001553 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001554 * Return all providers by name, that match criteria and are optionally
1555 * enabled.
1556 * Can return passive provider, but never returns fused provider.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001557 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001558 @Override
1559 public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
Victoria Lease37425c32012-10-16 16:08:48 -07001560 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001561 ArrayList<String> out;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001562 int uid = Binder.getCallingUid();
Victoria Lease269518e2012-10-29 08:25:39 -07001563 long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07001564 try {
1565 synchronized (mLock) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001566 out = new ArrayList<>(mProviders.size());
Victoria Leaseb711d572012-10-02 13:14:11 -07001567 for (LocationProviderInterface provider : mProviders) {
1568 String name = provider.getName();
1569 if (LocationManager.FUSED_PROVIDER.equals(name)) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001570 continue;
1571 }
Victoria Lease37425c32012-10-16 16:08:48 -07001572 if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08001573 if (enabledOnly && !isAllowedByUserSettingsLocked(name, uid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001574 continue;
1575 }
1576 if (criteria != null && !LocationProvider.propertiesMeetCriteria(
1577 name, provider.getProperties(), criteria)) {
1578 continue;
1579 }
1580 out.add(name);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001581 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001582 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001583 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001584 } finally {
1585 Binder.restoreCallingIdentity(identity);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001586 }
1587
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001588 if (D) Log.d(TAG, "getProviders()=" + out);
1589 return out;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001590 }
1591
1592 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001593 * Return the name of the best provider given a Criteria object.
1594 * This method has been deprecated from the public API,
Victoria Lease8dbb6342012-09-21 16:55:53 -07001595 * and the whole LocationProvider (including #meetsCriteria)
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001596 * has been deprecated as well. So this method now uses
1597 * some simplified logic.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001598 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001599 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001600 public String getBestProvider(Criteria criteria, boolean enabledOnly) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001601 String result = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001602
1603 List<String> providers = getProviders(criteria, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001604 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001605 result = pickBest(providers);
1606 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1607 return result;
1608 }
1609 providers = getProviders(null, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001610 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001611 result = pickBest(providers);
1612 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1613 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001614 }
1615
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001616 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001617 return null;
1618 }
1619
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001620 private String pickBest(List<String> providers) {
Victoria Lease1925e292012-09-24 17:00:18 -07001621 if (providers.contains(LocationManager.GPS_PROVIDER)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001622 return LocationManager.GPS_PROVIDER;
Victoria Lease1925e292012-09-24 17:00:18 -07001623 } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
1624 return LocationManager.NETWORK_PROVIDER;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001625 } else {
1626 return providers.get(0);
1627 }
1628 }
1629
Nick Pellye0fd6932012-07-11 10:26:13 -07001630 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001631 public boolean providerMeetsCriteria(String provider, Criteria criteria) {
1632 LocationProviderInterface p = mProvidersByName.get(provider);
1633 if (p == null) {
1634 throw new IllegalArgumentException("provider=" + provider);
1635 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001636
1637 boolean result = LocationProvider.propertiesMeetCriteria(
1638 p.getName(), p.getProperties(), criteria);
1639 if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result);
1640 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001641 }
1642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 private void updateProvidersLocked() {
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001644 boolean changesMade = false;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001645 for (int i = mProviders.size() - 1; i >= 0; i--) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001646 LocationProviderInterface p = mProviders.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001647 boolean isEnabled = p.isEnabled();
1648 String name = p.getName();
Victoria Lease09eeaec2013-02-05 11:34:13 -08001649 boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001650 if (isEnabled && !shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001651 updateProviderListenersLocked(name, false);
David Christieb084fef2013-12-18 14:33:57 -08001652 // If any provider has been disabled, clear all last locations for all providers.
1653 // This is to be on the safe side in case a provider has location derived from
1654 // this disabled provider.
1655 mLastLocation.clear();
1656 mLastLocationCoarseInterval.clear();
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001657 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001658 } else if (!isEnabled && shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001659 updateProviderListenersLocked(name, true);
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001660 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001661 }
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001662 }
1663 if (changesMade) {
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001664 mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
1665 UserHandle.ALL);
Tom O'Neill40a86c22013-09-03 18:05:13 -07001666 mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
1667 UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668 }
1669 }
1670
Amith Yamasanib27528d2014-06-05 15:02:10 -07001671 private void updateProviderListenersLocked(String provider, boolean enabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001672 int listeners = 0;
1673
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001674 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001675 if (p == null) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001676
1677 ArrayList<Receiver> deadReceivers = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07001678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1680 if (records != null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001681 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001682 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001683 // Sends a notification message to the receiver
1684 if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
1685 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001686 deadReceivers = new ArrayList<>();
Victoria Leaseb711d572012-10-02 13:14:11 -07001687 }
1688 deadReceivers.add(record.mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001689 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001690 listeners++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001691 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001692 }
1693 }
1694
1695 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001696 for (int i = deadReceivers.size() - 1; i >= 0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001697 removeUpdatesLocked(deadReceivers.get(i));
1698 }
1699 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 if (enabled) {
1702 p.enable();
1703 if (listeners > 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001704 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001705 }
1706 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001707 p.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 }
1710
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001711 private void applyRequirementsLocked(String provider) {
1712 LocationProviderInterface p = mProvidersByName.get(provider);
1713 if (p == null) return;
1714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001715 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001716 WorkSource worksource = new WorkSource();
1717 ProviderRequest providerRequest = new ProviderRequest();
1718
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001719 ContentResolver resolver = mContext.getContentResolver();
1720 long backgroundThrottleInterval = Settings.Global.getLong(
1721 resolver,
1722 Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
1723 DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
gomo48f1a642017-11-10 20:35:46 -08001724 // initialize the low power mode to true and set to false if any of the records requires
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001725
gomo48f1a642017-11-10 20:35:46 -08001726 providerRequest.lowPowerMode = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001727 if (records != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001728 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001729 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
David Christieb870dbf2015-06-22 12:42:53 -07001730 if (checkLocationAccess(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001731 record.mReceiver.mIdentity.mPid,
1732 record.mReceiver.mIdentity.mUid,
1733 record.mReceiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001734 record.mReceiver.mAllowedResolutionLevel)) {
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001735 LocationRequest locationRequest = record.mRealRequest;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001736 long interval = locationRequest.getInterval();
1737
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001738 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001739 if (!record.mIsForegroundUid) {
1740 interval = Math.max(interval, backgroundThrottleInterval);
1741 }
1742 if (interval != locationRequest.getInterval()) {
1743 locationRequest = new LocationRequest(locationRequest);
1744 locationRequest.setInterval(interval);
1745 }
1746 }
1747
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001748 record.mRequest = locationRequest;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001749 providerRequest.locationRequests.add(locationRequest);
gomo48f1a642017-11-10 20:35:46 -08001750 if (!locationRequest.isLowPowerMode()) {
1751 providerRequest.lowPowerMode = false;
1752 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001753 if (interval < providerRequest.interval) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001754 providerRequest.reportLocation = true;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001755 providerRequest.interval = interval;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001756 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001757 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001758 }
1759 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001760
1761 if (providerRequest.reportLocation) {
1762 // calculate who to blame for power
1763 // This is somewhat arbitrary. We pick a threshold interval
1764 // that is slightly higher that the minimum interval, and
1765 // spread the blame across all applications with a request
1766 // under that threshold.
1767 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
1768 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001769 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001770 LocationRequest locationRequest = record.mRequest;
Svet Ganove998c732016-06-10 00:12:38 -07001771
1772 // Don't assign battery blame for update records whose
1773 // client has no permission to receive location data.
1774 if (!providerRequest.locationRequests.contains(locationRequest)) {
1775 continue;
1776 }
1777
Victoria Leaseb711d572012-10-02 13:14:11 -07001778 if (locationRequest.getInterval() <= thresholdInterval) {
David Christiee55c9682013-08-22 10:10:34 -07001779 if (record.mReceiver.mWorkSource != null
Narayan Kamath32684dd2018-01-08 17:32:51 +00001780 && isValidWorkSource(record.mReceiver.mWorkSource)) {
David Christie82edc9b2013-07-19 11:31:42 -07001781 worksource.add(record.mReceiver.mWorkSource);
1782 } else {
Narayan Kamath32684dd2018-01-08 17:32:51 +00001783 // Assign blame to caller if there's no WorkSource associated with
1784 // the request or if it's invalid.
David Christie82edc9b2013-07-19 11:31:42 -07001785 worksource.add(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001786 record.mReceiver.mIdentity.mUid,
1787 record.mReceiver.mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001788 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001789 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001790 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001791 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 }
1793 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001794
1795 if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
1796 p.setRequest(providerRequest, worksource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797 }
1798
Narayan Kamath32684dd2018-01-08 17:32:51 +00001799 /**
1800 * Whether a given {@code WorkSource} associated with a Location request is valid.
1801 */
1802 private static boolean isValidWorkSource(WorkSource workSource) {
1803 if (workSource.size() > 0) {
1804 // If the WorkSource has one or more non-chained UIDs, make sure they're accompanied
1805 // by tags.
1806 return workSource.getName(0) != null;
1807 } else {
1808 // For now, make sure callers have supplied an attribution tag for use with
1809 // AppOpsManager. This might be relaxed in the future.
1810 final ArrayList<WorkChain> workChains = workSource.getWorkChains();
1811 return workChains != null && !workChains.isEmpty() &&
1812 workChains.get(0).getAttributionTag() != null;
1813 }
1814 }
1815
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001816 @Override
1817 public String[] getBackgroundThrottlingWhitelist() {
1818 synchronized (mLock) {
1819 return mBackgroundThrottlePackageWhitelist.toArray(
gomo48f1a642017-11-10 20:35:46 -08001820 new String[mBackgroundThrottlePackageWhitelist.size()]);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001821 }
1822 }
1823
1824 private void updateBackgroundThrottlingWhitelistLocked() {
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001825 String setting = Settings.Global.getString(
gomo48f1a642017-11-10 20:35:46 -08001826 mContext.getContentResolver(),
1827 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001828 if (setting == null) {
1829 setting = "";
1830 }
1831
1832 mBackgroundThrottlePackageWhitelist.clear();
1833 mBackgroundThrottlePackageWhitelist.addAll(
gomo48f1a642017-11-10 20:35:46 -08001834 SystemConfig.getInstance().getAllowUnthrottledLocation());
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001835 mBackgroundThrottlePackageWhitelist.addAll(
gomo48f1a642017-11-10 20:35:46 -08001836 Arrays.asList(setting.split(",")));
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001837 }
1838
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001839 private boolean isThrottlingExemptLocked(Identity identity) {
1840 if (identity.mUid == Process.SYSTEM_UID) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001841 return true;
1842 }
1843
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001844 if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001845 return true;
1846 }
1847
1848 for (LocationProviderProxy provider : mProxyProviders) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001849 if (identity.mPackageName.equals(provider.getConnectedPackageName())) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001850 return true;
1851 }
1852 }
1853
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001854 return false;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001855 }
1856
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001857 private class UpdateRecord {
1858 final String mProvider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001859 final LocationRequest mRealRequest; // original request from client
1860 LocationRequest mRequest; // possibly throttled version of the request
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001861 final Receiver mReceiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001862 boolean mIsForegroundUid;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001863 Location mLastFixBroadcast;
1864 long mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001865
1866 /**
1867 * Note: must be constructed with lock held.
1868 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001869 UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001870 mProvider = provider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001871 mRealRequest = request;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001872 mRequest = request;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001873 mReceiver = receiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001874 mIsForegroundUid = isImportanceForeground(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001875 mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001876
1877 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1878 if (records == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001879 records = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001880 mRecordsByProvider.put(provider, records);
1881 }
1882 if (!records.contains(this)) {
1883 records.add(this);
1884 }
David Christie2ff96af2014-01-30 16:09:37 -08001885
1886 // Update statistics for historical location requests by package/provider
1887 mRequestStatistics.startRequesting(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001888 mReceiver.mIdentity.mPackageName, provider, request.getInterval());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001889 }
1890
1891 /**
David Christie2ff96af2014-01-30 16:09:37 -08001892 * Method to be called when a record will no longer be used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001893 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001894 void disposeLocked(boolean removeReceiver) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001895 mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider);
David Christie2ff96af2014-01-30 16:09:37 -08001896
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001897 // remove from mRecordsByProvider
1898 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
1899 if (globalRecords != null) {
1900 globalRecords.remove(this);
1901 }
1902
1903 if (!removeReceiver) return; // the caller will handle the rest
1904
1905 // remove from Receiver#mUpdateRecords
1906 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
1907 if (receiverRecords != null) {
1908 receiverRecords.remove(this.mProvider);
1909
1910 // and also remove the Receiver if it has no more update records
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001911 if (receiverRecords.size() == 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001912 removeUpdatesLocked(mReceiver);
1913 }
Mike Lockwood3a76fd62009-09-01 07:26:56 -04001914 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001915 }
1916
1917 @Override
1918 public String toString() {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001919 return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
gomo48f1a642017-11-10 20:35:46 -08001920 + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground"
1921 : " background")
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001922 + ")" + " " + mRealRequest + "]";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001923 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001924 }
1925
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001926 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -07001927 String packageName, WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001928 IBinder binder = listener.asBinder();
1929 Receiver receiver = mReceivers.get(binder);
1930 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07001931 receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
1932 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001933 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001934 receiver.getListener().asBinder().linkToDeath(receiver, 0);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001935 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001936 Slog.e(TAG, "linkToDeath failed:", e);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001937 return null;
1938 }
Wen Jingcb3ab222014-03-27 13:42:59 +08001939 mReceivers.put(binder, receiver);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001940 }
1941 return receiver;
1942 }
1943
David Christie82edc9b2013-07-19 11:31:42 -07001944 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
David Christie40e57822013-07-30 11:36:48 -07001945 WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001946 Receiver receiver = mReceivers.get(intent);
1947 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07001948 receiver = new Receiver(null, intent, pid, uid, packageName, workSource,
1949 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001950 mReceivers.put(intent, receiver);
1951 }
1952 return receiver;
1953 }
1954
Victoria Lease37425c32012-10-16 16:08:48 -07001955 /**
1956 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
1957 * and consistency requirements.
1958 *
1959 * @param request the LocationRequest from which to create a sanitized version
Victoria Lease37425c32012-10-16 16:08:48 -07001960 * @return a version of request that meets the given resolution and consistency requirements
1961 * @hide
1962 */
gomo48f1a642017-11-10 20:35:46 -08001963 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel,
1964 boolean callerHasLocationHardwarePermission) {
Victoria Lease37425c32012-10-16 16:08:48 -07001965 LocationRequest sanitizedRequest = new LocationRequest(request);
gomo48f1a642017-11-10 20:35:46 -08001966 if (!callerHasLocationHardwarePermission) {
1967 // allow setting low power mode only for callers with location hardware permission
1968 sanitizedRequest.setLowPowerMode(false);
1969 }
Victoria Lease37425c32012-10-16 16:08:48 -07001970 if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
1971 switch (sanitizedRequest.getQuality()) {
Victoria Lease09016ab2012-09-16 12:33:15 -07001972 case LocationRequest.ACCURACY_FINE:
Victoria Lease37425c32012-10-16 16:08:48 -07001973 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
Victoria Lease09016ab2012-09-16 12:33:15 -07001974 break;
1975 case LocationRequest.POWER_HIGH:
Victoria Lease37425c32012-10-16 16:08:48 -07001976 sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
Victoria Lease09016ab2012-09-16 12:33:15 -07001977 break;
1978 }
1979 // throttle
Victoria Lease37425c32012-10-16 16:08:48 -07001980 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1981 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001982 }
Victoria Lease37425c32012-10-16 16:08:48 -07001983 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1984 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001985 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07001986 }
Nick Pelly4e31c4f2012-08-13 19:35:39 -07001987 // make getFastestInterval() the minimum of interval and fastest interval
Victoria Lease37425c32012-10-16 16:08:48 -07001988 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07001989 request.setFastestInterval(request.getInterval());
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001990 }
Victoria Lease37425c32012-10-16 16:08:48 -07001991 return sanitizedRequest;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001992 }
1993
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001994 private void checkPackageName(String packageName) {
Nick Pellye0fd6932012-07-11 10:26:13 -07001995 if (packageName == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001996 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07001997 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001998 int uid = Binder.getCallingUid();
Nick Pellye0fd6932012-07-11 10:26:13 -07001999 String[] packages = mPackageManager.getPackagesForUid(uid);
2000 if (packages == null) {
2001 throw new SecurityException("invalid UID " + uid);
2002 }
2003 for (String pkg : packages) {
2004 if (packageName.equals(pkg)) return;
2005 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002006 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002007 }
2008
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002009 private void checkPendingIntent(PendingIntent intent) {
2010 if (intent == null) {
2011 throw new IllegalArgumentException("invalid pending intent: " + intent);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002012 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002013 }
2014
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002015 private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent,
David Christie40e57822013-07-30 11:36:48 -07002016 int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002017 if (intent == null && listener == null) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002018 throw new IllegalArgumentException("need either listener or intent");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002019 } else if (intent != null && listener != null) {
2020 throw new IllegalArgumentException("cannot register both listener and intent");
2021 } else if (intent != null) {
2022 checkPendingIntent(intent);
David Christie40e57822013-07-30 11:36:48 -07002023 return getReceiverLocked(intent, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002024 } else {
David Christie40e57822013-07-30 11:36:48 -07002025 return getReceiverLocked(listener, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002026 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002027 }
2028
Nick Pellye0fd6932012-07-11 10:26:13 -07002029 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002030 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
2031 PendingIntent intent, String packageName) {
2032 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2033 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002034 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2035 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2036 request.getProvider());
David Christie82edc9b2013-07-19 11:31:42 -07002037 WorkSource workSource = request.getWorkSource();
Narayan Kamath32684dd2018-01-08 17:32:51 +00002038 if (workSource != null && !workSource.isEmpty()) {
David Christie40e57822013-07-30 11:36:48 -07002039 checkDeviceStatsAllowed();
2040 }
2041 boolean hideFromAppOps = request.getHideFromAppOps();
2042 if (hideFromAppOps) {
2043 checkUpdateAppOpsAllowed();
David Christie82edc9b2013-07-19 11:31:42 -07002044 }
gomo48f1a642017-11-10 20:35:46 -08002045 boolean callerHasLocationHardwarePermission =
2046 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
Maggieaa080f92018-01-04 15:35:11 -08002047 == PERMISSION_GRANTED;
gomo48f1a642017-11-10 20:35:46 -08002048 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel,
2049 callerHasLocationHardwarePermission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002050
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002051 final int pid = Binder.getCallingPid();
2052 final int uid = Binder.getCallingUid();
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002053 // providers may use public location API's, need to clear identity
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002054 long identity = Binder.clearCallingIdentity();
2055 try {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002056 // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2057 // a location.
David Christieb870dbf2015-06-22 12:42:53 -07002058 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002059
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002060 synchronized (mLock) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002061 Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
David Christie40e57822013-07-30 11:36:48 -07002062 packageName, workSource, hideFromAppOps);
Victoria Lease37425c32012-10-16 16:08:48 -07002063 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
Mike Lockwood2d4d1bf2010-10-18 17:06:26 -04002064 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002065 } finally {
2066 Binder.restoreCallingIdentity(identity);
2067 }
2068 }
2069
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002070 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
2071 int pid, int uid, String packageName) {
2072 // Figure out the provider. Either its explicitly request (legacy use cases), or
2073 // use the fused provider
2074 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2075 String name = request.getProvider();
Victoria Lease09016ab2012-09-16 12:33:15 -07002076 if (name == null) {
2077 throw new IllegalArgumentException("provider name must not be null");
2078 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -07002079
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002080 LocationProviderInterface provider = mProvidersByName.get(name);
2081 if (provider == null) {
Victoria Leaseb30f3832013-10-13 12:15:40 -07002082 throw new IllegalArgumentException("provider doesn't exist: " + name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002083 }
2084
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002085 UpdateRecord record = new UpdateRecord(name, request, receiver);
gomo48f1a642017-11-10 20:35:46 -08002086 if (D) {
2087 Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
2088 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
2089 + (record.mIsForegroundUid ? "foreground" : "background")
2090 + (isThrottlingExemptLocked(receiver.mIdentity)
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002091 ? " [whitelisted]" : "") + ")");
gomo48f1a642017-11-10 20:35:46 -08002092 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002093
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002094 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
2095 if (oldRecord != null) {
2096 oldRecord.disposeLocked(false);
2097 }
2098
Victoria Lease09eeaec2013-02-05 11:34:13 -08002099 boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002100 if (isProviderEnabled) {
2101 applyRequirementsLocked(name);
2102 } else {
2103 // Notify the listener that updates are currently disabled
2104 receiver.callProviderEnabledLocked(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002105 }
David Christie0b837452013-07-29 16:02:13 -07002106 // Update the monitoring here just in case multiple location requests were added to the
2107 // same receiver (this request may be high power and the initial might not have been).
2108 receiver.updateMonitoring(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002109 }
2110
Nick Pellye0fd6932012-07-11 10:26:13 -07002111 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002112 public void removeUpdates(ILocationListener listener, PendingIntent intent,
2113 String packageName) {
2114 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002115
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002116 final int pid = Binder.getCallingPid();
2117 final int uid = Binder.getCallingUid();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002118
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002119 synchronized (mLock) {
David Christie82edc9b2013-07-19 11:31:42 -07002120 WorkSource workSource = null;
David Christie40e57822013-07-30 11:36:48 -07002121 boolean hideFromAppOps = false;
2122 Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid,
2123 packageName, workSource, hideFromAppOps);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002124
2125 // providers may use public location API's, need to clear identity
2126 long identity = Binder.clearCallingIdentity();
2127 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002128 removeUpdatesLocked(receiver);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002129 } finally {
2130 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002132 }
2133 }
2134
2135 private void removeUpdatesLocked(Receiver receiver) {
Dianne Hackborn7ff30112012-11-08 11:12:09 -08002136 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002137
2138 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
2139 receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
2140 synchronized (receiver) {
Victoria Lease0aa28602013-05-29 15:28:26 -07002141 receiver.clearPendingBroadcastsLocked();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002142 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002143 }
2144
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07002145 receiver.updateMonitoring(false);
2146
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002147 // Record which providers were associated with this listener
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002148 HashSet<String> providers = new HashSet<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002149 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2150 if (oldRecords != null) {
2151 // Call dispose() on the obsolete update records.
2152 for (UpdateRecord record : oldRecords.values()) {
David Christie2ff96af2014-01-30 16:09:37 -08002153 // Update statistics for historical location requests by package/provider
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002154 record.disposeLocked(false);
2155 }
2156 // Accumulate providers
2157 providers.addAll(oldRecords.keySet());
2158 }
2159
2160 // update provider
2161 for (String provider : providers) {
2162 // If provider is already disabled, don't need to do anything
Victoria Lease09eeaec2013-02-05 11:34:13 -08002163 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002164 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002165 }
2166
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002167 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002168 }
2169 }
2170
Dianne Hackbornc2293022013-02-06 23:14:49 -08002171 private void applyAllProviderRequirementsLocked() {
2172 for (LocationProviderInterface p : mProviders) {
2173 // If provider is already disabled, don't need to do anything
Dianne Hackborn64d41d72013-02-07 00:33:31 -08002174 if (!isAllowedByCurrentUserSettingsLocked(p.getName())) {
Dianne Hackbornc2293022013-02-06 23:14:49 -08002175 continue;
2176 }
2177
2178 applyRequirementsLocked(p.getName());
2179 }
2180 }
2181
Nick Pellye0fd6932012-07-11 10:26:13 -07002182 @Override
Nick Pelly4035f5a2012-08-17 14:43:49 -07002183 public Location getLastLocation(LocationRequest request, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002184 if (D) Log.d(TAG, "getLastLocation: " + request);
2185 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002186 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly4035f5a2012-08-17 14:43:49 -07002187 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002188 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2189 request.getProvider());
2190 // no need to sanitize this request, as only the provider name is used
Nick Pelly4035f5a2012-08-17 14:43:49 -07002191
David Christieb870dbf2015-06-22 12:42:53 -07002192 final int pid = Binder.getCallingPid();
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002193 final int uid = Binder.getCallingUid();
2194 final long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07002195 try {
2196 if (mBlacklist.isBlacklisted(packageName)) {
gomo48f1a642017-11-10 20:35:46 -08002197 if (D) {
2198 Log.d(TAG, "not returning last loc for blacklisted app: " +
2199 packageName);
2200 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002201 return null;
2202 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002203
David Christieb870dbf2015-06-22 12:42:53 -07002204 if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel)) {
gomo48f1a642017-11-10 20:35:46 -08002205 if (D) {
2206 Log.d(TAG, "not returning last loc for no op app: " +
2207 packageName);
2208 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002209 return null;
2210 }
2211
Victoria Leaseb711d572012-10-02 13:14:11 -07002212 synchronized (mLock) {
2213 // Figure out the provider. Either its explicitly request (deprecated API's),
2214 // or use the fused provider
2215 String name = request.getProvider();
2216 if (name == null) name = LocationManager.FUSED_PROVIDER;
2217 LocationProviderInterface provider = mProvidersByName.get(name);
2218 if (provider == null) return null;
2219
Victoria Lease09eeaec2013-02-05 11:34:13 -08002220 if (!isAllowedByUserSettingsLocked(name, uid)) return null;
Victoria Leaseb711d572012-10-02 13:14:11 -07002221
David Christie1b9b7b12013-04-15 15:31:11 -07002222 Location location;
2223 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2224 // Make sure that an app with coarse permissions can't get frequent location
2225 // updates by calling LocationManager.getLastKnownLocation repeatedly.
2226 location = mLastLocationCoarseInterval.get(name);
2227 } else {
2228 location = mLastLocation.get(name);
2229 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002230 if (location == null) {
2231 return null;
2232 }
Victoria Lease37425c32012-10-16 16:08:48 -07002233 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
gomo48f1a642017-11-10 20:35:46 -08002234 Location noGPSLocation = location.getExtraLocation(
2235 Location.EXTRA_NO_GPS_LOCATION);
Victoria Leaseb711d572012-10-02 13:14:11 -07002236 if (noGPSLocation != null) {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002237 return new Location(mLocationFudger.getOrCreate(noGPSLocation));
Victoria Leaseb711d572012-10-02 13:14:11 -07002238 }
Victoria Lease37425c32012-10-16 16:08:48 -07002239 } else {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002240 return new Location(location);
Victoria Lease09016ab2012-09-16 12:33:15 -07002241 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002242 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002243 return null;
2244 } finally {
2245 Binder.restoreCallingIdentity(identity);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002246 }
2247 }
2248
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002249 /**
2250 * Provides an interface to inject and set the last location if location is not available
2251 * currently.
2252 *
2253 * This helps in cases where the product (Cars for example) has saved the last known location
2254 * before powering off. This interface lets the client inject the saved location while the GPS
2255 * chipset is getting its first fix, there by improving user experience.
2256 *
2257 * @param location - Location object to inject
2258 * @return true if update was successful, false if not
2259 */
2260 @Override
2261 public boolean injectLocation(Location location) {
2262 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
2263 "Location Hardware permission not granted to inject location");
2264 mContext.enforceCallingPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
2265 "Access Fine Location permission not granted to inject Location");
2266
2267 if (location == null) {
2268 if (D) {
2269 Log.d(TAG, "injectLocation(): called with null location");
2270 }
2271 return false;
2272 }
2273 LocationProviderInterface p = null;
2274 String provider = location.getProvider();
2275 if (provider != null) {
2276 p = mProvidersByName.get(provider);
2277 }
2278 if (p == null) {
2279 if (D) {
2280 Log.d(TAG, "injectLocation(): unknown provider");
2281 }
2282 return false;
2283 }
2284 synchronized (mLock) {
2285 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
2286 if (D) {
2287 Log.d(TAG, "Location disabled in Settings for current user:" + mCurrentUserId);
2288 }
2289 return false;
2290 } else {
2291 // NOTE: If last location is already available, location is not injected. If
2292 // provider's normal source (like a GPS chipset) have already provided an output,
2293 // there is no need to inject this location.
2294 if (mLastLocation.get(provider) == null) {
2295 updateLastLocationLocked(location, provider);
2296 } else {
2297 if (D) {
2298 Log.d(TAG, "injectLocation(): Location exists. Not updating");
2299 }
2300 return false;
2301 }
2302 }
2303 }
2304 return true;
2305 }
2306
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002307 @Override
2308 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
2309 String packageName) {
2310 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002311 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2312 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002313 checkPendingIntent(intent);
2314 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002315 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2316 request.getProvider());
gomo48f1a642017-11-10 20:35:46 -08002317 // Require that caller can manage given document
2318 boolean callerHasLocationHardwarePermission =
2319 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
Maggieaa080f92018-01-04 15:35:11 -08002320 == PERMISSION_GRANTED;
gomo48f1a642017-11-10 20:35:46 -08002321 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel,
2322 callerHasLocationHardwarePermission);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002323
Victoria Lease37425c32012-10-16 16:08:48 -07002324 if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002325
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002326 // geo-fence manager uses the public location API, need to clear identity
2327 int uid = Binder.getCallingUid();
Xiaohui Chena4490622015-09-22 15:29:31 -07002328 // TODO: http://b/23822629
2329 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
Victoria Lease56e675b2012-11-05 19:25:06 -08002330 // temporary measure until geofences work for secondary users
2331 Log.w(TAG, "proximity alerts are currently available only to the primary user");
2332 return;
2333 }
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002334 long identity = Binder.clearCallingIdentity();
2335 try {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002336 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
2337 uid, packageName);
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002338 } finally {
2339 Binder.restoreCallingIdentity(identity);
2340 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002341 }
2342
2343 @Override
2344 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002345 checkPendingIntent(intent);
2346 checkPackageName(packageName);
2347
2348 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2349
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002350 // geo-fence manager uses the public location API, need to clear identity
2351 long identity = Binder.clearCallingIdentity();
2352 try {
2353 mGeofenceManager.removeFence(geofence, intent);
2354 } finally {
2355 Binder.restoreCallingIdentity(identity);
2356 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002357 }
2358
2359
2360 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002361 public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002362 if (!hasGnssPermissions(packageName) || mGnssStatusProvider == null) {
Takayuki Hoshib254ab6a2014-10-23 16:46:02 +09002363 return false;
2364 }
2365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002366 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002367 mGnssStatusProvider.registerGnssStatusCallback(callback);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002368 } catch (RemoteException e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002369 Slog.e(TAG, "mGpsStatusProvider.registerGnssStatusCallback failed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002370 return false;
2371 }
2372 return true;
2373 }
2374
Nick Pellye0fd6932012-07-11 10:26:13 -07002375 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002376 public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002377 synchronized (mLock) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002378 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002379 mGnssStatusProvider.unregisterGnssStatusCallback(callback);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002380 } catch (Exception e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002381 Slog.e(TAG, "mGpsStatusProvider.unregisterGnssStatusCallback failed", e);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002382 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002383 }
2384 }
2385
Nick Pellye0fd6932012-07-11 10:26:13 -07002386 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002387 public boolean addGnssMeasurementsListener(
gomo48f1a642017-11-10 20:35:46 -08002388 IGnssMeasurementsListener listener, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002389 if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
destradaaea8a8a62014-06-23 18:19:03 -07002390 return false;
2391 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002392
2393 synchronized (mLock) {
2394 Identity callerIdentity
2395 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
Wyatt Riley11cc7492018-01-17 08:48:27 -08002396 mGnssMeasurementsListeners.put(listener.asBinder(), callerIdentity);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002397 long identity = Binder.clearCallingIdentity();
2398 try {
2399 if (isThrottlingExemptLocked(callerIdentity)
2400 || isImportanceForeground(
gomo48f1a642017-11-10 20:35:46 -08002401 mActivityManager.getPackageImportance(packageName))) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002402 return mGnssMeasurementsProvider.addListener(listener);
2403 }
2404 } finally {
2405 Binder.restoreCallingIdentity(identity);
2406 }
2407
2408 return true;
2409 }
destradaaea8a8a62014-06-23 18:19:03 -07002410 }
2411
2412 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002413 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
2414 if (mGnssMeasurementsProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002415 synchronized (mLock) {
Wyatt Riley11cc7492018-01-17 08:48:27 -08002416 mGnssMeasurementsListeners.remove(listener.asBinder());
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002417 mGnssMeasurementsProvider.removeListener(listener);
2418 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002419 }
destradaaea8a8a62014-06-23 18:19:03 -07002420 }
2421
2422 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002423 public boolean addGnssNavigationMessageListener(
2424 IGnssNavigationMessageListener listener,
destradaa4b3e3932014-07-21 18:01:47 -07002425 String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002426 if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) {
destradaa4b3e3932014-07-21 18:01:47 -07002427 return false;
2428 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002429
2430 synchronized (mLock) {
2431 Identity callerIdentity
gomo48f1a642017-11-10 20:35:46 -08002432 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
Wyatt Riley11cc7492018-01-17 08:48:27 -08002433 mGnssNavigationMessageListeners.put(listener.asBinder(), callerIdentity);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002434 long identity = Binder.clearCallingIdentity();
2435 try {
2436 if (isThrottlingExemptLocked(callerIdentity)
2437 || isImportanceForeground(
gomo48f1a642017-11-10 20:35:46 -08002438 mActivityManager.getPackageImportance(packageName))) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002439 return mGnssNavigationMessageProvider.addListener(listener);
2440 }
2441 } finally {
2442 Binder.restoreCallingIdentity(identity);
2443 }
2444
2445 return true;
2446 }
destradaa4b3e3932014-07-21 18:01:47 -07002447 }
2448
2449 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002450 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
2451 if (mGnssNavigationMessageProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002452 synchronized (mLock) {
Wyatt Riley11cc7492018-01-17 08:48:27 -08002453 mGnssNavigationMessageListeners.remove(listener.asBinder());
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002454 mGnssNavigationMessageProvider.removeListener(listener);
2455 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002456 }
destradaa4b3e3932014-07-21 18:01:47 -07002457 }
2458
2459 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002460 public boolean sendExtraCommand(String provider, String command, Bundle extras) {
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002461 if (provider == null) {
2462 // throw NullPointerException to remain compatible with previous implementation
2463 throw new NullPointerException();
2464 }
Victoria Lease37425c32012-10-16 16:08:48 -07002465 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2466 provider);
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002468 // and check for ACCESS_LOCATION_EXTRA_COMMANDS
Mike Lockwoodb7e99222009-07-07 13:18:21 -04002469 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
Maggieaa080f92018-01-04 15:35:11 -08002470 != PERMISSION_GRANTED)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002471 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
2472 }
2473
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002474 synchronized (mLock) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002475 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002476 if (p == null) return false;
Nick Pellye0fd6932012-07-11 10:26:13 -07002477
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002478 return p.sendExtraCommand(command, extras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002479 }
2480 }
2481
Nick Pellye0fd6932012-07-11 10:26:13 -07002482 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002483 public boolean sendNiResponse(int notifId, int userResponse) {
Mike Lockwood18ad9f62009-08-27 14:01:23 -07002484 if (Binder.getCallingUid() != Process.myUid()) {
2485 throw new SecurityException(
2486 "calling sendNiResponse from outside of the system is not allowed");
2487 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002488 try {
2489 return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002490 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002491 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
Danke Xie22d1f9f2009-08-18 18:28:45 -04002492 return false;
2493 }
2494 }
2495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002496 /**
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002497 * @return null if the provider does not exist
Alexey Tarasovf2db9fb2009-09-01 02:37:07 +11002498 * @throws SecurityException if the provider is not allowed to be
gomo48f1a642017-11-10 20:35:46 -08002499 * accessed by the caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002500 */
Nick Pellye0fd6932012-07-11 10:26:13 -07002501 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002502 public ProviderProperties getProviderProperties(String provider) {
Laurent Tub7f9d252012-10-16 14:25:00 -07002503 if (mProvidersByName.get(provider) == null) {
David Christie2ff96af2014-01-30 16:09:37 -08002504 return null;
Laurent Tub7f9d252012-10-16 14:25:00 -07002505 }
2506
Victoria Lease37425c32012-10-16 16:08:48 -07002507 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2508 provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002509
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002510 LocationProviderInterface p;
2511 synchronized (mLock) {
2512 p = mProvidersByName.get(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002513 }
2514
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002515 if (p == null) return null;
2516 return p.getProperties();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002517 }
2518
Jason Monkb71218a2015-06-17 14:44:39 -04002519 /**
2520 * @return null if the provider does not exist
2521 * @throws SecurityException if the provider is not allowed to be
gomo48f1a642017-11-10 20:35:46 -08002522 * accessed by the caller
Jason Monkb71218a2015-06-17 14:44:39 -04002523 */
2524 @Override
2525 public String getNetworkProviderPackage() {
2526 LocationProviderInterface p;
2527 synchronized (mLock) {
2528 if (mProvidersByName.get(LocationManager.NETWORK_PROVIDER) == null) {
2529 return null;
2530 }
2531 p = mProvidersByName.get(LocationManager.NETWORK_PROVIDER);
2532 }
2533
2534 if (p instanceof LocationProviderProxy) {
2535 return ((LocationProviderProxy) p).getConnectedPackageName();
2536 }
2537 return null;
2538 }
2539
Maggieaa080f92018-01-04 15:35:11 -08002540 /**
Maggieaa080f92018-01-04 15:35:11 -08002541 * Read location provider status from Settings.Secure
2542 *
2543 * @param provider the location provider to query
2544 * @param userId the user id to query
2545 * @return true if the provider is enabled
2546 */
2547 private boolean isLocationProviderEnabledForUser(String provider, int userId) {
2548 long identity = Binder.clearCallingIdentity();
2549 try {
2550 // Use system settings
2551 ContentResolver cr = mContext.getContentResolver();
2552 String allowedProviders = Settings.Secure.getStringForUser(
2553 cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userId);
2554 return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
2555 } finally {
2556 Binder.restoreCallingIdentity(identity);
2557 }
2558 }
2559
2560 /**
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002561 * Returns "true" if the UID belongs to a bound location provider.
2562 *
2563 * @param uid the uid
2564 * @return true if uid belongs to a bound location provider
2565 */
2566 private boolean isUidALocationProvider(int uid) {
2567 if (uid == Process.SYSTEM_UID) {
2568 return true;
2569 }
2570 if (mGeocodeProvider != null) {
David Christie1f141c12014-05-14 15:11:15 -07002571 if (doesUidHavePackage(uid, mGeocodeProvider.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002572 }
2573 for (LocationProviderProxy proxy : mProxyProviders) {
David Christie1f141c12014-05-14 15:11:15 -07002574 if (doesUidHavePackage(uid, proxy.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002575 }
2576 return false;
2577 }
2578
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002579 private void checkCallerIsProvider() {
2580 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
Maggieaa080f92018-01-04 15:35:11 -08002581 == PERMISSION_GRANTED) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002582 return;
2583 }
2584
2585 // Previously we only used the INSTALL_LOCATION_PROVIDER
2586 // check. But that is system or signature
2587 // protection level which is not flexible enough for
2588 // providers installed oustide the system image. So
2589 // also allow providers with a UID matching the
2590 // currently bound package name
2591
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002592 if (isUidALocationProvider(Binder.getCallingUid())) {
2593 return;
2594 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002595
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002596 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
2597 "or UID of a currently bound location provider");
2598 }
2599
David Christie1f141c12014-05-14 15:11:15 -07002600 /**
2601 * Returns true if the given package belongs to the given uid.
2602 */
2603 private boolean doesUidHavePackage(int uid, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002604 if (packageName == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002605 return false;
2606 }
David Christie1f141c12014-05-14 15:11:15 -07002607 String[] packageNames = mPackageManager.getPackagesForUid(uid);
2608 if (packageNames == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002609 return false;
2610 }
David Christie1f141c12014-05-14 15:11:15 -07002611 for (String name : packageNames) {
2612 if (packageName.equals(name)) {
2613 return true;
2614 }
2615 }
2616 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002617 }
2618
Nick Pellye0fd6932012-07-11 10:26:13 -07002619 @Override
Mike Lockwooda4903f22010-02-17 06:42:23 -05002620 public void reportLocation(Location location, boolean passive) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002621 checkCallerIsProvider();
Mike Lockwood275555c2009-05-01 11:30:34 -04002622
Nick Pelly2eeeec22012-07-18 13:13:37 -07002623 if (!location.isComplete()) {
2624 Log.w(TAG, "Dropping incomplete location: " + location);
2625 return;
2626 }
2627
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002628 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location);
2629 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location);
Mike Lockwooda4903f22010-02-17 06:42:23 -05002630 m.arg1 = (passive ? 1 : 0);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002631 mLocationHandler.sendMessageAtFrontOfQueue(m);
2632 }
2633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002634
Laurent Tu75defb62012-11-01 16:21:52 -07002635 private static boolean shouldBroadcastSafe(
2636 Location loc, Location lastLoc, UpdateRecord record, long now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002637 // Always broadcast the first update
2638 if (lastLoc == null) {
2639 return true;
2640 }
2641
Nick Pellyf1be6862012-05-15 10:53:42 -07002642 // Check whether sufficient time has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002643 long minTime = record.mRealRequest.getFastestInterval();
David Christie1b9b7b12013-04-15 15:31:11 -07002644 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
2645 / NANOS_PER_MILLI;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002646 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002647 return false;
2648 }
2649
2650 // Check whether sufficient distance has been traveled
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002651 double minDistance = record.mRealRequest.getSmallestDisplacement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002652 if (minDistance > 0.0) {
2653 if (loc.distanceTo(lastLoc) <= minDistance) {
2654 return false;
2655 }
2656 }
2657
Laurent Tu75defb62012-11-01 16:21:52 -07002658 // Check whether sufficient number of udpates is left
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002659 if (record.mRealRequest.getNumUpdates() <= 0) {
Laurent Tu75defb62012-11-01 16:21:52 -07002660 return false;
2661 }
2662
2663 // Check whether the expiry date has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002664 return record.mRealRequest.getExpireAt() >= now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002665 }
2666
Mike Lockwooda4903f22010-02-17 06:42:23 -05002667 private void handleLocationChangedLocked(Location location, boolean passive) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002668 if (D) Log.d(TAG, "incoming location: " + location);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002669 long now = SystemClock.elapsedRealtime();
Mike Lockwooda4903f22010-02-17 06:42:23 -05002670 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
Laurent Tu60ec50a2012-10-04 17:00:10 -07002671 // Skip if the provider is unknown.
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002672 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002673 if (p == null) return;
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002674 updateLastLocationLocked(location, provider);
2675 // mLastLocation should have been updated from the updateLastLocationLocked call above.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002676 Location lastLocation = mLastLocation.get(provider);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002677 if (lastLocation == null) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002678 Log.e(TAG, "handleLocationChangedLocked() updateLastLocation failed");
2679 return;
Mike Lockwood4e50b782009-04-03 08:24:43 -07002680 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002681
David Christie1b9b7b12013-04-15 15:31:11 -07002682 // Update last known coarse interval location if enough time has passed.
2683 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider);
2684 if (lastLocationCoarseInterval == null) {
2685 lastLocationCoarseInterval = new Location(location);
2686 mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval);
2687 }
2688 long timeDiffNanos = location.getElapsedRealtimeNanos()
2689 - lastLocationCoarseInterval.getElapsedRealtimeNanos();
2690 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
2691 lastLocationCoarseInterval.set(location);
2692 }
2693 // Don't ever return a coarse location that is more recent than the allowed update
2694 // interval (i.e. don't allow an app to keep registering and unregistering for
2695 // location updates to overcome the minimum interval).
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002696 Location noGPSLocation =
David Christie1b9b7b12013-04-15 15:31:11 -07002697 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2698
Laurent Tu60ec50a2012-10-04 17:00:10 -07002699 // Skip if there are no UpdateRecords for this provider.
2700 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
2701 if (records == null || records.size() == 0) return;
2702
Victoria Lease09016ab2012-09-16 12:33:15 -07002703 // Fetch coarse location
2704 Location coarseLocation = null;
David Christie1b9b7b12013-04-15 15:31:11 -07002705 if (noGPSLocation != null) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002706 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
2707 }
2708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002709 // Fetch latest status update time
2710 long newStatusUpdateTime = p.getStatusUpdateTime();
2711
David Christie2ff96af2014-01-30 16:09:37 -08002712 // Get latest status
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002713 Bundle extras = new Bundle();
2714 int status = p.getStatus(extras);
2715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002716 ArrayList<Receiver> deadReceivers = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002717 ArrayList<UpdateRecord> deadUpdateRecords = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07002718
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 // Broadcast location or status to all listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002720 for (UpdateRecord r : records) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002721 Receiver receiver = r.mReceiver;
Mike Lockwood03ca2162010-04-01 08:10:09 -07002722 boolean receiverDead = false;
Nick Pelly4035f5a2012-08-17 14:43:49 -07002723
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002724 int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid);
2725 if (!isCurrentProfile(receiverUserId)
2726 && !isUidALocationProvider(receiver.mIdentity.mUid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002727 if (D) {
Victoria Lease269518e2012-10-29 08:25:39 -07002728 Log.d(TAG, "skipping loc update for background user " + receiverUserId +
Victoria Leaseb711d572012-10-02 13:14:11 -07002729 " (current user: " + mCurrentUserId + ", app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002730 receiver.mIdentity.mPackageName + ")");
Victoria Leaseb711d572012-10-02 13:14:11 -07002731 }
2732 continue;
2733 }
2734
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002735 if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) {
gomo48f1a642017-11-10 20:35:46 -08002736 if (D) {
2737 Log.d(TAG, "skipping loc update for blacklisted app: " +
2738 receiver.mIdentity.mPackageName);
2739 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07002740 continue;
2741 }
2742
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002743 if (!reportLocationAccessNoThrow(
2744 receiver.mIdentity.mPid,
2745 receiver.mIdentity.mUid,
2746 receiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002747 receiver.mAllowedResolutionLevel)) {
gomo48f1a642017-11-10 20:35:46 -08002748 if (D) {
2749 Log.d(TAG, "skipping loc update for no op app: " +
2750 receiver.mIdentity.mPackageName);
2751 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002752 continue;
2753 }
2754
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002755 Location notifyLocation;
Victoria Lease37425c32012-10-16 16:08:48 -07002756 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2757 notifyLocation = coarseLocation; // use coarse location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002758 } else {
Victoria Lease37425c32012-10-16 16:08:48 -07002759 notifyLocation = lastLocation; // use fine location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002760 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002761 if (notifyLocation != null) {
2762 Location lastLoc = r.mLastFixBroadcast;
Laurent Tu75defb62012-11-01 16:21:52 -07002763 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002764 if (lastLoc == null) {
2765 lastLoc = new Location(notifyLocation);
2766 r.mLastFixBroadcast = lastLoc;
2767 } else {
2768 lastLoc.set(notifyLocation);
2769 }
2770 if (!receiver.callLocationChangedLocked(notifyLocation)) {
2771 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
2772 receiverDead = true;
2773 }
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002774 r.mRealRequest.decrementNumUpdates();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002775 }
2776 }
2777
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002778 long prevStatusUpdateTime = r.mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002779 if ((newStatusUpdateTime > prevStatusUpdateTime) &&
Victoria Lease09016ab2012-09-16 12:33:15 -07002780 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002781
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002782 r.mLastStatusBroadcast = newStatusUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002783 if (!receiver.callStatusChangedLocked(provider, status, extras)) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002784 receiverDead = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002785 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
Mike Lockwood03ca2162010-04-01 08:10:09 -07002786 }
2787 }
2788
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002789 // track expired records
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002790 if (r.mRealRequest.getNumUpdates() <= 0 || r.mRealRequest.getExpireAt() < now) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002791 if (deadUpdateRecords == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002792 deadUpdateRecords = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002793 }
2794 deadUpdateRecords.add(r);
2795 }
2796 // track dead receivers
2797 if (receiverDead) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002798 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002799 deadReceivers = new ArrayList<>();
Mike Lockwood03ca2162010-04-01 08:10:09 -07002800 }
2801 if (!deadReceivers.contains(receiver)) {
2802 deadReceivers.add(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002803 }
2804 }
2805 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002806
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002807 // remove dead records and receivers outside the loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002808 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002809 for (Receiver receiver : deadReceivers) {
2810 removeUpdatesLocked(receiver);
2811 }
2812 }
2813 if (deadUpdateRecords != null) {
2814 for (UpdateRecord r : deadUpdateRecords) {
2815 r.disposeLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002816 }
Victoria Lease8b38b292012-12-04 15:04:43 -08002817 applyRequirementsLocked(provider);
2818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002819 }
2820
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002821 /**
2822 * Updates last location with the given location
2823 *
2824 * @param location new location to update
2825 * @param provider Location provider to update for
2826 */
2827 private void updateLastLocationLocked(Location location, String provider) {
2828 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2829 Location lastNoGPSLocation;
2830 Location lastLocation = mLastLocation.get(provider);
2831 if (lastLocation == null) {
2832 lastLocation = new Location(provider);
2833 mLastLocation.put(provider, lastLocation);
2834 } else {
2835 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2836 if (noGPSLocation == null && lastNoGPSLocation != null) {
2837 // New location has no no-GPS location: adopt last no-GPS location. This is set
2838 // directly into location because we do not want to notify COARSE clients.
2839 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
2840 }
2841 }
2842 lastLocation.set(location);
2843 }
2844
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002845 private class LocationWorkerHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08002846 public LocationWorkerHandler(Looper looper) {
2847 super(looper, null, true);
2848 }
2849
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002850 @Override
2851 public void handleMessage(Message msg) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002852 switch (msg.what) {
2853 case MSG_LOCATION_CHANGED:
2854 handleLocationChanged((Location) msg.obj, msg.arg1 == 1);
2855 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002856 }
2857 }
2858 }
2859
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002860 private boolean isMockProvider(String provider) {
2861 synchronized (mLock) {
2862 return mMockProviders.containsKey(provider);
2863 }
2864 }
2865
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002866 private void handleLocationChanged(Location location, boolean passive) {
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002867 // create a working copy of the incoming Location so that the service can modify it without
2868 // disturbing the caller's copy
2869 Location myLocation = new Location(location);
2870 String provider = myLocation.getProvider();
2871
2872 // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this
2873 // bit if location did not come from a mock provider because passive/fused providers can
2874 // forward locations from mock providers, and should not grant them legitimacy in doing so.
2875 if (!myLocation.isFromMockProvider() && isMockProvider(provider)) {
2876 myLocation.setIsFromMockProvider(true);
2877 }
Jeff Sharkey5e613312012-01-30 11:16:20 -08002878
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002879 synchronized (mLock) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08002880 if (isAllowedByCurrentUserSettingsLocked(provider)) {
2881 if (!passive) {
2882 // notify passive provider of the new location
2883 mPassiveProvider.updateLocation(myLocation);
2884 }
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002885 handleLocationChangedLocked(myLocation, passive);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002886 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002887 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002888 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002889
Mike Lockwoode97ae402010-09-29 15:23:46 -04002890 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
2891 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002892 public void onPackageDisappeared(String packageName, int reason) {
2893 // remove all receivers associated with this package name
2894 synchronized (mLock) {
2895 ArrayList<Receiver> deadReceivers = null;
2896
2897 for (Receiver receiver : mReceivers.values()) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002898 if (receiver.mIdentity.mPackageName.equals(packageName)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002899 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002900 deadReceivers = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002901 }
2902 deadReceivers.add(receiver);
2903 }
2904 }
2905
2906 // perform removal outside of mReceivers loop
2907 if (deadReceivers != null) {
2908 for (Receiver receiver : deadReceivers) {
2909 removeUpdatesLocked(receiver);
2910 }
2911 }
2912 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002913 }
Mike Lockwoode97ae402010-09-29 15:23:46 -04002914 };
2915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002916 // Geocoder
2917
Nick Pellye0fd6932012-07-11 10:26:13 -07002918 @Override
Mike Lockwoode15735a2010-09-20 17:48:47 -04002919 public boolean geocoderIsPresent() {
Mark Vandevoorde01ac80b2010-05-21 15:43:26 -07002920 return mGeocodeProvider != null;
2921 }
2922
Nick Pellye0fd6932012-07-11 10:26:13 -07002923 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002924 public String getFromLocation(double latitude, double longitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002925 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002926 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002927 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
2928 params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002929 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002930 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002931 }
2932
Mike Lockwooda55c3212009-04-15 11:10:11 -04002933
Nick Pellye0fd6932012-07-11 10:26:13 -07002934 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002935 public String getFromLocationName(String locationName,
Mike Lockwooda55c3212009-04-15 11:10:11 -04002936 double lowerLeftLatitude, double lowerLeftLongitude,
2937 double upperRightLatitude, double upperRightLongitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002938 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002939
2940 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002941 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
2942 lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
2943 maxResults, params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002944 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002945 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002946 }
2947
2948 // Mock Providers
2949
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002950 private boolean canCallerAccessMockLocation(String opPackageName) {
2951 return mAppOps.noteOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(),
2952 opPackageName) == AppOpsManager.MODE_ALLOWED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002953 }
2954
Nick Pellye0fd6932012-07-11 10:26:13 -07002955 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002956 public void addTestProvider(String name, ProviderProperties properties, String opPackageName) {
2957 if (!canCallerAccessMockLocation(opPackageName)) {
2958 return;
2959 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002960
Mike Lockwooda4903f22010-02-17 06:42:23 -05002961 if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
2962 throw new IllegalArgumentException("Cannot mock the passive location provider");
2963 }
2964
Mike Lockwood86328a92009-10-23 08:38:25 -04002965 long identity = Binder.clearCallingIdentity();
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002966 synchronized (mLock) {
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002967 // remove the real provider if we are replacing GPS or network provider
2968 if (LocationManager.GPS_PROVIDER.equals(name)
Nick Pelly1332b532012-08-21 16:25:47 -07002969 || LocationManager.NETWORK_PROVIDER.equals(name)
2970 || LocationManager.FUSED_PROVIDER.equals(name)) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002971 LocationProviderInterface p = mProvidersByName.get(name);
2972 if (p != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002973 removeProviderLocked(p);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002974 }
2975 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09002976 addTestProviderLocked(name, properties);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002977 updateProvidersLocked();
2978 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002979 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002980 }
2981
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09002982 private void addTestProviderLocked(String name, ProviderProperties properties) {
2983 if (mProvidersByName.get(name) != null) {
2984 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
2985 }
2986 MockProvider provider = new MockProvider(name, this, properties);
2987 addProviderLocked(provider);
2988 mMockProviders.put(name, provider);
2989 mLastLocation.put(name, null);
2990 mLastLocationCoarseInterval.put(name, null);
2991 }
2992
Nick Pellye0fd6932012-07-11 10:26:13 -07002993 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002994 public void removeTestProvider(String provider, String opPackageName) {
2995 if (!canCallerAccessMockLocation(opPackageName)) {
2996 return;
2997 }
2998
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002999 synchronized (mLock) {
Tom O'Neill07ee5d12014-03-03 17:48:35 -08003000
3001 // These methods can't be called after removing the test provider, so first make sure
Tom O'Neillfe6d3c52014-03-04 08:26:17 -08003002 // we don't leave anything dangling.
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003003 clearTestProviderEnabled(provider, opPackageName);
3004 clearTestProviderLocation(provider, opPackageName);
3005 clearTestProviderStatus(provider, opPackageName);
Tom O'Neill07ee5d12014-03-03 17:48:35 -08003006
You Kima6d0b6f2012-10-28 03:58:44 +09003007 MockProvider mockProvider = mMockProviders.remove(provider);
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003008 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003009 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3010 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003011 long identity = Binder.clearCallingIdentity();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003012 removeProviderLocked(mProvidersByName.get(provider));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003013
3014 // reinstate real provider if available
3015 LocationProviderInterface realProvider = mRealProviders.get(provider);
3016 if (realProvider != null) {
3017 addProviderLocked(realProvider);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003018 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003019 mLastLocation.put(provider, null);
David Christie1b9b7b12013-04-15 15:31:11 -07003020 mLastLocationCoarseInterval.put(provider, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003021 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003022 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003023 }
3024 }
3025
Nick Pellye0fd6932012-07-11 10:26:13 -07003026 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003027 public void setTestProviderLocation(String provider, Location loc, String opPackageName) {
3028 if (!canCallerAccessMockLocation(opPackageName)) {
3029 return;
3030 }
3031
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003032 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003033 MockProvider mockProvider = mMockProviders.get(provider);
3034 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003035 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3036 }
Tom O'Neilla206a0f2016-12-15 10:26:28 -08003037
3038 // Ensure that the location is marked as being mock. There's some logic to do this in
3039 // handleLocationChanged(), but it fails if loc has the wrong provider (bug 33091107).
3040 Location mock = new Location(loc);
3041 mock.setIsFromMockProvider(true);
3042
3043 if (!TextUtils.isEmpty(loc.getProvider()) && !provider.equals(loc.getProvider())) {
3044 // The location has an explicit provider that is different from the mock provider
3045 // name. The caller may be trying to fool us via bug 33091107.
3046 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
3047 provider + "!=" + loc.getProvider());
3048 }
3049
Mike Lockwood95427cd2009-05-07 13:27:54 -04003050 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
3051 long identity = Binder.clearCallingIdentity();
Tom O'Neilla206a0f2016-12-15 10:26:28 -08003052 mockProvider.setLocation(mock);
Mike Lockwood95427cd2009-05-07 13:27:54 -04003053 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 }
3055 }
3056
Nick Pellye0fd6932012-07-11 10:26:13 -07003057 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003058 public void clearTestProviderLocation(String provider, String opPackageName) {
3059 if (!canCallerAccessMockLocation(opPackageName)) {
3060 return;
3061 }
3062
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003063 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003064 MockProvider mockProvider = mMockProviders.get(provider);
3065 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3067 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003068 mockProvider.clearLocation();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003069 }
3070 }
3071
Nick Pellye0fd6932012-07-11 10:26:13 -07003072 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003073 public void setTestProviderEnabled(String provider, boolean enabled, String opPackageName) {
3074 if (!canCallerAccessMockLocation(opPackageName)) {
3075 return;
3076 }
3077
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003078 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003079 MockProvider mockProvider = mMockProviders.get(provider);
3080 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003081 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3082 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003083 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003084 if (enabled) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003085 mockProvider.enable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086 mEnabledProviders.add(provider);
3087 mDisabledProviders.remove(provider);
3088 } else {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003089 mockProvider.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003090 mEnabledProviders.remove(provider);
3091 mDisabledProviders.add(provider);
3092 }
3093 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003094 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003095 }
3096 }
3097
Nick Pellye0fd6932012-07-11 10:26:13 -07003098 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003099 public void clearTestProviderEnabled(String provider, String opPackageName) {
3100 if (!canCallerAccessMockLocation(opPackageName)) {
3101 return;
3102 }
3103
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003104 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003105 MockProvider mockProvider = mMockProviders.get(provider);
3106 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003107 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3108 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003109 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003110 mEnabledProviders.remove(provider);
3111 mDisabledProviders.remove(provider);
3112 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003113 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003114 }
3115 }
3116
Nick Pellye0fd6932012-07-11 10:26:13 -07003117 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003118 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime,
3119 String opPackageName) {
3120 if (!canCallerAccessMockLocation(opPackageName)) {
3121 return;
3122 }
3123
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003124 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003125 MockProvider mockProvider = mMockProviders.get(provider);
3126 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003127 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3128 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003129 mockProvider.setStatus(status, extras, updateTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003130 }
3131 }
3132
Nick Pellye0fd6932012-07-11 10:26:13 -07003133 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003134 public void clearTestProviderStatus(String provider, String opPackageName) {
3135 if (!canCallerAccessMockLocation(opPackageName)) {
3136 return;
3137 }
3138
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003139 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003140 MockProvider mockProvider = mMockProviders.get(provider);
3141 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003142 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3143 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003144 mockProvider.clearStatus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003145 }
3146 }
3147
3148 private void log(String log) {
3149 if (Log.isLoggable(TAG, Log.VERBOSE)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003150 Slog.d(TAG, log);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003151 }
3152 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003153
3154 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003155 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003156 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Nick Pellye0fd6932012-07-11 10:26:13 -07003157
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003158 synchronized (mLock) {
Siddharth Raybb608c82017-03-16 11:33:34 -07003159 if (args.length > 0 && args[0].equals("--gnssmetrics")) {
3160 if (mGnssMetricsProvider != null) {
3161 pw.append(mGnssMetricsProvider.getGnssMetricsAsProtoString());
3162 }
3163 return;
3164 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003165 pw.println("Current Location Manager state:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003166 pw.println(" Location Listeners:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003167 for (Receiver receiver : mReceivers.values()) {
3168 pw.println(" " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003169 }
David Christie2ff96af2014-01-30 16:09:37 -08003170 pw.println(" Active Records by Provider:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003171 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
3172 pw.println(" " + entry.getKey() + ":");
3173 for (UpdateRecord record : entry.getValue()) {
3174 pw.println(" " + record);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003175 }
3176 }
Wyatt Riley11cc7492018-01-17 08:48:27 -08003177 pw.println(" Active GnssMeasurement Listeners:");
3178 for (Identity identity : mGnssMeasurementsListeners.values()) {
3179 pw.println(" " + identity.mPid + " " + identity.mUid + " "
3180 + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
3181 }
3182 pw.println(" Active GnssNavigationMessage Listeners:");
3183 for (Identity identity : mGnssNavigationMessageListeners.values()) {
3184 pw.println(" " + identity.mPid + " " + identity.mUid + " "
3185 + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
3186 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003187 pw.println(" Overlay Provider Packages:");
3188 for (LocationProviderInterface provider : mProviders) {
3189 if (provider instanceof LocationProviderProxy) {
3190 pw.println(" " + provider.getName() + ": "
3191 + ((LocationProviderProxy) provider).getConnectedPackageName());
3192 }
3193 }
David Christie2ff96af2014-01-30 16:09:37 -08003194 pw.println(" Historical Records by Provider:");
3195 for (Map.Entry<PackageProviderKey, PackageStatistics> entry
3196 : mRequestStatistics.statistics.entrySet()) {
3197 PackageProviderKey key = entry.getKey();
3198 PackageStatistics stats = entry.getValue();
3199 pw.println(" " + key.packageName + ": " + key.providerName + ": " + stats);
3200 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003201 pw.println(" Last Known Locations:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003202 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
3203 String provider = entry.getKey();
3204 Location location = entry.getValue();
3205 pw.println(" " + provider + ": " + location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003206 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003207
David Christie1b9b7b12013-04-15 15:31:11 -07003208 pw.println(" Last Known Locations Coarse Intervals:");
3209 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
3210 String provider = entry.getKey();
3211 Location location = entry.getValue();
3212 pw.println(" " + provider + ": " + location);
3213 }
3214
Nick Pellye0fd6932012-07-11 10:26:13 -07003215 mGeofenceManager.dump(pw);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003217 if (mEnabledProviders.size() > 0) {
3218 pw.println(" Enabled Providers:");
3219 for (String i : mEnabledProviders) {
3220 pw.println(" " + i);
3221 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003223 }
3224 if (mDisabledProviders.size() > 0) {
3225 pw.println(" Disabled Providers:");
3226 for (String i : mDisabledProviders) {
3227 pw.println(" " + i);
3228 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003229 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07003230 pw.append(" ");
3231 mBlacklist.dump(pw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003232 if (mMockProviders.size() > 0) {
3233 pw.println(" Mock Providers:");
3234 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003235 i.getValue().dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003236 }
3237 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003238
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08003239 if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
3240 pw.println(" Throttling Whitelisted Packages:");
3241 for (String packageName : mBackgroundThrottlePackageWhitelist) {
3242 pw.println(" " + packageName);
3243 }
3244 }
3245
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003246 pw.append(" fudger: ");
gomo48f1a642017-11-10 20:35:46 -08003247 mLocationFudger.dump(fd, pw, args);
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003248
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003249 if (args.length > 0 && "short".equals(args[0])) {
3250 return;
3251 }
gomo48f1a642017-11-10 20:35:46 -08003252 for (LocationProviderInterface provider : mProviders) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003253 pw.print(provider.getName() + " Internal State");
3254 if (provider instanceof LocationProviderProxy) {
3255 LocationProviderProxy proxy = (LocationProviderProxy) provider;
3256 pw.print(" (" + proxy.getConnectedPackageName() + ")");
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003257 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003258 pw.println(":");
3259 provider.dump(fd, pw, args);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003260 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08003261 if (mGnssBatchingInProgress) {
3262 pw.println(" GNSS batching in progress");
3263 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003264 }
3265 }
3266}