blob: 776cf47a1e56bf0d555bb4f7bcc680b23c749b76 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Maggieaa080f92018-01-04 15:35:11 -080019import static android.content.pm.PackageManager.PERMISSION_GRANTED;
20
Wyatt Rileycf879db2017-01-12 13:57:38 -080021import android.annotation.NonNull;
Wyatt Riley49097c02018-03-15 09:14:43 -070022import android.annotation.Nullable;
Maggieaa080f92018-01-04 15:35:11 -080023import android.app.ActivityManager;
24import android.app.AppOpsManager;
25import android.app.PendingIntent;
26import android.content.BroadcastReceiver;
27import android.content.ContentResolver;
28import android.content.Context;
29import android.content.Intent;
30import android.content.IntentFilter;
31import android.content.pm.ApplicationInfo;
32import android.content.pm.PackageInfo;
33import android.content.pm.PackageManager;
34import android.content.pm.PackageManager.NameNotFoundException;
35import android.content.pm.PackageManagerInternal;
36import android.content.pm.ResolveInfo;
37import android.content.pm.Signature;
38import android.content.res.Resources;
39import android.database.ContentObserver;
40import android.hardware.location.ActivityRecognitionHardware;
41import android.location.Address;
42import android.location.Criteria;
43import android.location.GeocoderParams;
44import android.location.Geofence;
45import android.location.IBatchedLocationCallback;
46import android.location.IGnssMeasurementsListener;
47import android.location.IGnssNavigationMessageListener;
48import android.location.IGnssStatusListener;
49import android.location.IGnssStatusProvider;
50import android.location.IGpsGeofenceHardware;
51import android.location.ILocationListener;
52import android.location.ILocationManager;
53import android.location.INetInitiatedListener;
54import android.location.Location;
55import android.location.LocationManager;
56import android.location.LocationProvider;
57import android.location.LocationRequest;
58import android.os.Binder;
59import android.os.Bundle;
60import android.os.Handler;
61import android.os.IBinder;
62import android.os.Looper;
63import android.os.Message;
64import android.os.PowerManager;
65import android.os.Process;
66import android.os.RemoteException;
67import android.os.SystemClock;
68import android.os.UserHandle;
69import android.os.UserManager;
70import android.os.WorkSource;
Narayan Kamath32684dd2018-01-08 17:32:51 +000071import android.os.WorkSource.WorkChain;
Maggieaa080f92018-01-04 15:35:11 -080072import android.provider.Settings;
73import android.text.TextUtils;
Soonil Nagarkar681d7112017-02-23 17:14:16 -080074import android.util.ArrayMap;
Soonil Nagarkar2b565df2017-02-14 13:33:23 -080075import android.util.ArraySet;
Maggieaa080f92018-01-04 15:35:11 -080076import android.util.EventLog;
77import android.util.Log;
78import android.util.Slog;
destradaaea8a8a62014-06-23 18:19:03 -070079import com.android.internal.content.PackageMonitor;
80import com.android.internal.location.ProviderProperties;
81import com.android.internal.location.ProviderRequest;
82import com.android.internal.os.BackgroundThread;
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -070083import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060084import com.android.internal.util.DumpUtils;
destradaaa4fa3b52014-07-09 10:46:39 -070085import com.android.server.location.ActivityRecognitionProxy;
destradaaea8a8a62014-06-23 18:19:03 -070086import com.android.server.location.GeocoderProxy;
87import com.android.server.location.GeofenceManager;
88import com.android.server.location.GeofenceProxy;
Yu-Han Yang3557cc72018-03-21 12:48:36 -070089import com.android.server.location.GnssBatchingProvider;
Lifu Tang818aa2c2016-02-01 01:52:00 -080090import com.android.server.location.GnssLocationProvider;
91import com.android.server.location.GnssMeasurementsProvider;
92import com.android.server.location.GnssNavigationMessageProvider;
destradaaea8a8a62014-06-23 18:19:03 -070093import com.android.server.location.LocationBlacklist;
94import com.android.server.location.LocationFudger;
95import com.android.server.location.LocationProviderInterface;
96import com.android.server.location.LocationProviderProxy;
97import com.android.server.location.LocationRequestStatistics;
98import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
99import com.android.server.location.LocationRequestStatistics.PackageStatistics;
100import com.android.server.location.MockProvider;
101import com.android.server.location.PassiveProvider;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400102import java.io.FileDescriptor;
103import java.io.PrintWriter;
104import java.util.ArrayList;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700105import java.util.Arrays;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400106import java.util.HashMap;
107import java.util.HashSet;
108import java.util.List;
109import java.util.Map;
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800110import java.util.Map.Entry;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800111import java.util.NoSuchElementException;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400112import java.util.Set;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113
114/**
115 * The service class that manages LocationProviders and issues location
116 * updates and alerts.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117 */
Victoria Lease5cd731a2012-12-19 15:04:21 -0800118public class LocationManagerService extends ILocationManager.Stub {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119 private static final String TAG = "LocationManagerService";
JP Abgrallf79811e72013-02-01 18:45:05 -0800120 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700121
Olivier Gaillard7a222662017-11-20 16:07:24 +0000122 private static final String WAKELOCK_KEY = "*location*";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123
Victoria Lease37425c32012-10-16 16:08:48 -0700124 // Location resolution level: no location data whatsoever
125 private static final int RESOLUTION_LEVEL_NONE = 0;
126 // Location resolution level: coarse location data only
127 private static final int RESOLUTION_LEVEL_COARSE = 1;
128 // Location resolution level: fine location data
129 private static final int RESOLUTION_LEVEL_FINE = 2;
130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131 private static final String ACCESS_MOCK_LOCATION =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700132 android.Manifest.permission.ACCESS_MOCK_LOCATION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700134 android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
Mike Lockwood275555c2009-05-01 11:30:34 -0400135 private static final String INSTALL_LOCATION_PROVIDER =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700136 android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
137
138 private static final String NETWORK_LOCATION_SERVICE_ACTION =
Stan Chesnutt39062dd2013-07-22 14:33:30 -0700139 "com.android.location.service.v3.NetworkLocationProvider";
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700140 private static final String FUSED_LOCATION_SERVICE_ACTION =
141 "com.android.location.service.FusedLocationProvider";
142
143 private static final int MSG_LOCATION_CHANGED = 1;
144
David Christie1b9b7b12013-04-15 15:31:11 -0700145 private static final long NANOS_PER_MILLI = 1000000L;
146
David Christie0b837452013-07-29 16:02:13 -0700147 // The maximum interval a location request can have and still be considered "high power".
148 private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
149
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700150 private static final int FOREGROUND_IMPORTANCE_CUTOFF
gomo48f1a642017-11-10 20:35:46 -0800151 = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700152
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800153 // default background throttling interval if not overriden in settings
Soonil Nagarkarde6780a2017-02-07 10:39:41 -0800154 private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800155
Wei Wangdd070f22018-06-21 11:29:40 -0700156 // Default value for maximum age of last location returned to applications with foreground-only
157 // location permissions.
158 private static final long DEFAULT_LAST_LOCATION_MAX_AGE_MS = 20 * 60 * 1000;
159
Nick Pellyf1be6862012-05-15 10:53:42 -0700160 // Location Providers may sometimes deliver location updates
161 // slightly faster that requested - provide grace period so
162 // we don't unnecessarily filter events that are otherwise on
163 // time
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700164 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
Nick Pellyf1be6862012-05-15 10:53:42 -0700165
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700166 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
167
168 private final Context mContext;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800169 private final AppOpsManager mAppOps;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700170
171 // used internally for synchronization
172 private final Object mLock = new Object();
173
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700174 // --- fields below are final after systemRunning() ---
Nick Pelly74fa7ea2012-08-13 19:36:38 -0700175 private LocationFudger mLocationFudger;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700176 private GeofenceManager mGeofenceManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700177 private PackageManager mPackageManager;
Victoria Lease0aa28602013-05-29 15:28:26 -0700178 private PowerManager mPowerManager;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800179 private ActivityManager mActivityManager;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700180 private UserManager mUserManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700181 private GeocoderProxy mGeocodeProvider;
Lifu Tang30f95a72016-01-07 23:20:38 -0800182 private IGnssStatusProvider mGnssStatusProvider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700183 private INetInitiatedListener mNetInitiatedListener;
184 private LocationWorkerHandler mLocationHandler;
Nick Pelly4035f5a2012-08-17 14:43:49 -0700185 private PassiveProvider mPassiveProvider; // track passive provider for special cases
186 private LocationBlacklist mBlacklist;
Lifu Tang818aa2c2016-02-01 01:52:00 -0800187 private GnssMeasurementsProvider mGnssMeasurementsProvider;
188 private GnssNavigationMessageProvider mGnssNavigationMessageProvider;
Wei Liu5241a4c2015-05-11 14:00:36 -0700189 private IGpsGeofenceHardware mGpsGeofenceProxy;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700190
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700191 // --- fields below are protected by mLock ---
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 // Set of providers that are explicitly enabled
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700193 // Only used by passive, fused & test. Network & GPS are controlled separately, and not listed.
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800194 private final Set<String> mEnabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195
196 // Set of providers that are explicitly disabled
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800197 private final Set<String> mDisabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700199 // Mock (test) providers
200 private final HashMap<String, MockProvider> mMockProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800201 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700203 // all receivers
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800204 private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700206 // currently installed providers (with mocks replacing real providers)
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500207 private final ArrayList<LocationProviderInterface> mProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800208 new ArrayList<>();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400209
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700210 // real providers, saved here when mocked out
211 private final HashMap<String, LocationProviderInterface> mRealProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800212 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700214 // mapping from provider name to provider
215 private final HashMap<String, LocationProviderInterface> mProvidersByName =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800216 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700218 // mapping from provider name to all its UpdateRecords
219 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800220 new HashMap<>();
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700221
David Christie2ff96af2014-01-30 16:09:37 -0800222 private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics();
223
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700224 // mapping from provider name to last known location
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800225 private final HashMap<String, Location> mLastLocation = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226
David Christie1b9b7b12013-04-15 15:31:11 -0700227 // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
228 // locations stored here are not fudged for coarse permissions.
229 private final HashMap<String, Location> mLastLocationCoarseInterval =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800230 new HashMap<>();
David Christie1b9b7b12013-04-15 15:31:11 -0700231
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800232 // all providers that operate over proxy, for authorizing incoming location and whitelisting
233 // throttling
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700234 private final ArrayList<LocationProviderProxy> mProxyProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800235 new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800237 private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800238
Wyatt Riley11cc7492018-01-17 08:48:27 -0800239 private final ArrayMap<IBinder, Identity> mGnssMeasurementsListeners = new ArrayMap<>();
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800240
Wyatt Riley11cc7492018-01-17 08:48:27 -0800241 private final ArrayMap<IBinder, Identity>
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800242 mGnssNavigationMessageListeners = new ArrayMap<>();
243
Victoria Lease38389b62012-09-30 11:44:22 -0700244 // current active user on the device - other users are denied location data
Xiaohui Chena4490622015-09-22 15:29:31 -0700245 private int mCurrentUserId = UserHandle.USER_SYSTEM;
gomo48f1a642017-11-10 20:35:46 -0800246 private int[] mCurrentUserProfiles = new int[]{UserHandle.USER_SYSTEM};
Victoria Lease38389b62012-09-30 11:44:22 -0700247
Wei Wangdd070f22018-06-21 11:29:40 -0700248 // Maximum age of last location returned to clients with foreground-only location permissions.
249 private long mLastLocationMaxAgeMs;
250
Lifu Tang9363b942016-02-16 18:07:00 -0800251 private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;
Lifu Tang82f893d2016-01-21 18:15:33 -0800252
Siddharth Raybb608c82017-03-16 11:33:34 -0700253 private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;
Wyatt Rileyaa420d52017-07-03 15:14:42 -0700254
Yu-Han Yang3557cc72018-03-21 12:48:36 -0700255 private GnssBatchingProvider mGnssBatchingProvider;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800256 private IBatchedLocationCallback mGnssBatchingCallback;
257 private LinkedCallback mGnssBatchingDeathCallback;
258 private boolean mGnssBatchingInProgress = false;
259
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700260 public LocationManagerService(Context context) {
261 super();
262 mContext = context;
gomo48f1a642017-11-10 20:35:46 -0800263 mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800264
Svet Ganovadc1cf42015-06-15 16:36:24 -0700265 // Let the package manager query which are the default location
266 // providers as they get certain permissions granted by default.
267 PackageManagerInternal packageManagerInternal = LocalServices.getService(
268 PackageManagerInternal.class);
269 packageManagerInternal.setLocationPackagesProvider(
270 new PackageManagerInternal.PackagesProvider() {
271 @Override
272 public String[] getPackages(int userId) {
273 return mContext.getResources().getStringArray(
274 com.android.internal.R.array.config_locationProviderPackageNames);
275 }
276 });
277
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700278 if (D) Log.d(TAG, "Constructed");
279
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700280 // most startup is deferred until systemRunning()
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700281 }
282
Svetoslav Ganova0027152013-06-25 14:59:53 -0700283 public void systemRunning() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700284 synchronized (mLock) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700285 if (D) Log.d(TAG, "systemRunning()");
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700286
Victoria Lease5cd731a2012-12-19 15:04:21 -0800287 // fetch package manager
288 mPackageManager = mContext.getPackageManager();
289
Victoria Lease0aa28602013-05-29 15:28:26 -0700290 // fetch power manager
291 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
Victoria Lease5cd731a2012-12-19 15:04:21 -0800292
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800293 // fetch activity manager
294 mActivityManager
295 = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
296
Victoria Lease5cd731a2012-12-19 15:04:21 -0800297 // prepare worker thread
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700298 mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper());
Victoria Lease5cd731a2012-12-19 15:04:21 -0800299
300 // prepare mLocationHandler's dependents
301 mLocationFudger = new LocationFudger(mContext, mLocationHandler);
302 mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
303 mBlacklist.init();
304 mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
305
Dianne Hackbornc2293022013-02-06 23:14:49 -0800306 // Monitor for app ops mode changes.
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700307 AppOpsManager.OnOpChangedListener callback
308 = new AppOpsManager.OnOpChangedInternalListener() {
309 public void onOpChanged(int op, String packageName) {
Dianne Hackbornc2293022013-02-06 23:14:49 -0800310 synchronized (mLock) {
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700311 for (Receiver receiver : mReceivers.values()) {
312 receiver.updateMonitoring(true);
313 }
Dianne Hackbornc2293022013-02-06 23:14:49 -0800314 applyAllProviderRequirementsLocked();
315 }
316 }
317 };
Wei Wangdd070f22018-06-21 11:29:40 -0700318 mAppOps.startWatchingMode(AppOpsManager.OP_COARSE_LOCATION, null,
319 AppOpsManager.WATCH_FOREGROUND_CHANGES, callback);
Dianne Hackbornc2293022013-02-06 23:14:49 -0800320
David Christieb870dbf2015-06-22 12:42:53 -0700321 PackageManager.OnPermissionsChangedListener permissionListener
322 = new PackageManager.OnPermissionsChangedListener() {
323 @Override
324 public void onPermissionsChanged(final int uid) {
325 synchronized (mLock) {
326 applyAllProviderRequirementsLocked();
327 }
328 }
329 };
330 mPackageManager.addOnPermissionsChangeListener(permissionListener);
331
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800332 // listen for background/foreground changes
333 ActivityManager.OnUidImportanceListener uidImportanceListener
334 = new ActivityManager.OnUidImportanceListener() {
335 @Override
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700336 public void onUidImportance(final int uid, final int importance) {
337 mLocationHandler.post(new Runnable() {
338 @Override
339 public void run() {
340 onUidImportanceChanged(uid, importance);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800341 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700342 });
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800343 }
344 };
345 mActivityManager.addOnUidImportanceListener(uidImportanceListener,
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700346 FOREGROUND_IMPORTANCE_CUTOFF);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800347
Amith Yamasanib27528d2014-06-05 15:02:10 -0700348 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
349 updateUserProfiles(mCurrentUserId);
350
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800351 updateBackgroundThrottlingWhitelistLocked();
Wei Wangdd070f22018-06-21 11:29:40 -0700352 updateLastLocationMaxAgeLocked();
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800353
Victoria Lease5cd731a2012-12-19 15:04:21 -0800354 // prepare providers
355 loadProvidersLocked();
356 updateProvidersLocked();
357 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700358
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700359 // listen for settings changes
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700360 mContext.getContentResolver().registerContentObserver(
Laurent Tu75defb62012-11-01 16:21:52 -0700361 Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700362 new ContentObserver(mLocationHandler) {
Victoria Lease5cd731a2012-12-19 15:04:21 -0800363 @Override
364 public void onChange(boolean selfChange) {
365 synchronized (mLock) {
366 updateProvidersLocked();
367 }
368 }
369 }, UserHandle.USER_ALL);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800370 mContext.getContentResolver().registerContentObserver(
371 Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS),
372 true,
373 new ContentObserver(mLocationHandler) {
374 @Override
375 public void onChange(boolean selfChange) {
376 synchronized (mLock) {
377 updateProvidersLocked();
378 }
379 }
380 }, UserHandle.USER_ALL);
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800381 mContext.getContentResolver().registerContentObserver(
Wei Wangdd070f22018-06-21 11:29:40 -0700382 Settings.Global.getUriFor(Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS),
383 true,
384 new ContentObserver(mLocationHandler) {
385 @Override
386 public void onChange(boolean selfChange) {
387 synchronized (mLock) {
388 updateLastLocationMaxAgeLocked();
389 }
390 }
391 }
392 );
393 mContext.getContentResolver().registerContentObserver(
gomo48f1a642017-11-10 20:35:46 -0800394 Settings.Global.getUriFor(
395 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
396 true,
397 new ContentObserver(mLocationHandler) {
398 @Override
399 public void onChange(boolean selfChange) {
400 synchronized (mLock) {
401 updateBackgroundThrottlingWhitelistLocked();
402 updateProvidersLocked();
403 }
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800404 }
gomo48f1a642017-11-10 20:35:46 -0800405 }, UserHandle.USER_ALL);
Wei Wangdd070f22018-06-21 11:29:40 -0700406
Victoria Lease5cd731a2012-12-19 15:04:21 -0800407 mPackageMonitor.register(mContext, mLocationHandler.getLooper(), true);
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700408
Victoria Lease38389b62012-09-30 11:44:22 -0700409 // listen for user change
410 IntentFilter intentFilter = new IntentFilter();
411 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700412 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
413 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
destradaab9026982015-08-27 17:34:54 -0700414 intentFilter.addAction(Intent.ACTION_SHUTDOWN);
Victoria Lease38389b62012-09-30 11:44:22 -0700415
416 mContext.registerReceiverAsUser(new BroadcastReceiver() {
417 @Override
418 public void onReceive(Context context, Intent intent) {
419 String action = intent.getAction();
420 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
421 switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
Amith Yamasanib27528d2014-06-05 15:02:10 -0700422 } else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)
423 || Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
424 updateUserProfiles(mCurrentUserId);
destradaab9026982015-08-27 17:34:54 -0700425 } else if (Intent.ACTION_SHUTDOWN.equals(action)) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700426 // shutdown only if UserId indicates whole system, not just one user
gomo48f1a642017-11-10 20:35:46 -0800427 if (D) Log.d(TAG, "Shutdown received with UserId: " + getSendingUserId());
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700428 if (getSendingUserId() == UserHandle.USER_ALL) {
429 shutdownComponents();
430 }
Victoria Lease38389b62012-09-30 11:44:22 -0700431 }
432 }
Victoria Lease5cd731a2012-12-19 15:04:21 -0800433 }, UserHandle.ALL, intentFilter, null, mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700434 }
435
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700436 private void onUidImportanceChanged(int uid, int importance) {
437 boolean foreground = isImportanceForeground(importance);
438 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
439 synchronized (mLock) {
440 for (Entry<String, ArrayList<UpdateRecord>> entry
gomo48f1a642017-11-10 20:35:46 -0800441 : mRecordsByProvider.entrySet()) {
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700442 String provider = entry.getKey();
443 for (UpdateRecord record : entry.getValue()) {
444 if (record.mReceiver.mIdentity.mUid == uid
gomo48f1a642017-11-10 20:35:46 -0800445 && record.mIsForegroundUid != foreground) {
446 if (D) {
447 Log.d(TAG, "request from uid " + uid + " is now "
448 + (foreground ? "foreground" : "background)"));
449 }
Wyatt Rileyf7075e02018-04-12 17:54:26 -0700450 record.updateForeground(foreground);
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700451
452 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
453 affectedProviders.add(provider);
454 }
455 }
456 }
457 }
458 for (String provider : affectedProviders) {
459 applyRequirementsLocked(provider);
460 }
461
Wyatt Riley11cc7492018-01-17 08:48:27 -0800462 for (Entry<IBinder, Identity> entry : mGnssMeasurementsListeners.entrySet()) {
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700463 if (entry.getValue().mUid == uid) {
gomo48f1a642017-11-10 20:35:46 -0800464 if (D) {
465 Log.d(TAG, "gnss measurements listener from uid " + uid
466 + " is now " + (foreground ? "foreground" : "background)"));
467 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700468 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800469 mGnssMeasurementsProvider.addListener(
470 IGnssMeasurementsListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700471 } else {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800472 mGnssMeasurementsProvider.removeListener(
473 IGnssMeasurementsListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700474 }
475 }
476 }
477
Wyatt Riley11cc7492018-01-17 08:48:27 -0800478 for (Entry<IBinder, Identity> entry : mGnssNavigationMessageListeners.entrySet()) {
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700479 if (entry.getValue().mUid == uid) {
gomo48f1a642017-11-10 20:35:46 -0800480 if (D) {
481 Log.d(TAG, "gnss navigation message listener from uid "
482 + uid + " is now "
483 + (foreground ? "foreground" : "background)"));
484 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700485 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800486 mGnssNavigationMessageProvider.addListener(
487 IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700488 } else {
Wyatt Riley11cc7492018-01-17 08:48:27 -0800489 mGnssNavigationMessageProvider.removeListener(
490 IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()));
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700491 }
492 }
493 }
494 }
495 }
496
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800497 private static boolean isImportanceForeground(int importance) {
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700498 return importance <= FOREGROUND_IMPORTANCE_CUTOFF;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800499 }
500
Amith Yamasanib27528d2014-06-05 15:02:10 -0700501 /**
destradaab9026982015-08-27 17:34:54 -0700502 * Provides a way for components held by the {@link LocationManagerService} to clean-up
503 * gracefully on system's shutdown.
504 *
505 * NOTES:
506 * 1) Only provides a chance to clean-up on an opt-in basis. This guarantees back-compat
507 * support for components that do not wish to handle such event.
508 */
509 private void shutdownComponents() {
gomo48f1a642017-11-10 20:35:46 -0800510 if (D) Log.d(TAG, "Shutting down components...");
destradaab9026982015-08-27 17:34:54 -0700511
512 LocationProviderInterface gpsProvider = mProvidersByName.get(LocationManager.GPS_PROVIDER);
513 if (gpsProvider != null && gpsProvider.isEnabled()) {
514 gpsProvider.disable();
515 }
destradaab9026982015-08-27 17:34:54 -0700516 }
517
518 /**
Amith Yamasanib27528d2014-06-05 15:02:10 -0700519 * Makes a list of userids that are related to the current user. This is
520 * relevant when using managed profiles. Otherwise the list only contains
521 * the current user.
522 *
523 * @param currentUserId the current user, who might have an alter-ego.
524 */
525 void updateUserProfiles(int currentUserId) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700526 int[] profileIds = mUserManager.getProfileIdsWithDisabled(currentUserId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700527 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700528 mCurrentUserProfiles = profileIds;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700529 }
530 }
531
532 /**
533 * Checks if the specified userId matches any of the current foreground
534 * users stored in mCurrentUserProfiles.
535 */
536 private boolean isCurrentProfile(int userId) {
537 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700538 return ArrayUtils.contains(mCurrentUserProfiles, userId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700539 }
540 }
541
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500542 private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) {
543 PackageManager pm = mContext.getPackageManager();
544 String systemPackageName = mContext.getPackageName();
545 ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
546
547 List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
548 new Intent(FUSED_LOCATION_SERVICE_ACTION),
549 PackageManager.GET_META_DATA, mCurrentUserId);
550 for (ResolveInfo rInfo : rInfos) {
551 String packageName = rInfo.serviceInfo.packageName;
552
553 // Check that the signature is in the list of supported sigs. If it's not in
554 // this list the standard provider binding logic won't bind to it.
555 try {
556 PackageInfo pInfo;
557 pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
558 if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
559 Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
560 ", but has wrong signature, ignoring");
561 continue;
562 }
563 } catch (NameNotFoundException e) {
564 Log.e(TAG, "missing package: " + packageName);
565 continue;
566 }
567
568 // Get the version info
569 if (rInfo.serviceInfo.metaData == null) {
570 Log.w(TAG, "Found fused provider without metadata: " + packageName);
571 continue;
572 }
573
574 int version = rInfo.serviceInfo.metaData.getInt(
575 ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
576 if (version == 0) {
577 // This should be the fallback fused location provider.
578
579 // Make sure it's in the system partition.
580 if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
581 if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
582 continue;
583 }
584
585 // Check that the fallback is signed the same as the OS
586 // as a proxy for coreApp="true"
587 if (pm.checkSignatures(systemPackageName, packageName)
588 != PackageManager.SIGNATURE_MATCH) {
gomo48f1a642017-11-10 20:35:46 -0800589 if (D) {
590 Log.d(TAG, "Fallback candidate not signed the same as system: "
591 + packageName);
592 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500593 continue;
594 }
595
596 // Found a valid fallback.
597 if (D) Log.d(TAG, "Found fallback provider: " + packageName);
598 return;
599 } else {
600 if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
601 }
602 }
603
604 throw new IllegalStateException("Unable to find a fused location provider that is in the "
605 + "system partition with version 0 and signed with the platform certificate. "
606 + "Such a package is needed to provide a default fused location provider in the "
607 + "event that no other fused location provider has been installed or is currently "
608 + "available. For example, coreOnly boot mode when decrypting the data "
609 + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
610 }
611
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700612 private void loadProvidersLocked() {
Victoria Lease5c24fd02012-10-01 11:00:50 -0700613 // create a passive location provider, which is always enabled
614 PassiveProvider passiveProvider = new PassiveProvider(this);
615 addProviderLocked(passiveProvider);
616 mEnabledProviders.add(passiveProvider.getName());
617 mPassiveProvider = passiveProvider;
618
Lifu Tang30f95a72016-01-07 23:20:38 -0800619 if (GnssLocationProvider.isSupported()) {
Wei Liu5241a4c2015-05-11 14:00:36 -0700620 // Create a gps location provider
Lifu Tang30f95a72016-01-07 23:20:38 -0800621 GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this,
Wei Liu5241a4c2015-05-11 14:00:36 -0700622 mLocationHandler.getLooper());
Lifu Tang9363b942016-02-16 18:07:00 -0800623 mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
Wyatt Rileycf879db2017-01-12 13:57:38 -0800624 mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider();
Siddharth Raybb608c82017-03-16 11:33:34 -0700625 mGnssMetricsProvider = gnssProvider.getGnssMetricsProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800626 mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
627 mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
628 addProviderLocked(gnssProvider);
629 mRealProviders.put(LocationManager.GPS_PROVIDER, gnssProvider);
Lifu Tang818aa2c2016-02-01 01:52:00 -0800630 mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
631 mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800632 mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700633 }
634
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700635 /*
636 Load package name(s) containing location provider support.
637 These packages can contain services implementing location providers:
638 Geocoder Provider, Network Location Provider, and
639 Fused Location Provider. They will each be searched for
640 service components implementing these providers.
641 The location framework also has support for installation
642 of new location providers at run-time. The new package does not
643 have to be explicitly listed here, however it must have a signature
644 that matches the signature of at least one package on this list.
645 */
646 Resources resources = mContext.getResources();
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800647 ArrayList<String> providerPackageNames = new ArrayList<>();
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500648 String[] pkgs = resources.getStringArray(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700649 com.android.internal.R.array.config_locationProviderPackageNames);
gomo48f1a642017-11-10 20:35:46 -0800650 if (D) {
651 Log.d(TAG, "certificates for location providers pulled from: " +
652 Arrays.toString(pkgs));
653 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500654 if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));
655
656 ensureFallbackFusedProviderPresentLocked(providerPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700657
658 // bind to network provider
659 LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
660 mContext,
661 LocationManager.NETWORK_PROVIDER,
662 NETWORK_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700663 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
664 com.android.internal.R.string.config_networkLocationProviderPackageName,
665 com.android.internal.R.array.config_locationProviderPackageNames,
666 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700667 if (networkProvider != null) {
668 mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
669 mProxyProviders.add(networkProvider);
670 addProviderLocked(networkProvider);
671 } else {
gomo48f1a642017-11-10 20:35:46 -0800672 Slog.w(TAG, "no network location provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700673 }
674
675 // bind to fused provider
676 LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind(
677 mContext,
678 LocationManager.FUSED_PROVIDER,
679 FUSED_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700680 com.android.internal.R.bool.config_enableFusedLocationOverlay,
681 com.android.internal.R.string.config_fusedLocationProviderPackageName,
682 com.android.internal.R.array.config_locationProviderPackageNames,
683 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700684 if (fusedLocationProvider != null) {
685 addProviderLocked(fusedLocationProvider);
686 mProxyProviders.add(fusedLocationProvider);
687 mEnabledProviders.add(fusedLocationProvider.getName());
Kenny Rootc3575182012-10-09 12:44:40 -0700688 mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700689 } else {
690 Slog.e(TAG, "no fused location provider found",
691 new IllegalStateException("Location service needs a fused location provider"));
692 }
693
694 // bind to geocoder provider
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700695 mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
696 com.android.internal.R.bool.config_enableGeocoderOverlay,
697 com.android.internal.R.string.config_geocoderProviderPackageName,
698 com.android.internal.R.array.config_locationProviderPackageNames,
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800699 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700700 if (mGeocodeProvider == null) {
gomo48f1a642017-11-10 20:35:46 -0800701 Slog.e(TAG, "no geocoder provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700702 }
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700703
destradaaf9a274c2014-07-25 15:11:56 -0700704 // bind to geofence provider
705 GeofenceProxy provider = GeofenceProxy.createAndBind(
gomo48f1a642017-11-10 20:35:46 -0800706 mContext, com.android.internal.R.bool.config_enableGeofenceOverlay,
destradaaf9a274c2014-07-25 15:11:56 -0700707 com.android.internal.R.string.config_geofenceProviderPackageName,
708 com.android.internal.R.array.config_locationProviderPackageNames,
709 mLocationHandler,
Wei Liu5241a4c2015-05-11 14:00:36 -0700710 mGpsGeofenceProxy,
Jiyong Park4cc3a1c2018-03-08 16:43:07 +0900711 null);
destradaaf9a274c2014-07-25 15:11:56 -0700712 if (provider == null) {
gomo48f1a642017-11-10 20:35:46 -0800713 Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
destradaa0682809a2013-08-12 18:50:30 -0700714 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900715
destradaa6e2fe752015-06-23 17:25:53 -0700716 // bind to hardware activity recognition
717 boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
718 ActivityRecognitionHardware activityRecognitionHardware = null;
719 if (activityRecognitionHardwareIsSupported) {
720 activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
destradaaa4fa3b52014-07-09 10:46:39 -0700721 } else {
destradaa6b4893a2016-05-03 15:33:43 -0700722 Slog.d(TAG, "Hardware Activity-Recognition not supported.");
destradaaa4fa3b52014-07-09 10:46:39 -0700723 }
destradaa6e2fe752015-06-23 17:25:53 -0700724 ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
725 mContext,
726 mLocationHandler,
727 activityRecognitionHardwareIsSupported,
728 activityRecognitionHardware,
729 com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
730 com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
731 com.android.internal.R.array.config_locationProviderPackageNames);
732 if (proxy == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700733 Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
destradaa6e2fe752015-06-23 17:25:53 -0700734 }
destradaaa4fa3b52014-07-09 10:46:39 -0700735
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900736 String[] testProviderStrings = resources.getStringArray(
737 com.android.internal.R.array.config_testLocationProviders);
738 for (String testProviderString : testProviderStrings) {
739 String fragments[] = testProviderString.split(",");
740 String name = fragments[0].trim();
741 if (mProvidersByName.get(name) != null) {
742 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
743 }
744 ProviderProperties properties = new ProviderProperties(
745 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
746 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
747 Boolean.parseBoolean(fragments[3]) /* requiresCell */,
748 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
749 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
750 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
751 Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
752 Integer.parseInt(fragments[8]) /* powerRequirement */,
753 Integer.parseInt(fragments[9]) /* accuracy */);
754 addTestProviderLocked(name, properties);
755 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700756 }
Mike Lockwood9637d472009-04-02 21:41:57 -0700757
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800758 /**
Victoria Lease38389b62012-09-30 11:44:22 -0700759 * Called when the device's active user changes.
gomo48f1a642017-11-10 20:35:46 -0800760 *
Victoria Lease38389b62012-09-30 11:44:22 -0700761 * @param userId the new active user's UserId
762 */
763 private void switchUser(int userId) {
Jianzheng Zhoud5c69462013-10-10 14:02:09 +0800764 if (mCurrentUserId == userId) {
765 return;
766 }
Victoria Lease83762d22012-10-03 13:51:17 -0700767 mBlacklist.switchUser(userId);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800768 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED);
Victoria Lease38389b62012-09-30 11:44:22 -0700769 synchronized (mLock) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700770 mLastLocation.clear();
David Christie1b9b7b12013-04-15 15:31:11 -0700771 mLastLocationCoarseInterval.clear();
Victoria Leaseb711d572012-10-02 13:14:11 -0700772 for (LocationProviderInterface p : mProviders) {
Amith Yamasanib27528d2014-06-05 15:02:10 -0700773 updateProviderListenersLocked(p.getName(), false);
Victoria Leaseb711d572012-10-02 13:14:11 -0700774 }
Victoria Lease38389b62012-09-30 11:44:22 -0700775 mCurrentUserId = userId;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700776 updateUserProfiles(userId);
Victoria Leaseb711d572012-10-02 13:14:11 -0700777 updateProvidersLocked();
Victoria Lease38389b62012-09-30 11:44:22 -0700778 }
779 }
780
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800781 private static final class Identity {
782 final int mUid;
783 final int mPid;
784 final String mPackageName;
785
786 Identity(int uid, int pid, String packageName) {
787 mUid = uid;
788 mPid = pid;
789 mPackageName = packageName;
790 }
791 }
792
Victoria Lease38389b62012-09-30 11:44:22 -0700793 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 * A wrapper class holding either an ILocationListener or a PendingIntent to receive
795 * location updates.
796 */
Mike Lockwood48f17512009-04-23 09:12:08 -0700797 private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800798 final Identity mIdentity;
Victoria Lease37425c32012-10-16 16:08:48 -0700799 final int mAllowedResolutionLevel; // resolution level allowed to receiver
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801 final ILocationListener mListener;
802 final PendingIntent mPendingIntent;
David Christie82edc9b2013-07-19 11:31:42 -0700803 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
David Christie40e57822013-07-30 11:36:48 -0700804 final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805 final Object mKey;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700806
gomo48f1a642017-11-10 20:35:46 -0800807 final HashMap<String, UpdateRecord> mUpdateRecords = new HashMap<>();
Nick Pellyf1be6862012-05-15 10:53:42 -0700808
David Christie0b837452013-07-29 16:02:13 -0700809 // True if app ops has started monitoring this receiver for locations.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700810 boolean mOpMonitoring;
David Christie0b837452013-07-29 16:02:13 -0700811 // True if app ops has started monitoring this receiver for high power (gps) locations.
812 boolean mOpHighPowerMonitoring;
Mike Lockwood48f17512009-04-23 09:12:08 -0700813 int mPendingBroadcasts;
Victoria Lease0aa28602013-05-29 15:28:26 -0700814 PowerManager.WakeLock mWakeLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700816 Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -0700817 String packageName, WorkSource workSource, boolean hideFromAppOps) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800818 mListener = listener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 mPendingIntent = intent;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700820 if (listener != null) {
821 mKey = listener.asBinder();
822 } else {
823 mKey = intent;
824 }
Victoria Lease37425c32012-10-16 16:08:48 -0700825 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800826 mIdentity = new Identity(uid, pid, packageName);
Narayan Kamath32684dd2018-01-08 17:32:51 +0000827 if (workSource != null && workSource.isEmpty()) {
David Christie82edc9b2013-07-19 11:31:42 -0700828 workSource = null;
829 }
830 mWorkSource = workSource;
David Christie40e57822013-07-30 11:36:48 -0700831 mHideFromAppOps = hideFromAppOps;
Victoria Lease0aa28602013-05-29 15:28:26 -0700832
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700833 updateMonitoring(true);
834
Victoria Lease0aa28602013-05-29 15:28:26 -0700835 // construct/configure wakelock
836 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
David Christie82edc9b2013-07-19 11:31:42 -0700837 if (workSource == null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800838 workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -0700839 }
840 mWakeLock.setWorkSource(workSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800841 }
842
843 @Override
844 public boolean equals(Object otherObj) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800845 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846 }
847
848 @Override
849 public int hashCode() {
850 return mKey.hashCode();
851 }
Mike Lockwood3681f262009-05-12 10:52:03 -0400852
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 @Override
854 public String toString() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700855 StringBuilder s = new StringBuilder();
856 s.append("Reciever[");
857 s.append(Integer.toHexString(System.identityHashCode(this)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800858 if (mListener != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700859 s.append(" listener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700861 s.append(" intent");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800862 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700863 for (String p : mUpdateRecords.keySet()) {
864 s.append(" ").append(mUpdateRecords.get(p).toString());
865 }
Wei Wangdd070f22018-06-21 11:29:40 -0700866 s.append(" monitoring location: ").append(mOpMonitoring);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700867 s.append("]");
868 return s.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 }
870
David Christie15b31912013-08-13 15:54:32 -0700871 /**
872 * Update AppOp monitoring for this receiver.
873 *
874 * @param allow If true receiver is currently active, if false it's been removed.
875 */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700876 public void updateMonitoring(boolean allow) {
David Christie40e57822013-07-30 11:36:48 -0700877 if (mHideFromAppOps) {
878 return;
879 }
880
David Christie15b31912013-08-13 15:54:32 -0700881 boolean requestingLocation = false;
882 boolean requestingHighPowerLocation = false;
883 if (allow) {
884 // See if receiver has any enabled update records. Also note if any update records
885 // are high power (has a high power provider with an interval under a threshold).
886 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
887 if (isAllowedByCurrentUserSettingsLocked(updateRecord.mProvider)) {
888 requestingLocation = true;
889 LocationProviderInterface locationProvider
David Christie2ff96af2014-01-30 16:09:37 -0800890 = mProvidersByName.get(updateRecord.mProvider);
David Christie15b31912013-08-13 15:54:32 -0700891 ProviderProperties properties = locationProvider != null
892 ? locationProvider.getProperties() : null;
893 if (properties != null
894 && properties.mPowerRequirement == Criteria.POWER_HIGH
895 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
896 requestingHighPowerLocation = true;
897 break;
898 }
899 }
900 }
901 }
902
David Christie0b837452013-07-29 16:02:13 -0700903 // First update monitoring of any location request (including high power).
David Christie15b31912013-08-13 15:54:32 -0700904 mOpMonitoring = updateMonitoring(
905 requestingLocation,
906 mOpMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700907 AppOpsManager.OP_MONITOR_LOCATION);
908
909 // Now update monitoring of high power requests only.
David Christiec750c1f2013-08-08 12:56:57 -0700910 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
David Christie15b31912013-08-13 15:54:32 -0700911 mOpHighPowerMonitoring = updateMonitoring(
912 requestingHighPowerLocation,
913 mOpHighPowerMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700914 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
David Christiec750c1f2013-08-08 12:56:57 -0700915 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
David Christie15b31912013-08-13 15:54:32 -0700916 // Send an intent to notify that a high power request has been added/removed.
David Christiec750c1f2013-08-08 12:56:57 -0700917 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
918 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
919 }
David Christie0b837452013-07-29 16:02:13 -0700920 }
921
922 /**
923 * Update AppOps monitoring for a single location request and op type.
924 *
gomo48f1a642017-11-10 20:35:46 -0800925 * @param allowMonitoring True if monitoring is allowed for this request/op.
David Christie0b837452013-07-29 16:02:13 -0700926 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
gomo48f1a642017-11-10 20:35:46 -0800927 * @param op AppOps code for the op to update.
David Christie0b837452013-07-29 16:02:13 -0700928 * @return True if monitoring is on for this request/op after updating.
929 */
930 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
931 int op) {
932 if (!currentlyMonitoring) {
933 if (allowMonitoring) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800934 return mAppOps.startOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700935 == AppOpsManager.MODE_ALLOWED;
936 }
937 } else {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800938 if (!allowMonitoring
Wei Wangdd070f22018-06-21 11:29:40 -0700939 || mAppOps.noteOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700940 != AppOpsManager.MODE_ALLOWED) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800941 mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName);
David Christie0b837452013-07-29 16:02:13 -0700942 return false;
943 }
944 }
945
946 return currentlyMonitoring;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700947 }
948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800949 public boolean isListener() {
950 return mListener != null;
951 }
952
953 public boolean isPendingIntent() {
954 return mPendingIntent != null;
955 }
956
957 public ILocationListener getListener() {
958 if (mListener != null) {
959 return mListener;
960 }
961 throw new IllegalStateException("Request for non-existent listener");
962 }
963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
965 if (mListener != null) {
966 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700967 synchronized (this) {
968 // synchronize to ensure incrementPendingBroadcastsLocked()
969 // is called before decrementPendingBroadcasts()
970 mListener.onStatusChanged(provider, status, extras);
Nick Pellye0fd6932012-07-11 10:26:13 -0700971 // call this after broadcasting so we do not increment
972 // if we throw an exeption.
973 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -0700974 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 } catch (RemoteException e) {
976 return false;
977 }
978 } else {
979 Intent statusChanged = new Intent();
Victoria Lease61ecb022012-11-13 15:12:51 -0800980 statusChanged.putExtras(new Bundle(extras));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800981 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
982 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700983 synchronized (this) {
984 // synchronize to ensure incrementPendingBroadcastsLocked()
985 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700986 mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
Lifu Tang519f0d02018-04-12 16:39:39 -0700987 getResolutionPermission(mAllowedResolutionLevel),
988 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
Mike Lockwood48f17512009-04-23 09:12:08 -0700989 // call this after broadcasting so we do not increment
990 // if we throw an exeption.
991 incrementPendingBroadcastsLocked();
992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 } catch (PendingIntent.CanceledException e) {
994 return false;
995 }
996 }
997 return true;
998 }
999
1000 public boolean callLocationChangedLocked(Location location) {
1001 if (mListener != null) {
1002 try {
Mike Lockwood48f17512009-04-23 09:12:08 -07001003 synchronized (this) {
1004 // synchronize to ensure incrementPendingBroadcastsLocked()
1005 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08001006 mListener.onLocationChanged(new Location(location));
Nick Pellye0fd6932012-07-11 10:26:13 -07001007 // call this after broadcasting so we do not increment
1008 // if we throw an exeption.
1009 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001010 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 } catch (RemoteException e) {
1012 return false;
1013 }
1014 } else {
1015 Intent locationChanged = new Intent();
gomo48f1a642017-11-10 20:35:46 -08001016 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED,
1017 new Location(location));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 try {
Mike Lockwood48f17512009-04-23 09:12:08 -07001019 synchronized (this) {
1020 // synchronize to ensure incrementPendingBroadcastsLocked()
1021 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001022 mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
Lifu Tang519f0d02018-04-12 16:39:39 -07001023 getResolutionPermission(mAllowedResolutionLevel),
1024 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
Mike Lockwood48f17512009-04-23 09:12:08 -07001025 // call this after broadcasting so we do not increment
1026 // if we throw an exeption.
1027 incrementPendingBroadcastsLocked();
1028 }
1029 } catch (PendingIntent.CanceledException e) {
1030 return false;
1031 }
1032 }
1033 return true;
1034 }
1035
1036 public boolean callProviderEnabledLocked(String provider, boolean enabled) {
David Christie15b31912013-08-13 15:54:32 -07001037 // First update AppOp monitoring.
1038 // An app may get/lose location access as providers are enabled/disabled.
1039 updateMonitoring(true);
1040
Mike Lockwood48f17512009-04-23 09:12:08 -07001041 if (mListener != null) {
1042 try {
1043 synchronized (this) {
1044 // synchronize to ensure incrementPendingBroadcastsLocked()
1045 // is called before decrementPendingBroadcasts()
1046 if (enabled) {
1047 mListener.onProviderEnabled(provider);
1048 } else {
1049 mListener.onProviderDisabled(provider);
1050 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001051 // call this after broadcasting so we do not increment
1052 // if we throw an exeption.
1053 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001054 }
1055 } catch (RemoteException e) {
1056 return false;
1057 }
1058 } else {
1059 Intent providerIntent = new Intent();
1060 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1061 try {
1062 synchronized (this) {
1063 // synchronize to ensure incrementPendingBroadcastsLocked()
1064 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001065 mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
Lifu Tang519f0d02018-04-12 16:39:39 -07001066 getResolutionPermission(mAllowedResolutionLevel),
1067 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
Mike Lockwood48f17512009-04-23 09:12:08 -07001068 // call this after broadcasting so we do not increment
1069 // if we throw an exeption.
1070 incrementPendingBroadcastsLocked();
1071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 } catch (PendingIntent.CanceledException e) {
1073 return false;
1074 }
1075 }
1076 return true;
1077 }
1078
Nick Pellyf1be6862012-05-15 10:53:42 -07001079 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001080 public void binderDied() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001081 if (D) Log.d(TAG, "Location listener died");
1082
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001083 synchronized (mLock) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084 removeUpdatesLocked(this);
1085 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001086 synchronized (this) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001087 clearPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001088 }
1089 }
1090
Nick Pellye0fd6932012-07-11 10:26:13 -07001091 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001092 public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1093 int resultCode, String resultData, Bundle resultExtras) {
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001094 synchronized (this) {
1095 decrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001096 }
1097 }
1098
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001099 // this must be called while synchronized by caller in a synchronized block
1100 // containing the sending of the broadcaset
1101 private void incrementPendingBroadcastsLocked() {
1102 if (mPendingBroadcasts++ == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001103 mWakeLock.acquire();
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001104 }
1105 }
1106
1107 private void decrementPendingBroadcastsLocked() {
1108 if (--mPendingBroadcasts == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001109 if (mWakeLock.isHeld()) {
1110 mWakeLock.release();
1111 }
1112 }
1113 }
1114
1115 public void clearPendingBroadcastsLocked() {
1116 if (mPendingBroadcasts > 0) {
1117 mPendingBroadcasts = 0;
1118 if (mWakeLock.isHeld()) {
1119 mWakeLock.release();
1120 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001121 }
1122 }
1123 }
1124
Nick Pellye0fd6932012-07-11 10:26:13 -07001125 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001126 public void locationCallbackFinished(ILocationListener listener) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001127 //Do not use getReceiverLocked here as that will add the ILocationListener to
Joshua Bartel080b61b2009-10-05 12:44:46 -04001128 //the receiver list if it is not found. If it is not found then the
1129 //LocationListener was removed when it had a pending broadcast and should
1130 //not be added back.
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001131 synchronized (mLock) {
1132 IBinder binder = listener.asBinder();
1133 Receiver receiver = mReceivers.get(binder);
1134 if (receiver != null) {
1135 synchronized (receiver) {
1136 // so wakelock calls will succeed
1137 long identity = Binder.clearCallingIdentity();
1138 receiver.decrementPendingBroadcastsLocked();
1139 Binder.restoreCallingIdentity(identity);
David Christie2ff96af2014-01-30 16:09:37 -08001140 }
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001141 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001142 }
1143 }
1144
Lifu Tang82f893d2016-01-21 18:15:33 -08001145 /**
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001146 * Returns the year of the GNSS hardware.
Lifu Tang82f893d2016-01-21 18:15:33 -08001147 */
1148 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001149 public int getGnssYearOfHardware() {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001150 if (mGnssSystemInfoProvider != null) {
Lifu Tang9363b942016-02-16 18:07:00 -08001151 return mGnssSystemInfoProvider.getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001152 } else {
1153 return 0;
1154 }
1155 }
1156
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001157
1158 /**
1159 * Returns the model name of the GNSS hardware.
1160 */
1161 @Override
Wyatt Riley49097c02018-03-15 09:14:43 -07001162 @Nullable
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001163 public String getGnssHardwareModelName() {
1164 if (mGnssSystemInfoProvider != null) {
1165 return mGnssSystemInfoProvider.getGnssHardwareModelName();
1166 } else {
Wyatt Riley49097c02018-03-15 09:14:43 -07001167 return null;
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001168 }
1169 }
1170
Wyatt Rileycf879db2017-01-12 13:57:38 -08001171 /**
1172 * Runs some checks for GNSS (FINE) level permissions, used by several methods which directly
1173 * (try to) access GNSS information at this layer.
1174 */
1175 private boolean hasGnssPermissions(String packageName) {
1176 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
1177 checkResolutionLevelIsSufficientForProviderUse(
1178 allowedResolutionLevel,
1179 LocationManager.GPS_PROVIDER);
1180
1181 int pid = Binder.getCallingPid();
1182 int uid = Binder.getCallingUid();
1183 long identity = Binder.clearCallingIdentity();
1184 boolean hasLocationAccess;
1185 try {
1186 hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
1187 } finally {
1188 Binder.restoreCallingIdentity(identity);
1189 }
1190
1191 return hasLocationAccess;
1192 }
1193
1194 /**
1195 * Returns the GNSS batching size, if available.
1196 */
1197 @Override
1198 public int getGnssBatchSize(String packageName) {
1199 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1200 "Location Hardware permission not granted to access hardware batching");
1201
1202 if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
Yu-Han Yang3557cc72018-03-21 12:48:36 -07001203 return mGnssBatchingProvider.getBatchSize();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001204 } else {
1205 return 0;
1206 }
1207 }
1208
1209 /**
1210 * Adds a callback for GNSS Batching events, if permissions allow, which are transported
1211 * to potentially multiple listeners by the BatchedLocationCallbackTransport above this.
1212 */
1213 @Override
1214 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) {
1215 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1216 "Location Hardware permission not granted to access hardware batching");
1217
1218 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1219 return false;
1220 }
1221
1222 mGnssBatchingCallback = callback;
1223 mGnssBatchingDeathCallback = new LinkedCallback(callback);
1224 try {
1225 callback.asBinder().linkToDeath(mGnssBatchingDeathCallback, 0 /* flags */);
1226 } catch (RemoteException e) {
1227 // if the remote process registering the listener is already dead, just swallow the
1228 // exception and return
1229 Log.e(TAG, "Remote listener already died.", e);
1230 return false;
1231 }
1232
1233 return true;
1234 }
1235
1236 private class LinkedCallback implements IBinder.DeathRecipient {
1237 private final IBatchedLocationCallback mCallback;
1238
1239 public LinkedCallback(@NonNull IBatchedLocationCallback callback) {
1240 mCallback = callback;
1241 }
1242
1243 @NonNull
1244 public IBatchedLocationCallback getUnderlyingListener() {
1245 return mCallback;
1246 }
1247
1248 @Override
1249 public void binderDied() {
1250 Log.d(TAG, "Remote Batching Callback died: " + mCallback);
1251 stopGnssBatch();
1252 removeGnssBatchingCallback();
1253 }
1254 }
1255
1256 /**
1257 * Removes callback for GNSS batching
1258 */
1259 @Override
1260 public void removeGnssBatchingCallback() {
1261 try {
1262 mGnssBatchingCallback.asBinder().unlinkToDeath(mGnssBatchingDeathCallback,
1263 0 /* flags */);
1264 } catch (NoSuchElementException e) {
1265 // if the death callback isn't connected (it should be...), log error, swallow the
1266 // exception and return
1267 Log.e(TAG, "Couldn't unlink death callback.", e);
1268 }
1269 mGnssBatchingCallback = null;
1270 mGnssBatchingDeathCallback = null;
1271 }
1272
1273
1274 /**
1275 * Starts GNSS batching, if available.
1276 */
1277 @Override
1278 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
1279 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1280 "Location Hardware permission not granted to access hardware batching");
1281
1282 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1283 return false;
1284 }
1285
1286 if (mGnssBatchingInProgress) {
1287 // Current design does not expect multiple starts to be called repeatedly
1288 Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch");
1289 // Try to clean up anyway, and continue
1290 stopGnssBatch();
1291 }
1292
1293 mGnssBatchingInProgress = true;
1294 return mGnssBatchingProvider.start(periodNanos, wakeOnFifoFull);
1295 }
1296
1297 /**
1298 * Flushes a GNSS batch in progress
1299 */
1300 @Override
1301 public void flushGnssBatch(String packageName) {
1302 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1303 "Location Hardware permission not granted to access hardware batching");
1304
1305 if (!hasGnssPermissions(packageName)) {
1306 Log.e(TAG, "flushGnssBatch called without GNSS permissions");
1307 return;
1308 }
1309
1310 if (!mGnssBatchingInProgress) {
1311 Log.w(TAG, "flushGnssBatch called with no batch in progress");
1312 }
1313
1314 if (mGnssBatchingProvider != null) {
gomo48f1a642017-11-10 20:35:46 -08001315 mGnssBatchingProvider.flush();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001316 }
1317 }
1318
1319 /**
1320 * Stops GNSS batching
1321 */
1322 @Override
1323 public boolean stopGnssBatch() {
1324 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1325 "Location Hardware permission not granted to access hardware batching");
1326
1327 if (mGnssBatchingProvider != null) {
1328 mGnssBatchingInProgress = false;
1329 return mGnssBatchingProvider.stop();
gomo48f1a642017-11-10 20:35:46 -08001330 } else {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001331 return false;
1332 }
1333 }
1334
1335 @Override
1336 public void reportLocationBatch(List<Location> locations) {
1337 checkCallerIsProvider();
1338
1339 // Currently used only for GNSS locations - update permissions check if changed
1340 if (isAllowedByCurrentUserSettingsLocked(LocationManager.GPS_PROVIDER)) {
1341 if (mGnssBatchingCallback == null) {
1342 Slog.e(TAG, "reportLocationBatch() called without active Callback");
1343 return;
1344 }
1345 try {
1346 mGnssBatchingCallback.onLocationBatch(locations);
1347 } catch (RemoteException e) {
1348 Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e);
1349 }
1350 } else {
1351 Slog.w(TAG, "reportLocationBatch() called without user permission, locations blocked");
1352 }
1353 }
1354
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001355 private void addProviderLocked(LocationProviderInterface provider) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001356 mProviders.add(provider);
1357 mProvidersByName.put(provider.getName(), provider);
1358 }
1359
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001360 private void removeProviderLocked(LocationProviderInterface provider) {
1361 provider.disable();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001362 mProviders.remove(provider);
1363 mProvidersByName.remove(provider.getName());
1364 }
1365
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001366 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001367 * Returns "true" if access to the specified location provider is allowed by the current
1368 * user's settings. Access to all location providers is forbidden to non-location-provider
1369 * processes belonging to background users.
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001370 *
1371 * @param provider the name of the location provider
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001372 */
Victoria Lease09eeaec2013-02-05 11:34:13 -08001373 private boolean isAllowedByCurrentUserSettingsLocked(String provider) {
Maggie2a9409e2018-03-21 11:47:28 -07001374 return isAllowedByUserSettingsLockedForUser(provider, mCurrentUserId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 }
1376
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001377 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001378 * Returns "true" if access to the specified location provider is allowed by the specified
1379 * user's settings. Access to all location providers is forbidden to non-location-provider
1380 * processes belonging to background users.
1381 *
1382 * @param provider the name of the location provider
Maggie2a9409e2018-03-21 11:47:28 -07001383 * @param userId the user id to query
Victoria Lease09eeaec2013-02-05 11:34:13 -08001384 */
Maggie2a9409e2018-03-21 11:47:28 -07001385 private boolean isAllowedByUserSettingsLockedForUser(String provider, int userId) {
1386 if (mEnabledProviders.contains(provider)) {
1387 return true;
1388 }
1389 if (mDisabledProviders.contains(provider)) {
1390 return false;
1391 }
1392 return isLocationProviderEnabledForUser(provider, userId);
1393 }
1394
1395
1396 /**
1397 * Returns "true" if access to the specified location provider is allowed by the specified
1398 * user's settings. Access to all location providers is forbidden to non-location-provider
1399 * processes belonging to background users.
1400 *
1401 * @param provider the name of the location provider
1402 * @param uid the requestor's UID
1403 * @param userId the user id to query
1404 */
1405 private boolean isAllowedByUserSettingsLocked(String provider, int uid, int userId) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001406 if (!isCurrentProfile(UserHandle.getUserId(uid)) && !isUidALocationProvider(uid)) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08001407 return false;
1408 }
Maggie2a9409e2018-03-21 11:47:28 -07001409 return isAllowedByUserSettingsLockedForUser(provider, userId);
Victoria Lease09eeaec2013-02-05 11:34:13 -08001410 }
1411
1412 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001413 * Returns the permission string associated with the specified resolution level.
1414 *
1415 * @param resolutionLevel the resolution level
1416 * @return the permission string
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001417 */
Victoria Lease37425c32012-10-16 16:08:48 -07001418 private String getResolutionPermission(int resolutionLevel) {
1419 switch (resolutionLevel) {
1420 case RESOLUTION_LEVEL_FINE:
1421 return android.Manifest.permission.ACCESS_FINE_LOCATION;
1422 case RESOLUTION_LEVEL_COARSE:
1423 return android.Manifest.permission.ACCESS_COARSE_LOCATION;
1424 default:
1425 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001426 }
Victoria Leaseda479c52012-10-15 15:24:16 -07001427 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001428
Victoria Leaseda479c52012-10-15 15:24:16 -07001429 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001430 * Returns the resolution level allowed to the given PID/UID pair.
1431 *
1432 * @param pid the PID
1433 * @param uid the UID
1434 * @return resolution level allowed to the pid/uid pair
Victoria Leaseda479c52012-10-15 15:24:16 -07001435 */
Victoria Lease37425c32012-10-16 16:08:48 -07001436 private int getAllowedResolutionLevel(int pid, int uid) {
1437 if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001438 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001439 return RESOLUTION_LEVEL_FINE;
1440 } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001441 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001442 return RESOLUTION_LEVEL_COARSE;
1443 } else {
1444 return RESOLUTION_LEVEL_NONE;
Victoria Leaseda479c52012-10-15 15:24:16 -07001445 }
Victoria Lease4fab68b2012-09-13 13:20:59 -07001446 }
1447
1448 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001449 * Returns the resolution level allowed to the caller
1450 *
1451 * @return resolution level allowed to caller
Victoria Lease4fab68b2012-09-13 13:20:59 -07001452 */
Victoria Lease37425c32012-10-16 16:08:48 -07001453 private int getCallerAllowedResolutionLevel() {
1454 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
1455 }
1456
1457 /**
1458 * Throw SecurityException if specified resolution level is insufficient to use geofences.
1459 *
1460 * @param allowedResolutionLevel resolution level allowed to caller
1461 */
1462 private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
1463 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Lease4fab68b2012-09-13 13:20:59 -07001464 throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
1465 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001466 }
1467
Victoria Lease37425c32012-10-16 16:08:48 -07001468 /**
1469 * Return the minimum resolution level required to use the specified location provider.
1470 *
1471 * @param provider the name of the location provider
1472 * @return minimum resolution level required for provider
1473 */
1474 private int getMinimumResolutionLevelForProviderUse(String provider) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001475 if (LocationManager.GPS_PROVIDER.equals(provider) ||
1476 LocationManager.PASSIVE_PROVIDER.equals(provider)) {
1477 // gps and passive providers require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001478 return RESOLUTION_LEVEL_FINE;
Victoria Lease8dbb6342012-09-21 16:55:53 -07001479 } else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
1480 LocationManager.FUSED_PROVIDER.equals(provider)) {
1481 // network and fused providers are ok with COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001482 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001483 } else {
1484 // mock providers
1485 LocationProviderInterface lp = mMockProviders.get(provider);
1486 if (lp != null) {
1487 ProviderProperties properties = lp.getProperties();
1488 if (properties != null) {
1489 if (properties.mRequiresSatellite) {
1490 // provider requiring satellites require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001491 return RESOLUTION_LEVEL_FINE;
Laurent Tu941221c2012-10-04 14:21:52 -07001492 } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
1493 // provider requiring network and or cell require COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001494 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001495 }
1496 }
1497 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001498 }
Victoria Lease37425c32012-10-16 16:08:48 -07001499 return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
Victoria Leaseda479c52012-10-15 15:24:16 -07001500 }
1501
Victoria Lease37425c32012-10-16 16:08:48 -07001502 /**
1503 * Throw SecurityException if specified resolution level is insufficient to use the named
1504 * location provider.
1505 *
1506 * @param allowedResolutionLevel resolution level allowed to caller
gomo48f1a642017-11-10 20:35:46 -08001507 * @param providerName the name of the location provider
Victoria Lease37425c32012-10-16 16:08:48 -07001508 */
1509 private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel,
1510 String providerName) {
1511 int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName);
1512 if (allowedResolutionLevel < requiredResolutionLevel) {
1513 switch (requiredResolutionLevel) {
1514 case RESOLUTION_LEVEL_FINE:
1515 throw new SecurityException("\"" + providerName + "\" location provider " +
1516 "requires ACCESS_FINE_LOCATION permission.");
1517 case RESOLUTION_LEVEL_COARSE:
1518 throw new SecurityException("\"" + providerName + "\" location provider " +
1519 "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
1520 default:
1521 throw new SecurityException("Insufficient permission for \"" + providerName +
1522 "\" location provider.");
Victoria Leaseda479c52012-10-15 15:24:16 -07001523 }
1524 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001525 }
1526
David Christie82edc9b2013-07-19 11:31:42 -07001527 /**
1528 * Throw SecurityException if WorkSource use is not allowed (i.e. can't blame other packages
1529 * for battery).
1530 */
David Christie40e57822013-07-30 11:36:48 -07001531 private void checkDeviceStatsAllowed() {
David Christie82edc9b2013-07-19 11:31:42 -07001532 mContext.enforceCallingOrSelfPermission(
1533 android.Manifest.permission.UPDATE_DEVICE_STATS, null);
1534 }
1535
David Christie40e57822013-07-30 11:36:48 -07001536 private void checkUpdateAppOpsAllowed() {
1537 mContext.enforceCallingOrSelfPermission(
1538 android.Manifest.permission.UPDATE_APP_OPS_STATS, null);
1539 }
1540
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001541 public static int resolutionLevelToOp(int allowedResolutionLevel) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001542 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
1543 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001544 return AppOpsManager.OP_COARSE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001545 } else {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001546 return AppOpsManager.OP_FINE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001547 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001548 }
1549 return -1;
1550 }
1551
Wei Wangb86334f2018-07-03 16:33:24 -07001552 private static String resolutionLevelToOpStr(int allowedResolutionLevel) {
1553 switch(allowedResolutionLevel) {
1554 case RESOLUTION_LEVEL_COARSE:
1555 return AppOpsManager.OPSTR_COARSE_LOCATION;
1556 case RESOLUTION_LEVEL_FINE:
1557 return AppOpsManager.OPSTR_FINE_LOCATION;
1558 case RESOLUTION_LEVEL_NONE:
1559 // The client is not allowed to get any location, so both FINE and COARSE ops will
1560 // be denied. Pick the most restrictive one to be safe.
1561 return AppOpsManager.OPSTR_FINE_LOCATION;
1562 default:
1563 // Use the most restrictive ops if not sure.
1564 return AppOpsManager.OPSTR_FINE_LOCATION;
1565 }
1566 }
1567
David Christieb870dbf2015-06-22 12:42:53 -07001568 boolean reportLocationAccessNoThrow(
1569 int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001570 int op = resolutionLevelToOp(allowedResolutionLevel);
1571 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001572 if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1573 return false;
1574 }
1575 }
David Christieb870dbf2015-06-22 12:42:53 -07001576
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001577 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001578 }
1579
David Christieb870dbf2015-06-22 12:42:53 -07001580 boolean checkLocationAccess(int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001581 int op = resolutionLevelToOp(allowedResolutionLevel);
1582 if (op >= 0) {
Wei Wangdd070f22018-06-21 11:29:40 -07001583 if (mAppOps.noteOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001584 return false;
1585 }
1586 }
David Christieb870dbf2015-06-22 12:42:53 -07001587
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001588 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001589 }
1590
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001591 /**
Maggie91e630c2018-01-24 17:31:46 -08001592 * Returns all providers by name, including passive and the ones that are not permitted to
1593 * be accessed by the calling activity or are currently disabled, but excluding fused.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001594 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001595 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 public List<String> getAllProviders() {
Maggie91e630c2018-01-24 17:31:46 -08001597 ArrayList<String> out;
1598 synchronized (mLock) {
1599 out = new ArrayList<>(mProviders.size());
1600 for (LocationProviderInterface provider : mProviders) {
1601 String name = provider.getName();
1602 if (LocationManager.FUSED_PROVIDER.equals(name)) {
1603 continue;
1604 }
1605 out.add(name);
1606 }
1607 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001608 if (D) Log.d(TAG, "getAllProviders()=" + out);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001609 return out;
1610 }
1611
Mike Lockwood03ca2162010-04-01 08:10:09 -07001612 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001613 * Return all providers by name, that match criteria and are optionally
1614 * enabled.
1615 * Can return passive provider, but never returns fused provider.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001616 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001617 @Override
1618 public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
Victoria Lease37425c32012-10-16 16:08:48 -07001619 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001620 ArrayList<String> out;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001621 int uid = Binder.getCallingUid();
Victoria Lease269518e2012-10-29 08:25:39 -07001622 long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07001623 try {
1624 synchronized (mLock) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001625 out = new ArrayList<>(mProviders.size());
Victoria Leaseb711d572012-10-02 13:14:11 -07001626 for (LocationProviderInterface provider : mProviders) {
1627 String name = provider.getName();
1628 if (LocationManager.FUSED_PROVIDER.equals(name)) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001629 continue;
1630 }
Victoria Lease37425c32012-10-16 16:08:48 -07001631 if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
Maggie2a9409e2018-03-21 11:47:28 -07001632 if (enabledOnly
1633 && !isAllowedByUserSettingsLocked(name, uid, mCurrentUserId)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001634 continue;
1635 }
1636 if (criteria != null && !LocationProvider.propertiesMeetCriteria(
1637 name, provider.getProperties(), criteria)) {
1638 continue;
1639 }
1640 out.add(name);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001641 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001642 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001643 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001644 } finally {
1645 Binder.restoreCallingIdentity(identity);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001646 }
1647
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001648 if (D) Log.d(TAG, "getProviders()=" + out);
1649 return out;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001650 }
1651
1652 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001653 * Return the name of the best provider given a Criteria object.
1654 * This method has been deprecated from the public API,
Victoria Lease8dbb6342012-09-21 16:55:53 -07001655 * and the whole LocationProvider (including #meetsCriteria)
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001656 * has been deprecated as well. So this method now uses
1657 * some simplified logic.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001658 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001659 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001660 public String getBestProvider(Criteria criteria, boolean enabledOnly) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001661 String result = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001662
1663 List<String> providers = getProviders(criteria, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001664 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001665 result = pickBest(providers);
1666 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1667 return result;
1668 }
1669 providers = getProviders(null, 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;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001674 }
1675
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001676 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001677 return null;
1678 }
1679
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001680 private String pickBest(List<String> providers) {
Victoria Lease1925e292012-09-24 17:00:18 -07001681 if (providers.contains(LocationManager.GPS_PROVIDER)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001682 return LocationManager.GPS_PROVIDER;
Victoria Lease1925e292012-09-24 17:00:18 -07001683 } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
1684 return LocationManager.NETWORK_PROVIDER;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001685 } else {
1686 return providers.get(0);
1687 }
1688 }
1689
Nick Pellye0fd6932012-07-11 10:26:13 -07001690 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001691 public boolean providerMeetsCriteria(String provider, Criteria criteria) {
1692 LocationProviderInterface p = mProvidersByName.get(provider);
1693 if (p == null) {
1694 throw new IllegalArgumentException("provider=" + provider);
1695 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001696
1697 boolean result = LocationProvider.propertiesMeetCriteria(
1698 p.getName(), p.getProperties(), criteria);
1699 if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result);
1700 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001701 }
1702
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001703 private void updateProvidersLocked() {
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001704 boolean changesMade = false;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001705 for (int i = mProviders.size() - 1; i >= 0; i--) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001706 LocationProviderInterface p = mProviders.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001707 boolean isEnabled = p.isEnabled();
1708 String name = p.getName();
Victoria Lease09eeaec2013-02-05 11:34:13 -08001709 boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001710 if (isEnabled && !shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001711 updateProviderListenersLocked(name, false);
David Christieb084fef2013-12-18 14:33:57 -08001712 // If any provider has been disabled, clear all last locations for all providers.
1713 // This is to be on the safe side in case a provider has location derived from
1714 // this disabled provider.
1715 mLastLocation.clear();
1716 mLastLocationCoarseInterval.clear();
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001717 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001718 } else if (!isEnabled && shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001719 updateProviderListenersLocked(name, true);
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001720 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001721 }
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001722 }
1723 if (changesMade) {
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001724 mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
1725 UserHandle.ALL);
Tom O'Neill40a86c22013-09-03 18:05:13 -07001726 mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
1727 UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728 }
1729 }
1730
Amith Yamasanib27528d2014-06-05 15:02:10 -07001731 private void updateProviderListenersLocked(String provider, boolean enabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001732 int listeners = 0;
1733
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001734 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001735 if (p == null) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736
1737 ArrayList<Receiver> deadReceivers = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07001738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1740 if (records != null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001741 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001742 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001743 // Sends a notification message to the receiver
1744 if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
1745 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001746 deadReceivers = new ArrayList<>();
Victoria Leaseb711d572012-10-02 13:14:11 -07001747 }
1748 deadReceivers.add(record.mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001749 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001750 listeners++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001751 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001752 }
1753 }
1754
1755 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001756 for (int i = deadReceivers.size() - 1; i >= 0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001757 removeUpdatesLocked(deadReceivers.get(i));
1758 }
1759 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001761 if (enabled) {
1762 p.enable();
1763 if (listeners > 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001764 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765 }
1766 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001767 p.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001769 }
1770
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001771 private void applyRequirementsLocked(String provider) {
1772 LocationProviderInterface p = mProvidersByName.get(provider);
1773 if (p == null) return;
1774
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001775 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001776 WorkSource worksource = new WorkSource();
1777 ProviderRequest providerRequest = new ProviderRequest();
1778
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001779 ContentResolver resolver = mContext.getContentResolver();
1780 long backgroundThrottleInterval = Settings.Global.getLong(
1781 resolver,
1782 Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
1783 DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
gomo48f1a642017-11-10 20:35:46 -08001784 // initialize the low power mode to true and set to false if any of the records requires
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001785
gomo48f1a642017-11-10 20:35:46 -08001786 providerRequest.lowPowerMode = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 if (records != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001788 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001789 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
David Christieb870dbf2015-06-22 12:42:53 -07001790 if (checkLocationAccess(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001791 record.mReceiver.mIdentity.mPid,
1792 record.mReceiver.mIdentity.mUid,
1793 record.mReceiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001794 record.mReceiver.mAllowedResolutionLevel)) {
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001795 LocationRequest locationRequest = record.mRealRequest;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001796 long interval = locationRequest.getInterval();
1797
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001798 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001799 if (!record.mIsForegroundUid) {
1800 interval = Math.max(interval, backgroundThrottleInterval);
1801 }
1802 if (interval != locationRequest.getInterval()) {
1803 locationRequest = new LocationRequest(locationRequest);
1804 locationRequest.setInterval(interval);
1805 }
1806 }
1807
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001808 record.mRequest = locationRequest;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001809 providerRequest.locationRequests.add(locationRequest);
gomo48f1a642017-11-10 20:35:46 -08001810 if (!locationRequest.isLowPowerMode()) {
1811 providerRequest.lowPowerMode = false;
1812 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001813 if (interval < providerRequest.interval) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001814 providerRequest.reportLocation = true;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001815 providerRequest.interval = interval;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001816 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001817 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001818 }
1819 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001820
1821 if (providerRequest.reportLocation) {
1822 // calculate who to blame for power
1823 // This is somewhat arbitrary. We pick a threshold interval
1824 // that is slightly higher that the minimum interval, and
1825 // spread the blame across all applications with a request
1826 // under that threshold.
1827 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
1828 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001829 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001830 LocationRequest locationRequest = record.mRequest;
Svet Ganove998c732016-06-10 00:12:38 -07001831
1832 // Don't assign battery blame for update records whose
1833 // client has no permission to receive location data.
1834 if (!providerRequest.locationRequests.contains(locationRequest)) {
1835 continue;
1836 }
1837
Victoria Leaseb711d572012-10-02 13:14:11 -07001838 if (locationRequest.getInterval() <= thresholdInterval) {
David Christiee55c9682013-08-22 10:10:34 -07001839 if (record.mReceiver.mWorkSource != null
Narayan Kamath32684dd2018-01-08 17:32:51 +00001840 && isValidWorkSource(record.mReceiver.mWorkSource)) {
David Christie82edc9b2013-07-19 11:31:42 -07001841 worksource.add(record.mReceiver.mWorkSource);
1842 } else {
Narayan Kamath32684dd2018-01-08 17:32:51 +00001843 // Assign blame to caller if there's no WorkSource associated with
1844 // the request or if it's invalid.
David Christie82edc9b2013-07-19 11:31:42 -07001845 worksource.add(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001846 record.mReceiver.mIdentity.mUid,
1847 record.mReceiver.mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001848 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001849 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001850 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001851 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001852 }
1853 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001854
1855 if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
1856 p.setRequest(providerRequest, worksource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001857 }
1858
Narayan Kamath32684dd2018-01-08 17:32:51 +00001859 /**
1860 * Whether a given {@code WorkSource} associated with a Location request is valid.
1861 */
1862 private static boolean isValidWorkSource(WorkSource workSource) {
1863 if (workSource.size() > 0) {
1864 // If the WorkSource has one or more non-chained UIDs, make sure they're accompanied
1865 // by tags.
1866 return workSource.getName(0) != null;
1867 } else {
1868 // For now, make sure callers have supplied an attribution tag for use with
1869 // AppOpsManager. This might be relaxed in the future.
1870 final ArrayList<WorkChain> workChains = workSource.getWorkChains();
1871 return workChains != null && !workChains.isEmpty() &&
1872 workChains.get(0).getAttributionTag() != null;
1873 }
1874 }
1875
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001876 @Override
1877 public String[] getBackgroundThrottlingWhitelist() {
1878 synchronized (mLock) {
1879 return mBackgroundThrottlePackageWhitelist.toArray(
gomo48f1a642017-11-10 20:35:46 -08001880 new String[mBackgroundThrottlePackageWhitelist.size()]);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001881 }
1882 }
1883
1884 private void updateBackgroundThrottlingWhitelistLocked() {
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001885 String setting = Settings.Global.getString(
gomo48f1a642017-11-10 20:35:46 -08001886 mContext.getContentResolver(),
1887 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001888 if (setting == null) {
1889 setting = "";
1890 }
1891
1892 mBackgroundThrottlePackageWhitelist.clear();
1893 mBackgroundThrottlePackageWhitelist.addAll(
gomo48f1a642017-11-10 20:35:46 -08001894 SystemConfig.getInstance().getAllowUnthrottledLocation());
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001895 mBackgroundThrottlePackageWhitelist.addAll(
gomo48f1a642017-11-10 20:35:46 -08001896 Arrays.asList(setting.split(",")));
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001897 }
1898
Wei Wangdd070f22018-06-21 11:29:40 -07001899 private void updateLastLocationMaxAgeLocked() {
1900 mLastLocationMaxAgeMs =
1901 Settings.Global.getLong(
1902 mContext.getContentResolver(),
1903 Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
1904 DEFAULT_LAST_LOCATION_MAX_AGE_MS);
1905 }
1906
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001907 private boolean isThrottlingExemptLocked(Identity identity) {
1908 if (identity.mUid == Process.SYSTEM_UID) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001909 return true;
1910 }
1911
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001912 if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001913 return true;
1914 }
1915
1916 for (LocationProviderProxy provider : mProxyProviders) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001917 if (identity.mPackageName.equals(provider.getConnectedPackageName())) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001918 return true;
1919 }
1920 }
1921
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001922 return false;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001923 }
1924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001925 private class UpdateRecord {
1926 final String mProvider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001927 final LocationRequest mRealRequest; // original request from client
1928 LocationRequest mRequest; // possibly throttled version of the request
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001929 final Receiver mReceiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001930 boolean mIsForegroundUid;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001931 Location mLastFixBroadcast;
1932 long mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001933
1934 /**
1935 * Note: must be constructed with lock held.
1936 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001937 UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001938 mProvider = provider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001939 mRealRequest = request;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001940 mRequest = request;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001941 mReceiver = receiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001942 mIsForegroundUid = isImportanceForeground(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001943 mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001944
1945 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1946 if (records == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001947 records = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001948 mRecordsByProvider.put(provider, records);
1949 }
1950 if (!records.contains(this)) {
1951 records.add(this);
1952 }
David Christie2ff96af2014-01-30 16:09:37 -08001953
1954 // Update statistics for historical location requests by package/provider
1955 mRequestStatistics.startRequesting(
Wyatt Rileyf7075e02018-04-12 17:54:26 -07001956 mReceiver.mIdentity.mPackageName, provider, request.getInterval(),
1957 mIsForegroundUid);
1958 }
1959
1960 /**
1961 * Method to be called when record changes foreground/background
1962 */
1963 void updateForeground(boolean isForeground){
1964 mIsForegroundUid = isForeground;
1965 mRequestStatistics.updateForeground(
1966 mReceiver.mIdentity.mPackageName, mProvider, isForeground);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001967 }
1968
1969 /**
David Christie2ff96af2014-01-30 16:09:37 -08001970 * Method to be called when a record will no longer be used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001971 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001972 void disposeLocked(boolean removeReceiver) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001973 mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider);
David Christie2ff96af2014-01-30 16:09:37 -08001974
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001975 // remove from mRecordsByProvider
1976 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
1977 if (globalRecords != null) {
1978 globalRecords.remove(this);
1979 }
1980
1981 if (!removeReceiver) return; // the caller will handle the rest
1982
1983 // remove from Receiver#mUpdateRecords
1984 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
1985 if (receiverRecords != null) {
1986 receiverRecords.remove(this.mProvider);
1987
1988 // and also remove the Receiver if it has no more update records
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001989 if (receiverRecords.size() == 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001990 removeUpdatesLocked(mReceiver);
1991 }
Mike Lockwood3a76fd62009-09-01 07:26:56 -04001992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001993 }
1994
1995 @Override
1996 public String toString() {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001997 return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
gomo48f1a642017-11-10 20:35:46 -08001998 + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground"
1999 : " background")
Wyatt Riley19adc022018-05-22 13:30:51 -07002000 + ")" + " " + mRealRequest + " "
2001 + mReceiver.mWorkSource + "]";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002002 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002003 }
2004
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002005 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -07002006 String packageName, WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002007 IBinder binder = listener.asBinder();
2008 Receiver receiver = mReceivers.get(binder);
2009 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07002010 receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
2011 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002012 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002013 receiver.getListener().asBinder().linkToDeath(receiver, 0);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002014 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002015 Slog.e(TAG, "linkToDeath failed:", e);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002016 return null;
2017 }
Wen Jingcb3ab222014-03-27 13:42:59 +08002018 mReceivers.put(binder, receiver);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002019 }
2020 return receiver;
2021 }
2022
David Christie82edc9b2013-07-19 11:31:42 -07002023 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
David Christie40e57822013-07-30 11:36:48 -07002024 WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002025 Receiver receiver = mReceivers.get(intent);
2026 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07002027 receiver = new Receiver(null, intent, pid, uid, packageName, workSource,
2028 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002029 mReceivers.put(intent, receiver);
2030 }
2031 return receiver;
2032 }
2033
Victoria Lease37425c32012-10-16 16:08:48 -07002034 /**
2035 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
2036 * and consistency requirements.
2037 *
2038 * @param request the LocationRequest from which to create a sanitized version
Victoria Lease37425c32012-10-16 16:08:48 -07002039 * @return a version of request that meets the given resolution and consistency requirements
2040 * @hide
2041 */
gomo48f1a642017-11-10 20:35:46 -08002042 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel,
2043 boolean callerHasLocationHardwarePermission) {
Victoria Lease37425c32012-10-16 16:08:48 -07002044 LocationRequest sanitizedRequest = new LocationRequest(request);
gomo48f1a642017-11-10 20:35:46 -08002045 if (!callerHasLocationHardwarePermission) {
2046 // allow setting low power mode only for callers with location hardware permission
2047 sanitizedRequest.setLowPowerMode(false);
2048 }
Victoria Lease37425c32012-10-16 16:08:48 -07002049 if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
2050 switch (sanitizedRequest.getQuality()) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002051 case LocationRequest.ACCURACY_FINE:
Victoria Lease37425c32012-10-16 16:08:48 -07002052 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
Victoria Lease09016ab2012-09-16 12:33:15 -07002053 break;
2054 case LocationRequest.POWER_HIGH:
Victoria Lease37425c32012-10-16 16:08:48 -07002055 sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
Victoria Lease09016ab2012-09-16 12:33:15 -07002056 break;
2057 }
2058 // throttle
Victoria Lease37425c32012-10-16 16:08:48 -07002059 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
2060 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07002061 }
Victoria Lease37425c32012-10-16 16:08:48 -07002062 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
2063 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07002064 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07002065 }
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002066 // make getFastestInterval() the minimum of interval and fastest interval
Victoria Lease37425c32012-10-16 16:08:48 -07002067 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002068 request.setFastestInterval(request.getInterval());
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002069 }
Victoria Lease37425c32012-10-16 16:08:48 -07002070 return sanitizedRequest;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002071 }
2072
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002073 private void checkPackageName(String packageName) {
Nick Pellye0fd6932012-07-11 10:26:13 -07002074 if (packageName == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002075 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002076 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002077 int uid = Binder.getCallingUid();
Nick Pellye0fd6932012-07-11 10:26:13 -07002078 String[] packages = mPackageManager.getPackagesForUid(uid);
2079 if (packages == null) {
2080 throw new SecurityException("invalid UID " + uid);
2081 }
2082 for (String pkg : packages) {
2083 if (packageName.equals(pkg)) return;
2084 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002085 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002086 }
2087
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002088 private void checkPendingIntent(PendingIntent intent) {
2089 if (intent == null) {
2090 throw new IllegalArgumentException("invalid pending intent: " + intent);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002091 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002092 }
2093
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002094 private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent,
David Christie40e57822013-07-30 11:36:48 -07002095 int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002096 if (intent == null && listener == null) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002097 throw new IllegalArgumentException("need either listener or intent");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002098 } else if (intent != null && listener != null) {
2099 throw new IllegalArgumentException("cannot register both listener and intent");
2100 } else if (intent != null) {
2101 checkPendingIntent(intent);
David Christie40e57822013-07-30 11:36:48 -07002102 return getReceiverLocked(intent, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002103 } else {
David Christie40e57822013-07-30 11:36:48 -07002104 return getReceiverLocked(listener, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002105 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002106 }
2107
Nick Pellye0fd6932012-07-11 10:26:13 -07002108 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002109 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
2110 PendingIntent intent, String packageName) {
2111 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2112 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002113 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2114 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2115 request.getProvider());
David Christie82edc9b2013-07-19 11:31:42 -07002116 WorkSource workSource = request.getWorkSource();
Narayan Kamath32684dd2018-01-08 17:32:51 +00002117 if (workSource != null && !workSource.isEmpty()) {
David Christie40e57822013-07-30 11:36:48 -07002118 checkDeviceStatsAllowed();
2119 }
2120 boolean hideFromAppOps = request.getHideFromAppOps();
2121 if (hideFromAppOps) {
2122 checkUpdateAppOpsAllowed();
David Christie82edc9b2013-07-19 11:31:42 -07002123 }
gomo48f1a642017-11-10 20:35:46 -08002124 boolean callerHasLocationHardwarePermission =
2125 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
Maggieaa080f92018-01-04 15:35:11 -08002126 == PERMISSION_GRANTED;
gomo48f1a642017-11-10 20:35:46 -08002127 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel,
2128 callerHasLocationHardwarePermission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002129
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002130 final int pid = Binder.getCallingPid();
2131 final int uid = Binder.getCallingUid();
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002132 // providers may use public location API's, need to clear identity
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002133 long identity = Binder.clearCallingIdentity();
2134 try {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002135 // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2136 // a location.
David Christieb870dbf2015-06-22 12:42:53 -07002137 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002138
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002139 synchronized (mLock) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002140 Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
David Christie40e57822013-07-30 11:36:48 -07002141 packageName, workSource, hideFromAppOps);
Victoria Lease37425c32012-10-16 16:08:48 -07002142 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
Mike Lockwood2d4d1bf2010-10-18 17:06:26 -04002143 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002144 } finally {
2145 Binder.restoreCallingIdentity(identity);
2146 }
2147 }
2148
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002149 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
2150 int pid, int uid, String packageName) {
2151 // Figure out the provider. Either its explicitly request (legacy use cases), or
2152 // use the fused provider
2153 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2154 String name = request.getProvider();
Victoria Lease09016ab2012-09-16 12:33:15 -07002155 if (name == null) {
2156 throw new IllegalArgumentException("provider name must not be null");
2157 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -07002158
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002159 LocationProviderInterface provider = mProvidersByName.get(name);
2160 if (provider == null) {
Victoria Leaseb30f3832013-10-13 12:15:40 -07002161 throw new IllegalArgumentException("provider doesn't exist: " + name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002162 }
2163
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002164 UpdateRecord record = new UpdateRecord(name, request, receiver);
gomo48f1a642017-11-10 20:35:46 -08002165 if (D) {
2166 Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
2167 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
2168 + (record.mIsForegroundUid ? "foreground" : "background")
2169 + (isThrottlingExemptLocked(receiver.mIdentity)
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002170 ? " [whitelisted]" : "") + ")");
gomo48f1a642017-11-10 20:35:46 -08002171 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002172
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002173 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
2174 if (oldRecord != null) {
2175 oldRecord.disposeLocked(false);
2176 }
2177
Maggie2a9409e2018-03-21 11:47:28 -07002178 boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid, mCurrentUserId);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002179 if (isProviderEnabled) {
2180 applyRequirementsLocked(name);
2181 } else {
2182 // Notify the listener that updates are currently disabled
2183 receiver.callProviderEnabledLocked(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002184 }
David Christie0b837452013-07-29 16:02:13 -07002185 // Update the monitoring here just in case multiple location requests were added to the
2186 // same receiver (this request may be high power and the initial might not have been).
2187 receiver.updateMonitoring(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188 }
2189
Nick Pellye0fd6932012-07-11 10:26:13 -07002190 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002191 public void removeUpdates(ILocationListener listener, PendingIntent intent,
2192 String packageName) {
2193 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002194
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002195 final int pid = Binder.getCallingPid();
2196 final int uid = Binder.getCallingUid();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002197
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002198 synchronized (mLock) {
David Christie82edc9b2013-07-19 11:31:42 -07002199 WorkSource workSource = null;
David Christie40e57822013-07-30 11:36:48 -07002200 boolean hideFromAppOps = false;
2201 Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid,
2202 packageName, workSource, hideFromAppOps);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002203
2204 // providers may use public location API's, need to clear identity
2205 long identity = Binder.clearCallingIdentity();
2206 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002207 removeUpdatesLocked(receiver);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002208 } finally {
2209 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002210 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002211 }
2212 }
2213
2214 private void removeUpdatesLocked(Receiver receiver) {
Dianne Hackborn7ff30112012-11-08 11:12:09 -08002215 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002216
2217 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
2218 receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
2219 synchronized (receiver) {
Victoria Lease0aa28602013-05-29 15:28:26 -07002220 receiver.clearPendingBroadcastsLocked();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002222 }
2223
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07002224 receiver.updateMonitoring(false);
2225
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002226 // Record which providers were associated with this listener
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002227 HashSet<String> providers = new HashSet<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002228 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2229 if (oldRecords != null) {
2230 // Call dispose() on the obsolete update records.
2231 for (UpdateRecord record : oldRecords.values()) {
David Christie2ff96af2014-01-30 16:09:37 -08002232 // Update statistics for historical location requests by package/provider
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002233 record.disposeLocked(false);
2234 }
2235 // Accumulate providers
2236 providers.addAll(oldRecords.keySet());
2237 }
2238
2239 // update provider
2240 for (String provider : providers) {
2241 // If provider is already disabled, don't need to do anything
Victoria Lease09eeaec2013-02-05 11:34:13 -08002242 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002243 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002244 }
2245
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002246 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002247 }
2248 }
2249
Dianne Hackbornc2293022013-02-06 23:14:49 -08002250 private void applyAllProviderRequirementsLocked() {
2251 for (LocationProviderInterface p : mProviders) {
2252 // If provider is already disabled, don't need to do anything
Dianne Hackborn64d41d72013-02-07 00:33:31 -08002253 if (!isAllowedByCurrentUserSettingsLocked(p.getName())) {
Dianne Hackbornc2293022013-02-06 23:14:49 -08002254 continue;
2255 }
2256
2257 applyRequirementsLocked(p.getName());
2258 }
2259 }
2260
Nick Pellye0fd6932012-07-11 10:26:13 -07002261 @Override
Nick Pelly4035f5a2012-08-17 14:43:49 -07002262 public Location getLastLocation(LocationRequest request, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002263 if (D) Log.d(TAG, "getLastLocation: " + request);
2264 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002265 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly4035f5a2012-08-17 14:43:49 -07002266 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002267 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2268 request.getProvider());
2269 // no need to sanitize this request, as only the provider name is used
Nick Pelly4035f5a2012-08-17 14:43:49 -07002270
David Christieb870dbf2015-06-22 12:42:53 -07002271 final int pid = Binder.getCallingPid();
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002272 final int uid = Binder.getCallingUid();
2273 final long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07002274 try {
2275 if (mBlacklist.isBlacklisted(packageName)) {
gomo48f1a642017-11-10 20:35:46 -08002276 if (D) {
2277 Log.d(TAG, "not returning last loc for blacklisted app: " +
2278 packageName);
2279 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002280 return null;
2281 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002282
David Christieb870dbf2015-06-22 12:42:53 -07002283 if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel)) {
gomo48f1a642017-11-10 20:35:46 -08002284 if (D) {
2285 Log.d(TAG, "not returning last loc for no op app: " +
2286 packageName);
2287 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002288 return null;
2289 }
2290
Victoria Leaseb711d572012-10-02 13:14:11 -07002291 synchronized (mLock) {
2292 // Figure out the provider. Either its explicitly request (deprecated API's),
2293 // or use the fused provider
2294 String name = request.getProvider();
2295 if (name == null) name = LocationManager.FUSED_PROVIDER;
2296 LocationProviderInterface provider = mProvidersByName.get(name);
2297 if (provider == null) return null;
2298
Maggie2a9409e2018-03-21 11:47:28 -07002299 if (!isAllowedByUserSettingsLocked(name, uid, mCurrentUserId)) return null;
Victoria Leaseb711d572012-10-02 13:14:11 -07002300
David Christie1b9b7b12013-04-15 15:31:11 -07002301 Location location;
2302 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2303 // Make sure that an app with coarse permissions can't get frequent location
2304 // updates by calling LocationManager.getLastKnownLocation repeatedly.
2305 location = mLastLocationCoarseInterval.get(name);
2306 } else {
2307 location = mLastLocation.get(name);
2308 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002309 if (location == null) {
2310 return null;
2311 }
Wei Wangdd070f22018-06-21 11:29:40 -07002312
2313 // Don't return stale location to apps with foreground-only location permission.
Wei Wangb86334f2018-07-03 16:33:24 -07002314 String op = resolutionLevelToOpStr(allowedResolutionLevel);
Wei Wangdd070f22018-06-21 11:29:40 -07002315 long locationAgeMs = SystemClock.elapsedRealtime() -
2316 location.getElapsedRealtimeNanos() / NANOS_PER_MILLI;
2317 if ((locationAgeMs > mLastLocationMaxAgeMs)
2318 && (mAppOps.unsafeCheckOp(op, uid, packageName)
2319 == AppOpsManager.MODE_FOREGROUND)) {
2320 return null;
2321 }
2322
Victoria Lease37425c32012-10-16 16:08:48 -07002323 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
gomo48f1a642017-11-10 20:35:46 -08002324 Location noGPSLocation = location.getExtraLocation(
2325 Location.EXTRA_NO_GPS_LOCATION);
Victoria Leaseb711d572012-10-02 13:14:11 -07002326 if (noGPSLocation != null) {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002327 return new Location(mLocationFudger.getOrCreate(noGPSLocation));
Victoria Leaseb711d572012-10-02 13:14:11 -07002328 }
Victoria Lease37425c32012-10-16 16:08:48 -07002329 } else {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002330 return new Location(location);
Victoria Lease09016ab2012-09-16 12:33:15 -07002331 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002332 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002333 return null;
2334 } finally {
2335 Binder.restoreCallingIdentity(identity);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002336 }
2337 }
2338
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002339 /**
2340 * Provides an interface to inject and set the last location if location is not available
2341 * currently.
2342 *
2343 * This helps in cases where the product (Cars for example) has saved the last known location
2344 * before powering off. This interface lets the client inject the saved location while the GPS
2345 * chipset is getting its first fix, there by improving user experience.
2346 *
2347 * @param location - Location object to inject
2348 * @return true if update was successful, false if not
2349 */
2350 @Override
2351 public boolean injectLocation(Location location) {
2352 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
2353 "Location Hardware permission not granted to inject location");
2354 mContext.enforceCallingPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
2355 "Access Fine Location permission not granted to inject Location");
2356
2357 if (location == null) {
2358 if (D) {
2359 Log.d(TAG, "injectLocation(): called with null location");
2360 }
2361 return false;
2362 }
2363 LocationProviderInterface p = null;
2364 String provider = location.getProvider();
2365 if (provider != null) {
2366 p = mProvidersByName.get(provider);
2367 }
2368 if (p == null) {
2369 if (D) {
2370 Log.d(TAG, "injectLocation(): unknown provider");
2371 }
2372 return false;
2373 }
2374 synchronized (mLock) {
2375 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
2376 if (D) {
2377 Log.d(TAG, "Location disabled in Settings for current user:" + mCurrentUserId);
2378 }
2379 return false;
2380 } else {
2381 // NOTE: If last location is already available, location is not injected. If
2382 // provider's normal source (like a GPS chipset) have already provided an output,
2383 // there is no need to inject this location.
2384 if (mLastLocation.get(provider) == null) {
2385 updateLastLocationLocked(location, provider);
2386 } else {
2387 if (D) {
2388 Log.d(TAG, "injectLocation(): Location exists. Not updating");
2389 }
2390 return false;
2391 }
2392 }
2393 }
2394 return true;
2395 }
2396
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002397 @Override
2398 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
2399 String packageName) {
2400 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002401 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2402 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002403 checkPendingIntent(intent);
2404 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002405 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2406 request.getProvider());
gomo48f1a642017-11-10 20:35:46 -08002407 // Require that caller can manage given document
2408 boolean callerHasLocationHardwarePermission =
2409 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
Maggieaa080f92018-01-04 15:35:11 -08002410 == PERMISSION_GRANTED;
gomo48f1a642017-11-10 20:35:46 -08002411 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel,
2412 callerHasLocationHardwarePermission);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002413
Victoria Lease37425c32012-10-16 16:08:48 -07002414 if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002415
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002416 // geo-fence manager uses the public location API, need to clear identity
2417 int uid = Binder.getCallingUid();
Xiaohui Chena4490622015-09-22 15:29:31 -07002418 // TODO: http://b/23822629
2419 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
Victoria Lease56e675b2012-11-05 19:25:06 -08002420 // temporary measure until geofences work for secondary users
2421 Log.w(TAG, "proximity alerts are currently available only to the primary user");
2422 return;
2423 }
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002424 long identity = Binder.clearCallingIdentity();
2425 try {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002426 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
2427 uid, packageName);
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002428 } finally {
2429 Binder.restoreCallingIdentity(identity);
2430 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002431 }
2432
2433 @Override
2434 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002435 checkPendingIntent(intent);
2436 checkPackageName(packageName);
2437
2438 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2439
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002440 // geo-fence manager uses the public location API, need to clear identity
2441 long identity = Binder.clearCallingIdentity();
2442 try {
2443 mGeofenceManager.removeFence(geofence, intent);
2444 } finally {
2445 Binder.restoreCallingIdentity(identity);
2446 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002447 }
2448
2449
2450 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002451 public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002452 if (!hasGnssPermissions(packageName) || mGnssStatusProvider == null) {
Takayuki Hoshib254ab6a2014-10-23 16:46:02 +09002453 return false;
2454 }
2455
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002456 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002457 mGnssStatusProvider.registerGnssStatusCallback(callback);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002458 } catch (RemoteException e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002459 Slog.e(TAG, "mGpsStatusProvider.registerGnssStatusCallback failed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002460 return false;
2461 }
2462 return true;
2463 }
2464
Nick Pellye0fd6932012-07-11 10:26:13 -07002465 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002466 public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002467 synchronized (mLock) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002468 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002469 mGnssStatusProvider.unregisterGnssStatusCallback(callback);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002470 } catch (Exception e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002471 Slog.e(TAG, "mGpsStatusProvider.unregisterGnssStatusCallback failed", e);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002473 }
2474 }
2475
Nick Pellye0fd6932012-07-11 10:26:13 -07002476 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002477 public boolean addGnssMeasurementsListener(
gomo48f1a642017-11-10 20:35:46 -08002478 IGnssMeasurementsListener listener, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002479 if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
destradaaea8a8a62014-06-23 18:19:03 -07002480 return false;
2481 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002482
2483 synchronized (mLock) {
2484 Identity callerIdentity
2485 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
Wyatt Riley11cc7492018-01-17 08:48:27 -08002486 mGnssMeasurementsListeners.put(listener.asBinder(), callerIdentity);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002487 long identity = Binder.clearCallingIdentity();
2488 try {
2489 if (isThrottlingExemptLocked(callerIdentity)
2490 || isImportanceForeground(
gomo48f1a642017-11-10 20:35:46 -08002491 mActivityManager.getPackageImportance(packageName))) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002492 return mGnssMeasurementsProvider.addListener(listener);
2493 }
2494 } finally {
2495 Binder.restoreCallingIdentity(identity);
2496 }
2497
2498 return true;
2499 }
destradaaea8a8a62014-06-23 18:19:03 -07002500 }
2501
2502 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002503 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
2504 if (mGnssMeasurementsProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002505 synchronized (mLock) {
Wyatt Riley11cc7492018-01-17 08:48:27 -08002506 mGnssMeasurementsListeners.remove(listener.asBinder());
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002507 mGnssMeasurementsProvider.removeListener(listener);
2508 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002509 }
destradaaea8a8a62014-06-23 18:19:03 -07002510 }
2511
2512 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002513 public boolean addGnssNavigationMessageListener(
2514 IGnssNavigationMessageListener listener,
destradaa4b3e3932014-07-21 18:01:47 -07002515 String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002516 if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) {
destradaa4b3e3932014-07-21 18:01:47 -07002517 return false;
2518 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002519
2520 synchronized (mLock) {
2521 Identity callerIdentity
gomo48f1a642017-11-10 20:35:46 -08002522 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
Wyatt Riley11cc7492018-01-17 08:48:27 -08002523 mGnssNavigationMessageListeners.put(listener.asBinder(), callerIdentity);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002524 long identity = Binder.clearCallingIdentity();
2525 try {
2526 if (isThrottlingExemptLocked(callerIdentity)
2527 || isImportanceForeground(
gomo48f1a642017-11-10 20:35:46 -08002528 mActivityManager.getPackageImportance(packageName))) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002529 return mGnssNavigationMessageProvider.addListener(listener);
2530 }
2531 } finally {
2532 Binder.restoreCallingIdentity(identity);
2533 }
2534
2535 return true;
2536 }
destradaa4b3e3932014-07-21 18:01:47 -07002537 }
2538
2539 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002540 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
2541 if (mGnssNavigationMessageProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002542 synchronized (mLock) {
Wyatt Riley11cc7492018-01-17 08:48:27 -08002543 mGnssNavigationMessageListeners.remove(listener.asBinder());
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002544 mGnssNavigationMessageProvider.removeListener(listener);
2545 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002546 }
destradaa4b3e3932014-07-21 18:01:47 -07002547 }
2548
2549 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002550 public boolean sendExtraCommand(String provider, String command, Bundle extras) {
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002551 if (provider == null) {
2552 // throw NullPointerException to remain compatible with previous implementation
2553 throw new NullPointerException();
2554 }
Victoria Lease37425c32012-10-16 16:08:48 -07002555 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2556 provider);
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002558 // and check for ACCESS_LOCATION_EXTRA_COMMANDS
Mike Lockwoodb7e99222009-07-07 13:18:21 -04002559 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
Maggieaa080f92018-01-04 15:35:11 -08002560 != PERMISSION_GRANTED)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002561 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
2562 }
2563
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002564 synchronized (mLock) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002565 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002566 if (p == null) return false;
Nick Pellye0fd6932012-07-11 10:26:13 -07002567
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002568 return p.sendExtraCommand(command, extras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002569 }
2570 }
2571
Nick Pellye0fd6932012-07-11 10:26:13 -07002572 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002573 public boolean sendNiResponse(int notifId, int userResponse) {
Mike Lockwood18ad9f62009-08-27 14:01:23 -07002574 if (Binder.getCallingUid() != Process.myUid()) {
2575 throw new SecurityException(
2576 "calling sendNiResponse from outside of the system is not allowed");
2577 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002578 try {
2579 return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002580 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002581 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
Danke Xie22d1f9f2009-08-18 18:28:45 -04002582 return false;
2583 }
2584 }
2585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002586 /**
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002587 * @return null if the provider does not exist
Alexey Tarasovf2db9fb2009-09-01 02:37:07 +11002588 * @throws SecurityException if the provider is not allowed to be
gomo48f1a642017-11-10 20:35:46 -08002589 * accessed by the caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002590 */
Nick Pellye0fd6932012-07-11 10:26:13 -07002591 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002592 public ProviderProperties getProviderProperties(String provider) {
Laurent Tub7f9d252012-10-16 14:25:00 -07002593 if (mProvidersByName.get(provider) == null) {
David Christie2ff96af2014-01-30 16:09:37 -08002594 return null;
Laurent Tub7f9d252012-10-16 14:25:00 -07002595 }
2596
Victoria Lease37425c32012-10-16 16:08:48 -07002597 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2598 provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002599
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002600 LocationProviderInterface p;
2601 synchronized (mLock) {
2602 p = mProvidersByName.get(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002603 }
2604
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002605 if (p == null) return null;
2606 return p.getProperties();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002607 }
2608
Jason Monkb71218a2015-06-17 14:44:39 -04002609 /**
2610 * @return null if the provider does not exist
2611 * @throws SecurityException if the provider is not allowed to be
gomo48f1a642017-11-10 20:35:46 -08002612 * accessed by the caller
Jason Monkb71218a2015-06-17 14:44:39 -04002613 */
2614 @Override
2615 public String getNetworkProviderPackage() {
2616 LocationProviderInterface p;
2617 synchronized (mLock) {
2618 if (mProvidersByName.get(LocationManager.NETWORK_PROVIDER) == null) {
2619 return null;
2620 }
2621 p = mProvidersByName.get(LocationManager.NETWORK_PROVIDER);
2622 }
2623
2624 if (p instanceof LocationProviderProxy) {
2625 return ((LocationProviderProxy) p).getConnectedPackageName();
2626 }
2627 return null;
2628 }
2629
Maggieaa080f92018-01-04 15:35:11 -08002630 /**
Maggie2a9409e2018-03-21 11:47:28 -07002631 * Returns the current location enabled/disabled status for a user
2632 *
2633 * @param userId the id of the user
2634 * @return true if location is enabled
2635 */
2636 @Override
2637 public boolean isLocationEnabledForUser(int userId) {
2638 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2639 checkInteractAcrossUsersPermission(userId);
2640
2641 long identity = Binder.clearCallingIdentity();
2642 try {
2643 synchronized (mLock) {
2644 final String allowedProviders = Settings.Secure.getStringForUser(
2645 mContext.getContentResolver(),
2646 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
2647 userId);
2648 if (allowedProviders == null) {
2649 return false;
2650 }
2651 final List<String> providerList = Arrays.asList(allowedProviders.split(","));
2652 for(String provider : mRealProviders.keySet()) {
2653 if (provider.equals(LocationManager.PASSIVE_PROVIDER)
2654 || provider.equals(LocationManager.FUSED_PROVIDER)) {
2655 continue;
2656 }
2657 if (providerList.contains(provider)) {
2658 return true;
2659 }
2660 }
2661 return false;
2662 }
2663 } finally {
2664 Binder.restoreCallingIdentity(identity);
2665 }
2666 }
2667
2668 /**
2669 * Enable or disable location for a user
2670 *
2671 * @param enabled true to enable location, false to disable location
2672 * @param userId the id of the user
2673 */
2674 @Override
2675 public void setLocationEnabledForUser(boolean enabled, int userId) {
2676 mContext.enforceCallingPermission(
2677 android.Manifest.permission.WRITE_SECURE_SETTINGS,
2678 "Requires WRITE_SECURE_SETTINGS permission");
2679
2680 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2681 checkInteractAcrossUsersPermission(userId);
2682
2683 long identity = Binder.clearCallingIdentity();
2684 try {
2685 synchronized (mLock) {
2686 final Set<String> allRealProviders = mRealProviders.keySet();
2687 // Update all providers on device plus gps and network provider when disabling
2688 // location
2689 Set<String> allProvidersSet = new ArraySet<>(allRealProviders.size() + 2);
2690 allProvidersSet.addAll(allRealProviders);
2691 // When disabling location, disable gps and network provider that could have been
2692 // enabled by location mode api.
2693 if (enabled == false) {
2694 allProvidersSet.add(LocationManager.GPS_PROVIDER);
2695 allProvidersSet.add(LocationManager.NETWORK_PROVIDER);
2696 }
2697 if (allProvidersSet.isEmpty()) {
2698 return;
2699 }
2700 // to ensure thread safety, we write the provider name with a '+' or '-'
2701 // and let the SettingsProvider handle it rather than reading and modifying
2702 // the list of enabled providers.
2703 final String prefix = enabled ? "+" : "-";
2704 StringBuilder locationProvidersAllowed = new StringBuilder();
2705 for (String provider : allProvidersSet) {
2706 if (provider.equals(LocationManager.PASSIVE_PROVIDER)
2707 || provider.equals(LocationManager.FUSED_PROVIDER)) {
2708 continue;
2709 }
2710 locationProvidersAllowed.append(prefix);
2711 locationProvidersAllowed.append(provider);
2712 locationProvidersAllowed.append(",");
2713 }
2714 // Remove the trailing comma
2715 locationProvidersAllowed.setLength(locationProvidersAllowed.length() - 1);
2716 Settings.Secure.putStringForUser(
2717 mContext.getContentResolver(),
2718 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
2719 locationProvidersAllowed.toString(),
2720 userId);
2721 }
2722 } finally {
2723 Binder.restoreCallingIdentity(identity);
2724 }
2725 }
2726
2727 /**
2728 * Returns the current enabled/disabled status of a location provider and user
2729 *
2730 * @param provider name of the provider
2731 * @param userId the id of the user
2732 * @return true if the provider exists and is enabled
2733 */
2734 @Override
2735 public boolean isProviderEnabledForUser(String provider, int userId) {
2736 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2737 checkInteractAcrossUsersPermission(userId);
2738
2739 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2740 // so we discourage its use
2741 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
2742
2743 int uid = Binder.getCallingUid();
2744 synchronized (mLock) {
2745 LocationProviderInterface p = mProvidersByName.get(provider);
2746 return p != null
2747 && isAllowedByUserSettingsLocked(provider, uid, userId);
2748 }
2749 }
2750
2751 /**
2752 * Enable or disable a single location provider.
2753 *
2754 * @param provider name of the provider
2755 * @param enabled true to enable the provider. False to disable the provider
2756 * @param userId the id of the user to set
2757 * @return true if the value was set, false on errors
2758 */
2759 @Override
2760 public boolean setProviderEnabledForUser(String provider, boolean enabled, int userId) {
2761 mContext.enforceCallingPermission(
2762 android.Manifest.permission.WRITE_SECURE_SETTINGS,
2763 "Requires WRITE_SECURE_SETTINGS permission");
2764
2765 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
2766 checkInteractAcrossUsersPermission(userId);
2767
2768 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2769 // so we discourage its use
2770 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
2771
2772 long identity = Binder.clearCallingIdentity();
2773 try {
2774 synchronized (mLock) {
2775 // No such provider exists
2776 if (!mProvidersByName.containsKey(provider)) return false;
2777
2778 // If it is a test provider, do not write to Settings.Secure
2779 if (mMockProviders.containsKey(provider)) {
2780 setTestProviderEnabled(provider, enabled);
2781 return true;
2782 }
2783
2784 // to ensure thread safety, we write the provider name with a '+' or '-'
2785 // and let the SettingsProvider handle it rather than reading and modifying
2786 // the list of enabled providers.
2787 String providerChange = (enabled ? "+" : "-") + provider;
2788 return Settings.Secure.putStringForUser(
2789 mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
2790 providerChange, userId);
2791 }
2792 } finally {
2793 Binder.restoreCallingIdentity(identity);
2794 }
2795 }
2796
2797 /**
Maggieaa080f92018-01-04 15:35:11 -08002798 * Read location provider status from Settings.Secure
2799 *
2800 * @param provider the location provider to query
2801 * @param userId the user id to query
2802 * @return true if the provider is enabled
2803 */
2804 private boolean isLocationProviderEnabledForUser(String provider, int userId) {
2805 long identity = Binder.clearCallingIdentity();
2806 try {
2807 // Use system settings
2808 ContentResolver cr = mContext.getContentResolver();
2809 String allowedProviders = Settings.Secure.getStringForUser(
2810 cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userId);
2811 return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
2812 } finally {
2813 Binder.restoreCallingIdentity(identity);
2814 }
2815 }
2816
2817 /**
Maggie2a9409e2018-03-21 11:47:28 -07002818 * Method for checking INTERACT_ACROSS_USERS permission if specified user id is not the same as
2819 * current user id
2820 *
2821 * @param userId the user id to get or set value
2822 */
2823 private void checkInteractAcrossUsersPermission(int userId) {
2824 int uid = Binder.getCallingUid();
2825 if (UserHandle.getUserId(uid) != userId) {
2826 if (ActivityManager.checkComponentPermission(
2827 android.Manifest.permission.INTERACT_ACROSS_USERS, uid, -1, true)
2828 != PERMISSION_GRANTED) {
2829 throw new SecurityException("Requires INTERACT_ACROSS_USERS permission");
2830 }
2831 }
2832 }
2833
2834 /**
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002835 * Returns "true" if the UID belongs to a bound location provider.
2836 *
2837 * @param uid the uid
2838 * @return true if uid belongs to a bound location provider
2839 */
2840 private boolean isUidALocationProvider(int uid) {
2841 if (uid == Process.SYSTEM_UID) {
2842 return true;
2843 }
2844 if (mGeocodeProvider != null) {
David Christie1f141c12014-05-14 15:11:15 -07002845 if (doesUidHavePackage(uid, mGeocodeProvider.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002846 }
2847 for (LocationProviderProxy proxy : mProxyProviders) {
David Christie1f141c12014-05-14 15:11:15 -07002848 if (doesUidHavePackage(uid, proxy.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002849 }
2850 return false;
2851 }
2852
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002853 private void checkCallerIsProvider() {
2854 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
Maggieaa080f92018-01-04 15:35:11 -08002855 == PERMISSION_GRANTED) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002856 return;
2857 }
2858
2859 // Previously we only used the INSTALL_LOCATION_PROVIDER
2860 // check. But that is system or signature
2861 // protection level which is not flexible enough for
2862 // providers installed oustide the system image. So
2863 // also allow providers with a UID matching the
2864 // currently bound package name
2865
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002866 if (isUidALocationProvider(Binder.getCallingUid())) {
2867 return;
2868 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002869
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002870 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
2871 "or UID of a currently bound location provider");
2872 }
2873
David Christie1f141c12014-05-14 15:11:15 -07002874 /**
2875 * Returns true if the given package belongs to the given uid.
2876 */
2877 private boolean doesUidHavePackage(int uid, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002878 if (packageName == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002879 return false;
2880 }
David Christie1f141c12014-05-14 15:11:15 -07002881 String[] packageNames = mPackageManager.getPackagesForUid(uid);
2882 if (packageNames == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002883 return false;
2884 }
David Christie1f141c12014-05-14 15:11:15 -07002885 for (String name : packageNames) {
2886 if (packageName.equals(name)) {
2887 return true;
2888 }
2889 }
2890 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002891 }
2892
Nick Pellye0fd6932012-07-11 10:26:13 -07002893 @Override
Mike Lockwooda4903f22010-02-17 06:42:23 -05002894 public void reportLocation(Location location, boolean passive) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002895 checkCallerIsProvider();
Mike Lockwood275555c2009-05-01 11:30:34 -04002896
Nick Pelly2eeeec22012-07-18 13:13:37 -07002897 if (!location.isComplete()) {
2898 Log.w(TAG, "Dropping incomplete location: " + location);
2899 return;
2900 }
2901
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002902 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location);
2903 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location);
Mike Lockwooda4903f22010-02-17 06:42:23 -05002904 m.arg1 = (passive ? 1 : 0);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002905 mLocationHandler.sendMessageAtFrontOfQueue(m);
2906 }
2907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002908
Laurent Tu75defb62012-11-01 16:21:52 -07002909 private static boolean shouldBroadcastSafe(
2910 Location loc, Location lastLoc, UpdateRecord record, long now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002911 // Always broadcast the first update
2912 if (lastLoc == null) {
2913 return true;
2914 }
2915
Nick Pellyf1be6862012-05-15 10:53:42 -07002916 // Check whether sufficient time has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002917 long minTime = record.mRealRequest.getFastestInterval();
David Christie1b9b7b12013-04-15 15:31:11 -07002918 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
2919 / NANOS_PER_MILLI;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002920 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002921 return false;
2922 }
2923
2924 // Check whether sufficient distance has been traveled
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002925 double minDistance = record.mRealRequest.getSmallestDisplacement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002926 if (minDistance > 0.0) {
2927 if (loc.distanceTo(lastLoc) <= minDistance) {
2928 return false;
2929 }
2930 }
2931
Laurent Tu75defb62012-11-01 16:21:52 -07002932 // Check whether sufficient number of udpates is left
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002933 if (record.mRealRequest.getNumUpdates() <= 0) {
Laurent Tu75defb62012-11-01 16:21:52 -07002934 return false;
2935 }
2936
2937 // Check whether the expiry date has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002938 return record.mRealRequest.getExpireAt() >= now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002939 }
2940
Mike Lockwooda4903f22010-02-17 06:42:23 -05002941 private void handleLocationChangedLocked(Location location, boolean passive) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002942 if (D) Log.d(TAG, "incoming location: " + location);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002943 long now = SystemClock.elapsedRealtime();
Mike Lockwooda4903f22010-02-17 06:42:23 -05002944 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
Laurent Tu60ec50a2012-10-04 17:00:10 -07002945 // Skip if the provider is unknown.
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002946 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002947 if (p == null) return;
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002948 updateLastLocationLocked(location, provider);
2949 // mLastLocation should have been updated from the updateLastLocationLocked call above.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002950 Location lastLocation = mLastLocation.get(provider);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002951 if (lastLocation == null) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002952 Log.e(TAG, "handleLocationChangedLocked() updateLastLocation failed");
2953 return;
Mike Lockwood4e50b782009-04-03 08:24:43 -07002954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002955
David Christie1b9b7b12013-04-15 15:31:11 -07002956 // Update last known coarse interval location if enough time has passed.
2957 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider);
2958 if (lastLocationCoarseInterval == null) {
2959 lastLocationCoarseInterval = new Location(location);
2960 mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval);
2961 }
2962 long timeDiffNanos = location.getElapsedRealtimeNanos()
2963 - lastLocationCoarseInterval.getElapsedRealtimeNanos();
2964 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
2965 lastLocationCoarseInterval.set(location);
2966 }
2967 // Don't ever return a coarse location that is more recent than the allowed update
2968 // interval (i.e. don't allow an app to keep registering and unregistering for
2969 // location updates to overcome the minimum interval).
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002970 Location noGPSLocation =
David Christie1b9b7b12013-04-15 15:31:11 -07002971 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2972
Laurent Tu60ec50a2012-10-04 17:00:10 -07002973 // Skip if there are no UpdateRecords for this provider.
2974 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
2975 if (records == null || records.size() == 0) return;
2976
Victoria Lease09016ab2012-09-16 12:33:15 -07002977 // Fetch coarse location
2978 Location coarseLocation = null;
David Christie1b9b7b12013-04-15 15:31:11 -07002979 if (noGPSLocation != null) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002980 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
2981 }
2982
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002983 // Fetch latest status update time
2984 long newStatusUpdateTime = p.getStatusUpdateTime();
2985
David Christie2ff96af2014-01-30 16:09:37 -08002986 // Get latest status
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002987 Bundle extras = new Bundle();
2988 int status = p.getStatus(extras);
2989
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002990 ArrayList<Receiver> deadReceivers = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002991 ArrayList<UpdateRecord> deadUpdateRecords = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07002992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002993 // Broadcast location or status to all listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002994 for (UpdateRecord r : records) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002995 Receiver receiver = r.mReceiver;
Mike Lockwood03ca2162010-04-01 08:10:09 -07002996 boolean receiverDead = false;
Nick Pelly4035f5a2012-08-17 14:43:49 -07002997
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002998 int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid);
2999 if (!isCurrentProfile(receiverUserId)
3000 && !isUidALocationProvider(receiver.mIdentity.mUid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07003001 if (D) {
Victoria Lease269518e2012-10-29 08:25:39 -07003002 Log.d(TAG, "skipping loc update for background user " + receiverUserId +
Victoria Leaseb711d572012-10-02 13:14:11 -07003003 " (current user: " + mCurrentUserId + ", app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08003004 receiver.mIdentity.mPackageName + ")");
Victoria Leaseb711d572012-10-02 13:14:11 -07003005 }
3006 continue;
3007 }
3008
Soonil Nagarkar681d7112017-02-23 17:14:16 -08003009 if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) {
gomo48f1a642017-11-10 20:35:46 -08003010 if (D) {
3011 Log.d(TAG, "skipping loc update for blacklisted app: " +
3012 receiver.mIdentity.mPackageName);
3013 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07003014 continue;
3015 }
3016
Soonil Nagarkar681d7112017-02-23 17:14:16 -08003017 if (!reportLocationAccessNoThrow(
3018 receiver.mIdentity.mPid,
3019 receiver.mIdentity.mUid,
3020 receiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08003021 receiver.mAllowedResolutionLevel)) {
gomo48f1a642017-11-10 20:35:46 -08003022 if (D) {
3023 Log.d(TAG, "skipping loc update for no op app: " +
3024 receiver.mIdentity.mPackageName);
3025 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08003026 continue;
3027 }
3028
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003029 Location notifyLocation;
Victoria Lease37425c32012-10-16 16:08:48 -07003030 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
3031 notifyLocation = coarseLocation; // use coarse location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003032 } else {
Victoria Lease37425c32012-10-16 16:08:48 -07003033 notifyLocation = lastLocation; // use fine location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003034 }
Victoria Lease09016ab2012-09-16 12:33:15 -07003035 if (notifyLocation != null) {
3036 Location lastLoc = r.mLastFixBroadcast;
Laurent Tu75defb62012-11-01 16:21:52 -07003037 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) {
Victoria Lease09016ab2012-09-16 12:33:15 -07003038 if (lastLoc == null) {
3039 lastLoc = new Location(notifyLocation);
3040 r.mLastFixBroadcast = lastLoc;
3041 } else {
3042 lastLoc.set(notifyLocation);
3043 }
3044 if (!receiver.callLocationChangedLocked(notifyLocation)) {
3045 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
3046 receiverDead = true;
3047 }
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07003048 r.mRealRequest.decrementNumUpdates();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003049 }
3050 }
3051
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003052 long prevStatusUpdateTime = r.mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003053 if ((newStatusUpdateTime > prevStatusUpdateTime) &&
Victoria Lease09016ab2012-09-16 12:33:15 -07003054 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003055
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003056 r.mLastStatusBroadcast = newStatusUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003057 if (!receiver.callStatusChangedLocked(provider, status, extras)) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07003058 receiverDead = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003059 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
Mike Lockwood03ca2162010-04-01 08:10:09 -07003060 }
3061 }
3062
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003063 // track expired records
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07003064 if (r.mRealRequest.getNumUpdates() <= 0 || r.mRealRequest.getExpireAt() < now) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003065 if (deadUpdateRecords == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003066 deadUpdateRecords = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003067 }
3068 deadUpdateRecords.add(r);
3069 }
3070 // track dead receivers
3071 if (receiverDead) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07003072 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003073 deadReceivers = new ArrayList<>();
Mike Lockwood03ca2162010-04-01 08:10:09 -07003074 }
3075 if (!deadReceivers.contains(receiver)) {
3076 deadReceivers.add(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003077 }
3078 }
3079 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003080
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003081 // remove dead records and receivers outside the loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003082 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003083 for (Receiver receiver : deadReceivers) {
3084 removeUpdatesLocked(receiver);
3085 }
3086 }
3087 if (deadUpdateRecords != null) {
3088 for (UpdateRecord r : deadUpdateRecords) {
3089 r.disposeLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003090 }
Victoria Lease8b38b292012-12-04 15:04:43 -08003091 applyRequirementsLocked(provider);
3092 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003093 }
3094
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08003095 /**
3096 * Updates last location with the given location
3097 *
3098 * @param location new location to update
3099 * @param provider Location provider to update for
3100 */
3101 private void updateLastLocationLocked(Location location, String provider) {
3102 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
3103 Location lastNoGPSLocation;
3104 Location lastLocation = mLastLocation.get(provider);
3105 if (lastLocation == null) {
3106 lastLocation = new Location(provider);
3107 mLastLocation.put(provider, lastLocation);
3108 } else {
3109 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
3110 if (noGPSLocation == null && lastNoGPSLocation != null) {
3111 // New location has no no-GPS location: adopt last no-GPS location. This is set
3112 // directly into location because we do not want to notify COARSE clients.
3113 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
3114 }
3115 }
3116 lastLocation.set(location);
3117 }
3118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003119 private class LocationWorkerHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08003120 public LocationWorkerHandler(Looper looper) {
3121 super(looper, null, true);
3122 }
3123
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003124 @Override
3125 public void handleMessage(Message msg) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003126 switch (msg.what) {
3127 case MSG_LOCATION_CHANGED:
3128 handleLocationChanged((Location) msg.obj, msg.arg1 == 1);
3129 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003130 }
3131 }
3132 }
3133
Victoria Lease54ca7ae2013-01-08 09:39:50 -08003134 private boolean isMockProvider(String provider) {
3135 synchronized (mLock) {
3136 return mMockProviders.containsKey(provider);
3137 }
3138 }
3139
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003140 private void handleLocationChanged(Location location, boolean passive) {
Victoria Lease54ca7ae2013-01-08 09:39:50 -08003141 // create a working copy of the incoming Location so that the service can modify it without
3142 // disturbing the caller's copy
3143 Location myLocation = new Location(location);
3144 String provider = myLocation.getProvider();
3145
3146 // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this
3147 // bit if location did not come from a mock provider because passive/fused providers can
3148 // forward locations from mock providers, and should not grant them legitimacy in doing so.
3149 if (!myLocation.isFromMockProvider() && isMockProvider(provider)) {
3150 myLocation.setIsFromMockProvider(true);
3151 }
Jeff Sharkey5e613312012-01-30 11:16:20 -08003152
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003153 synchronized (mLock) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08003154 if (isAllowedByCurrentUserSettingsLocked(provider)) {
3155 if (!passive) {
3156 // notify passive provider of the new location
3157 mPassiveProvider.updateLocation(myLocation);
3158 }
Victoria Lease54ca7ae2013-01-08 09:39:50 -08003159 handleLocationChangedLocked(myLocation, passive);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003160 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003161 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003162 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003163
Mike Lockwoode97ae402010-09-29 15:23:46 -04003164 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
3165 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003166 public void onPackageDisappeared(String packageName, int reason) {
3167 // remove all receivers associated with this package name
3168 synchronized (mLock) {
3169 ArrayList<Receiver> deadReceivers = null;
3170
3171 for (Receiver receiver : mReceivers.values()) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08003172 if (receiver.mIdentity.mPackageName.equals(packageName)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003173 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003174 deadReceivers = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003175 }
3176 deadReceivers.add(receiver);
3177 }
3178 }
3179
3180 // perform removal outside of mReceivers loop
3181 if (deadReceivers != null) {
3182 for (Receiver receiver : deadReceivers) {
3183 removeUpdatesLocked(receiver);
3184 }
3185 }
3186 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003187 }
Mike Lockwoode97ae402010-09-29 15:23:46 -04003188 };
3189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003190 // Geocoder
3191
Nick Pellye0fd6932012-07-11 10:26:13 -07003192 @Override
Mike Lockwoode15735a2010-09-20 17:48:47 -04003193 public boolean geocoderIsPresent() {
Mark Vandevoorde01ac80b2010-05-21 15:43:26 -07003194 return mGeocodeProvider != null;
3195 }
3196
Nick Pellye0fd6932012-07-11 10:26:13 -07003197 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003198 public String getFromLocation(double latitude, double longitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05003199 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04003200 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05003201 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
3202 params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003203 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04003204 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003205 }
3206
Mike Lockwooda55c3212009-04-15 11:10:11 -04003207
Nick Pellye0fd6932012-07-11 10:26:13 -07003208 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003209 public String getFromLocationName(String locationName,
Mike Lockwooda55c3212009-04-15 11:10:11 -04003210 double lowerLeftLatitude, double lowerLeftLongitude,
3211 double upperRightLatitude, double upperRightLongitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05003212 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04003213
3214 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05003215 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
3216 lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
3217 maxResults, params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003218 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04003219 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003220 }
3221
3222 // Mock Providers
3223
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003224 private boolean canCallerAccessMockLocation(String opPackageName) {
3225 return mAppOps.noteOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(),
3226 opPackageName) == AppOpsManager.MODE_ALLOWED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003227 }
3228
Nick Pellye0fd6932012-07-11 10:26:13 -07003229 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003230 public void addTestProvider(String name, ProviderProperties properties, String opPackageName) {
3231 if (!canCallerAccessMockLocation(opPackageName)) {
3232 return;
3233 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003234
Mike Lockwooda4903f22010-02-17 06:42:23 -05003235 if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
3236 throw new IllegalArgumentException("Cannot mock the passive location provider");
3237 }
3238
Mike Lockwood86328a92009-10-23 08:38:25 -04003239 long identity = Binder.clearCallingIdentity();
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003240 synchronized (mLock) {
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003241 // remove the real provider if we are replacing GPS or network provider
3242 if (LocationManager.GPS_PROVIDER.equals(name)
Nick Pelly1332b532012-08-21 16:25:47 -07003243 || LocationManager.NETWORK_PROVIDER.equals(name)
3244 || LocationManager.FUSED_PROVIDER.equals(name)) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05003245 LocationProviderInterface p = mProvidersByName.get(name);
3246 if (p != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003247 removeProviderLocked(p);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003248 }
3249 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09003250 addTestProviderLocked(name, properties);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003251 updateProvidersLocked();
3252 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003253 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003254 }
3255
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09003256 private void addTestProviderLocked(String name, ProviderProperties properties) {
3257 if (mProvidersByName.get(name) != null) {
3258 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
3259 }
3260 MockProvider provider = new MockProvider(name, this, properties);
3261 addProviderLocked(provider);
3262 mMockProviders.put(name, provider);
3263 mLastLocation.put(name, null);
3264 mLastLocationCoarseInterval.put(name, null);
3265 }
3266
Nick Pellye0fd6932012-07-11 10:26:13 -07003267 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003268 public void removeTestProvider(String provider, String opPackageName) {
3269 if (!canCallerAccessMockLocation(opPackageName)) {
3270 return;
3271 }
3272
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003273 synchronized (mLock) {
Tom O'Neill07ee5d12014-03-03 17:48:35 -08003274
3275 // These methods can't be called after removing the test provider, so first make sure
Tom O'Neillfe6d3c52014-03-04 08:26:17 -08003276 // we don't leave anything dangling.
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003277 clearTestProviderEnabled(provider, opPackageName);
3278 clearTestProviderLocation(provider, opPackageName);
3279 clearTestProviderStatus(provider, opPackageName);
Tom O'Neill07ee5d12014-03-03 17:48:35 -08003280
You Kima6d0b6f2012-10-28 03:58:44 +09003281 MockProvider mockProvider = mMockProviders.remove(provider);
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003282 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003283 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3284 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003285 long identity = Binder.clearCallingIdentity();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003286 removeProviderLocked(mProvidersByName.get(provider));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003287
3288 // reinstate real provider if available
3289 LocationProviderInterface realProvider = mRealProviders.get(provider);
3290 if (realProvider != null) {
3291 addProviderLocked(realProvider);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003292 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003293 mLastLocation.put(provider, null);
David Christie1b9b7b12013-04-15 15:31:11 -07003294 mLastLocationCoarseInterval.put(provider, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003295 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003296 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003297 }
3298 }
3299
Nick Pellye0fd6932012-07-11 10:26:13 -07003300 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003301 public void setTestProviderLocation(String provider, Location loc, String opPackageName) {
3302 if (!canCallerAccessMockLocation(opPackageName)) {
3303 return;
3304 }
3305
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003306 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003307 MockProvider mockProvider = mMockProviders.get(provider);
3308 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003309 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3310 }
Tom O'Neilla206a0f2016-12-15 10:26:28 -08003311
3312 // Ensure that the location is marked as being mock. There's some logic to do this in
3313 // handleLocationChanged(), but it fails if loc has the wrong provider (bug 33091107).
3314 Location mock = new Location(loc);
3315 mock.setIsFromMockProvider(true);
3316
3317 if (!TextUtils.isEmpty(loc.getProvider()) && !provider.equals(loc.getProvider())) {
3318 // The location has an explicit provider that is different from the mock provider
3319 // name. The caller may be trying to fool us via bug 33091107.
3320 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
3321 provider + "!=" + loc.getProvider());
3322 }
3323
Mike Lockwood95427cd2009-05-07 13:27:54 -04003324 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
3325 long identity = Binder.clearCallingIdentity();
Tom O'Neilla206a0f2016-12-15 10:26:28 -08003326 mockProvider.setLocation(mock);
Mike Lockwood95427cd2009-05-07 13:27:54 -04003327 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003328 }
3329 }
3330
Nick Pellye0fd6932012-07-11 10:26:13 -07003331 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003332 public void clearTestProviderLocation(String provider, String opPackageName) {
3333 if (!canCallerAccessMockLocation(opPackageName)) {
3334 return;
3335 }
3336
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003337 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003338 MockProvider mockProvider = mMockProviders.get(provider);
3339 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003340 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3341 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003342 mockProvider.clearLocation();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003343 }
3344 }
3345
Nick Pellye0fd6932012-07-11 10:26:13 -07003346 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003347 public void setTestProviderEnabled(String provider, boolean enabled, String opPackageName) {
3348 if (!canCallerAccessMockLocation(opPackageName)) {
3349 return;
3350 }
Maggie2a9409e2018-03-21 11:47:28 -07003351 setTestProviderEnabled(provider, enabled);
3352 }
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003353
Maggie2a9409e2018-03-21 11:47:28 -07003354 /** Enable or disable a test location provider. */
3355 private void setTestProviderEnabled(String provider, boolean enabled) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003356 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003357 MockProvider mockProvider = mMockProviders.get(provider);
3358 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3360 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003361 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003362 if (enabled) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003363 mockProvider.enable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003364 mEnabledProviders.add(provider);
3365 mDisabledProviders.remove(provider);
3366 } else {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003367 mockProvider.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003368 mEnabledProviders.remove(provider);
3369 mDisabledProviders.add(provider);
3370 }
3371 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003372 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003373 }
3374 }
3375
Nick Pellye0fd6932012-07-11 10:26:13 -07003376 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003377 public void clearTestProviderEnabled(String provider, String opPackageName) {
3378 if (!canCallerAccessMockLocation(opPackageName)) {
3379 return;
3380 }
3381
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003382 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003383 MockProvider mockProvider = mMockProviders.get(provider);
3384 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003385 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3386 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003387 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003388 mEnabledProviders.remove(provider);
3389 mDisabledProviders.remove(provider);
3390 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003391 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003392 }
3393 }
3394
Nick Pellye0fd6932012-07-11 10:26:13 -07003395 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003396 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime,
3397 String opPackageName) {
3398 if (!canCallerAccessMockLocation(opPackageName)) {
3399 return;
3400 }
3401
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003402 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003403 MockProvider mockProvider = mMockProviders.get(provider);
3404 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003405 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3406 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003407 mockProvider.setStatus(status, extras, updateTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003408 }
3409 }
3410
Nick Pellye0fd6932012-07-11 10:26:13 -07003411 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003412 public void clearTestProviderStatus(String provider, String opPackageName) {
3413 if (!canCallerAccessMockLocation(opPackageName)) {
3414 return;
3415 }
3416
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003417 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003418 MockProvider mockProvider = mMockProviders.get(provider);
3419 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003420 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3421 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003422 mockProvider.clearStatus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003423 }
3424 }
3425
3426 private void log(String log) {
3427 if (Log.isLoggable(TAG, Log.VERBOSE)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003428 Slog.d(TAG, log);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003429 }
3430 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003431
3432 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003433 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003434 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Nick Pellye0fd6932012-07-11 10:26:13 -07003435
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003436 synchronized (mLock) {
Siddharth Raybb608c82017-03-16 11:33:34 -07003437 if (args.length > 0 && args[0].equals("--gnssmetrics")) {
3438 if (mGnssMetricsProvider != null) {
3439 pw.append(mGnssMetricsProvider.getGnssMetricsAsProtoString());
3440 }
3441 return;
3442 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003443 pw.println("Current Location Manager state:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003444 pw.println(" Location Listeners:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003445 for (Receiver receiver : mReceivers.values()) {
3446 pw.println(" " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003447 }
David Christie2ff96af2014-01-30 16:09:37 -08003448 pw.println(" Active Records by Provider:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003449 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
3450 pw.println(" " + entry.getKey() + ":");
3451 for (UpdateRecord record : entry.getValue()) {
3452 pw.println(" " + record);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003453 }
3454 }
Wyatt Riley11cc7492018-01-17 08:48:27 -08003455 pw.println(" Active GnssMeasurement Listeners:");
3456 for (Identity identity : mGnssMeasurementsListeners.values()) {
3457 pw.println(" " + identity.mPid + " " + identity.mUid + " "
3458 + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
3459 }
3460 pw.println(" Active GnssNavigationMessage Listeners:");
3461 for (Identity identity : mGnssNavigationMessageListeners.values()) {
3462 pw.println(" " + identity.mPid + " " + identity.mUid + " "
3463 + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
3464 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003465 pw.println(" Overlay Provider Packages:");
3466 for (LocationProviderInterface provider : mProviders) {
3467 if (provider instanceof LocationProviderProxy) {
3468 pw.println(" " + provider.getName() + ": "
3469 + ((LocationProviderProxy) provider).getConnectedPackageName());
3470 }
3471 }
David Christie2ff96af2014-01-30 16:09:37 -08003472 pw.println(" Historical Records by Provider:");
3473 for (Map.Entry<PackageProviderKey, PackageStatistics> entry
3474 : mRequestStatistics.statistics.entrySet()) {
3475 PackageProviderKey key = entry.getKey();
3476 PackageStatistics stats = entry.getValue();
3477 pw.println(" " + key.packageName + ": " + key.providerName + ": " + stats);
3478 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003479 pw.println(" Last Known Locations:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003480 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
3481 String provider = entry.getKey();
3482 Location location = entry.getValue();
3483 pw.println(" " + provider + ": " + location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003484 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003485
David Christie1b9b7b12013-04-15 15:31:11 -07003486 pw.println(" Last Known Locations Coarse Intervals:");
3487 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
3488 String provider = entry.getKey();
3489 Location location = entry.getValue();
3490 pw.println(" " + provider + ": " + location);
3491 }
3492
Nick Pellye0fd6932012-07-11 10:26:13 -07003493 mGeofenceManager.dump(pw);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003495 if (mEnabledProviders.size() > 0) {
3496 pw.println(" Enabled Providers:");
3497 for (String i : mEnabledProviders) {
3498 pw.println(" " + i);
3499 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003501 }
3502 if (mDisabledProviders.size() > 0) {
3503 pw.println(" Disabled Providers:");
3504 for (String i : mDisabledProviders) {
3505 pw.println(" " + i);
3506 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003507 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07003508 pw.append(" ");
3509 mBlacklist.dump(pw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003510 if (mMockProviders.size() > 0) {
3511 pw.println(" Mock Providers:");
3512 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003513 i.getValue().dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003514 }
3515 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003516
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08003517 if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
3518 pw.println(" Throttling Whitelisted Packages:");
3519 for (String packageName : mBackgroundThrottlePackageWhitelist) {
3520 pw.println(" " + packageName);
3521 }
3522 }
3523
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003524 pw.append(" fudger: ");
gomo48f1a642017-11-10 20:35:46 -08003525 mLocationFudger.dump(fd, pw, args);
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003526
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003527 if (args.length > 0 && "short".equals(args[0])) {
3528 return;
3529 }
gomo48f1a642017-11-10 20:35:46 -08003530 for (LocationProviderInterface provider : mProviders) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003531 pw.print(provider.getName() + " Internal State");
3532 if (provider instanceof LocationProviderProxy) {
3533 LocationProviderProxy proxy = (LocationProviderProxy) provider;
3534 pw.print(" (" + proxy.getConnectedPackageName() + ")");
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003535 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003536 pw.println(":");
3537 provider.dump(fd, pw, args);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003538 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08003539 if (mGnssBatchingInProgress) {
3540 pw.println(" GNSS batching in progress");
3541 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003542 }
3543 }
3544}