blob: da19e27b5b823db513be940c8bf623f4775efc6c [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;
Soonil Nagarkar94749f72018-11-08 11:46:43 -080020import static android.provider.Settings.Global.LOCATION_DISABLE_STATUS_CALLBACKS;
Maggieaa080f92018-01-04 15:35:11 -080021
Wyatt Rileycf879db2017-01-12 13:57:38 -080022import android.annotation.NonNull;
Wyatt Riley49097c02018-03-15 09:14:43 -070023import android.annotation.Nullable;
Maggieaa080f92018-01-04 15:35:11 -080024import android.app.ActivityManager;
25import android.app.AppOpsManager;
26import android.app.PendingIntent;
27import android.content.BroadcastReceiver;
28import android.content.ContentResolver;
29import android.content.Context;
30import android.content.Intent;
31import android.content.IntentFilter;
32import android.content.pm.ApplicationInfo;
33import android.content.pm.PackageInfo;
34import android.content.pm.PackageManager;
35import android.content.pm.PackageManager.NameNotFoundException;
36import android.content.pm.PackageManagerInternal;
37import android.content.pm.ResolveInfo;
38import android.content.pm.Signature;
39import android.content.res.Resources;
40import android.database.ContentObserver;
41import android.hardware.location.ActivityRecognitionHardware;
42import android.location.Address;
43import android.location.Criteria;
44import android.location.GeocoderParams;
45import android.location.Geofence;
46import android.location.IBatchedLocationCallback;
47import android.location.IGnssMeasurementsListener;
48import android.location.IGnssNavigationMessageListener;
49import android.location.IGnssStatusListener;
Maggieaa080f92018-01-04 15:35:11 -080050import android.location.IGpsGeofenceHardware;
51import android.location.ILocationListener;
52import android.location.ILocationManager;
53import android.location.INetInitiatedListener;
54import android.location.Location;
55import android.location.LocationManager;
56import android.location.LocationProvider;
57import android.location.LocationRequest;
58import android.os.Binder;
59import android.os.Bundle;
60import android.os.Handler;
61import android.os.IBinder;
62import android.os.Looper;
63import android.os.Message;
64import android.os.PowerManager;
65import android.os.Process;
66import android.os.RemoteException;
67import android.os.SystemClock;
68import android.os.UserHandle;
69import android.os.UserManager;
70import android.os.WorkSource;
Narayan Kamath32684dd2018-01-08 17:32:51 +000071import android.os.WorkSource.WorkChain;
Maggieaa080f92018-01-04 15:35:11 -080072import android.provider.Settings;
73import android.text.TextUtils;
Soonil Nagarkar681d7112017-02-23 17:14:16 -080074import android.util.ArrayMap;
Soonil Nagarkar2b565df2017-02-14 13:33:23 -080075import android.util.ArraySet;
Maggieaa080f92018-01-04 15:35:11 -080076import android.util.EventLog;
77import android.util.Log;
78import android.util.Slog;
Yu-Han Yanga4d250e2018-10-02 21:29:20 -070079
destradaaea8a8a62014-06-23 18:19:03 -070080import com.android.internal.content.PackageMonitor;
81import com.android.internal.location.ProviderProperties;
82import com.android.internal.location.ProviderRequest;
83import com.android.internal.os.BackgroundThread;
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -070084import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060085import com.android.internal.util.DumpUtils;
destradaaa4fa3b52014-07-09 10:46:39 -070086import com.android.server.location.ActivityRecognitionProxy;
destradaaea8a8a62014-06-23 18:19:03 -070087import com.android.server.location.GeocoderProxy;
88import com.android.server.location.GeofenceManager;
89import com.android.server.location.GeofenceProxy;
Yu-Han Yang3557cc72018-03-21 12:48:36 -070090import com.android.server.location.GnssBatchingProvider;
Lifu Tang818aa2c2016-02-01 01:52:00 -080091import com.android.server.location.GnssLocationProvider;
92import com.android.server.location.GnssMeasurementsProvider;
93import com.android.server.location.GnssNavigationMessageProvider;
Anil Admal75b9fd62018-11-28 11:22:50 -080094import com.android.server.location.GnssStatusListenerHelper;
destradaaea8a8a62014-06-23 18:19:03 -070095import com.android.server.location.LocationBlacklist;
96import com.android.server.location.LocationFudger;
97import com.android.server.location.LocationProviderInterface;
98import com.android.server.location.LocationProviderProxy;
99import com.android.server.location.LocationRequestStatistics;
100import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
101import com.android.server.location.LocationRequestStatistics.PackageStatistics;
102import com.android.server.location.MockProvider;
103import com.android.server.location.PassiveProvider;
Yu-Han Yanga4d250e2018-10-02 21:29:20 -0700104
Mike Lockwood43e33f22010-03-26 10:41:48 -0400105import java.io.FileDescriptor;
106import java.io.PrintWriter;
107import java.util.ArrayList;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700108import java.util.Arrays;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400109import java.util.HashMap;
110import java.util.HashSet;
111import java.util.List;
112import java.util.Map;
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800113import java.util.Map.Entry;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800114import java.util.NoSuchElementException;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400115import java.util.Set;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116
117/**
118 * The service class that manages LocationProviders and issues location
119 * updates and alerts.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 */
Victoria Lease5cd731a2012-12-19 15:04:21 -0800121public class LocationManagerService extends ILocationManager.Stub {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122 private static final String TAG = "LocationManagerService";
JP Abgrallf79811e72013-02-01 18:45:05 -0800123 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700124
Olivier Gaillard7a222662017-11-20 16:07:24 +0000125 private static final String WAKELOCK_KEY = "*location*";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126
Victoria Lease37425c32012-10-16 16:08:48 -0700127 // Location resolution level: no location data whatsoever
128 private static final int RESOLUTION_LEVEL_NONE = 0;
129 // Location resolution level: coarse location data only
130 private static final int RESOLUTION_LEVEL_COARSE = 1;
131 // Location resolution level: fine location data
132 private static final int RESOLUTION_LEVEL_FINE = 2;
133
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134 private static final String ACCESS_MOCK_LOCATION =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700135 android.Manifest.permission.ACCESS_MOCK_LOCATION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700137 android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
Mike Lockwood275555c2009-05-01 11:30:34 -0400138 private static final String INSTALL_LOCATION_PROVIDER =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700139 android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
140
141 private static final String NETWORK_LOCATION_SERVICE_ACTION =
Stan Chesnutt39062dd2013-07-22 14:33:30 -0700142 "com.android.location.service.v3.NetworkLocationProvider";
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700143 private static final String FUSED_LOCATION_SERVICE_ACTION =
144 "com.android.location.service.FusedLocationProvider";
145
146 private static final int MSG_LOCATION_CHANGED = 1;
147
David Christie1b9b7b12013-04-15 15:31:11 -0700148 private static final long NANOS_PER_MILLI = 1000000L;
149
David Christie0b837452013-07-29 16:02:13 -0700150 // The maximum interval a location request can have and still be considered "high power".
151 private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
152
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700153 private static final int FOREGROUND_IMPORTANCE_CUTOFF
gomo48f1a642017-11-10 20:35:46 -0800154 = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700155
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800156 // default background throttling interval if not overriden in settings
Soonil Nagarkarde6780a2017-02-07 10:39:41 -0800157 private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800158
Wei Wangdd070f22018-06-21 11:29:40 -0700159 // Default value for maximum age of last location returned to applications with foreground-only
160 // location permissions.
161 private static final long DEFAULT_LAST_LOCATION_MAX_AGE_MS = 20 * 60 * 1000;
162
Nick Pellyf1be6862012-05-15 10:53:42 -0700163 // Location Providers may sometimes deliver location updates
164 // slightly faster that requested - provide grace period so
165 // we don't unnecessarily filter events that are otherwise on
166 // time
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700167 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
Nick Pellyf1be6862012-05-15 10:53:42 -0700168
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700169 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
170
171 private final Context mContext;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800172 private final AppOpsManager mAppOps;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700173
174 // used internally for synchronization
175 private final Object mLock = new Object();
176
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700177 // --- fields below are final after systemRunning() ---
Nick Pelly74fa7ea2012-08-13 19:36:38 -0700178 private LocationFudger mLocationFudger;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700179 private GeofenceManager mGeofenceManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700180 private PackageManager mPackageManager;
Victoria Lease0aa28602013-05-29 15:28:26 -0700181 private PowerManager mPowerManager;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800182 private ActivityManager mActivityManager;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700183 private UserManager mUserManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700184 private GeocoderProxy mGeocodeProvider;
Anil Admal75b9fd62018-11-28 11:22:50 -0800185 private GnssStatusListenerHelper mGnssStatusProvider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700186 private INetInitiatedListener mNetInitiatedListener;
187 private LocationWorkerHandler mLocationHandler;
Nick Pelly4035f5a2012-08-17 14:43:49 -0700188 private PassiveProvider mPassiveProvider; // track passive provider for special cases
189 private LocationBlacklist mBlacklist;
Lifu Tang818aa2c2016-02-01 01:52:00 -0800190 private GnssMeasurementsProvider mGnssMeasurementsProvider;
191 private GnssNavigationMessageProvider mGnssNavigationMessageProvider;
Wei Liu5241a4c2015-05-11 14:00:36 -0700192 private IGpsGeofenceHardware mGpsGeofenceProxy;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700193
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700194 // --- fields below are protected by mLock ---
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 // Set of providers that are explicitly enabled
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700196 // Only used by passive, fused & test. Network & GPS are controlled separately, and not listed.
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800197 private final Set<String> mEnabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198
199 // Set of providers that are explicitly disabled
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800200 private final Set<String> mDisabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700202 // Mock (test) providers
203 private final HashMap<String, MockProvider> mMockProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800204 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700206 // all receivers
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800207 private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700209 // currently installed providers (with mocks replacing real providers)
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500210 private final ArrayList<LocationProviderInterface> mProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800211 new ArrayList<>();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400212
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700213 // real providers, saved here when mocked out
214 private final HashMap<String, LocationProviderInterface> mRealProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800215 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700217 // mapping from provider name to provider
218 private final HashMap<String, LocationProviderInterface> mProvidersByName =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800219 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700221 // mapping from provider name to all its UpdateRecords
222 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800223 new HashMap<>();
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700224
David Christie2ff96af2014-01-30 16:09:37 -0800225 private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics();
226
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700227 // mapping from provider name to last known location
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800228 private final HashMap<String, Location> mLastLocation = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229
David Christie1b9b7b12013-04-15 15:31:11 -0700230 // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
231 // locations stored here are not fudged for coarse permissions.
232 private final HashMap<String, Location> mLastLocationCoarseInterval =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800233 new HashMap<>();
David Christie1b9b7b12013-04-15 15:31:11 -0700234
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800235 // all providers that operate over proxy, for authorizing incoming location and whitelisting
236 // throttling
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700237 private final ArrayList<LocationProviderProxy> mProxyProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800238 new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800240 private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800241
Wyatt Riley11cc7492018-01-17 08:48:27 -0800242 private final ArrayMap<IBinder, Identity> mGnssMeasurementsListeners = new ArrayMap<>();
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800243
Wyatt Riley11cc7492018-01-17 08:48:27 -0800244 private final ArrayMap<IBinder, Identity>
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800245 mGnssNavigationMessageListeners = new ArrayMap<>();
246
Victoria Lease38389b62012-09-30 11:44:22 -0700247 // current active user on the device - other users are denied location data
Xiaohui Chena4490622015-09-22 15:29:31 -0700248 private int mCurrentUserId = UserHandle.USER_SYSTEM;
gomo48f1a642017-11-10 20:35:46 -0800249 private int[] mCurrentUserProfiles = new int[]{UserHandle.USER_SYSTEM};
Victoria Lease38389b62012-09-30 11:44:22 -0700250
Wei Wangdd070f22018-06-21 11:29:40 -0700251 // Maximum age of last location returned to clients with foreground-only location permissions.
252 private long mLastLocationMaxAgeMs;
253
Lifu Tang9363b942016-02-16 18:07:00 -0800254 private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;
Lifu Tang82f893d2016-01-21 18:15:33 -0800255
Siddharth Raybb608c82017-03-16 11:33:34 -0700256 private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;
Wyatt Rileyaa420d52017-07-03 15:14:42 -0700257
Yu-Han Yang3557cc72018-03-21 12:48:36 -0700258 private GnssBatchingProvider mGnssBatchingProvider;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800259 private IBatchedLocationCallback mGnssBatchingCallback;
260 private LinkedCallback mGnssBatchingDeathCallback;
261 private boolean mGnssBatchingInProgress = false;
262
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700263 public LocationManagerService(Context context) {
264 super();
265 mContext = context;
gomo48f1a642017-11-10 20:35:46 -0800266 mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800267
Svet Ganovadc1cf42015-06-15 16:36:24 -0700268 // Let the package manager query which are the default location
269 // providers as they get certain permissions granted by default.
270 PackageManagerInternal packageManagerInternal = LocalServices.getService(
271 PackageManagerInternal.class);
272 packageManagerInternal.setLocationPackagesProvider(
273 new PackageManagerInternal.PackagesProvider() {
274 @Override
275 public String[] getPackages(int userId) {
276 return mContext.getResources().getStringArray(
277 com.android.internal.R.array.config_locationProviderPackageNames);
278 }
279 });
280
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700281 if (D) Log.d(TAG, "Constructed");
282
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700283 // most startup is deferred until systemRunning()
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700284 }
285
Svetoslav Ganova0027152013-06-25 14:59:53 -0700286 public void systemRunning() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700287 synchronized (mLock) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700288 if (D) Log.d(TAG, "systemRunning()");
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700289
Victoria Lease5cd731a2012-12-19 15:04:21 -0800290 // fetch package manager
291 mPackageManager = mContext.getPackageManager();
292
Victoria Lease0aa28602013-05-29 15:28:26 -0700293 // fetch power manager
294 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
Victoria Lease5cd731a2012-12-19 15:04:21 -0800295
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800296 // fetch activity manager
297 mActivityManager
298 = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
299
Victoria Lease5cd731a2012-12-19 15:04:21 -0800300 // prepare worker thread
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700301 mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper());
Victoria Lease5cd731a2012-12-19 15:04:21 -0800302
303 // prepare mLocationHandler's dependents
304 mLocationFudger = new LocationFudger(mContext, mLocationHandler);
305 mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
306 mBlacklist.init();
307 mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
308
Dianne Hackbornc2293022013-02-06 23:14:49 -0800309 // Monitor for app ops mode changes.
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700310 AppOpsManager.OnOpChangedListener callback
311 = new AppOpsManager.OnOpChangedInternalListener() {
312 public void onOpChanged(int op, String packageName) {
Dianne Hackbornc2293022013-02-06 23:14:49 -0800313 synchronized (mLock) {
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700314 for (Receiver receiver : mReceivers.values()) {
315 receiver.updateMonitoring(true);
316 }
Dianne Hackbornc2293022013-02-06 23:14:49 -0800317 applyAllProviderRequirementsLocked();
318 }
319 }
320 };
Wei Wangdd070f22018-06-21 11:29:40 -0700321 mAppOps.startWatchingMode(AppOpsManager.OP_COARSE_LOCATION, null,
322 AppOpsManager.WATCH_FOREGROUND_CHANGES, callback);
Dianne Hackbornc2293022013-02-06 23:14:49 -0800323
David Christieb870dbf2015-06-22 12:42:53 -0700324 PackageManager.OnPermissionsChangedListener permissionListener
325 = new PackageManager.OnPermissionsChangedListener() {
326 @Override
327 public void onPermissionsChanged(final int uid) {
328 synchronized (mLock) {
329 applyAllProviderRequirementsLocked();
330 }
331 }
332 };
333 mPackageManager.addOnPermissionsChangeListener(permissionListener);
334
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800335 // listen for background/foreground changes
336 ActivityManager.OnUidImportanceListener uidImportanceListener
337 = new ActivityManager.OnUidImportanceListener() {
338 @Override
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700339 public void onUidImportance(final int uid, final int importance) {
340 mLocationHandler.post(new Runnable() {
341 @Override
342 public void run() {
343 onUidImportanceChanged(uid, importance);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800344 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700345 });
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800346 }
347 };
348 mActivityManager.addOnUidImportanceListener(uidImportanceListener,
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700349 FOREGROUND_IMPORTANCE_CUTOFF);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800350
Amith Yamasanib27528d2014-06-05 15:02:10 -0700351 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
352 updateUserProfiles(mCurrentUserId);
353
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800354 updateBackgroundThrottlingWhitelistLocked();
Wei Wangdd070f22018-06-21 11:29:40 -0700355 updateLastLocationMaxAgeLocked();
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800356
Victoria Lease5cd731a2012-12-19 15:04:21 -0800357 // prepare providers
358 loadProvidersLocked();
359 updateProvidersLocked();
360 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700361
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700362 // listen for settings changes
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700363 mContext.getContentResolver().registerContentObserver(
Laurent Tu75defb62012-11-01 16:21:52 -0700364 Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700365 new ContentObserver(mLocationHandler) {
Victoria Lease5cd731a2012-12-19 15:04:21 -0800366 @Override
367 public void onChange(boolean selfChange) {
368 synchronized (mLock) {
369 updateProvidersLocked();
370 }
371 }
372 }, UserHandle.USER_ALL);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800373 mContext.getContentResolver().registerContentObserver(
374 Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS),
375 true,
376 new ContentObserver(mLocationHandler) {
377 @Override
378 public void onChange(boolean selfChange) {
379 synchronized (mLock) {
380 updateProvidersLocked();
381 }
382 }
383 }, UserHandle.USER_ALL);
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800384 mContext.getContentResolver().registerContentObserver(
Wei Wangdd070f22018-06-21 11:29:40 -0700385 Settings.Global.getUriFor(Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS),
386 true,
387 new ContentObserver(mLocationHandler) {
388 @Override
389 public void onChange(boolean selfChange) {
390 synchronized (mLock) {
391 updateLastLocationMaxAgeLocked();
392 }
393 }
394 }
395 );
396 mContext.getContentResolver().registerContentObserver(
gomo48f1a642017-11-10 20:35:46 -0800397 Settings.Global.getUriFor(
398 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
399 true,
400 new ContentObserver(mLocationHandler) {
401 @Override
402 public void onChange(boolean selfChange) {
403 synchronized (mLock) {
404 updateBackgroundThrottlingWhitelistLocked();
405 updateProvidersLocked();
406 }
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800407 }
gomo48f1a642017-11-10 20:35:46 -0800408 }, UserHandle.USER_ALL);
Wei Wangdd070f22018-06-21 11:29:40 -0700409
Victoria Lease5cd731a2012-12-19 15:04:21 -0800410 mPackageMonitor.register(mContext, mLocationHandler.getLooper(), true);
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700411
Victoria Lease38389b62012-09-30 11:44:22 -0700412 // listen for user change
413 IntentFilter intentFilter = new IntentFilter();
414 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700415 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
416 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
destradaab9026982015-08-27 17:34:54 -0700417 intentFilter.addAction(Intent.ACTION_SHUTDOWN);
Victoria Lease38389b62012-09-30 11:44:22 -0700418
419 mContext.registerReceiverAsUser(new BroadcastReceiver() {
420 @Override
421 public void onReceive(Context context, Intent intent) {
422 String action = intent.getAction();
423 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
424 switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
Amith Yamasanib27528d2014-06-05 15:02:10 -0700425 } else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)
426 || Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
427 updateUserProfiles(mCurrentUserId);
destradaab9026982015-08-27 17:34:54 -0700428 } else if (Intent.ACTION_SHUTDOWN.equals(action)) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700429 // shutdown only if UserId indicates whole system, not just one user
gomo48f1a642017-11-10 20:35:46 -0800430 if (D) Log.d(TAG, "Shutdown received with UserId: " + getSendingUserId());
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700431 if (getSendingUserId() == UserHandle.USER_ALL) {
432 shutdownComponents();
433 }
Victoria Lease38389b62012-09-30 11:44:22 -0700434 }
435 }
Victoria Lease5cd731a2012-12-19 15:04:21 -0800436 }, UserHandle.ALL, intentFilter, null, mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700437 }
438
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700439 private void onUidImportanceChanged(int uid, int importance) {
440 boolean foreground = isImportanceForeground(importance);
441 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
442 synchronized (mLock) {
443 for (Entry<String, ArrayList<UpdateRecord>> entry
gomo48f1a642017-11-10 20:35:46 -0800444 : mRecordsByProvider.entrySet()) {
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700445 String provider = entry.getKey();
446 for (UpdateRecord record : entry.getValue()) {
447 if (record.mReceiver.mIdentity.mUid == uid
gomo48f1a642017-11-10 20:35:46 -0800448 && record.mIsForegroundUid != foreground) {
449 if (D) {
450 Log.d(TAG, "request from uid " + uid + " is now "
451 + (foreground ? "foreground" : "background)"));
452 }
Wyatt Rileyf7075e02018-04-12 17:54:26 -0700453 record.updateForeground(foreground);
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700454
455 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
456 affectedProviders.add(provider);
457 }
458 }
459 }
460 }
461 for (String provider : affectedProviders) {
462 applyRequirementsLocked(provider);
463 }
464
Wyatt Riley11cc7492018-01-17 08:48:27 -0800465 for (Entry<IBinder, Identity> entry : mGnssMeasurementsListeners.entrySet()) {
Anil Admal75b9fd62018-11-28 11:22:50 -0800466 Identity callerIdentity = entry.getValue();
467 if (callerIdentity.mUid == uid) {
gomo48f1a642017-11-10 20:35:46 -0800468 if (D) {
469 Log.d(TAG, "gnss measurements listener from uid " + uid
470 + " is now " + (foreground ? "foreground" : "background)"));
471 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700472 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800473 mGnssMeasurementsProvider.addListener(
Anil Admal75b9fd62018-11-28 11:22:50 -0800474 IGnssMeasurementsListener.Stub.asInterface(entry.getKey()),
475 callerIdentity.mUid, callerIdentity.mPackageName);
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700476 } else {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800477 mGnssMeasurementsProvider.removeListener(
478 IGnssMeasurementsListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700479 }
480 }
481 }
482
Wyatt Riley11cc7492018-01-17 08:48:27 -0800483 for (Entry<IBinder, Identity> entry : mGnssNavigationMessageListeners.entrySet()) {
Anil Admal75b9fd62018-11-28 11:22:50 -0800484 Identity callerIdentity = entry.getValue();
485 if (callerIdentity.mUid == uid) {
gomo48f1a642017-11-10 20:35:46 -0800486 if (D) {
487 Log.d(TAG, "gnss navigation message listener from uid "
488 + uid + " is now "
489 + (foreground ? "foreground" : "background)"));
490 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700491 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800492 mGnssNavigationMessageProvider.addListener(
Anil Admal75b9fd62018-11-28 11:22:50 -0800493 IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()),
494 callerIdentity.mUid, callerIdentity.mPackageName);
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700495 } else {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800496 mGnssNavigationMessageProvider.removeListener(
497 IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700498 }
499 }
500 }
Anil Admal75b9fd62018-11-28 11:22:50 -0800501
502 // TODO(b/120449926): The GNSS status listeners should be handled similar to the above.
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700503 }
504 }
505
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800506 private static boolean isImportanceForeground(int importance) {
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700507 return importance <= FOREGROUND_IMPORTANCE_CUTOFF;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800508 }
509
Amith Yamasanib27528d2014-06-05 15:02:10 -0700510 /**
destradaab9026982015-08-27 17:34:54 -0700511 * Provides a way for components held by the {@link LocationManagerService} to clean-up
512 * gracefully on system's shutdown.
513 *
514 * NOTES:
515 * 1) Only provides a chance to clean-up on an opt-in basis. This guarantees back-compat
516 * support for components that do not wish to handle such event.
517 */
518 private void shutdownComponents() {
gomo48f1a642017-11-10 20:35:46 -0800519 if (D) Log.d(TAG, "Shutting down components...");
destradaab9026982015-08-27 17:34:54 -0700520
521 LocationProviderInterface gpsProvider = mProvidersByName.get(LocationManager.GPS_PROVIDER);
522 if (gpsProvider != null && gpsProvider.isEnabled()) {
523 gpsProvider.disable();
524 }
destradaab9026982015-08-27 17:34:54 -0700525 }
526
527 /**
Amith Yamasanib27528d2014-06-05 15:02:10 -0700528 * Makes a list of userids that are related to the current user. This is
529 * relevant when using managed profiles. Otherwise the list only contains
530 * the current user.
531 *
532 * @param currentUserId the current user, who might have an alter-ego.
533 */
534 void updateUserProfiles(int currentUserId) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700535 int[] profileIds = mUserManager.getProfileIdsWithDisabled(currentUserId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700536 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700537 mCurrentUserProfiles = profileIds;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700538 }
539 }
540
541 /**
542 * Checks if the specified userId matches any of the current foreground
543 * users stored in mCurrentUserProfiles.
544 */
545 private boolean isCurrentProfile(int userId) {
546 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700547 return ArrayUtils.contains(mCurrentUserProfiles, userId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700548 }
549 }
550
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700551 private void ensureFallbackFusedProviderPresentLocked(String[] pkgs) {
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500552 PackageManager pm = mContext.getPackageManager();
553 String systemPackageName = mContext.getPackageName();
554 ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
555
556 List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
557 new Intent(FUSED_LOCATION_SERVICE_ACTION),
558 PackageManager.GET_META_DATA, mCurrentUserId);
559 for (ResolveInfo rInfo : rInfos) {
560 String packageName = rInfo.serviceInfo.packageName;
561
562 // Check that the signature is in the list of supported sigs. If it's not in
563 // this list the standard provider binding logic won't bind to it.
564 try {
565 PackageInfo pInfo;
566 pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
567 if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
568 Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
569 ", but has wrong signature, ignoring");
570 continue;
571 }
572 } catch (NameNotFoundException e) {
573 Log.e(TAG, "missing package: " + packageName);
574 continue;
575 }
576
577 // Get the version info
578 if (rInfo.serviceInfo.metaData == null) {
579 Log.w(TAG, "Found fused provider without metadata: " + packageName);
580 continue;
581 }
582
583 int version = rInfo.serviceInfo.metaData.getInt(
584 ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
585 if (version == 0) {
586 // This should be the fallback fused location provider.
587
588 // Make sure it's in the system partition.
589 if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
590 if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
591 continue;
592 }
593
594 // Check that the fallback is signed the same as the OS
595 // as a proxy for coreApp="true"
596 if (pm.checkSignatures(systemPackageName, packageName)
597 != PackageManager.SIGNATURE_MATCH) {
gomo48f1a642017-11-10 20:35:46 -0800598 if (D) {
599 Log.d(TAG, "Fallback candidate not signed the same as system: "
600 + packageName);
601 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500602 continue;
603 }
604
605 // Found a valid fallback.
606 if (D) Log.d(TAG, "Found fallback provider: " + packageName);
607 return;
608 } else {
609 if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
610 }
611 }
612
613 throw new IllegalStateException("Unable to find a fused location provider that is in the "
614 + "system partition with version 0 and signed with the platform certificate. "
615 + "Such a package is needed to provide a default fused location provider in the "
616 + "event that no other fused location provider has been installed or is currently "
617 + "available. For example, coreOnly boot mode when decrypting the data "
618 + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
619 }
620
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700621 private void loadProvidersLocked() {
Victoria Lease5c24fd02012-10-01 11:00:50 -0700622 // create a passive location provider, which is always enabled
623 PassiveProvider passiveProvider = new PassiveProvider(this);
624 addProviderLocked(passiveProvider);
625 mEnabledProviders.add(passiveProvider.getName());
626 mPassiveProvider = passiveProvider;
627
Lifu Tang30f95a72016-01-07 23:20:38 -0800628 if (GnssLocationProvider.isSupported()) {
Wei Liu5241a4c2015-05-11 14:00:36 -0700629 // Create a gps location provider
Lifu Tang30f95a72016-01-07 23:20:38 -0800630 GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this,
Wei Liu5241a4c2015-05-11 14:00:36 -0700631 mLocationHandler.getLooper());
Lifu Tang9363b942016-02-16 18:07:00 -0800632 mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
Wyatt Rileycf879db2017-01-12 13:57:38 -0800633 mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider();
Siddharth Raybb608c82017-03-16 11:33:34 -0700634 mGnssMetricsProvider = gnssProvider.getGnssMetricsProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800635 mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
636 mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
637 addProviderLocked(gnssProvider);
638 mRealProviders.put(LocationManager.GPS_PROVIDER, gnssProvider);
Lifu Tang818aa2c2016-02-01 01:52:00 -0800639 mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
640 mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800641 mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700642 }
643
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700644 /*
645 Load package name(s) containing location provider support.
646 These packages can contain services implementing location providers:
647 Geocoder Provider, Network Location Provider, and
648 Fused Location Provider. They will each be searched for
649 service components implementing these providers.
650 The location framework also has support for installation
651 of new location providers at run-time. The new package does not
652 have to be explicitly listed here, however it must have a signature
653 that matches the signature of at least one package on this list.
654 */
655 Resources resources = mContext.getResources();
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500656 String[] pkgs = resources.getStringArray(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700657 com.android.internal.R.array.config_locationProviderPackageNames);
gomo48f1a642017-11-10 20:35:46 -0800658 if (D) {
659 Log.d(TAG, "certificates for location providers pulled from: " +
660 Arrays.toString(pkgs));
661 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500662
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700663 ensureFallbackFusedProviderPresentLocked(pkgs);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700664
665 // bind to network provider
666 LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
667 mContext,
668 LocationManager.NETWORK_PROVIDER,
669 NETWORK_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700670 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
671 com.android.internal.R.string.config_networkLocationProviderPackageName,
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700672 com.android.internal.R.array.config_locationProviderPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700673 if (networkProvider != null) {
674 mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
675 mProxyProviders.add(networkProvider);
676 addProviderLocked(networkProvider);
677 } else {
gomo48f1a642017-11-10 20:35:46 -0800678 Slog.w(TAG, "no network location provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700679 }
680
681 // bind to fused provider
682 LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind(
683 mContext,
684 LocationManager.FUSED_PROVIDER,
685 FUSED_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700686 com.android.internal.R.bool.config_enableFusedLocationOverlay,
687 com.android.internal.R.string.config_fusedLocationProviderPackageName,
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700688 com.android.internal.R.array.config_locationProviderPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700689 if (fusedLocationProvider != null) {
690 addProviderLocked(fusedLocationProvider);
691 mProxyProviders.add(fusedLocationProvider);
692 mEnabledProviders.add(fusedLocationProvider.getName());
Kenny Rootc3575182012-10-09 12:44:40 -0700693 mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700694 } else {
695 Slog.e(TAG, "no fused location provider found",
696 new IllegalStateException("Location service needs a fused location provider"));
697 }
698
699 // bind to geocoder provider
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700700 mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
701 com.android.internal.R.bool.config_enableGeocoderOverlay,
702 com.android.internal.R.string.config_geocoderProviderPackageName,
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700703 com.android.internal.R.array.config_locationProviderPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700704 if (mGeocodeProvider == null) {
gomo48f1a642017-11-10 20:35:46 -0800705 Slog.e(TAG, "no geocoder provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700706 }
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700707
destradaaf9a274c2014-07-25 15:11:56 -0700708 // bind to geofence provider
709 GeofenceProxy provider = GeofenceProxy.createAndBind(
gomo48f1a642017-11-10 20:35:46 -0800710 mContext, com.android.internal.R.bool.config_enableGeofenceOverlay,
destradaaf9a274c2014-07-25 15:11:56 -0700711 com.android.internal.R.string.config_geofenceProviderPackageName,
712 com.android.internal.R.array.config_locationProviderPackageNames,
Wei Liu5241a4c2015-05-11 14:00:36 -0700713 mGpsGeofenceProxy,
Jiyong Park4cc3a1c2018-03-08 16:43:07 +0900714 null);
destradaaf9a274c2014-07-25 15:11:56 -0700715 if (provider == null) {
gomo48f1a642017-11-10 20:35:46 -0800716 Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
destradaa0682809a2013-08-12 18:50:30 -0700717 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900718
destradaa6e2fe752015-06-23 17:25:53 -0700719 // bind to hardware activity recognition
720 boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
721 ActivityRecognitionHardware activityRecognitionHardware = null;
722 if (activityRecognitionHardwareIsSupported) {
723 activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
destradaaa4fa3b52014-07-09 10:46:39 -0700724 } else {
destradaa6b4893a2016-05-03 15:33:43 -0700725 Slog.d(TAG, "Hardware Activity-Recognition not supported.");
destradaaa4fa3b52014-07-09 10:46:39 -0700726 }
destradaa6e2fe752015-06-23 17:25:53 -0700727 ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
728 mContext,
destradaa6e2fe752015-06-23 17:25:53 -0700729 activityRecognitionHardwareIsSupported,
730 activityRecognitionHardware,
731 com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
732 com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
733 com.android.internal.R.array.config_locationProviderPackageNames);
734 if (proxy == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700735 Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
destradaa6e2fe752015-06-23 17:25:53 -0700736 }
destradaaa4fa3b52014-07-09 10:46:39 -0700737
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900738 String[] testProviderStrings = resources.getStringArray(
739 com.android.internal.R.array.config_testLocationProviders);
740 for (String testProviderString : testProviderStrings) {
741 String fragments[] = testProviderString.split(",");
742 String name = fragments[0].trim();
743 if (mProvidersByName.get(name) != null) {
744 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
745 }
746 ProviderProperties properties = new ProviderProperties(
747 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
748 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
749 Boolean.parseBoolean(fragments[3]) /* requiresCell */,
750 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
751 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
752 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
753 Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
754 Integer.parseInt(fragments[8]) /* powerRequirement */,
755 Integer.parseInt(fragments[9]) /* accuracy */);
756 addTestProviderLocked(name, properties);
757 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700758 }
Mike Lockwood9637d472009-04-02 21:41:57 -0700759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 /**
Victoria Lease38389b62012-09-30 11:44:22 -0700761 * Called when the device's active user changes.
gomo48f1a642017-11-10 20:35:46 -0800762 *
Victoria Lease38389b62012-09-30 11:44:22 -0700763 * @param userId the new active user's UserId
764 */
765 private void switchUser(int userId) {
Jianzheng Zhoud5c69462013-10-10 14:02:09 +0800766 if (mCurrentUserId == userId) {
767 return;
768 }
Victoria Lease83762d22012-10-03 13:51:17 -0700769 mBlacklist.switchUser(userId);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800770 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED);
Victoria Lease38389b62012-09-30 11:44:22 -0700771 synchronized (mLock) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700772 mLastLocation.clear();
David Christie1b9b7b12013-04-15 15:31:11 -0700773 mLastLocationCoarseInterval.clear();
Victoria Leaseb711d572012-10-02 13:14:11 -0700774 for (LocationProviderInterface p : mProviders) {
Amith Yamasanib27528d2014-06-05 15:02:10 -0700775 updateProviderListenersLocked(p.getName(), false);
Victoria Leaseb711d572012-10-02 13:14:11 -0700776 }
Victoria Lease38389b62012-09-30 11:44:22 -0700777 mCurrentUserId = userId;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700778 updateUserProfiles(userId);
Victoria Leaseb711d572012-10-02 13:14:11 -0700779 updateProvidersLocked();
Victoria Lease38389b62012-09-30 11:44:22 -0700780 }
781 }
782
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800783 private static final class Identity {
784 final int mUid;
785 final int mPid;
786 final String mPackageName;
787
788 Identity(int uid, int pid, String packageName) {
789 mUid = uid;
790 mPid = pid;
791 mPackageName = packageName;
792 }
793 }
794
Victoria Lease38389b62012-09-30 11:44:22 -0700795 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796 * A wrapper class holding either an ILocationListener or a PendingIntent to receive
797 * location updates.
798 */
Mike Lockwood48f17512009-04-23 09:12:08 -0700799 private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
Yu-Han Yang24189822018-07-11 15:24:11 -0700800 private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800801 final Identity mIdentity;
Victoria Lease37425c32012-10-16 16:08:48 -0700802 final int mAllowedResolutionLevel; // resolution level allowed to receiver
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700803
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804 final ILocationListener mListener;
805 final PendingIntent mPendingIntent;
David Christie82edc9b2013-07-19 11:31:42 -0700806 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
David Christie40e57822013-07-30 11:36:48 -0700807 final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800808 final Object mKey;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700809
gomo48f1a642017-11-10 20:35:46 -0800810 final HashMap<String, UpdateRecord> mUpdateRecords = new HashMap<>();
Nick Pellyf1be6862012-05-15 10:53:42 -0700811
David Christie0b837452013-07-29 16:02:13 -0700812 // True if app ops has started monitoring this receiver for locations.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700813 boolean mOpMonitoring;
David Christie0b837452013-07-29 16:02:13 -0700814 // True if app ops has started monitoring this receiver for high power (gps) locations.
815 boolean mOpHighPowerMonitoring;
Mike Lockwood48f17512009-04-23 09:12:08 -0700816 int mPendingBroadcasts;
Victoria Lease0aa28602013-05-29 15:28:26 -0700817 PowerManager.WakeLock mWakeLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800818
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700819 Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -0700820 String packageName, WorkSource workSource, boolean hideFromAppOps) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800821 mListener = listener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822 mPendingIntent = intent;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700823 if (listener != null) {
824 mKey = listener.asBinder();
825 } else {
826 mKey = intent;
827 }
Victoria Lease37425c32012-10-16 16:08:48 -0700828 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800829 mIdentity = new Identity(uid, pid, packageName);
Narayan Kamath32684dd2018-01-08 17:32:51 +0000830 if (workSource != null && workSource.isEmpty()) {
David Christie82edc9b2013-07-19 11:31:42 -0700831 workSource = null;
832 }
833 mWorkSource = workSource;
David Christie40e57822013-07-30 11:36:48 -0700834 mHideFromAppOps = hideFromAppOps;
Victoria Lease0aa28602013-05-29 15:28:26 -0700835
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700836 updateMonitoring(true);
837
Victoria Lease0aa28602013-05-29 15:28:26 -0700838 // construct/configure wakelock
839 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
David Christie82edc9b2013-07-19 11:31:42 -0700840 if (workSource == null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800841 workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -0700842 }
843 mWakeLock.setWorkSource(workSource);
Yu-Han Yang24189822018-07-11 15:24:11 -0700844
845 // For a non-reference counted wakelock, each acquire will reset the timeout, and we
846 // only need to release it once.
847 mWakeLock.setReferenceCounted(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848 }
849
850 @Override
851 public boolean equals(Object otherObj) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800852 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 }
854
855 @Override
856 public int hashCode() {
857 return mKey.hashCode();
858 }
Mike Lockwood3681f262009-05-12 10:52:03 -0400859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 @Override
861 public String toString() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700862 StringBuilder s = new StringBuilder();
863 s.append("Reciever[");
864 s.append(Integer.toHexString(System.identityHashCode(this)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 if (mListener != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700866 s.append(" listener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700868 s.append(" intent");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700870 for (String p : mUpdateRecords.keySet()) {
871 s.append(" ").append(mUpdateRecords.get(p).toString());
872 }
Wei Wangdd070f22018-06-21 11:29:40 -0700873 s.append(" monitoring location: ").append(mOpMonitoring);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700874 s.append("]");
875 return s.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876 }
877
David Christie15b31912013-08-13 15:54:32 -0700878 /**
879 * Update AppOp monitoring for this receiver.
880 *
881 * @param allow If true receiver is currently active, if false it's been removed.
882 */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700883 public void updateMonitoring(boolean allow) {
David Christie40e57822013-07-30 11:36:48 -0700884 if (mHideFromAppOps) {
885 return;
886 }
887
David Christie15b31912013-08-13 15:54:32 -0700888 boolean requestingLocation = false;
889 boolean requestingHighPowerLocation = false;
890 if (allow) {
891 // See if receiver has any enabled update records. Also note if any update records
892 // are high power (has a high power provider with an interval under a threshold).
893 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
894 if (isAllowedByCurrentUserSettingsLocked(updateRecord.mProvider)) {
895 requestingLocation = true;
896 LocationProviderInterface locationProvider
David Christie2ff96af2014-01-30 16:09:37 -0800897 = mProvidersByName.get(updateRecord.mProvider);
David Christie15b31912013-08-13 15:54:32 -0700898 ProviderProperties properties = locationProvider != null
899 ? locationProvider.getProperties() : null;
900 if (properties != null
901 && properties.mPowerRequirement == Criteria.POWER_HIGH
902 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
903 requestingHighPowerLocation = true;
904 break;
905 }
906 }
907 }
908 }
909
David Christie0b837452013-07-29 16:02:13 -0700910 // First update monitoring of any location request (including high power).
David Christie15b31912013-08-13 15:54:32 -0700911 mOpMonitoring = updateMonitoring(
912 requestingLocation,
913 mOpMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700914 AppOpsManager.OP_MONITOR_LOCATION);
915
916 // Now update monitoring of high power requests only.
David Christiec750c1f2013-08-08 12:56:57 -0700917 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
David Christie15b31912013-08-13 15:54:32 -0700918 mOpHighPowerMonitoring = updateMonitoring(
919 requestingHighPowerLocation,
920 mOpHighPowerMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700921 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
David Christiec750c1f2013-08-08 12:56:57 -0700922 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
David Christie15b31912013-08-13 15:54:32 -0700923 // Send an intent to notify that a high power request has been added/removed.
David Christiec750c1f2013-08-08 12:56:57 -0700924 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
925 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
926 }
David Christie0b837452013-07-29 16:02:13 -0700927 }
928
929 /**
930 * Update AppOps monitoring for a single location request and op type.
931 *
gomo48f1a642017-11-10 20:35:46 -0800932 * @param allowMonitoring True if monitoring is allowed for this request/op.
David Christie0b837452013-07-29 16:02:13 -0700933 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
gomo48f1a642017-11-10 20:35:46 -0800934 * @param op AppOps code for the op to update.
David Christie0b837452013-07-29 16:02:13 -0700935 * @return True if monitoring is on for this request/op after updating.
936 */
937 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
938 int op) {
939 if (!currentlyMonitoring) {
940 if (allowMonitoring) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800941 return mAppOps.startOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700942 == AppOpsManager.MODE_ALLOWED;
943 }
944 } else {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800945 if (!allowMonitoring
Wei Wangdd070f22018-06-21 11:29:40 -0700946 || mAppOps.noteOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700947 != AppOpsManager.MODE_ALLOWED) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800948 mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName);
David Christie0b837452013-07-29 16:02:13 -0700949 return false;
950 }
951 }
952
953 return currentlyMonitoring;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700954 }
955
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 public boolean isListener() {
957 return mListener != null;
958 }
959
960 public boolean isPendingIntent() {
961 return mPendingIntent != null;
962 }
963
964 public ILocationListener getListener() {
965 if (mListener != null) {
966 return mListener;
967 }
968 throw new IllegalStateException("Request for non-existent listener");
969 }
970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800971 public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
972 if (mListener != null) {
973 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700974 synchronized (this) {
975 // synchronize to ensure incrementPendingBroadcastsLocked()
976 // is called before decrementPendingBroadcasts()
977 mListener.onStatusChanged(provider, status, extras);
Nick Pellye0fd6932012-07-11 10:26:13 -0700978 // call this after broadcasting so we do not increment
979 // if we throw an exeption.
980 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -0700981 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982 } catch (RemoteException e) {
983 return false;
984 }
985 } else {
986 Intent statusChanged = new Intent();
Victoria Lease61ecb022012-11-13 15:12:51 -0800987 statusChanged.putExtras(new Bundle(extras));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
989 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700990 synchronized (this) {
991 // synchronize to ensure incrementPendingBroadcastsLocked()
992 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700993 mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
Lifu Tang519f0d02018-04-12 16:39:39 -0700994 getResolutionPermission(mAllowedResolutionLevel),
995 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
Mike Lockwood48f17512009-04-23 09:12:08 -0700996 // call this after broadcasting so we do not increment
997 // if we throw an exeption.
998 incrementPendingBroadcastsLocked();
999 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 } catch (PendingIntent.CanceledException e) {
1001 return false;
1002 }
1003 }
1004 return true;
1005 }
1006
1007 public boolean callLocationChangedLocked(Location location) {
1008 if (mListener != null) {
1009 try {
Mike Lockwood48f17512009-04-23 09:12:08 -07001010 synchronized (this) {
1011 // synchronize to ensure incrementPendingBroadcastsLocked()
1012 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08001013 mListener.onLocationChanged(new Location(location));
Nick Pellye0fd6932012-07-11 10:26:13 -07001014 // call this after broadcasting so we do not increment
1015 // if we throw an exeption.
1016 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 } catch (RemoteException e) {
1019 return false;
1020 }
1021 } else {
1022 Intent locationChanged = new Intent();
gomo48f1a642017-11-10 20:35:46 -08001023 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED,
1024 new Location(location));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 try {
Mike Lockwood48f17512009-04-23 09:12:08 -07001026 synchronized (this) {
1027 // synchronize to ensure incrementPendingBroadcastsLocked()
1028 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001029 mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
Lifu Tang519f0d02018-04-12 16:39:39 -07001030 getResolutionPermission(mAllowedResolutionLevel),
1031 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
Mike Lockwood48f17512009-04-23 09:12:08 -07001032 // call this after broadcasting so we do not increment
1033 // if we throw an exeption.
1034 incrementPendingBroadcastsLocked();
1035 }
1036 } catch (PendingIntent.CanceledException e) {
1037 return false;
1038 }
1039 }
1040 return true;
1041 }
1042
1043 public boolean callProviderEnabledLocked(String provider, boolean enabled) {
David Christie15b31912013-08-13 15:54:32 -07001044 // First update AppOp monitoring.
1045 // An app may get/lose location access as providers are enabled/disabled.
1046 updateMonitoring(true);
1047
Mike Lockwood48f17512009-04-23 09:12:08 -07001048 if (mListener != null) {
1049 try {
1050 synchronized (this) {
1051 // synchronize to ensure incrementPendingBroadcastsLocked()
1052 // is called before decrementPendingBroadcasts()
1053 if (enabled) {
1054 mListener.onProviderEnabled(provider);
1055 } else {
1056 mListener.onProviderDisabled(provider);
1057 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001058 // call this after broadcasting so we do not increment
1059 // if we throw an exeption.
1060 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001061 }
1062 } catch (RemoteException e) {
1063 return false;
1064 }
1065 } else {
1066 Intent providerIntent = new Intent();
1067 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1068 try {
1069 synchronized (this) {
1070 // synchronize to ensure incrementPendingBroadcastsLocked()
1071 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001072 mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
Lifu Tang519f0d02018-04-12 16:39:39 -07001073 getResolutionPermission(mAllowedResolutionLevel),
1074 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
Mike Lockwood48f17512009-04-23 09:12:08 -07001075 // call this after broadcasting so we do not increment
1076 // if we throw an exeption.
1077 incrementPendingBroadcastsLocked();
1078 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001079 } catch (PendingIntent.CanceledException e) {
1080 return false;
1081 }
1082 }
1083 return true;
1084 }
1085
Nick Pellyf1be6862012-05-15 10:53:42 -07001086 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 public void binderDied() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001088 if (D) Log.d(TAG, "Location listener died");
1089
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001090 synchronized (mLock) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 removeUpdatesLocked(this);
1092 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001093 synchronized (this) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001094 clearPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001095 }
1096 }
1097
Nick Pellye0fd6932012-07-11 10:26:13 -07001098 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001099 public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1100 int resultCode, String resultData, Bundle resultExtras) {
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001101 synchronized (this) {
1102 decrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001103 }
1104 }
1105
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001106 // this must be called while synchronized by caller in a synchronized block
1107 // containing the sending of the broadcaset
1108 private void incrementPendingBroadcastsLocked() {
Yu-Han Yang24189822018-07-11 15:24:11 -07001109 mPendingBroadcasts++;
1110 mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001111 }
1112
1113 private void decrementPendingBroadcastsLocked() {
1114 if (--mPendingBroadcasts == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001115 if (mWakeLock.isHeld()) {
1116 mWakeLock.release();
1117 }
1118 }
1119 }
1120
1121 public void clearPendingBroadcastsLocked() {
1122 if (mPendingBroadcasts > 0) {
1123 mPendingBroadcasts = 0;
1124 if (mWakeLock.isHeld()) {
1125 mWakeLock.release();
1126 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001127 }
1128 }
1129 }
1130
Nick Pellye0fd6932012-07-11 10:26:13 -07001131 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001132 public void locationCallbackFinished(ILocationListener listener) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001133 //Do not use getReceiverLocked here as that will add the ILocationListener to
Joshua Bartel080b61b2009-10-05 12:44:46 -04001134 //the receiver list if it is not found. If it is not found then the
1135 //LocationListener was removed when it had a pending broadcast and should
1136 //not be added back.
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001137 synchronized (mLock) {
1138 IBinder binder = listener.asBinder();
1139 Receiver receiver = mReceivers.get(binder);
1140 if (receiver != null) {
1141 synchronized (receiver) {
1142 // so wakelock calls will succeed
1143 long identity = Binder.clearCallingIdentity();
1144 receiver.decrementPendingBroadcastsLocked();
1145 Binder.restoreCallingIdentity(identity);
David Christie2ff96af2014-01-30 16:09:37 -08001146 }
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001147 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001148 }
1149 }
1150
Lifu Tang82f893d2016-01-21 18:15:33 -08001151 /**
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001152 * Returns the year of the GNSS hardware.
Lifu Tang82f893d2016-01-21 18:15:33 -08001153 */
1154 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001155 public int getGnssYearOfHardware() {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001156 if (mGnssSystemInfoProvider != null) {
Lifu Tang9363b942016-02-16 18:07:00 -08001157 return mGnssSystemInfoProvider.getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001158 } else {
1159 return 0;
1160 }
1161 }
1162
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001163
1164 /**
1165 * Returns the model name of the GNSS hardware.
1166 */
1167 @Override
Wyatt Riley49097c02018-03-15 09:14:43 -07001168 @Nullable
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001169 public String getGnssHardwareModelName() {
1170 if (mGnssSystemInfoProvider != null) {
1171 return mGnssSystemInfoProvider.getGnssHardwareModelName();
1172 } else {
Wyatt Riley49097c02018-03-15 09:14:43 -07001173 return null;
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001174 }
1175 }
1176
Wyatt Rileycf879db2017-01-12 13:57:38 -08001177 /**
1178 * Runs some checks for GNSS (FINE) level permissions, used by several methods which directly
1179 * (try to) access GNSS information at this layer.
1180 */
1181 private boolean hasGnssPermissions(String packageName) {
1182 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
1183 checkResolutionLevelIsSufficientForProviderUse(
1184 allowedResolutionLevel,
1185 LocationManager.GPS_PROVIDER);
1186
1187 int pid = Binder.getCallingPid();
1188 int uid = Binder.getCallingUid();
1189 long identity = Binder.clearCallingIdentity();
1190 boolean hasLocationAccess;
1191 try {
1192 hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
1193 } finally {
1194 Binder.restoreCallingIdentity(identity);
1195 }
1196
1197 return hasLocationAccess;
1198 }
1199
1200 /**
1201 * Returns the GNSS batching size, if available.
1202 */
1203 @Override
1204 public int getGnssBatchSize(String packageName) {
1205 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1206 "Location Hardware permission not granted to access hardware batching");
1207
1208 if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
Yu-Han Yang3557cc72018-03-21 12:48:36 -07001209 return mGnssBatchingProvider.getBatchSize();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001210 } else {
1211 return 0;
1212 }
1213 }
1214
1215 /**
1216 * Adds a callback for GNSS Batching events, if permissions allow, which are transported
1217 * to potentially multiple listeners by the BatchedLocationCallbackTransport above this.
1218 */
1219 @Override
1220 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) {
1221 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1222 "Location Hardware permission not granted to access hardware batching");
1223
1224 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1225 return false;
1226 }
1227
1228 mGnssBatchingCallback = callback;
1229 mGnssBatchingDeathCallback = new LinkedCallback(callback);
1230 try {
1231 callback.asBinder().linkToDeath(mGnssBatchingDeathCallback, 0 /* flags */);
1232 } catch (RemoteException e) {
1233 // if the remote process registering the listener is already dead, just swallow the
1234 // exception and return
1235 Log.e(TAG, "Remote listener already died.", e);
1236 return false;
1237 }
1238
1239 return true;
1240 }
1241
1242 private class LinkedCallback implements IBinder.DeathRecipient {
1243 private final IBatchedLocationCallback mCallback;
1244
1245 public LinkedCallback(@NonNull IBatchedLocationCallback callback) {
1246 mCallback = callback;
1247 }
1248
1249 @NonNull
1250 public IBatchedLocationCallback getUnderlyingListener() {
1251 return mCallback;
1252 }
1253
1254 @Override
1255 public void binderDied() {
1256 Log.d(TAG, "Remote Batching Callback died: " + mCallback);
1257 stopGnssBatch();
1258 removeGnssBatchingCallback();
1259 }
1260 }
1261
1262 /**
1263 * Removes callback for GNSS batching
1264 */
1265 @Override
1266 public void removeGnssBatchingCallback() {
1267 try {
1268 mGnssBatchingCallback.asBinder().unlinkToDeath(mGnssBatchingDeathCallback,
1269 0 /* flags */);
1270 } catch (NoSuchElementException e) {
1271 // if the death callback isn't connected (it should be...), log error, swallow the
1272 // exception and return
1273 Log.e(TAG, "Couldn't unlink death callback.", e);
1274 }
1275 mGnssBatchingCallback = null;
1276 mGnssBatchingDeathCallback = null;
1277 }
1278
1279
1280 /**
1281 * Starts GNSS batching, if available.
1282 */
1283 @Override
1284 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
1285 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1286 "Location Hardware permission not granted to access hardware batching");
1287
1288 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1289 return false;
1290 }
1291
1292 if (mGnssBatchingInProgress) {
1293 // Current design does not expect multiple starts to be called repeatedly
1294 Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch");
1295 // Try to clean up anyway, and continue
1296 stopGnssBatch();
1297 }
1298
1299 mGnssBatchingInProgress = true;
1300 return mGnssBatchingProvider.start(periodNanos, wakeOnFifoFull);
1301 }
1302
1303 /**
1304 * Flushes a GNSS batch in progress
1305 */
1306 @Override
1307 public void flushGnssBatch(String packageName) {
1308 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1309 "Location Hardware permission not granted to access hardware batching");
1310
1311 if (!hasGnssPermissions(packageName)) {
1312 Log.e(TAG, "flushGnssBatch called without GNSS permissions");
1313 return;
1314 }
1315
1316 if (!mGnssBatchingInProgress) {
1317 Log.w(TAG, "flushGnssBatch called with no batch in progress");
1318 }
1319
1320 if (mGnssBatchingProvider != null) {
gomo48f1a642017-11-10 20:35:46 -08001321 mGnssBatchingProvider.flush();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001322 }
1323 }
1324
1325 /**
1326 * Stops GNSS batching
1327 */
1328 @Override
1329 public boolean stopGnssBatch() {
1330 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1331 "Location Hardware permission not granted to access hardware batching");
1332
1333 if (mGnssBatchingProvider != null) {
1334 mGnssBatchingInProgress = false;
1335 return mGnssBatchingProvider.stop();
gomo48f1a642017-11-10 20:35:46 -08001336 } else {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001337 return false;
1338 }
1339 }
1340
1341 @Override
1342 public void reportLocationBatch(List<Location> locations) {
1343 checkCallerIsProvider();
1344
1345 // Currently used only for GNSS locations - update permissions check if changed
1346 if (isAllowedByCurrentUserSettingsLocked(LocationManager.GPS_PROVIDER)) {
1347 if (mGnssBatchingCallback == null) {
1348 Slog.e(TAG, "reportLocationBatch() called without active Callback");
1349 return;
1350 }
1351 try {
1352 mGnssBatchingCallback.onLocationBatch(locations);
1353 } catch (RemoteException e) {
1354 Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e);
1355 }
1356 } else {
1357 Slog.w(TAG, "reportLocationBatch() called without user permission, locations blocked");
1358 }
1359 }
1360
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001361 private void addProviderLocked(LocationProviderInterface provider) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001362 mProviders.add(provider);
1363 mProvidersByName.put(provider.getName(), provider);
1364 }
1365
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001366 private void removeProviderLocked(LocationProviderInterface provider) {
1367 provider.disable();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001368 mProviders.remove(provider);
1369 mProvidersByName.remove(provider.getName());
1370 }
1371
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001372 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001373 * Returns "true" if access to the specified location provider is allowed by the current
1374 * user's settings. Access to all location providers is forbidden to non-location-provider
1375 * processes belonging to background users.
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001376 *
1377 * @param provider the name of the location provider
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001378 */
Victoria Lease09eeaec2013-02-05 11:34:13 -08001379 private boolean isAllowedByCurrentUserSettingsLocked(String provider) {
Maggie2a9409e2018-03-21 11:47:28 -07001380 return isAllowedByUserSettingsLockedForUser(provider, mCurrentUserId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 }
1382
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001383 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001384 * Returns "true" if access to the specified location provider is allowed by the specified
1385 * user's settings. Access to all location providers is forbidden to non-location-provider
1386 * processes belonging to background users.
1387 *
1388 * @param provider the name of the location provider
Maggie2a9409e2018-03-21 11:47:28 -07001389 * @param userId the user id to query
Victoria Lease09eeaec2013-02-05 11:34:13 -08001390 */
Maggie2a9409e2018-03-21 11:47:28 -07001391 private boolean isAllowedByUserSettingsLockedForUser(String provider, int userId) {
1392 if (mEnabledProviders.contains(provider)) {
1393 return true;
1394 }
1395 if (mDisabledProviders.contains(provider)) {
1396 return false;
1397 }
1398 return isLocationProviderEnabledForUser(provider, userId);
1399 }
1400
1401
1402 /**
1403 * Returns "true" if access to the specified location provider is allowed by the specified
1404 * user's settings. Access to all location providers is forbidden to non-location-provider
1405 * processes belonging to background users.
1406 *
1407 * @param provider the name of the location provider
1408 * @param uid the requestor's UID
1409 * @param userId the user id to query
1410 */
1411 private boolean isAllowedByUserSettingsLocked(String provider, int uid, int userId) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001412 if (!isCurrentProfile(UserHandle.getUserId(uid)) && !isUidALocationProvider(uid)) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08001413 return false;
1414 }
Maggie2a9409e2018-03-21 11:47:28 -07001415 return isAllowedByUserSettingsLockedForUser(provider, userId);
Victoria Lease09eeaec2013-02-05 11:34:13 -08001416 }
1417
1418 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001419 * Returns the permission string associated with the specified resolution level.
1420 *
1421 * @param resolutionLevel the resolution level
1422 * @return the permission string
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001423 */
Victoria Lease37425c32012-10-16 16:08:48 -07001424 private String getResolutionPermission(int resolutionLevel) {
1425 switch (resolutionLevel) {
1426 case RESOLUTION_LEVEL_FINE:
1427 return android.Manifest.permission.ACCESS_FINE_LOCATION;
1428 case RESOLUTION_LEVEL_COARSE:
1429 return android.Manifest.permission.ACCESS_COARSE_LOCATION;
1430 default:
1431 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001432 }
Victoria Leaseda479c52012-10-15 15:24:16 -07001433 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001434
Victoria Leaseda479c52012-10-15 15:24:16 -07001435 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001436 * Returns the resolution level allowed to the given PID/UID pair.
1437 *
1438 * @param pid the PID
1439 * @param uid the UID
1440 * @return resolution level allowed to the pid/uid pair
Victoria Leaseda479c52012-10-15 15:24:16 -07001441 */
Victoria Lease37425c32012-10-16 16:08:48 -07001442 private int getAllowedResolutionLevel(int pid, int uid) {
1443 if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001444 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001445 return RESOLUTION_LEVEL_FINE;
1446 } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001447 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001448 return RESOLUTION_LEVEL_COARSE;
1449 } else {
1450 return RESOLUTION_LEVEL_NONE;
Victoria Leaseda479c52012-10-15 15:24:16 -07001451 }
Victoria Lease4fab68b2012-09-13 13:20:59 -07001452 }
1453
1454 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001455 * Returns the resolution level allowed to the caller
1456 *
1457 * @return resolution level allowed to caller
Victoria Lease4fab68b2012-09-13 13:20:59 -07001458 */
Victoria Lease37425c32012-10-16 16:08:48 -07001459 private int getCallerAllowedResolutionLevel() {
1460 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
1461 }
1462
1463 /**
1464 * Throw SecurityException if specified resolution level is insufficient to use geofences.
1465 *
1466 * @param allowedResolutionLevel resolution level allowed to caller
1467 */
1468 private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
1469 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Lease4fab68b2012-09-13 13:20:59 -07001470 throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
1471 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001472 }
1473
Victoria Lease37425c32012-10-16 16:08:48 -07001474 /**
1475 * Return the minimum resolution level required to use the specified location provider.
1476 *
1477 * @param provider the name of the location provider
1478 * @return minimum resolution level required for provider
1479 */
1480 private int getMinimumResolutionLevelForProviderUse(String provider) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001481 if (LocationManager.GPS_PROVIDER.equals(provider) ||
1482 LocationManager.PASSIVE_PROVIDER.equals(provider)) {
1483 // gps and passive providers require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001484 return RESOLUTION_LEVEL_FINE;
Victoria Lease8dbb6342012-09-21 16:55:53 -07001485 } else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
1486 LocationManager.FUSED_PROVIDER.equals(provider)) {
1487 // network and fused providers are ok with COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001488 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001489 } else {
1490 // mock providers
1491 LocationProviderInterface lp = mMockProviders.get(provider);
1492 if (lp != null) {
1493 ProviderProperties properties = lp.getProperties();
1494 if (properties != null) {
1495 if (properties.mRequiresSatellite) {
1496 // provider requiring satellites require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001497 return RESOLUTION_LEVEL_FINE;
Laurent Tu941221c2012-10-04 14:21:52 -07001498 } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
1499 // provider requiring network and or cell require COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001500 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001501 }
1502 }
1503 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001504 }
Victoria Lease37425c32012-10-16 16:08:48 -07001505 return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
Victoria Leaseda479c52012-10-15 15:24:16 -07001506 }
1507
Victoria Lease37425c32012-10-16 16:08:48 -07001508 /**
1509 * Throw SecurityException if specified resolution level is insufficient to use the named
1510 * location provider.
1511 *
1512 * @param allowedResolutionLevel resolution level allowed to caller
gomo48f1a642017-11-10 20:35:46 -08001513 * @param providerName the name of the location provider
Victoria Lease37425c32012-10-16 16:08:48 -07001514 */
1515 private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel,
1516 String providerName) {
1517 int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName);
1518 if (allowedResolutionLevel < requiredResolutionLevel) {
1519 switch (requiredResolutionLevel) {
1520 case RESOLUTION_LEVEL_FINE:
1521 throw new SecurityException("\"" + providerName + "\" location provider " +
1522 "requires ACCESS_FINE_LOCATION permission.");
1523 case RESOLUTION_LEVEL_COARSE:
1524 throw new SecurityException("\"" + providerName + "\" location provider " +
1525 "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
1526 default:
1527 throw new SecurityException("Insufficient permission for \"" + providerName +
1528 "\" location provider.");
Victoria Leaseda479c52012-10-15 15:24:16 -07001529 }
1530 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001531 }
1532
David Christie82edc9b2013-07-19 11:31:42 -07001533 /**
1534 * Throw SecurityException if WorkSource use is not allowed (i.e. can't blame other packages
1535 * for battery).
1536 */
David Christie40e57822013-07-30 11:36:48 -07001537 private void checkDeviceStatsAllowed() {
David Christie82edc9b2013-07-19 11:31:42 -07001538 mContext.enforceCallingOrSelfPermission(
1539 android.Manifest.permission.UPDATE_DEVICE_STATS, null);
1540 }
1541
David Christie40e57822013-07-30 11:36:48 -07001542 private void checkUpdateAppOpsAllowed() {
1543 mContext.enforceCallingOrSelfPermission(
1544 android.Manifest.permission.UPDATE_APP_OPS_STATS, null);
1545 }
1546
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001547 public static int resolutionLevelToOp(int allowedResolutionLevel) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001548 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
1549 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001550 return AppOpsManager.OP_COARSE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001551 } else {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001552 return AppOpsManager.OP_FINE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001553 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001554 }
1555 return -1;
1556 }
1557
Wei Wangb86334f2018-07-03 16:33:24 -07001558 private static String resolutionLevelToOpStr(int allowedResolutionLevel) {
1559 switch(allowedResolutionLevel) {
1560 case RESOLUTION_LEVEL_COARSE:
1561 return AppOpsManager.OPSTR_COARSE_LOCATION;
1562 case RESOLUTION_LEVEL_FINE:
1563 return AppOpsManager.OPSTR_FINE_LOCATION;
1564 case RESOLUTION_LEVEL_NONE:
1565 // The client is not allowed to get any location, so both FINE and COARSE ops will
1566 // be denied. Pick the most restrictive one to be safe.
1567 return AppOpsManager.OPSTR_FINE_LOCATION;
1568 default:
1569 // Use the most restrictive ops if not sure.
1570 return AppOpsManager.OPSTR_FINE_LOCATION;
1571 }
1572 }
1573
David Christieb870dbf2015-06-22 12:42:53 -07001574 boolean reportLocationAccessNoThrow(
1575 int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001576 int op = resolutionLevelToOp(allowedResolutionLevel);
1577 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001578 if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1579 return false;
1580 }
1581 }
David Christieb870dbf2015-06-22 12:42:53 -07001582
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001583 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001584 }
1585
David Christieb870dbf2015-06-22 12:42:53 -07001586 boolean checkLocationAccess(int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001587 int op = resolutionLevelToOp(allowedResolutionLevel);
1588 if (op >= 0) {
Wei Wangdd070f22018-06-21 11:29:40 -07001589 if (mAppOps.noteOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001590 return false;
1591 }
1592 }
David Christieb870dbf2015-06-22 12:42:53 -07001593
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001594 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001595 }
1596
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001597 /**
Maggie91e630c2018-01-24 17:31:46 -08001598 * Returns all providers by name, including passive and the ones that are not permitted to
1599 * be accessed by the calling activity or are currently disabled, but excluding fused.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001600 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001601 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001602 public List<String> getAllProviders() {
Maggie91e630c2018-01-24 17:31:46 -08001603 ArrayList<String> out;
1604 synchronized (mLock) {
1605 out = new ArrayList<>(mProviders.size());
1606 for (LocationProviderInterface provider : mProviders) {
1607 String name = provider.getName();
1608 if (LocationManager.FUSED_PROVIDER.equals(name)) {
1609 continue;
1610 }
1611 out.add(name);
1612 }
1613 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001614 if (D) Log.d(TAG, "getAllProviders()=" + out);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615 return out;
1616 }
1617
Mike Lockwood03ca2162010-04-01 08:10:09 -07001618 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001619 * Return all providers by name, that match criteria and are optionally
1620 * enabled.
1621 * Can return passive provider, but never returns fused provider.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001622 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001623 @Override
1624 public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
Victoria Lease37425c32012-10-16 16:08:48 -07001625 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001626 ArrayList<String> out;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001627 int uid = Binder.getCallingUid();
Victoria Lease269518e2012-10-29 08:25:39 -07001628 long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07001629 try {
1630 synchronized (mLock) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001631 out = new ArrayList<>(mProviders.size());
Victoria Leaseb711d572012-10-02 13:14:11 -07001632 for (LocationProviderInterface provider : mProviders) {
1633 String name = provider.getName();
1634 if (LocationManager.FUSED_PROVIDER.equals(name)) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001635 continue;
1636 }
Victoria Lease37425c32012-10-16 16:08:48 -07001637 if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
Maggie2a9409e2018-03-21 11:47:28 -07001638 if (enabledOnly
1639 && !isAllowedByUserSettingsLocked(name, uid, mCurrentUserId)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001640 continue;
1641 }
1642 if (criteria != null && !LocationProvider.propertiesMeetCriteria(
1643 name, provider.getProperties(), criteria)) {
1644 continue;
1645 }
1646 out.add(name);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001647 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001648 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001649 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001650 } finally {
1651 Binder.restoreCallingIdentity(identity);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001652 }
1653
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001654 if (D) Log.d(TAG, "getProviders()=" + out);
1655 return out;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001656 }
1657
1658 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001659 * Return the name of the best provider given a Criteria object.
1660 * This method has been deprecated from the public API,
Victoria Lease8dbb6342012-09-21 16:55:53 -07001661 * and the whole LocationProvider (including #meetsCriteria)
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001662 * has been deprecated as well. So this method now uses
1663 * some simplified logic.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001664 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001665 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001666 public String getBestProvider(Criteria criteria, boolean enabledOnly) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001667 String result = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001668
1669 List<String> providers = getProviders(criteria, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001670 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001671 result = pickBest(providers);
1672 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1673 return result;
1674 }
1675 providers = getProviders(null, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001676 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001677 result = pickBest(providers);
1678 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1679 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001680 }
1681
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001682 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001683 return null;
1684 }
1685
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001686 private String pickBest(List<String> providers) {
Victoria Lease1925e292012-09-24 17:00:18 -07001687 if (providers.contains(LocationManager.GPS_PROVIDER)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001688 return LocationManager.GPS_PROVIDER;
Victoria Lease1925e292012-09-24 17:00:18 -07001689 } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
1690 return LocationManager.NETWORK_PROVIDER;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001691 } else {
1692 return providers.get(0);
1693 }
1694 }
1695
Nick Pellye0fd6932012-07-11 10:26:13 -07001696 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001697 public boolean providerMeetsCriteria(String provider, Criteria criteria) {
1698 LocationProviderInterface p = mProvidersByName.get(provider);
1699 if (p == null) {
1700 throw new IllegalArgumentException("provider=" + provider);
1701 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001702
1703 boolean result = LocationProvider.propertiesMeetCriteria(
1704 p.getName(), p.getProperties(), criteria);
1705 if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result);
1706 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001707 }
1708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 private void updateProvidersLocked() {
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001710 boolean changesMade = false;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001711 for (int i = mProviders.size() - 1; i >= 0; i--) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001712 LocationProviderInterface p = mProviders.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 boolean isEnabled = p.isEnabled();
1714 String name = p.getName();
Victoria Lease09eeaec2013-02-05 11:34:13 -08001715 boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001716 if (isEnabled && !shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001717 updateProviderListenersLocked(name, false);
David Christieb084fef2013-12-18 14:33:57 -08001718 // If any provider has been disabled, clear all last locations for all providers.
1719 // This is to be on the safe side in case a provider has location derived from
1720 // this disabled provider.
1721 mLastLocation.clear();
1722 mLastLocationCoarseInterval.clear();
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001723 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001724 } else if (!isEnabled && shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001725 updateProviderListenersLocked(name, true);
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001726 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001727 }
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001728 }
1729 if (changesMade) {
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001730 mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
1731 UserHandle.ALL);
Tom O'Neill40a86c22013-09-03 18:05:13 -07001732 mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
1733 UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001734 }
1735 }
1736
Amith Yamasanib27528d2014-06-05 15:02:10 -07001737 private void updateProviderListenersLocked(String provider, boolean enabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 int listeners = 0;
1739
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001740 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001741 if (p == null) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001742
1743 ArrayList<Receiver> deadReceivers = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07001744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1746 if (records != null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001747 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001748 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001749 // Sends a notification message to the receiver
1750 if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
1751 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001752 deadReceivers = new ArrayList<>();
Victoria Leaseb711d572012-10-02 13:14:11 -07001753 }
1754 deadReceivers.add(record.mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001755 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001756 listeners++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001757 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001758 }
1759 }
1760
1761 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001762 for (int i = deadReceivers.size() - 1; i >= 0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001763 removeUpdatesLocked(deadReceivers.get(i));
1764 }
1765 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001767 if (enabled) {
1768 p.enable();
Yu-Han Yanga4d250e2018-10-02 21:29:20 -07001769 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771 p.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001773 }
1774
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001775 private void applyRequirementsLocked(String provider) {
1776 LocationProviderInterface p = mProvidersByName.get(provider);
1777 if (p == null) return;
1778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001779 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001780 WorkSource worksource = new WorkSource();
1781 ProviderRequest providerRequest = new ProviderRequest();
1782
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001783 ContentResolver resolver = mContext.getContentResolver();
1784 long backgroundThrottleInterval = Settings.Global.getLong(
1785 resolver,
1786 Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
1787 DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
gomo48f1a642017-11-10 20:35:46 -08001788 // initialize the low power mode to true and set to false if any of the records requires
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001789
gomo48f1a642017-11-10 20:35:46 -08001790 providerRequest.lowPowerMode = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001791 if (records != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001792 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001793 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
David Christieb870dbf2015-06-22 12:42:53 -07001794 if (checkLocationAccess(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001795 record.mReceiver.mIdentity.mPid,
1796 record.mReceiver.mIdentity.mUid,
1797 record.mReceiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001798 record.mReceiver.mAllowedResolutionLevel)) {
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001799 LocationRequest locationRequest = record.mRealRequest;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001800 long interval = locationRequest.getInterval();
1801
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001802 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001803 if (!record.mIsForegroundUid) {
1804 interval = Math.max(interval, backgroundThrottleInterval);
1805 }
1806 if (interval != locationRequest.getInterval()) {
1807 locationRequest = new LocationRequest(locationRequest);
1808 locationRequest.setInterval(interval);
1809 }
1810 }
1811
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001812 record.mRequest = locationRequest;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001813 providerRequest.locationRequests.add(locationRequest);
gomo48f1a642017-11-10 20:35:46 -08001814 if (!locationRequest.isLowPowerMode()) {
1815 providerRequest.lowPowerMode = false;
1816 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001817 if (interval < providerRequest.interval) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001818 providerRequest.reportLocation = true;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001819 providerRequest.interval = interval;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001820 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001821 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001822 }
1823 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001824
1825 if (providerRequest.reportLocation) {
1826 // calculate who to blame for power
1827 // This is somewhat arbitrary. We pick a threshold interval
1828 // that is slightly higher that the minimum interval, and
1829 // spread the blame across all applications with a request
1830 // under that threshold.
1831 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
1832 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001833 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001834 LocationRequest locationRequest = record.mRequest;
Svet Ganove998c732016-06-10 00:12:38 -07001835
1836 // Don't assign battery blame for update records whose
1837 // client has no permission to receive location data.
1838 if (!providerRequest.locationRequests.contains(locationRequest)) {
1839 continue;
1840 }
1841
Victoria Leaseb711d572012-10-02 13:14:11 -07001842 if (locationRequest.getInterval() <= thresholdInterval) {
David Christiee55c9682013-08-22 10:10:34 -07001843 if (record.mReceiver.mWorkSource != null
Narayan Kamath32684dd2018-01-08 17:32:51 +00001844 && isValidWorkSource(record.mReceiver.mWorkSource)) {
David Christie82edc9b2013-07-19 11:31:42 -07001845 worksource.add(record.mReceiver.mWorkSource);
1846 } else {
Narayan Kamath32684dd2018-01-08 17:32:51 +00001847 // Assign blame to caller if there's no WorkSource associated with
1848 // the request or if it's invalid.
David Christie82edc9b2013-07-19 11:31:42 -07001849 worksource.add(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001850 record.mReceiver.mIdentity.mUid,
1851 record.mReceiver.mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001852 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001853 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001854 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 }
1857 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001858
1859 if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
1860 p.setRequest(providerRequest, worksource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001861 }
1862
Narayan Kamath32684dd2018-01-08 17:32:51 +00001863 /**
1864 * Whether a given {@code WorkSource} associated with a Location request is valid.
1865 */
1866 private static boolean isValidWorkSource(WorkSource workSource) {
1867 if (workSource.size() > 0) {
1868 // If the WorkSource has one or more non-chained UIDs, make sure they're accompanied
1869 // by tags.
1870 return workSource.getName(0) != null;
1871 } else {
1872 // For now, make sure callers have supplied an attribution tag for use with
1873 // AppOpsManager. This might be relaxed in the future.
1874 final ArrayList<WorkChain> workChains = workSource.getWorkChains();
1875 return workChains != null && !workChains.isEmpty() &&
1876 workChains.get(0).getAttributionTag() != null;
1877 }
1878 }
1879
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001880 @Override
1881 public String[] getBackgroundThrottlingWhitelist() {
1882 synchronized (mLock) {
1883 return mBackgroundThrottlePackageWhitelist.toArray(
gomo48f1a642017-11-10 20:35:46 -08001884 new String[mBackgroundThrottlePackageWhitelist.size()]);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001885 }
1886 }
1887
1888 private void updateBackgroundThrottlingWhitelistLocked() {
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001889 String setting = Settings.Global.getString(
gomo48f1a642017-11-10 20:35:46 -08001890 mContext.getContentResolver(),
1891 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001892 if (setting == null) {
1893 setting = "";
1894 }
1895
1896 mBackgroundThrottlePackageWhitelist.clear();
1897 mBackgroundThrottlePackageWhitelist.addAll(
gomo48f1a642017-11-10 20:35:46 -08001898 SystemConfig.getInstance().getAllowUnthrottledLocation());
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001899 mBackgroundThrottlePackageWhitelist.addAll(
gomo48f1a642017-11-10 20:35:46 -08001900 Arrays.asList(setting.split(",")));
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001901 }
1902
Wei Wangdd070f22018-06-21 11:29:40 -07001903 private void updateLastLocationMaxAgeLocked() {
1904 mLastLocationMaxAgeMs =
1905 Settings.Global.getLong(
1906 mContext.getContentResolver(),
1907 Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
1908 DEFAULT_LAST_LOCATION_MAX_AGE_MS);
1909 }
1910
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001911 private boolean isThrottlingExemptLocked(Identity identity) {
1912 if (identity.mUid == Process.SYSTEM_UID) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001913 return true;
1914 }
1915
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001916 if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001917 return true;
1918 }
1919
1920 for (LocationProviderProxy provider : mProxyProviders) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001921 if (identity.mPackageName.equals(provider.getConnectedPackageName())) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001922 return true;
1923 }
1924 }
1925
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001926 return false;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001927 }
1928
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001929 private class UpdateRecord {
1930 final String mProvider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001931 final LocationRequest mRealRequest; // original request from client
1932 LocationRequest mRequest; // possibly throttled version of the request
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001933 final Receiver mReceiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001934 boolean mIsForegroundUid;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001935 Location mLastFixBroadcast;
1936 long mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937
1938 /**
1939 * Note: must be constructed with lock held.
1940 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001941 UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001942 mProvider = provider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001943 mRealRequest = request;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001944 mRequest = request;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001945 mReceiver = receiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001946 mIsForegroundUid = isImportanceForeground(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001947 mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001948
1949 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1950 if (records == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001951 records = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001952 mRecordsByProvider.put(provider, records);
1953 }
1954 if (!records.contains(this)) {
1955 records.add(this);
1956 }
David Christie2ff96af2014-01-30 16:09:37 -08001957
1958 // Update statistics for historical location requests by package/provider
1959 mRequestStatistics.startRequesting(
Wyatt Rileyf7075e02018-04-12 17:54:26 -07001960 mReceiver.mIdentity.mPackageName, provider, request.getInterval(),
1961 mIsForegroundUid);
1962 }
1963
1964 /**
1965 * Method to be called when record changes foreground/background
1966 */
1967 void updateForeground(boolean isForeground){
1968 mIsForegroundUid = isForeground;
1969 mRequestStatistics.updateForeground(
1970 mReceiver.mIdentity.mPackageName, mProvider, isForeground);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001971 }
1972
1973 /**
David Christie2ff96af2014-01-30 16:09:37 -08001974 * Method to be called when a record will no longer be used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001975 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001976 void disposeLocked(boolean removeReceiver) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001977 mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider);
David Christie2ff96af2014-01-30 16:09:37 -08001978
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001979 // remove from mRecordsByProvider
1980 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
1981 if (globalRecords != null) {
1982 globalRecords.remove(this);
1983 }
1984
1985 if (!removeReceiver) return; // the caller will handle the rest
1986
1987 // remove from Receiver#mUpdateRecords
1988 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
1989 if (receiverRecords != null) {
1990 receiverRecords.remove(this.mProvider);
1991
1992 // and also remove the Receiver if it has no more update records
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001993 if (receiverRecords.size() == 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001994 removeUpdatesLocked(mReceiver);
1995 }
Mike Lockwood3a76fd62009-09-01 07:26:56 -04001996 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001997 }
1998
1999 @Override
2000 public String toString() {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002001 return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
gomo48f1a642017-11-10 20:35:46 -08002002 + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground"
2003 : " background")
Wyatt Riley19adc022018-05-22 13:30:51 -07002004 + ")" + " " + mRealRequest + " "
2005 + mReceiver.mWorkSource + "]";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002006 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002007 }
2008
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002009 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -07002010 String packageName, WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002011 IBinder binder = listener.asBinder();
2012 Receiver receiver = mReceivers.get(binder);
2013 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07002014 receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
2015 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002016 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002017 receiver.getListener().asBinder().linkToDeath(receiver, 0);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002018 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002019 Slog.e(TAG, "linkToDeath failed:", e);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002020 return null;
2021 }
Wen Jingcb3ab222014-03-27 13:42:59 +08002022 mReceivers.put(binder, receiver);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002023 }
2024 return receiver;
2025 }
2026
David Christie82edc9b2013-07-19 11:31:42 -07002027 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
David Christie40e57822013-07-30 11:36:48 -07002028 WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002029 Receiver receiver = mReceivers.get(intent);
2030 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07002031 receiver = new Receiver(null, intent, pid, uid, packageName, workSource,
2032 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002033 mReceivers.put(intent, receiver);
2034 }
2035 return receiver;
2036 }
2037
Victoria Lease37425c32012-10-16 16:08:48 -07002038 /**
2039 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
2040 * and consistency requirements.
2041 *
2042 * @param request the LocationRequest from which to create a sanitized version
Victoria Lease37425c32012-10-16 16:08:48 -07002043 * @return a version of request that meets the given resolution and consistency requirements
2044 * @hide
2045 */
gomo48f1a642017-11-10 20:35:46 -08002046 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel,
2047 boolean callerHasLocationHardwarePermission) {
Victoria Lease37425c32012-10-16 16:08:48 -07002048 LocationRequest sanitizedRequest = new LocationRequest(request);
gomo48f1a642017-11-10 20:35:46 -08002049 if (!callerHasLocationHardwarePermission) {
2050 // allow setting low power mode only for callers with location hardware permission
2051 sanitizedRequest.setLowPowerMode(false);
2052 }
Victoria Lease37425c32012-10-16 16:08:48 -07002053 if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
2054 switch (sanitizedRequest.getQuality()) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002055 case LocationRequest.ACCURACY_FINE:
Victoria Lease37425c32012-10-16 16:08:48 -07002056 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
Victoria Lease09016ab2012-09-16 12:33:15 -07002057 break;
2058 case LocationRequest.POWER_HIGH:
Victoria Lease37425c32012-10-16 16:08:48 -07002059 sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
Victoria Lease09016ab2012-09-16 12:33:15 -07002060 break;
2061 }
2062 // throttle
Victoria Lease37425c32012-10-16 16:08:48 -07002063 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
2064 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07002065 }
Victoria Lease37425c32012-10-16 16:08:48 -07002066 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
2067 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07002068 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07002069 }
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002070 // make getFastestInterval() the minimum of interval and fastest interval
Victoria Lease37425c32012-10-16 16:08:48 -07002071 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002072 request.setFastestInterval(request.getInterval());
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002073 }
Victoria Lease37425c32012-10-16 16:08:48 -07002074 return sanitizedRequest;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002075 }
2076
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002077 private void checkPackageName(String packageName) {
Nick Pellye0fd6932012-07-11 10:26:13 -07002078 if (packageName == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002079 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002080 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002081 int uid = Binder.getCallingUid();
Nick Pellye0fd6932012-07-11 10:26:13 -07002082 String[] packages = mPackageManager.getPackagesForUid(uid);
2083 if (packages == null) {
2084 throw new SecurityException("invalid UID " + uid);
2085 }
2086 for (String pkg : packages) {
2087 if (packageName.equals(pkg)) return;
2088 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002089 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002090 }
2091
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002092 private void checkPendingIntent(PendingIntent intent) {
2093 if (intent == null) {
2094 throw new IllegalArgumentException("invalid pending intent: " + intent);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002095 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002096 }
2097
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002098 private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent,
David Christie40e57822013-07-30 11:36:48 -07002099 int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002100 if (intent == null && listener == null) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002101 throw new IllegalArgumentException("need either listener or intent");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002102 } else if (intent != null && listener != null) {
2103 throw new IllegalArgumentException("cannot register both listener and intent");
2104 } else if (intent != null) {
2105 checkPendingIntent(intent);
David Christie40e57822013-07-30 11:36:48 -07002106 return getReceiverLocked(intent, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002107 } else {
David Christie40e57822013-07-30 11:36:48 -07002108 return getReceiverLocked(listener, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002109 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002110 }
2111
Nick Pellye0fd6932012-07-11 10:26:13 -07002112 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002113 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
2114 PendingIntent intent, String packageName) {
2115 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2116 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002117 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2118 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2119 request.getProvider());
David Christie82edc9b2013-07-19 11:31:42 -07002120 WorkSource workSource = request.getWorkSource();
Narayan Kamath32684dd2018-01-08 17:32:51 +00002121 if (workSource != null && !workSource.isEmpty()) {
David Christie40e57822013-07-30 11:36:48 -07002122 checkDeviceStatsAllowed();
2123 }
2124 boolean hideFromAppOps = request.getHideFromAppOps();
2125 if (hideFromAppOps) {
2126 checkUpdateAppOpsAllowed();
David Christie82edc9b2013-07-19 11:31:42 -07002127 }
gomo48f1a642017-11-10 20:35:46 -08002128 boolean callerHasLocationHardwarePermission =
2129 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
Maggieaa080f92018-01-04 15:35:11 -08002130 == PERMISSION_GRANTED;
gomo48f1a642017-11-10 20:35:46 -08002131 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel,
2132 callerHasLocationHardwarePermission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002133
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002134 final int pid = Binder.getCallingPid();
2135 final int uid = Binder.getCallingUid();
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002136 // providers may use public location API's, need to clear identity
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002137 long identity = Binder.clearCallingIdentity();
2138 try {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002139 // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2140 // a location.
David Christieb870dbf2015-06-22 12:42:53 -07002141 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002142
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002143 synchronized (mLock) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002144 Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
David Christie40e57822013-07-30 11:36:48 -07002145 packageName, workSource, hideFromAppOps);
Victoria Lease37425c32012-10-16 16:08:48 -07002146 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
Mike Lockwood2d4d1bf2010-10-18 17:06:26 -04002147 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002148 } finally {
2149 Binder.restoreCallingIdentity(identity);
2150 }
2151 }
2152
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002153 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
2154 int pid, int uid, String packageName) {
2155 // Figure out the provider. Either its explicitly request (legacy use cases), or
2156 // use the fused provider
2157 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2158 String name = request.getProvider();
Victoria Lease09016ab2012-09-16 12:33:15 -07002159 if (name == null) {
2160 throw new IllegalArgumentException("provider name must not be null");
2161 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -07002162
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002163 LocationProviderInterface provider = mProvidersByName.get(name);
2164 if (provider == null) {
Victoria Leaseb30f3832013-10-13 12:15:40 -07002165 throw new IllegalArgumentException("provider doesn't exist: " + name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002166 }
2167
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002168 UpdateRecord record = new UpdateRecord(name, request, receiver);
gomo48f1a642017-11-10 20:35:46 -08002169 if (D) {
2170 Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
2171 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
2172 + (record.mIsForegroundUid ? "foreground" : "background")
2173 + (isThrottlingExemptLocked(receiver.mIdentity)
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002174 ? " [whitelisted]" : "") + ")");
gomo48f1a642017-11-10 20:35:46 -08002175 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002176
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002177 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
2178 if (oldRecord != null) {
2179 oldRecord.disposeLocked(false);
2180 }
2181
Maggie2a9409e2018-03-21 11:47:28 -07002182 boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid, mCurrentUserId);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002183 if (isProviderEnabled) {
2184 applyRequirementsLocked(name);
2185 } else {
2186 // Notify the listener that updates are currently disabled
2187 receiver.callProviderEnabledLocked(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188 }
David Christie0b837452013-07-29 16:02:13 -07002189 // Update the monitoring here just in case multiple location requests were added to the
2190 // same receiver (this request may be high power and the initial might not have been).
2191 receiver.updateMonitoring(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192 }
2193
Nick Pellye0fd6932012-07-11 10:26:13 -07002194 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002195 public void removeUpdates(ILocationListener listener, PendingIntent intent,
2196 String packageName) {
2197 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002198
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002199 final int pid = Binder.getCallingPid();
2200 final int uid = Binder.getCallingUid();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002201
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002202 synchronized (mLock) {
David Christie82edc9b2013-07-19 11:31:42 -07002203 WorkSource workSource = null;
David Christie40e57822013-07-30 11:36:48 -07002204 boolean hideFromAppOps = false;
2205 Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid,
2206 packageName, workSource, hideFromAppOps);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002207
2208 // providers may use public location API's, need to clear identity
2209 long identity = Binder.clearCallingIdentity();
2210 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002211 removeUpdatesLocked(receiver);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002212 } finally {
2213 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002214 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002215 }
2216 }
2217
2218 private void removeUpdatesLocked(Receiver receiver) {
Dianne Hackborn7ff30112012-11-08 11:12:09 -08002219 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002220
2221 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
2222 receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
2223 synchronized (receiver) {
Victoria Lease0aa28602013-05-29 15:28:26 -07002224 receiver.clearPendingBroadcastsLocked();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002225 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002226 }
2227
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07002228 receiver.updateMonitoring(false);
2229
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002230 // Record which providers were associated with this listener
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002231 HashSet<String> providers = new HashSet<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002232 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2233 if (oldRecords != null) {
2234 // Call dispose() on the obsolete update records.
2235 for (UpdateRecord record : oldRecords.values()) {
David Christie2ff96af2014-01-30 16:09:37 -08002236 // Update statistics for historical location requests by package/provider
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002237 record.disposeLocked(false);
2238 }
2239 // Accumulate providers
2240 providers.addAll(oldRecords.keySet());
2241 }
2242
2243 // update provider
2244 for (String provider : providers) {
2245 // If provider is already disabled, don't need to do anything
Victoria Lease09eeaec2013-02-05 11:34:13 -08002246 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002247 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002248 }
2249
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002250 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002251 }
2252 }
2253
Dianne Hackbornc2293022013-02-06 23:14:49 -08002254 private void applyAllProviderRequirementsLocked() {
2255 for (LocationProviderInterface p : mProviders) {
2256 // If provider is already disabled, don't need to do anything
Dianne Hackborn64d41d72013-02-07 00:33:31 -08002257 if (!isAllowedByCurrentUserSettingsLocked(p.getName())) {
Dianne Hackbornc2293022013-02-06 23:14:49 -08002258 continue;
2259 }
2260
2261 applyRequirementsLocked(p.getName());
2262 }
2263 }
2264
Nick Pellye0fd6932012-07-11 10:26:13 -07002265 @Override
Nick Pelly4035f5a2012-08-17 14:43:49 -07002266 public Location getLastLocation(LocationRequest request, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002267 if (D) Log.d(TAG, "getLastLocation: " + request);
2268 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002269 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly4035f5a2012-08-17 14:43:49 -07002270 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002271 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2272 request.getProvider());
2273 // no need to sanitize this request, as only the provider name is used
Nick Pelly4035f5a2012-08-17 14:43:49 -07002274
David Christieb870dbf2015-06-22 12:42:53 -07002275 final int pid = Binder.getCallingPid();
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002276 final int uid = Binder.getCallingUid();
2277 final long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07002278 try {
2279 if (mBlacklist.isBlacklisted(packageName)) {
gomo48f1a642017-11-10 20:35:46 -08002280 if (D) {
2281 Log.d(TAG, "not returning last loc for blacklisted app: " +
2282 packageName);
2283 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002284 return null;
2285 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002286
David Christieb870dbf2015-06-22 12:42:53 -07002287 if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel)) {
gomo48f1a642017-11-10 20:35:46 -08002288 if (D) {
2289 Log.d(TAG, "not returning last loc for no op app: " +
2290 packageName);
2291 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002292 return null;
2293 }
2294
Victoria Leaseb711d572012-10-02 13:14:11 -07002295 synchronized (mLock) {
2296 // Figure out the provider. Either its explicitly request (deprecated API's),
2297 // or use the fused provider
2298 String name = request.getProvider();
2299 if (name == null) name = LocationManager.FUSED_PROVIDER;
2300 LocationProviderInterface provider = mProvidersByName.get(name);
2301 if (provider == null) return null;
2302
Maggie2a9409e2018-03-21 11:47:28 -07002303 if (!isAllowedByUserSettingsLocked(name, uid, mCurrentUserId)) return null;
Victoria Leaseb711d572012-10-02 13:14:11 -07002304
David Christie1b9b7b12013-04-15 15:31:11 -07002305 Location location;
2306 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2307 // Make sure that an app with coarse permissions can't get frequent location
2308 // updates by calling LocationManager.getLastKnownLocation repeatedly.
2309 location = mLastLocationCoarseInterval.get(name);
2310 } else {
2311 location = mLastLocation.get(name);
2312 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002313 if (location == null) {
2314 return null;
2315 }
Wei Wangdd070f22018-06-21 11:29:40 -07002316
2317 // Don't return stale location to apps with foreground-only location permission.
Wei Wangb86334f2018-07-03 16:33:24 -07002318 String op = resolutionLevelToOpStr(allowedResolutionLevel);
Wei Wangdd070f22018-06-21 11:29:40 -07002319 long locationAgeMs = SystemClock.elapsedRealtime() -
2320 location.getElapsedRealtimeNanos() / NANOS_PER_MILLI;
2321 if ((locationAgeMs > mLastLocationMaxAgeMs)
2322 && (mAppOps.unsafeCheckOp(op, uid, packageName)
2323 == AppOpsManager.MODE_FOREGROUND)) {
2324 return null;
2325 }
2326
Victoria Lease37425c32012-10-16 16:08:48 -07002327 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
gomo48f1a642017-11-10 20:35:46 -08002328 Location noGPSLocation = location.getExtraLocation(
2329 Location.EXTRA_NO_GPS_LOCATION);
Victoria Leaseb711d572012-10-02 13:14:11 -07002330 if (noGPSLocation != null) {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002331 return new Location(mLocationFudger.getOrCreate(noGPSLocation));
Victoria Leaseb711d572012-10-02 13:14:11 -07002332 }
Victoria Lease37425c32012-10-16 16:08:48 -07002333 } else {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002334 return new Location(location);
Victoria Lease09016ab2012-09-16 12:33:15 -07002335 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002336 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002337 return null;
2338 } finally {
2339 Binder.restoreCallingIdentity(identity);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002340 }
2341 }
2342
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002343 /**
2344 * Provides an interface to inject and set the last location if location is not available
2345 * currently.
2346 *
2347 * This helps in cases where the product (Cars for example) has saved the last known location
2348 * before powering off. This interface lets the client inject the saved location while the GPS
2349 * chipset is getting its first fix, there by improving user experience.
2350 *
2351 * @param location - Location object to inject
2352 * @return true if update was successful, false if not
2353 */
2354 @Override
2355 public boolean injectLocation(Location location) {
2356 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
2357 "Location Hardware permission not granted to inject location");
2358 mContext.enforceCallingPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
2359 "Access Fine Location permission not granted to inject Location");
2360
2361 if (location == null) {
2362 if (D) {
2363 Log.d(TAG, "injectLocation(): called with null location");
2364 }
2365 return false;
2366 }
2367 LocationProviderInterface p = null;
2368 String provider = location.getProvider();
2369 if (provider != null) {
2370 p = mProvidersByName.get(provider);
2371 }
2372 if (p == null) {
2373 if (D) {
2374 Log.d(TAG, "injectLocation(): unknown provider");
2375 }
2376 return false;
2377 }
2378 synchronized (mLock) {
2379 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
2380 if (D) {
2381 Log.d(TAG, "Location disabled in Settings for current user:" + mCurrentUserId);
2382 }
2383 return false;
2384 } else {
2385 // NOTE: If last location is already available, location is not injected. If
2386 // provider's normal source (like a GPS chipset) have already provided an output,
2387 // there is no need to inject this location.
2388 if (mLastLocation.get(provider) == null) {
2389 updateLastLocationLocked(location, provider);
2390 } else {
2391 if (D) {
2392 Log.d(TAG, "injectLocation(): Location exists. Not updating");
2393 }
2394 return false;
2395 }
2396 }
2397 }
2398 return true;
2399 }
2400
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002401 @Override
2402 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
2403 String packageName) {
2404 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002405 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2406 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002407 checkPendingIntent(intent);
2408 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002409 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2410 request.getProvider());
gomo48f1a642017-11-10 20:35:46 -08002411 // Require that caller can manage given document
2412 boolean callerHasLocationHardwarePermission =
2413 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
Maggieaa080f92018-01-04 15:35:11 -08002414 == PERMISSION_GRANTED;
gomo48f1a642017-11-10 20:35:46 -08002415 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel,
2416 callerHasLocationHardwarePermission);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002417
Victoria Lease37425c32012-10-16 16:08:48 -07002418 if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002419
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002420 // geo-fence manager uses the public location API, need to clear identity
2421 int uid = Binder.getCallingUid();
Xiaohui Chena4490622015-09-22 15:29:31 -07002422 // TODO: http://b/23822629
2423 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
Victoria Lease56e675b2012-11-05 19:25:06 -08002424 // temporary measure until geofences work for secondary users
2425 Log.w(TAG, "proximity alerts are currently available only to the primary user");
2426 return;
2427 }
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002428 long identity = Binder.clearCallingIdentity();
2429 try {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002430 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
2431 uid, packageName);
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002432 } finally {
2433 Binder.restoreCallingIdentity(identity);
2434 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002435 }
2436
2437 @Override
2438 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002439 checkPendingIntent(intent);
2440 checkPackageName(packageName);
2441
2442 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2443
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002444 // geo-fence manager uses the public location API, need to clear identity
2445 long identity = Binder.clearCallingIdentity();
2446 try {
2447 mGeofenceManager.removeFence(geofence, intent);
2448 } finally {
2449 Binder.restoreCallingIdentity(identity);
2450 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002451 }
2452
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002453 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002454 public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002455 if (!hasGnssPermissions(packageName) || mGnssStatusProvider == null) {
Takayuki Hoshib254ab6a2014-10-23 16:46:02 +09002456 return false;
2457 }
2458
Anil Admal75b9fd62018-11-28 11:22:50 -08002459 // TODO(b/120449926): The GNSS status listeners should be handled similar to the GNSS
2460 // measurements listeners.
2461 return mGnssStatusProvider.addListener(callback, Binder.getCallingUid(), packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002462 }
2463
Nick Pellye0fd6932012-07-11 10:26:13 -07002464 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002465 public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
Anil Admal75b9fd62018-11-28 11:22:50 -08002466 mGnssStatusProvider.removeListener(callback);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002467 }
2468
Nick Pellye0fd6932012-07-11 10:26:13 -07002469 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002470 public boolean addGnssMeasurementsListener(
gomo48f1a642017-11-10 20:35:46 -08002471 IGnssMeasurementsListener listener, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002472 if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
destradaaea8a8a62014-06-23 18:19:03 -07002473 return false;
2474 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002475
2476 synchronized (mLock) {
2477 Identity callerIdentity
2478 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
Anil Admal75b9fd62018-11-28 11:22:50 -08002479 // TODO(b/120481270): Register for client death notification and update map.
Wyatt Riley11cc7492018-01-17 08:48:27 -08002480 mGnssMeasurementsListeners.put(listener.asBinder(), callerIdentity);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002481 long identity = Binder.clearCallingIdentity();
2482 try {
2483 if (isThrottlingExemptLocked(callerIdentity)
2484 || isImportanceForeground(
gomo48f1a642017-11-10 20:35:46 -08002485 mActivityManager.getPackageImportance(packageName))) {
Anil Admal75b9fd62018-11-28 11:22:50 -08002486 return mGnssMeasurementsProvider.addListener(listener,
2487 callerIdentity.mUid, callerIdentity.mPackageName);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002488 }
2489 } finally {
2490 Binder.restoreCallingIdentity(identity);
2491 }
2492
2493 return true;
2494 }
destradaaea8a8a62014-06-23 18:19:03 -07002495 }
2496
2497 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002498 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
2499 if (mGnssMeasurementsProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002500 synchronized (mLock) {
Wyatt Riley11cc7492018-01-17 08:48:27 -08002501 mGnssMeasurementsListeners.remove(listener.asBinder());
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002502 mGnssMeasurementsProvider.removeListener(listener);
2503 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002504 }
destradaaea8a8a62014-06-23 18:19:03 -07002505 }
2506
2507 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002508 public boolean addGnssNavigationMessageListener(
2509 IGnssNavigationMessageListener listener,
destradaa4b3e3932014-07-21 18:01:47 -07002510 String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002511 if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) {
destradaa4b3e3932014-07-21 18:01:47 -07002512 return false;
2513 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002514
2515 synchronized (mLock) {
2516 Identity callerIdentity
gomo48f1a642017-11-10 20:35:46 -08002517 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
Anil Admal75b9fd62018-11-28 11:22:50 -08002518 // TODO(b/120481270): Register for client death notification and update map.
Wyatt Riley11cc7492018-01-17 08:48:27 -08002519 mGnssNavigationMessageListeners.put(listener.asBinder(), callerIdentity);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002520 long identity = Binder.clearCallingIdentity();
2521 try {
2522 if (isThrottlingExemptLocked(callerIdentity)
2523 || isImportanceForeground(
gomo48f1a642017-11-10 20:35:46 -08002524 mActivityManager.getPackageImportance(packageName))) {
Anil Admal75b9fd62018-11-28 11:22:50 -08002525 return mGnssNavigationMessageProvider.addListener(listener,
2526 callerIdentity.mUid, callerIdentity.mPackageName);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002527 }
2528 } finally {
2529 Binder.restoreCallingIdentity(identity);
2530 }
2531
2532 return true;
2533 }
destradaa4b3e3932014-07-21 18:01:47 -07002534 }
2535
2536 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002537 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
2538 if (mGnssNavigationMessageProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002539 synchronized (mLock) {
Wyatt Riley11cc7492018-01-17 08:48:27 -08002540 mGnssNavigationMessageListeners.remove(listener.asBinder());
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002541 mGnssNavigationMessageProvider.removeListener(listener);
2542 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002543 }
destradaa4b3e3932014-07-21 18:01:47 -07002544 }
2545
2546 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002547 public boolean sendExtraCommand(String provider, String command, Bundle extras) {
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002548 if (provider == null) {
2549 // throw NullPointerException to remain compatible with previous implementation
2550 throw new NullPointerException();
2551 }
Victoria Lease37425c32012-10-16 16:08:48 -07002552 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2553 provider);
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002554
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002555 // and check for ACCESS_LOCATION_EXTRA_COMMANDS
Mike Lockwoodb7e99222009-07-07 13:18:21 -04002556 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
Maggieaa080f92018-01-04 15:35:11 -08002557 != PERMISSION_GRANTED)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002558 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
2559 }
2560
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002561 synchronized (mLock) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002562 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002563 if (p == null) return false;
Nick Pellye0fd6932012-07-11 10:26:13 -07002564
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002565 return p.sendExtraCommand(command, extras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002566 }
2567 }
2568
Nick Pellye0fd6932012-07-11 10:26:13 -07002569 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002570 public boolean sendNiResponse(int notifId, int userResponse) {
Mike Lockwood18ad9f62009-08-27 14:01:23 -07002571 if (Binder.getCallingUid() != Process.myUid()) {
2572 throw new SecurityException(
2573 "calling sendNiResponse from outside of the system is not allowed");
2574 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002575 try {
2576 return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002577 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002578 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
Danke Xie22d1f9f2009-08-18 18:28:45 -04002579 return false;
2580 }
2581 }
2582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002583 /**
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002584 * @return null if the provider does not exist
Alexey Tarasovf2db9fb2009-09-01 02:37:07 +11002585 * @throws SecurityException if the provider is not allowed to be
gomo48f1a642017-11-10 20:35:46 -08002586 * accessed by the caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002587 */
Nick Pellye0fd6932012-07-11 10:26:13 -07002588 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002589 public ProviderProperties getProviderProperties(String provider) {
Laurent Tub7f9d252012-10-16 14:25:00 -07002590 if (mProvidersByName.get(provider) == null) {
David Christie2ff96af2014-01-30 16:09:37 -08002591 return null;
Laurent Tub7f9d252012-10-16 14:25:00 -07002592 }
2593
Victoria Lease37425c32012-10-16 16:08:48 -07002594 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2595 provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002596
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002597 LocationProviderInterface p;
2598 synchronized (mLock) {
2599 p = mProvidersByName.get(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600 }
2601
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002602 if (p == null) return null;
2603 return p.getProperties();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002604 }
2605
Jason Monkb71218a2015-06-17 14:44:39 -04002606 /**
2607 * @return null if the provider does not exist
2608 * @throws SecurityException if the provider is not allowed to be
gomo48f1a642017-11-10 20:35:46 -08002609 * accessed by the caller
Jason Monkb71218a2015-06-17 14:44:39 -04002610 */
2611 @Override
2612 public String getNetworkProviderPackage() {
2613 LocationProviderInterface p;
2614 synchronized (mLock) {
2615 if (mProvidersByName.get(LocationManager.NETWORK_PROVIDER) == null) {
2616 return null;
2617 }
2618 p = mProvidersByName.get(LocationManager.NETWORK_PROVIDER);
2619 }
2620
2621 if (p instanceof LocationProviderProxy) {
2622 return ((LocationProviderProxy) p).getConnectedPackageName();
2623 }
2624 return null;
2625 }
2626
Maggieaa080f92018-01-04 15:35:11 -08002627 /**
Maggie2a9409e2018-03-21 11:47:28 -07002628 * Returns the current location enabled/disabled status for a user
2629 *
2630 * @param userId the id of the user
2631 * @return true if location is enabled
2632 */
2633 @Override
2634 public boolean isLocationEnabledForUser(int userId) {
2635 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2636 checkInteractAcrossUsersPermission(userId);
2637
2638 long identity = Binder.clearCallingIdentity();
2639 try {
2640 synchronized (mLock) {
2641 final String allowedProviders = Settings.Secure.getStringForUser(
2642 mContext.getContentResolver(),
2643 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
2644 userId);
2645 if (allowedProviders == null) {
2646 return false;
2647 }
2648 final List<String> providerList = Arrays.asList(allowedProviders.split(","));
2649 for(String provider : mRealProviders.keySet()) {
2650 if (provider.equals(LocationManager.PASSIVE_PROVIDER)
2651 || provider.equals(LocationManager.FUSED_PROVIDER)) {
2652 continue;
2653 }
2654 if (providerList.contains(provider)) {
2655 return true;
2656 }
2657 }
2658 return false;
2659 }
2660 } finally {
2661 Binder.restoreCallingIdentity(identity);
2662 }
2663 }
2664
2665 /**
2666 * Enable or disable location for a user
2667 *
2668 * @param enabled true to enable location, false to disable location
2669 * @param userId the id of the user
2670 */
2671 @Override
2672 public void setLocationEnabledForUser(boolean enabled, int userId) {
2673 mContext.enforceCallingPermission(
2674 android.Manifest.permission.WRITE_SECURE_SETTINGS,
2675 "Requires WRITE_SECURE_SETTINGS permission");
2676
2677 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2678 checkInteractAcrossUsersPermission(userId);
2679
2680 long identity = Binder.clearCallingIdentity();
2681 try {
2682 synchronized (mLock) {
2683 final Set<String> allRealProviders = mRealProviders.keySet();
2684 // Update all providers on device plus gps and network provider when disabling
2685 // location
2686 Set<String> allProvidersSet = new ArraySet<>(allRealProviders.size() + 2);
2687 allProvidersSet.addAll(allRealProviders);
2688 // When disabling location, disable gps and network provider that could have been
2689 // enabled by location mode api.
2690 if (enabled == false) {
2691 allProvidersSet.add(LocationManager.GPS_PROVIDER);
2692 allProvidersSet.add(LocationManager.NETWORK_PROVIDER);
2693 }
2694 if (allProvidersSet.isEmpty()) {
2695 return;
2696 }
2697 // to ensure thread safety, we write the provider name with a '+' or '-'
2698 // and let the SettingsProvider handle it rather than reading and modifying
2699 // the list of enabled providers.
2700 final String prefix = enabled ? "+" : "-";
2701 StringBuilder locationProvidersAllowed = new StringBuilder();
2702 for (String provider : allProvidersSet) {
2703 if (provider.equals(LocationManager.PASSIVE_PROVIDER)
2704 || provider.equals(LocationManager.FUSED_PROVIDER)) {
2705 continue;
2706 }
2707 locationProvidersAllowed.append(prefix);
2708 locationProvidersAllowed.append(provider);
2709 locationProvidersAllowed.append(",");
2710 }
2711 // Remove the trailing comma
2712 locationProvidersAllowed.setLength(locationProvidersAllowed.length() - 1);
2713 Settings.Secure.putStringForUser(
2714 mContext.getContentResolver(),
2715 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
2716 locationProvidersAllowed.toString(),
2717 userId);
2718 }
2719 } finally {
2720 Binder.restoreCallingIdentity(identity);
2721 }
2722 }
2723
2724 /**
2725 * Returns the current enabled/disabled status of a location provider and user
2726 *
2727 * @param provider name of the provider
2728 * @param userId the id of the user
2729 * @return true if the provider exists and is enabled
2730 */
2731 @Override
2732 public boolean isProviderEnabledForUser(String provider, int userId) {
2733 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2734 checkInteractAcrossUsersPermission(userId);
2735
2736 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2737 // so we discourage its use
2738 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
2739
2740 int uid = Binder.getCallingUid();
2741 synchronized (mLock) {
2742 LocationProviderInterface p = mProvidersByName.get(provider);
2743 return p != null
2744 && isAllowedByUserSettingsLocked(provider, uid, userId);
2745 }
2746 }
2747
2748 /**
2749 * Enable or disable a single location provider.
2750 *
2751 * @param provider name of the provider
2752 * @param enabled true to enable the provider. False to disable the provider
2753 * @param userId the id of the user to set
2754 * @return true if the value was set, false on errors
2755 */
2756 @Override
2757 public boolean setProviderEnabledForUser(String provider, boolean enabled, int userId) {
2758 mContext.enforceCallingPermission(
2759 android.Manifest.permission.WRITE_SECURE_SETTINGS,
2760 "Requires WRITE_SECURE_SETTINGS permission");
2761
2762 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2763 checkInteractAcrossUsersPermission(userId);
2764
2765 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2766 // so we discourage its use
2767 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
2768
2769 long identity = Binder.clearCallingIdentity();
2770 try {
2771 synchronized (mLock) {
2772 // No such provider exists
2773 if (!mProvidersByName.containsKey(provider)) return false;
2774
2775 // If it is a test provider, do not write to Settings.Secure
2776 if (mMockProviders.containsKey(provider)) {
2777 setTestProviderEnabled(provider, enabled);
2778 return true;
2779 }
2780
2781 // to ensure thread safety, we write the provider name with a '+' or '-'
2782 // and let the SettingsProvider handle it rather than reading and modifying
2783 // the list of enabled providers.
2784 String providerChange = (enabled ? "+" : "-") + provider;
2785 return Settings.Secure.putStringForUser(
2786 mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
2787 providerChange, userId);
2788 }
2789 } finally {
2790 Binder.restoreCallingIdentity(identity);
2791 }
2792 }
2793
2794 /**
Maggieaa080f92018-01-04 15:35:11 -08002795 * Read location provider status from Settings.Secure
2796 *
2797 * @param provider the location provider to query
2798 * @param userId the user id to query
2799 * @return true if the provider is enabled
2800 */
2801 private boolean isLocationProviderEnabledForUser(String provider, int userId) {
2802 long identity = Binder.clearCallingIdentity();
2803 try {
2804 // Use system settings
2805 ContentResolver cr = mContext.getContentResolver();
2806 String allowedProviders = Settings.Secure.getStringForUser(
2807 cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userId);
2808 return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
2809 } finally {
2810 Binder.restoreCallingIdentity(identity);
2811 }
2812 }
2813
2814 /**
Maggie2a9409e2018-03-21 11:47:28 -07002815 * Method for checking INTERACT_ACROSS_USERS permission if specified user id is not the same as
2816 * current user id
2817 *
2818 * @param userId the user id to get or set value
2819 */
2820 private void checkInteractAcrossUsersPermission(int userId) {
2821 int uid = Binder.getCallingUid();
2822 if (UserHandle.getUserId(uid) != userId) {
2823 if (ActivityManager.checkComponentPermission(
2824 android.Manifest.permission.INTERACT_ACROSS_USERS, uid, -1, true)
2825 != PERMISSION_GRANTED) {
2826 throw new SecurityException("Requires INTERACT_ACROSS_USERS permission");
2827 }
2828 }
2829 }
2830
2831 /**
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002832 * Returns "true" if the UID belongs to a bound location provider.
2833 *
2834 * @param uid the uid
2835 * @return true if uid belongs to a bound location provider
2836 */
2837 private boolean isUidALocationProvider(int uid) {
2838 if (uid == Process.SYSTEM_UID) {
2839 return true;
2840 }
2841 if (mGeocodeProvider != null) {
David Christie1f141c12014-05-14 15:11:15 -07002842 if (doesUidHavePackage(uid, mGeocodeProvider.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002843 }
2844 for (LocationProviderProxy proxy : mProxyProviders) {
David Christie1f141c12014-05-14 15:11:15 -07002845 if (doesUidHavePackage(uid, proxy.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002846 }
2847 return false;
2848 }
2849
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002850 private void checkCallerIsProvider() {
2851 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
Maggieaa080f92018-01-04 15:35:11 -08002852 == PERMISSION_GRANTED) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002853 return;
2854 }
2855
2856 // Previously we only used the INSTALL_LOCATION_PROVIDER
2857 // check. But that is system or signature
2858 // protection level which is not flexible enough for
2859 // providers installed oustide the system image. So
2860 // also allow providers with a UID matching the
2861 // currently bound package name
2862
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002863 if (isUidALocationProvider(Binder.getCallingUid())) {
2864 return;
2865 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002866
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002867 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
2868 "or UID of a currently bound location provider");
2869 }
2870
David Christie1f141c12014-05-14 15:11:15 -07002871 /**
2872 * Returns true if the given package belongs to the given uid.
2873 */
2874 private boolean doesUidHavePackage(int uid, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002875 if (packageName == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002876 return false;
2877 }
David Christie1f141c12014-05-14 15:11:15 -07002878 String[] packageNames = mPackageManager.getPackagesForUid(uid);
2879 if (packageNames == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002880 return false;
2881 }
David Christie1f141c12014-05-14 15:11:15 -07002882 for (String name : packageNames) {
2883 if (packageName.equals(name)) {
2884 return true;
2885 }
2886 }
2887 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002888 }
2889
Nick Pellye0fd6932012-07-11 10:26:13 -07002890 @Override
Mike Lockwooda4903f22010-02-17 06:42:23 -05002891 public void reportLocation(Location location, boolean passive) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002892 checkCallerIsProvider();
Mike Lockwood275555c2009-05-01 11:30:34 -04002893
Nick Pelly2eeeec22012-07-18 13:13:37 -07002894 if (!location.isComplete()) {
2895 Log.w(TAG, "Dropping incomplete location: " + location);
2896 return;
2897 }
2898
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002899 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location);
2900 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location);
Mike Lockwooda4903f22010-02-17 06:42:23 -05002901 m.arg1 = (passive ? 1 : 0);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002902 mLocationHandler.sendMessageAtFrontOfQueue(m);
2903 }
2904
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002905
Laurent Tu75defb62012-11-01 16:21:52 -07002906 private static boolean shouldBroadcastSafe(
2907 Location loc, Location lastLoc, UpdateRecord record, long now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002908 // Always broadcast the first update
2909 if (lastLoc == null) {
2910 return true;
2911 }
2912
Nick Pellyf1be6862012-05-15 10:53:42 -07002913 // Check whether sufficient time has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002914 long minTime = record.mRealRequest.getFastestInterval();
David Christie1b9b7b12013-04-15 15:31:11 -07002915 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
2916 / NANOS_PER_MILLI;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002917 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002918 return false;
2919 }
2920
2921 // Check whether sufficient distance has been traveled
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002922 double minDistance = record.mRealRequest.getSmallestDisplacement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002923 if (minDistance > 0.0) {
2924 if (loc.distanceTo(lastLoc) <= minDistance) {
2925 return false;
2926 }
2927 }
2928
Laurent Tu75defb62012-11-01 16:21:52 -07002929 // Check whether sufficient number of udpates is left
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002930 if (record.mRealRequest.getNumUpdates() <= 0) {
Laurent Tu75defb62012-11-01 16:21:52 -07002931 return false;
2932 }
2933
2934 // Check whether the expiry date has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002935 return record.mRealRequest.getExpireAt() >= now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002936 }
2937
Mike Lockwooda4903f22010-02-17 06:42:23 -05002938 private void handleLocationChangedLocked(Location location, boolean passive) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002939 if (D) Log.d(TAG, "incoming location: " + location);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002940 long now = SystemClock.elapsedRealtime();
Mike Lockwooda4903f22010-02-17 06:42:23 -05002941 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
Laurent Tu60ec50a2012-10-04 17:00:10 -07002942 // Skip if the provider is unknown.
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002943 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002944 if (p == null) return;
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002945 updateLastLocationLocked(location, provider);
2946 // mLastLocation should have been updated from the updateLastLocationLocked call above.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002947 Location lastLocation = mLastLocation.get(provider);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002948 if (lastLocation == null) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002949 Log.e(TAG, "handleLocationChangedLocked() updateLastLocation failed");
2950 return;
Mike Lockwood4e50b782009-04-03 08:24:43 -07002951 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002952
David Christie1b9b7b12013-04-15 15:31:11 -07002953 // Update last known coarse interval location if enough time has passed.
2954 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider);
2955 if (lastLocationCoarseInterval == null) {
2956 lastLocationCoarseInterval = new Location(location);
2957 mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval);
2958 }
2959 long timeDiffNanos = location.getElapsedRealtimeNanos()
2960 - lastLocationCoarseInterval.getElapsedRealtimeNanos();
2961 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
2962 lastLocationCoarseInterval.set(location);
2963 }
2964 // Don't ever return a coarse location that is more recent than the allowed update
2965 // interval (i.e. don't allow an app to keep registering and unregistering for
2966 // location updates to overcome the minimum interval).
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002967 Location noGPSLocation =
David Christie1b9b7b12013-04-15 15:31:11 -07002968 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2969
Laurent Tu60ec50a2012-10-04 17:00:10 -07002970 // Skip if there are no UpdateRecords for this provider.
2971 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
2972 if (records == null || records.size() == 0) return;
2973
Victoria Lease09016ab2012-09-16 12:33:15 -07002974 // Fetch coarse location
2975 Location coarseLocation = null;
David Christie1b9b7b12013-04-15 15:31:11 -07002976 if (noGPSLocation != null) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002977 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
2978 }
2979
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002980 // Fetch latest status update time
2981 long newStatusUpdateTime = p.getStatusUpdateTime();
2982
David Christie2ff96af2014-01-30 16:09:37 -08002983 // Get latest status
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002984 Bundle extras = new Bundle();
2985 int status = p.getStatus(extras);
2986
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002987 ArrayList<Receiver> deadReceivers = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002988 ArrayList<UpdateRecord> deadUpdateRecords = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07002989
Soonil Nagarkar94749f72018-11-08 11:46:43 -08002990 // Broadcast location to all listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002991 for (UpdateRecord r : records) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002992 Receiver receiver = r.mReceiver;
Mike Lockwood03ca2162010-04-01 08:10:09 -07002993 boolean receiverDead = false;
Nick Pelly4035f5a2012-08-17 14:43:49 -07002994
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002995 int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid);
2996 if (!isCurrentProfile(receiverUserId)
2997 && !isUidALocationProvider(receiver.mIdentity.mUid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002998 if (D) {
Victoria Lease269518e2012-10-29 08:25:39 -07002999 Log.d(TAG, "skipping loc update for background user " + receiverUserId +
Victoria Leaseb711d572012-10-02 13:14:11 -07003000 " (current user: " + mCurrentUserId + ", app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08003001 receiver.mIdentity.mPackageName + ")");
Victoria Leaseb711d572012-10-02 13:14:11 -07003002 }
3003 continue;
3004 }
3005
Soonil Nagarkar681d7112017-02-23 17:14:16 -08003006 if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) {
gomo48f1a642017-11-10 20:35:46 -08003007 if (D) {
3008 Log.d(TAG, "skipping loc update for blacklisted app: " +
3009 receiver.mIdentity.mPackageName);
3010 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07003011 continue;
3012 }
3013
Soonil Nagarkar681d7112017-02-23 17:14:16 -08003014 if (!reportLocationAccessNoThrow(
3015 receiver.mIdentity.mPid,
3016 receiver.mIdentity.mUid,
3017 receiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08003018 receiver.mAllowedResolutionLevel)) {
gomo48f1a642017-11-10 20:35:46 -08003019 if (D) {
3020 Log.d(TAG, "skipping loc update for no op app: " +
3021 receiver.mIdentity.mPackageName);
3022 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08003023 continue;
3024 }
3025
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003026 Location notifyLocation;
Victoria Lease37425c32012-10-16 16:08:48 -07003027 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
3028 notifyLocation = coarseLocation; // use coarse location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003029 } else {
Victoria Lease37425c32012-10-16 16:08:48 -07003030 notifyLocation = lastLocation; // use fine location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003031 }
Victoria Lease09016ab2012-09-16 12:33:15 -07003032 if (notifyLocation != null) {
3033 Location lastLoc = r.mLastFixBroadcast;
Laurent Tu75defb62012-11-01 16:21:52 -07003034 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) {
Victoria Lease09016ab2012-09-16 12:33:15 -07003035 if (lastLoc == null) {
3036 lastLoc = new Location(notifyLocation);
3037 r.mLastFixBroadcast = lastLoc;
3038 } else {
3039 lastLoc.set(notifyLocation);
3040 }
3041 if (!receiver.callLocationChangedLocked(notifyLocation)) {
3042 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
3043 receiverDead = true;
3044 }
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07003045 r.mRealRequest.decrementNumUpdates();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003046 }
3047 }
3048
Soonil Nagarkar94749f72018-11-08 11:46:43 -08003049 // TODO: location provider status callbacks have been disabled and deprecated, and are
3050 // guarded behind this setting now. should be removed completely post-Q
3051 if (Settings.Global.getInt(mContext.getContentResolver(),
3052 LOCATION_DISABLE_STATUS_CALLBACKS, 1) == 0) {
3053 long prevStatusUpdateTime = r.mLastStatusBroadcast;
3054 if ((newStatusUpdateTime > prevStatusUpdateTime)
3055 && (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003056
Soonil Nagarkar94749f72018-11-08 11:46:43 -08003057 r.mLastStatusBroadcast = newStatusUpdateTime;
3058 if (!receiver.callStatusChangedLocked(provider, status, extras)) {
3059 receiverDead = true;
3060 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
3061 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07003062 }
3063 }
3064
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003065 // track expired records
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07003066 if (r.mRealRequest.getNumUpdates() <= 0 || r.mRealRequest.getExpireAt() < now) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003067 if (deadUpdateRecords == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003068 deadUpdateRecords = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003069 }
3070 deadUpdateRecords.add(r);
3071 }
3072 // track dead receivers
3073 if (receiverDead) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07003074 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003075 deadReceivers = new ArrayList<>();
Mike Lockwood03ca2162010-04-01 08:10:09 -07003076 }
3077 if (!deadReceivers.contains(receiver)) {
3078 deadReceivers.add(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003079 }
3080 }
3081 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003082
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003083 // remove dead records and receivers outside the loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003084 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003085 for (Receiver receiver : deadReceivers) {
3086 removeUpdatesLocked(receiver);
3087 }
3088 }
3089 if (deadUpdateRecords != null) {
3090 for (UpdateRecord r : deadUpdateRecords) {
3091 r.disposeLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003092 }
Victoria Lease8b38b292012-12-04 15:04:43 -08003093 applyRequirementsLocked(provider);
3094 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003095 }
3096
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08003097 /**
3098 * Updates last location with the given location
3099 *
3100 * @param location new location to update
3101 * @param provider Location provider to update for
3102 */
3103 private void updateLastLocationLocked(Location location, String provider) {
3104 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
3105 Location lastNoGPSLocation;
3106 Location lastLocation = mLastLocation.get(provider);
3107 if (lastLocation == null) {
3108 lastLocation = new Location(provider);
3109 mLastLocation.put(provider, lastLocation);
3110 } else {
3111 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
3112 if (noGPSLocation == null && lastNoGPSLocation != null) {
3113 // New location has no no-GPS location: adopt last no-GPS location. This is set
3114 // directly into location because we do not want to notify COARSE clients.
3115 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
3116 }
3117 }
3118 lastLocation.set(location);
3119 }
3120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003121 private class LocationWorkerHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08003122 public LocationWorkerHandler(Looper looper) {
3123 super(looper, null, true);
3124 }
3125
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003126 @Override
3127 public void handleMessage(Message msg) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003128 switch (msg.what) {
3129 case MSG_LOCATION_CHANGED:
3130 handleLocationChanged((Location) msg.obj, msg.arg1 == 1);
3131 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003132 }
3133 }
3134 }
3135
Victoria Lease54ca7ae2013-01-08 09:39:50 -08003136 private boolean isMockProvider(String provider) {
3137 synchronized (mLock) {
3138 return mMockProviders.containsKey(provider);
3139 }
3140 }
3141
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003142 private void handleLocationChanged(Location location, boolean passive) {
Victoria Lease54ca7ae2013-01-08 09:39:50 -08003143 // create a working copy of the incoming Location so that the service can modify it without
3144 // disturbing the caller's copy
3145 Location myLocation = new Location(location);
3146 String provider = myLocation.getProvider();
3147
3148 // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this
3149 // bit if location did not come from a mock provider because passive/fused providers can
3150 // forward locations from mock providers, and should not grant them legitimacy in doing so.
3151 if (!myLocation.isFromMockProvider() && isMockProvider(provider)) {
3152 myLocation.setIsFromMockProvider(true);
3153 }
Jeff Sharkey5e613312012-01-30 11:16:20 -08003154
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003155 synchronized (mLock) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08003156 if (isAllowedByCurrentUserSettingsLocked(provider)) {
3157 if (!passive) {
3158 // notify passive provider of the new location
3159 mPassiveProvider.updateLocation(myLocation);
3160 }
Victoria Lease54ca7ae2013-01-08 09:39:50 -08003161 handleLocationChangedLocked(myLocation, passive);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003163 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003164 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003165
Mike Lockwoode97ae402010-09-29 15:23:46 -04003166 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
3167 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003168 public void onPackageDisappeared(String packageName, int reason) {
3169 // remove all receivers associated with this package name
3170 synchronized (mLock) {
3171 ArrayList<Receiver> deadReceivers = null;
3172
3173 for (Receiver receiver : mReceivers.values()) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08003174 if (receiver.mIdentity.mPackageName.equals(packageName)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003175 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003176 deadReceivers = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003177 }
3178 deadReceivers.add(receiver);
3179 }
3180 }
3181
3182 // perform removal outside of mReceivers loop
3183 if (deadReceivers != null) {
3184 for (Receiver receiver : deadReceivers) {
3185 removeUpdatesLocked(receiver);
3186 }
3187 }
3188 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003189 }
Mike Lockwoode97ae402010-09-29 15:23:46 -04003190 };
3191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003192 // Geocoder
3193
Nick Pellye0fd6932012-07-11 10:26:13 -07003194 @Override
Mike Lockwoode15735a2010-09-20 17:48:47 -04003195 public boolean geocoderIsPresent() {
Mark Vandevoorde01ac80b2010-05-21 15:43:26 -07003196 return mGeocodeProvider != null;
3197 }
3198
Nick Pellye0fd6932012-07-11 10:26:13 -07003199 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003200 public String getFromLocation(double latitude, double longitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05003201 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04003202 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05003203 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
3204 params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003205 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04003206 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003207 }
3208
Mike Lockwooda55c3212009-04-15 11:10:11 -04003209
Nick Pellye0fd6932012-07-11 10:26:13 -07003210 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003211 public String getFromLocationName(String locationName,
Mike Lockwooda55c3212009-04-15 11:10:11 -04003212 double lowerLeftLatitude, double lowerLeftLongitude,
3213 double upperRightLatitude, double upperRightLongitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05003214 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04003215
3216 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05003217 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
3218 lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
3219 maxResults, params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003220 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04003221 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003222 }
3223
3224 // Mock Providers
3225
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003226 private boolean canCallerAccessMockLocation(String opPackageName) {
3227 return mAppOps.noteOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(),
3228 opPackageName) == AppOpsManager.MODE_ALLOWED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003229 }
3230
Nick Pellye0fd6932012-07-11 10:26:13 -07003231 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003232 public void addTestProvider(String name, ProviderProperties properties, String opPackageName) {
3233 if (!canCallerAccessMockLocation(opPackageName)) {
3234 return;
3235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003236
Mike Lockwooda4903f22010-02-17 06:42:23 -05003237 if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
3238 throw new IllegalArgumentException("Cannot mock the passive location provider");
3239 }
3240
Mike Lockwood86328a92009-10-23 08:38:25 -04003241 long identity = Binder.clearCallingIdentity();
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003242 synchronized (mLock) {
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003243 // remove the real provider if we are replacing GPS or network provider
3244 if (LocationManager.GPS_PROVIDER.equals(name)
Nick Pelly1332b532012-08-21 16:25:47 -07003245 || LocationManager.NETWORK_PROVIDER.equals(name)
3246 || LocationManager.FUSED_PROVIDER.equals(name)) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05003247 LocationProviderInterface p = mProvidersByName.get(name);
3248 if (p != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003249 removeProviderLocked(p);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003250 }
3251 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09003252 addTestProviderLocked(name, properties);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003253 updateProvidersLocked();
3254 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003255 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003256 }
3257
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09003258 private void addTestProviderLocked(String name, ProviderProperties properties) {
3259 if (mProvidersByName.get(name) != null) {
3260 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
3261 }
3262 MockProvider provider = new MockProvider(name, this, properties);
3263 addProviderLocked(provider);
3264 mMockProviders.put(name, provider);
3265 mLastLocation.put(name, null);
3266 mLastLocationCoarseInterval.put(name, null);
3267 }
3268
Nick Pellye0fd6932012-07-11 10:26:13 -07003269 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003270 public void removeTestProvider(String provider, String opPackageName) {
3271 if (!canCallerAccessMockLocation(opPackageName)) {
3272 return;
3273 }
3274
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003275 synchronized (mLock) {
Tom O'Neill07ee5d12014-03-03 17:48:35 -08003276
3277 // These methods can't be called after removing the test provider, so first make sure
Tom O'Neillfe6d3c52014-03-04 08:26:17 -08003278 // we don't leave anything dangling.
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003279 clearTestProviderEnabled(provider, opPackageName);
3280 clearTestProviderLocation(provider, opPackageName);
Tom O'Neill07ee5d12014-03-03 17:48:35 -08003281
You Kima6d0b6f2012-10-28 03:58:44 +09003282 MockProvider mockProvider = mMockProviders.remove(provider);
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003283 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003284 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3285 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003286 long identity = Binder.clearCallingIdentity();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003287 removeProviderLocked(mProvidersByName.get(provider));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003288
3289 // reinstate real provider if available
3290 LocationProviderInterface realProvider = mRealProviders.get(provider);
3291 if (realProvider != null) {
3292 addProviderLocked(realProvider);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003293 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003294 mLastLocation.put(provider, null);
David Christie1b9b7b12013-04-15 15:31:11 -07003295 mLastLocationCoarseInterval.put(provider, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003296 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003297 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003298 }
3299 }
3300
Nick Pellye0fd6932012-07-11 10:26:13 -07003301 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003302 public void setTestProviderLocation(String provider, Location loc, String opPackageName) {
3303 if (!canCallerAccessMockLocation(opPackageName)) {
3304 return;
3305 }
3306
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003307 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003308 MockProvider mockProvider = mMockProviders.get(provider);
3309 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003310 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3311 }
Tom O'Neilla206a0f2016-12-15 10:26:28 -08003312
3313 // Ensure that the location is marked as being mock. There's some logic to do this in
3314 // handleLocationChanged(), but it fails if loc has the wrong provider (bug 33091107).
3315 Location mock = new Location(loc);
3316 mock.setIsFromMockProvider(true);
3317
3318 if (!TextUtils.isEmpty(loc.getProvider()) && !provider.equals(loc.getProvider())) {
3319 // The location has an explicit provider that is different from the mock provider
3320 // name. The caller may be trying to fool us via bug 33091107.
3321 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
3322 provider + "!=" + loc.getProvider());
3323 }
3324
Mike Lockwood95427cd2009-05-07 13:27:54 -04003325 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
3326 long identity = Binder.clearCallingIdentity();
Tom O'Neilla206a0f2016-12-15 10:26:28 -08003327 mockProvider.setLocation(mock);
Mike Lockwood95427cd2009-05-07 13:27:54 -04003328 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003329 }
3330 }
3331
Nick Pellye0fd6932012-07-11 10:26:13 -07003332 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003333 public void clearTestProviderLocation(String provider, String opPackageName) {
3334 if (!canCallerAccessMockLocation(opPackageName)) {
3335 return;
3336 }
3337
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003338 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003339 MockProvider mockProvider = mMockProviders.get(provider);
3340 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003341 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3342 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003343 mockProvider.clearLocation();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003344 }
3345 }
3346
Nick Pellye0fd6932012-07-11 10:26:13 -07003347 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003348 public void setTestProviderEnabled(String provider, boolean enabled, String opPackageName) {
3349 if (!canCallerAccessMockLocation(opPackageName)) {
3350 return;
3351 }
Maggie2a9409e2018-03-21 11:47:28 -07003352 setTestProviderEnabled(provider, enabled);
3353 }
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003354
Maggie2a9409e2018-03-21 11:47:28 -07003355 /** Enable or disable a test location provider. */
3356 private void setTestProviderEnabled(String provider, boolean enabled) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003357 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003358 MockProvider mockProvider = mMockProviders.get(provider);
3359 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003360 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3361 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003362 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003363 if (enabled) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003364 mockProvider.enable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003365 mEnabledProviders.add(provider);
3366 mDisabledProviders.remove(provider);
3367 } else {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003368 mockProvider.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003369 mEnabledProviders.remove(provider);
3370 mDisabledProviders.add(provider);
3371 }
3372 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003373 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003374 }
3375 }
3376
Nick Pellye0fd6932012-07-11 10:26:13 -07003377 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003378 public void clearTestProviderEnabled(String provider, String opPackageName) {
3379 if (!canCallerAccessMockLocation(opPackageName)) {
3380 return;
3381 }
3382
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003383 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003384 MockProvider mockProvider = mMockProviders.get(provider);
3385 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003386 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3387 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003388 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003389 mEnabledProviders.remove(provider);
3390 mDisabledProviders.remove(provider);
3391 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003392 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003393 }
3394 }
3395
Nick Pellye0fd6932012-07-11 10:26:13 -07003396 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003397 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime,
3398 String opPackageName) {
3399 if (!canCallerAccessMockLocation(opPackageName)) {
3400 return;
3401 }
3402
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003403 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003404 MockProvider mockProvider = mMockProviders.get(provider);
3405 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003406 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3407 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003408 mockProvider.setStatus(status, extras, updateTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003409 }
3410 }
3411
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003412 private void log(String log) {
3413 if (Log.isLoggable(TAG, Log.VERBOSE)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003414 Slog.d(TAG, log);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003415 }
3416 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003417
3418 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003419 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003420 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Nick Pellye0fd6932012-07-11 10:26:13 -07003421
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003422 synchronized (mLock) {
Siddharth Raybb608c82017-03-16 11:33:34 -07003423 if (args.length > 0 && args[0].equals("--gnssmetrics")) {
3424 if (mGnssMetricsProvider != null) {
3425 pw.append(mGnssMetricsProvider.getGnssMetricsAsProtoString());
3426 }
3427 return;
3428 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003429 pw.println("Current Location Manager state:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003430 pw.println(" Location Listeners:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003431 for (Receiver receiver : mReceivers.values()) {
3432 pw.println(" " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003433 }
David Christie2ff96af2014-01-30 16:09:37 -08003434 pw.println(" Active Records by Provider:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003435 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
3436 pw.println(" " + entry.getKey() + ":");
3437 for (UpdateRecord record : entry.getValue()) {
3438 pw.println(" " + record);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003439 }
3440 }
Wyatt Riley11cc7492018-01-17 08:48:27 -08003441 pw.println(" Active GnssMeasurement Listeners:");
3442 for (Identity identity : mGnssMeasurementsListeners.values()) {
3443 pw.println(" " + identity.mPid + " " + identity.mUid + " "
3444 + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
3445 }
3446 pw.println(" Active GnssNavigationMessage Listeners:");
3447 for (Identity identity : mGnssNavigationMessageListeners.values()) {
3448 pw.println(" " + identity.mPid + " " + identity.mUid + " "
3449 + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
3450 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003451 pw.println(" Overlay Provider Packages:");
3452 for (LocationProviderInterface provider : mProviders) {
3453 if (provider instanceof LocationProviderProxy) {
3454 pw.println(" " + provider.getName() + ": "
3455 + ((LocationProviderProxy) provider).getConnectedPackageName());
3456 }
3457 }
David Christie2ff96af2014-01-30 16:09:37 -08003458 pw.println(" Historical Records by Provider:");
3459 for (Map.Entry<PackageProviderKey, PackageStatistics> entry
3460 : mRequestStatistics.statistics.entrySet()) {
3461 PackageProviderKey key = entry.getKey();
3462 PackageStatistics stats = entry.getValue();
3463 pw.println(" " + key.packageName + ": " + key.providerName + ": " + stats);
3464 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003465 pw.println(" Last Known Locations:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003466 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
3467 String provider = entry.getKey();
3468 Location location = entry.getValue();
3469 pw.println(" " + provider + ": " + location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003470 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003471
David Christie1b9b7b12013-04-15 15:31:11 -07003472 pw.println(" Last Known Locations Coarse Intervals:");
3473 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
3474 String provider = entry.getKey();
3475 Location location = entry.getValue();
3476 pw.println(" " + provider + ": " + location);
3477 }
3478
Nick Pellye0fd6932012-07-11 10:26:13 -07003479 mGeofenceManager.dump(pw);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003481 if (mEnabledProviders.size() > 0) {
3482 pw.println(" Enabled Providers:");
3483 for (String i : mEnabledProviders) {
3484 pw.println(" " + i);
3485 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003486
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003487 }
3488 if (mDisabledProviders.size() > 0) {
3489 pw.println(" Disabled Providers:");
3490 for (String i : mDisabledProviders) {
3491 pw.println(" " + i);
3492 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003493 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07003494 pw.append(" ");
3495 mBlacklist.dump(pw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003496 if (mMockProviders.size() > 0) {
3497 pw.println(" Mock Providers:");
3498 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003499 i.getValue().dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003500 }
3501 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003502
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08003503 if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
3504 pw.println(" Throttling Whitelisted Packages:");
3505 for (String packageName : mBackgroundThrottlePackageWhitelist) {
3506 pw.println(" " + packageName);
3507 }
3508 }
3509
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003510 pw.append(" fudger: ");
gomo48f1a642017-11-10 20:35:46 -08003511 mLocationFudger.dump(fd, pw, args);
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003512
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003513 if (args.length > 0 && "short".equals(args[0])) {
3514 return;
3515 }
gomo48f1a642017-11-10 20:35:46 -08003516 for (LocationProviderInterface provider : mProviders) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003517 pw.print(provider.getName() + " Internal State");
3518 if (provider instanceof LocationProviderProxy) {
3519 LocationProviderProxy proxy = (LocationProviderProxy) provider;
3520 pw.print(" (" + proxy.getConnectedPackageName() + ")");
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003521 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003522 pw.println(":");
3523 provider.dump(fd, pw, args);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003524 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08003525 if (mGnssBatchingInProgress) {
3526 pw.println(" GNSS batching in progress");
3527 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003528 }
3529 }
3530}