blob: 19e5cc62fb159d6ca0dffa26af44a23d09b655f8 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Maggieaa080f92018-01-04 15:35:11 -080019import static android.content.pm.PackageManager.PERMISSION_GRANTED;
20
Wyatt Rileycf879db2017-01-12 13:57:38 -080021import android.annotation.NonNull;
Wyatt Riley49097c02018-03-15 09:14:43 -070022import android.annotation.Nullable;
Maggieaa080f92018-01-04 15:35:11 -080023import android.app.ActivityManager;
24import android.app.AppOpsManager;
25import android.app.PendingIntent;
26import android.content.BroadcastReceiver;
27import android.content.ContentResolver;
28import android.content.Context;
29import android.content.Intent;
30import android.content.IntentFilter;
31import android.content.pm.ApplicationInfo;
32import android.content.pm.PackageInfo;
33import android.content.pm.PackageManager;
34import android.content.pm.PackageManager.NameNotFoundException;
35import android.content.pm.PackageManagerInternal;
36import android.content.pm.ResolveInfo;
37import android.content.pm.Signature;
38import android.content.res.Resources;
39import android.database.ContentObserver;
40import android.hardware.location.ActivityRecognitionHardware;
41import android.location.Address;
42import android.location.Criteria;
43import android.location.GeocoderParams;
44import android.location.Geofence;
45import android.location.IBatchedLocationCallback;
46import android.location.IGnssMeasurementsListener;
47import android.location.IGnssNavigationMessageListener;
48import android.location.IGnssStatusListener;
49import android.location.IGnssStatusProvider;
50import android.location.IGpsGeofenceHardware;
51import android.location.ILocationListener;
52import android.location.ILocationManager;
53import android.location.INetInitiatedListener;
54import android.location.Location;
55import android.location.LocationManager;
56import android.location.LocationProvider;
57import android.location.LocationRequest;
58import android.os.Binder;
59import android.os.Bundle;
60import android.os.Handler;
61import android.os.IBinder;
62import android.os.Looper;
63import android.os.Message;
64import android.os.PowerManager;
65import android.os.Process;
66import android.os.RemoteException;
67import android.os.SystemClock;
68import android.os.UserHandle;
69import android.os.UserManager;
70import android.os.WorkSource;
Narayan Kamath32684dd2018-01-08 17:32:51 +000071import android.os.WorkSource.WorkChain;
Maggieaa080f92018-01-04 15:35:11 -080072import android.provider.Settings;
73import android.text.TextUtils;
Soonil Nagarkar681d7112017-02-23 17:14:16 -080074import android.util.ArrayMap;
Soonil Nagarkar2b565df2017-02-14 13:33:23 -080075import android.util.ArraySet;
Maggieaa080f92018-01-04 15:35:11 -080076import android.util.EventLog;
77import android.util.Log;
78import android.util.Slog;
destradaaea8a8a62014-06-23 18:19:03 -070079import com.android.internal.content.PackageMonitor;
80import com.android.internal.location.ProviderProperties;
81import com.android.internal.location.ProviderRequest;
82import com.android.internal.os.BackgroundThread;
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -070083import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060084import com.android.internal.util.DumpUtils;
destradaaa4fa3b52014-07-09 10:46:39 -070085import com.android.server.location.ActivityRecognitionProxy;
destradaaea8a8a62014-06-23 18:19:03 -070086import com.android.server.location.FlpHardwareProvider;
87import com.android.server.location.FusedProxy;
88import com.android.server.location.GeocoderProxy;
89import com.android.server.location.GeofenceManager;
90import com.android.server.location.GeofenceProxy;
Lifu Tang818aa2c2016-02-01 01:52:00 -080091import com.android.server.location.GnssLocationProvider;
92import com.android.server.location.GnssMeasurementsProvider;
93import com.android.server.location.GnssNavigationMessageProvider;
destradaaea8a8a62014-06-23 18:19:03 -070094import com.android.server.location.LocationBlacklist;
95import com.android.server.location.LocationFudger;
96import com.android.server.location.LocationProviderInterface;
97import com.android.server.location.LocationProviderProxy;
98import com.android.server.location.LocationRequestStatistics;
99import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
100import com.android.server.location.LocationRequestStatistics.PackageStatistics;
101import com.android.server.location.MockProvider;
102import com.android.server.location.PassiveProvider;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400103import java.io.FileDescriptor;
104import java.io.PrintWriter;
105import java.util.ArrayList;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700106import java.util.Arrays;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400107import java.util.HashMap;
108import java.util.HashSet;
109import java.util.List;
110import java.util.Map;
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800111import java.util.Map.Entry;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800112import java.util.NoSuchElementException;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400113import java.util.Set;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114
115/**
116 * The service class that manages LocationProviders and issues location
117 * updates and alerts.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 */
Victoria Lease5cd731a2012-12-19 15:04:21 -0800119public class LocationManagerService extends ILocationManager.Stub {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 private static final String TAG = "LocationManagerService";
JP Abgrallf79811e72013-02-01 18:45:05 -0800121 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700122
Olivier Gaillard7a222662017-11-20 16:07:24 +0000123 private static final String WAKELOCK_KEY = "*location*";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124
Victoria Lease37425c32012-10-16 16:08:48 -0700125 // Location resolution level: no location data whatsoever
126 private static final int RESOLUTION_LEVEL_NONE = 0;
127 // Location resolution level: coarse location data only
128 private static final int RESOLUTION_LEVEL_COARSE = 1;
129 // Location resolution level: fine location data
130 private static final int RESOLUTION_LEVEL_FINE = 2;
131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 private static final String ACCESS_MOCK_LOCATION =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700133 android.Manifest.permission.ACCESS_MOCK_LOCATION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134 private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700135 android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
Mike Lockwood275555c2009-05-01 11:30:34 -0400136 private static final String INSTALL_LOCATION_PROVIDER =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700137 android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
138
139 private static final String NETWORK_LOCATION_SERVICE_ACTION =
Stan Chesnutt39062dd2013-07-22 14:33:30 -0700140 "com.android.location.service.v3.NetworkLocationProvider";
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700141 private static final String FUSED_LOCATION_SERVICE_ACTION =
142 "com.android.location.service.FusedLocationProvider";
143
144 private static final int MSG_LOCATION_CHANGED = 1;
145
David Christie1b9b7b12013-04-15 15:31:11 -0700146 private static final long NANOS_PER_MILLI = 1000000L;
147
David Christie0b837452013-07-29 16:02:13 -0700148 // The maximum interval a location request can have and still be considered "high power".
149 private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
150
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700151 private static final int FOREGROUND_IMPORTANCE_CUTOFF
gomo48f1a642017-11-10 20:35:46 -0800152 = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700153
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800154 // default background throttling interval if not overriden in settings
Soonil Nagarkarde6780a2017-02-07 10:39:41 -0800155 private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800156
Nick Pellyf1be6862012-05-15 10:53:42 -0700157 // Location Providers may sometimes deliver location updates
158 // slightly faster that requested - provide grace period so
159 // we don't unnecessarily filter events that are otherwise on
160 // time
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700161 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
Nick Pellyf1be6862012-05-15 10:53:42 -0700162
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700163 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
164
165 private final Context mContext;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800166 private final AppOpsManager mAppOps;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700167
168 // used internally for synchronization
169 private final Object mLock = new Object();
170
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700171 // --- fields below are final after systemRunning() ---
Nick Pelly74fa7ea2012-08-13 19:36:38 -0700172 private LocationFudger mLocationFudger;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700173 private GeofenceManager mGeofenceManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700174 private PackageManager mPackageManager;
Victoria Lease0aa28602013-05-29 15:28:26 -0700175 private PowerManager mPowerManager;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800176 private ActivityManager mActivityManager;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700177 private UserManager mUserManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700178 private GeocoderProxy mGeocodeProvider;
Lifu Tang30f95a72016-01-07 23:20:38 -0800179 private IGnssStatusProvider mGnssStatusProvider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700180 private INetInitiatedListener mNetInitiatedListener;
181 private LocationWorkerHandler mLocationHandler;
Nick Pelly4035f5a2012-08-17 14:43:49 -0700182 private PassiveProvider mPassiveProvider; // track passive provider for special cases
183 private LocationBlacklist mBlacklist;
Lifu Tang818aa2c2016-02-01 01:52:00 -0800184 private GnssMeasurementsProvider mGnssMeasurementsProvider;
185 private GnssNavigationMessageProvider mGnssNavigationMessageProvider;
Wei Liu5241a4c2015-05-11 14:00:36 -0700186 private IGpsGeofenceHardware mGpsGeofenceProxy;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700187
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700188 // --- fields below are protected by mLock ---
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 // Set of providers that are explicitly enabled
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700190 // Only used by passive, fused & test. Network & GPS are controlled separately, and not listed.
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800191 private final Set<String> mEnabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192
193 // Set of providers that are explicitly disabled
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800194 private final Set<String> mDisabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700196 // Mock (test) providers
197 private final HashMap<String, MockProvider> mMockProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800198 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700200 // all receivers
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800201 private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700203 // currently installed providers (with mocks replacing real providers)
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500204 private final ArrayList<LocationProviderInterface> mProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800205 new ArrayList<>();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400206
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700207 // real providers, saved here when mocked out
208 private final HashMap<String, LocationProviderInterface> mRealProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800209 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700211 // mapping from provider name to provider
212 private final HashMap<String, LocationProviderInterface> mProvidersByName =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800213 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700215 // mapping from provider name to all its UpdateRecords
216 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800217 new HashMap<>();
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700218
David Christie2ff96af2014-01-30 16:09:37 -0800219 private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics();
220
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700221 // mapping from provider name to last known location
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800222 private final HashMap<String, Location> mLastLocation = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223
David Christie1b9b7b12013-04-15 15:31:11 -0700224 // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
225 // locations stored here are not fudged for coarse permissions.
226 private final HashMap<String, Location> mLastLocationCoarseInterval =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800227 new HashMap<>();
David Christie1b9b7b12013-04-15 15:31:11 -0700228
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800229 // all providers that operate over proxy, for authorizing incoming location and whitelisting
230 // throttling
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700231 private final ArrayList<LocationProviderProxy> mProxyProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800232 new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800234 private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800235
Wyatt Riley11cc7492018-01-17 08:48:27 -0800236 private final ArrayMap<IBinder, Identity> mGnssMeasurementsListeners = new ArrayMap<>();
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800237
Wyatt Riley11cc7492018-01-17 08:48:27 -0800238 private final ArrayMap<IBinder, Identity>
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800239 mGnssNavigationMessageListeners = new ArrayMap<>();
240
Victoria Lease38389b62012-09-30 11:44:22 -0700241 // current active user on the device - other users are denied location data
Xiaohui Chena4490622015-09-22 15:29:31 -0700242 private int mCurrentUserId = UserHandle.USER_SYSTEM;
gomo48f1a642017-11-10 20:35:46 -0800243 private int[] mCurrentUserProfiles = new int[]{UserHandle.USER_SYSTEM};
Victoria Lease38389b62012-09-30 11:44:22 -0700244
Lifu Tang9363b942016-02-16 18:07:00 -0800245 private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;
Lifu Tang82f893d2016-01-21 18:15:33 -0800246
Siddharth Raybb608c82017-03-16 11:33:34 -0700247 private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;
Wyatt Rileyaa420d52017-07-03 15:14:42 -0700248
249 private GnssLocationProvider.GnssBatchingProvider mGnssBatchingProvider;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800250 private IBatchedLocationCallback mGnssBatchingCallback;
251 private LinkedCallback mGnssBatchingDeathCallback;
252 private boolean mGnssBatchingInProgress = false;
253
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700254 public LocationManagerService(Context context) {
255 super();
256 mContext = context;
gomo48f1a642017-11-10 20:35:46 -0800257 mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800258
Svet Ganovadc1cf42015-06-15 16:36:24 -0700259 // Let the package manager query which are the default location
260 // providers as they get certain permissions granted by default.
261 PackageManagerInternal packageManagerInternal = LocalServices.getService(
262 PackageManagerInternal.class);
263 packageManagerInternal.setLocationPackagesProvider(
264 new PackageManagerInternal.PackagesProvider() {
265 @Override
266 public String[] getPackages(int userId) {
267 return mContext.getResources().getStringArray(
268 com.android.internal.R.array.config_locationProviderPackageNames);
269 }
270 });
271
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700272 if (D) Log.d(TAG, "Constructed");
273
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700274 // most startup is deferred until systemRunning()
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700275 }
276
Svetoslav Ganova0027152013-06-25 14:59:53 -0700277 public void systemRunning() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700278 synchronized (mLock) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700279 if (D) Log.d(TAG, "systemRunning()");
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700280
Victoria Lease5cd731a2012-12-19 15:04:21 -0800281 // fetch package manager
282 mPackageManager = mContext.getPackageManager();
283
Victoria Lease0aa28602013-05-29 15:28:26 -0700284 // fetch power manager
285 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
Victoria Lease5cd731a2012-12-19 15:04:21 -0800286
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800287 // fetch activity manager
288 mActivityManager
289 = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
290
Victoria Lease5cd731a2012-12-19 15:04:21 -0800291 // prepare worker thread
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700292 mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper());
Victoria Lease5cd731a2012-12-19 15:04:21 -0800293
294 // prepare mLocationHandler's dependents
295 mLocationFudger = new LocationFudger(mContext, mLocationHandler);
296 mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
297 mBlacklist.init();
298 mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
299
Dianne Hackbornc2293022013-02-06 23:14:49 -0800300 // Monitor for app ops mode changes.
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700301 AppOpsManager.OnOpChangedListener callback
302 = new AppOpsManager.OnOpChangedInternalListener() {
303 public void onOpChanged(int op, String packageName) {
Dianne Hackbornc2293022013-02-06 23:14:49 -0800304 synchronized (mLock) {
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700305 for (Receiver receiver : mReceivers.values()) {
306 receiver.updateMonitoring(true);
307 }
Dianne Hackbornc2293022013-02-06 23:14:49 -0800308 applyAllProviderRequirementsLocked();
309 }
310 }
311 };
312 mAppOps.startWatchingMode(AppOpsManager.OP_COARSE_LOCATION, null, callback);
313
David Christieb870dbf2015-06-22 12:42:53 -0700314 PackageManager.OnPermissionsChangedListener permissionListener
315 = new PackageManager.OnPermissionsChangedListener() {
316 @Override
317 public void onPermissionsChanged(final int uid) {
318 synchronized (mLock) {
319 applyAllProviderRequirementsLocked();
320 }
321 }
322 };
323 mPackageManager.addOnPermissionsChangeListener(permissionListener);
324
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800325 // listen for background/foreground changes
326 ActivityManager.OnUidImportanceListener uidImportanceListener
327 = new ActivityManager.OnUidImportanceListener() {
328 @Override
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700329 public void onUidImportance(final int uid, final int importance) {
330 mLocationHandler.post(new Runnable() {
331 @Override
332 public void run() {
333 onUidImportanceChanged(uid, importance);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800334 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700335 });
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800336 }
337 };
338 mActivityManager.addOnUidImportanceListener(uidImportanceListener,
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700339 FOREGROUND_IMPORTANCE_CUTOFF);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800340
Amith Yamasanib27528d2014-06-05 15:02:10 -0700341 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
342 updateUserProfiles(mCurrentUserId);
343
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800344 updateBackgroundThrottlingWhitelistLocked();
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800345
Victoria Lease5cd731a2012-12-19 15:04:21 -0800346 // prepare providers
347 loadProvidersLocked();
348 updateProvidersLocked();
349 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700350
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700351 // listen for settings changes
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700352 mContext.getContentResolver().registerContentObserver(
Laurent Tu75defb62012-11-01 16:21:52 -0700353 Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700354 new ContentObserver(mLocationHandler) {
Victoria Lease5cd731a2012-12-19 15:04:21 -0800355 @Override
356 public void onChange(boolean selfChange) {
357 synchronized (mLock) {
358 updateProvidersLocked();
359 }
360 }
361 }, UserHandle.USER_ALL);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800362 mContext.getContentResolver().registerContentObserver(
363 Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS),
364 true,
365 new ContentObserver(mLocationHandler) {
366 @Override
367 public void onChange(boolean selfChange) {
368 synchronized (mLock) {
369 updateProvidersLocked();
370 }
371 }
372 }, UserHandle.USER_ALL);
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800373 mContext.getContentResolver().registerContentObserver(
gomo48f1a642017-11-10 20:35:46 -0800374 Settings.Global.getUriFor(
375 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
376 true,
377 new ContentObserver(mLocationHandler) {
378 @Override
379 public void onChange(boolean selfChange) {
380 synchronized (mLock) {
381 updateBackgroundThrottlingWhitelistLocked();
382 updateProvidersLocked();
383 }
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800384 }
gomo48f1a642017-11-10 20:35:46 -0800385 }, UserHandle.USER_ALL);
Victoria Lease5cd731a2012-12-19 15:04:21 -0800386 mPackageMonitor.register(mContext, mLocationHandler.getLooper(), true);
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700387
Victoria Lease38389b62012-09-30 11:44:22 -0700388 // listen for user change
389 IntentFilter intentFilter = new IntentFilter();
390 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700391 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
392 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
destradaab9026982015-08-27 17:34:54 -0700393 intentFilter.addAction(Intent.ACTION_SHUTDOWN);
Victoria Lease38389b62012-09-30 11:44:22 -0700394
395 mContext.registerReceiverAsUser(new BroadcastReceiver() {
396 @Override
397 public void onReceive(Context context, Intent intent) {
398 String action = intent.getAction();
399 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
400 switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
Amith Yamasanib27528d2014-06-05 15:02:10 -0700401 } else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)
402 || Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
403 updateUserProfiles(mCurrentUserId);
destradaab9026982015-08-27 17:34:54 -0700404 } else if (Intent.ACTION_SHUTDOWN.equals(action)) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700405 // shutdown only if UserId indicates whole system, not just one user
gomo48f1a642017-11-10 20:35:46 -0800406 if (D) Log.d(TAG, "Shutdown received with UserId: " + getSendingUserId());
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700407 if (getSendingUserId() == UserHandle.USER_ALL) {
408 shutdownComponents();
409 }
Victoria Lease38389b62012-09-30 11:44:22 -0700410 }
411 }
Victoria Lease5cd731a2012-12-19 15:04:21 -0800412 }, UserHandle.ALL, intentFilter, null, mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700413 }
414
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700415 private void onUidImportanceChanged(int uid, int importance) {
416 boolean foreground = isImportanceForeground(importance);
417 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
418 synchronized (mLock) {
419 for (Entry<String, ArrayList<UpdateRecord>> entry
gomo48f1a642017-11-10 20:35:46 -0800420 : mRecordsByProvider.entrySet()) {
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700421 String provider = entry.getKey();
422 for (UpdateRecord record : entry.getValue()) {
423 if (record.mReceiver.mIdentity.mUid == uid
gomo48f1a642017-11-10 20:35:46 -0800424 && record.mIsForegroundUid != foreground) {
425 if (D) {
426 Log.d(TAG, "request from uid " + uid + " is now "
427 + (foreground ? "foreground" : "background)"));
428 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700429 record.mIsForegroundUid = foreground;
430
431 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
432 affectedProviders.add(provider);
433 }
434 }
435 }
436 }
437 for (String provider : affectedProviders) {
438 applyRequirementsLocked(provider);
439 }
440
Wyatt Riley11cc7492018-01-17 08:48:27 -0800441 for (Entry<IBinder, Identity> entry : mGnssMeasurementsListeners.entrySet()) {
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700442 if (entry.getValue().mUid == uid) {
gomo48f1a642017-11-10 20:35:46 -0800443 if (D) {
444 Log.d(TAG, "gnss measurements listener from uid " + uid
445 + " is now " + (foreground ? "foreground" : "background)"));
446 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700447 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800448 mGnssMeasurementsProvider.addListener(
449 IGnssMeasurementsListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700450 } else {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800451 mGnssMeasurementsProvider.removeListener(
452 IGnssMeasurementsListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700453 }
454 }
455 }
456
Wyatt Riley11cc7492018-01-17 08:48:27 -0800457 for (Entry<IBinder, Identity> entry : mGnssNavigationMessageListeners.entrySet()) {
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700458 if (entry.getValue().mUid == uid) {
gomo48f1a642017-11-10 20:35:46 -0800459 if (D) {
460 Log.d(TAG, "gnss navigation message listener from uid "
461 + uid + " is now "
462 + (foreground ? "foreground" : "background)"));
463 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700464 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800465 mGnssNavigationMessageProvider.addListener(
466 IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700467 } else {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800468 mGnssNavigationMessageProvider.removeListener(
469 IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700470 }
471 }
472 }
473 }
474 }
475
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800476 private static boolean isImportanceForeground(int importance) {
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700477 return importance <= FOREGROUND_IMPORTANCE_CUTOFF;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800478 }
479
Amith Yamasanib27528d2014-06-05 15:02:10 -0700480 /**
destradaab9026982015-08-27 17:34:54 -0700481 * Provides a way for components held by the {@link LocationManagerService} to clean-up
482 * gracefully on system's shutdown.
483 *
484 * NOTES:
485 * 1) Only provides a chance to clean-up on an opt-in basis. This guarantees back-compat
486 * support for components that do not wish to handle such event.
487 */
488 private void shutdownComponents() {
gomo48f1a642017-11-10 20:35:46 -0800489 if (D) Log.d(TAG, "Shutting down components...");
destradaab9026982015-08-27 17:34:54 -0700490
491 LocationProviderInterface gpsProvider = mProvidersByName.get(LocationManager.GPS_PROVIDER);
492 if (gpsProvider != null && gpsProvider.isEnabled()) {
493 gpsProvider.disable();
494 }
495
destradaa2e385072015-10-14 16:45:58 -0700496 // it is needed to check if FLP HW provider is supported before accessing the instance, this
497 // avoids an exception to be thrown by the singleton factory method
498 if (FlpHardwareProvider.isSupported()) {
499 FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
destradaab9026982015-08-27 17:34:54 -0700500 flpHardwareProvider.cleanup();
501 }
502 }
503
504 /**
Amith Yamasanib27528d2014-06-05 15:02:10 -0700505 * Makes a list of userids that are related to the current user. This is
506 * relevant when using managed profiles. Otherwise the list only contains
507 * the current user.
508 *
509 * @param currentUserId the current user, who might have an alter-ego.
510 */
511 void updateUserProfiles(int currentUserId) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700512 int[] profileIds = mUserManager.getProfileIdsWithDisabled(currentUserId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700513 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700514 mCurrentUserProfiles = profileIds;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700515 }
516 }
517
518 /**
519 * Checks if the specified userId matches any of the current foreground
520 * users stored in mCurrentUserProfiles.
521 */
522 private boolean isCurrentProfile(int userId) {
523 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700524 return ArrayUtils.contains(mCurrentUserProfiles, userId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700525 }
526 }
527
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500528 private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) {
529 PackageManager pm = mContext.getPackageManager();
530 String systemPackageName = mContext.getPackageName();
531 ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
532
533 List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
534 new Intent(FUSED_LOCATION_SERVICE_ACTION),
535 PackageManager.GET_META_DATA, mCurrentUserId);
536 for (ResolveInfo rInfo : rInfos) {
537 String packageName = rInfo.serviceInfo.packageName;
538
539 // Check that the signature is in the list of supported sigs. If it's not in
540 // this list the standard provider binding logic won't bind to it.
541 try {
542 PackageInfo pInfo;
543 pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
544 if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
545 Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
546 ", but has wrong signature, ignoring");
547 continue;
548 }
549 } catch (NameNotFoundException e) {
550 Log.e(TAG, "missing package: " + packageName);
551 continue;
552 }
553
554 // Get the version info
555 if (rInfo.serviceInfo.metaData == null) {
556 Log.w(TAG, "Found fused provider without metadata: " + packageName);
557 continue;
558 }
559
560 int version = rInfo.serviceInfo.metaData.getInt(
561 ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
562 if (version == 0) {
563 // This should be the fallback fused location provider.
564
565 // Make sure it's in the system partition.
566 if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
567 if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
568 continue;
569 }
570
571 // Check that the fallback is signed the same as the OS
572 // as a proxy for coreApp="true"
573 if (pm.checkSignatures(systemPackageName, packageName)
574 != PackageManager.SIGNATURE_MATCH) {
gomo48f1a642017-11-10 20:35:46 -0800575 if (D) {
576 Log.d(TAG, "Fallback candidate not signed the same as system: "
577 + packageName);
578 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500579 continue;
580 }
581
582 // Found a valid fallback.
583 if (D) Log.d(TAG, "Found fallback provider: " + packageName);
584 return;
585 } else {
586 if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
587 }
588 }
589
590 throw new IllegalStateException("Unable to find a fused location provider that is in the "
591 + "system partition with version 0 and signed with the platform certificate. "
592 + "Such a package is needed to provide a default fused location provider in the "
593 + "event that no other fused location provider has been installed or is currently "
594 + "available. For example, coreOnly boot mode when decrypting the data "
595 + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
596 }
597
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700598 private void loadProvidersLocked() {
Victoria Lease5c24fd02012-10-01 11:00:50 -0700599 // create a passive location provider, which is always enabled
600 PassiveProvider passiveProvider = new PassiveProvider(this);
601 addProviderLocked(passiveProvider);
602 mEnabledProviders.add(passiveProvider.getName());
603 mPassiveProvider = passiveProvider;
604
Lifu Tang30f95a72016-01-07 23:20:38 -0800605 if (GnssLocationProvider.isSupported()) {
Wei Liu5241a4c2015-05-11 14:00:36 -0700606 // Create a gps location provider
Lifu Tang30f95a72016-01-07 23:20:38 -0800607 GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this,
Wei Liu5241a4c2015-05-11 14:00:36 -0700608 mLocationHandler.getLooper());
Lifu Tang9363b942016-02-16 18:07:00 -0800609 mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
Wyatt Rileycf879db2017-01-12 13:57:38 -0800610 mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider();
Siddharth Raybb608c82017-03-16 11:33:34 -0700611 mGnssMetricsProvider = gnssProvider.getGnssMetricsProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800612 mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
613 mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
614 addProviderLocked(gnssProvider);
615 mRealProviders.put(LocationManager.GPS_PROVIDER, gnssProvider);
Lifu Tang818aa2c2016-02-01 01:52:00 -0800616 mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
617 mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800618 mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700619 }
620
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700621 /*
622 Load package name(s) containing location provider support.
623 These packages can contain services implementing location providers:
624 Geocoder Provider, Network Location Provider, and
625 Fused Location Provider. They will each be searched for
626 service components implementing these providers.
627 The location framework also has support for installation
628 of new location providers at run-time. The new package does not
629 have to be explicitly listed here, however it must have a signature
630 that matches the signature of at least one package on this list.
631 */
632 Resources resources = mContext.getResources();
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800633 ArrayList<String> providerPackageNames = new ArrayList<>();
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500634 String[] pkgs = resources.getStringArray(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700635 com.android.internal.R.array.config_locationProviderPackageNames);
gomo48f1a642017-11-10 20:35:46 -0800636 if (D) {
637 Log.d(TAG, "certificates for location providers pulled from: " +
638 Arrays.toString(pkgs));
639 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500640 if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));
641
642 ensureFallbackFusedProviderPresentLocked(providerPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700643
644 // bind to network provider
645 LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
646 mContext,
647 LocationManager.NETWORK_PROVIDER,
648 NETWORK_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700649 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
650 com.android.internal.R.string.config_networkLocationProviderPackageName,
651 com.android.internal.R.array.config_locationProviderPackageNames,
652 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700653 if (networkProvider != null) {
654 mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
655 mProxyProviders.add(networkProvider);
656 addProviderLocked(networkProvider);
657 } else {
gomo48f1a642017-11-10 20:35:46 -0800658 Slog.w(TAG, "no network location provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700659 }
660
661 // bind to fused provider
662 LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind(
663 mContext,
664 LocationManager.FUSED_PROVIDER,
665 FUSED_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700666 com.android.internal.R.bool.config_enableFusedLocationOverlay,
667 com.android.internal.R.string.config_fusedLocationProviderPackageName,
668 com.android.internal.R.array.config_locationProviderPackageNames,
669 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700670 if (fusedLocationProvider != null) {
671 addProviderLocked(fusedLocationProvider);
672 mProxyProviders.add(fusedLocationProvider);
673 mEnabledProviders.add(fusedLocationProvider.getName());
Kenny Rootc3575182012-10-09 12:44:40 -0700674 mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700675 } else {
676 Slog.e(TAG, "no fused location provider found",
677 new IllegalStateException("Location service needs a fused location provider"));
678 }
679
680 // bind to geocoder provider
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700681 mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
682 com.android.internal.R.bool.config_enableGeocoderOverlay,
683 com.android.internal.R.string.config_geocoderProviderPackageName,
684 com.android.internal.R.array.config_locationProviderPackageNames,
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800685 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700686 if (mGeocodeProvider == null) {
gomo48f1a642017-11-10 20:35:46 -0800687 Slog.e(TAG, "no geocoder provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700688 }
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700689
destradaaa4fa3b52014-07-09 10:46:39 -0700690 // bind to fused hardware provider if supported
destradaabeea4422014-07-30 18:17:21 -0700691 // in devices without support, requesting an instance of FlpHardwareProvider will raise an
692 // exception, so make sure we only do that when supported
693 FlpHardwareProvider flpHardwareProvider;
destradaa5ce66d82014-05-28 18:24:08 -0700694 if (FlpHardwareProvider.isSupported()) {
destradaabeea4422014-07-30 18:17:21 -0700695 flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
destradaaf9a274c2014-07-25 15:11:56 -0700696 FusedProxy fusedProxy = FusedProxy.createAndBind(
697 mContext,
698 mLocationHandler,
699 flpHardwareProvider.getLocationHardware(),
700 com.android.internal.R.bool.config_enableHardwareFlpOverlay,
701 com.android.internal.R.string.config_hardwareFlpPackageName,
702 com.android.internal.R.array.config_locationProviderPackageNames);
703 if (fusedProxy == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700704 Slog.d(TAG, "Unable to bind FusedProxy.");
destradaaf9a274c2014-07-25 15:11:56 -0700705 }
destradaacfbdcd22014-04-30 11:29:11 -0700706 } else {
destradaabeea4422014-07-30 18:17:21 -0700707 flpHardwareProvider = null;
destradaa6b4893a2016-05-03 15:33:43 -0700708 Slog.d(TAG, "FLP HAL not supported");
destradaaf9a274c2014-07-25 15:11:56 -0700709 }
710
711 // bind to geofence provider
712 GeofenceProxy provider = GeofenceProxy.createAndBind(
gomo48f1a642017-11-10 20:35:46 -0800713 mContext, com.android.internal.R.bool.config_enableGeofenceOverlay,
destradaaf9a274c2014-07-25 15:11:56 -0700714 com.android.internal.R.string.config_geofenceProviderPackageName,
715 com.android.internal.R.array.config_locationProviderPackageNames,
716 mLocationHandler,
Wei Liu5241a4c2015-05-11 14:00:36 -0700717 mGpsGeofenceProxy,
destradaabeea4422014-07-30 18:17:21 -0700718 flpHardwareProvider != null ? flpHardwareProvider.getGeofenceHardware() : null);
destradaaf9a274c2014-07-25 15:11:56 -0700719 if (provider == null) {
gomo48f1a642017-11-10 20:35:46 -0800720 Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
destradaa0682809a2013-08-12 18:50:30 -0700721 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900722
destradaa6e2fe752015-06-23 17:25:53 -0700723 // bind to hardware activity recognition
724 boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
725 ActivityRecognitionHardware activityRecognitionHardware = null;
726 if (activityRecognitionHardwareIsSupported) {
727 activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
destradaaa4fa3b52014-07-09 10:46:39 -0700728 } else {
destradaa6b4893a2016-05-03 15:33:43 -0700729 Slog.d(TAG, "Hardware Activity-Recognition not supported.");
destradaaa4fa3b52014-07-09 10:46:39 -0700730 }
destradaa6e2fe752015-06-23 17:25:53 -0700731 ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
732 mContext,
733 mLocationHandler,
734 activityRecognitionHardwareIsSupported,
735 activityRecognitionHardware,
736 com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
737 com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
738 com.android.internal.R.array.config_locationProviderPackageNames);
739 if (proxy == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700740 Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
destradaa6e2fe752015-06-23 17:25:53 -0700741 }
destradaaa4fa3b52014-07-09 10:46:39 -0700742
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900743 String[] testProviderStrings = resources.getStringArray(
744 com.android.internal.R.array.config_testLocationProviders);
745 for (String testProviderString : testProviderStrings) {
746 String fragments[] = testProviderString.split(",");
747 String name = fragments[0].trim();
748 if (mProvidersByName.get(name) != null) {
749 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
750 }
751 ProviderProperties properties = new ProviderProperties(
752 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
753 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
754 Boolean.parseBoolean(fragments[3]) /* requiresCell */,
755 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
756 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
757 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
758 Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
759 Integer.parseInt(fragments[8]) /* powerRequirement */,
760 Integer.parseInt(fragments[9]) /* accuracy */);
761 addTestProviderLocked(name, properties);
762 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700763 }
Mike Lockwood9637d472009-04-02 21:41:57 -0700764
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765 /**
Victoria Lease38389b62012-09-30 11:44:22 -0700766 * Called when the device's active user changes.
gomo48f1a642017-11-10 20:35:46 -0800767 *
Victoria Lease38389b62012-09-30 11:44:22 -0700768 * @param userId the new active user's UserId
769 */
770 private void switchUser(int userId) {
Jianzheng Zhoud5c69462013-10-10 14:02:09 +0800771 if (mCurrentUserId == userId) {
772 return;
773 }
Victoria Lease83762d22012-10-03 13:51:17 -0700774 mBlacklist.switchUser(userId);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800775 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED);
Victoria Lease38389b62012-09-30 11:44:22 -0700776 synchronized (mLock) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700777 mLastLocation.clear();
David Christie1b9b7b12013-04-15 15:31:11 -0700778 mLastLocationCoarseInterval.clear();
Victoria Leaseb711d572012-10-02 13:14:11 -0700779 for (LocationProviderInterface p : mProviders) {
Amith Yamasanib27528d2014-06-05 15:02:10 -0700780 updateProviderListenersLocked(p.getName(), false);
Victoria Leaseb711d572012-10-02 13:14:11 -0700781 }
Victoria Lease38389b62012-09-30 11:44:22 -0700782 mCurrentUserId = userId;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700783 updateUserProfiles(userId);
Victoria Leaseb711d572012-10-02 13:14:11 -0700784 updateProvidersLocked();
Victoria Lease38389b62012-09-30 11:44:22 -0700785 }
786 }
787
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800788 private static final class Identity {
789 final int mUid;
790 final int mPid;
791 final String mPackageName;
792
793 Identity(int uid, int pid, String packageName) {
794 mUid = uid;
795 mPid = pid;
796 mPackageName = packageName;
797 }
798 }
799
Victoria Lease38389b62012-09-30 11:44:22 -0700800 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801 * A wrapper class holding either an ILocationListener or a PendingIntent to receive
802 * location updates.
803 */
Mike Lockwood48f17512009-04-23 09:12:08 -0700804 private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800805 final Identity mIdentity;
Victoria Lease37425c32012-10-16 16:08:48 -0700806 final int mAllowedResolutionLevel; // resolution level allowed to receiver
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700807
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800808 final ILocationListener mListener;
809 final PendingIntent mPendingIntent;
David Christie82edc9b2013-07-19 11:31:42 -0700810 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
David Christie40e57822013-07-30 11:36:48 -0700811 final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812 final Object mKey;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700813
gomo48f1a642017-11-10 20:35:46 -0800814 final HashMap<String, UpdateRecord> mUpdateRecords = new HashMap<>();
Nick Pellyf1be6862012-05-15 10:53:42 -0700815
David Christie0b837452013-07-29 16:02:13 -0700816 // True if app ops has started monitoring this receiver for locations.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700817 boolean mOpMonitoring;
David Christie0b837452013-07-29 16:02:13 -0700818 // True if app ops has started monitoring this receiver for high power (gps) locations.
819 boolean mOpHighPowerMonitoring;
Mike Lockwood48f17512009-04-23 09:12:08 -0700820 int mPendingBroadcasts;
Victoria Lease0aa28602013-05-29 15:28:26 -0700821 PowerManager.WakeLock mWakeLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700823 Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -0700824 String packageName, WorkSource workSource, boolean hideFromAppOps) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825 mListener = listener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 mPendingIntent = intent;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700827 if (listener != null) {
828 mKey = listener.asBinder();
829 } else {
830 mKey = intent;
831 }
Victoria Lease37425c32012-10-16 16:08:48 -0700832 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800833 mIdentity = new Identity(uid, pid, packageName);
Narayan Kamath32684dd2018-01-08 17:32:51 +0000834 if (workSource != null && workSource.isEmpty()) {
David Christie82edc9b2013-07-19 11:31:42 -0700835 workSource = null;
836 }
837 mWorkSource = workSource;
David Christie40e57822013-07-30 11:36:48 -0700838 mHideFromAppOps = hideFromAppOps;
Victoria Lease0aa28602013-05-29 15:28:26 -0700839
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700840 updateMonitoring(true);
841
Victoria Lease0aa28602013-05-29 15:28:26 -0700842 // construct/configure wakelock
843 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
David Christie82edc9b2013-07-19 11:31:42 -0700844 if (workSource == null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800845 workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -0700846 }
847 mWakeLock.setWorkSource(workSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848 }
849
850 @Override
851 public boolean equals(Object otherObj) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800852 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 }
854
855 @Override
856 public int hashCode() {
857 return mKey.hashCode();
858 }
Mike Lockwood3681f262009-05-12 10:52:03 -0400859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 @Override
861 public String toString() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700862 StringBuilder s = new StringBuilder();
863 s.append("Reciever[");
864 s.append(Integer.toHexString(System.identityHashCode(this)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 if (mListener != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700866 s.append(" listener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700868 s.append(" intent");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700870 for (String p : mUpdateRecords.keySet()) {
871 s.append(" ").append(mUpdateRecords.get(p).toString());
872 }
873 s.append("]");
874 return s.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800875 }
876
David Christie15b31912013-08-13 15:54:32 -0700877 /**
878 * Update AppOp monitoring for this receiver.
879 *
880 * @param allow If true receiver is currently active, if false it's been removed.
881 */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700882 public void updateMonitoring(boolean allow) {
David Christie40e57822013-07-30 11:36:48 -0700883 if (mHideFromAppOps) {
884 return;
885 }
886
David Christie15b31912013-08-13 15:54:32 -0700887 boolean requestingLocation = false;
888 boolean requestingHighPowerLocation = false;
889 if (allow) {
890 // See if receiver has any enabled update records. Also note if any update records
891 // are high power (has a high power provider with an interval under a threshold).
892 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
893 if (isAllowedByCurrentUserSettingsLocked(updateRecord.mProvider)) {
894 requestingLocation = true;
895 LocationProviderInterface locationProvider
David Christie2ff96af2014-01-30 16:09:37 -0800896 = mProvidersByName.get(updateRecord.mProvider);
David Christie15b31912013-08-13 15:54:32 -0700897 ProviderProperties properties = locationProvider != null
898 ? locationProvider.getProperties() : null;
899 if (properties != null
900 && properties.mPowerRequirement == Criteria.POWER_HIGH
901 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
902 requestingHighPowerLocation = true;
903 break;
904 }
905 }
906 }
907 }
908
David Christie0b837452013-07-29 16:02:13 -0700909 // First update monitoring of any location request (including high power).
David Christie15b31912013-08-13 15:54:32 -0700910 mOpMonitoring = updateMonitoring(
911 requestingLocation,
912 mOpMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700913 AppOpsManager.OP_MONITOR_LOCATION);
914
915 // Now update monitoring of high power requests only.
David Christiec750c1f2013-08-08 12:56:57 -0700916 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
David Christie15b31912013-08-13 15:54:32 -0700917 mOpHighPowerMonitoring = updateMonitoring(
918 requestingHighPowerLocation,
919 mOpHighPowerMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700920 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
David Christiec750c1f2013-08-08 12:56:57 -0700921 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
David Christie15b31912013-08-13 15:54:32 -0700922 // Send an intent to notify that a high power request has been added/removed.
David Christiec750c1f2013-08-08 12:56:57 -0700923 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
924 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
925 }
David Christie0b837452013-07-29 16:02:13 -0700926 }
927
928 /**
929 * Update AppOps monitoring for a single location request and op type.
930 *
gomo48f1a642017-11-10 20:35:46 -0800931 * @param allowMonitoring True if monitoring is allowed for this request/op.
David Christie0b837452013-07-29 16:02:13 -0700932 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
gomo48f1a642017-11-10 20:35:46 -0800933 * @param op AppOps code for the op to update.
David Christie0b837452013-07-29 16:02:13 -0700934 * @return True if monitoring is on for this request/op after updating.
935 */
936 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
937 int op) {
938 if (!currentlyMonitoring) {
939 if (allowMonitoring) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800940 return mAppOps.startOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700941 == AppOpsManager.MODE_ALLOWED;
942 }
943 } else {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800944 if (!allowMonitoring
945 || mAppOps.checkOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700946 != AppOpsManager.MODE_ALLOWED) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800947 mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName);
David Christie0b837452013-07-29 16:02:13 -0700948 return false;
949 }
950 }
951
952 return currentlyMonitoring;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700953 }
954
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800955 public boolean isListener() {
956 return mListener != null;
957 }
958
959 public boolean isPendingIntent() {
960 return mPendingIntent != null;
961 }
962
963 public ILocationListener getListener() {
964 if (mListener != null) {
965 return mListener;
966 }
967 throw new IllegalStateException("Request for non-existent listener");
968 }
969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970 public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
971 if (mListener != null) {
972 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700973 synchronized (this) {
974 // synchronize to ensure incrementPendingBroadcastsLocked()
975 // is called before decrementPendingBroadcasts()
976 mListener.onStatusChanged(provider, status, extras);
Nick Pellye0fd6932012-07-11 10:26:13 -0700977 // call this after broadcasting so we do not increment
978 // if we throw an exeption.
979 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -0700980 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800981 } catch (RemoteException e) {
982 return false;
983 }
984 } else {
985 Intent statusChanged = new Intent();
Victoria Lease61ecb022012-11-13 15:12:51 -0800986 statusChanged.putExtras(new Bundle(extras));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
988 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700989 synchronized (this) {
990 // synchronize to ensure incrementPendingBroadcastsLocked()
991 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700992 mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -0700993 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -0700994 // call this after broadcasting so we do not increment
995 // if we throw an exeption.
996 incrementPendingBroadcastsLocked();
997 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800998 } catch (PendingIntent.CanceledException e) {
999 return false;
1000 }
1001 }
1002 return true;
1003 }
1004
1005 public boolean callLocationChangedLocked(Location location) {
1006 if (mListener != null) {
1007 try {
Mike Lockwood48f17512009-04-23 09:12:08 -07001008 synchronized (this) {
1009 // synchronize to ensure incrementPendingBroadcastsLocked()
1010 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08001011 mListener.onLocationChanged(new Location(location));
Nick Pellye0fd6932012-07-11 10:26:13 -07001012 // call this after broadcasting so we do not increment
1013 // if we throw an exeption.
1014 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001015 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 } catch (RemoteException e) {
1017 return false;
1018 }
1019 } else {
1020 Intent locationChanged = new Intent();
gomo48f1a642017-11-10 20:35:46 -08001021 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED,
1022 new Location(location));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023 try {
Mike Lockwood48f17512009-04-23 09:12:08 -07001024 synchronized (this) {
1025 // synchronize to ensure incrementPendingBroadcastsLocked()
1026 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001027 mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -07001028 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -07001029 // call this after broadcasting so we do not increment
1030 // if we throw an exeption.
1031 incrementPendingBroadcastsLocked();
1032 }
1033 } catch (PendingIntent.CanceledException e) {
1034 return false;
1035 }
1036 }
1037 return true;
1038 }
1039
1040 public boolean callProviderEnabledLocked(String provider, boolean enabled) {
David Christie15b31912013-08-13 15:54:32 -07001041 // First update AppOp monitoring.
1042 // An app may get/lose location access as providers are enabled/disabled.
1043 updateMonitoring(true);
1044
Mike Lockwood48f17512009-04-23 09:12:08 -07001045 if (mListener != null) {
1046 try {
1047 synchronized (this) {
1048 // synchronize to ensure incrementPendingBroadcastsLocked()
1049 // is called before decrementPendingBroadcasts()
1050 if (enabled) {
1051 mListener.onProviderEnabled(provider);
1052 } else {
1053 mListener.onProviderDisabled(provider);
1054 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001055 // call this after broadcasting so we do not increment
1056 // if we throw an exeption.
1057 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001058 }
1059 } catch (RemoteException e) {
1060 return false;
1061 }
1062 } else {
1063 Intent providerIntent = new Intent();
1064 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1065 try {
1066 synchronized (this) {
1067 // synchronize to ensure incrementPendingBroadcastsLocked()
1068 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001069 mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -07001070 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -07001071 // call this after broadcasting so we do not increment
1072 // if we throw an exeption.
1073 incrementPendingBroadcastsLocked();
1074 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001075 } catch (PendingIntent.CanceledException e) {
1076 return false;
1077 }
1078 }
1079 return true;
1080 }
1081
Nick Pellyf1be6862012-05-15 10:53:42 -07001082 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001083 public void binderDied() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001084 if (D) Log.d(TAG, "Location listener died");
1085
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001086 synchronized (mLock) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 removeUpdatesLocked(this);
1088 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001089 synchronized (this) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001090 clearPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001091 }
1092 }
1093
Nick Pellye0fd6932012-07-11 10:26:13 -07001094 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001095 public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1096 int resultCode, String resultData, Bundle resultExtras) {
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001097 synchronized (this) {
1098 decrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001099 }
1100 }
1101
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001102 // this must be called while synchronized by caller in a synchronized block
1103 // containing the sending of the broadcaset
1104 private void incrementPendingBroadcastsLocked() {
1105 if (mPendingBroadcasts++ == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001106 mWakeLock.acquire();
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001107 }
1108 }
1109
1110 private void decrementPendingBroadcastsLocked() {
1111 if (--mPendingBroadcasts == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001112 if (mWakeLock.isHeld()) {
1113 mWakeLock.release();
1114 }
1115 }
1116 }
1117
1118 public void clearPendingBroadcastsLocked() {
1119 if (mPendingBroadcasts > 0) {
1120 mPendingBroadcasts = 0;
1121 if (mWakeLock.isHeld()) {
1122 mWakeLock.release();
1123 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001124 }
1125 }
1126 }
1127
Nick Pellye0fd6932012-07-11 10:26:13 -07001128 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001129 public void locationCallbackFinished(ILocationListener listener) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001130 //Do not use getReceiverLocked here as that will add the ILocationListener to
Joshua Bartel080b61b2009-10-05 12:44:46 -04001131 //the receiver list if it is not found. If it is not found then the
1132 //LocationListener was removed when it had a pending broadcast and should
1133 //not be added back.
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001134 synchronized (mLock) {
1135 IBinder binder = listener.asBinder();
1136 Receiver receiver = mReceivers.get(binder);
1137 if (receiver != null) {
1138 synchronized (receiver) {
1139 // so wakelock calls will succeed
1140 long identity = Binder.clearCallingIdentity();
1141 receiver.decrementPendingBroadcastsLocked();
1142 Binder.restoreCallingIdentity(identity);
David Christie2ff96af2014-01-30 16:09:37 -08001143 }
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001144 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001145 }
1146 }
1147
Lifu Tang82f893d2016-01-21 18:15:33 -08001148 /**
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001149 * Returns the year of the GNSS hardware.
Lifu Tang82f893d2016-01-21 18:15:33 -08001150 */
1151 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001152 public int getGnssYearOfHardware() {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001153 if (mGnssSystemInfoProvider != null) {
Lifu Tang9363b942016-02-16 18:07:00 -08001154 return mGnssSystemInfoProvider.getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001155 } else {
1156 return 0;
1157 }
1158 }
1159
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001160
1161 /**
1162 * Returns the model name of the GNSS hardware.
1163 */
1164 @Override
Wyatt Riley49097c02018-03-15 09:14:43 -07001165 @Nullable
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001166 public String getGnssHardwareModelName() {
1167 if (mGnssSystemInfoProvider != null) {
1168 return mGnssSystemInfoProvider.getGnssHardwareModelName();
1169 } else {
Wyatt Riley49097c02018-03-15 09:14:43 -07001170 return null;
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001171 }
1172 }
1173
Wyatt Rileycf879db2017-01-12 13:57:38 -08001174 /**
1175 * Runs some checks for GNSS (FINE) level permissions, used by several methods which directly
1176 * (try to) access GNSS information at this layer.
1177 */
1178 private boolean hasGnssPermissions(String packageName) {
1179 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
1180 checkResolutionLevelIsSufficientForProviderUse(
1181 allowedResolutionLevel,
1182 LocationManager.GPS_PROVIDER);
1183
1184 int pid = Binder.getCallingPid();
1185 int uid = Binder.getCallingUid();
1186 long identity = Binder.clearCallingIdentity();
1187 boolean hasLocationAccess;
1188 try {
1189 hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
1190 } finally {
1191 Binder.restoreCallingIdentity(identity);
1192 }
1193
1194 return hasLocationAccess;
1195 }
1196
1197 /**
1198 * Returns the GNSS batching size, if available.
1199 */
1200 @Override
1201 public int getGnssBatchSize(String packageName) {
1202 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1203 "Location Hardware permission not granted to access hardware batching");
1204
1205 if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
1206 return mGnssBatchingProvider.getSize();
1207 } else {
1208 return 0;
1209 }
1210 }
1211
1212 /**
1213 * Adds a callback for GNSS Batching events, if permissions allow, which are transported
1214 * to potentially multiple listeners by the BatchedLocationCallbackTransport above this.
1215 */
1216 @Override
1217 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) {
1218 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1219 "Location Hardware permission not granted to access hardware batching");
1220
1221 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1222 return false;
1223 }
1224
1225 mGnssBatchingCallback = callback;
1226 mGnssBatchingDeathCallback = new LinkedCallback(callback);
1227 try {
1228 callback.asBinder().linkToDeath(mGnssBatchingDeathCallback, 0 /* flags */);
1229 } catch (RemoteException e) {
1230 // if the remote process registering the listener is already dead, just swallow the
1231 // exception and return
1232 Log.e(TAG, "Remote listener already died.", e);
1233 return false;
1234 }
1235
1236 return true;
1237 }
1238
1239 private class LinkedCallback implements IBinder.DeathRecipient {
1240 private final IBatchedLocationCallback mCallback;
1241
1242 public LinkedCallback(@NonNull IBatchedLocationCallback callback) {
1243 mCallback = callback;
1244 }
1245
1246 @NonNull
1247 public IBatchedLocationCallback getUnderlyingListener() {
1248 return mCallback;
1249 }
1250
1251 @Override
1252 public void binderDied() {
1253 Log.d(TAG, "Remote Batching Callback died: " + mCallback);
1254 stopGnssBatch();
1255 removeGnssBatchingCallback();
1256 }
1257 }
1258
1259 /**
1260 * Removes callback for GNSS batching
1261 */
1262 @Override
1263 public void removeGnssBatchingCallback() {
1264 try {
1265 mGnssBatchingCallback.asBinder().unlinkToDeath(mGnssBatchingDeathCallback,
1266 0 /* flags */);
1267 } catch (NoSuchElementException e) {
1268 // if the death callback isn't connected (it should be...), log error, swallow the
1269 // exception and return
1270 Log.e(TAG, "Couldn't unlink death callback.", e);
1271 }
1272 mGnssBatchingCallback = null;
1273 mGnssBatchingDeathCallback = null;
1274 }
1275
1276
1277 /**
1278 * Starts GNSS batching, if available.
1279 */
1280 @Override
1281 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
1282 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1283 "Location Hardware permission not granted to access hardware batching");
1284
1285 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1286 return false;
1287 }
1288
1289 if (mGnssBatchingInProgress) {
1290 // Current design does not expect multiple starts to be called repeatedly
1291 Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch");
1292 // Try to clean up anyway, and continue
1293 stopGnssBatch();
1294 }
1295
1296 mGnssBatchingInProgress = true;
1297 return mGnssBatchingProvider.start(periodNanos, wakeOnFifoFull);
1298 }
1299
1300 /**
1301 * Flushes a GNSS batch in progress
1302 */
1303 @Override
1304 public void flushGnssBatch(String packageName) {
1305 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1306 "Location Hardware permission not granted to access hardware batching");
1307
1308 if (!hasGnssPermissions(packageName)) {
1309 Log.e(TAG, "flushGnssBatch called without GNSS permissions");
1310 return;
1311 }
1312
1313 if (!mGnssBatchingInProgress) {
1314 Log.w(TAG, "flushGnssBatch called with no batch in progress");
1315 }
1316
1317 if (mGnssBatchingProvider != null) {
gomo48f1a642017-11-10 20:35:46 -08001318 mGnssBatchingProvider.flush();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001319 }
1320 }
1321
1322 /**
1323 * Stops GNSS batching
1324 */
1325 @Override
1326 public boolean stopGnssBatch() {
1327 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1328 "Location Hardware permission not granted to access hardware batching");
1329
1330 if (mGnssBatchingProvider != null) {
1331 mGnssBatchingInProgress = false;
1332 return mGnssBatchingProvider.stop();
gomo48f1a642017-11-10 20:35:46 -08001333 } else {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001334 return false;
1335 }
1336 }
1337
1338 @Override
1339 public void reportLocationBatch(List<Location> locations) {
1340 checkCallerIsProvider();
1341
1342 // Currently used only for GNSS locations - update permissions check if changed
1343 if (isAllowedByCurrentUserSettingsLocked(LocationManager.GPS_PROVIDER)) {
1344 if (mGnssBatchingCallback == null) {
1345 Slog.e(TAG, "reportLocationBatch() called without active Callback");
1346 return;
1347 }
1348 try {
1349 mGnssBatchingCallback.onLocationBatch(locations);
1350 } catch (RemoteException e) {
1351 Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e);
1352 }
1353 } else {
1354 Slog.w(TAG, "reportLocationBatch() called without user permission, locations blocked");
1355 }
1356 }
1357
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001358 private void addProviderLocked(LocationProviderInterface provider) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001359 mProviders.add(provider);
1360 mProvidersByName.put(provider.getName(), provider);
1361 }
1362
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001363 private void removeProviderLocked(LocationProviderInterface provider) {
1364 provider.disable();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001365 mProviders.remove(provider);
1366 mProvidersByName.remove(provider.getName());
1367 }
1368
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001369 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001370 * Returns "true" if access to the specified location provider is allowed by the current
1371 * user's settings. Access to all location providers is forbidden to non-location-provider
1372 * processes belonging to background users.
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001373 *
1374 * @param provider the name of the location provider
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001375 */
Victoria Lease09eeaec2013-02-05 11:34:13 -08001376 private boolean isAllowedByCurrentUserSettingsLocked(String provider) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001377 if (mEnabledProviders.contains(provider)) {
1378 return true;
1379 }
1380 if (mDisabledProviders.contains(provider)) {
1381 return false;
1382 }
Maggieaa080f92018-01-04 15:35:11 -08001383 return isLocationProviderEnabledForUser(provider, mCurrentUserId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001384 }
1385
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001386 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001387 * Returns "true" if access to the specified location provider is allowed by the specified
1388 * user's settings. Access to all location providers is forbidden to non-location-provider
1389 * processes belonging to background users.
1390 *
1391 * @param provider the name of the location provider
gomo48f1a642017-11-10 20:35:46 -08001392 * @param uid the requestor's UID
Victoria Lease09eeaec2013-02-05 11:34:13 -08001393 */
1394 private boolean isAllowedByUserSettingsLocked(String provider, int uid) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001395 if (!isCurrentProfile(UserHandle.getUserId(uid)) && !isUidALocationProvider(uid)) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08001396 return false;
1397 }
1398 return isAllowedByCurrentUserSettingsLocked(provider);
1399 }
1400
1401 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001402 * Returns the permission string associated with the specified resolution level.
1403 *
1404 * @param resolutionLevel the resolution level
1405 * @return the permission string
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001406 */
Victoria Lease37425c32012-10-16 16:08:48 -07001407 private String getResolutionPermission(int resolutionLevel) {
1408 switch (resolutionLevel) {
1409 case RESOLUTION_LEVEL_FINE:
1410 return android.Manifest.permission.ACCESS_FINE_LOCATION;
1411 case RESOLUTION_LEVEL_COARSE:
1412 return android.Manifest.permission.ACCESS_COARSE_LOCATION;
1413 default:
1414 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001415 }
Victoria Leaseda479c52012-10-15 15:24:16 -07001416 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001417
Victoria Leaseda479c52012-10-15 15:24:16 -07001418 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001419 * Returns the resolution level allowed to the given PID/UID pair.
1420 *
1421 * @param pid the PID
1422 * @param uid the UID
1423 * @return resolution level allowed to the pid/uid pair
Victoria Leaseda479c52012-10-15 15:24:16 -07001424 */
Victoria Lease37425c32012-10-16 16:08:48 -07001425 private int getAllowedResolutionLevel(int pid, int uid) {
1426 if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001427 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001428 return RESOLUTION_LEVEL_FINE;
1429 } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001430 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001431 return RESOLUTION_LEVEL_COARSE;
1432 } else {
1433 return RESOLUTION_LEVEL_NONE;
Victoria Leaseda479c52012-10-15 15:24:16 -07001434 }
Victoria Lease4fab68b2012-09-13 13:20:59 -07001435 }
1436
1437 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001438 * Returns the resolution level allowed to the caller
1439 *
1440 * @return resolution level allowed to caller
Victoria Lease4fab68b2012-09-13 13:20:59 -07001441 */
Victoria Lease37425c32012-10-16 16:08:48 -07001442 private int getCallerAllowedResolutionLevel() {
1443 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
1444 }
1445
1446 /**
1447 * Throw SecurityException if specified resolution level is insufficient to use geofences.
1448 *
1449 * @param allowedResolutionLevel resolution level allowed to caller
1450 */
1451 private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
1452 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Lease4fab68b2012-09-13 13:20:59 -07001453 throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
1454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001455 }
1456
Victoria Lease37425c32012-10-16 16:08:48 -07001457 /**
1458 * Return the minimum resolution level required to use the specified location provider.
1459 *
1460 * @param provider the name of the location provider
1461 * @return minimum resolution level required for provider
1462 */
1463 private int getMinimumResolutionLevelForProviderUse(String provider) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001464 if (LocationManager.GPS_PROVIDER.equals(provider) ||
1465 LocationManager.PASSIVE_PROVIDER.equals(provider)) {
1466 // gps and passive providers require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001467 return RESOLUTION_LEVEL_FINE;
Victoria Lease8dbb6342012-09-21 16:55:53 -07001468 } else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
1469 LocationManager.FUSED_PROVIDER.equals(provider)) {
1470 // network and fused providers are ok with COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001471 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001472 } else {
1473 // mock providers
1474 LocationProviderInterface lp = mMockProviders.get(provider);
1475 if (lp != null) {
1476 ProviderProperties properties = lp.getProperties();
1477 if (properties != null) {
1478 if (properties.mRequiresSatellite) {
1479 // provider requiring satellites require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001480 return RESOLUTION_LEVEL_FINE;
Laurent Tu941221c2012-10-04 14:21:52 -07001481 } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
1482 // provider requiring network and or cell require COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001483 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001484 }
1485 }
1486 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001487 }
Victoria Lease37425c32012-10-16 16:08:48 -07001488 return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
Victoria Leaseda479c52012-10-15 15:24:16 -07001489 }
1490
Victoria Lease37425c32012-10-16 16:08:48 -07001491 /**
1492 * Throw SecurityException if specified resolution level is insufficient to use the named
1493 * location provider.
1494 *
1495 * @param allowedResolutionLevel resolution level allowed to caller
gomo48f1a642017-11-10 20:35:46 -08001496 * @param providerName the name of the location provider
Victoria Lease37425c32012-10-16 16:08:48 -07001497 */
1498 private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel,
1499 String providerName) {
1500 int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName);
1501 if (allowedResolutionLevel < requiredResolutionLevel) {
1502 switch (requiredResolutionLevel) {
1503 case RESOLUTION_LEVEL_FINE:
1504 throw new SecurityException("\"" + providerName + "\" location provider " +
1505 "requires ACCESS_FINE_LOCATION permission.");
1506 case RESOLUTION_LEVEL_COARSE:
1507 throw new SecurityException("\"" + providerName + "\" location provider " +
1508 "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
1509 default:
1510 throw new SecurityException("Insufficient permission for \"" + providerName +
1511 "\" location provider.");
Victoria Leaseda479c52012-10-15 15:24:16 -07001512 }
1513 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001514 }
1515
David Christie82edc9b2013-07-19 11:31:42 -07001516 /**
1517 * Throw SecurityException if WorkSource use is not allowed (i.e. can't blame other packages
1518 * for battery).
1519 */
David Christie40e57822013-07-30 11:36:48 -07001520 private void checkDeviceStatsAllowed() {
David Christie82edc9b2013-07-19 11:31:42 -07001521 mContext.enforceCallingOrSelfPermission(
1522 android.Manifest.permission.UPDATE_DEVICE_STATS, null);
1523 }
1524
David Christie40e57822013-07-30 11:36:48 -07001525 private void checkUpdateAppOpsAllowed() {
1526 mContext.enforceCallingOrSelfPermission(
1527 android.Manifest.permission.UPDATE_APP_OPS_STATS, null);
1528 }
1529
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001530 public static int resolutionLevelToOp(int allowedResolutionLevel) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001531 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
1532 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001533 return AppOpsManager.OP_COARSE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001534 } else {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001535 return AppOpsManager.OP_FINE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001536 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001537 }
1538 return -1;
1539 }
1540
David Christieb870dbf2015-06-22 12:42:53 -07001541 boolean reportLocationAccessNoThrow(
1542 int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001543 int op = resolutionLevelToOp(allowedResolutionLevel);
1544 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001545 if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1546 return false;
1547 }
1548 }
David Christieb870dbf2015-06-22 12:42:53 -07001549
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001550 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001551 }
1552
David Christieb870dbf2015-06-22 12:42:53 -07001553 boolean checkLocationAccess(int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001554 int op = resolutionLevelToOp(allowedResolutionLevel);
1555 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001556 if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1557 return false;
1558 }
1559 }
David Christieb870dbf2015-06-22 12:42:53 -07001560
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001561 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001562 }
1563
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001564 /**
Maggie91e630c2018-01-24 17:31:46 -08001565 * Returns all providers by name, including passive and the ones that are not permitted to
1566 * be accessed by the calling activity or are currently disabled, but excluding fused.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001567 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001568 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001569 public List<String> getAllProviders() {
Maggie91e630c2018-01-24 17:31:46 -08001570 ArrayList<String> out;
1571 synchronized (mLock) {
1572 out = new ArrayList<>(mProviders.size());
1573 for (LocationProviderInterface provider : mProviders) {
1574 String name = provider.getName();
1575 if (LocationManager.FUSED_PROVIDER.equals(name)) {
1576 continue;
1577 }
1578 out.add(name);
1579 }
1580 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001581 if (D) Log.d(TAG, "getAllProviders()=" + out);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 return out;
1583 }
1584
Mike Lockwood03ca2162010-04-01 08:10:09 -07001585 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001586 * Return all providers by name, that match criteria and are optionally
1587 * enabled.
1588 * Can return passive provider, but never returns fused provider.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001589 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001590 @Override
1591 public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
Victoria Lease37425c32012-10-16 16:08:48 -07001592 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001593 ArrayList<String> out;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001594 int uid = Binder.getCallingUid();
Victoria Lease269518e2012-10-29 08:25:39 -07001595 long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07001596 try {
1597 synchronized (mLock) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001598 out = new ArrayList<>(mProviders.size());
Victoria Leaseb711d572012-10-02 13:14:11 -07001599 for (LocationProviderInterface provider : mProviders) {
1600 String name = provider.getName();
1601 if (LocationManager.FUSED_PROVIDER.equals(name)) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001602 continue;
1603 }
Victoria Lease37425c32012-10-16 16:08:48 -07001604 if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08001605 if (enabledOnly && !isAllowedByUserSettingsLocked(name, uid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001606 continue;
1607 }
1608 if (criteria != null && !LocationProvider.propertiesMeetCriteria(
1609 name, provider.getProperties(), criteria)) {
1610 continue;
1611 }
1612 out.add(name);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001613 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001614 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001615 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001616 } finally {
1617 Binder.restoreCallingIdentity(identity);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001618 }
1619
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001620 if (D) Log.d(TAG, "getProviders()=" + out);
1621 return out;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001622 }
1623
1624 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001625 * Return the name of the best provider given a Criteria object.
1626 * This method has been deprecated from the public API,
Victoria Lease8dbb6342012-09-21 16:55:53 -07001627 * and the whole LocationProvider (including #meetsCriteria)
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001628 * has been deprecated as well. So this method now uses
1629 * some simplified logic.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001630 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001631 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001632 public String getBestProvider(Criteria criteria, boolean enabledOnly) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001633 String result = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001634
1635 List<String> providers = getProviders(criteria, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001636 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001637 result = pickBest(providers);
1638 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1639 return result;
1640 }
1641 providers = getProviders(null, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001642 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001643 result = pickBest(providers);
1644 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1645 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001646 }
1647
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001648 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001649 return null;
1650 }
1651
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001652 private String pickBest(List<String> providers) {
Victoria Lease1925e292012-09-24 17:00:18 -07001653 if (providers.contains(LocationManager.GPS_PROVIDER)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001654 return LocationManager.GPS_PROVIDER;
Victoria Lease1925e292012-09-24 17:00:18 -07001655 } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
1656 return LocationManager.NETWORK_PROVIDER;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001657 } else {
1658 return providers.get(0);
1659 }
1660 }
1661
Nick Pellye0fd6932012-07-11 10:26:13 -07001662 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001663 public boolean providerMeetsCriteria(String provider, Criteria criteria) {
1664 LocationProviderInterface p = mProvidersByName.get(provider);
1665 if (p == null) {
1666 throw new IllegalArgumentException("provider=" + provider);
1667 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001668
1669 boolean result = LocationProvider.propertiesMeetCriteria(
1670 p.getName(), p.getProperties(), criteria);
1671 if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result);
1672 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001673 }
1674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 private void updateProvidersLocked() {
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001676 boolean changesMade = false;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001677 for (int i = mProviders.size() - 1; i >= 0; i--) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001678 LocationProviderInterface p = mProviders.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679 boolean isEnabled = p.isEnabled();
1680 String name = p.getName();
Victoria Lease09eeaec2013-02-05 11:34:13 -08001681 boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 if (isEnabled && !shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001683 updateProviderListenersLocked(name, false);
David Christieb084fef2013-12-18 14:33:57 -08001684 // If any provider has been disabled, clear all last locations for all providers.
1685 // This is to be on the safe side in case a provider has location derived from
1686 // this disabled provider.
1687 mLastLocation.clear();
1688 mLastLocationCoarseInterval.clear();
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001689 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690 } else if (!isEnabled && shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001691 updateProviderListenersLocked(name, true);
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001692 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 }
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001694 }
1695 if (changesMade) {
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001696 mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
1697 UserHandle.ALL);
Tom O'Neill40a86c22013-09-03 18:05:13 -07001698 mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
1699 UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001700 }
1701 }
1702
Amith Yamasanib27528d2014-06-05 15:02:10 -07001703 private void updateProviderListenersLocked(String provider, boolean enabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 int listeners = 0;
1705
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001706 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001707 if (p == null) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708
1709 ArrayList<Receiver> deadReceivers = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07001710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001711 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1712 if (records != null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001713 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001714 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001715 // Sends a notification message to the receiver
1716 if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
1717 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001718 deadReceivers = new ArrayList<>();
Victoria Leaseb711d572012-10-02 13:14:11 -07001719 }
1720 deadReceivers.add(record.mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001721 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001722 listeners++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001723 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001724 }
1725 }
1726
1727 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001728 for (int i = deadReceivers.size() - 1; i >= 0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001729 removeUpdatesLocked(deadReceivers.get(i));
1730 }
1731 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001733 if (enabled) {
1734 p.enable();
1735 if (listeners > 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001736 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001737 }
1738 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739 p.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001740 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001741 }
1742
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001743 private void applyRequirementsLocked(String provider) {
1744 LocationProviderInterface p = mProvidersByName.get(provider);
1745 if (p == null) return;
1746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001747 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001748 WorkSource worksource = new WorkSource();
1749 ProviderRequest providerRequest = new ProviderRequest();
1750
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001751 ContentResolver resolver = mContext.getContentResolver();
1752 long backgroundThrottleInterval = Settings.Global.getLong(
1753 resolver,
1754 Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
1755 DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
gomo48f1a642017-11-10 20:35:46 -08001756 // initialize the low power mode to true and set to false if any of the records requires
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001757
gomo48f1a642017-11-10 20:35:46 -08001758 providerRequest.lowPowerMode = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001759 if (records != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001760 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001761 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
David Christieb870dbf2015-06-22 12:42:53 -07001762 if (checkLocationAccess(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001763 record.mReceiver.mIdentity.mPid,
1764 record.mReceiver.mIdentity.mUid,
1765 record.mReceiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001766 record.mReceiver.mAllowedResolutionLevel)) {
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001767 LocationRequest locationRequest = record.mRealRequest;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001768 long interval = locationRequest.getInterval();
1769
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001770 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001771 if (!record.mIsForegroundUid) {
1772 interval = Math.max(interval, backgroundThrottleInterval);
1773 }
1774 if (interval != locationRequest.getInterval()) {
1775 locationRequest = new LocationRequest(locationRequest);
1776 locationRequest.setInterval(interval);
1777 }
1778 }
1779
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001780 record.mRequest = locationRequest;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001781 providerRequest.locationRequests.add(locationRequest);
gomo48f1a642017-11-10 20:35:46 -08001782 if (!locationRequest.isLowPowerMode()) {
1783 providerRequest.lowPowerMode = false;
1784 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001785 if (interval < providerRequest.interval) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001786 providerRequest.reportLocation = true;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001787 providerRequest.interval = interval;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001788 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001789 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001790 }
1791 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001792
1793 if (providerRequest.reportLocation) {
1794 // calculate who to blame for power
1795 // This is somewhat arbitrary. We pick a threshold interval
1796 // that is slightly higher that the minimum interval, and
1797 // spread the blame across all applications with a request
1798 // under that threshold.
1799 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
1800 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001801 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001802 LocationRequest locationRequest = record.mRequest;
Svet Ganove998c732016-06-10 00:12:38 -07001803
1804 // Don't assign battery blame for update records whose
1805 // client has no permission to receive location data.
1806 if (!providerRequest.locationRequests.contains(locationRequest)) {
1807 continue;
1808 }
1809
Victoria Leaseb711d572012-10-02 13:14:11 -07001810 if (locationRequest.getInterval() <= thresholdInterval) {
David Christiee55c9682013-08-22 10:10:34 -07001811 if (record.mReceiver.mWorkSource != null
Narayan Kamath32684dd2018-01-08 17:32:51 +00001812 && isValidWorkSource(record.mReceiver.mWorkSource)) {
David Christie82edc9b2013-07-19 11:31:42 -07001813 worksource.add(record.mReceiver.mWorkSource);
1814 } else {
Narayan Kamath32684dd2018-01-08 17:32:51 +00001815 // Assign blame to caller if there's no WorkSource associated with
1816 // the request or if it's invalid.
David Christie82edc9b2013-07-19 11:31:42 -07001817 worksource.add(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001818 record.mReceiver.mIdentity.mUid,
1819 record.mReceiver.mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001820 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001821 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001822 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001823 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001824 }
1825 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001826
1827 if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
1828 p.setRequest(providerRequest, worksource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 }
1830
Narayan Kamath32684dd2018-01-08 17:32:51 +00001831 /**
1832 * Whether a given {@code WorkSource} associated with a Location request is valid.
1833 */
1834 private static boolean isValidWorkSource(WorkSource workSource) {
1835 if (workSource.size() > 0) {
1836 // If the WorkSource has one or more non-chained UIDs, make sure they're accompanied
1837 // by tags.
1838 return workSource.getName(0) != null;
1839 } else {
1840 // For now, make sure callers have supplied an attribution tag for use with
1841 // AppOpsManager. This might be relaxed in the future.
1842 final ArrayList<WorkChain> workChains = workSource.getWorkChains();
1843 return workChains != null && !workChains.isEmpty() &&
1844 workChains.get(0).getAttributionTag() != null;
1845 }
1846 }
1847
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001848 @Override
1849 public String[] getBackgroundThrottlingWhitelist() {
1850 synchronized (mLock) {
1851 return mBackgroundThrottlePackageWhitelist.toArray(
gomo48f1a642017-11-10 20:35:46 -08001852 new String[mBackgroundThrottlePackageWhitelist.size()]);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001853 }
1854 }
1855
1856 private void updateBackgroundThrottlingWhitelistLocked() {
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001857 String setting = Settings.Global.getString(
gomo48f1a642017-11-10 20:35:46 -08001858 mContext.getContentResolver(),
1859 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001860 if (setting == null) {
1861 setting = "";
1862 }
1863
1864 mBackgroundThrottlePackageWhitelist.clear();
1865 mBackgroundThrottlePackageWhitelist.addAll(
gomo48f1a642017-11-10 20:35:46 -08001866 SystemConfig.getInstance().getAllowUnthrottledLocation());
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001867 mBackgroundThrottlePackageWhitelist.addAll(
gomo48f1a642017-11-10 20:35:46 -08001868 Arrays.asList(setting.split(",")));
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001869 }
1870
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001871 private boolean isThrottlingExemptLocked(Identity identity) {
1872 if (identity.mUid == Process.SYSTEM_UID) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001873 return true;
1874 }
1875
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001876 if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001877 return true;
1878 }
1879
1880 for (LocationProviderProxy provider : mProxyProviders) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001881 if (identity.mPackageName.equals(provider.getConnectedPackageName())) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001882 return true;
1883 }
1884 }
1885
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001886 return false;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001887 }
1888
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001889 private class UpdateRecord {
1890 final String mProvider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001891 final LocationRequest mRealRequest; // original request from client
1892 LocationRequest mRequest; // possibly throttled version of the request
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001893 final Receiver mReceiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001894 boolean mIsForegroundUid;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001895 Location mLastFixBroadcast;
1896 long mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001897
1898 /**
1899 * Note: must be constructed with lock held.
1900 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001901 UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001902 mProvider = provider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001903 mRealRequest = request;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001904 mRequest = request;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001905 mReceiver = receiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001906 mIsForegroundUid = isImportanceForeground(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001907 mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001908
1909 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1910 if (records == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001911 records = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001912 mRecordsByProvider.put(provider, records);
1913 }
1914 if (!records.contains(this)) {
1915 records.add(this);
1916 }
David Christie2ff96af2014-01-30 16:09:37 -08001917
1918 // Update statistics for historical location requests by package/provider
1919 mRequestStatistics.startRequesting(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001920 mReceiver.mIdentity.mPackageName, provider, request.getInterval());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001921 }
1922
1923 /**
David Christie2ff96af2014-01-30 16:09:37 -08001924 * Method to be called when a record will no longer be used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001925 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001926 void disposeLocked(boolean removeReceiver) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001927 mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider);
David Christie2ff96af2014-01-30 16:09:37 -08001928
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001929 // remove from mRecordsByProvider
1930 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
1931 if (globalRecords != null) {
1932 globalRecords.remove(this);
1933 }
1934
1935 if (!removeReceiver) return; // the caller will handle the rest
1936
1937 // remove from Receiver#mUpdateRecords
1938 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
1939 if (receiverRecords != null) {
1940 receiverRecords.remove(this.mProvider);
1941
1942 // and also remove the Receiver if it has no more update records
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001943 if (receiverRecords.size() == 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001944 removeUpdatesLocked(mReceiver);
1945 }
Mike Lockwood3a76fd62009-09-01 07:26:56 -04001946 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001947 }
1948
1949 @Override
1950 public String toString() {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001951 return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
gomo48f1a642017-11-10 20:35:46 -08001952 + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground"
1953 : " background")
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001954 + ")" + " " + mRealRequest + "]";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001955 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001956 }
1957
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001958 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -07001959 String packageName, WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001960 IBinder binder = listener.asBinder();
1961 Receiver receiver = mReceivers.get(binder);
1962 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07001963 receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
1964 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001965 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001966 receiver.getListener().asBinder().linkToDeath(receiver, 0);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001967 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001968 Slog.e(TAG, "linkToDeath failed:", e);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001969 return null;
1970 }
Wen Jingcb3ab222014-03-27 13:42:59 +08001971 mReceivers.put(binder, receiver);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001972 }
1973 return receiver;
1974 }
1975
David Christie82edc9b2013-07-19 11:31:42 -07001976 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
David Christie40e57822013-07-30 11:36:48 -07001977 WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001978 Receiver receiver = mReceivers.get(intent);
1979 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07001980 receiver = new Receiver(null, intent, pid, uid, packageName, workSource,
1981 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001982 mReceivers.put(intent, receiver);
1983 }
1984 return receiver;
1985 }
1986
Victoria Lease37425c32012-10-16 16:08:48 -07001987 /**
1988 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
1989 * and consistency requirements.
1990 *
1991 * @param request the LocationRequest from which to create a sanitized version
Victoria Lease37425c32012-10-16 16:08:48 -07001992 * @return a version of request that meets the given resolution and consistency requirements
1993 * @hide
1994 */
gomo48f1a642017-11-10 20:35:46 -08001995 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel,
1996 boolean callerHasLocationHardwarePermission) {
Victoria Lease37425c32012-10-16 16:08:48 -07001997 LocationRequest sanitizedRequest = new LocationRequest(request);
gomo48f1a642017-11-10 20:35:46 -08001998 if (!callerHasLocationHardwarePermission) {
1999 // allow setting low power mode only for callers with location hardware permission
2000 sanitizedRequest.setLowPowerMode(false);
2001 }
Victoria Lease37425c32012-10-16 16:08:48 -07002002 if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
2003 switch (sanitizedRequest.getQuality()) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002004 case LocationRequest.ACCURACY_FINE:
Victoria Lease37425c32012-10-16 16:08:48 -07002005 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
Victoria Lease09016ab2012-09-16 12:33:15 -07002006 break;
2007 case LocationRequest.POWER_HIGH:
Victoria Lease37425c32012-10-16 16:08:48 -07002008 sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
Victoria Lease09016ab2012-09-16 12:33:15 -07002009 break;
2010 }
2011 // throttle
Victoria Lease37425c32012-10-16 16:08:48 -07002012 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
2013 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07002014 }
Victoria Lease37425c32012-10-16 16:08:48 -07002015 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
2016 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07002017 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07002018 }
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002019 // make getFastestInterval() the minimum of interval and fastest interval
Victoria Lease37425c32012-10-16 16:08:48 -07002020 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002021 request.setFastestInterval(request.getInterval());
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002022 }
Victoria Lease37425c32012-10-16 16:08:48 -07002023 return sanitizedRequest;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002024 }
2025
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002026 private void checkPackageName(String packageName) {
Nick Pellye0fd6932012-07-11 10:26:13 -07002027 if (packageName == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002028 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002029 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002030 int uid = Binder.getCallingUid();
Nick Pellye0fd6932012-07-11 10:26:13 -07002031 String[] packages = mPackageManager.getPackagesForUid(uid);
2032 if (packages == null) {
2033 throw new SecurityException("invalid UID " + uid);
2034 }
2035 for (String pkg : packages) {
2036 if (packageName.equals(pkg)) return;
2037 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002038 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002039 }
2040
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002041 private void checkPendingIntent(PendingIntent intent) {
2042 if (intent == null) {
2043 throw new IllegalArgumentException("invalid pending intent: " + intent);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002044 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002045 }
2046
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002047 private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent,
David Christie40e57822013-07-30 11:36:48 -07002048 int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002049 if (intent == null && listener == null) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002050 throw new IllegalArgumentException("need either listener or intent");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002051 } else if (intent != null && listener != null) {
2052 throw new IllegalArgumentException("cannot register both listener and intent");
2053 } else if (intent != null) {
2054 checkPendingIntent(intent);
David Christie40e57822013-07-30 11:36:48 -07002055 return getReceiverLocked(intent, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002056 } else {
David Christie40e57822013-07-30 11:36:48 -07002057 return getReceiverLocked(listener, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002058 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002059 }
2060
Nick Pellye0fd6932012-07-11 10:26:13 -07002061 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002062 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
2063 PendingIntent intent, String packageName) {
2064 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2065 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002066 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2067 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2068 request.getProvider());
David Christie82edc9b2013-07-19 11:31:42 -07002069 WorkSource workSource = request.getWorkSource();
Narayan Kamath32684dd2018-01-08 17:32:51 +00002070 if (workSource != null && !workSource.isEmpty()) {
David Christie40e57822013-07-30 11:36:48 -07002071 checkDeviceStatsAllowed();
2072 }
2073 boolean hideFromAppOps = request.getHideFromAppOps();
2074 if (hideFromAppOps) {
2075 checkUpdateAppOpsAllowed();
David Christie82edc9b2013-07-19 11:31:42 -07002076 }
gomo48f1a642017-11-10 20:35:46 -08002077 boolean callerHasLocationHardwarePermission =
2078 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
Maggieaa080f92018-01-04 15:35:11 -08002079 == PERMISSION_GRANTED;
gomo48f1a642017-11-10 20:35:46 -08002080 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel,
2081 callerHasLocationHardwarePermission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002082
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002083 final int pid = Binder.getCallingPid();
2084 final int uid = Binder.getCallingUid();
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002085 // providers may use public location API's, need to clear identity
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002086 long identity = Binder.clearCallingIdentity();
2087 try {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002088 // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2089 // a location.
David Christieb870dbf2015-06-22 12:42:53 -07002090 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002091
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002092 synchronized (mLock) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002093 Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
David Christie40e57822013-07-30 11:36:48 -07002094 packageName, workSource, hideFromAppOps);
Victoria Lease37425c32012-10-16 16:08:48 -07002095 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
Mike Lockwood2d4d1bf2010-10-18 17:06:26 -04002096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002097 } finally {
2098 Binder.restoreCallingIdentity(identity);
2099 }
2100 }
2101
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002102 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
2103 int pid, int uid, String packageName) {
2104 // Figure out the provider. Either its explicitly request (legacy use cases), or
2105 // use the fused provider
2106 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2107 String name = request.getProvider();
Victoria Lease09016ab2012-09-16 12:33:15 -07002108 if (name == null) {
2109 throw new IllegalArgumentException("provider name must not be null");
2110 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -07002111
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002112 LocationProviderInterface provider = mProvidersByName.get(name);
2113 if (provider == null) {
Victoria Leaseb30f3832013-10-13 12:15:40 -07002114 throw new IllegalArgumentException("provider doesn't exist: " + name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002115 }
2116
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002117 UpdateRecord record = new UpdateRecord(name, request, receiver);
gomo48f1a642017-11-10 20:35:46 -08002118 if (D) {
2119 Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
2120 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
2121 + (record.mIsForegroundUid ? "foreground" : "background")
2122 + (isThrottlingExemptLocked(receiver.mIdentity)
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002123 ? " [whitelisted]" : "") + ")");
gomo48f1a642017-11-10 20:35:46 -08002124 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002125
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002126 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
2127 if (oldRecord != null) {
2128 oldRecord.disposeLocked(false);
2129 }
2130
Victoria Lease09eeaec2013-02-05 11:34:13 -08002131 boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002132 if (isProviderEnabled) {
2133 applyRequirementsLocked(name);
2134 } else {
2135 // Notify the listener that updates are currently disabled
2136 receiver.callProviderEnabledLocked(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002137 }
David Christie0b837452013-07-29 16:02:13 -07002138 // Update the monitoring here just in case multiple location requests were added to the
2139 // same receiver (this request may be high power and the initial might not have been).
2140 receiver.updateMonitoring(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002141 }
2142
Nick Pellye0fd6932012-07-11 10:26:13 -07002143 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002144 public void removeUpdates(ILocationListener listener, PendingIntent intent,
2145 String packageName) {
2146 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002147
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002148 final int pid = Binder.getCallingPid();
2149 final int uid = Binder.getCallingUid();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002150
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002151 synchronized (mLock) {
David Christie82edc9b2013-07-19 11:31:42 -07002152 WorkSource workSource = null;
David Christie40e57822013-07-30 11:36:48 -07002153 boolean hideFromAppOps = false;
2154 Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid,
2155 packageName, workSource, hideFromAppOps);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002156
2157 // providers may use public location API's, need to clear identity
2158 long identity = Binder.clearCallingIdentity();
2159 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002160 removeUpdatesLocked(receiver);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002161 } finally {
2162 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002163 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002164 }
2165 }
2166
2167 private void removeUpdatesLocked(Receiver receiver) {
Dianne Hackborn7ff30112012-11-08 11:12:09 -08002168 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002169
2170 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
2171 receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
2172 synchronized (receiver) {
Victoria Lease0aa28602013-05-29 15:28:26 -07002173 receiver.clearPendingBroadcastsLocked();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002175 }
2176
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07002177 receiver.updateMonitoring(false);
2178
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002179 // Record which providers were associated with this listener
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002180 HashSet<String> providers = new HashSet<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002181 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2182 if (oldRecords != null) {
2183 // Call dispose() on the obsolete update records.
2184 for (UpdateRecord record : oldRecords.values()) {
David Christie2ff96af2014-01-30 16:09:37 -08002185 // Update statistics for historical location requests by package/provider
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002186 record.disposeLocked(false);
2187 }
2188 // Accumulate providers
2189 providers.addAll(oldRecords.keySet());
2190 }
2191
2192 // update provider
2193 for (String provider : providers) {
2194 // If provider is already disabled, don't need to do anything
Victoria Lease09eeaec2013-02-05 11:34:13 -08002195 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002196 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002197 }
2198
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002199 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002200 }
2201 }
2202
Dianne Hackbornc2293022013-02-06 23:14:49 -08002203 private void applyAllProviderRequirementsLocked() {
2204 for (LocationProviderInterface p : mProviders) {
2205 // If provider is already disabled, don't need to do anything
Dianne Hackborn64d41d72013-02-07 00:33:31 -08002206 if (!isAllowedByCurrentUserSettingsLocked(p.getName())) {
Dianne Hackbornc2293022013-02-06 23:14:49 -08002207 continue;
2208 }
2209
2210 applyRequirementsLocked(p.getName());
2211 }
2212 }
2213
Nick Pellye0fd6932012-07-11 10:26:13 -07002214 @Override
Nick Pelly4035f5a2012-08-17 14:43:49 -07002215 public Location getLastLocation(LocationRequest request, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002216 if (D) Log.d(TAG, "getLastLocation: " + request);
2217 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002218 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly4035f5a2012-08-17 14:43:49 -07002219 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002220 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2221 request.getProvider());
2222 // no need to sanitize this request, as only the provider name is used
Nick Pelly4035f5a2012-08-17 14:43:49 -07002223
David Christieb870dbf2015-06-22 12:42:53 -07002224 final int pid = Binder.getCallingPid();
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002225 final int uid = Binder.getCallingUid();
2226 final long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07002227 try {
2228 if (mBlacklist.isBlacklisted(packageName)) {
gomo48f1a642017-11-10 20:35:46 -08002229 if (D) {
2230 Log.d(TAG, "not returning last loc for blacklisted app: " +
2231 packageName);
2232 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002233 return null;
2234 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002235
David Christieb870dbf2015-06-22 12:42:53 -07002236 if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel)) {
gomo48f1a642017-11-10 20:35:46 -08002237 if (D) {
2238 Log.d(TAG, "not returning last loc for no op app: " +
2239 packageName);
2240 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002241 return null;
2242 }
2243
Victoria Leaseb711d572012-10-02 13:14:11 -07002244 synchronized (mLock) {
2245 // Figure out the provider. Either its explicitly request (deprecated API's),
2246 // or use the fused provider
2247 String name = request.getProvider();
2248 if (name == null) name = LocationManager.FUSED_PROVIDER;
2249 LocationProviderInterface provider = mProvidersByName.get(name);
2250 if (provider == null) return null;
2251
Victoria Lease09eeaec2013-02-05 11:34:13 -08002252 if (!isAllowedByUserSettingsLocked(name, uid)) return null;
Victoria Leaseb711d572012-10-02 13:14:11 -07002253
David Christie1b9b7b12013-04-15 15:31:11 -07002254 Location location;
2255 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2256 // Make sure that an app with coarse permissions can't get frequent location
2257 // updates by calling LocationManager.getLastKnownLocation repeatedly.
2258 location = mLastLocationCoarseInterval.get(name);
2259 } else {
2260 location = mLastLocation.get(name);
2261 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002262 if (location == null) {
2263 return null;
2264 }
Victoria Lease37425c32012-10-16 16:08:48 -07002265 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
gomo48f1a642017-11-10 20:35:46 -08002266 Location noGPSLocation = location.getExtraLocation(
2267 Location.EXTRA_NO_GPS_LOCATION);
Victoria Leaseb711d572012-10-02 13:14:11 -07002268 if (noGPSLocation != null) {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002269 return new Location(mLocationFudger.getOrCreate(noGPSLocation));
Victoria Leaseb711d572012-10-02 13:14:11 -07002270 }
Victoria Lease37425c32012-10-16 16:08:48 -07002271 } else {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002272 return new Location(location);
Victoria Lease09016ab2012-09-16 12:33:15 -07002273 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002274 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002275 return null;
2276 } finally {
2277 Binder.restoreCallingIdentity(identity);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002278 }
2279 }
2280
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002281 /**
2282 * Provides an interface to inject and set the last location if location is not available
2283 * currently.
2284 *
2285 * This helps in cases where the product (Cars for example) has saved the last known location
2286 * before powering off. This interface lets the client inject the saved location while the GPS
2287 * chipset is getting its first fix, there by improving user experience.
2288 *
2289 * @param location - Location object to inject
2290 * @return true if update was successful, false if not
2291 */
2292 @Override
2293 public boolean injectLocation(Location location) {
2294 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
2295 "Location Hardware permission not granted to inject location");
2296 mContext.enforceCallingPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
2297 "Access Fine Location permission not granted to inject Location");
2298
2299 if (location == null) {
2300 if (D) {
2301 Log.d(TAG, "injectLocation(): called with null location");
2302 }
2303 return false;
2304 }
2305 LocationProviderInterface p = null;
2306 String provider = location.getProvider();
2307 if (provider != null) {
2308 p = mProvidersByName.get(provider);
2309 }
2310 if (p == null) {
2311 if (D) {
2312 Log.d(TAG, "injectLocation(): unknown provider");
2313 }
2314 return false;
2315 }
2316 synchronized (mLock) {
2317 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
2318 if (D) {
2319 Log.d(TAG, "Location disabled in Settings for current user:" + mCurrentUserId);
2320 }
2321 return false;
2322 } else {
2323 // NOTE: If last location is already available, location is not injected. If
2324 // provider's normal source (like a GPS chipset) have already provided an output,
2325 // there is no need to inject this location.
2326 if (mLastLocation.get(provider) == null) {
2327 updateLastLocationLocked(location, provider);
2328 } else {
2329 if (D) {
2330 Log.d(TAG, "injectLocation(): Location exists. Not updating");
2331 }
2332 return false;
2333 }
2334 }
2335 }
2336 return true;
2337 }
2338
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002339 @Override
2340 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
2341 String packageName) {
2342 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002343 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2344 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002345 checkPendingIntent(intent);
2346 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002347 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2348 request.getProvider());
gomo48f1a642017-11-10 20:35:46 -08002349 // Require that caller can manage given document
2350 boolean callerHasLocationHardwarePermission =
2351 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
Maggieaa080f92018-01-04 15:35:11 -08002352 == PERMISSION_GRANTED;
gomo48f1a642017-11-10 20:35:46 -08002353 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel,
2354 callerHasLocationHardwarePermission);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002355
Victoria Lease37425c32012-10-16 16:08:48 -07002356 if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002357
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002358 // geo-fence manager uses the public location API, need to clear identity
2359 int uid = Binder.getCallingUid();
Xiaohui Chena4490622015-09-22 15:29:31 -07002360 // TODO: http://b/23822629
2361 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
Victoria Lease56e675b2012-11-05 19:25:06 -08002362 // temporary measure until geofences work for secondary users
2363 Log.w(TAG, "proximity alerts are currently available only to the primary user");
2364 return;
2365 }
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002366 long identity = Binder.clearCallingIdentity();
2367 try {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002368 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
2369 uid, packageName);
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002370 } finally {
2371 Binder.restoreCallingIdentity(identity);
2372 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002373 }
2374
2375 @Override
2376 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002377 checkPendingIntent(intent);
2378 checkPackageName(packageName);
2379
2380 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2381
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002382 // geo-fence manager uses the public location API, need to clear identity
2383 long identity = Binder.clearCallingIdentity();
2384 try {
2385 mGeofenceManager.removeFence(geofence, intent);
2386 } finally {
2387 Binder.restoreCallingIdentity(identity);
2388 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002389 }
2390
2391
2392 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002393 public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002394 if (!hasGnssPermissions(packageName) || mGnssStatusProvider == null) {
Takayuki Hoshib254ab6a2014-10-23 16:46:02 +09002395 return false;
2396 }
2397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002398 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002399 mGnssStatusProvider.registerGnssStatusCallback(callback);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002400 } catch (RemoteException e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002401 Slog.e(TAG, "mGpsStatusProvider.registerGnssStatusCallback failed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002402 return false;
2403 }
2404 return true;
2405 }
2406
Nick Pellye0fd6932012-07-11 10:26:13 -07002407 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002408 public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002409 synchronized (mLock) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002410 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002411 mGnssStatusProvider.unregisterGnssStatusCallback(callback);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002412 } catch (Exception e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002413 Slog.e(TAG, "mGpsStatusProvider.unregisterGnssStatusCallback failed", e);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002414 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002415 }
2416 }
2417
Nick Pellye0fd6932012-07-11 10:26:13 -07002418 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002419 public boolean addGnssMeasurementsListener(
gomo48f1a642017-11-10 20:35:46 -08002420 IGnssMeasurementsListener listener, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002421 if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
destradaaea8a8a62014-06-23 18:19:03 -07002422 return false;
2423 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002424
2425 synchronized (mLock) {
2426 Identity callerIdentity
2427 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
Wyatt Riley11cc7492018-01-17 08:48:27 -08002428 mGnssMeasurementsListeners.put(listener.asBinder(), callerIdentity);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002429 long identity = Binder.clearCallingIdentity();
2430 try {
2431 if (isThrottlingExemptLocked(callerIdentity)
2432 || isImportanceForeground(
gomo48f1a642017-11-10 20:35:46 -08002433 mActivityManager.getPackageImportance(packageName))) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002434 return mGnssMeasurementsProvider.addListener(listener);
2435 }
2436 } finally {
2437 Binder.restoreCallingIdentity(identity);
2438 }
2439
2440 return true;
2441 }
destradaaea8a8a62014-06-23 18:19:03 -07002442 }
2443
2444 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002445 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
2446 if (mGnssMeasurementsProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002447 synchronized (mLock) {
Wyatt Riley11cc7492018-01-17 08:48:27 -08002448 mGnssMeasurementsListeners.remove(listener.asBinder());
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002449 mGnssMeasurementsProvider.removeListener(listener);
2450 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002451 }
destradaaea8a8a62014-06-23 18:19:03 -07002452 }
2453
2454 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002455 public boolean addGnssNavigationMessageListener(
2456 IGnssNavigationMessageListener listener,
destradaa4b3e3932014-07-21 18:01:47 -07002457 String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002458 if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) {
destradaa4b3e3932014-07-21 18:01:47 -07002459 return false;
2460 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002461
2462 synchronized (mLock) {
2463 Identity callerIdentity
gomo48f1a642017-11-10 20:35:46 -08002464 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
Wyatt Riley11cc7492018-01-17 08:48:27 -08002465 mGnssNavigationMessageListeners.put(listener.asBinder(), callerIdentity);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002466 long identity = Binder.clearCallingIdentity();
2467 try {
2468 if (isThrottlingExemptLocked(callerIdentity)
2469 || isImportanceForeground(
gomo48f1a642017-11-10 20:35:46 -08002470 mActivityManager.getPackageImportance(packageName))) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002471 return mGnssNavigationMessageProvider.addListener(listener);
2472 }
2473 } finally {
2474 Binder.restoreCallingIdentity(identity);
2475 }
2476
2477 return true;
2478 }
destradaa4b3e3932014-07-21 18:01:47 -07002479 }
2480
2481 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002482 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
2483 if (mGnssNavigationMessageProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002484 synchronized (mLock) {
Wyatt Riley11cc7492018-01-17 08:48:27 -08002485 mGnssNavigationMessageListeners.remove(listener.asBinder());
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002486 mGnssNavigationMessageProvider.removeListener(listener);
2487 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002488 }
destradaa4b3e3932014-07-21 18:01:47 -07002489 }
2490
2491 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002492 public boolean sendExtraCommand(String provider, String command, Bundle extras) {
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002493 if (provider == null) {
2494 // throw NullPointerException to remain compatible with previous implementation
2495 throw new NullPointerException();
2496 }
Victoria Lease37425c32012-10-16 16:08:48 -07002497 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2498 provider);
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002500 // and check for ACCESS_LOCATION_EXTRA_COMMANDS
Mike Lockwoodb7e99222009-07-07 13:18:21 -04002501 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
Maggieaa080f92018-01-04 15:35:11 -08002502 != PERMISSION_GRANTED)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002503 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
2504 }
2505
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002506 synchronized (mLock) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002507 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002508 if (p == null) return false;
Nick Pellye0fd6932012-07-11 10:26:13 -07002509
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002510 return p.sendExtraCommand(command, extras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002511 }
2512 }
2513
Nick Pellye0fd6932012-07-11 10:26:13 -07002514 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002515 public boolean sendNiResponse(int notifId, int userResponse) {
Mike Lockwood18ad9f62009-08-27 14:01:23 -07002516 if (Binder.getCallingUid() != Process.myUid()) {
2517 throw new SecurityException(
2518 "calling sendNiResponse from outside of the system is not allowed");
2519 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002520 try {
2521 return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002522 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002523 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
Danke Xie22d1f9f2009-08-18 18:28:45 -04002524 return false;
2525 }
2526 }
2527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002528 /**
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002529 * @return null if the provider does not exist
Alexey Tarasovf2db9fb2009-09-01 02:37:07 +11002530 * @throws SecurityException if the provider is not allowed to be
gomo48f1a642017-11-10 20:35:46 -08002531 * accessed by the caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002532 */
Nick Pellye0fd6932012-07-11 10:26:13 -07002533 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002534 public ProviderProperties getProviderProperties(String provider) {
Laurent Tub7f9d252012-10-16 14:25:00 -07002535 if (mProvidersByName.get(provider) == null) {
David Christie2ff96af2014-01-30 16:09:37 -08002536 return null;
Laurent Tub7f9d252012-10-16 14:25:00 -07002537 }
2538
Victoria Lease37425c32012-10-16 16:08:48 -07002539 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2540 provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002541
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002542 LocationProviderInterface p;
2543 synchronized (mLock) {
2544 p = mProvidersByName.get(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002545 }
2546
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002547 if (p == null) return null;
2548 return p.getProperties();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002549 }
2550
Jason Monkb71218a2015-06-17 14:44:39 -04002551 /**
2552 * @return null if the provider does not exist
2553 * @throws SecurityException if the provider is not allowed to be
gomo48f1a642017-11-10 20:35:46 -08002554 * accessed by the caller
Jason Monkb71218a2015-06-17 14:44:39 -04002555 */
2556 @Override
2557 public String getNetworkProviderPackage() {
2558 LocationProviderInterface p;
2559 synchronized (mLock) {
2560 if (mProvidersByName.get(LocationManager.NETWORK_PROVIDER) == null) {
2561 return null;
2562 }
2563 p = mProvidersByName.get(LocationManager.NETWORK_PROVIDER);
2564 }
2565
2566 if (p instanceof LocationProviderProxy) {
2567 return ((LocationProviderProxy) p).getConnectedPackageName();
2568 }
2569 return null;
2570 }
2571
Maggieaa080f92018-01-04 15:35:11 -08002572 /**
Maggieaa080f92018-01-04 15:35:11 -08002573 * Read location provider status from Settings.Secure
2574 *
2575 * @param provider the location provider to query
2576 * @param userId the user id to query
2577 * @return true if the provider is enabled
2578 */
2579 private boolean isLocationProviderEnabledForUser(String provider, int userId) {
2580 long identity = Binder.clearCallingIdentity();
2581 try {
2582 // Use system settings
2583 ContentResolver cr = mContext.getContentResolver();
2584 String allowedProviders = Settings.Secure.getStringForUser(
2585 cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userId);
2586 return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
2587 } finally {
2588 Binder.restoreCallingIdentity(identity);
2589 }
2590 }
2591
2592 /**
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002593 * Returns "true" if the UID belongs to a bound location provider.
2594 *
2595 * @param uid the uid
2596 * @return true if uid belongs to a bound location provider
2597 */
2598 private boolean isUidALocationProvider(int uid) {
2599 if (uid == Process.SYSTEM_UID) {
2600 return true;
2601 }
2602 if (mGeocodeProvider != null) {
David Christie1f141c12014-05-14 15:11:15 -07002603 if (doesUidHavePackage(uid, mGeocodeProvider.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002604 }
2605 for (LocationProviderProxy proxy : mProxyProviders) {
David Christie1f141c12014-05-14 15:11:15 -07002606 if (doesUidHavePackage(uid, proxy.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002607 }
2608 return false;
2609 }
2610
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002611 private void checkCallerIsProvider() {
2612 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
Maggieaa080f92018-01-04 15:35:11 -08002613 == PERMISSION_GRANTED) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002614 return;
2615 }
2616
2617 // Previously we only used the INSTALL_LOCATION_PROVIDER
2618 // check. But that is system or signature
2619 // protection level which is not flexible enough for
2620 // providers installed oustide the system image. So
2621 // also allow providers with a UID matching the
2622 // currently bound package name
2623
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002624 if (isUidALocationProvider(Binder.getCallingUid())) {
2625 return;
2626 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002627
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002628 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
2629 "or UID of a currently bound location provider");
2630 }
2631
David Christie1f141c12014-05-14 15:11:15 -07002632 /**
2633 * Returns true if the given package belongs to the given uid.
2634 */
2635 private boolean doesUidHavePackage(int uid, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002636 if (packageName == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002637 return false;
2638 }
David Christie1f141c12014-05-14 15:11:15 -07002639 String[] packageNames = mPackageManager.getPackagesForUid(uid);
2640 if (packageNames == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002641 return false;
2642 }
David Christie1f141c12014-05-14 15:11:15 -07002643 for (String name : packageNames) {
2644 if (packageName.equals(name)) {
2645 return true;
2646 }
2647 }
2648 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002649 }
2650
Nick Pellye0fd6932012-07-11 10:26:13 -07002651 @Override
Mike Lockwooda4903f22010-02-17 06:42:23 -05002652 public void reportLocation(Location location, boolean passive) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002653 checkCallerIsProvider();
Mike Lockwood275555c2009-05-01 11:30:34 -04002654
Nick Pelly2eeeec22012-07-18 13:13:37 -07002655 if (!location.isComplete()) {
2656 Log.w(TAG, "Dropping incomplete location: " + location);
2657 return;
2658 }
2659
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002660 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location);
2661 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location);
Mike Lockwooda4903f22010-02-17 06:42:23 -05002662 m.arg1 = (passive ? 1 : 0);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002663 mLocationHandler.sendMessageAtFrontOfQueue(m);
2664 }
2665
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002666
Laurent Tu75defb62012-11-01 16:21:52 -07002667 private static boolean shouldBroadcastSafe(
2668 Location loc, Location lastLoc, UpdateRecord record, long now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002669 // Always broadcast the first update
2670 if (lastLoc == null) {
2671 return true;
2672 }
2673
Nick Pellyf1be6862012-05-15 10:53:42 -07002674 // Check whether sufficient time has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002675 long minTime = record.mRealRequest.getFastestInterval();
David Christie1b9b7b12013-04-15 15:31:11 -07002676 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
2677 / NANOS_PER_MILLI;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002678 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002679 return false;
2680 }
2681
2682 // Check whether sufficient distance has been traveled
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002683 double minDistance = record.mRealRequest.getSmallestDisplacement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002684 if (minDistance > 0.0) {
2685 if (loc.distanceTo(lastLoc) <= minDistance) {
2686 return false;
2687 }
2688 }
2689
Laurent Tu75defb62012-11-01 16:21:52 -07002690 // Check whether sufficient number of udpates is left
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002691 if (record.mRealRequest.getNumUpdates() <= 0) {
Laurent Tu75defb62012-11-01 16:21:52 -07002692 return false;
2693 }
2694
2695 // Check whether the expiry date has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002696 return record.mRealRequest.getExpireAt() >= now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 }
2698
Mike Lockwooda4903f22010-02-17 06:42:23 -05002699 private void handleLocationChangedLocked(Location location, boolean passive) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002700 if (D) Log.d(TAG, "incoming location: " + location);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002701 long now = SystemClock.elapsedRealtime();
Mike Lockwooda4903f22010-02-17 06:42:23 -05002702 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
Laurent Tu60ec50a2012-10-04 17:00:10 -07002703 // Skip if the provider is unknown.
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002704 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002705 if (p == null) return;
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002706 updateLastLocationLocked(location, provider);
2707 // mLastLocation should have been updated from the updateLastLocationLocked call above.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002708 Location lastLocation = mLastLocation.get(provider);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002709 if (lastLocation == null) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002710 Log.e(TAG, "handleLocationChangedLocked() updateLastLocation failed");
2711 return;
Mike Lockwood4e50b782009-04-03 08:24:43 -07002712 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002713
David Christie1b9b7b12013-04-15 15:31:11 -07002714 // Update last known coarse interval location if enough time has passed.
2715 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider);
2716 if (lastLocationCoarseInterval == null) {
2717 lastLocationCoarseInterval = new Location(location);
2718 mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval);
2719 }
2720 long timeDiffNanos = location.getElapsedRealtimeNanos()
2721 - lastLocationCoarseInterval.getElapsedRealtimeNanos();
2722 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
2723 lastLocationCoarseInterval.set(location);
2724 }
2725 // Don't ever return a coarse location that is more recent than the allowed update
2726 // interval (i.e. don't allow an app to keep registering and unregistering for
2727 // location updates to overcome the minimum interval).
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002728 Location noGPSLocation =
David Christie1b9b7b12013-04-15 15:31:11 -07002729 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2730
Laurent Tu60ec50a2012-10-04 17:00:10 -07002731 // Skip if there are no UpdateRecords for this provider.
2732 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
2733 if (records == null || records.size() == 0) return;
2734
Victoria Lease09016ab2012-09-16 12:33:15 -07002735 // Fetch coarse location
2736 Location coarseLocation = null;
David Christie1b9b7b12013-04-15 15:31:11 -07002737 if (noGPSLocation != null) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002738 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
2739 }
2740
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002741 // Fetch latest status update time
2742 long newStatusUpdateTime = p.getStatusUpdateTime();
2743
David Christie2ff96af2014-01-30 16:09:37 -08002744 // Get latest status
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002745 Bundle extras = new Bundle();
2746 int status = p.getStatus(extras);
2747
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002748 ArrayList<Receiver> deadReceivers = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002749 ArrayList<UpdateRecord> deadUpdateRecords = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07002750
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002751 // Broadcast location or status to all listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002752 for (UpdateRecord r : records) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002753 Receiver receiver = r.mReceiver;
Mike Lockwood03ca2162010-04-01 08:10:09 -07002754 boolean receiverDead = false;
Nick Pelly4035f5a2012-08-17 14:43:49 -07002755
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002756 int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid);
2757 if (!isCurrentProfile(receiverUserId)
2758 && !isUidALocationProvider(receiver.mIdentity.mUid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002759 if (D) {
Victoria Lease269518e2012-10-29 08:25:39 -07002760 Log.d(TAG, "skipping loc update for background user " + receiverUserId +
Victoria Leaseb711d572012-10-02 13:14:11 -07002761 " (current user: " + mCurrentUserId + ", app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002762 receiver.mIdentity.mPackageName + ")");
Victoria Leaseb711d572012-10-02 13:14:11 -07002763 }
2764 continue;
2765 }
2766
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002767 if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) {
gomo48f1a642017-11-10 20:35:46 -08002768 if (D) {
2769 Log.d(TAG, "skipping loc update for blacklisted app: " +
2770 receiver.mIdentity.mPackageName);
2771 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07002772 continue;
2773 }
2774
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002775 if (!reportLocationAccessNoThrow(
2776 receiver.mIdentity.mPid,
2777 receiver.mIdentity.mUid,
2778 receiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002779 receiver.mAllowedResolutionLevel)) {
gomo48f1a642017-11-10 20:35:46 -08002780 if (D) {
2781 Log.d(TAG, "skipping loc update for no op app: " +
2782 receiver.mIdentity.mPackageName);
2783 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002784 continue;
2785 }
2786
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002787 Location notifyLocation;
Victoria Lease37425c32012-10-16 16:08:48 -07002788 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2789 notifyLocation = coarseLocation; // use coarse location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002790 } else {
Victoria Lease37425c32012-10-16 16:08:48 -07002791 notifyLocation = lastLocation; // use fine location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002792 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002793 if (notifyLocation != null) {
2794 Location lastLoc = r.mLastFixBroadcast;
Laurent Tu75defb62012-11-01 16:21:52 -07002795 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002796 if (lastLoc == null) {
2797 lastLoc = new Location(notifyLocation);
2798 r.mLastFixBroadcast = lastLoc;
2799 } else {
2800 lastLoc.set(notifyLocation);
2801 }
2802 if (!receiver.callLocationChangedLocked(notifyLocation)) {
2803 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
2804 receiverDead = true;
2805 }
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002806 r.mRealRequest.decrementNumUpdates();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002807 }
2808 }
2809
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002810 long prevStatusUpdateTime = r.mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002811 if ((newStatusUpdateTime > prevStatusUpdateTime) &&
Victoria Lease09016ab2012-09-16 12:33:15 -07002812 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002813
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002814 r.mLastStatusBroadcast = newStatusUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002815 if (!receiver.callStatusChangedLocked(provider, status, extras)) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002816 receiverDead = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002817 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
Mike Lockwood03ca2162010-04-01 08:10:09 -07002818 }
2819 }
2820
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002821 // track expired records
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002822 if (r.mRealRequest.getNumUpdates() <= 0 || r.mRealRequest.getExpireAt() < now) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002823 if (deadUpdateRecords == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002824 deadUpdateRecords = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002825 }
2826 deadUpdateRecords.add(r);
2827 }
2828 // track dead receivers
2829 if (receiverDead) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002830 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002831 deadReceivers = new ArrayList<>();
Mike Lockwood03ca2162010-04-01 08:10:09 -07002832 }
2833 if (!deadReceivers.contains(receiver)) {
2834 deadReceivers.add(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002835 }
2836 }
2837 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002838
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002839 // remove dead records and receivers outside the loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002840 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002841 for (Receiver receiver : deadReceivers) {
2842 removeUpdatesLocked(receiver);
2843 }
2844 }
2845 if (deadUpdateRecords != null) {
2846 for (UpdateRecord r : deadUpdateRecords) {
2847 r.disposeLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002848 }
Victoria Lease8b38b292012-12-04 15:04:43 -08002849 applyRequirementsLocked(provider);
2850 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002851 }
2852
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002853 /**
2854 * Updates last location with the given location
2855 *
2856 * @param location new location to update
2857 * @param provider Location provider to update for
2858 */
2859 private void updateLastLocationLocked(Location location, String provider) {
2860 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2861 Location lastNoGPSLocation;
2862 Location lastLocation = mLastLocation.get(provider);
2863 if (lastLocation == null) {
2864 lastLocation = new Location(provider);
2865 mLastLocation.put(provider, lastLocation);
2866 } else {
2867 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2868 if (noGPSLocation == null && lastNoGPSLocation != null) {
2869 // New location has no no-GPS location: adopt last no-GPS location. This is set
2870 // directly into location because we do not want to notify COARSE clients.
2871 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
2872 }
2873 }
2874 lastLocation.set(location);
2875 }
2876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002877 private class LocationWorkerHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08002878 public LocationWorkerHandler(Looper looper) {
2879 super(looper, null, true);
2880 }
2881
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002882 @Override
2883 public void handleMessage(Message msg) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002884 switch (msg.what) {
2885 case MSG_LOCATION_CHANGED:
2886 handleLocationChanged((Location) msg.obj, msg.arg1 == 1);
2887 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002888 }
2889 }
2890 }
2891
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002892 private boolean isMockProvider(String provider) {
2893 synchronized (mLock) {
2894 return mMockProviders.containsKey(provider);
2895 }
2896 }
2897
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002898 private void handleLocationChanged(Location location, boolean passive) {
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002899 // create a working copy of the incoming Location so that the service can modify it without
2900 // disturbing the caller's copy
2901 Location myLocation = new Location(location);
2902 String provider = myLocation.getProvider();
2903
2904 // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this
2905 // bit if location did not come from a mock provider because passive/fused providers can
2906 // forward locations from mock providers, and should not grant them legitimacy in doing so.
2907 if (!myLocation.isFromMockProvider() && isMockProvider(provider)) {
2908 myLocation.setIsFromMockProvider(true);
2909 }
Jeff Sharkey5e613312012-01-30 11:16:20 -08002910
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002911 synchronized (mLock) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08002912 if (isAllowedByCurrentUserSettingsLocked(provider)) {
2913 if (!passive) {
2914 // notify passive provider of the new location
2915 mPassiveProvider.updateLocation(myLocation);
2916 }
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002917 handleLocationChangedLocked(myLocation, passive);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002918 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002919 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002920 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002921
Mike Lockwoode97ae402010-09-29 15:23:46 -04002922 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
2923 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002924 public void onPackageDisappeared(String packageName, int reason) {
2925 // remove all receivers associated with this package name
2926 synchronized (mLock) {
2927 ArrayList<Receiver> deadReceivers = null;
2928
2929 for (Receiver receiver : mReceivers.values()) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002930 if (receiver.mIdentity.mPackageName.equals(packageName)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002931 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002932 deadReceivers = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002933 }
2934 deadReceivers.add(receiver);
2935 }
2936 }
2937
2938 // perform removal outside of mReceivers loop
2939 if (deadReceivers != null) {
2940 for (Receiver receiver : deadReceivers) {
2941 removeUpdatesLocked(receiver);
2942 }
2943 }
2944 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002945 }
Mike Lockwoode97ae402010-09-29 15:23:46 -04002946 };
2947
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002948 // Geocoder
2949
Nick Pellye0fd6932012-07-11 10:26:13 -07002950 @Override
Mike Lockwoode15735a2010-09-20 17:48:47 -04002951 public boolean geocoderIsPresent() {
Mark Vandevoorde01ac80b2010-05-21 15:43:26 -07002952 return mGeocodeProvider != null;
2953 }
2954
Nick Pellye0fd6932012-07-11 10:26:13 -07002955 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002956 public String getFromLocation(double latitude, double longitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002957 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002958 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002959 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
2960 params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002961 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002962 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002963 }
2964
Mike Lockwooda55c3212009-04-15 11:10:11 -04002965
Nick Pellye0fd6932012-07-11 10:26:13 -07002966 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002967 public String getFromLocationName(String locationName,
Mike Lockwooda55c3212009-04-15 11:10:11 -04002968 double lowerLeftLatitude, double lowerLeftLongitude,
2969 double upperRightLatitude, double upperRightLongitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002970 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002971
2972 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002973 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
2974 lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
2975 maxResults, params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002976 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002977 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002978 }
2979
2980 // Mock Providers
2981
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002982 private boolean canCallerAccessMockLocation(String opPackageName) {
2983 return mAppOps.noteOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(),
2984 opPackageName) == AppOpsManager.MODE_ALLOWED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002985 }
2986
Nick Pellye0fd6932012-07-11 10:26:13 -07002987 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002988 public void addTestProvider(String name, ProviderProperties properties, String opPackageName) {
2989 if (!canCallerAccessMockLocation(opPackageName)) {
2990 return;
2991 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002992
Mike Lockwooda4903f22010-02-17 06:42:23 -05002993 if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
2994 throw new IllegalArgumentException("Cannot mock the passive location provider");
2995 }
2996
Mike Lockwood86328a92009-10-23 08:38:25 -04002997 long identity = Binder.clearCallingIdentity();
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002998 synchronized (mLock) {
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002999 // remove the real provider if we are replacing GPS or network provider
3000 if (LocationManager.GPS_PROVIDER.equals(name)
Nick Pelly1332b532012-08-21 16:25:47 -07003001 || LocationManager.NETWORK_PROVIDER.equals(name)
3002 || LocationManager.FUSED_PROVIDER.equals(name)) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05003003 LocationProviderInterface p = mProvidersByName.get(name);
3004 if (p != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003005 removeProviderLocked(p);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003006 }
3007 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09003008 addTestProviderLocked(name, properties);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003009 updateProvidersLocked();
3010 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003011 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003012 }
3013
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09003014 private void addTestProviderLocked(String name, ProviderProperties properties) {
3015 if (mProvidersByName.get(name) != null) {
3016 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
3017 }
3018 MockProvider provider = new MockProvider(name, this, properties);
3019 addProviderLocked(provider);
3020 mMockProviders.put(name, provider);
3021 mLastLocation.put(name, null);
3022 mLastLocationCoarseInterval.put(name, null);
3023 }
3024
Nick Pellye0fd6932012-07-11 10:26:13 -07003025 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003026 public void removeTestProvider(String provider, String opPackageName) {
3027 if (!canCallerAccessMockLocation(opPackageName)) {
3028 return;
3029 }
3030
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003031 synchronized (mLock) {
Tom O'Neill07ee5d12014-03-03 17:48:35 -08003032
3033 // These methods can't be called after removing the test provider, so first make sure
Tom O'Neillfe6d3c52014-03-04 08:26:17 -08003034 // we don't leave anything dangling.
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003035 clearTestProviderEnabled(provider, opPackageName);
3036 clearTestProviderLocation(provider, opPackageName);
3037 clearTestProviderStatus(provider, opPackageName);
Tom O'Neill07ee5d12014-03-03 17:48:35 -08003038
You Kima6d0b6f2012-10-28 03:58:44 +09003039 MockProvider mockProvider = mMockProviders.remove(provider);
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003040 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003041 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3042 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003043 long identity = Binder.clearCallingIdentity();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003044 removeProviderLocked(mProvidersByName.get(provider));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003045
3046 // reinstate real provider if available
3047 LocationProviderInterface realProvider = mRealProviders.get(provider);
3048 if (realProvider != null) {
3049 addProviderLocked(realProvider);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003050 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003051 mLastLocation.put(provider, null);
David Christie1b9b7b12013-04-15 15:31:11 -07003052 mLastLocationCoarseInterval.put(provider, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003053 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003054 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003055 }
3056 }
3057
Nick Pellye0fd6932012-07-11 10:26:13 -07003058 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003059 public void setTestProviderLocation(String provider, Location loc, String opPackageName) {
3060 if (!canCallerAccessMockLocation(opPackageName)) {
3061 return;
3062 }
3063
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003064 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003065 MockProvider mockProvider = mMockProviders.get(provider);
3066 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003067 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3068 }
Tom O'Neilla206a0f2016-12-15 10:26:28 -08003069
3070 // Ensure that the location is marked as being mock. There's some logic to do this in
3071 // handleLocationChanged(), but it fails if loc has the wrong provider (bug 33091107).
3072 Location mock = new Location(loc);
3073 mock.setIsFromMockProvider(true);
3074
3075 if (!TextUtils.isEmpty(loc.getProvider()) && !provider.equals(loc.getProvider())) {
3076 // The location has an explicit provider that is different from the mock provider
3077 // name. The caller may be trying to fool us via bug 33091107.
3078 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
3079 provider + "!=" + loc.getProvider());
3080 }
3081
Mike Lockwood95427cd2009-05-07 13:27:54 -04003082 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
3083 long identity = Binder.clearCallingIdentity();
Tom O'Neilla206a0f2016-12-15 10:26:28 -08003084 mockProvider.setLocation(mock);
Mike Lockwood95427cd2009-05-07 13:27:54 -04003085 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086 }
3087 }
3088
Nick Pellye0fd6932012-07-11 10:26:13 -07003089 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003090 public void clearTestProviderLocation(String provider, String opPackageName) {
3091 if (!canCallerAccessMockLocation(opPackageName)) {
3092 return;
3093 }
3094
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003095 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003096 MockProvider mockProvider = mMockProviders.get(provider);
3097 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003098 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3099 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003100 mockProvider.clearLocation();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003101 }
3102 }
3103
Nick Pellye0fd6932012-07-11 10:26:13 -07003104 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003105 public void setTestProviderEnabled(String provider, boolean enabled, String opPackageName) {
3106 if (!canCallerAccessMockLocation(opPackageName)) {
3107 return;
3108 }
3109
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003110 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003111 MockProvider mockProvider = mMockProviders.get(provider);
3112 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003113 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3114 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003115 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003116 if (enabled) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003117 mockProvider.enable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003118 mEnabledProviders.add(provider);
3119 mDisabledProviders.remove(provider);
3120 } else {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003121 mockProvider.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003122 mEnabledProviders.remove(provider);
3123 mDisabledProviders.add(provider);
3124 }
3125 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003126 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003127 }
3128 }
3129
Nick Pellye0fd6932012-07-11 10:26:13 -07003130 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003131 public void clearTestProviderEnabled(String provider, String opPackageName) {
3132 if (!canCallerAccessMockLocation(opPackageName)) {
3133 return;
3134 }
3135
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003136 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003137 MockProvider mockProvider = mMockProviders.get(provider);
3138 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003139 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3140 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003141 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003142 mEnabledProviders.remove(provider);
3143 mDisabledProviders.remove(provider);
3144 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003145 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003146 }
3147 }
3148
Nick Pellye0fd6932012-07-11 10:26:13 -07003149 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003150 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime,
3151 String opPackageName) {
3152 if (!canCallerAccessMockLocation(opPackageName)) {
3153 return;
3154 }
3155
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003156 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003157 MockProvider mockProvider = mMockProviders.get(provider);
3158 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003159 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3160 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003161 mockProvider.setStatus(status, extras, updateTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 }
3163 }
3164
Nick Pellye0fd6932012-07-11 10:26:13 -07003165 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003166 public void clearTestProviderStatus(String provider, String opPackageName) {
3167 if (!canCallerAccessMockLocation(opPackageName)) {
3168 return;
3169 }
3170
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003171 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003172 MockProvider mockProvider = mMockProviders.get(provider);
3173 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003174 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3175 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003176 mockProvider.clearStatus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003177 }
3178 }
3179
3180 private void log(String log) {
3181 if (Log.isLoggable(TAG, Log.VERBOSE)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003182 Slog.d(TAG, log);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003183 }
3184 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003185
3186 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003187 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003188 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Nick Pellye0fd6932012-07-11 10:26:13 -07003189
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003190 synchronized (mLock) {
Siddharth Raybb608c82017-03-16 11:33:34 -07003191 if (args.length > 0 && args[0].equals("--gnssmetrics")) {
3192 if (mGnssMetricsProvider != null) {
3193 pw.append(mGnssMetricsProvider.getGnssMetricsAsProtoString());
3194 }
3195 return;
3196 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003197 pw.println("Current Location Manager state:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003198 pw.println(" Location Listeners:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003199 for (Receiver receiver : mReceivers.values()) {
3200 pw.println(" " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003201 }
David Christie2ff96af2014-01-30 16:09:37 -08003202 pw.println(" Active Records by Provider:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003203 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
3204 pw.println(" " + entry.getKey() + ":");
3205 for (UpdateRecord record : entry.getValue()) {
3206 pw.println(" " + record);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003207 }
3208 }
Wyatt Riley11cc7492018-01-17 08:48:27 -08003209 pw.println(" Active GnssMeasurement Listeners:");
3210 for (Identity identity : mGnssMeasurementsListeners.values()) {
3211 pw.println(" " + identity.mPid + " " + identity.mUid + " "
3212 + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
3213 }
3214 pw.println(" Active GnssNavigationMessage Listeners:");
3215 for (Identity identity : mGnssNavigationMessageListeners.values()) {
3216 pw.println(" " + identity.mPid + " " + identity.mUid + " "
3217 + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
3218 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003219 pw.println(" Overlay Provider Packages:");
3220 for (LocationProviderInterface provider : mProviders) {
3221 if (provider instanceof LocationProviderProxy) {
3222 pw.println(" " + provider.getName() + ": "
3223 + ((LocationProviderProxy) provider).getConnectedPackageName());
3224 }
3225 }
David Christie2ff96af2014-01-30 16:09:37 -08003226 pw.println(" Historical Records by Provider:");
3227 for (Map.Entry<PackageProviderKey, PackageStatistics> entry
3228 : mRequestStatistics.statistics.entrySet()) {
3229 PackageProviderKey key = entry.getKey();
3230 PackageStatistics stats = entry.getValue();
3231 pw.println(" " + key.packageName + ": " + key.providerName + ": " + stats);
3232 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003233 pw.println(" Last Known Locations:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003234 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
3235 String provider = entry.getKey();
3236 Location location = entry.getValue();
3237 pw.println(" " + provider + ": " + location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003238 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003239
David Christie1b9b7b12013-04-15 15:31:11 -07003240 pw.println(" Last Known Locations Coarse Intervals:");
3241 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
3242 String provider = entry.getKey();
3243 Location location = entry.getValue();
3244 pw.println(" " + provider + ": " + location);
3245 }
3246
Nick Pellye0fd6932012-07-11 10:26:13 -07003247 mGeofenceManager.dump(pw);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003249 if (mEnabledProviders.size() > 0) {
3250 pw.println(" Enabled Providers:");
3251 for (String i : mEnabledProviders) {
3252 pw.println(" " + i);
3253 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003255 }
3256 if (mDisabledProviders.size() > 0) {
3257 pw.println(" Disabled Providers:");
3258 for (String i : mDisabledProviders) {
3259 pw.println(" " + i);
3260 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003261 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07003262 pw.append(" ");
3263 mBlacklist.dump(pw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003264 if (mMockProviders.size() > 0) {
3265 pw.println(" Mock Providers:");
3266 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003267 i.getValue().dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003268 }
3269 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003270
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08003271 if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
3272 pw.println(" Throttling Whitelisted Packages:");
3273 for (String packageName : mBackgroundThrottlePackageWhitelist) {
3274 pw.println(" " + packageName);
3275 }
3276 }
3277
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003278 pw.append(" fudger: ");
gomo48f1a642017-11-10 20:35:46 -08003279 mLocationFudger.dump(fd, pw, args);
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003280
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003281 if (args.length > 0 && "short".equals(args[0])) {
3282 return;
3283 }
gomo48f1a642017-11-10 20:35:46 -08003284 for (LocationProviderInterface provider : mProviders) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003285 pw.print(provider.getName() + " Internal State");
3286 if (provider instanceof LocationProviderProxy) {
3287 LocationProviderProxy proxy = (LocationProviderProxy) provider;
3288 pw.print(" (" + proxy.getConnectedPackageName() + ")");
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003289 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003290 pw.println(":");
3291 provider.dump(fd, pw, args);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003292 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08003293 if (mGnssBatchingInProgress) {
3294 pw.println(" GNSS batching in progress");
3295 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003296 }
3297 }
3298}