blob: a6f3e39ffbcfc7717a2bc71ea8401a742e442b7c [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
Soonil Nagarkar7decfb62017-01-18 12:18:49 -080019import android.app.ActivityManager;
Wyatt Rileycf879db2017-01-12 13:57:38 -080020import android.annotation.NonNull;
Svet Ganovadc1cf42015-06-15 16:36:24 -070021import android.content.pm.PackageManagerInternal;
Soonil Nagarkar681d7112017-02-23 17:14:16 -080022import android.util.ArrayMap;
Soonil Nagarkar2b565df2017-02-14 13:33:23 -080023import android.util.ArraySet;
destradaaea8a8a62014-06-23 18:19:03 -070024import com.android.internal.content.PackageMonitor;
25import com.android.internal.location.ProviderProperties;
26import com.android.internal.location.ProviderRequest;
27import com.android.internal.os.BackgroundThread;
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -070028import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060029import com.android.internal.util.DumpUtils;
destradaaa4fa3b52014-07-09 10:46:39 -070030import com.android.server.location.ActivityRecognitionProxy;
destradaaea8a8a62014-06-23 18:19:03 -070031import com.android.server.location.FlpHardwareProvider;
32import com.android.server.location.FusedProxy;
33import com.android.server.location.GeocoderProxy;
34import com.android.server.location.GeofenceManager;
35import com.android.server.location.GeofenceProxy;
Lifu Tang818aa2c2016-02-01 01:52:00 -080036import com.android.server.location.GnssLocationProvider;
37import com.android.server.location.GnssMeasurementsProvider;
38import com.android.server.location.GnssNavigationMessageProvider;
destradaaea8a8a62014-06-23 18:19:03 -070039import com.android.server.location.LocationBlacklist;
40import com.android.server.location.LocationFudger;
41import com.android.server.location.LocationProviderInterface;
42import com.android.server.location.LocationProviderProxy;
43import com.android.server.location.LocationRequestStatistics;
44import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
45import com.android.server.location.LocationRequestStatistics.PackageStatistics;
46import com.android.server.location.MockProvider;
47import com.android.server.location.PassiveProvider;
48
Dianne Hackborna06de0f2012-12-11 16:34:47 -080049import android.app.AppOpsManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.app.PendingIntent;
Victoria Lease38389b62012-09-30 11:44:22 -070051import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.content.ContentResolver;
53import android.content.Context;
54import android.content.Intent;
Victoria Lease38389b62012-09-30 11:44:22 -070055import android.content.IntentFilter;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070056import android.content.pm.ApplicationInfo;
Jeff Hamiltonfbadb692012-10-05 14:21:58 -050057import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.content.pm.PackageManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070059import android.content.pm.PackageManager.NameNotFoundException;
Jeff Hamiltonfbadb692012-10-05 14:21:58 -050060import android.content.pm.ResolveInfo;
61import android.content.pm.Signature;
Mike Lockwood628fd6d2010-01-25 22:46:13 -050062import android.content.res.Resources;
Brian Muramatsubb95cb92012-08-29 10:43:21 -070063import android.database.ContentObserver;
destradaaa4fa3b52014-07-09 10:46:39 -070064import android.hardware.location.ActivityRecognitionHardware;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.location.Address;
Mike Lockwood03ca2162010-04-01 08:10:09 -070066import android.location.Criteria;
Mike Lockwood34901402010-01-04 12:14:21 -050067import android.location.GeocoderParams;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070068import android.location.Geofence;
Wyatt Rileycf879db2017-01-12 13:57:38 -080069import android.location.IBatchedLocationCallback;
Lifu Tang818aa2c2016-02-01 01:52:00 -080070import android.location.IGnssMeasurementsListener;
Lifu Tang30f95a72016-01-07 23:20:38 -080071import android.location.IGnssStatusListener;
72import android.location.IGnssStatusProvider;
Wei Liu5241a4c2015-05-11 14:00:36 -070073import android.location.IGpsGeofenceHardware;
Lifu Tang818aa2c2016-02-01 01:52:00 -080074import android.location.IGnssNavigationMessageListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.location.ILocationListener;
76import android.location.ILocationManager;
Danke Xie22d1f9f2009-08-18 18:28:45 -040077import android.location.INetInitiatedListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078import android.location.Location;
79import android.location.LocationManager;
80import android.location.LocationProvider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070081import android.location.LocationRequest;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.os.Binder;
83import android.os.Bundle;
84import android.os.Handler;
85import android.os.IBinder;
Mike Lockwood3d12b512009-04-21 23:25:35 -070086import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.os.Message;
88import android.os.PowerManager;
Mike Lockwoode932f7f2009-04-06 10:51:26 -070089import android.os.Process;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090import android.os.RemoteException;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070091import android.os.SystemClock;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070092import android.os.UserHandle;
Amith Yamasanib27528d2014-06-05 15:02:10 -070093import android.os.UserManager;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070094import android.os.WorkSource;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095import android.provider.Settings;
Tom O'Neilla206a0f2016-12-15 10:26:28 -080096import android.text.TextUtils;
97import android.util.EventLog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098import android.util.Log;
Joe Onorato8a9b2202010-02-26 18:56:32 -080099import android.util.Slog;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700100
Mike Lockwood43e33f22010-03-26 10:41:48 -0400101import java.io.FileDescriptor;
102import java.io.PrintWriter;
103import java.util.ArrayList;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700104import java.util.Arrays;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400105import java.util.HashMap;
106import java.util.HashSet;
107import java.util.List;
108import java.util.Map;
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800109import java.util.Map.Entry;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800110import java.util.NoSuchElementException;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400111import java.util.Set;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112
113/**
114 * The service class that manages LocationProviders and issues location
115 * updates and alerts.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116 */
Victoria Lease5cd731a2012-12-19 15:04:21 -0800117public class LocationManagerService extends ILocationManager.Stub {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 private static final String TAG = "LocationManagerService";
JP Abgrallf79811e72013-02-01 18:45:05 -0800119 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700120
121 private static final String WAKELOCK_KEY = TAG;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122
Victoria Lease37425c32012-10-16 16:08:48 -0700123 // Location resolution level: no location data whatsoever
124 private static final int RESOLUTION_LEVEL_NONE = 0;
125 // Location resolution level: coarse location data only
126 private static final int RESOLUTION_LEVEL_COARSE = 1;
127 // Location resolution level: fine location data
128 private static final int RESOLUTION_LEVEL_FINE = 2;
129
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130 private static final String ACCESS_MOCK_LOCATION =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700131 android.Manifest.permission.ACCESS_MOCK_LOCATION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700133 android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
Mike Lockwood275555c2009-05-01 11:30:34 -0400134 private static final String INSTALL_LOCATION_PROVIDER =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700135 android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
136
137 private static final String NETWORK_LOCATION_SERVICE_ACTION =
Stan Chesnutt39062dd2013-07-22 14:33:30 -0700138 "com.android.location.service.v3.NetworkLocationProvider";
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700139 private static final String FUSED_LOCATION_SERVICE_ACTION =
140 "com.android.location.service.FusedLocationProvider";
141
142 private static final int MSG_LOCATION_CHANGED = 1;
143
David Christie1b9b7b12013-04-15 15:31:11 -0700144 private static final long NANOS_PER_MILLI = 1000000L;
145
David Christie0b837452013-07-29 16:02:13 -0700146 // The maximum interval a location request can have and still be considered "high power".
147 private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
148
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800149 // default background throttling interval if not overriden in settings
Soonil Nagarkarde6780a2017-02-07 10:39:41 -0800150 private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800151
Nick Pellyf1be6862012-05-15 10:53:42 -0700152 // Location Providers may sometimes deliver location updates
153 // slightly faster that requested - provide grace period so
154 // we don't unnecessarily filter events that are otherwise on
155 // time
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700156 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
Nick Pellyf1be6862012-05-15 10:53:42 -0700157
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700158 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
159
160 private final Context mContext;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800161 private final AppOpsManager mAppOps;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700162
163 // used internally for synchronization
164 private final Object mLock = new Object();
165
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700166 // --- fields below are final after systemRunning() ---
Nick Pelly74fa7ea2012-08-13 19:36:38 -0700167 private LocationFudger mLocationFudger;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700168 private GeofenceManager mGeofenceManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700169 private PackageManager mPackageManager;
Victoria Lease0aa28602013-05-29 15:28:26 -0700170 private PowerManager mPowerManager;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800171 private ActivityManager mActivityManager;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700172 private UserManager mUserManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700173 private GeocoderProxy mGeocodeProvider;
Lifu Tang30f95a72016-01-07 23:20:38 -0800174 private IGnssStatusProvider mGnssStatusProvider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700175 private INetInitiatedListener mNetInitiatedListener;
176 private LocationWorkerHandler mLocationHandler;
Nick Pelly4035f5a2012-08-17 14:43:49 -0700177 private PassiveProvider mPassiveProvider; // track passive provider for special cases
178 private LocationBlacklist mBlacklist;
Lifu Tang818aa2c2016-02-01 01:52:00 -0800179 private GnssMeasurementsProvider mGnssMeasurementsProvider;
180 private GnssNavigationMessageProvider mGnssNavigationMessageProvider;
Wei Liu5241a4c2015-05-11 14:00:36 -0700181 private IGpsGeofenceHardware mGpsGeofenceProxy;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700182
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700183 // --- fields below are protected by mLock ---
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 // Set of providers that are explicitly enabled
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700185 // Only used by passive, fused & test. Network & GPS are controlled separately, and not listed.
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800186 private final Set<String> mEnabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187
188 // Set of providers that are explicitly disabled
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800189 private final Set<String> mDisabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700191 // Mock (test) providers
192 private final HashMap<String, MockProvider> mMockProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800193 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700195 // all receivers
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800196 private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700198 // currently installed providers (with mocks replacing real providers)
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500199 private final ArrayList<LocationProviderInterface> mProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800200 new ArrayList<>();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400201
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700202 // real providers, saved here when mocked out
203 private final HashMap<String, LocationProviderInterface> mRealProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800204 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700206 // mapping from provider name to provider
207 private final HashMap<String, LocationProviderInterface> mProvidersByName =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800208 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700210 // mapping from provider name to all its UpdateRecords
211 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800212 new HashMap<>();
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700213
David Christie2ff96af2014-01-30 16:09:37 -0800214 private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics();
215
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700216 // mapping from provider name to last known location
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800217 private final HashMap<String, Location> mLastLocation = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218
David Christie1b9b7b12013-04-15 15:31:11 -0700219 // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
220 // locations stored here are not fudged for coarse permissions.
221 private final HashMap<String, Location> mLastLocationCoarseInterval =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800222 new HashMap<>();
David Christie1b9b7b12013-04-15 15:31:11 -0700223
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800224 // all providers that operate over proxy, for authorizing incoming location and whitelisting
225 // throttling
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700226 private final ArrayList<LocationProviderProxy> mProxyProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800227 new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800229 private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800230
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800231 private final ArrayMap<IGnssMeasurementsListener, Identity> mGnssMeasurementsListeners =
232 new ArrayMap<>();
233
234 private final ArrayMap<IGnssNavigationMessageListener, Identity>
235 mGnssNavigationMessageListeners = new ArrayMap<>();
236
Victoria Lease38389b62012-09-30 11:44:22 -0700237 // current active user on the device - other users are denied location data
Xiaohui Chena4490622015-09-22 15:29:31 -0700238 private int mCurrentUserId = UserHandle.USER_SYSTEM;
239 private int[] mCurrentUserProfiles = new int[] { UserHandle.USER_SYSTEM };
Victoria Lease38389b62012-09-30 11:44:22 -0700240
Lifu Tang9363b942016-02-16 18:07:00 -0800241 private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;
Lifu Tang82f893d2016-01-21 18:15:33 -0800242
Wyatt Rileycf879db2017-01-12 13:57:38 -0800243 private GnssLocationProvider.GnssBatchingProvider mGnssBatchingProvider;
Siddharth Raybb608c82017-03-16 11:33:34 -0700244 private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800245 private IBatchedLocationCallback mGnssBatchingCallback;
246 private LinkedCallback mGnssBatchingDeathCallback;
247 private boolean mGnssBatchingInProgress = false;
248
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700249 public LocationManagerService(Context context) {
250 super();
251 mContext = context;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800252 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800253
Svet Ganovadc1cf42015-06-15 16:36:24 -0700254 // Let the package manager query which are the default location
255 // providers as they get certain permissions granted by default.
256 PackageManagerInternal packageManagerInternal = LocalServices.getService(
257 PackageManagerInternal.class);
258 packageManagerInternal.setLocationPackagesProvider(
259 new PackageManagerInternal.PackagesProvider() {
260 @Override
261 public String[] getPackages(int userId) {
262 return mContext.getResources().getStringArray(
263 com.android.internal.R.array.config_locationProviderPackageNames);
264 }
265 });
266
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700267 if (D) Log.d(TAG, "Constructed");
268
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700269 // most startup is deferred until systemRunning()
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700270 }
271
Svetoslav Ganova0027152013-06-25 14:59:53 -0700272 public void systemRunning() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700273 synchronized (mLock) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700274 if (D) Log.d(TAG, "systemRunning()");
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700275
Victoria Lease5cd731a2012-12-19 15:04:21 -0800276 // fetch package manager
277 mPackageManager = mContext.getPackageManager();
278
Victoria Lease0aa28602013-05-29 15:28:26 -0700279 // fetch power manager
280 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
Victoria Lease5cd731a2012-12-19 15:04:21 -0800281
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800282 // fetch activity manager
283 mActivityManager
284 = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
285
Victoria Lease5cd731a2012-12-19 15:04:21 -0800286 // prepare worker thread
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700287 mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper());
Victoria Lease5cd731a2012-12-19 15:04:21 -0800288
289 // prepare mLocationHandler's dependents
290 mLocationFudger = new LocationFudger(mContext, mLocationHandler);
291 mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
292 mBlacklist.init();
293 mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
294
Dianne Hackbornc2293022013-02-06 23:14:49 -0800295 // Monitor for app ops mode changes.
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700296 AppOpsManager.OnOpChangedListener callback
297 = new AppOpsManager.OnOpChangedInternalListener() {
298 public void onOpChanged(int op, String packageName) {
Dianne Hackbornc2293022013-02-06 23:14:49 -0800299 synchronized (mLock) {
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700300 for (Receiver receiver : mReceivers.values()) {
301 receiver.updateMonitoring(true);
302 }
Dianne Hackbornc2293022013-02-06 23:14:49 -0800303 applyAllProviderRequirementsLocked();
304 }
305 }
306 };
307 mAppOps.startWatchingMode(AppOpsManager.OP_COARSE_LOCATION, null, callback);
308
David Christieb870dbf2015-06-22 12:42:53 -0700309 PackageManager.OnPermissionsChangedListener permissionListener
310 = new PackageManager.OnPermissionsChangedListener() {
311 @Override
312 public void onPermissionsChanged(final int uid) {
313 synchronized (mLock) {
314 applyAllProviderRequirementsLocked();
315 }
316 }
317 };
318 mPackageManager.addOnPermissionsChangeListener(permissionListener);
319
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800320 // listen for background/foreground changes
321 ActivityManager.OnUidImportanceListener uidImportanceListener
322 = new ActivityManager.OnUidImportanceListener() {
323 @Override
324 public void onUidImportance(int uid, int importance) {
325 boolean foreground = isImportanceForeground(importance);
326 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
327 synchronized (mLock) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800328 for (Entry<String, ArrayList<UpdateRecord>> entry
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800329 : mRecordsByProvider.entrySet()) {
330 String provider = entry.getKey();
331 for (UpdateRecord record : entry.getValue()) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800332 if (record.mReceiver.mIdentity.mUid == uid
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800333 && record.mIsForegroundUid != foreground) {
334 if (D) Log.d(TAG, "request from uid " + uid + " is now "
335 + (foreground ? "foreground" : "background)"));
336 record.mIsForegroundUid = foreground;
337
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800338 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800339 affectedProviders.add(provider);
340 }
341 }
342 }
343 }
344 for (String provider : affectedProviders) {
345 applyRequirementsLocked(provider);
346 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800347
348 for (Entry<IGnssMeasurementsListener, Identity> entry
349 : mGnssMeasurementsListeners.entrySet()) {
350 if (entry.getValue().mUid == uid) {
351 if (D) Log.d(TAG, "gnss measurements listener from uid " + uid
352 + " is now " + (foreground ? "foreground" : "background)"));
353 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
354 mGnssMeasurementsProvider.addListener(entry.getKey());
355 } else {
356 mGnssMeasurementsProvider.removeListener(entry.getKey());
357 }
358 }
359 }
360
361 for (Entry<IGnssNavigationMessageListener, Identity> entry
362 : mGnssNavigationMessageListeners.entrySet()) {
363 if (entry.getValue().mUid == uid) {
364 if (D) Log.d(TAG, "gnss navigation message listener from uid "
365 + uid + " is now "
366 + (foreground ? "foreground" : "background)"));
367 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
368 mGnssNavigationMessageProvider.addListener(entry.getKey());
369 } else {
370 mGnssNavigationMessageProvider.removeListener(entry.getKey());
371 }
372 }
373 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800374 }
375
376 }
377 };
378 mActivityManager.addOnUidImportanceListener(uidImportanceListener,
379 ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE);
380
Amith Yamasanib27528d2014-06-05 15:02:10 -0700381 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
382 updateUserProfiles(mCurrentUserId);
383
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800384 updateBackgroundThrottlingWhitelistLocked();
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800385
Victoria Lease5cd731a2012-12-19 15:04:21 -0800386 // prepare providers
387 loadProvidersLocked();
388 updateProvidersLocked();
389 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700390
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700391 // listen for settings changes
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700392 mContext.getContentResolver().registerContentObserver(
Laurent Tu75defb62012-11-01 16:21:52 -0700393 Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700394 new ContentObserver(mLocationHandler) {
Victoria Lease5cd731a2012-12-19 15:04:21 -0800395 @Override
396 public void onChange(boolean selfChange) {
397 synchronized (mLock) {
398 updateProvidersLocked();
399 }
400 }
401 }, UserHandle.USER_ALL);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800402 mContext.getContentResolver().registerContentObserver(
403 Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS),
404 true,
405 new ContentObserver(mLocationHandler) {
406 @Override
407 public void onChange(boolean selfChange) {
408 synchronized (mLock) {
409 updateProvidersLocked();
410 }
411 }
412 }, UserHandle.USER_ALL);
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800413 mContext.getContentResolver().registerContentObserver(
414 Settings.Global.getUriFor(
415 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
416 true,
417 new ContentObserver(mLocationHandler) {
418 @Override
419 public void onChange(boolean selfChange) {
420 synchronized (mLock) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800421 updateBackgroundThrottlingWhitelistLocked();
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800422 updateProvidersLocked();
423 }
424 }
425 }, UserHandle.USER_ALL);
Victoria Lease5cd731a2012-12-19 15:04:21 -0800426 mPackageMonitor.register(mContext, mLocationHandler.getLooper(), true);
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700427
Victoria Lease38389b62012-09-30 11:44:22 -0700428 // listen for user change
429 IntentFilter intentFilter = new IntentFilter();
430 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700431 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
432 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
destradaab9026982015-08-27 17:34:54 -0700433 intentFilter.addAction(Intent.ACTION_SHUTDOWN);
Victoria Lease38389b62012-09-30 11:44:22 -0700434
435 mContext.registerReceiverAsUser(new BroadcastReceiver() {
436 @Override
437 public void onReceive(Context context, Intent intent) {
438 String action = intent.getAction();
439 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
440 switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
Amith Yamasanib27528d2014-06-05 15:02:10 -0700441 } else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)
442 || Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
443 updateUserProfiles(mCurrentUserId);
destradaab9026982015-08-27 17:34:54 -0700444 } else if (Intent.ACTION_SHUTDOWN.equals(action)) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700445 // shutdown only if UserId indicates whole system, not just one user
446 if(D) Log.d(TAG, "Shutdown received with UserId: " + getSendingUserId());
447 if (getSendingUserId() == UserHandle.USER_ALL) {
448 shutdownComponents();
449 }
Victoria Lease38389b62012-09-30 11:44:22 -0700450 }
451 }
Victoria Lease5cd731a2012-12-19 15:04:21 -0800452 }, UserHandle.ALL, intentFilter, null, mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700453 }
454
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800455 private static boolean isImportanceForeground(int importance) {
456 return importance <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
457 }
458
Amith Yamasanib27528d2014-06-05 15:02:10 -0700459 /**
destradaab9026982015-08-27 17:34:54 -0700460 * Provides a way for components held by the {@link LocationManagerService} to clean-up
461 * gracefully on system's shutdown.
462 *
463 * NOTES:
464 * 1) Only provides a chance to clean-up on an opt-in basis. This guarantees back-compat
465 * support for components that do not wish to handle such event.
466 */
467 private void shutdownComponents() {
468 if(D) Log.d(TAG, "Shutting down components...");
469
470 LocationProviderInterface gpsProvider = mProvidersByName.get(LocationManager.GPS_PROVIDER);
471 if (gpsProvider != null && gpsProvider.isEnabled()) {
472 gpsProvider.disable();
473 }
474
destradaa2e385072015-10-14 16:45:58 -0700475 // it is needed to check if FLP HW provider is supported before accessing the instance, this
476 // avoids an exception to be thrown by the singleton factory method
477 if (FlpHardwareProvider.isSupported()) {
478 FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
destradaab9026982015-08-27 17:34:54 -0700479 flpHardwareProvider.cleanup();
480 }
481 }
482
483 /**
Amith Yamasanib27528d2014-06-05 15:02:10 -0700484 * Makes a list of userids that are related to the current user. This is
485 * relevant when using managed profiles. Otherwise the list only contains
486 * the current user.
487 *
488 * @param currentUserId the current user, who might have an alter-ego.
489 */
490 void updateUserProfiles(int currentUserId) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700491 int[] profileIds = mUserManager.getProfileIdsWithDisabled(currentUserId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700492 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700493 mCurrentUserProfiles = profileIds;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700494 }
495 }
496
497 /**
498 * Checks if the specified userId matches any of the current foreground
499 * users stored in mCurrentUserProfiles.
500 */
501 private boolean isCurrentProfile(int userId) {
502 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700503 return ArrayUtils.contains(mCurrentUserProfiles, userId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700504 }
505 }
506
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500507 private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) {
508 PackageManager pm = mContext.getPackageManager();
509 String systemPackageName = mContext.getPackageName();
510 ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
511
512 List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
513 new Intent(FUSED_LOCATION_SERVICE_ACTION),
514 PackageManager.GET_META_DATA, mCurrentUserId);
515 for (ResolveInfo rInfo : rInfos) {
516 String packageName = rInfo.serviceInfo.packageName;
517
518 // Check that the signature is in the list of supported sigs. If it's not in
519 // this list the standard provider binding logic won't bind to it.
520 try {
521 PackageInfo pInfo;
522 pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
523 if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
524 Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
525 ", but has wrong signature, ignoring");
526 continue;
527 }
528 } catch (NameNotFoundException e) {
529 Log.e(TAG, "missing package: " + packageName);
530 continue;
531 }
532
533 // Get the version info
534 if (rInfo.serviceInfo.metaData == null) {
535 Log.w(TAG, "Found fused provider without metadata: " + packageName);
536 continue;
537 }
538
539 int version = rInfo.serviceInfo.metaData.getInt(
540 ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
541 if (version == 0) {
542 // This should be the fallback fused location provider.
543
544 // Make sure it's in the system partition.
545 if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
546 if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
547 continue;
548 }
549
550 // Check that the fallback is signed the same as the OS
551 // as a proxy for coreApp="true"
552 if (pm.checkSignatures(systemPackageName, packageName)
553 != PackageManager.SIGNATURE_MATCH) {
554 if (D) Log.d(TAG, "Fallback candidate not signed the same as system: "
555 + packageName);
556 continue;
557 }
558
559 // Found a valid fallback.
560 if (D) Log.d(TAG, "Found fallback provider: " + packageName);
561 return;
562 } else {
563 if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
564 }
565 }
566
567 throw new IllegalStateException("Unable to find a fused location provider that is in the "
568 + "system partition with version 0 and signed with the platform certificate. "
569 + "Such a package is needed to provide a default fused location provider in the "
570 + "event that no other fused location provider has been installed or is currently "
571 + "available. For example, coreOnly boot mode when decrypting the data "
572 + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
573 }
574
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700575 private void loadProvidersLocked() {
Victoria Lease5c24fd02012-10-01 11:00:50 -0700576 // create a passive location provider, which is always enabled
577 PassiveProvider passiveProvider = new PassiveProvider(this);
578 addProviderLocked(passiveProvider);
579 mEnabledProviders.add(passiveProvider.getName());
580 mPassiveProvider = passiveProvider;
581
Lifu Tang30f95a72016-01-07 23:20:38 -0800582 if (GnssLocationProvider.isSupported()) {
Wei Liu5241a4c2015-05-11 14:00:36 -0700583 // Create a gps location provider
Lifu Tang30f95a72016-01-07 23:20:38 -0800584 GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this,
Wei Liu5241a4c2015-05-11 14:00:36 -0700585 mLocationHandler.getLooper());
Lifu Tang9363b942016-02-16 18:07:00 -0800586 mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
Wyatt Rileycf879db2017-01-12 13:57:38 -0800587 mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider();
Siddharth Raybb608c82017-03-16 11:33:34 -0700588 mGnssMetricsProvider = gnssProvider.getGnssMetricsProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800589 mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
590 mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
591 addProviderLocked(gnssProvider);
592 mRealProviders.put(LocationManager.GPS_PROVIDER, gnssProvider);
Lifu Tang818aa2c2016-02-01 01:52:00 -0800593 mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
594 mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800595 mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700596 }
597
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700598 /*
599 Load package name(s) containing location provider support.
600 These packages can contain services implementing location providers:
601 Geocoder Provider, Network Location Provider, and
602 Fused Location Provider. They will each be searched for
603 service components implementing these providers.
604 The location framework also has support for installation
605 of new location providers at run-time. The new package does not
606 have to be explicitly listed here, however it must have a signature
607 that matches the signature of at least one package on this list.
608 */
609 Resources resources = mContext.getResources();
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800610 ArrayList<String> providerPackageNames = new ArrayList<>();
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500611 String[] pkgs = resources.getStringArray(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700612 com.android.internal.R.array.config_locationProviderPackageNames);
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500613 if (D) Log.d(TAG, "certificates for location providers pulled from: " +
614 Arrays.toString(pkgs));
615 if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));
616
617 ensureFallbackFusedProviderPresentLocked(providerPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700618
619 // bind to network provider
620 LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
621 mContext,
622 LocationManager.NETWORK_PROVIDER,
623 NETWORK_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700624 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
625 com.android.internal.R.string.config_networkLocationProviderPackageName,
626 com.android.internal.R.array.config_locationProviderPackageNames,
627 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700628 if (networkProvider != null) {
629 mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
630 mProxyProviders.add(networkProvider);
631 addProviderLocked(networkProvider);
632 } else {
633 Slog.w(TAG, "no network location provider found");
634 }
635
636 // bind to fused provider
637 LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind(
638 mContext,
639 LocationManager.FUSED_PROVIDER,
640 FUSED_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700641 com.android.internal.R.bool.config_enableFusedLocationOverlay,
642 com.android.internal.R.string.config_fusedLocationProviderPackageName,
643 com.android.internal.R.array.config_locationProviderPackageNames,
644 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700645 if (fusedLocationProvider != null) {
646 addProviderLocked(fusedLocationProvider);
647 mProxyProviders.add(fusedLocationProvider);
648 mEnabledProviders.add(fusedLocationProvider.getName());
Kenny Rootc3575182012-10-09 12:44:40 -0700649 mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700650 } else {
651 Slog.e(TAG, "no fused location provider found",
652 new IllegalStateException("Location service needs a fused location provider"));
653 }
654
655 // bind to geocoder provider
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700656 mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
657 com.android.internal.R.bool.config_enableGeocoderOverlay,
658 com.android.internal.R.string.config_geocoderProviderPackageName,
659 com.android.internal.R.array.config_locationProviderPackageNames,
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800660 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700661 if (mGeocodeProvider == null) {
662 Slog.e(TAG, "no geocoder provider found");
663 }
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700664
destradaaa4fa3b52014-07-09 10:46:39 -0700665 // bind to fused hardware provider if supported
destradaabeea4422014-07-30 18:17:21 -0700666 // in devices without support, requesting an instance of FlpHardwareProvider will raise an
667 // exception, so make sure we only do that when supported
668 FlpHardwareProvider flpHardwareProvider;
destradaa5ce66d82014-05-28 18:24:08 -0700669 if (FlpHardwareProvider.isSupported()) {
destradaabeea4422014-07-30 18:17:21 -0700670 flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
destradaaf9a274c2014-07-25 15:11:56 -0700671 FusedProxy fusedProxy = FusedProxy.createAndBind(
672 mContext,
673 mLocationHandler,
674 flpHardwareProvider.getLocationHardware(),
675 com.android.internal.R.bool.config_enableHardwareFlpOverlay,
676 com.android.internal.R.string.config_hardwareFlpPackageName,
677 com.android.internal.R.array.config_locationProviderPackageNames);
678 if (fusedProxy == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700679 Slog.d(TAG, "Unable to bind FusedProxy.");
destradaaf9a274c2014-07-25 15:11:56 -0700680 }
destradaacfbdcd22014-04-30 11:29:11 -0700681 } else {
destradaabeea4422014-07-30 18:17:21 -0700682 flpHardwareProvider = null;
destradaa6b4893a2016-05-03 15:33:43 -0700683 Slog.d(TAG, "FLP HAL not supported");
destradaaf9a274c2014-07-25 15:11:56 -0700684 }
685
686 // bind to geofence provider
687 GeofenceProxy provider = GeofenceProxy.createAndBind(
688 mContext,com.android.internal.R.bool.config_enableGeofenceOverlay,
689 com.android.internal.R.string.config_geofenceProviderPackageName,
690 com.android.internal.R.array.config_locationProviderPackageNames,
691 mLocationHandler,
Wei Liu5241a4c2015-05-11 14:00:36 -0700692 mGpsGeofenceProxy,
destradaabeea4422014-07-30 18:17:21 -0700693 flpHardwareProvider != null ? flpHardwareProvider.getGeofenceHardware() : null);
destradaaf9a274c2014-07-25 15:11:56 -0700694 if (provider == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700695 Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
destradaa0682809a2013-08-12 18:50:30 -0700696 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900697
destradaa6e2fe752015-06-23 17:25:53 -0700698 // bind to hardware activity recognition
699 boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
700 ActivityRecognitionHardware activityRecognitionHardware = null;
701 if (activityRecognitionHardwareIsSupported) {
702 activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
destradaaa4fa3b52014-07-09 10:46:39 -0700703 } else {
destradaa6b4893a2016-05-03 15:33:43 -0700704 Slog.d(TAG, "Hardware Activity-Recognition not supported.");
destradaaa4fa3b52014-07-09 10:46:39 -0700705 }
destradaa6e2fe752015-06-23 17:25:53 -0700706 ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
707 mContext,
708 mLocationHandler,
709 activityRecognitionHardwareIsSupported,
710 activityRecognitionHardware,
711 com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
712 com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
713 com.android.internal.R.array.config_locationProviderPackageNames);
714 if (proxy == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700715 Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
destradaa6e2fe752015-06-23 17:25:53 -0700716 }
destradaaa4fa3b52014-07-09 10:46:39 -0700717
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900718 String[] testProviderStrings = resources.getStringArray(
719 com.android.internal.R.array.config_testLocationProviders);
720 for (String testProviderString : testProviderStrings) {
721 String fragments[] = testProviderString.split(",");
722 String name = fragments[0].trim();
723 if (mProvidersByName.get(name) != null) {
724 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
725 }
726 ProviderProperties properties = new ProviderProperties(
727 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
728 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
729 Boolean.parseBoolean(fragments[3]) /* requiresCell */,
730 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
731 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
732 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
733 Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
734 Integer.parseInt(fragments[8]) /* powerRequirement */,
735 Integer.parseInt(fragments[9]) /* accuracy */);
736 addTestProviderLocked(name, properties);
737 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700738 }
Mike Lockwood9637d472009-04-02 21:41:57 -0700739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800740 /**
Victoria Lease38389b62012-09-30 11:44:22 -0700741 * Called when the device's active user changes.
742 * @param userId the new active user's UserId
743 */
744 private void switchUser(int userId) {
Jianzheng Zhoud5c69462013-10-10 14:02:09 +0800745 if (mCurrentUserId == userId) {
746 return;
747 }
Victoria Lease83762d22012-10-03 13:51:17 -0700748 mBlacklist.switchUser(userId);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800749 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED);
Victoria Lease38389b62012-09-30 11:44:22 -0700750 synchronized (mLock) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700751 mLastLocation.clear();
David Christie1b9b7b12013-04-15 15:31:11 -0700752 mLastLocationCoarseInterval.clear();
Victoria Leaseb711d572012-10-02 13:14:11 -0700753 for (LocationProviderInterface p : mProviders) {
Amith Yamasanib27528d2014-06-05 15:02:10 -0700754 updateProviderListenersLocked(p.getName(), false);
Victoria Leaseb711d572012-10-02 13:14:11 -0700755 }
Victoria Lease38389b62012-09-30 11:44:22 -0700756 mCurrentUserId = userId;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700757 updateUserProfiles(userId);
Victoria Leaseb711d572012-10-02 13:14:11 -0700758 updateProvidersLocked();
Victoria Lease38389b62012-09-30 11:44:22 -0700759 }
760 }
761
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800762 private static final class Identity {
763 final int mUid;
764 final int mPid;
765 final String mPackageName;
766
767 Identity(int uid, int pid, String packageName) {
768 mUid = uid;
769 mPid = pid;
770 mPackageName = packageName;
771 }
772 }
773
Victoria Lease38389b62012-09-30 11:44:22 -0700774 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800775 * A wrapper class holding either an ILocationListener or a PendingIntent to receive
776 * location updates.
777 */
Mike Lockwood48f17512009-04-23 09:12:08 -0700778 private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800779 final Identity mIdentity;
Victoria Lease37425c32012-10-16 16:08:48 -0700780 final int mAllowedResolutionLevel; // resolution level allowed to receiver
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 final ILocationListener mListener;
783 final PendingIntent mPendingIntent;
David Christie82edc9b2013-07-19 11:31:42 -0700784 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
David Christie40e57822013-07-30 11:36:48 -0700785 final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 final Object mKey;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700787
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800788 final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<>();
Nick Pellyf1be6862012-05-15 10:53:42 -0700789
David Christie0b837452013-07-29 16:02:13 -0700790 // True if app ops has started monitoring this receiver for locations.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700791 boolean mOpMonitoring;
David Christie0b837452013-07-29 16:02:13 -0700792 // True if app ops has started monitoring this receiver for high power (gps) locations.
793 boolean mOpHighPowerMonitoring;
Mike Lockwood48f17512009-04-23 09:12:08 -0700794 int mPendingBroadcasts;
Victoria Lease0aa28602013-05-29 15:28:26 -0700795 PowerManager.WakeLock mWakeLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700797 Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -0700798 String packageName, WorkSource workSource, boolean hideFromAppOps) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800799 mListener = listener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800800 mPendingIntent = intent;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700801 if (listener != null) {
802 mKey = listener.asBinder();
803 } else {
804 mKey = intent;
805 }
Victoria Lease37425c32012-10-16 16:08:48 -0700806 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800807 mIdentity = new Identity(uid, pid, packageName);
David Christie82edc9b2013-07-19 11:31:42 -0700808 if (workSource != null && workSource.size() <= 0) {
809 workSource = null;
810 }
811 mWorkSource = workSource;
David Christie40e57822013-07-30 11:36:48 -0700812 mHideFromAppOps = hideFromAppOps;
Victoria Lease0aa28602013-05-29 15:28:26 -0700813
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700814 updateMonitoring(true);
815
Victoria Lease0aa28602013-05-29 15:28:26 -0700816 // construct/configure wakelock
817 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
David Christie82edc9b2013-07-19 11:31:42 -0700818 if (workSource == null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800819 workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -0700820 }
821 mWakeLock.setWorkSource(workSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822 }
823
824 @Override
825 public boolean equals(Object otherObj) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800826 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800827 }
828
829 @Override
830 public int hashCode() {
831 return mKey.hashCode();
832 }
Mike Lockwood3681f262009-05-12 10:52:03 -0400833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800834 @Override
835 public String toString() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700836 StringBuilder s = new StringBuilder();
837 s.append("Reciever[");
838 s.append(Integer.toHexString(System.identityHashCode(this)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800839 if (mListener != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700840 s.append(" listener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800841 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700842 s.append(" intent");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800843 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700844 for (String p : mUpdateRecords.keySet()) {
845 s.append(" ").append(mUpdateRecords.get(p).toString());
846 }
847 s.append("]");
848 return s.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800849 }
850
David Christie15b31912013-08-13 15:54:32 -0700851 /**
852 * Update AppOp monitoring for this receiver.
853 *
854 * @param allow If true receiver is currently active, if false it's been removed.
855 */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700856 public void updateMonitoring(boolean allow) {
David Christie40e57822013-07-30 11:36:48 -0700857 if (mHideFromAppOps) {
858 return;
859 }
860
David Christie15b31912013-08-13 15:54:32 -0700861 boolean requestingLocation = false;
862 boolean requestingHighPowerLocation = false;
863 if (allow) {
864 // See if receiver has any enabled update records. Also note if any update records
865 // are high power (has a high power provider with an interval under a threshold).
866 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
867 if (isAllowedByCurrentUserSettingsLocked(updateRecord.mProvider)) {
868 requestingLocation = true;
869 LocationProviderInterface locationProvider
David Christie2ff96af2014-01-30 16:09:37 -0800870 = mProvidersByName.get(updateRecord.mProvider);
David Christie15b31912013-08-13 15:54:32 -0700871 ProviderProperties properties = locationProvider != null
872 ? locationProvider.getProperties() : null;
873 if (properties != null
874 && properties.mPowerRequirement == Criteria.POWER_HIGH
875 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
876 requestingHighPowerLocation = true;
877 break;
878 }
879 }
880 }
881 }
882
David Christie0b837452013-07-29 16:02:13 -0700883 // First update monitoring of any location request (including high power).
David Christie15b31912013-08-13 15:54:32 -0700884 mOpMonitoring = updateMonitoring(
885 requestingLocation,
886 mOpMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700887 AppOpsManager.OP_MONITOR_LOCATION);
888
889 // Now update monitoring of high power requests only.
David Christiec750c1f2013-08-08 12:56:57 -0700890 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
David Christie15b31912013-08-13 15:54:32 -0700891 mOpHighPowerMonitoring = updateMonitoring(
892 requestingHighPowerLocation,
893 mOpHighPowerMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700894 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
David Christiec750c1f2013-08-08 12:56:57 -0700895 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
David Christie15b31912013-08-13 15:54:32 -0700896 // Send an intent to notify that a high power request has been added/removed.
David Christiec750c1f2013-08-08 12:56:57 -0700897 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
898 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
899 }
David Christie0b837452013-07-29 16:02:13 -0700900 }
901
902 /**
903 * Update AppOps monitoring for a single location request and op type.
904 *
905 * @param allowMonitoring True if monitoring is allowed for this request/op.
906 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
907 * @param op AppOps code for the op to update.
908 * @return True if monitoring is on for this request/op after updating.
909 */
910 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
911 int op) {
912 if (!currentlyMonitoring) {
913 if (allowMonitoring) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800914 return mAppOps.startOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700915 == AppOpsManager.MODE_ALLOWED;
916 }
917 } else {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800918 if (!allowMonitoring
919 || mAppOps.checkOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700920 != AppOpsManager.MODE_ALLOWED) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800921 mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName);
David Christie0b837452013-07-29 16:02:13 -0700922 return false;
923 }
924 }
925
926 return currentlyMonitoring;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700927 }
928
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800929 public boolean isListener() {
930 return mListener != null;
931 }
932
933 public boolean isPendingIntent() {
934 return mPendingIntent != null;
935 }
936
937 public ILocationListener getListener() {
938 if (mListener != null) {
939 return mListener;
940 }
941 throw new IllegalStateException("Request for non-existent listener");
942 }
943
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
945 if (mListener != null) {
946 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700947 synchronized (this) {
948 // synchronize to ensure incrementPendingBroadcastsLocked()
949 // is called before decrementPendingBroadcasts()
950 mListener.onStatusChanged(provider, status, extras);
Nick Pellye0fd6932012-07-11 10:26:13 -0700951 // call this after broadcasting so we do not increment
952 // if we throw an exeption.
953 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -0700954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800955 } catch (RemoteException e) {
956 return false;
957 }
958 } else {
959 Intent statusChanged = new Intent();
Victoria Lease61ecb022012-11-13 15:12:51 -0800960 statusChanged.putExtras(new Bundle(extras));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
962 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700963 synchronized (this) {
964 // synchronize to ensure incrementPendingBroadcastsLocked()
965 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700966 mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -0700967 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -0700968 // call this after broadcasting so we do not increment
969 // if we throw an exeption.
970 incrementPendingBroadcastsLocked();
971 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972 } catch (PendingIntent.CanceledException e) {
973 return false;
974 }
975 }
976 return true;
977 }
978
979 public boolean callLocationChangedLocked(Location location) {
980 if (mListener != null) {
981 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700982 synchronized (this) {
983 // synchronize to ensure incrementPendingBroadcastsLocked()
984 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c5406a2012-11-29 16:18:01 -0800985 mListener.onLocationChanged(new Location(location));
Nick Pellye0fd6932012-07-11 10:26:13 -0700986 // call this after broadcasting so we do not increment
987 // if we throw an exeption.
988 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -0700989 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800990 } catch (RemoteException e) {
991 return false;
992 }
993 } else {
994 Intent locationChanged = new Intent();
Victoria Lease61ecb022012-11-13 15:12:51 -0800995 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, new Location(location));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800996 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700997 synchronized (this) {
998 // synchronize to ensure incrementPendingBroadcastsLocked()
999 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001000 mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -07001001 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -07001002 // call this after broadcasting so we do not increment
1003 // if we throw an exeption.
1004 incrementPendingBroadcastsLocked();
1005 }
1006 } catch (PendingIntent.CanceledException e) {
1007 return false;
1008 }
1009 }
1010 return true;
1011 }
1012
1013 public boolean callProviderEnabledLocked(String provider, boolean enabled) {
David Christie15b31912013-08-13 15:54:32 -07001014 // First update AppOp monitoring.
1015 // An app may get/lose location access as providers are enabled/disabled.
1016 updateMonitoring(true);
1017
Mike Lockwood48f17512009-04-23 09:12:08 -07001018 if (mListener != null) {
1019 try {
1020 synchronized (this) {
1021 // synchronize to ensure incrementPendingBroadcastsLocked()
1022 // is called before decrementPendingBroadcasts()
1023 if (enabled) {
1024 mListener.onProviderEnabled(provider);
1025 } else {
1026 mListener.onProviderDisabled(provider);
1027 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001028 // call this after broadcasting so we do not increment
1029 // if we throw an exeption.
1030 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001031 }
1032 } catch (RemoteException e) {
1033 return false;
1034 }
1035 } else {
1036 Intent providerIntent = new Intent();
1037 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1038 try {
1039 synchronized (this) {
1040 // synchronize to ensure incrementPendingBroadcastsLocked()
1041 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001042 mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -07001043 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -07001044 // call this after broadcasting so we do not increment
1045 // if we throw an exeption.
1046 incrementPendingBroadcastsLocked();
1047 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001048 } catch (PendingIntent.CanceledException e) {
1049 return false;
1050 }
1051 }
1052 return true;
1053 }
1054
Nick Pellyf1be6862012-05-15 10:53:42 -07001055 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001056 public void binderDied() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001057 if (D) Log.d(TAG, "Location listener died");
1058
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001059 synchronized (mLock) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001060 removeUpdatesLocked(this);
1061 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001062 synchronized (this) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001063 clearPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001064 }
1065 }
1066
Nick Pellye0fd6932012-07-11 10:26:13 -07001067 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001068 public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1069 int resultCode, String resultData, Bundle resultExtras) {
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001070 synchronized (this) {
1071 decrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001072 }
1073 }
1074
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001075 // this must be called while synchronized by caller in a synchronized block
1076 // containing the sending of the broadcaset
1077 private void incrementPendingBroadcastsLocked() {
1078 if (mPendingBroadcasts++ == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001079 mWakeLock.acquire();
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001080 }
1081 }
1082
1083 private void decrementPendingBroadcastsLocked() {
1084 if (--mPendingBroadcasts == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001085 if (mWakeLock.isHeld()) {
1086 mWakeLock.release();
1087 }
1088 }
1089 }
1090
1091 public void clearPendingBroadcastsLocked() {
1092 if (mPendingBroadcasts > 0) {
1093 mPendingBroadcasts = 0;
1094 if (mWakeLock.isHeld()) {
1095 mWakeLock.release();
1096 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001097 }
1098 }
1099 }
1100
Nick Pellye0fd6932012-07-11 10:26:13 -07001101 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001102 public void locationCallbackFinished(ILocationListener listener) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001103 //Do not use getReceiverLocked here as that will add the ILocationListener to
Joshua Bartel080b61b2009-10-05 12:44:46 -04001104 //the receiver list if it is not found. If it is not found then the
1105 //LocationListener was removed when it had a pending broadcast and should
1106 //not be added back.
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001107 synchronized (mLock) {
1108 IBinder binder = listener.asBinder();
1109 Receiver receiver = mReceivers.get(binder);
1110 if (receiver != null) {
1111 synchronized (receiver) {
1112 // so wakelock calls will succeed
1113 long identity = Binder.clearCallingIdentity();
1114 receiver.decrementPendingBroadcastsLocked();
1115 Binder.restoreCallingIdentity(identity);
David Christie2ff96af2014-01-30 16:09:37 -08001116 }
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001117 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001118 }
1119 }
1120
Lifu Tang82f893d2016-01-21 18:15:33 -08001121 /**
Lifu Tang9363b942016-02-16 18:07:00 -08001122 * Returns the system information of the GNSS hardware.
Lifu Tang82f893d2016-01-21 18:15:33 -08001123 */
1124 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001125 public int getGnssYearOfHardware() {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001126 if (mGnssSystemInfoProvider != null) {
Lifu Tang9363b942016-02-16 18:07:00 -08001127 return mGnssSystemInfoProvider.getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001128 } else {
1129 return 0;
1130 }
1131 }
1132
Wyatt Rileycf879db2017-01-12 13:57:38 -08001133 /**
1134 * Runs some checks for GNSS (FINE) level permissions, used by several methods which directly
1135 * (try to) access GNSS information at this layer.
1136 */
1137 private boolean hasGnssPermissions(String packageName) {
1138 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
1139 checkResolutionLevelIsSufficientForProviderUse(
1140 allowedResolutionLevel,
1141 LocationManager.GPS_PROVIDER);
1142
1143 int pid = Binder.getCallingPid();
1144 int uid = Binder.getCallingUid();
1145 long identity = Binder.clearCallingIdentity();
1146 boolean hasLocationAccess;
1147 try {
1148 hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
1149 } finally {
1150 Binder.restoreCallingIdentity(identity);
1151 }
1152
1153 return hasLocationAccess;
1154 }
1155
1156 /**
1157 * Returns the GNSS batching size, if available.
1158 */
1159 @Override
1160 public int getGnssBatchSize(String packageName) {
1161 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1162 "Location Hardware permission not granted to access hardware batching");
1163
1164 if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
1165 return mGnssBatchingProvider.getSize();
1166 } else {
1167 return 0;
1168 }
1169 }
1170
1171 /**
1172 * Adds a callback for GNSS Batching events, if permissions allow, which are transported
1173 * to potentially multiple listeners by the BatchedLocationCallbackTransport above this.
1174 */
1175 @Override
1176 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) {
1177 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1178 "Location Hardware permission not granted to access hardware batching");
1179
1180 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1181 return false;
1182 }
1183
1184 mGnssBatchingCallback = callback;
1185 mGnssBatchingDeathCallback = new LinkedCallback(callback);
1186 try {
1187 callback.asBinder().linkToDeath(mGnssBatchingDeathCallback, 0 /* flags */);
1188 } catch (RemoteException e) {
1189 // if the remote process registering the listener is already dead, just swallow the
1190 // exception and return
1191 Log.e(TAG, "Remote listener already died.", e);
1192 return false;
1193 }
1194
1195 return true;
1196 }
1197
1198 private class LinkedCallback implements IBinder.DeathRecipient {
1199 private final IBatchedLocationCallback mCallback;
1200
1201 public LinkedCallback(@NonNull IBatchedLocationCallback callback) {
1202 mCallback = callback;
1203 }
1204
1205 @NonNull
1206 public IBatchedLocationCallback getUnderlyingListener() {
1207 return mCallback;
1208 }
1209
1210 @Override
1211 public void binderDied() {
1212 Log.d(TAG, "Remote Batching Callback died: " + mCallback);
1213 stopGnssBatch();
1214 removeGnssBatchingCallback();
1215 }
1216 }
1217
1218 /**
1219 * Removes callback for GNSS batching
1220 */
1221 @Override
1222 public void removeGnssBatchingCallback() {
1223 try {
1224 mGnssBatchingCallback.asBinder().unlinkToDeath(mGnssBatchingDeathCallback,
1225 0 /* flags */);
1226 } catch (NoSuchElementException e) {
1227 // if the death callback isn't connected (it should be...), log error, swallow the
1228 // exception and return
1229 Log.e(TAG, "Couldn't unlink death callback.", e);
1230 }
1231 mGnssBatchingCallback = null;
1232 mGnssBatchingDeathCallback = null;
1233 }
1234
1235
1236 /**
1237 * Starts GNSS batching, if available.
1238 */
1239 @Override
1240 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
1241 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1242 "Location Hardware permission not granted to access hardware batching");
1243
1244 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1245 return false;
1246 }
1247
1248 if (mGnssBatchingInProgress) {
1249 // Current design does not expect multiple starts to be called repeatedly
1250 Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch");
1251 // Try to clean up anyway, and continue
1252 stopGnssBatch();
1253 }
1254
1255 mGnssBatchingInProgress = true;
1256 return mGnssBatchingProvider.start(periodNanos, wakeOnFifoFull);
1257 }
1258
1259 /**
1260 * Flushes a GNSS batch in progress
1261 */
1262 @Override
1263 public void flushGnssBatch(String packageName) {
1264 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1265 "Location Hardware permission not granted to access hardware batching");
1266
1267 if (!hasGnssPermissions(packageName)) {
1268 Log.e(TAG, "flushGnssBatch called without GNSS permissions");
1269 return;
1270 }
1271
1272 if (!mGnssBatchingInProgress) {
1273 Log.w(TAG, "flushGnssBatch called with no batch in progress");
1274 }
1275
1276 if (mGnssBatchingProvider != null) {
1277 mGnssBatchingProvider.flush();
1278 }
1279 }
1280
1281 /**
1282 * Stops GNSS batching
1283 */
1284 @Override
1285 public boolean stopGnssBatch() {
1286 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1287 "Location Hardware permission not granted to access hardware batching");
1288
1289 if (mGnssBatchingProvider != null) {
1290 mGnssBatchingInProgress = false;
1291 return mGnssBatchingProvider.stop();
1292 } else {
1293 return false;
1294 }
1295 }
1296
1297 @Override
1298 public void reportLocationBatch(List<Location> locations) {
1299 checkCallerIsProvider();
1300
1301 // Currently used only for GNSS locations - update permissions check if changed
1302 if (isAllowedByCurrentUserSettingsLocked(LocationManager.GPS_PROVIDER)) {
1303 if (mGnssBatchingCallback == null) {
1304 Slog.e(TAG, "reportLocationBatch() called without active Callback");
1305 return;
1306 }
1307 try {
1308 mGnssBatchingCallback.onLocationBatch(locations);
1309 } catch (RemoteException e) {
1310 Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e);
1311 }
1312 } else {
1313 Slog.w(TAG, "reportLocationBatch() called without user permission, locations blocked");
1314 }
1315 }
1316
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001317 private void addProviderLocked(LocationProviderInterface provider) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001318 mProviders.add(provider);
1319 mProvidersByName.put(provider.getName(), provider);
1320 }
1321
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001322 private void removeProviderLocked(LocationProviderInterface provider) {
1323 provider.disable();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001324 mProviders.remove(provider);
1325 mProvidersByName.remove(provider.getName());
1326 }
1327
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001328 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001329 * Returns "true" if access to the specified location provider is allowed by the current
1330 * user's settings. Access to all location providers is forbidden to non-location-provider
1331 * processes belonging to background users.
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001332 *
1333 * @param provider the name of the location provider
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001334 */
Victoria Lease09eeaec2013-02-05 11:34:13 -08001335 private boolean isAllowedByCurrentUserSettingsLocked(String provider) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001336 if (mEnabledProviders.contains(provider)) {
1337 return true;
1338 }
1339 if (mDisabledProviders.contains(provider)) {
1340 return false;
1341 }
1342 // Use system settings
1343 ContentResolver resolver = mContext.getContentResolver();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001344
Victoria Leaseb711d572012-10-02 13:14:11 -07001345 return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001346 }
1347
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001348 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001349 * Returns "true" if access to the specified location provider is allowed by the specified
1350 * user's settings. Access to all location providers is forbidden to non-location-provider
1351 * processes belonging to background users.
1352 *
1353 * @param provider the name of the location provider
1354 * @param uid the requestor's UID
Victoria Lease09eeaec2013-02-05 11:34:13 -08001355 */
1356 private boolean isAllowedByUserSettingsLocked(String provider, int uid) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001357 if (!isCurrentProfile(UserHandle.getUserId(uid)) && !isUidALocationProvider(uid)) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08001358 return false;
1359 }
1360 return isAllowedByCurrentUserSettingsLocked(provider);
1361 }
1362
1363 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001364 * Returns the permission string associated with the specified resolution level.
1365 *
1366 * @param resolutionLevel the resolution level
1367 * @return the permission string
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001368 */
Victoria Lease37425c32012-10-16 16:08:48 -07001369 private String getResolutionPermission(int resolutionLevel) {
1370 switch (resolutionLevel) {
1371 case RESOLUTION_LEVEL_FINE:
1372 return android.Manifest.permission.ACCESS_FINE_LOCATION;
1373 case RESOLUTION_LEVEL_COARSE:
1374 return android.Manifest.permission.ACCESS_COARSE_LOCATION;
1375 default:
1376 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001377 }
Victoria Leaseda479c52012-10-15 15:24:16 -07001378 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001379
Victoria Leaseda479c52012-10-15 15:24:16 -07001380 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001381 * Returns the resolution level allowed to the given PID/UID pair.
1382 *
1383 * @param pid the PID
1384 * @param uid the UID
1385 * @return resolution level allowed to the pid/uid pair
Victoria Leaseda479c52012-10-15 15:24:16 -07001386 */
Victoria Lease37425c32012-10-16 16:08:48 -07001387 private int getAllowedResolutionLevel(int pid, int uid) {
1388 if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
1389 pid, uid) == PackageManager.PERMISSION_GRANTED) {
1390 return RESOLUTION_LEVEL_FINE;
1391 } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
1392 pid, uid) == PackageManager.PERMISSION_GRANTED) {
1393 return RESOLUTION_LEVEL_COARSE;
1394 } else {
1395 return RESOLUTION_LEVEL_NONE;
Victoria Leaseda479c52012-10-15 15:24:16 -07001396 }
Victoria Lease4fab68b2012-09-13 13:20:59 -07001397 }
1398
1399 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001400 * Returns the resolution level allowed to the caller
1401 *
1402 * @return resolution level allowed to caller
Victoria Lease4fab68b2012-09-13 13:20:59 -07001403 */
Victoria Lease37425c32012-10-16 16:08:48 -07001404 private int getCallerAllowedResolutionLevel() {
1405 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
1406 }
1407
1408 /**
1409 * Throw SecurityException if specified resolution level is insufficient to use geofences.
1410 *
1411 * @param allowedResolutionLevel resolution level allowed to caller
1412 */
1413 private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
1414 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Lease4fab68b2012-09-13 13:20:59 -07001415 throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
1416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001417 }
1418
Victoria Lease37425c32012-10-16 16:08:48 -07001419 /**
1420 * Return the minimum resolution level required to use the specified location provider.
1421 *
1422 * @param provider the name of the location provider
1423 * @return minimum resolution level required for provider
1424 */
1425 private int getMinimumResolutionLevelForProviderUse(String provider) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001426 if (LocationManager.GPS_PROVIDER.equals(provider) ||
1427 LocationManager.PASSIVE_PROVIDER.equals(provider)) {
1428 // gps and passive providers require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001429 return RESOLUTION_LEVEL_FINE;
Victoria Lease8dbb6342012-09-21 16:55:53 -07001430 } else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
1431 LocationManager.FUSED_PROVIDER.equals(provider)) {
1432 // network and fused providers are ok with COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001433 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001434 } else {
1435 // mock providers
1436 LocationProviderInterface lp = mMockProviders.get(provider);
1437 if (lp != null) {
1438 ProviderProperties properties = lp.getProperties();
1439 if (properties != null) {
1440 if (properties.mRequiresSatellite) {
1441 // provider requiring satellites require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001442 return RESOLUTION_LEVEL_FINE;
Laurent Tu941221c2012-10-04 14:21:52 -07001443 } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
1444 // provider requiring network and or cell require COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001445 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001446 }
1447 }
1448 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001449 }
Victoria Lease37425c32012-10-16 16:08:48 -07001450 return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
Victoria Leaseda479c52012-10-15 15:24:16 -07001451 }
1452
Victoria Lease37425c32012-10-16 16:08:48 -07001453 /**
1454 * Throw SecurityException if specified resolution level is insufficient to use the named
1455 * location provider.
1456 *
1457 * @param allowedResolutionLevel resolution level allowed to caller
1458 * @param providerName the name of the location provider
1459 */
1460 private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel,
1461 String providerName) {
1462 int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName);
1463 if (allowedResolutionLevel < requiredResolutionLevel) {
1464 switch (requiredResolutionLevel) {
1465 case RESOLUTION_LEVEL_FINE:
1466 throw new SecurityException("\"" + providerName + "\" location provider " +
1467 "requires ACCESS_FINE_LOCATION permission.");
1468 case RESOLUTION_LEVEL_COARSE:
1469 throw new SecurityException("\"" + providerName + "\" location provider " +
1470 "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
1471 default:
1472 throw new SecurityException("Insufficient permission for \"" + providerName +
1473 "\" location provider.");
Victoria Leaseda479c52012-10-15 15:24:16 -07001474 }
1475 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001476 }
1477
David Christie82edc9b2013-07-19 11:31:42 -07001478 /**
1479 * Throw SecurityException if WorkSource use is not allowed (i.e. can't blame other packages
1480 * for battery).
1481 */
David Christie40e57822013-07-30 11:36:48 -07001482 private void checkDeviceStatsAllowed() {
David Christie82edc9b2013-07-19 11:31:42 -07001483 mContext.enforceCallingOrSelfPermission(
1484 android.Manifest.permission.UPDATE_DEVICE_STATS, null);
1485 }
1486
David Christie40e57822013-07-30 11:36:48 -07001487 private void checkUpdateAppOpsAllowed() {
1488 mContext.enforceCallingOrSelfPermission(
1489 android.Manifest.permission.UPDATE_APP_OPS_STATS, null);
1490 }
1491
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001492 public static int resolutionLevelToOp(int allowedResolutionLevel) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001493 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
1494 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001495 return AppOpsManager.OP_COARSE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001496 } else {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001497 return AppOpsManager.OP_FINE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001498 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001499 }
1500 return -1;
1501 }
1502
David Christieb870dbf2015-06-22 12:42:53 -07001503 boolean reportLocationAccessNoThrow(
1504 int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001505 int op = resolutionLevelToOp(allowedResolutionLevel);
1506 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001507 if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1508 return false;
1509 }
1510 }
David Christieb870dbf2015-06-22 12:42:53 -07001511
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001512 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001513 }
1514
David Christieb870dbf2015-06-22 12:42:53 -07001515 boolean checkLocationAccess(int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001516 int op = resolutionLevelToOp(allowedResolutionLevel);
1517 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001518 if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1519 return false;
1520 }
1521 }
David Christieb870dbf2015-06-22 12:42:53 -07001522
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001523 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001524 }
1525
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001526 /**
1527 * Returns all providers by name, including passive, but excluding
Laurent Tu0d21e212012-10-02 15:33:48 -07001528 * fused, also including ones that are not permitted to
1529 * be accessed by the calling activity or are currently disabled.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001530 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001531 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 public List<String> getAllProviders() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001533 ArrayList<String> out;
1534 synchronized (mLock) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001535 out = new ArrayList<>(mProviders.size());
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001536 for (LocationProviderInterface provider : mProviders) {
1537 String name = provider.getName();
1538 if (LocationManager.FUSED_PROVIDER.equals(name)) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07001539 continue;
1540 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001541 out.add(name);
1542 }
1543 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001544
1545 if (D) Log.d(TAG, "getAllProviders()=" + out);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001546 return out;
1547 }
1548
Mike Lockwood03ca2162010-04-01 08:10:09 -07001549 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001550 * Return all providers by name, that match criteria and are optionally
1551 * enabled.
1552 * Can return passive provider, but never returns fused provider.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001553 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001554 @Override
1555 public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
Victoria Lease37425c32012-10-16 16:08:48 -07001556 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001557 ArrayList<String> out;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001558 int uid = Binder.getCallingUid();
Victoria Lease269518e2012-10-29 08:25:39 -07001559 long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07001560 try {
1561 synchronized (mLock) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001562 out = new ArrayList<>(mProviders.size());
Victoria Leaseb711d572012-10-02 13:14:11 -07001563 for (LocationProviderInterface provider : mProviders) {
1564 String name = provider.getName();
1565 if (LocationManager.FUSED_PROVIDER.equals(name)) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001566 continue;
1567 }
Victoria Lease37425c32012-10-16 16:08:48 -07001568 if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08001569 if (enabledOnly && !isAllowedByUserSettingsLocked(name, uid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001570 continue;
1571 }
1572 if (criteria != null && !LocationProvider.propertiesMeetCriteria(
1573 name, provider.getProperties(), criteria)) {
1574 continue;
1575 }
1576 out.add(name);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001577 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001578 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001579 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001580 } finally {
1581 Binder.restoreCallingIdentity(identity);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001582 }
1583
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001584 if (D) Log.d(TAG, "getProviders()=" + out);
1585 return out;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001586 }
1587
1588 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001589 * Return the name of the best provider given a Criteria object.
1590 * This method has been deprecated from the public API,
Victoria Lease8dbb6342012-09-21 16:55:53 -07001591 * and the whole LocationProvider (including #meetsCriteria)
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001592 * has been deprecated as well. So this method now uses
1593 * some simplified logic.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001594 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001595 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001596 public String getBestProvider(Criteria criteria, boolean enabledOnly) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001597 String result = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001598
1599 List<String> providers = getProviders(criteria, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001600 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001601 result = pickBest(providers);
1602 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1603 return result;
1604 }
1605 providers = getProviders(null, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001606 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001607 result = pickBest(providers);
1608 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1609 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001610 }
1611
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001612 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001613 return null;
1614 }
1615
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001616 private String pickBest(List<String> providers) {
Victoria Lease1925e292012-09-24 17:00:18 -07001617 if (providers.contains(LocationManager.GPS_PROVIDER)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001618 return LocationManager.GPS_PROVIDER;
Victoria Lease1925e292012-09-24 17:00:18 -07001619 } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
1620 return LocationManager.NETWORK_PROVIDER;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001621 } else {
1622 return providers.get(0);
1623 }
1624 }
1625
Nick Pellye0fd6932012-07-11 10:26:13 -07001626 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001627 public boolean providerMeetsCriteria(String provider, Criteria criteria) {
1628 LocationProviderInterface p = mProvidersByName.get(provider);
1629 if (p == null) {
1630 throw new IllegalArgumentException("provider=" + provider);
1631 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001632
1633 boolean result = LocationProvider.propertiesMeetCriteria(
1634 p.getName(), p.getProperties(), criteria);
1635 if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result);
1636 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001637 }
1638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001639 private void updateProvidersLocked() {
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001640 boolean changesMade = false;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001641 for (int i = mProviders.size() - 1; i >= 0; i--) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001642 LocationProviderInterface p = mProviders.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 boolean isEnabled = p.isEnabled();
1644 String name = p.getName();
Victoria Lease09eeaec2013-02-05 11:34:13 -08001645 boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 if (isEnabled && !shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001647 updateProviderListenersLocked(name, false);
David Christieb084fef2013-12-18 14:33:57 -08001648 // If any provider has been disabled, clear all last locations for all providers.
1649 // This is to be on the safe side in case a provider has location derived from
1650 // this disabled provider.
1651 mLastLocation.clear();
1652 mLastLocationCoarseInterval.clear();
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001653 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001654 } else if (!isEnabled && shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001655 updateProviderListenersLocked(name, true);
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001656 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001657 }
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001658 }
1659 if (changesMade) {
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001660 mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
1661 UserHandle.ALL);
Tom O'Neill40a86c22013-09-03 18:05:13 -07001662 mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
1663 UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001664 }
1665 }
1666
Amith Yamasanib27528d2014-06-05 15:02:10 -07001667 private void updateProviderListenersLocked(String provider, boolean enabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668 int listeners = 0;
1669
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001670 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001671 if (p == null) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001672
1673 ArrayList<Receiver> deadReceivers = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07001674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1676 if (records != null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001677 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001678 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001679 // Sends a notification message to the receiver
1680 if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
1681 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001682 deadReceivers = new ArrayList<>();
Victoria Leaseb711d572012-10-02 13:14:11 -07001683 }
1684 deadReceivers.add(record.mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001686 listeners++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001688 }
1689 }
1690
1691 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001692 for (int i = deadReceivers.size() - 1; i >= 0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 removeUpdatesLocked(deadReceivers.get(i));
1694 }
1695 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001697 if (enabled) {
1698 p.enable();
1699 if (listeners > 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001700 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 }
1702 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001703 p.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001705 }
1706
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001707 private void applyRequirementsLocked(String provider) {
1708 LocationProviderInterface p = mProvidersByName.get(provider);
1709 if (p == null) return;
1710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001711 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001712 WorkSource worksource = new WorkSource();
1713 ProviderRequest providerRequest = new ProviderRequest();
1714
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001715 ContentResolver resolver = mContext.getContentResolver();
1716 long backgroundThrottleInterval = Settings.Global.getLong(
1717 resolver,
1718 Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
1719 DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
1720
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001721 if (records != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001722 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001723 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
David Christieb870dbf2015-06-22 12:42:53 -07001724 if (checkLocationAccess(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001725 record.mReceiver.mIdentity.mPid,
1726 record.mReceiver.mIdentity.mUid,
1727 record.mReceiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001728 record.mReceiver.mAllowedResolutionLevel)) {
1729 LocationRequest locationRequest = record.mRequest;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001730 long interval = locationRequest.getInterval();
1731
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001732 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001733 if (!record.mIsForegroundUid) {
1734 interval = Math.max(interval, backgroundThrottleInterval);
1735 }
1736 if (interval != locationRequest.getInterval()) {
1737 locationRequest = new LocationRequest(locationRequest);
1738 locationRequest.setInterval(interval);
1739 }
1740 }
1741
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001742 providerRequest.locationRequests.add(locationRequest);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001743 if (interval < providerRequest.interval) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001744 providerRequest.reportLocation = true;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001745 providerRequest.interval = interval;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001746 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001747 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001748 }
1749 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001750
1751 if (providerRequest.reportLocation) {
1752 // calculate who to blame for power
1753 // This is somewhat arbitrary. We pick a threshold interval
1754 // that is slightly higher that the minimum interval, and
1755 // spread the blame across all applications with a request
1756 // under that threshold.
1757 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
1758 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001759 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001760 LocationRequest locationRequest = record.mRequest;
Svet Ganove998c732016-06-10 00:12:38 -07001761
1762 // Don't assign battery blame for update records whose
1763 // client has no permission to receive location data.
1764 if (!providerRequest.locationRequests.contains(locationRequest)) {
1765 continue;
1766 }
1767
Victoria Leaseb711d572012-10-02 13:14:11 -07001768 if (locationRequest.getInterval() <= thresholdInterval) {
David Christiee55c9682013-08-22 10:10:34 -07001769 if (record.mReceiver.mWorkSource != null
1770 && record.mReceiver.mWorkSource.size() > 0
1771 && record.mReceiver.mWorkSource.getName(0) != null) {
David Christie82edc9b2013-07-19 11:31:42 -07001772 // Assign blame to another work source.
David Christiee55c9682013-08-22 10:10:34 -07001773 // Can only assign blame if the WorkSource contains names.
David Christie82edc9b2013-07-19 11:31:42 -07001774 worksource.add(record.mReceiver.mWorkSource);
1775 } else {
1776 // Assign blame to caller.
1777 worksource.add(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001778 record.mReceiver.mIdentity.mUid,
1779 record.mReceiver.mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001780 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001781 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001782 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001783 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 }
1785 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001786
1787 if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
1788 p.setRequest(providerRequest, worksource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001789 }
1790
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001791 @Override
1792 public String[] getBackgroundThrottlingWhitelist() {
1793 synchronized (mLock) {
1794 return mBackgroundThrottlePackageWhitelist.toArray(
1795 new String[mBackgroundThrottlePackageWhitelist.size()]);
1796 }
1797 }
1798
1799 private void updateBackgroundThrottlingWhitelistLocked() {
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001800 String setting = Settings.Global.getString(
1801 mContext.getContentResolver(),
1802 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
1803 if (setting == null) {
1804 setting = "";
1805 }
1806
1807 mBackgroundThrottlePackageWhitelist.clear();
1808 mBackgroundThrottlePackageWhitelist.addAll(
1809 SystemConfig.getInstance().getAllowUnthrottledLocation());
1810 mBackgroundThrottlePackageWhitelist.addAll(
1811 Arrays.asList(setting.split(",")));
1812 }
1813
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001814 private boolean isThrottlingExemptLocked(Identity identity) {
1815 if (identity.mUid == Process.SYSTEM_UID) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001816 return true;
1817 }
1818
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001819 if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001820 return true;
1821 }
1822
1823 for (LocationProviderProxy provider : mProxyProviders) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001824 if (identity.mPackageName.equals(provider.getConnectedPackageName())) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001825 return true;
1826 }
1827 }
1828
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001829 return false;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001830 }
1831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832 private class UpdateRecord {
1833 final String mProvider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001834 final LocationRequest mRequest;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001835 final Receiver mReceiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001836 boolean mIsForegroundUid;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001837 Location mLastFixBroadcast;
1838 long mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839
1840 /**
1841 * Note: must be constructed with lock held.
1842 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001843 UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844 mProvider = provider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001845 mRequest = request;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001846 mReceiver = receiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001847 mIsForegroundUid = isImportanceForeground(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001848 mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001849
1850 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1851 if (records == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001852 records = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 mRecordsByProvider.put(provider, records);
1854 }
1855 if (!records.contains(this)) {
1856 records.add(this);
1857 }
David Christie2ff96af2014-01-30 16:09:37 -08001858
1859 // Update statistics for historical location requests by package/provider
1860 mRequestStatistics.startRequesting(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001861 mReceiver.mIdentity.mPackageName, provider, request.getInterval());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001862 }
1863
1864 /**
David Christie2ff96af2014-01-30 16:09:37 -08001865 * Method to be called when a record will no longer be used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001866 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001867 void disposeLocked(boolean removeReceiver) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001868 mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider);
David Christie2ff96af2014-01-30 16:09:37 -08001869
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001870 // remove from mRecordsByProvider
1871 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
1872 if (globalRecords != null) {
1873 globalRecords.remove(this);
1874 }
1875
1876 if (!removeReceiver) return; // the caller will handle the rest
1877
1878 // remove from Receiver#mUpdateRecords
1879 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
1880 if (receiverRecords != null) {
1881 receiverRecords.remove(this.mProvider);
1882
1883 // and also remove the Receiver if it has no more update records
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001884 if (receiverRecords.size() == 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001885 removeUpdatesLocked(mReceiver);
1886 }
Mike Lockwood3a76fd62009-09-01 07:26:56 -04001887 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001888 }
1889
1890 @Override
1891 public String toString() {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001892 return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
1893 + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground" : " background")
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001894 + ")" + " " + mRequest + "]";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001896 }
1897
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001898 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -07001899 String packageName, WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001900 IBinder binder = listener.asBinder();
1901 Receiver receiver = mReceivers.get(binder);
1902 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07001903 receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
1904 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001905 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001906 receiver.getListener().asBinder().linkToDeath(receiver, 0);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001907 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001908 Slog.e(TAG, "linkToDeath failed:", e);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001909 return null;
1910 }
Wen Jingcb3ab222014-03-27 13:42:59 +08001911 mReceivers.put(binder, receiver);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001912 }
1913 return receiver;
1914 }
1915
David Christie82edc9b2013-07-19 11:31:42 -07001916 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
David Christie40e57822013-07-30 11:36:48 -07001917 WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001918 Receiver receiver = mReceivers.get(intent);
1919 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07001920 receiver = new Receiver(null, intent, pid, uid, packageName, workSource,
1921 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001922 mReceivers.put(intent, receiver);
1923 }
1924 return receiver;
1925 }
1926
Victoria Lease37425c32012-10-16 16:08:48 -07001927 /**
1928 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
1929 * and consistency requirements.
1930 *
1931 * @param request the LocationRequest from which to create a sanitized version
Victoria Lease37425c32012-10-16 16:08:48 -07001932 * @return a version of request that meets the given resolution and consistency requirements
1933 * @hide
1934 */
1935 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel) {
1936 LocationRequest sanitizedRequest = new LocationRequest(request);
1937 if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
1938 switch (sanitizedRequest.getQuality()) {
Victoria Lease09016ab2012-09-16 12:33:15 -07001939 case LocationRequest.ACCURACY_FINE:
Victoria Lease37425c32012-10-16 16:08:48 -07001940 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
Victoria Lease09016ab2012-09-16 12:33:15 -07001941 break;
1942 case LocationRequest.POWER_HIGH:
Victoria Lease37425c32012-10-16 16:08:48 -07001943 sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
Victoria Lease09016ab2012-09-16 12:33:15 -07001944 break;
1945 }
1946 // throttle
Victoria Lease37425c32012-10-16 16:08:48 -07001947 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1948 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001949 }
Victoria Lease37425c32012-10-16 16:08:48 -07001950 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1951 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001952 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07001953 }
Nick Pelly4e31c4f2012-08-13 19:35:39 -07001954 // make getFastestInterval() the minimum of interval and fastest interval
Victoria Lease37425c32012-10-16 16:08:48 -07001955 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07001956 request.setFastestInterval(request.getInterval());
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001957 }
Victoria Lease37425c32012-10-16 16:08:48 -07001958 return sanitizedRequest;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001959 }
1960
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001961 private void checkPackageName(String packageName) {
Nick Pellye0fd6932012-07-11 10:26:13 -07001962 if (packageName == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001963 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07001964 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001965 int uid = Binder.getCallingUid();
Nick Pellye0fd6932012-07-11 10:26:13 -07001966 String[] packages = mPackageManager.getPackagesForUid(uid);
1967 if (packages == null) {
1968 throw new SecurityException("invalid UID " + uid);
1969 }
1970 for (String pkg : packages) {
1971 if (packageName.equals(pkg)) return;
1972 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001973 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07001974 }
1975
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001976 private void checkPendingIntent(PendingIntent intent) {
1977 if (intent == null) {
1978 throw new IllegalArgumentException("invalid pending intent: " + intent);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001979 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001980 }
1981
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001982 private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent,
David Christie40e57822013-07-30 11:36:48 -07001983 int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001984 if (intent == null && listener == null) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001985 throw new IllegalArgumentException("need either listener or intent");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001986 } else if (intent != null && listener != null) {
1987 throw new IllegalArgumentException("cannot register both listener and intent");
1988 } else if (intent != null) {
1989 checkPendingIntent(intent);
David Christie40e57822013-07-30 11:36:48 -07001990 return getReceiverLocked(intent, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001991 } else {
David Christie40e57822013-07-30 11:36:48 -07001992 return getReceiverLocked(listener, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001993 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001994 }
1995
Nick Pellye0fd6932012-07-11 10:26:13 -07001996 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001997 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
1998 PendingIntent intent, String packageName) {
1999 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2000 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002001 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2002 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2003 request.getProvider());
David Christie82edc9b2013-07-19 11:31:42 -07002004 WorkSource workSource = request.getWorkSource();
2005 if (workSource != null && workSource.size() > 0) {
David Christie40e57822013-07-30 11:36:48 -07002006 checkDeviceStatsAllowed();
2007 }
2008 boolean hideFromAppOps = request.getHideFromAppOps();
2009 if (hideFromAppOps) {
2010 checkUpdateAppOpsAllowed();
David Christie82edc9b2013-07-19 11:31:42 -07002011 }
Victoria Lease37425c32012-10-16 16:08:48 -07002012 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002013
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002014 final int pid = Binder.getCallingPid();
2015 final int uid = Binder.getCallingUid();
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002016 // providers may use public location API's, need to clear identity
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002017 long identity = Binder.clearCallingIdentity();
2018 try {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002019 // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2020 // a location.
David Christieb870dbf2015-06-22 12:42:53 -07002021 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002022
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002023 synchronized (mLock) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002024 Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
David Christie40e57822013-07-30 11:36:48 -07002025 packageName, workSource, hideFromAppOps);
Victoria Lease37425c32012-10-16 16:08:48 -07002026 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
Mike Lockwood2d4d1bf2010-10-18 17:06:26 -04002027 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002028 } finally {
2029 Binder.restoreCallingIdentity(identity);
2030 }
2031 }
2032
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002033 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
2034 int pid, int uid, String packageName) {
2035 // Figure out the provider. Either its explicitly request (legacy use cases), or
2036 // use the fused provider
2037 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2038 String name = request.getProvider();
Victoria Lease09016ab2012-09-16 12:33:15 -07002039 if (name == null) {
2040 throw new IllegalArgumentException("provider name must not be null");
2041 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -07002042
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002043 LocationProviderInterface provider = mProvidersByName.get(name);
2044 if (provider == null) {
Victoria Leaseb30f3832013-10-13 12:15:40 -07002045 throw new IllegalArgumentException("provider doesn't exist: " + name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002046 }
2047
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002048 UpdateRecord record = new UpdateRecord(name, request, receiver);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002049 if (D) Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
2050 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
2051 + (record.mIsForegroundUid ? "foreground" : "background")
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002052 + (isThrottlingExemptLocked(receiver.mIdentity)
2053 ? " [whitelisted]" : "") + ")");
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002054
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002055 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
2056 if (oldRecord != null) {
2057 oldRecord.disposeLocked(false);
2058 }
2059
Victoria Lease09eeaec2013-02-05 11:34:13 -08002060 boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002061 if (isProviderEnabled) {
2062 applyRequirementsLocked(name);
2063 } else {
2064 // Notify the listener that updates are currently disabled
2065 receiver.callProviderEnabledLocked(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002066 }
David Christie0b837452013-07-29 16:02:13 -07002067 // Update the monitoring here just in case multiple location requests were added to the
2068 // same receiver (this request may be high power and the initial might not have been).
2069 receiver.updateMonitoring(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002070 }
2071
Nick Pellye0fd6932012-07-11 10:26:13 -07002072 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002073 public void removeUpdates(ILocationListener listener, PendingIntent intent,
2074 String packageName) {
2075 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002076
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002077 final int pid = Binder.getCallingPid();
2078 final int uid = Binder.getCallingUid();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002079
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002080 synchronized (mLock) {
David Christie82edc9b2013-07-19 11:31:42 -07002081 WorkSource workSource = null;
David Christie40e57822013-07-30 11:36:48 -07002082 boolean hideFromAppOps = false;
2083 Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid,
2084 packageName, workSource, hideFromAppOps);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002085
2086 // providers may use public location API's, need to clear identity
2087 long identity = Binder.clearCallingIdentity();
2088 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002089 removeUpdatesLocked(receiver);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002090 } finally {
2091 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002092 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002093 }
2094 }
2095
2096 private void removeUpdatesLocked(Receiver receiver) {
Dianne Hackborn7ff30112012-11-08 11:12:09 -08002097 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002098
2099 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
2100 receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
2101 synchronized (receiver) {
Victoria Lease0aa28602013-05-29 15:28:26 -07002102 receiver.clearPendingBroadcastsLocked();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002103 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002104 }
2105
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07002106 receiver.updateMonitoring(false);
2107
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002108 // Record which providers were associated with this listener
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002109 HashSet<String> providers = new HashSet<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002110 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2111 if (oldRecords != null) {
2112 // Call dispose() on the obsolete update records.
2113 for (UpdateRecord record : oldRecords.values()) {
David Christie2ff96af2014-01-30 16:09:37 -08002114 // Update statistics for historical location requests by package/provider
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002115 record.disposeLocked(false);
2116 }
2117 // Accumulate providers
2118 providers.addAll(oldRecords.keySet());
2119 }
2120
2121 // update provider
2122 for (String provider : providers) {
2123 // If provider is already disabled, don't need to do anything
Victoria Lease09eeaec2013-02-05 11:34:13 -08002124 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002125 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002126 }
2127
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002128 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002129 }
2130 }
2131
Dianne Hackbornc2293022013-02-06 23:14:49 -08002132 private void applyAllProviderRequirementsLocked() {
2133 for (LocationProviderInterface p : mProviders) {
2134 // If provider is already disabled, don't need to do anything
Dianne Hackborn64d41d72013-02-07 00:33:31 -08002135 if (!isAllowedByCurrentUserSettingsLocked(p.getName())) {
Dianne Hackbornc2293022013-02-06 23:14:49 -08002136 continue;
2137 }
2138
2139 applyRequirementsLocked(p.getName());
2140 }
2141 }
2142
Nick Pellye0fd6932012-07-11 10:26:13 -07002143 @Override
Nick Pelly4035f5a2012-08-17 14:43:49 -07002144 public Location getLastLocation(LocationRequest request, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002145 if (D) Log.d(TAG, "getLastLocation: " + request);
2146 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002147 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly4035f5a2012-08-17 14:43:49 -07002148 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002149 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2150 request.getProvider());
2151 // no need to sanitize this request, as only the provider name is used
Nick Pelly4035f5a2012-08-17 14:43:49 -07002152
David Christieb870dbf2015-06-22 12:42:53 -07002153 final int pid = Binder.getCallingPid();
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002154 final int uid = Binder.getCallingUid();
2155 final long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07002156 try {
2157 if (mBlacklist.isBlacklisted(packageName)) {
2158 if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
2159 packageName);
Victoria Lease09016ab2012-09-16 12:33:15 -07002160 return null;
2161 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002162
David Christieb870dbf2015-06-22 12:42:53 -07002163 if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel)) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002164 if (D) Log.d(TAG, "not returning last loc for no op app: " +
2165 packageName);
2166 return null;
2167 }
2168
Victoria Leaseb711d572012-10-02 13:14:11 -07002169 synchronized (mLock) {
2170 // Figure out the provider. Either its explicitly request (deprecated API's),
2171 // or use the fused provider
2172 String name = request.getProvider();
2173 if (name == null) name = LocationManager.FUSED_PROVIDER;
2174 LocationProviderInterface provider = mProvidersByName.get(name);
2175 if (provider == null) return null;
2176
Victoria Lease09eeaec2013-02-05 11:34:13 -08002177 if (!isAllowedByUserSettingsLocked(name, uid)) return null;
Victoria Leaseb711d572012-10-02 13:14:11 -07002178
David Christie1b9b7b12013-04-15 15:31:11 -07002179 Location location;
2180 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2181 // Make sure that an app with coarse permissions can't get frequent location
2182 // updates by calling LocationManager.getLastKnownLocation repeatedly.
2183 location = mLastLocationCoarseInterval.get(name);
2184 } else {
2185 location = mLastLocation.get(name);
2186 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002187 if (location == null) {
2188 return null;
2189 }
Victoria Lease37425c32012-10-16 16:08:48 -07002190 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002191 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2192 if (noGPSLocation != null) {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002193 return new Location(mLocationFudger.getOrCreate(noGPSLocation));
Victoria Leaseb711d572012-10-02 13:14:11 -07002194 }
Victoria Lease37425c32012-10-16 16:08:48 -07002195 } else {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002196 return new Location(location);
Victoria Lease09016ab2012-09-16 12:33:15 -07002197 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002198 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002199 return null;
2200 } finally {
2201 Binder.restoreCallingIdentity(identity);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002202 }
2203 }
2204
2205 @Override
2206 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
2207 String packageName) {
2208 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002209 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2210 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002211 checkPendingIntent(intent);
2212 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002213 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2214 request.getProvider());
2215 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002216
Victoria Lease37425c32012-10-16 16:08:48 -07002217 if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002218
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002219 // geo-fence manager uses the public location API, need to clear identity
2220 int uid = Binder.getCallingUid();
Xiaohui Chena4490622015-09-22 15:29:31 -07002221 // TODO: http://b/23822629
2222 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
Victoria Lease56e675b2012-11-05 19:25:06 -08002223 // temporary measure until geofences work for secondary users
2224 Log.w(TAG, "proximity alerts are currently available only to the primary user");
2225 return;
2226 }
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002227 long identity = Binder.clearCallingIdentity();
2228 try {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002229 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
2230 uid, packageName);
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002231 } finally {
2232 Binder.restoreCallingIdentity(identity);
2233 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002234 }
2235
2236 @Override
2237 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002238 checkPendingIntent(intent);
2239 checkPackageName(packageName);
2240
2241 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2242
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002243 // geo-fence manager uses the public location API, need to clear identity
2244 long identity = Binder.clearCallingIdentity();
2245 try {
2246 mGeofenceManager.removeFence(geofence, intent);
2247 } finally {
2248 Binder.restoreCallingIdentity(identity);
2249 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002250 }
2251
2252
2253 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002254 public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002255 if (!hasGnssPermissions(packageName) || mGnssStatusProvider == null) {
Takayuki Hoshib254ab6a2014-10-23 16:46:02 +09002256 return false;
2257 }
2258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002259 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002260 mGnssStatusProvider.registerGnssStatusCallback(callback);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002261 } catch (RemoteException e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002262 Slog.e(TAG, "mGpsStatusProvider.registerGnssStatusCallback failed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002263 return false;
2264 }
2265 return true;
2266 }
2267
Nick Pellye0fd6932012-07-11 10:26:13 -07002268 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002269 public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002270 synchronized (mLock) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002271 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002272 mGnssStatusProvider.unregisterGnssStatusCallback(callback);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002273 } catch (Exception e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002274 Slog.e(TAG, "mGpsStatusProvider.unregisterGnssStatusCallback failed", e);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002275 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002276 }
2277 }
2278
Nick Pellye0fd6932012-07-11 10:26:13 -07002279 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002280 public boolean addGnssMeasurementsListener(
2281 IGnssMeasurementsListener listener,
destradaaea8a8a62014-06-23 18:19:03 -07002282 String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002283 if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
destradaaea8a8a62014-06-23 18:19:03 -07002284 return false;
2285 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002286
2287 synchronized (mLock) {
2288 Identity callerIdentity
2289 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
2290 mGnssMeasurementsListeners.put(listener, callerIdentity);
2291 long identity = Binder.clearCallingIdentity();
2292 try {
2293 if (isThrottlingExemptLocked(callerIdentity)
2294 || isImportanceForeground(
2295 mActivityManager.getPackageImportance(packageName))) {
2296 return mGnssMeasurementsProvider.addListener(listener);
2297 }
2298 } finally {
2299 Binder.restoreCallingIdentity(identity);
2300 }
2301
2302 return true;
2303 }
destradaaea8a8a62014-06-23 18:19:03 -07002304 }
2305
2306 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002307 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
2308 if (mGnssMeasurementsProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002309 synchronized (mLock) {
2310 mGnssMeasurementsListeners.remove(listener);
2311 mGnssMeasurementsProvider.removeListener(listener);
2312 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002313 }
destradaaea8a8a62014-06-23 18:19:03 -07002314 }
2315
2316 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002317 public boolean addGnssNavigationMessageListener(
2318 IGnssNavigationMessageListener listener,
destradaa4b3e3932014-07-21 18:01:47 -07002319 String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002320 if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) {
destradaa4b3e3932014-07-21 18:01:47 -07002321 return false;
2322 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002323
2324 synchronized (mLock) {
2325 Identity callerIdentity
2326 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
2327 mGnssNavigationMessageListeners.put(listener, callerIdentity);
2328 long identity = Binder.clearCallingIdentity();
2329 try {
2330 if (isThrottlingExemptLocked(callerIdentity)
2331 || isImportanceForeground(
2332 mActivityManager.getPackageImportance(packageName))) {
2333 return mGnssNavigationMessageProvider.addListener(listener);
2334 }
2335 } finally {
2336 Binder.restoreCallingIdentity(identity);
2337 }
2338
2339 return true;
2340 }
destradaa4b3e3932014-07-21 18:01:47 -07002341 }
2342
2343 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002344 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
2345 if (mGnssNavigationMessageProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002346 synchronized (mLock) {
2347 mGnssNavigationMessageListeners.remove(listener);
2348 mGnssNavigationMessageProvider.removeListener(listener);
2349 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002350 }
destradaa4b3e3932014-07-21 18:01:47 -07002351 }
2352
2353 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 public boolean sendExtraCommand(String provider, String command, Bundle extras) {
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002355 if (provider == null) {
2356 // throw NullPointerException to remain compatible with previous implementation
2357 throw new NullPointerException();
2358 }
Victoria Lease37425c32012-10-16 16:08:48 -07002359 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2360 provider);
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002361
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002362 // and check for ACCESS_LOCATION_EXTRA_COMMANDS
Mike Lockwoodb7e99222009-07-07 13:18:21 -04002363 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002364 != PackageManager.PERMISSION_GRANTED)) {
2365 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
2366 }
2367
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002368 synchronized (mLock) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002369 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002370 if (p == null) return false;
Nick Pellye0fd6932012-07-11 10:26:13 -07002371
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002372 return p.sendExtraCommand(command, extras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002373 }
2374 }
2375
Nick Pellye0fd6932012-07-11 10:26:13 -07002376 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002377 public boolean sendNiResponse(int notifId, int userResponse) {
Mike Lockwood18ad9f62009-08-27 14:01:23 -07002378 if (Binder.getCallingUid() != Process.myUid()) {
2379 throw new SecurityException(
2380 "calling sendNiResponse from outside of the system is not allowed");
2381 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002382 try {
2383 return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002384 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002385 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
Danke Xie22d1f9f2009-08-18 18:28:45 -04002386 return false;
2387 }
2388 }
2389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002390 /**
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002391 * @return null if the provider does not exist
Alexey Tarasovf2db9fb2009-09-01 02:37:07 +11002392 * @throws SecurityException if the provider is not allowed to be
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002393 * accessed by the caller
2394 */
Nick Pellye0fd6932012-07-11 10:26:13 -07002395 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002396 public ProviderProperties getProviderProperties(String provider) {
Laurent Tub7f9d252012-10-16 14:25:00 -07002397 if (mProvidersByName.get(provider) == null) {
David Christie2ff96af2014-01-30 16:09:37 -08002398 return null;
Laurent Tub7f9d252012-10-16 14:25:00 -07002399 }
2400
Victoria Lease37425c32012-10-16 16:08:48 -07002401 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2402 provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002403
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002404 LocationProviderInterface p;
2405 synchronized (mLock) {
2406 p = mProvidersByName.get(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002407 }
2408
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002409 if (p == null) return null;
2410 return p.getProperties();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002411 }
2412
Jason Monkb71218a2015-06-17 14:44:39 -04002413 /**
2414 * @return null if the provider does not exist
2415 * @throws SecurityException if the provider is not allowed to be
2416 * accessed by the caller
2417 */
2418 @Override
2419 public String getNetworkProviderPackage() {
2420 LocationProviderInterface p;
2421 synchronized (mLock) {
2422 if (mProvidersByName.get(LocationManager.NETWORK_PROVIDER) == null) {
2423 return null;
2424 }
2425 p = mProvidersByName.get(LocationManager.NETWORK_PROVIDER);
2426 }
2427
2428 if (p instanceof LocationProviderProxy) {
2429 return ((LocationProviderProxy) p).getConnectedPackageName();
2430 }
2431 return null;
2432 }
2433
Nick Pellye0fd6932012-07-11 10:26:13 -07002434 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002435 public boolean isProviderEnabled(String provider) {
Tom O'Neilld5759432013-09-11 11:03:03 -07002436 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2437 // so we discourage its use
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002438 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
2439
Victoria Lease09eeaec2013-02-05 11:34:13 -08002440 int uid = Binder.getCallingUid();
Victoria Lease269518e2012-10-29 08:25:39 -07002441 long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07002442 try {
2443 synchronized (mLock) {
2444 LocationProviderInterface p = mProvidersByName.get(provider);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002445 return p != null && isAllowedByUserSettingsLocked(provider, uid);
Victoria Leaseb711d572012-10-02 13:14:11 -07002446 }
2447 } finally {
2448 Binder.restoreCallingIdentity(identity);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002449 }
2450 }
2451
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002452 /**
2453 * Returns "true" if the UID belongs to a bound location provider.
2454 *
2455 * @param uid the uid
2456 * @return true if uid belongs to a bound location provider
2457 */
2458 private boolean isUidALocationProvider(int uid) {
2459 if (uid == Process.SYSTEM_UID) {
2460 return true;
2461 }
2462 if (mGeocodeProvider != null) {
David Christie1f141c12014-05-14 15:11:15 -07002463 if (doesUidHavePackage(uid, mGeocodeProvider.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002464 }
2465 for (LocationProviderProxy proxy : mProxyProviders) {
David Christie1f141c12014-05-14 15:11:15 -07002466 if (doesUidHavePackage(uid, proxy.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002467 }
2468 return false;
2469 }
2470
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002471 private void checkCallerIsProvider() {
2472 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
2473 == PackageManager.PERMISSION_GRANTED) {
2474 return;
2475 }
2476
2477 // Previously we only used the INSTALL_LOCATION_PROVIDER
2478 // check. But that is system or signature
2479 // protection level which is not flexible enough for
2480 // providers installed oustide the system image. So
2481 // also allow providers with a UID matching the
2482 // currently bound package name
2483
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002484 if (isUidALocationProvider(Binder.getCallingUid())) {
2485 return;
2486 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002487
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002488 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
2489 "or UID of a currently bound location provider");
2490 }
2491
David Christie1f141c12014-05-14 15:11:15 -07002492 /**
2493 * Returns true if the given package belongs to the given uid.
2494 */
2495 private boolean doesUidHavePackage(int uid, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002496 if (packageName == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002497 return false;
2498 }
David Christie1f141c12014-05-14 15:11:15 -07002499 String[] packageNames = mPackageManager.getPackagesForUid(uid);
2500 if (packageNames == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002501 return false;
2502 }
David Christie1f141c12014-05-14 15:11:15 -07002503 for (String name : packageNames) {
2504 if (packageName.equals(name)) {
2505 return true;
2506 }
2507 }
2508 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002509 }
2510
Nick Pellye0fd6932012-07-11 10:26:13 -07002511 @Override
Mike Lockwooda4903f22010-02-17 06:42:23 -05002512 public void reportLocation(Location location, boolean passive) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002513 checkCallerIsProvider();
Mike Lockwood275555c2009-05-01 11:30:34 -04002514
Nick Pelly2eeeec22012-07-18 13:13:37 -07002515 if (!location.isComplete()) {
2516 Log.w(TAG, "Dropping incomplete location: " + location);
2517 return;
2518 }
2519
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002520 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location);
2521 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location);
Mike Lockwooda4903f22010-02-17 06:42:23 -05002522 m.arg1 = (passive ? 1 : 0);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002523 mLocationHandler.sendMessageAtFrontOfQueue(m);
2524 }
2525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002526
Laurent Tu75defb62012-11-01 16:21:52 -07002527 private static boolean shouldBroadcastSafe(
2528 Location loc, Location lastLoc, UpdateRecord record, long now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002529 // Always broadcast the first update
2530 if (lastLoc == null) {
2531 return true;
2532 }
2533
Nick Pellyf1be6862012-05-15 10:53:42 -07002534 // Check whether sufficient time has passed
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002535 long minTime = record.mRequest.getFastestInterval();
David Christie1b9b7b12013-04-15 15:31:11 -07002536 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
2537 / NANOS_PER_MILLI;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002538 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002539 return false;
2540 }
2541
2542 // Check whether sufficient distance has been traveled
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002543 double minDistance = record.mRequest.getSmallestDisplacement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002544 if (minDistance > 0.0) {
2545 if (loc.distanceTo(lastLoc) <= minDistance) {
2546 return false;
2547 }
2548 }
2549
Laurent Tu75defb62012-11-01 16:21:52 -07002550 // Check whether sufficient number of udpates is left
2551 if (record.mRequest.getNumUpdates() <= 0) {
2552 return false;
2553 }
2554
2555 // Check whether the expiry date has passed
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002556 return record.mRequest.getExpireAt() >= now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002557 }
2558
Mike Lockwooda4903f22010-02-17 06:42:23 -05002559 private void handleLocationChangedLocked(Location location, boolean passive) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002560 if (D) Log.d(TAG, "incoming location: " + location);
2561
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002562 long now = SystemClock.elapsedRealtime();
Mike Lockwooda4903f22010-02-17 06:42:23 -05002563 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002564
Laurent Tu60ec50a2012-10-04 17:00:10 -07002565 // Skip if the provider is unknown.
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002566 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002567 if (p == null) return;
2568
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002569 // Update last known locations
Victoria Lease09016ab2012-09-16 12:33:15 -07002570 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002571 Location lastNoGPSLocation;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002572 Location lastLocation = mLastLocation.get(provider);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002573 if (lastLocation == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002574 lastLocation = new Location(provider);
2575 mLastLocation.put(provider, lastLocation);
Victoria Lease09016ab2012-09-16 12:33:15 -07002576 } else {
2577 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2578 if (noGPSLocation == null && lastNoGPSLocation != null) {
2579 // New location has no no-GPS location: adopt last no-GPS location. This is set
2580 // directly into location because we do not want to notify COARSE clients.
2581 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
2582 }
Mike Lockwood4e50b782009-04-03 08:24:43 -07002583 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002584 lastLocation.set(location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002585
David Christie1b9b7b12013-04-15 15:31:11 -07002586 // Update last known coarse interval location if enough time has passed.
2587 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider);
2588 if (lastLocationCoarseInterval == null) {
2589 lastLocationCoarseInterval = new Location(location);
2590 mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval);
2591 }
2592 long timeDiffNanos = location.getElapsedRealtimeNanos()
2593 - lastLocationCoarseInterval.getElapsedRealtimeNanos();
2594 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
2595 lastLocationCoarseInterval.set(location);
2596 }
2597 // Don't ever return a coarse location that is more recent than the allowed update
2598 // interval (i.e. don't allow an app to keep registering and unregistering for
2599 // location updates to overcome the minimum interval).
2600 noGPSLocation =
2601 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2602
Laurent Tu60ec50a2012-10-04 17:00:10 -07002603 // Skip if there are no UpdateRecords for this provider.
2604 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
2605 if (records == null || records.size() == 0) return;
2606
Victoria Lease09016ab2012-09-16 12:33:15 -07002607 // Fetch coarse location
2608 Location coarseLocation = null;
David Christie1b9b7b12013-04-15 15:31:11 -07002609 if (noGPSLocation != null) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002610 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
2611 }
2612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002613 // Fetch latest status update time
2614 long newStatusUpdateTime = p.getStatusUpdateTime();
2615
David Christie2ff96af2014-01-30 16:09:37 -08002616 // Get latest status
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002617 Bundle extras = new Bundle();
2618 int status = p.getStatus(extras);
2619
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002620 ArrayList<Receiver> deadReceivers = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002621 ArrayList<UpdateRecord> deadUpdateRecords = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07002622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002623 // Broadcast location or status to all listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002624 for (UpdateRecord r : records) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002625 Receiver receiver = r.mReceiver;
Mike Lockwood03ca2162010-04-01 08:10:09 -07002626 boolean receiverDead = false;
Nick Pelly4035f5a2012-08-17 14:43:49 -07002627
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002628 int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid);
2629 if (!isCurrentProfile(receiverUserId)
2630 && !isUidALocationProvider(receiver.mIdentity.mUid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002631 if (D) {
Victoria Lease269518e2012-10-29 08:25:39 -07002632 Log.d(TAG, "skipping loc update for background user " + receiverUserId +
Victoria Leaseb711d572012-10-02 13:14:11 -07002633 " (current user: " + mCurrentUserId + ", app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002634 receiver.mIdentity.mPackageName + ")");
Victoria Leaseb711d572012-10-02 13:14:11 -07002635 }
2636 continue;
2637 }
2638
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002639 if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) {
Nick Pelly4035f5a2012-08-17 14:43:49 -07002640 if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002641 receiver.mIdentity.mPackageName);
Nick Pelly4035f5a2012-08-17 14:43:49 -07002642 continue;
2643 }
2644
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002645 if (!reportLocationAccessNoThrow(
2646 receiver.mIdentity.mPid,
2647 receiver.mIdentity.mUid,
2648 receiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002649 receiver.mAllowedResolutionLevel)) {
2650 if (D) Log.d(TAG, "skipping loc update for no op app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002651 receiver.mIdentity.mPackageName);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002652 continue;
2653 }
2654
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002655 Location notifyLocation;
Victoria Lease37425c32012-10-16 16:08:48 -07002656 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2657 notifyLocation = coarseLocation; // use coarse location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002658 } else {
Victoria Lease37425c32012-10-16 16:08:48 -07002659 notifyLocation = lastLocation; // use fine location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002660 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002661 if (notifyLocation != null) {
2662 Location lastLoc = r.mLastFixBroadcast;
Laurent Tu75defb62012-11-01 16:21:52 -07002663 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002664 if (lastLoc == null) {
2665 lastLoc = new Location(notifyLocation);
2666 r.mLastFixBroadcast = lastLoc;
2667 } else {
2668 lastLoc.set(notifyLocation);
2669 }
2670 if (!receiver.callLocationChangedLocked(notifyLocation)) {
2671 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
2672 receiverDead = true;
2673 }
Laurent Tu75defb62012-11-01 16:21:52 -07002674 r.mRequest.decrementNumUpdates();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002675 }
2676 }
2677
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002678 long prevStatusUpdateTime = r.mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002679 if ((newStatusUpdateTime > prevStatusUpdateTime) &&
Victoria Lease09016ab2012-09-16 12:33:15 -07002680 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002681
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002682 r.mLastStatusBroadcast = newStatusUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002683 if (!receiver.callStatusChangedLocked(provider, status, extras)) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002684 receiverDead = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002685 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
Mike Lockwood03ca2162010-04-01 08:10:09 -07002686 }
2687 }
2688
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002689 // track expired records
Laurent Tu75defb62012-11-01 16:21:52 -07002690 if (r.mRequest.getNumUpdates() <= 0 || r.mRequest.getExpireAt() < now) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002691 if (deadUpdateRecords == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002692 deadUpdateRecords = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002693 }
2694 deadUpdateRecords.add(r);
2695 }
2696 // track dead receivers
2697 if (receiverDead) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002698 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002699 deadReceivers = new ArrayList<>();
Mike Lockwood03ca2162010-04-01 08:10:09 -07002700 }
2701 if (!deadReceivers.contains(receiver)) {
2702 deadReceivers.add(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002703 }
2704 }
2705 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002706
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002707 // remove dead records and receivers outside the loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002708 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002709 for (Receiver receiver : deadReceivers) {
2710 removeUpdatesLocked(receiver);
2711 }
2712 }
2713 if (deadUpdateRecords != null) {
2714 for (UpdateRecord r : deadUpdateRecords) {
2715 r.disposeLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002716 }
Victoria Lease8b38b292012-12-04 15:04:43 -08002717 applyRequirementsLocked(provider);
2718 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 }
2720
2721 private class LocationWorkerHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08002722 public LocationWorkerHandler(Looper looper) {
2723 super(looper, null, true);
2724 }
2725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002726 @Override
2727 public void handleMessage(Message msg) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002728 switch (msg.what) {
2729 case MSG_LOCATION_CHANGED:
2730 handleLocationChanged((Location) msg.obj, msg.arg1 == 1);
2731 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002732 }
2733 }
2734 }
2735
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002736 private boolean isMockProvider(String provider) {
2737 synchronized (mLock) {
2738 return mMockProviders.containsKey(provider);
2739 }
2740 }
2741
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002742 private void handleLocationChanged(Location location, boolean passive) {
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002743 // create a working copy of the incoming Location so that the service can modify it without
2744 // disturbing the caller's copy
2745 Location myLocation = new Location(location);
2746 String provider = myLocation.getProvider();
2747
2748 // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this
2749 // bit if location did not come from a mock provider because passive/fused providers can
2750 // forward locations from mock providers, and should not grant them legitimacy in doing so.
2751 if (!myLocation.isFromMockProvider() && isMockProvider(provider)) {
2752 myLocation.setIsFromMockProvider(true);
2753 }
Jeff Sharkey5e613312012-01-30 11:16:20 -08002754
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002755 synchronized (mLock) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08002756 if (isAllowedByCurrentUserSettingsLocked(provider)) {
2757 if (!passive) {
2758 // notify passive provider of the new location
2759 mPassiveProvider.updateLocation(myLocation);
2760 }
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002761 handleLocationChangedLocked(myLocation, passive);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002762 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002763 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002764 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002765
Mike Lockwoode97ae402010-09-29 15:23:46 -04002766 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
2767 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002768 public void onPackageDisappeared(String packageName, int reason) {
2769 // remove all receivers associated with this package name
2770 synchronized (mLock) {
2771 ArrayList<Receiver> deadReceivers = null;
2772
2773 for (Receiver receiver : mReceivers.values()) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002774 if (receiver.mIdentity.mPackageName.equals(packageName)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002775 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002776 deadReceivers = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002777 }
2778 deadReceivers.add(receiver);
2779 }
2780 }
2781
2782 // perform removal outside of mReceivers loop
2783 if (deadReceivers != null) {
2784 for (Receiver receiver : deadReceivers) {
2785 removeUpdatesLocked(receiver);
2786 }
2787 }
2788 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002789 }
Mike Lockwoode97ae402010-09-29 15:23:46 -04002790 };
2791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002792 // Geocoder
2793
Nick Pellye0fd6932012-07-11 10:26:13 -07002794 @Override
Mike Lockwoode15735a2010-09-20 17:48:47 -04002795 public boolean geocoderIsPresent() {
Mark Vandevoorde01ac80b2010-05-21 15:43:26 -07002796 return mGeocodeProvider != null;
2797 }
2798
Nick Pellye0fd6932012-07-11 10:26:13 -07002799 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002800 public String getFromLocation(double latitude, double longitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002801 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002802 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002803 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
2804 params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002805 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002806 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002807 }
2808
Mike Lockwooda55c3212009-04-15 11:10:11 -04002809
Nick Pellye0fd6932012-07-11 10:26:13 -07002810 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002811 public String getFromLocationName(String locationName,
Mike Lockwooda55c3212009-04-15 11:10:11 -04002812 double lowerLeftLatitude, double lowerLeftLongitude,
2813 double upperRightLatitude, double upperRightLongitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002814 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002815
2816 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002817 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
2818 lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
2819 maxResults, params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002820 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002821 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002822 }
2823
2824 // Mock Providers
2825
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002826 private boolean canCallerAccessMockLocation(String opPackageName) {
2827 return mAppOps.noteOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(),
2828 opPackageName) == AppOpsManager.MODE_ALLOWED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002829 }
2830
Nick Pellye0fd6932012-07-11 10:26:13 -07002831 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002832 public void addTestProvider(String name, ProviderProperties properties, String opPackageName) {
2833 if (!canCallerAccessMockLocation(opPackageName)) {
2834 return;
2835 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002836
Mike Lockwooda4903f22010-02-17 06:42:23 -05002837 if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
2838 throw new IllegalArgumentException("Cannot mock the passive location provider");
2839 }
2840
Mike Lockwood86328a92009-10-23 08:38:25 -04002841 long identity = Binder.clearCallingIdentity();
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002842 synchronized (mLock) {
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002843 // remove the real provider if we are replacing GPS or network provider
2844 if (LocationManager.GPS_PROVIDER.equals(name)
Nick Pelly1332b532012-08-21 16:25:47 -07002845 || LocationManager.NETWORK_PROVIDER.equals(name)
2846 || LocationManager.FUSED_PROVIDER.equals(name)) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002847 LocationProviderInterface p = mProvidersByName.get(name);
2848 if (p != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002849 removeProviderLocked(p);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002850 }
2851 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09002852 addTestProviderLocked(name, properties);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002853 updateProvidersLocked();
2854 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002855 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002856 }
2857
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09002858 private void addTestProviderLocked(String name, ProviderProperties properties) {
2859 if (mProvidersByName.get(name) != null) {
2860 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
2861 }
2862 MockProvider provider = new MockProvider(name, this, properties);
2863 addProviderLocked(provider);
2864 mMockProviders.put(name, provider);
2865 mLastLocation.put(name, null);
2866 mLastLocationCoarseInterval.put(name, null);
2867 }
2868
Nick Pellye0fd6932012-07-11 10:26:13 -07002869 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002870 public void removeTestProvider(String provider, String opPackageName) {
2871 if (!canCallerAccessMockLocation(opPackageName)) {
2872 return;
2873 }
2874
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002875 synchronized (mLock) {
Tom O'Neill07ee5d12014-03-03 17:48:35 -08002876
2877 // These methods can't be called after removing the test provider, so first make sure
Tom O'Neillfe6d3c52014-03-04 08:26:17 -08002878 // we don't leave anything dangling.
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002879 clearTestProviderEnabled(provider, opPackageName);
2880 clearTestProviderLocation(provider, opPackageName);
2881 clearTestProviderStatus(provider, opPackageName);
Tom O'Neill07ee5d12014-03-03 17:48:35 -08002882
You Kima6d0b6f2012-10-28 03:58:44 +09002883 MockProvider mockProvider = mMockProviders.remove(provider);
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002884 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002885 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2886 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002887 long identity = Binder.clearCallingIdentity();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002888 removeProviderLocked(mProvidersByName.get(provider));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002889
2890 // reinstate real provider if available
2891 LocationProviderInterface realProvider = mRealProviders.get(provider);
2892 if (realProvider != null) {
2893 addProviderLocked(realProvider);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002894 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002895 mLastLocation.put(provider, null);
David Christie1b9b7b12013-04-15 15:31:11 -07002896 mLastLocationCoarseInterval.put(provider, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002897 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04002898 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002899 }
2900 }
2901
Nick Pellye0fd6932012-07-11 10:26:13 -07002902 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002903 public void setTestProviderLocation(String provider, Location loc, String opPackageName) {
2904 if (!canCallerAccessMockLocation(opPackageName)) {
2905 return;
2906 }
2907
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002908 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002909 MockProvider mockProvider = mMockProviders.get(provider);
2910 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002911 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2912 }
Tom O'Neilla206a0f2016-12-15 10:26:28 -08002913
2914 // Ensure that the location is marked as being mock. There's some logic to do this in
2915 // handleLocationChanged(), but it fails if loc has the wrong provider (bug 33091107).
2916 Location mock = new Location(loc);
2917 mock.setIsFromMockProvider(true);
2918
2919 if (!TextUtils.isEmpty(loc.getProvider()) && !provider.equals(loc.getProvider())) {
2920 // The location has an explicit provider that is different from the mock provider
2921 // name. The caller may be trying to fool us via bug 33091107.
2922 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
2923 provider + "!=" + loc.getProvider());
2924 }
2925
Mike Lockwood95427cd2009-05-07 13:27:54 -04002926 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
2927 long identity = Binder.clearCallingIdentity();
Tom O'Neilla206a0f2016-12-15 10:26:28 -08002928 mockProvider.setLocation(mock);
Mike Lockwood95427cd2009-05-07 13:27:54 -04002929 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002930 }
2931 }
2932
Nick Pellye0fd6932012-07-11 10:26:13 -07002933 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002934 public void clearTestProviderLocation(String provider, String opPackageName) {
2935 if (!canCallerAccessMockLocation(opPackageName)) {
2936 return;
2937 }
2938
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002939 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002940 MockProvider mockProvider = mMockProviders.get(provider);
2941 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002942 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2943 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002944 mockProvider.clearLocation();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002945 }
2946 }
2947
Nick Pellye0fd6932012-07-11 10:26:13 -07002948 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002949 public void setTestProviderEnabled(String provider, boolean enabled, String opPackageName) {
2950 if (!canCallerAccessMockLocation(opPackageName)) {
2951 return;
2952 }
2953
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002954 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002955 MockProvider mockProvider = mMockProviders.get(provider);
2956 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002957 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2958 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002959 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002960 if (enabled) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002961 mockProvider.enable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002962 mEnabledProviders.add(provider);
2963 mDisabledProviders.remove(provider);
2964 } else {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002965 mockProvider.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002966 mEnabledProviders.remove(provider);
2967 mDisabledProviders.add(provider);
2968 }
2969 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04002970 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002971 }
2972 }
2973
Nick Pellye0fd6932012-07-11 10:26:13 -07002974 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002975 public void clearTestProviderEnabled(String provider, String opPackageName) {
2976 if (!canCallerAccessMockLocation(opPackageName)) {
2977 return;
2978 }
2979
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002980 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002981 MockProvider mockProvider = mMockProviders.get(provider);
2982 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002983 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2984 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002985 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002986 mEnabledProviders.remove(provider);
2987 mDisabledProviders.remove(provider);
2988 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04002989 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002990 }
2991 }
2992
Nick Pellye0fd6932012-07-11 10:26:13 -07002993 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002994 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime,
2995 String opPackageName) {
2996 if (!canCallerAccessMockLocation(opPackageName)) {
2997 return;
2998 }
2999
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003000 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003001 MockProvider mockProvider = mMockProviders.get(provider);
3002 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003003 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3004 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003005 mockProvider.setStatus(status, extras, updateTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003006 }
3007 }
3008
Nick Pellye0fd6932012-07-11 10:26:13 -07003009 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003010 public void clearTestProviderStatus(String provider, String opPackageName) {
3011 if (!canCallerAccessMockLocation(opPackageName)) {
3012 return;
3013 }
3014
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003015 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003016 MockProvider mockProvider = mMockProviders.get(provider);
3017 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003018 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3019 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003020 mockProvider.clearStatus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003021 }
3022 }
3023
3024 private void log(String log) {
3025 if (Log.isLoggable(TAG, Log.VERBOSE)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003026 Slog.d(TAG, log);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003027 }
3028 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003029
3030 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003031 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003032 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Nick Pellye0fd6932012-07-11 10:26:13 -07003033
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003034 synchronized (mLock) {
Siddharth Raybb608c82017-03-16 11:33:34 -07003035 if (args.length > 0 && args[0].equals("--gnssmetrics")) {
3036 if (mGnssMetricsProvider != null) {
3037 pw.append(mGnssMetricsProvider.getGnssMetricsAsProtoString());
3038 }
3039 return;
3040 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003041 pw.println("Current Location Manager state:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003042 pw.println(" Location Listeners:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003043 for (Receiver receiver : mReceivers.values()) {
3044 pw.println(" " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003045 }
David Christie2ff96af2014-01-30 16:09:37 -08003046 pw.println(" Active Records by Provider:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003047 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
3048 pw.println(" " + entry.getKey() + ":");
3049 for (UpdateRecord record : entry.getValue()) {
3050 pw.println(" " + record);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003051 }
3052 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003053 pw.println(" Overlay Provider Packages:");
3054 for (LocationProviderInterface provider : mProviders) {
3055 if (provider instanceof LocationProviderProxy) {
3056 pw.println(" " + provider.getName() + ": "
3057 + ((LocationProviderProxy) provider).getConnectedPackageName());
3058 }
3059 }
David Christie2ff96af2014-01-30 16:09:37 -08003060 pw.println(" Historical Records by Provider:");
3061 for (Map.Entry<PackageProviderKey, PackageStatistics> entry
3062 : mRequestStatistics.statistics.entrySet()) {
3063 PackageProviderKey key = entry.getKey();
3064 PackageStatistics stats = entry.getValue();
3065 pw.println(" " + key.packageName + ": " + key.providerName + ": " + stats);
3066 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003067 pw.println(" Last Known Locations:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003068 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
3069 String provider = entry.getKey();
3070 Location location = entry.getValue();
3071 pw.println(" " + provider + ": " + location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003072 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003073
David Christie1b9b7b12013-04-15 15:31:11 -07003074 pw.println(" Last Known Locations Coarse Intervals:");
3075 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
3076 String provider = entry.getKey();
3077 Location location = entry.getValue();
3078 pw.println(" " + provider + ": " + location);
3079 }
3080
Nick Pellye0fd6932012-07-11 10:26:13 -07003081 mGeofenceManager.dump(pw);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003082
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003083 if (mEnabledProviders.size() > 0) {
3084 pw.println(" Enabled Providers:");
3085 for (String i : mEnabledProviders) {
3086 pw.println(" " + i);
3087 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003089 }
3090 if (mDisabledProviders.size() > 0) {
3091 pw.println(" Disabled Providers:");
3092 for (String i : mDisabledProviders) {
3093 pw.println(" " + i);
3094 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003095 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07003096 pw.append(" ");
3097 mBlacklist.dump(pw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003098 if (mMockProviders.size() > 0) {
3099 pw.println(" Mock Providers:");
3100 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003101 i.getValue().dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003102 }
3103 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003104
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08003105 if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
3106 pw.println(" Throttling Whitelisted Packages:");
3107 for (String packageName : mBackgroundThrottlePackageWhitelist) {
3108 pw.println(" " + packageName);
3109 }
3110 }
3111
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003112 pw.append(" fudger: ");
3113 mLocationFudger.dump(fd, pw, args);
3114
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003115 if (args.length > 0 && "short".equals(args[0])) {
3116 return;
3117 }
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003118 for (LocationProviderInterface provider: mProviders) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003119 pw.print(provider.getName() + " Internal State");
3120 if (provider instanceof LocationProviderProxy) {
3121 LocationProviderProxy proxy = (LocationProviderProxy) provider;
3122 pw.print(" (" + proxy.getConnectedPackageName() + ")");
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003123 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003124 pw.println(":");
3125 provider.dump(fd, pw, args);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003126 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08003127 if (mGnssBatchingInProgress) {
3128 pw.println(" GNSS batching in progress");
3129 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003130 }
3131 }
3132}