blob: 966e553a6396c478824aad6c0d6bd94b5ed6c368 [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 Nagarkarebda0282017-04-10 14:55:37 -0700149 private static final int FOREGROUND_IMPORTANCE_CUTOFF
150 = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
151
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800152 // default background throttling interval if not overriden in settings
Soonil Nagarkarde6780a2017-02-07 10:39:41 -0800153 private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800154
Nick Pellyf1be6862012-05-15 10:53:42 -0700155 // Location Providers may sometimes deliver location updates
156 // slightly faster that requested - provide grace period so
157 // we don't unnecessarily filter events that are otherwise on
158 // time
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700159 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
Nick Pellyf1be6862012-05-15 10:53:42 -0700160
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700161 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
162
163 private final Context mContext;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800164 private final AppOpsManager mAppOps;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700165
166 // used internally for synchronization
167 private final Object mLock = new Object();
168
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700169 // --- fields below are final after systemRunning() ---
Nick Pelly74fa7ea2012-08-13 19:36:38 -0700170 private LocationFudger mLocationFudger;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700171 private GeofenceManager mGeofenceManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700172 private PackageManager mPackageManager;
Victoria Lease0aa28602013-05-29 15:28:26 -0700173 private PowerManager mPowerManager;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800174 private ActivityManager mActivityManager;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700175 private UserManager mUserManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700176 private GeocoderProxy mGeocodeProvider;
Lifu Tang30f95a72016-01-07 23:20:38 -0800177 private IGnssStatusProvider mGnssStatusProvider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700178 private INetInitiatedListener mNetInitiatedListener;
179 private LocationWorkerHandler mLocationHandler;
Nick Pelly4035f5a2012-08-17 14:43:49 -0700180 private PassiveProvider mPassiveProvider; // track passive provider for special cases
181 private LocationBlacklist mBlacklist;
Lifu Tang818aa2c2016-02-01 01:52:00 -0800182 private GnssMeasurementsProvider mGnssMeasurementsProvider;
183 private GnssNavigationMessageProvider mGnssNavigationMessageProvider;
Wei Liu5241a4c2015-05-11 14:00:36 -0700184 private IGpsGeofenceHardware mGpsGeofenceProxy;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700185
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700186 // --- fields below are protected by mLock ---
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 // Set of providers that are explicitly enabled
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700188 // Only used by passive, fused & test. Network & GPS are controlled separately, and not listed.
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800189 private final Set<String> mEnabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190
191 // Set of providers that are explicitly disabled
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800192 private final Set<String> mDisabledProviders = new HashSet<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700194 // Mock (test) providers
195 private final HashMap<String, MockProvider> mMockProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800196 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700198 // all receivers
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800199 private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700201 // currently installed providers (with mocks replacing real providers)
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500202 private final ArrayList<LocationProviderInterface> mProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800203 new ArrayList<>();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400204
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700205 // real providers, saved here when mocked out
206 private final HashMap<String, LocationProviderInterface> mRealProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800207 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700209 // mapping from provider name to provider
210 private final HashMap<String, LocationProviderInterface> mProvidersByName =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800211 new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700213 // mapping from provider name to all its UpdateRecords
214 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800215 new HashMap<>();
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700216
David Christie2ff96af2014-01-30 16:09:37 -0800217 private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics();
218
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700219 // mapping from provider name to last known location
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800220 private final HashMap<String, Location> mLastLocation = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221
David Christie1b9b7b12013-04-15 15:31:11 -0700222 // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
223 // locations stored here are not fudged for coarse permissions.
224 private final HashMap<String, Location> mLastLocationCoarseInterval =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800225 new HashMap<>();
David Christie1b9b7b12013-04-15 15:31:11 -0700226
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800227 // all providers that operate over proxy, for authorizing incoming location and whitelisting
228 // throttling
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700229 private final ArrayList<LocationProviderProxy> mProxyProviders =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800230 new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800232 private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800233
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800234 private final ArrayMap<IGnssMeasurementsListener, Identity> mGnssMeasurementsListeners =
235 new ArrayMap<>();
236
237 private final ArrayMap<IGnssNavigationMessageListener, Identity>
238 mGnssNavigationMessageListeners = new ArrayMap<>();
239
Victoria Lease38389b62012-09-30 11:44:22 -0700240 // current active user on the device - other users are denied location data
Xiaohui Chena4490622015-09-22 15:29:31 -0700241 private int mCurrentUserId = UserHandle.USER_SYSTEM;
242 private int[] mCurrentUserProfiles = new int[] { UserHandle.USER_SYSTEM };
Victoria Lease38389b62012-09-30 11:44:22 -0700243
Lifu Tang9363b942016-02-16 18:07:00 -0800244 private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;
Lifu Tang82f893d2016-01-21 18:15:33 -0800245
Siddharth Raybb608c82017-03-16 11:33:34 -0700246 private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;
Wyatt Rileyaa420d52017-07-03 15:14:42 -0700247
248 private GnssLocationProvider.GnssBatchingProvider mGnssBatchingProvider;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800249 private IBatchedLocationCallback mGnssBatchingCallback;
250 private LinkedCallback mGnssBatchingDeathCallback;
251 private boolean mGnssBatchingInProgress = false;
252
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700253 public LocationManagerService(Context context) {
254 super();
255 mContext = context;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800256 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800257
Svet Ganovadc1cf42015-06-15 16:36:24 -0700258 // Let the package manager query which are the default location
259 // providers as they get certain permissions granted by default.
260 PackageManagerInternal packageManagerInternal = LocalServices.getService(
261 PackageManagerInternal.class);
262 packageManagerInternal.setLocationPackagesProvider(
263 new PackageManagerInternal.PackagesProvider() {
264 @Override
265 public String[] getPackages(int userId) {
266 return mContext.getResources().getStringArray(
267 com.android.internal.R.array.config_locationProviderPackageNames);
268 }
269 });
270
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700271 if (D) Log.d(TAG, "Constructed");
272
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700273 // most startup is deferred until systemRunning()
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700274 }
275
Svetoslav Ganova0027152013-06-25 14:59:53 -0700276 public void systemRunning() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700277 synchronized (mLock) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700278 if (D) Log.d(TAG, "systemRunning()");
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700279
Victoria Lease5cd731a2012-12-19 15:04:21 -0800280 // fetch package manager
281 mPackageManager = mContext.getPackageManager();
282
Victoria Lease0aa28602013-05-29 15:28:26 -0700283 // fetch power manager
284 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
Victoria Lease5cd731a2012-12-19 15:04:21 -0800285
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800286 // fetch activity manager
287 mActivityManager
288 = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
289
Victoria Lease5cd731a2012-12-19 15:04:21 -0800290 // prepare worker thread
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700291 mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper());
Victoria Lease5cd731a2012-12-19 15:04:21 -0800292
293 // prepare mLocationHandler's dependents
294 mLocationFudger = new LocationFudger(mContext, mLocationHandler);
295 mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
296 mBlacklist.init();
297 mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
298
Dianne Hackbornc2293022013-02-06 23:14:49 -0800299 // Monitor for app ops mode changes.
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700300 AppOpsManager.OnOpChangedListener callback
301 = new AppOpsManager.OnOpChangedInternalListener() {
302 public void onOpChanged(int op, String packageName) {
Dianne Hackbornc2293022013-02-06 23:14:49 -0800303 synchronized (mLock) {
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700304 for (Receiver receiver : mReceivers.values()) {
305 receiver.updateMonitoring(true);
306 }
Dianne Hackbornc2293022013-02-06 23:14:49 -0800307 applyAllProviderRequirementsLocked();
308 }
309 }
310 };
311 mAppOps.startWatchingMode(AppOpsManager.OP_COARSE_LOCATION, null, callback);
312
David Christieb870dbf2015-06-22 12:42:53 -0700313 PackageManager.OnPermissionsChangedListener permissionListener
314 = new PackageManager.OnPermissionsChangedListener() {
315 @Override
316 public void onPermissionsChanged(final int uid) {
317 synchronized (mLock) {
318 applyAllProviderRequirementsLocked();
319 }
320 }
321 };
322 mPackageManager.addOnPermissionsChangeListener(permissionListener);
323
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800324 // listen for background/foreground changes
325 ActivityManager.OnUidImportanceListener uidImportanceListener
326 = new ActivityManager.OnUidImportanceListener() {
327 @Override
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700328 public void onUidImportance(final int uid, final int importance) {
329 mLocationHandler.post(new Runnable() {
330 @Override
331 public void run() {
332 onUidImportanceChanged(uid, importance);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800333 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700334 });
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800335 }
336 };
337 mActivityManager.addOnUidImportanceListener(uidImportanceListener,
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700338 FOREGROUND_IMPORTANCE_CUTOFF);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800339
Amith Yamasanib27528d2014-06-05 15:02:10 -0700340 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
341 updateUserProfiles(mCurrentUserId);
342
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800343 updateBackgroundThrottlingWhitelistLocked();
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800344
Victoria Lease5cd731a2012-12-19 15:04:21 -0800345 // prepare providers
346 loadProvidersLocked();
347 updateProvidersLocked();
348 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700349
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700350 // listen for settings changes
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700351 mContext.getContentResolver().registerContentObserver(
Laurent Tu75defb62012-11-01 16:21:52 -0700352 Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700353 new ContentObserver(mLocationHandler) {
Victoria Lease5cd731a2012-12-19 15:04:21 -0800354 @Override
355 public void onChange(boolean selfChange) {
356 synchronized (mLock) {
357 updateProvidersLocked();
358 }
359 }
360 }, UserHandle.USER_ALL);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800361 mContext.getContentResolver().registerContentObserver(
362 Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS),
363 true,
364 new ContentObserver(mLocationHandler) {
365 @Override
366 public void onChange(boolean selfChange) {
367 synchronized (mLock) {
368 updateProvidersLocked();
369 }
370 }
371 }, UserHandle.USER_ALL);
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800372 mContext.getContentResolver().registerContentObserver(
373 Settings.Global.getUriFor(
374 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
375 true,
376 new ContentObserver(mLocationHandler) {
377 @Override
378 public void onChange(boolean selfChange) {
379 synchronized (mLock) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800380 updateBackgroundThrottlingWhitelistLocked();
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800381 updateProvidersLocked();
382 }
383 }
384 }, UserHandle.USER_ALL);
Victoria Lease5cd731a2012-12-19 15:04:21 -0800385 mPackageMonitor.register(mContext, mLocationHandler.getLooper(), true);
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700386
Victoria Lease38389b62012-09-30 11:44:22 -0700387 // listen for user change
388 IntentFilter intentFilter = new IntentFilter();
389 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700390 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
391 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
destradaab9026982015-08-27 17:34:54 -0700392 intentFilter.addAction(Intent.ACTION_SHUTDOWN);
Victoria Lease38389b62012-09-30 11:44:22 -0700393
394 mContext.registerReceiverAsUser(new BroadcastReceiver() {
395 @Override
396 public void onReceive(Context context, Intent intent) {
397 String action = intent.getAction();
398 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
399 switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
Amith Yamasanib27528d2014-06-05 15:02:10 -0700400 } else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)
401 || Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
402 updateUserProfiles(mCurrentUserId);
destradaab9026982015-08-27 17:34:54 -0700403 } else if (Intent.ACTION_SHUTDOWN.equals(action)) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700404 // shutdown only if UserId indicates whole system, not just one user
405 if(D) Log.d(TAG, "Shutdown received with UserId: " + getSendingUserId());
406 if (getSendingUserId() == UserHandle.USER_ALL) {
407 shutdownComponents();
408 }
Victoria Lease38389b62012-09-30 11:44:22 -0700409 }
410 }
Victoria Lease5cd731a2012-12-19 15:04:21 -0800411 }, UserHandle.ALL, intentFilter, null, mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700412 }
413
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700414 private void onUidImportanceChanged(int uid, int importance) {
415 boolean foreground = isImportanceForeground(importance);
416 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
417 synchronized (mLock) {
418 for (Entry<String, ArrayList<UpdateRecord>> entry
419 : mRecordsByProvider.entrySet()) {
420 String provider = entry.getKey();
421 for (UpdateRecord record : entry.getValue()) {
422 if (record.mReceiver.mIdentity.mUid == uid
423 && record.mIsForegroundUid != foreground) {
424 if (D) Log.d(TAG, "request from uid " + uid + " is now "
425 + (foreground ? "foreground" : "background)"));
426 record.mIsForegroundUid = foreground;
427
428 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
429 affectedProviders.add(provider);
430 }
431 }
432 }
433 }
434 for (String provider : affectedProviders) {
435 applyRequirementsLocked(provider);
436 }
437
438 for (Entry<IGnssMeasurementsListener, Identity> entry
439 : mGnssMeasurementsListeners.entrySet()) {
440 if (entry.getValue().mUid == uid) {
441 if (D) Log.d(TAG, "gnss measurements listener from uid " + uid
442 + " is now " + (foreground ? "foreground" : "background)"));
443 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
444 mGnssMeasurementsProvider.addListener(entry.getKey());
445 } else {
446 mGnssMeasurementsProvider.removeListener(entry.getKey());
447 }
448 }
449 }
450
451 for (Entry<IGnssNavigationMessageListener, Identity> entry
452 : mGnssNavigationMessageListeners.entrySet()) {
453 if (entry.getValue().mUid == uid) {
454 if (D) Log.d(TAG, "gnss navigation message listener from uid "
455 + uid + " is now "
456 + (foreground ? "foreground" : "background)"));
457 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
458 mGnssNavigationMessageProvider.addListener(entry.getKey());
459 } else {
460 mGnssNavigationMessageProvider.removeListener(entry.getKey());
461 }
462 }
463 }
464 }
465 }
466
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800467 private static boolean isImportanceForeground(int importance) {
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700468 return importance <= FOREGROUND_IMPORTANCE_CUTOFF;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800469 }
470
Amith Yamasanib27528d2014-06-05 15:02:10 -0700471 /**
destradaab9026982015-08-27 17:34:54 -0700472 * Provides a way for components held by the {@link LocationManagerService} to clean-up
473 * gracefully on system's shutdown.
474 *
475 * NOTES:
476 * 1) Only provides a chance to clean-up on an opt-in basis. This guarantees back-compat
477 * support for components that do not wish to handle such event.
478 */
479 private void shutdownComponents() {
480 if(D) Log.d(TAG, "Shutting down components...");
481
482 LocationProviderInterface gpsProvider = mProvidersByName.get(LocationManager.GPS_PROVIDER);
483 if (gpsProvider != null && gpsProvider.isEnabled()) {
484 gpsProvider.disable();
485 }
486
destradaa2e385072015-10-14 16:45:58 -0700487 // it is needed to check if FLP HW provider is supported before accessing the instance, this
488 // avoids an exception to be thrown by the singleton factory method
489 if (FlpHardwareProvider.isSupported()) {
490 FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
destradaab9026982015-08-27 17:34:54 -0700491 flpHardwareProvider.cleanup();
492 }
493 }
494
495 /**
Amith Yamasanib27528d2014-06-05 15:02:10 -0700496 * Makes a list of userids that are related to the current user. This is
497 * relevant when using managed profiles. Otherwise the list only contains
498 * the current user.
499 *
500 * @param currentUserId the current user, who might have an alter-ego.
501 */
502 void updateUserProfiles(int currentUserId) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700503 int[] profileIds = mUserManager.getProfileIdsWithDisabled(currentUserId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700504 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700505 mCurrentUserProfiles = profileIds;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700506 }
507 }
508
509 /**
510 * Checks if the specified userId matches any of the current foreground
511 * users stored in mCurrentUserProfiles.
512 */
513 private boolean isCurrentProfile(int userId) {
514 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700515 return ArrayUtils.contains(mCurrentUserProfiles, userId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700516 }
517 }
518
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500519 private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) {
520 PackageManager pm = mContext.getPackageManager();
521 String systemPackageName = mContext.getPackageName();
522 ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
523
524 List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
525 new Intent(FUSED_LOCATION_SERVICE_ACTION),
526 PackageManager.GET_META_DATA, mCurrentUserId);
527 for (ResolveInfo rInfo : rInfos) {
528 String packageName = rInfo.serviceInfo.packageName;
529
530 // Check that the signature is in the list of supported sigs. If it's not in
531 // this list the standard provider binding logic won't bind to it.
532 try {
533 PackageInfo pInfo;
534 pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
535 if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
536 Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
537 ", but has wrong signature, ignoring");
538 continue;
539 }
540 } catch (NameNotFoundException e) {
541 Log.e(TAG, "missing package: " + packageName);
542 continue;
543 }
544
545 // Get the version info
546 if (rInfo.serviceInfo.metaData == null) {
547 Log.w(TAG, "Found fused provider without metadata: " + packageName);
548 continue;
549 }
550
551 int version = rInfo.serviceInfo.metaData.getInt(
552 ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
553 if (version == 0) {
554 // This should be the fallback fused location provider.
555
556 // Make sure it's in the system partition.
557 if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
558 if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
559 continue;
560 }
561
562 // Check that the fallback is signed the same as the OS
563 // as a proxy for coreApp="true"
564 if (pm.checkSignatures(systemPackageName, packageName)
565 != PackageManager.SIGNATURE_MATCH) {
566 if (D) Log.d(TAG, "Fallback candidate not signed the same as system: "
567 + packageName);
568 continue;
569 }
570
571 // Found a valid fallback.
572 if (D) Log.d(TAG, "Found fallback provider: " + packageName);
573 return;
574 } else {
575 if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
576 }
577 }
578
579 throw new IllegalStateException("Unable to find a fused location provider that is in the "
580 + "system partition with version 0 and signed with the platform certificate. "
581 + "Such a package is needed to provide a default fused location provider in the "
582 + "event that no other fused location provider has been installed or is currently "
583 + "available. For example, coreOnly boot mode when decrypting the data "
584 + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
585 }
586
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700587 private void loadProvidersLocked() {
Victoria Lease5c24fd02012-10-01 11:00:50 -0700588 // create a passive location provider, which is always enabled
589 PassiveProvider passiveProvider = new PassiveProvider(this);
590 addProviderLocked(passiveProvider);
591 mEnabledProviders.add(passiveProvider.getName());
592 mPassiveProvider = passiveProvider;
593
Lifu Tang30f95a72016-01-07 23:20:38 -0800594 if (GnssLocationProvider.isSupported()) {
Wei Liu5241a4c2015-05-11 14:00:36 -0700595 // Create a gps location provider
Lifu Tang30f95a72016-01-07 23:20:38 -0800596 GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this,
Wei Liu5241a4c2015-05-11 14:00:36 -0700597 mLocationHandler.getLooper());
Lifu Tang9363b942016-02-16 18:07:00 -0800598 mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
Wyatt Rileycf879db2017-01-12 13:57:38 -0800599 mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider();
Siddharth Raybb608c82017-03-16 11:33:34 -0700600 mGnssMetricsProvider = gnssProvider.getGnssMetricsProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800601 mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
602 mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
603 addProviderLocked(gnssProvider);
604 mRealProviders.put(LocationManager.GPS_PROVIDER, gnssProvider);
Lifu Tang818aa2c2016-02-01 01:52:00 -0800605 mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
606 mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800607 mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700608 }
609
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700610 /*
611 Load package name(s) containing location provider support.
612 These packages can contain services implementing location providers:
613 Geocoder Provider, Network Location Provider, and
614 Fused Location Provider. They will each be searched for
615 service components implementing these providers.
616 The location framework also has support for installation
617 of new location providers at run-time. The new package does not
618 have to be explicitly listed here, however it must have a signature
619 that matches the signature of at least one package on this list.
620 */
621 Resources resources = mContext.getResources();
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800622 ArrayList<String> providerPackageNames = new ArrayList<>();
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500623 String[] pkgs = resources.getStringArray(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700624 com.android.internal.R.array.config_locationProviderPackageNames);
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500625 if (D) Log.d(TAG, "certificates for location providers pulled from: " +
626 Arrays.toString(pkgs));
627 if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));
628
629 ensureFallbackFusedProviderPresentLocked(providerPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700630
631 // bind to network provider
632 LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
633 mContext,
634 LocationManager.NETWORK_PROVIDER,
635 NETWORK_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700636 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
637 com.android.internal.R.string.config_networkLocationProviderPackageName,
638 com.android.internal.R.array.config_locationProviderPackageNames,
639 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700640 if (networkProvider != null) {
641 mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
642 mProxyProviders.add(networkProvider);
643 addProviderLocked(networkProvider);
644 } else {
645 Slog.w(TAG, "no network location provider found");
646 }
647
648 // bind to fused provider
649 LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind(
650 mContext,
651 LocationManager.FUSED_PROVIDER,
652 FUSED_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700653 com.android.internal.R.bool.config_enableFusedLocationOverlay,
654 com.android.internal.R.string.config_fusedLocationProviderPackageName,
655 com.android.internal.R.array.config_locationProviderPackageNames,
656 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700657 if (fusedLocationProvider != null) {
658 addProviderLocked(fusedLocationProvider);
659 mProxyProviders.add(fusedLocationProvider);
660 mEnabledProviders.add(fusedLocationProvider.getName());
Kenny Rootc3575182012-10-09 12:44:40 -0700661 mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700662 } else {
663 Slog.e(TAG, "no fused location provider found",
664 new IllegalStateException("Location service needs a fused location provider"));
665 }
666
667 // bind to geocoder provider
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700668 mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
669 com.android.internal.R.bool.config_enableGeocoderOverlay,
670 com.android.internal.R.string.config_geocoderProviderPackageName,
671 com.android.internal.R.array.config_locationProviderPackageNames,
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800672 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700673 if (mGeocodeProvider == null) {
674 Slog.e(TAG, "no geocoder provider found");
675 }
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700676
destradaaa4fa3b52014-07-09 10:46:39 -0700677 // bind to fused hardware provider if supported
destradaabeea4422014-07-30 18:17:21 -0700678 // in devices without support, requesting an instance of FlpHardwareProvider will raise an
679 // exception, so make sure we only do that when supported
680 FlpHardwareProvider flpHardwareProvider;
destradaa5ce66d82014-05-28 18:24:08 -0700681 if (FlpHardwareProvider.isSupported()) {
destradaabeea4422014-07-30 18:17:21 -0700682 flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
destradaaf9a274c2014-07-25 15:11:56 -0700683 FusedProxy fusedProxy = FusedProxy.createAndBind(
684 mContext,
685 mLocationHandler,
686 flpHardwareProvider.getLocationHardware(),
687 com.android.internal.R.bool.config_enableHardwareFlpOverlay,
688 com.android.internal.R.string.config_hardwareFlpPackageName,
689 com.android.internal.R.array.config_locationProviderPackageNames);
690 if (fusedProxy == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700691 Slog.d(TAG, "Unable to bind FusedProxy.");
destradaaf9a274c2014-07-25 15:11:56 -0700692 }
destradaacfbdcd22014-04-30 11:29:11 -0700693 } else {
destradaabeea4422014-07-30 18:17:21 -0700694 flpHardwareProvider = null;
destradaa6b4893a2016-05-03 15:33:43 -0700695 Slog.d(TAG, "FLP HAL not supported");
destradaaf9a274c2014-07-25 15:11:56 -0700696 }
697
698 // bind to geofence provider
699 GeofenceProxy provider = GeofenceProxy.createAndBind(
700 mContext,com.android.internal.R.bool.config_enableGeofenceOverlay,
701 com.android.internal.R.string.config_geofenceProviderPackageName,
702 com.android.internal.R.array.config_locationProviderPackageNames,
703 mLocationHandler,
Wei Liu5241a4c2015-05-11 14:00:36 -0700704 mGpsGeofenceProxy,
destradaabeea4422014-07-30 18:17:21 -0700705 flpHardwareProvider != null ? flpHardwareProvider.getGeofenceHardware() : null);
destradaaf9a274c2014-07-25 15:11:56 -0700706 if (provider == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700707 Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
destradaa0682809a2013-08-12 18:50:30 -0700708 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900709
destradaa6e2fe752015-06-23 17:25:53 -0700710 // bind to hardware activity recognition
711 boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
712 ActivityRecognitionHardware activityRecognitionHardware = null;
713 if (activityRecognitionHardwareIsSupported) {
714 activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
destradaaa4fa3b52014-07-09 10:46:39 -0700715 } else {
destradaa6b4893a2016-05-03 15:33:43 -0700716 Slog.d(TAG, "Hardware Activity-Recognition not supported.");
destradaaa4fa3b52014-07-09 10:46:39 -0700717 }
destradaa6e2fe752015-06-23 17:25:53 -0700718 ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
719 mContext,
720 mLocationHandler,
721 activityRecognitionHardwareIsSupported,
722 activityRecognitionHardware,
723 com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
724 com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
725 com.android.internal.R.array.config_locationProviderPackageNames);
726 if (proxy == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700727 Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
destradaa6e2fe752015-06-23 17:25:53 -0700728 }
destradaaa4fa3b52014-07-09 10:46:39 -0700729
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900730 String[] testProviderStrings = resources.getStringArray(
731 com.android.internal.R.array.config_testLocationProviders);
732 for (String testProviderString : testProviderStrings) {
733 String fragments[] = testProviderString.split(",");
734 String name = fragments[0].trim();
735 if (mProvidersByName.get(name) != null) {
736 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
737 }
738 ProviderProperties properties = new ProviderProperties(
739 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
740 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
741 Boolean.parseBoolean(fragments[3]) /* requiresCell */,
742 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
743 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
744 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
745 Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
746 Integer.parseInt(fragments[8]) /* powerRequirement */,
747 Integer.parseInt(fragments[9]) /* accuracy */);
748 addTestProviderLocked(name, properties);
749 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700750 }
Mike Lockwood9637d472009-04-02 21:41:57 -0700751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800752 /**
Victoria Lease38389b62012-09-30 11:44:22 -0700753 * Called when the device's active user changes.
754 * @param userId the new active user's UserId
755 */
756 private void switchUser(int userId) {
Jianzheng Zhoud5c69462013-10-10 14:02:09 +0800757 if (mCurrentUserId == userId) {
758 return;
759 }
Victoria Lease83762d22012-10-03 13:51:17 -0700760 mBlacklist.switchUser(userId);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800761 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED);
Victoria Lease38389b62012-09-30 11:44:22 -0700762 synchronized (mLock) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700763 mLastLocation.clear();
David Christie1b9b7b12013-04-15 15:31:11 -0700764 mLastLocationCoarseInterval.clear();
Victoria Leaseb711d572012-10-02 13:14:11 -0700765 for (LocationProviderInterface p : mProviders) {
Amith Yamasanib27528d2014-06-05 15:02:10 -0700766 updateProviderListenersLocked(p.getName(), false);
Victoria Leaseb711d572012-10-02 13:14:11 -0700767 }
Victoria Lease38389b62012-09-30 11:44:22 -0700768 mCurrentUserId = userId;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700769 updateUserProfiles(userId);
Victoria Leaseb711d572012-10-02 13:14:11 -0700770 updateProvidersLocked();
Victoria Lease38389b62012-09-30 11:44:22 -0700771 }
772 }
773
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800774 private static final class Identity {
775 final int mUid;
776 final int mPid;
777 final String mPackageName;
778
779 Identity(int uid, int pid, String packageName) {
780 mUid = uid;
781 mPid = pid;
782 mPackageName = packageName;
783 }
784 }
785
Victoria Lease38389b62012-09-30 11:44:22 -0700786 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 * A wrapper class holding either an ILocationListener or a PendingIntent to receive
788 * location updates.
789 */
Mike Lockwood48f17512009-04-23 09:12:08 -0700790 private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800791 final Identity mIdentity;
Victoria Lease37425c32012-10-16 16:08:48 -0700792 final int mAllowedResolutionLevel; // resolution level allowed to receiver
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 final ILocationListener mListener;
795 final PendingIntent mPendingIntent;
David Christie82edc9b2013-07-19 11:31:42 -0700796 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
David Christie40e57822013-07-30 11:36:48 -0700797 final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 final Object mKey;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700799
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800800 final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<>();
Nick Pellyf1be6862012-05-15 10:53:42 -0700801
David Christie0b837452013-07-29 16:02:13 -0700802 // True if app ops has started monitoring this receiver for locations.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700803 boolean mOpMonitoring;
David Christie0b837452013-07-29 16:02:13 -0700804 // True if app ops has started monitoring this receiver for high power (gps) locations.
805 boolean mOpHighPowerMonitoring;
Mike Lockwood48f17512009-04-23 09:12:08 -0700806 int mPendingBroadcasts;
Victoria Lease0aa28602013-05-29 15:28:26 -0700807 PowerManager.WakeLock mWakeLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800808
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700809 Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -0700810 String packageName, WorkSource workSource, boolean hideFromAppOps) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800811 mListener = listener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812 mPendingIntent = intent;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700813 if (listener != null) {
814 mKey = listener.asBinder();
815 } else {
816 mKey = intent;
817 }
Victoria Lease37425c32012-10-16 16:08:48 -0700818 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800819 mIdentity = new Identity(uid, pid, packageName);
David Christie82edc9b2013-07-19 11:31:42 -0700820 if (workSource != null && workSource.size() <= 0) {
821 workSource = null;
822 }
823 mWorkSource = workSource;
David Christie40e57822013-07-30 11:36:48 -0700824 mHideFromAppOps = hideFromAppOps;
Victoria Lease0aa28602013-05-29 15:28:26 -0700825
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700826 updateMonitoring(true);
827
Victoria Lease0aa28602013-05-29 15:28:26 -0700828 // construct/configure wakelock
829 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
David Christie82edc9b2013-07-19 11:31:42 -0700830 if (workSource == null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800831 workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -0700832 }
833 mWakeLock.setWorkSource(workSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800834 }
835
836 @Override
837 public boolean equals(Object otherObj) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800838 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800839 }
840
841 @Override
842 public int hashCode() {
843 return mKey.hashCode();
844 }
Mike Lockwood3681f262009-05-12 10:52:03 -0400845
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846 @Override
847 public String toString() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700848 StringBuilder s = new StringBuilder();
849 s.append("Reciever[");
850 s.append(Integer.toHexString(System.identityHashCode(this)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800851 if (mListener != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700852 s.append(" listener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700854 s.append(" intent");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800855 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700856 for (String p : mUpdateRecords.keySet()) {
857 s.append(" ").append(mUpdateRecords.get(p).toString());
858 }
859 s.append("]");
860 return s.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800861 }
862
David Christie15b31912013-08-13 15:54:32 -0700863 /**
864 * Update AppOp monitoring for this receiver.
865 *
866 * @param allow If true receiver is currently active, if false it's been removed.
867 */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700868 public void updateMonitoring(boolean allow) {
David Christie40e57822013-07-30 11:36:48 -0700869 if (mHideFromAppOps) {
870 return;
871 }
872
David Christie15b31912013-08-13 15:54:32 -0700873 boolean requestingLocation = false;
874 boolean requestingHighPowerLocation = false;
875 if (allow) {
876 // See if receiver has any enabled update records. Also note if any update records
877 // are high power (has a high power provider with an interval under a threshold).
878 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
879 if (isAllowedByCurrentUserSettingsLocked(updateRecord.mProvider)) {
880 requestingLocation = true;
881 LocationProviderInterface locationProvider
David Christie2ff96af2014-01-30 16:09:37 -0800882 = mProvidersByName.get(updateRecord.mProvider);
David Christie15b31912013-08-13 15:54:32 -0700883 ProviderProperties properties = locationProvider != null
884 ? locationProvider.getProperties() : null;
885 if (properties != null
886 && properties.mPowerRequirement == Criteria.POWER_HIGH
887 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
888 requestingHighPowerLocation = true;
889 break;
890 }
891 }
892 }
893 }
894
David Christie0b837452013-07-29 16:02:13 -0700895 // First update monitoring of any location request (including high power).
David Christie15b31912013-08-13 15:54:32 -0700896 mOpMonitoring = updateMonitoring(
897 requestingLocation,
898 mOpMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700899 AppOpsManager.OP_MONITOR_LOCATION);
900
901 // Now update monitoring of high power requests only.
David Christiec750c1f2013-08-08 12:56:57 -0700902 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
David Christie15b31912013-08-13 15:54:32 -0700903 mOpHighPowerMonitoring = updateMonitoring(
904 requestingHighPowerLocation,
905 mOpHighPowerMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700906 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
David Christiec750c1f2013-08-08 12:56:57 -0700907 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
David Christie15b31912013-08-13 15:54:32 -0700908 // Send an intent to notify that a high power request has been added/removed.
David Christiec750c1f2013-08-08 12:56:57 -0700909 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
910 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
911 }
David Christie0b837452013-07-29 16:02:13 -0700912 }
913
914 /**
915 * Update AppOps monitoring for a single location request and op type.
916 *
917 * @param allowMonitoring True if monitoring is allowed for this request/op.
918 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
919 * @param op AppOps code for the op to update.
920 * @return True if monitoring is on for this request/op after updating.
921 */
922 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
923 int op) {
924 if (!currentlyMonitoring) {
925 if (allowMonitoring) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800926 return mAppOps.startOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700927 == AppOpsManager.MODE_ALLOWED;
928 }
929 } else {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800930 if (!allowMonitoring
931 || mAppOps.checkOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700932 != AppOpsManager.MODE_ALLOWED) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800933 mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName);
David Christie0b837452013-07-29 16:02:13 -0700934 return false;
935 }
936 }
937
938 return currentlyMonitoring;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700939 }
940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 public boolean isListener() {
942 return mListener != null;
943 }
944
945 public boolean isPendingIntent() {
946 return mPendingIntent != null;
947 }
948
949 public ILocationListener getListener() {
950 if (mListener != null) {
951 return mListener;
952 }
953 throw new IllegalStateException("Request for non-existent listener");
954 }
955
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
957 if (mListener != null) {
958 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700959 synchronized (this) {
960 // synchronize to ensure incrementPendingBroadcastsLocked()
961 // is called before decrementPendingBroadcasts()
962 mListener.onStatusChanged(provider, status, extras);
Nick Pellye0fd6932012-07-11 10:26:13 -0700963 // call this after broadcasting so we do not increment
964 // if we throw an exeption.
965 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -0700966 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967 } catch (RemoteException e) {
968 return false;
969 }
970 } else {
971 Intent statusChanged = new Intent();
Victoria Lease61ecb022012-11-13 15:12:51 -0800972 statusChanged.putExtras(new Bundle(extras));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
974 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700975 synchronized (this) {
976 // synchronize to ensure incrementPendingBroadcastsLocked()
977 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700978 mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -0700979 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -0700980 // call this after broadcasting so we do not increment
981 // if we throw an exeption.
982 incrementPendingBroadcastsLocked();
983 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 } catch (PendingIntent.CanceledException e) {
985 return false;
986 }
987 }
988 return true;
989 }
990
991 public boolean callLocationChangedLocked(Location location) {
992 if (mListener != null) {
993 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700994 synchronized (this) {
995 // synchronize to ensure incrementPendingBroadcastsLocked()
996 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c5406a2012-11-29 16:18:01 -0800997 mListener.onLocationChanged(new Location(location));
Nick Pellye0fd6932012-07-11 10:26:13 -0700998 // call this after broadcasting so we do not increment
999 // if we throw an exeption.
1000 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001001 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001002 } catch (RemoteException e) {
1003 return false;
1004 }
1005 } else {
1006 Intent locationChanged = new Intent();
Victoria Lease61ecb022012-11-13 15:12:51 -08001007 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, new Location(location));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001008 try {
Mike Lockwood48f17512009-04-23 09:12:08 -07001009 synchronized (this) {
1010 // synchronize to ensure incrementPendingBroadcastsLocked()
1011 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001012 mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -07001013 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -07001014 // call this after broadcasting so we do not increment
1015 // if we throw an exeption.
1016 incrementPendingBroadcastsLocked();
1017 }
1018 } catch (PendingIntent.CanceledException e) {
1019 return false;
1020 }
1021 }
1022 return true;
1023 }
1024
1025 public boolean callProviderEnabledLocked(String provider, boolean enabled) {
David Christie15b31912013-08-13 15:54:32 -07001026 // First update AppOp monitoring.
1027 // An app may get/lose location access as providers are enabled/disabled.
1028 updateMonitoring(true);
1029
Mike Lockwood48f17512009-04-23 09:12:08 -07001030 if (mListener != null) {
1031 try {
1032 synchronized (this) {
1033 // synchronize to ensure incrementPendingBroadcastsLocked()
1034 // is called before decrementPendingBroadcasts()
1035 if (enabled) {
1036 mListener.onProviderEnabled(provider);
1037 } else {
1038 mListener.onProviderDisabled(provider);
1039 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001040 // call this after broadcasting so we do not increment
1041 // if we throw an exeption.
1042 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001043 }
1044 } catch (RemoteException e) {
1045 return false;
1046 }
1047 } else {
1048 Intent providerIntent = new Intent();
1049 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1050 try {
1051 synchronized (this) {
1052 // synchronize to ensure incrementPendingBroadcastsLocked()
1053 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001054 mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -07001055 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -07001056 // call this after broadcasting so we do not increment
1057 // if we throw an exeption.
1058 incrementPendingBroadcastsLocked();
1059 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001060 } catch (PendingIntent.CanceledException e) {
1061 return false;
1062 }
1063 }
1064 return true;
1065 }
1066
Nick Pellyf1be6862012-05-15 10:53:42 -07001067 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001068 public void binderDied() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001069 if (D) Log.d(TAG, "Location listener died");
1070
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001071 synchronized (mLock) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 removeUpdatesLocked(this);
1073 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001074 synchronized (this) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001075 clearPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001076 }
1077 }
1078
Nick Pellye0fd6932012-07-11 10:26:13 -07001079 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001080 public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1081 int resultCode, String resultData, Bundle resultExtras) {
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001082 synchronized (this) {
1083 decrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001084 }
1085 }
1086
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001087 // this must be called while synchronized by caller in a synchronized block
1088 // containing the sending of the broadcaset
1089 private void incrementPendingBroadcastsLocked() {
1090 if (mPendingBroadcasts++ == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001091 mWakeLock.acquire();
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001092 }
1093 }
1094
1095 private void decrementPendingBroadcastsLocked() {
1096 if (--mPendingBroadcasts == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001097 if (mWakeLock.isHeld()) {
1098 mWakeLock.release();
1099 }
1100 }
1101 }
1102
1103 public void clearPendingBroadcastsLocked() {
1104 if (mPendingBroadcasts > 0) {
1105 mPendingBroadcasts = 0;
1106 if (mWakeLock.isHeld()) {
1107 mWakeLock.release();
1108 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001109 }
1110 }
1111 }
1112
Nick Pellye0fd6932012-07-11 10:26:13 -07001113 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001114 public void locationCallbackFinished(ILocationListener listener) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001115 //Do not use getReceiverLocked here as that will add the ILocationListener to
Joshua Bartel080b61b2009-10-05 12:44:46 -04001116 //the receiver list if it is not found. If it is not found then the
1117 //LocationListener was removed when it had a pending broadcast and should
1118 //not be added back.
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001119 synchronized (mLock) {
1120 IBinder binder = listener.asBinder();
1121 Receiver receiver = mReceivers.get(binder);
1122 if (receiver != null) {
1123 synchronized (receiver) {
1124 // so wakelock calls will succeed
1125 long identity = Binder.clearCallingIdentity();
1126 receiver.decrementPendingBroadcastsLocked();
1127 Binder.restoreCallingIdentity(identity);
David Christie2ff96af2014-01-30 16:09:37 -08001128 }
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001129 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001130 }
1131 }
1132
Lifu Tang82f893d2016-01-21 18:15:33 -08001133 /**
Lifu Tang9363b942016-02-16 18:07:00 -08001134 * Returns the system information of the GNSS hardware.
Lifu Tang82f893d2016-01-21 18:15:33 -08001135 */
1136 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001137 public int getGnssYearOfHardware() {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001138 if (mGnssSystemInfoProvider != null) {
Lifu Tang9363b942016-02-16 18:07:00 -08001139 return mGnssSystemInfoProvider.getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001140 } else {
1141 return 0;
1142 }
1143 }
1144
Wyatt Rileycf879db2017-01-12 13:57:38 -08001145 /**
1146 * Runs some checks for GNSS (FINE) level permissions, used by several methods which directly
1147 * (try to) access GNSS information at this layer.
1148 */
1149 private boolean hasGnssPermissions(String packageName) {
1150 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
1151 checkResolutionLevelIsSufficientForProviderUse(
1152 allowedResolutionLevel,
1153 LocationManager.GPS_PROVIDER);
1154
1155 int pid = Binder.getCallingPid();
1156 int uid = Binder.getCallingUid();
1157 long identity = Binder.clearCallingIdentity();
1158 boolean hasLocationAccess;
1159 try {
1160 hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
1161 } finally {
1162 Binder.restoreCallingIdentity(identity);
1163 }
1164
1165 return hasLocationAccess;
1166 }
1167
1168 /**
1169 * Returns the GNSS batching size, if available.
1170 */
1171 @Override
1172 public int getGnssBatchSize(String packageName) {
1173 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1174 "Location Hardware permission not granted to access hardware batching");
1175
1176 if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
1177 return mGnssBatchingProvider.getSize();
1178 } else {
1179 return 0;
1180 }
1181 }
1182
1183 /**
1184 * Adds a callback for GNSS Batching events, if permissions allow, which are transported
1185 * to potentially multiple listeners by the BatchedLocationCallbackTransport above this.
1186 */
1187 @Override
1188 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) {
1189 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1190 "Location Hardware permission not granted to access hardware batching");
1191
1192 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1193 return false;
1194 }
1195
1196 mGnssBatchingCallback = callback;
1197 mGnssBatchingDeathCallback = new LinkedCallback(callback);
1198 try {
1199 callback.asBinder().linkToDeath(mGnssBatchingDeathCallback, 0 /* flags */);
1200 } catch (RemoteException e) {
1201 // if the remote process registering the listener is already dead, just swallow the
1202 // exception and return
1203 Log.e(TAG, "Remote listener already died.", e);
1204 return false;
1205 }
1206
1207 return true;
1208 }
1209
1210 private class LinkedCallback implements IBinder.DeathRecipient {
1211 private final IBatchedLocationCallback mCallback;
1212
1213 public LinkedCallback(@NonNull IBatchedLocationCallback callback) {
1214 mCallback = callback;
1215 }
1216
1217 @NonNull
1218 public IBatchedLocationCallback getUnderlyingListener() {
1219 return mCallback;
1220 }
1221
1222 @Override
1223 public void binderDied() {
1224 Log.d(TAG, "Remote Batching Callback died: " + mCallback);
1225 stopGnssBatch();
1226 removeGnssBatchingCallback();
1227 }
1228 }
1229
1230 /**
1231 * Removes callback for GNSS batching
1232 */
1233 @Override
1234 public void removeGnssBatchingCallback() {
1235 try {
1236 mGnssBatchingCallback.asBinder().unlinkToDeath(mGnssBatchingDeathCallback,
1237 0 /* flags */);
1238 } catch (NoSuchElementException e) {
1239 // if the death callback isn't connected (it should be...), log error, swallow the
1240 // exception and return
1241 Log.e(TAG, "Couldn't unlink death callback.", e);
1242 }
1243 mGnssBatchingCallback = null;
1244 mGnssBatchingDeathCallback = null;
1245 }
1246
1247
1248 /**
1249 * Starts GNSS batching, if available.
1250 */
1251 @Override
1252 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
1253 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1254 "Location Hardware permission not granted to access hardware batching");
1255
1256 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1257 return false;
1258 }
1259
1260 if (mGnssBatchingInProgress) {
1261 // Current design does not expect multiple starts to be called repeatedly
1262 Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch");
1263 // Try to clean up anyway, and continue
1264 stopGnssBatch();
1265 }
1266
1267 mGnssBatchingInProgress = true;
1268 return mGnssBatchingProvider.start(periodNanos, wakeOnFifoFull);
1269 }
1270
1271 /**
1272 * Flushes a GNSS batch in progress
1273 */
1274 @Override
1275 public void flushGnssBatch(String packageName) {
1276 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1277 "Location Hardware permission not granted to access hardware batching");
1278
1279 if (!hasGnssPermissions(packageName)) {
1280 Log.e(TAG, "flushGnssBatch called without GNSS permissions");
1281 return;
1282 }
1283
1284 if (!mGnssBatchingInProgress) {
1285 Log.w(TAG, "flushGnssBatch called with no batch in progress");
1286 }
1287
1288 if (mGnssBatchingProvider != null) {
1289 mGnssBatchingProvider.flush();
1290 }
1291 }
1292
1293 /**
1294 * Stops GNSS batching
1295 */
1296 @Override
1297 public boolean stopGnssBatch() {
1298 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1299 "Location Hardware permission not granted to access hardware batching");
1300
1301 if (mGnssBatchingProvider != null) {
1302 mGnssBatchingInProgress = false;
1303 return mGnssBatchingProvider.stop();
1304 } else {
1305 return false;
1306 }
1307 }
1308
1309 @Override
1310 public void reportLocationBatch(List<Location> locations) {
1311 checkCallerIsProvider();
1312
1313 // Currently used only for GNSS locations - update permissions check if changed
1314 if (isAllowedByCurrentUserSettingsLocked(LocationManager.GPS_PROVIDER)) {
1315 if (mGnssBatchingCallback == null) {
1316 Slog.e(TAG, "reportLocationBatch() called without active Callback");
1317 return;
1318 }
1319 try {
1320 mGnssBatchingCallback.onLocationBatch(locations);
1321 } catch (RemoteException e) {
1322 Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e);
1323 }
1324 } else {
1325 Slog.w(TAG, "reportLocationBatch() called without user permission, locations blocked");
1326 }
1327 }
1328
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001329 private void addProviderLocked(LocationProviderInterface provider) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001330 mProviders.add(provider);
1331 mProvidersByName.put(provider.getName(), provider);
1332 }
1333
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001334 private void removeProviderLocked(LocationProviderInterface provider) {
1335 provider.disable();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001336 mProviders.remove(provider);
1337 mProvidersByName.remove(provider.getName());
1338 }
1339
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001340 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001341 * Returns "true" if access to the specified location provider is allowed by the current
1342 * user's settings. Access to all location providers is forbidden to non-location-provider
1343 * processes belonging to background users.
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001344 *
1345 * @param provider the name of the location provider
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001346 */
Victoria Lease09eeaec2013-02-05 11:34:13 -08001347 private boolean isAllowedByCurrentUserSettingsLocked(String provider) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348 if (mEnabledProviders.contains(provider)) {
1349 return true;
1350 }
1351 if (mDisabledProviders.contains(provider)) {
1352 return false;
1353 }
1354 // Use system settings
1355 ContentResolver resolver = mContext.getContentResolver();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001356
Victoria Leaseb711d572012-10-02 13:14:11 -07001357 return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358 }
1359
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001360 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001361 * Returns "true" if access to the specified location provider is allowed by the specified
1362 * user's settings. Access to all location providers is forbidden to non-location-provider
1363 * processes belonging to background users.
1364 *
1365 * @param provider the name of the location provider
1366 * @param uid the requestor's UID
Victoria Lease09eeaec2013-02-05 11:34:13 -08001367 */
1368 private boolean isAllowedByUserSettingsLocked(String provider, int uid) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001369 if (!isCurrentProfile(UserHandle.getUserId(uid)) && !isUidALocationProvider(uid)) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08001370 return false;
1371 }
1372 return isAllowedByCurrentUserSettingsLocked(provider);
1373 }
1374
1375 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001376 * Returns the permission string associated with the specified resolution level.
1377 *
1378 * @param resolutionLevel the resolution level
1379 * @return the permission string
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001380 */
Victoria Lease37425c32012-10-16 16:08:48 -07001381 private String getResolutionPermission(int resolutionLevel) {
1382 switch (resolutionLevel) {
1383 case RESOLUTION_LEVEL_FINE:
1384 return android.Manifest.permission.ACCESS_FINE_LOCATION;
1385 case RESOLUTION_LEVEL_COARSE:
1386 return android.Manifest.permission.ACCESS_COARSE_LOCATION;
1387 default:
1388 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 }
Victoria Leaseda479c52012-10-15 15:24:16 -07001390 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001391
Victoria Leaseda479c52012-10-15 15:24:16 -07001392 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001393 * Returns the resolution level allowed to the given PID/UID pair.
1394 *
1395 * @param pid the PID
1396 * @param uid the UID
1397 * @return resolution level allowed to the pid/uid pair
Victoria Leaseda479c52012-10-15 15:24:16 -07001398 */
Victoria Lease37425c32012-10-16 16:08:48 -07001399 private int getAllowedResolutionLevel(int pid, int uid) {
1400 if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
1401 pid, uid) == PackageManager.PERMISSION_GRANTED) {
1402 return RESOLUTION_LEVEL_FINE;
1403 } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
1404 pid, uid) == PackageManager.PERMISSION_GRANTED) {
1405 return RESOLUTION_LEVEL_COARSE;
1406 } else {
1407 return RESOLUTION_LEVEL_NONE;
Victoria Leaseda479c52012-10-15 15:24:16 -07001408 }
Victoria Lease4fab68b2012-09-13 13:20:59 -07001409 }
1410
1411 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001412 * Returns the resolution level allowed to the caller
1413 *
1414 * @return resolution level allowed to caller
Victoria Lease4fab68b2012-09-13 13:20:59 -07001415 */
Victoria Lease37425c32012-10-16 16:08:48 -07001416 private int getCallerAllowedResolutionLevel() {
1417 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
1418 }
1419
1420 /**
1421 * Throw SecurityException if specified resolution level is insufficient to use geofences.
1422 *
1423 * @param allowedResolutionLevel resolution level allowed to caller
1424 */
1425 private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
1426 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Lease4fab68b2012-09-13 13:20:59 -07001427 throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
1428 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001429 }
1430
Victoria Lease37425c32012-10-16 16:08:48 -07001431 /**
1432 * Return the minimum resolution level required to use the specified location provider.
1433 *
1434 * @param provider the name of the location provider
1435 * @return minimum resolution level required for provider
1436 */
1437 private int getMinimumResolutionLevelForProviderUse(String provider) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001438 if (LocationManager.GPS_PROVIDER.equals(provider) ||
1439 LocationManager.PASSIVE_PROVIDER.equals(provider)) {
1440 // gps and passive providers require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001441 return RESOLUTION_LEVEL_FINE;
Victoria Lease8dbb6342012-09-21 16:55:53 -07001442 } else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
1443 LocationManager.FUSED_PROVIDER.equals(provider)) {
1444 // network and fused providers are ok with COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001445 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001446 } else {
1447 // mock providers
1448 LocationProviderInterface lp = mMockProviders.get(provider);
1449 if (lp != null) {
1450 ProviderProperties properties = lp.getProperties();
1451 if (properties != null) {
1452 if (properties.mRequiresSatellite) {
1453 // provider requiring satellites require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001454 return RESOLUTION_LEVEL_FINE;
Laurent Tu941221c2012-10-04 14:21:52 -07001455 } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
1456 // provider requiring network and or cell require COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001457 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001458 }
1459 }
1460 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001461 }
Victoria Lease37425c32012-10-16 16:08:48 -07001462 return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
Victoria Leaseda479c52012-10-15 15:24:16 -07001463 }
1464
Victoria Lease37425c32012-10-16 16:08:48 -07001465 /**
1466 * Throw SecurityException if specified resolution level is insufficient to use the named
1467 * location provider.
1468 *
1469 * @param allowedResolutionLevel resolution level allowed to caller
1470 * @param providerName the name of the location provider
1471 */
1472 private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel,
1473 String providerName) {
1474 int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName);
1475 if (allowedResolutionLevel < requiredResolutionLevel) {
1476 switch (requiredResolutionLevel) {
1477 case RESOLUTION_LEVEL_FINE:
1478 throw new SecurityException("\"" + providerName + "\" location provider " +
1479 "requires ACCESS_FINE_LOCATION permission.");
1480 case RESOLUTION_LEVEL_COARSE:
1481 throw new SecurityException("\"" + providerName + "\" location provider " +
1482 "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
1483 default:
1484 throw new SecurityException("Insufficient permission for \"" + providerName +
1485 "\" location provider.");
Victoria Leaseda479c52012-10-15 15:24:16 -07001486 }
1487 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001488 }
1489
David Christie82edc9b2013-07-19 11:31:42 -07001490 /**
1491 * Throw SecurityException if WorkSource use is not allowed (i.e. can't blame other packages
1492 * for battery).
1493 */
David Christie40e57822013-07-30 11:36:48 -07001494 private void checkDeviceStatsAllowed() {
David Christie82edc9b2013-07-19 11:31:42 -07001495 mContext.enforceCallingOrSelfPermission(
1496 android.Manifest.permission.UPDATE_DEVICE_STATS, null);
1497 }
1498
David Christie40e57822013-07-30 11:36:48 -07001499 private void checkUpdateAppOpsAllowed() {
1500 mContext.enforceCallingOrSelfPermission(
1501 android.Manifest.permission.UPDATE_APP_OPS_STATS, null);
1502 }
1503
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001504 public static int resolutionLevelToOp(int allowedResolutionLevel) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001505 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
1506 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001507 return AppOpsManager.OP_COARSE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001508 } else {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001509 return AppOpsManager.OP_FINE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001510 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001511 }
1512 return -1;
1513 }
1514
David Christieb870dbf2015-06-22 12:42:53 -07001515 boolean reportLocationAccessNoThrow(
1516 int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001517 int op = resolutionLevelToOp(allowedResolutionLevel);
1518 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001519 if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1520 return false;
1521 }
1522 }
David Christieb870dbf2015-06-22 12:42:53 -07001523
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001524 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001525 }
1526
David Christieb870dbf2015-06-22 12:42:53 -07001527 boolean checkLocationAccess(int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001528 int op = resolutionLevelToOp(allowedResolutionLevel);
1529 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001530 if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1531 return false;
1532 }
1533 }
David Christieb870dbf2015-06-22 12:42:53 -07001534
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001535 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001536 }
1537
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001538 /**
1539 * Returns all providers by name, including passive, but excluding
Laurent Tu0d21e212012-10-02 15:33:48 -07001540 * fused, also including ones that are not permitted to
1541 * be accessed by the calling activity or are currently disabled.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001542 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001543 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001544 public List<String> getAllProviders() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001545 ArrayList<String> out;
1546 synchronized (mLock) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001547 out = new ArrayList<>(mProviders.size());
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001548 for (LocationProviderInterface provider : mProviders) {
1549 String name = provider.getName();
1550 if (LocationManager.FUSED_PROVIDER.equals(name)) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07001551 continue;
1552 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 out.add(name);
1554 }
1555 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001556
1557 if (D) Log.d(TAG, "getAllProviders()=" + out);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 return out;
1559 }
1560
Mike Lockwood03ca2162010-04-01 08:10:09 -07001561 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001562 * Return all providers by name, that match criteria and are optionally
1563 * enabled.
1564 * Can return passive provider, but never returns fused provider.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001565 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001566 @Override
1567 public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
Victoria Lease37425c32012-10-16 16:08:48 -07001568 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001569 ArrayList<String> out;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001570 int uid = Binder.getCallingUid();
Victoria Lease269518e2012-10-29 08:25:39 -07001571 long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07001572 try {
1573 synchronized (mLock) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001574 out = new ArrayList<>(mProviders.size());
Victoria Leaseb711d572012-10-02 13:14:11 -07001575 for (LocationProviderInterface provider : mProviders) {
1576 String name = provider.getName();
1577 if (LocationManager.FUSED_PROVIDER.equals(name)) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001578 continue;
1579 }
Victoria Lease37425c32012-10-16 16:08:48 -07001580 if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08001581 if (enabledOnly && !isAllowedByUserSettingsLocked(name, uid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001582 continue;
1583 }
1584 if (criteria != null && !LocationProvider.propertiesMeetCriteria(
1585 name, provider.getProperties(), criteria)) {
1586 continue;
1587 }
1588 out.add(name);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001589 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001590 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001591 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001592 } finally {
1593 Binder.restoreCallingIdentity(identity);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001594 }
1595
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001596 if (D) Log.d(TAG, "getProviders()=" + out);
1597 return out;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001598 }
1599
1600 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001601 * Return the name of the best provider given a Criteria object.
1602 * This method has been deprecated from the public API,
Victoria Lease8dbb6342012-09-21 16:55:53 -07001603 * and the whole LocationProvider (including #meetsCriteria)
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001604 * has been deprecated as well. So this method now uses
1605 * some simplified logic.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001606 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001607 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001608 public String getBestProvider(Criteria criteria, boolean enabledOnly) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001609 String result = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001610
1611 List<String> providers = getProviders(criteria, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001612 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001613 result = pickBest(providers);
1614 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1615 return result;
1616 }
1617 providers = getProviders(null, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001618 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001619 result = pickBest(providers);
1620 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1621 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001622 }
1623
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001624 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001625 return null;
1626 }
1627
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001628 private String pickBest(List<String> providers) {
Victoria Lease1925e292012-09-24 17:00:18 -07001629 if (providers.contains(LocationManager.GPS_PROVIDER)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001630 return LocationManager.GPS_PROVIDER;
Victoria Lease1925e292012-09-24 17:00:18 -07001631 } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
1632 return LocationManager.NETWORK_PROVIDER;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001633 } else {
1634 return providers.get(0);
1635 }
1636 }
1637
Nick Pellye0fd6932012-07-11 10:26:13 -07001638 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001639 public boolean providerMeetsCriteria(String provider, Criteria criteria) {
1640 LocationProviderInterface p = mProvidersByName.get(provider);
1641 if (p == null) {
1642 throw new IllegalArgumentException("provider=" + provider);
1643 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001644
1645 boolean result = LocationProvider.propertiesMeetCriteria(
1646 p.getName(), p.getProperties(), criteria);
1647 if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result);
1648 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001649 }
1650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001651 private void updateProvidersLocked() {
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001652 boolean changesMade = false;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001653 for (int i = mProviders.size() - 1; i >= 0; i--) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001654 LocationProviderInterface p = mProviders.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001655 boolean isEnabled = p.isEnabled();
1656 String name = p.getName();
Victoria Lease09eeaec2013-02-05 11:34:13 -08001657 boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001658 if (isEnabled && !shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001659 updateProviderListenersLocked(name, false);
David Christieb084fef2013-12-18 14:33:57 -08001660 // If any provider has been disabled, clear all last locations for all providers.
1661 // This is to be on the safe side in case a provider has location derived from
1662 // this disabled provider.
1663 mLastLocation.clear();
1664 mLastLocationCoarseInterval.clear();
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001665 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001666 } else if (!isEnabled && shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001667 updateProviderListenersLocked(name, true);
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001668 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001669 }
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001670 }
1671 if (changesMade) {
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001672 mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
1673 UserHandle.ALL);
Tom O'Neill40a86c22013-09-03 18:05:13 -07001674 mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
1675 UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001676 }
1677 }
1678
Amith Yamasanib27528d2014-06-05 15:02:10 -07001679 private void updateProviderListenersLocked(String provider, boolean enabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001680 int listeners = 0;
1681
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001682 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001683 if (p == null) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684
1685 ArrayList<Receiver> deadReceivers = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07001686
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1688 if (records != null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001689 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001690 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001691 // Sends a notification message to the receiver
1692 if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
1693 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001694 deadReceivers = new ArrayList<>();
Victoria Leaseb711d572012-10-02 13:14:11 -07001695 }
1696 deadReceivers.add(record.mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001697 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001698 listeners++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001700 }
1701 }
1702
1703 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001704 for (int i = deadReceivers.size() - 1; i >= 0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001705 removeUpdatesLocked(deadReceivers.get(i));
1706 }
1707 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 if (enabled) {
1710 p.enable();
1711 if (listeners > 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001712 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 }
1714 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001715 p.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001716 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001717 }
1718
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001719 private void applyRequirementsLocked(String provider) {
1720 LocationProviderInterface p = mProvidersByName.get(provider);
1721 if (p == null) return;
1722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001723 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001724 WorkSource worksource = new WorkSource();
1725 ProviderRequest providerRequest = new ProviderRequest();
1726
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001727 ContentResolver resolver = mContext.getContentResolver();
1728 long backgroundThrottleInterval = Settings.Global.getLong(
1729 resolver,
1730 Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
1731 DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
1732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001733 if (records != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001734 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001735 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
David Christieb870dbf2015-06-22 12:42:53 -07001736 if (checkLocationAccess(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001737 record.mReceiver.mIdentity.mPid,
1738 record.mReceiver.mIdentity.mUid,
1739 record.mReceiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001740 record.mReceiver.mAllowedResolutionLevel)) {
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001741 LocationRequest locationRequest = record.mRealRequest;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001742 long interval = locationRequest.getInterval();
1743
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001744 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001745 if (!record.mIsForegroundUid) {
1746 interval = Math.max(interval, backgroundThrottleInterval);
1747 }
1748 if (interval != locationRequest.getInterval()) {
1749 locationRequest = new LocationRequest(locationRequest);
1750 locationRequest.setInterval(interval);
1751 }
1752 }
1753
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001754 record.mRequest = locationRequest;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001755 providerRequest.locationRequests.add(locationRequest);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001756 if (interval < providerRequest.interval) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001757 providerRequest.reportLocation = true;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001758 providerRequest.interval = interval;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001759 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001760 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001761 }
1762 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001763
1764 if (providerRequest.reportLocation) {
1765 // calculate who to blame for power
1766 // This is somewhat arbitrary. We pick a threshold interval
1767 // that is slightly higher that the minimum interval, and
1768 // spread the blame across all applications with a request
1769 // under that threshold.
1770 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
1771 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001772 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001773 LocationRequest locationRequest = record.mRequest;
Svet Ganove998c732016-06-10 00:12:38 -07001774
1775 // Don't assign battery blame for update records whose
1776 // client has no permission to receive location data.
1777 if (!providerRequest.locationRequests.contains(locationRequest)) {
1778 continue;
1779 }
1780
Victoria Leaseb711d572012-10-02 13:14:11 -07001781 if (locationRequest.getInterval() <= thresholdInterval) {
David Christiee55c9682013-08-22 10:10:34 -07001782 if (record.mReceiver.mWorkSource != null
1783 && record.mReceiver.mWorkSource.size() > 0
1784 && record.mReceiver.mWorkSource.getName(0) != null) {
David Christie82edc9b2013-07-19 11:31:42 -07001785 // Assign blame to another work source.
David Christiee55c9682013-08-22 10:10:34 -07001786 // Can only assign blame if the WorkSource contains names.
David Christie82edc9b2013-07-19 11:31:42 -07001787 worksource.add(record.mReceiver.mWorkSource);
1788 } else {
1789 // Assign blame to caller.
1790 worksource.add(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001791 record.mReceiver.mIdentity.mUid,
1792 record.mReceiver.mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001793 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001794 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001795 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001796 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797 }
1798 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001799
1800 if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
1801 p.setRequest(providerRequest, worksource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001802 }
1803
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001804 @Override
1805 public String[] getBackgroundThrottlingWhitelist() {
1806 synchronized (mLock) {
1807 return mBackgroundThrottlePackageWhitelist.toArray(
1808 new String[mBackgroundThrottlePackageWhitelist.size()]);
1809 }
1810 }
1811
1812 private void updateBackgroundThrottlingWhitelistLocked() {
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001813 String setting = Settings.Global.getString(
1814 mContext.getContentResolver(),
1815 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
1816 if (setting == null) {
1817 setting = "";
1818 }
1819
1820 mBackgroundThrottlePackageWhitelist.clear();
1821 mBackgroundThrottlePackageWhitelist.addAll(
1822 SystemConfig.getInstance().getAllowUnthrottledLocation());
1823 mBackgroundThrottlePackageWhitelist.addAll(
1824 Arrays.asList(setting.split(",")));
1825 }
1826
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001827 private boolean isThrottlingExemptLocked(Identity identity) {
1828 if (identity.mUid == Process.SYSTEM_UID) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001829 return true;
1830 }
1831
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001832 if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001833 return true;
1834 }
1835
1836 for (LocationProviderProxy provider : mProxyProviders) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001837 if (identity.mPackageName.equals(provider.getConnectedPackageName())) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001838 return true;
1839 }
1840 }
1841
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001842 return false;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001843 }
1844
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001845 private class UpdateRecord {
1846 final String mProvider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001847 final LocationRequest mRealRequest; // original request from client
1848 LocationRequest mRequest; // possibly throttled version of the request
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001849 final Receiver mReceiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001850 boolean mIsForegroundUid;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001851 Location mLastFixBroadcast;
1852 long mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853
1854 /**
1855 * Note: must be constructed with lock held.
1856 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001857 UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001858 mProvider = provider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001859 mRealRequest = request;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001860 mRequest = request;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001861 mReceiver = receiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001862 mIsForegroundUid = isImportanceForeground(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001863 mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001864
1865 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1866 if (records == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001867 records = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001868 mRecordsByProvider.put(provider, records);
1869 }
1870 if (!records.contains(this)) {
1871 records.add(this);
1872 }
David Christie2ff96af2014-01-30 16:09:37 -08001873
1874 // Update statistics for historical location requests by package/provider
1875 mRequestStatistics.startRequesting(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001876 mReceiver.mIdentity.mPackageName, provider, request.getInterval());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001877 }
1878
1879 /**
David Christie2ff96af2014-01-30 16:09:37 -08001880 * Method to be called when a record will no longer be used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001881 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001882 void disposeLocked(boolean removeReceiver) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001883 mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider);
David Christie2ff96af2014-01-30 16:09:37 -08001884
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001885 // remove from mRecordsByProvider
1886 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
1887 if (globalRecords != null) {
1888 globalRecords.remove(this);
1889 }
1890
1891 if (!removeReceiver) return; // the caller will handle the rest
1892
1893 // remove from Receiver#mUpdateRecords
1894 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
1895 if (receiverRecords != null) {
1896 receiverRecords.remove(this.mProvider);
1897
1898 // and also remove the Receiver if it has no more update records
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001899 if (receiverRecords.size() == 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001900 removeUpdatesLocked(mReceiver);
1901 }
Mike Lockwood3a76fd62009-09-01 07:26:56 -04001902 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001903 }
1904
1905 @Override
1906 public String toString() {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001907 return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
1908 + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground" : " background")
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001909 + ")" + " " + mRealRequest + "]";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001910 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001911 }
1912
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001913 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -07001914 String packageName, WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001915 IBinder binder = listener.asBinder();
1916 Receiver receiver = mReceivers.get(binder);
1917 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07001918 receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
1919 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001920 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001921 receiver.getListener().asBinder().linkToDeath(receiver, 0);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001922 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001923 Slog.e(TAG, "linkToDeath failed:", e);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001924 return null;
1925 }
Wen Jingcb3ab222014-03-27 13:42:59 +08001926 mReceivers.put(binder, receiver);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001927 }
1928 return receiver;
1929 }
1930
David Christie82edc9b2013-07-19 11:31:42 -07001931 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
David Christie40e57822013-07-30 11:36:48 -07001932 WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001933 Receiver receiver = mReceivers.get(intent);
1934 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07001935 receiver = new Receiver(null, intent, pid, uid, packageName, workSource,
1936 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001937 mReceivers.put(intent, receiver);
1938 }
1939 return receiver;
1940 }
1941
Victoria Lease37425c32012-10-16 16:08:48 -07001942 /**
1943 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
1944 * and consistency requirements.
1945 *
1946 * @param request the LocationRequest from which to create a sanitized version
Victoria Lease37425c32012-10-16 16:08:48 -07001947 * @return a version of request that meets the given resolution and consistency requirements
1948 * @hide
1949 */
1950 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel) {
1951 LocationRequest sanitizedRequest = new LocationRequest(request);
1952 if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
1953 switch (sanitizedRequest.getQuality()) {
Victoria Lease09016ab2012-09-16 12:33:15 -07001954 case LocationRequest.ACCURACY_FINE:
Victoria Lease37425c32012-10-16 16:08:48 -07001955 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
Victoria Lease09016ab2012-09-16 12:33:15 -07001956 break;
1957 case LocationRequest.POWER_HIGH:
Victoria Lease37425c32012-10-16 16:08:48 -07001958 sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
Victoria Lease09016ab2012-09-16 12:33:15 -07001959 break;
1960 }
1961 // throttle
Victoria Lease37425c32012-10-16 16:08:48 -07001962 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1963 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001964 }
Victoria Lease37425c32012-10-16 16:08:48 -07001965 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1966 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001967 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07001968 }
Nick Pelly4e31c4f2012-08-13 19:35:39 -07001969 // make getFastestInterval() the minimum of interval and fastest interval
Victoria Lease37425c32012-10-16 16:08:48 -07001970 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07001971 request.setFastestInterval(request.getInterval());
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001972 }
Victoria Lease37425c32012-10-16 16:08:48 -07001973 return sanitizedRequest;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001974 }
1975
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001976 private void checkPackageName(String packageName) {
Nick Pellye0fd6932012-07-11 10:26:13 -07001977 if (packageName == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001978 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07001979 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001980 int uid = Binder.getCallingUid();
Nick Pellye0fd6932012-07-11 10:26:13 -07001981 String[] packages = mPackageManager.getPackagesForUid(uid);
1982 if (packages == null) {
1983 throw new SecurityException("invalid UID " + uid);
1984 }
1985 for (String pkg : packages) {
1986 if (packageName.equals(pkg)) return;
1987 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001988 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07001989 }
1990
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001991 private void checkPendingIntent(PendingIntent intent) {
1992 if (intent == null) {
1993 throw new IllegalArgumentException("invalid pending intent: " + intent);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001994 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001995 }
1996
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001997 private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent,
David Christie40e57822013-07-30 11:36:48 -07001998 int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001999 if (intent == null && listener == null) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002000 throw new IllegalArgumentException("need either listener or intent");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002001 } else if (intent != null && listener != null) {
2002 throw new IllegalArgumentException("cannot register both listener and intent");
2003 } else if (intent != null) {
2004 checkPendingIntent(intent);
David Christie40e57822013-07-30 11:36:48 -07002005 return getReceiverLocked(intent, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002006 } else {
David Christie40e57822013-07-30 11:36:48 -07002007 return getReceiverLocked(listener, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002008 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002009 }
2010
Nick Pellye0fd6932012-07-11 10:26:13 -07002011 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002012 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
2013 PendingIntent intent, String packageName) {
2014 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2015 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002016 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2017 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2018 request.getProvider());
David Christie82edc9b2013-07-19 11:31:42 -07002019 WorkSource workSource = request.getWorkSource();
2020 if (workSource != null && workSource.size() > 0) {
David Christie40e57822013-07-30 11:36:48 -07002021 checkDeviceStatsAllowed();
2022 }
2023 boolean hideFromAppOps = request.getHideFromAppOps();
2024 if (hideFromAppOps) {
2025 checkUpdateAppOpsAllowed();
David Christie82edc9b2013-07-19 11:31:42 -07002026 }
Victoria Lease37425c32012-10-16 16:08:48 -07002027 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002028
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002029 final int pid = Binder.getCallingPid();
2030 final int uid = Binder.getCallingUid();
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002031 // providers may use public location API's, need to clear identity
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002032 long identity = Binder.clearCallingIdentity();
2033 try {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002034 // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2035 // a location.
David Christieb870dbf2015-06-22 12:42:53 -07002036 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002037
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002038 synchronized (mLock) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002039 Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
David Christie40e57822013-07-30 11:36:48 -07002040 packageName, workSource, hideFromAppOps);
Victoria Lease37425c32012-10-16 16:08:48 -07002041 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
Mike Lockwood2d4d1bf2010-10-18 17:06:26 -04002042 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002043 } finally {
2044 Binder.restoreCallingIdentity(identity);
2045 }
2046 }
2047
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002048 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
2049 int pid, int uid, String packageName) {
2050 // Figure out the provider. Either its explicitly request (legacy use cases), or
2051 // use the fused provider
2052 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2053 String name = request.getProvider();
Victoria Lease09016ab2012-09-16 12:33:15 -07002054 if (name == null) {
2055 throw new IllegalArgumentException("provider name must not be null");
2056 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -07002057
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002058 LocationProviderInterface provider = mProvidersByName.get(name);
2059 if (provider == null) {
Victoria Leaseb30f3832013-10-13 12:15:40 -07002060 throw new IllegalArgumentException("provider doesn't exist: " + name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002061 }
2062
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002063 UpdateRecord record = new UpdateRecord(name, request, receiver);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002064 if (D) Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
2065 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
2066 + (record.mIsForegroundUid ? "foreground" : "background")
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002067 + (isThrottlingExemptLocked(receiver.mIdentity)
2068 ? " [whitelisted]" : "") + ")");
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002069
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002070 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
2071 if (oldRecord != null) {
2072 oldRecord.disposeLocked(false);
2073 }
2074
Victoria Lease09eeaec2013-02-05 11:34:13 -08002075 boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002076 if (isProviderEnabled) {
2077 applyRequirementsLocked(name);
2078 } else {
2079 // Notify the listener that updates are currently disabled
2080 receiver.callProviderEnabledLocked(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002081 }
David Christie0b837452013-07-29 16:02:13 -07002082 // Update the monitoring here just in case multiple location requests were added to the
2083 // same receiver (this request may be high power and the initial might not have been).
2084 receiver.updateMonitoring(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002085 }
2086
Nick Pellye0fd6932012-07-11 10:26:13 -07002087 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002088 public void removeUpdates(ILocationListener listener, PendingIntent intent,
2089 String packageName) {
2090 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002091
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002092 final int pid = Binder.getCallingPid();
2093 final int uid = Binder.getCallingUid();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002094
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002095 synchronized (mLock) {
David Christie82edc9b2013-07-19 11:31:42 -07002096 WorkSource workSource = null;
David Christie40e57822013-07-30 11:36:48 -07002097 boolean hideFromAppOps = false;
2098 Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid,
2099 packageName, workSource, hideFromAppOps);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002100
2101 // providers may use public location API's, need to clear identity
2102 long identity = Binder.clearCallingIdentity();
2103 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002104 removeUpdatesLocked(receiver);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002105 } finally {
2106 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002107 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002108 }
2109 }
2110
2111 private void removeUpdatesLocked(Receiver receiver) {
Dianne Hackborn7ff30112012-11-08 11:12:09 -08002112 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002113
2114 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
2115 receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
2116 synchronized (receiver) {
Victoria Lease0aa28602013-05-29 15:28:26 -07002117 receiver.clearPendingBroadcastsLocked();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002118 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002119 }
2120
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07002121 receiver.updateMonitoring(false);
2122
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002123 // Record which providers were associated with this listener
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002124 HashSet<String> providers = new HashSet<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002125 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2126 if (oldRecords != null) {
2127 // Call dispose() on the obsolete update records.
2128 for (UpdateRecord record : oldRecords.values()) {
David Christie2ff96af2014-01-30 16:09:37 -08002129 // Update statistics for historical location requests by package/provider
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002130 record.disposeLocked(false);
2131 }
2132 // Accumulate providers
2133 providers.addAll(oldRecords.keySet());
2134 }
2135
2136 // update provider
2137 for (String provider : providers) {
2138 // If provider is already disabled, don't need to do anything
Victoria Lease09eeaec2013-02-05 11:34:13 -08002139 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002140 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002141 }
2142
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002143 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002144 }
2145 }
2146
Dianne Hackbornc2293022013-02-06 23:14:49 -08002147 private void applyAllProviderRequirementsLocked() {
2148 for (LocationProviderInterface p : mProviders) {
2149 // If provider is already disabled, don't need to do anything
Dianne Hackborn64d41d72013-02-07 00:33:31 -08002150 if (!isAllowedByCurrentUserSettingsLocked(p.getName())) {
Dianne Hackbornc2293022013-02-06 23:14:49 -08002151 continue;
2152 }
2153
2154 applyRequirementsLocked(p.getName());
2155 }
2156 }
2157
Nick Pellye0fd6932012-07-11 10:26:13 -07002158 @Override
Nick Pelly4035f5a2012-08-17 14:43:49 -07002159 public Location getLastLocation(LocationRequest request, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002160 if (D) Log.d(TAG, "getLastLocation: " + request);
2161 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002162 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly4035f5a2012-08-17 14:43:49 -07002163 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002164 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2165 request.getProvider());
2166 // no need to sanitize this request, as only the provider name is used
Nick Pelly4035f5a2012-08-17 14:43:49 -07002167
David Christieb870dbf2015-06-22 12:42:53 -07002168 final int pid = Binder.getCallingPid();
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002169 final int uid = Binder.getCallingUid();
2170 final long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07002171 try {
2172 if (mBlacklist.isBlacklisted(packageName)) {
2173 if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
2174 packageName);
Victoria Lease09016ab2012-09-16 12:33:15 -07002175 return null;
2176 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002177
David Christieb870dbf2015-06-22 12:42:53 -07002178 if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel)) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002179 if (D) Log.d(TAG, "not returning last loc for no op app: " +
2180 packageName);
2181 return null;
2182 }
2183
Victoria Leaseb711d572012-10-02 13:14:11 -07002184 synchronized (mLock) {
2185 // Figure out the provider. Either its explicitly request (deprecated API's),
2186 // or use the fused provider
2187 String name = request.getProvider();
2188 if (name == null) name = LocationManager.FUSED_PROVIDER;
2189 LocationProviderInterface provider = mProvidersByName.get(name);
2190 if (provider == null) return null;
2191
Victoria Lease09eeaec2013-02-05 11:34:13 -08002192 if (!isAllowedByUserSettingsLocked(name, uid)) return null;
Victoria Leaseb711d572012-10-02 13:14:11 -07002193
David Christie1b9b7b12013-04-15 15:31:11 -07002194 Location location;
2195 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2196 // Make sure that an app with coarse permissions can't get frequent location
2197 // updates by calling LocationManager.getLastKnownLocation repeatedly.
2198 location = mLastLocationCoarseInterval.get(name);
2199 } else {
2200 location = mLastLocation.get(name);
2201 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002202 if (location == null) {
2203 return null;
2204 }
Victoria Lease37425c32012-10-16 16:08:48 -07002205 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002206 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2207 if (noGPSLocation != null) {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002208 return new Location(mLocationFudger.getOrCreate(noGPSLocation));
Victoria Leaseb711d572012-10-02 13:14:11 -07002209 }
Victoria Lease37425c32012-10-16 16:08:48 -07002210 } else {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002211 return new Location(location);
Victoria Lease09016ab2012-09-16 12:33:15 -07002212 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002213 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002214 return null;
2215 } finally {
2216 Binder.restoreCallingIdentity(identity);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002217 }
2218 }
2219
2220 @Override
2221 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
2222 String packageName) {
2223 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002224 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2225 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002226 checkPendingIntent(intent);
2227 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002228 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2229 request.getProvider());
2230 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002231
Victoria Lease37425c32012-10-16 16:08:48 -07002232 if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002233
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002234 // geo-fence manager uses the public location API, need to clear identity
2235 int uid = Binder.getCallingUid();
Xiaohui Chena4490622015-09-22 15:29:31 -07002236 // TODO: http://b/23822629
2237 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
Victoria Lease56e675b2012-11-05 19:25:06 -08002238 // temporary measure until geofences work for secondary users
2239 Log.w(TAG, "proximity alerts are currently available only to the primary user");
2240 return;
2241 }
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002242 long identity = Binder.clearCallingIdentity();
2243 try {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002244 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
2245 uid, packageName);
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002246 } finally {
2247 Binder.restoreCallingIdentity(identity);
2248 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002249 }
2250
2251 @Override
2252 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002253 checkPendingIntent(intent);
2254 checkPackageName(packageName);
2255
2256 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2257
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002258 // geo-fence manager uses the public location API, need to clear identity
2259 long identity = Binder.clearCallingIdentity();
2260 try {
2261 mGeofenceManager.removeFence(geofence, intent);
2262 } finally {
2263 Binder.restoreCallingIdentity(identity);
2264 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002265 }
2266
2267
2268 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002269 public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002270 if (!hasGnssPermissions(packageName) || mGnssStatusProvider == null) {
Takayuki Hoshib254ab6a2014-10-23 16:46:02 +09002271 return false;
2272 }
2273
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002274 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002275 mGnssStatusProvider.registerGnssStatusCallback(callback);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002276 } catch (RemoteException e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002277 Slog.e(TAG, "mGpsStatusProvider.registerGnssStatusCallback failed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002278 return false;
2279 }
2280 return true;
2281 }
2282
Nick Pellye0fd6932012-07-11 10:26:13 -07002283 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002284 public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002285 synchronized (mLock) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002286 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002287 mGnssStatusProvider.unregisterGnssStatusCallback(callback);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002288 } catch (Exception e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002289 Slog.e(TAG, "mGpsStatusProvider.unregisterGnssStatusCallback failed", e);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002291 }
2292 }
2293
Nick Pellye0fd6932012-07-11 10:26:13 -07002294 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002295 public boolean addGnssMeasurementsListener(
2296 IGnssMeasurementsListener listener,
destradaaea8a8a62014-06-23 18:19:03 -07002297 String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002298 if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
destradaaea8a8a62014-06-23 18:19:03 -07002299 return false;
2300 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002301
2302 synchronized (mLock) {
2303 Identity callerIdentity
2304 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
2305 mGnssMeasurementsListeners.put(listener, callerIdentity);
2306 long identity = Binder.clearCallingIdentity();
2307 try {
2308 if (isThrottlingExemptLocked(callerIdentity)
2309 || isImportanceForeground(
2310 mActivityManager.getPackageImportance(packageName))) {
2311 return mGnssMeasurementsProvider.addListener(listener);
2312 }
2313 } finally {
2314 Binder.restoreCallingIdentity(identity);
2315 }
2316
2317 return true;
2318 }
destradaaea8a8a62014-06-23 18:19:03 -07002319 }
2320
2321 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002322 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
2323 if (mGnssMeasurementsProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002324 synchronized (mLock) {
2325 mGnssMeasurementsListeners.remove(listener);
2326 mGnssMeasurementsProvider.removeListener(listener);
2327 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002328 }
destradaaea8a8a62014-06-23 18:19:03 -07002329 }
2330
2331 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002332 public boolean addGnssNavigationMessageListener(
2333 IGnssNavigationMessageListener listener,
destradaa4b3e3932014-07-21 18:01:47 -07002334 String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002335 if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) {
destradaa4b3e3932014-07-21 18:01:47 -07002336 return false;
2337 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002338
2339 synchronized (mLock) {
2340 Identity callerIdentity
2341 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
2342 mGnssNavigationMessageListeners.put(listener, callerIdentity);
2343 long identity = Binder.clearCallingIdentity();
2344 try {
2345 if (isThrottlingExemptLocked(callerIdentity)
2346 || isImportanceForeground(
2347 mActivityManager.getPackageImportance(packageName))) {
2348 return mGnssNavigationMessageProvider.addListener(listener);
2349 }
2350 } finally {
2351 Binder.restoreCallingIdentity(identity);
2352 }
2353
2354 return true;
2355 }
destradaa4b3e3932014-07-21 18:01:47 -07002356 }
2357
2358 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002359 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
2360 if (mGnssNavigationMessageProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002361 synchronized (mLock) {
2362 mGnssNavigationMessageListeners.remove(listener);
2363 mGnssNavigationMessageProvider.removeListener(listener);
2364 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002365 }
destradaa4b3e3932014-07-21 18:01:47 -07002366 }
2367
2368 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002369 public boolean sendExtraCommand(String provider, String command, Bundle extras) {
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002370 if (provider == null) {
2371 // throw NullPointerException to remain compatible with previous implementation
2372 throw new NullPointerException();
2373 }
Victoria Lease37425c32012-10-16 16:08:48 -07002374 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2375 provider);
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002376
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002377 // and check for ACCESS_LOCATION_EXTRA_COMMANDS
Mike Lockwoodb7e99222009-07-07 13:18:21 -04002378 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002379 != PackageManager.PERMISSION_GRANTED)) {
2380 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
2381 }
2382
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002383 synchronized (mLock) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002384 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002385 if (p == null) return false;
Nick Pellye0fd6932012-07-11 10:26:13 -07002386
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002387 return p.sendExtraCommand(command, extras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002388 }
2389 }
2390
Nick Pellye0fd6932012-07-11 10:26:13 -07002391 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002392 public boolean sendNiResponse(int notifId, int userResponse) {
Mike Lockwood18ad9f62009-08-27 14:01:23 -07002393 if (Binder.getCallingUid() != Process.myUid()) {
2394 throw new SecurityException(
2395 "calling sendNiResponse from outside of the system is not allowed");
2396 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002397 try {
2398 return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002399 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002400 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
Danke Xie22d1f9f2009-08-18 18:28:45 -04002401 return false;
2402 }
2403 }
2404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002405 /**
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002406 * @return null if the provider does not exist
Alexey Tarasovf2db9fb2009-09-01 02:37:07 +11002407 * @throws SecurityException if the provider is not allowed to be
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002408 * accessed by the caller
2409 */
Nick Pellye0fd6932012-07-11 10:26:13 -07002410 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002411 public ProviderProperties getProviderProperties(String provider) {
Laurent Tub7f9d252012-10-16 14:25:00 -07002412 if (mProvidersByName.get(provider) == null) {
David Christie2ff96af2014-01-30 16:09:37 -08002413 return null;
Laurent Tub7f9d252012-10-16 14:25:00 -07002414 }
2415
Victoria Lease37425c32012-10-16 16:08:48 -07002416 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2417 provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002418
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002419 LocationProviderInterface p;
2420 synchronized (mLock) {
2421 p = mProvidersByName.get(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002422 }
2423
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002424 if (p == null) return null;
2425 return p.getProperties();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002426 }
2427
Jason Monkb71218a2015-06-17 14:44:39 -04002428 /**
2429 * @return null if the provider does not exist
2430 * @throws SecurityException if the provider is not allowed to be
2431 * accessed by the caller
2432 */
2433 @Override
2434 public String getNetworkProviderPackage() {
2435 LocationProviderInterface p;
2436 synchronized (mLock) {
2437 if (mProvidersByName.get(LocationManager.NETWORK_PROVIDER) == null) {
2438 return null;
2439 }
2440 p = mProvidersByName.get(LocationManager.NETWORK_PROVIDER);
2441 }
2442
2443 if (p instanceof LocationProviderProxy) {
2444 return ((LocationProviderProxy) p).getConnectedPackageName();
2445 }
2446 return null;
2447 }
2448
Nick Pellye0fd6932012-07-11 10:26:13 -07002449 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002450 public boolean isProviderEnabled(String provider) {
Tom O'Neilld5759432013-09-11 11:03:03 -07002451 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2452 // so we discourage its use
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002453 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
2454
Victoria Lease09eeaec2013-02-05 11:34:13 -08002455 int uid = Binder.getCallingUid();
Victoria Lease269518e2012-10-29 08:25:39 -07002456 long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07002457 try {
2458 synchronized (mLock) {
2459 LocationProviderInterface p = mProvidersByName.get(provider);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002460 return p != null && isAllowedByUserSettingsLocked(provider, uid);
Victoria Leaseb711d572012-10-02 13:14:11 -07002461 }
2462 } finally {
2463 Binder.restoreCallingIdentity(identity);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002464 }
2465 }
2466
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002467 /**
2468 * Returns "true" if the UID belongs to a bound location provider.
2469 *
2470 * @param uid the uid
2471 * @return true if uid belongs to a bound location provider
2472 */
2473 private boolean isUidALocationProvider(int uid) {
2474 if (uid == Process.SYSTEM_UID) {
2475 return true;
2476 }
2477 if (mGeocodeProvider != null) {
David Christie1f141c12014-05-14 15:11:15 -07002478 if (doesUidHavePackage(uid, mGeocodeProvider.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002479 }
2480 for (LocationProviderProxy proxy : mProxyProviders) {
David Christie1f141c12014-05-14 15:11:15 -07002481 if (doesUidHavePackage(uid, proxy.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002482 }
2483 return false;
2484 }
2485
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002486 private void checkCallerIsProvider() {
2487 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
2488 == PackageManager.PERMISSION_GRANTED) {
2489 return;
2490 }
2491
2492 // Previously we only used the INSTALL_LOCATION_PROVIDER
2493 // check. But that is system or signature
2494 // protection level which is not flexible enough for
2495 // providers installed oustide the system image. So
2496 // also allow providers with a UID matching the
2497 // currently bound package name
2498
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002499 if (isUidALocationProvider(Binder.getCallingUid())) {
2500 return;
2501 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002502
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002503 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
2504 "or UID of a currently bound location provider");
2505 }
2506
David Christie1f141c12014-05-14 15:11:15 -07002507 /**
2508 * Returns true if the given package belongs to the given uid.
2509 */
2510 private boolean doesUidHavePackage(int uid, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002511 if (packageName == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002512 return false;
2513 }
David Christie1f141c12014-05-14 15:11:15 -07002514 String[] packageNames = mPackageManager.getPackagesForUid(uid);
2515 if (packageNames == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002516 return false;
2517 }
David Christie1f141c12014-05-14 15:11:15 -07002518 for (String name : packageNames) {
2519 if (packageName.equals(name)) {
2520 return true;
2521 }
2522 }
2523 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524 }
2525
Nick Pellye0fd6932012-07-11 10:26:13 -07002526 @Override
Mike Lockwooda4903f22010-02-17 06:42:23 -05002527 public void reportLocation(Location location, boolean passive) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002528 checkCallerIsProvider();
Mike Lockwood275555c2009-05-01 11:30:34 -04002529
Nick Pelly2eeeec22012-07-18 13:13:37 -07002530 if (!location.isComplete()) {
2531 Log.w(TAG, "Dropping incomplete location: " + location);
2532 return;
2533 }
2534
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002535 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location);
2536 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location);
Mike Lockwooda4903f22010-02-17 06:42:23 -05002537 m.arg1 = (passive ? 1 : 0);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002538 mLocationHandler.sendMessageAtFrontOfQueue(m);
2539 }
2540
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002541
Laurent Tu75defb62012-11-01 16:21:52 -07002542 private static boolean shouldBroadcastSafe(
2543 Location loc, Location lastLoc, UpdateRecord record, long now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002544 // Always broadcast the first update
2545 if (lastLoc == null) {
2546 return true;
2547 }
2548
Nick Pellyf1be6862012-05-15 10:53:42 -07002549 // Check whether sufficient time has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002550 long minTime = record.mRealRequest.getFastestInterval();
David Christie1b9b7b12013-04-15 15:31:11 -07002551 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
2552 / NANOS_PER_MILLI;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002553 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002554 return false;
2555 }
2556
2557 // Check whether sufficient distance has been traveled
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002558 double minDistance = record.mRealRequest.getSmallestDisplacement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002559 if (minDistance > 0.0) {
2560 if (loc.distanceTo(lastLoc) <= minDistance) {
2561 return false;
2562 }
2563 }
2564
Laurent Tu75defb62012-11-01 16:21:52 -07002565 // Check whether sufficient number of udpates is left
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002566 if (record.mRealRequest.getNumUpdates() <= 0) {
Laurent Tu75defb62012-11-01 16:21:52 -07002567 return false;
2568 }
2569
2570 // Check whether the expiry date has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002571 return record.mRealRequest.getExpireAt() >= now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002572 }
2573
Mike Lockwooda4903f22010-02-17 06:42:23 -05002574 private void handleLocationChangedLocked(Location location, boolean passive) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002575 if (D) Log.d(TAG, "incoming location: " + location);
2576
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002577 long now = SystemClock.elapsedRealtime();
Mike Lockwooda4903f22010-02-17 06:42:23 -05002578 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002579
Laurent Tu60ec50a2012-10-04 17:00:10 -07002580 // Skip if the provider is unknown.
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002581 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002582 if (p == null) return;
2583
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002584 // Update last known locations
Victoria Lease09016ab2012-09-16 12:33:15 -07002585 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002586 Location lastNoGPSLocation;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002587 Location lastLocation = mLastLocation.get(provider);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002588 if (lastLocation == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002589 lastLocation = new Location(provider);
2590 mLastLocation.put(provider, lastLocation);
Victoria Lease09016ab2012-09-16 12:33:15 -07002591 } else {
2592 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2593 if (noGPSLocation == null && lastNoGPSLocation != null) {
2594 // New location has no no-GPS location: adopt last no-GPS location. This is set
2595 // directly into location because we do not want to notify COARSE clients.
2596 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
2597 }
Mike Lockwood4e50b782009-04-03 08:24:43 -07002598 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002599 lastLocation.set(location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600
David Christie1b9b7b12013-04-15 15:31:11 -07002601 // Update last known coarse interval location if enough time has passed.
2602 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider);
2603 if (lastLocationCoarseInterval == null) {
2604 lastLocationCoarseInterval = new Location(location);
2605 mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval);
2606 }
2607 long timeDiffNanos = location.getElapsedRealtimeNanos()
2608 - lastLocationCoarseInterval.getElapsedRealtimeNanos();
2609 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
2610 lastLocationCoarseInterval.set(location);
2611 }
2612 // Don't ever return a coarse location that is more recent than the allowed update
2613 // interval (i.e. don't allow an app to keep registering and unregistering for
2614 // location updates to overcome the minimum interval).
2615 noGPSLocation =
2616 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2617
Laurent Tu60ec50a2012-10-04 17:00:10 -07002618 // Skip if there are no UpdateRecords for this provider.
2619 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
2620 if (records == null || records.size() == 0) return;
2621
Victoria Lease09016ab2012-09-16 12:33:15 -07002622 // Fetch coarse location
2623 Location coarseLocation = null;
David Christie1b9b7b12013-04-15 15:31:11 -07002624 if (noGPSLocation != null) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002625 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
2626 }
2627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002628 // Fetch latest status update time
2629 long newStatusUpdateTime = p.getStatusUpdateTime();
2630
David Christie2ff96af2014-01-30 16:09:37 -08002631 // Get latest status
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002632 Bundle extras = new Bundle();
2633 int status = p.getStatus(extras);
2634
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002635 ArrayList<Receiver> deadReceivers = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002636 ArrayList<UpdateRecord> deadUpdateRecords = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07002637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002638 // Broadcast location or status to all listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002639 for (UpdateRecord r : records) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002640 Receiver receiver = r.mReceiver;
Mike Lockwood03ca2162010-04-01 08:10:09 -07002641 boolean receiverDead = false;
Nick Pelly4035f5a2012-08-17 14:43:49 -07002642
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002643 int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid);
2644 if (!isCurrentProfile(receiverUserId)
2645 && !isUidALocationProvider(receiver.mIdentity.mUid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002646 if (D) {
Victoria Lease269518e2012-10-29 08:25:39 -07002647 Log.d(TAG, "skipping loc update for background user " + receiverUserId +
Victoria Leaseb711d572012-10-02 13:14:11 -07002648 " (current user: " + mCurrentUserId + ", app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002649 receiver.mIdentity.mPackageName + ")");
Victoria Leaseb711d572012-10-02 13:14:11 -07002650 }
2651 continue;
2652 }
2653
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002654 if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) {
Nick Pelly4035f5a2012-08-17 14:43:49 -07002655 if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002656 receiver.mIdentity.mPackageName);
Nick Pelly4035f5a2012-08-17 14:43:49 -07002657 continue;
2658 }
2659
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002660 if (!reportLocationAccessNoThrow(
2661 receiver.mIdentity.mPid,
2662 receiver.mIdentity.mUid,
2663 receiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002664 receiver.mAllowedResolutionLevel)) {
2665 if (D) Log.d(TAG, "skipping loc update for no op app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002666 receiver.mIdentity.mPackageName);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002667 continue;
2668 }
2669
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002670 Location notifyLocation;
Victoria Lease37425c32012-10-16 16:08:48 -07002671 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2672 notifyLocation = coarseLocation; // use coarse location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002673 } else {
Victoria Lease37425c32012-10-16 16:08:48 -07002674 notifyLocation = lastLocation; // use fine location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002675 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002676 if (notifyLocation != null) {
2677 Location lastLoc = r.mLastFixBroadcast;
Laurent Tu75defb62012-11-01 16:21:52 -07002678 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002679 if (lastLoc == null) {
2680 lastLoc = new Location(notifyLocation);
2681 r.mLastFixBroadcast = lastLoc;
2682 } else {
2683 lastLoc.set(notifyLocation);
2684 }
2685 if (!receiver.callLocationChangedLocked(notifyLocation)) {
2686 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
2687 receiverDead = true;
2688 }
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002689 r.mRealRequest.decrementNumUpdates();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002690 }
2691 }
2692
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002693 long prevStatusUpdateTime = r.mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002694 if ((newStatusUpdateTime > prevStatusUpdateTime) &&
Victoria Lease09016ab2012-09-16 12:33:15 -07002695 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002696
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002697 r.mLastStatusBroadcast = newStatusUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002698 if (!receiver.callStatusChangedLocked(provider, status, extras)) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002699 receiverDead = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002700 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
Mike Lockwood03ca2162010-04-01 08:10:09 -07002701 }
2702 }
2703
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002704 // track expired records
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002705 if (r.mRealRequest.getNumUpdates() <= 0 || r.mRealRequest.getExpireAt() < now) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002706 if (deadUpdateRecords == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002707 deadUpdateRecords = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002708 }
2709 deadUpdateRecords.add(r);
2710 }
2711 // track dead receivers
2712 if (receiverDead) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002713 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002714 deadReceivers = new ArrayList<>();
Mike Lockwood03ca2162010-04-01 08:10:09 -07002715 }
2716 if (!deadReceivers.contains(receiver)) {
2717 deadReceivers.add(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002718 }
2719 }
2720 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002721
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002722 // remove dead records and receivers outside the loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002723 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002724 for (Receiver receiver : deadReceivers) {
2725 removeUpdatesLocked(receiver);
2726 }
2727 }
2728 if (deadUpdateRecords != null) {
2729 for (UpdateRecord r : deadUpdateRecords) {
2730 r.disposeLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002731 }
Victoria Lease8b38b292012-12-04 15:04:43 -08002732 applyRequirementsLocked(provider);
2733 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734 }
2735
2736 private class LocationWorkerHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08002737 public LocationWorkerHandler(Looper looper) {
2738 super(looper, null, true);
2739 }
2740
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002741 @Override
2742 public void handleMessage(Message msg) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002743 switch (msg.what) {
2744 case MSG_LOCATION_CHANGED:
2745 handleLocationChanged((Location) msg.obj, msg.arg1 == 1);
2746 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002747 }
2748 }
2749 }
2750
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002751 private boolean isMockProvider(String provider) {
2752 synchronized (mLock) {
2753 return mMockProviders.containsKey(provider);
2754 }
2755 }
2756
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002757 private void handleLocationChanged(Location location, boolean passive) {
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002758 // create a working copy of the incoming Location so that the service can modify it without
2759 // disturbing the caller's copy
2760 Location myLocation = new Location(location);
2761 String provider = myLocation.getProvider();
2762
2763 // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this
2764 // bit if location did not come from a mock provider because passive/fused providers can
2765 // forward locations from mock providers, and should not grant them legitimacy in doing so.
2766 if (!myLocation.isFromMockProvider() && isMockProvider(provider)) {
2767 myLocation.setIsFromMockProvider(true);
2768 }
Jeff Sharkey5e613312012-01-30 11:16:20 -08002769
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002770 synchronized (mLock) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08002771 if (isAllowedByCurrentUserSettingsLocked(provider)) {
2772 if (!passive) {
2773 // notify passive provider of the new location
2774 mPassiveProvider.updateLocation(myLocation);
2775 }
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002776 handleLocationChangedLocked(myLocation, passive);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002777 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002778 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002779 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002780
Mike Lockwoode97ae402010-09-29 15:23:46 -04002781 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
2782 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002783 public void onPackageDisappeared(String packageName, int reason) {
2784 // remove all receivers associated with this package name
2785 synchronized (mLock) {
2786 ArrayList<Receiver> deadReceivers = null;
2787
2788 for (Receiver receiver : mReceivers.values()) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002789 if (receiver.mIdentity.mPackageName.equals(packageName)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002790 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002791 deadReceivers = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002792 }
2793 deadReceivers.add(receiver);
2794 }
2795 }
2796
2797 // perform removal outside of mReceivers loop
2798 if (deadReceivers != null) {
2799 for (Receiver receiver : deadReceivers) {
2800 removeUpdatesLocked(receiver);
2801 }
2802 }
2803 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002804 }
Mike Lockwoode97ae402010-09-29 15:23:46 -04002805 };
2806
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002807 // Geocoder
2808
Nick Pellye0fd6932012-07-11 10:26:13 -07002809 @Override
Mike Lockwoode15735a2010-09-20 17:48:47 -04002810 public boolean geocoderIsPresent() {
Mark Vandevoorde01ac80b2010-05-21 15:43:26 -07002811 return mGeocodeProvider != null;
2812 }
2813
Nick Pellye0fd6932012-07-11 10:26:13 -07002814 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002815 public String getFromLocation(double latitude, double longitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002816 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002817 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002818 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
2819 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
Mike Lockwooda55c3212009-04-15 11:10:11 -04002824
Nick Pellye0fd6932012-07-11 10:26:13 -07002825 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002826 public String getFromLocationName(String locationName,
Mike Lockwooda55c3212009-04-15 11:10:11 -04002827 double lowerLeftLatitude, double lowerLeftLongitude,
2828 double upperRightLatitude, double upperRightLongitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002829 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002830
2831 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002832 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
2833 lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
2834 maxResults, params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002835 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002836 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002837 }
2838
2839 // Mock Providers
2840
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002841 private boolean canCallerAccessMockLocation(String opPackageName) {
2842 return mAppOps.noteOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(),
2843 opPackageName) == AppOpsManager.MODE_ALLOWED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002844 }
2845
Nick Pellye0fd6932012-07-11 10:26:13 -07002846 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002847 public void addTestProvider(String name, ProviderProperties properties, String opPackageName) {
2848 if (!canCallerAccessMockLocation(opPackageName)) {
2849 return;
2850 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002851
Mike Lockwooda4903f22010-02-17 06:42:23 -05002852 if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
2853 throw new IllegalArgumentException("Cannot mock the passive location provider");
2854 }
2855
Mike Lockwood86328a92009-10-23 08:38:25 -04002856 long identity = Binder.clearCallingIdentity();
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002857 synchronized (mLock) {
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002858 // remove the real provider if we are replacing GPS or network provider
2859 if (LocationManager.GPS_PROVIDER.equals(name)
Nick Pelly1332b532012-08-21 16:25:47 -07002860 || LocationManager.NETWORK_PROVIDER.equals(name)
2861 || LocationManager.FUSED_PROVIDER.equals(name)) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002862 LocationProviderInterface p = mProvidersByName.get(name);
2863 if (p != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002864 removeProviderLocked(p);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002865 }
2866 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09002867 addTestProviderLocked(name, properties);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002868 updateProvidersLocked();
2869 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002870 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002871 }
2872
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09002873 private void addTestProviderLocked(String name, ProviderProperties properties) {
2874 if (mProvidersByName.get(name) != null) {
2875 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
2876 }
2877 MockProvider provider = new MockProvider(name, this, properties);
2878 addProviderLocked(provider);
2879 mMockProviders.put(name, provider);
2880 mLastLocation.put(name, null);
2881 mLastLocationCoarseInterval.put(name, null);
2882 }
2883
Nick Pellye0fd6932012-07-11 10:26:13 -07002884 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002885 public void removeTestProvider(String provider, String opPackageName) {
2886 if (!canCallerAccessMockLocation(opPackageName)) {
2887 return;
2888 }
2889
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002890 synchronized (mLock) {
Tom O'Neill07ee5d12014-03-03 17:48:35 -08002891
2892 // These methods can't be called after removing the test provider, so first make sure
Tom O'Neillfe6d3c52014-03-04 08:26:17 -08002893 // we don't leave anything dangling.
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002894 clearTestProviderEnabled(provider, opPackageName);
2895 clearTestProviderLocation(provider, opPackageName);
2896 clearTestProviderStatus(provider, opPackageName);
Tom O'Neill07ee5d12014-03-03 17:48:35 -08002897
You Kima6d0b6f2012-10-28 03:58:44 +09002898 MockProvider mockProvider = mMockProviders.remove(provider);
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002899 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002900 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2901 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002902 long identity = Binder.clearCallingIdentity();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002903 removeProviderLocked(mProvidersByName.get(provider));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002904
2905 // reinstate real provider if available
2906 LocationProviderInterface realProvider = mRealProviders.get(provider);
2907 if (realProvider != null) {
2908 addProviderLocked(realProvider);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002909 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002910 mLastLocation.put(provider, null);
David Christie1b9b7b12013-04-15 15:31:11 -07002911 mLastLocationCoarseInterval.put(provider, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002912 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04002913 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002914 }
2915 }
2916
Nick Pellye0fd6932012-07-11 10:26:13 -07002917 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002918 public void setTestProviderLocation(String provider, Location loc, String opPackageName) {
2919 if (!canCallerAccessMockLocation(opPackageName)) {
2920 return;
2921 }
2922
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002923 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002924 MockProvider mockProvider = mMockProviders.get(provider);
2925 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002926 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2927 }
Tom O'Neilla206a0f2016-12-15 10:26:28 -08002928
2929 // Ensure that the location is marked as being mock. There's some logic to do this in
2930 // handleLocationChanged(), but it fails if loc has the wrong provider (bug 33091107).
2931 Location mock = new Location(loc);
2932 mock.setIsFromMockProvider(true);
2933
2934 if (!TextUtils.isEmpty(loc.getProvider()) && !provider.equals(loc.getProvider())) {
2935 // The location has an explicit provider that is different from the mock provider
2936 // name. The caller may be trying to fool us via bug 33091107.
2937 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
2938 provider + "!=" + loc.getProvider());
2939 }
2940
Mike Lockwood95427cd2009-05-07 13:27:54 -04002941 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
2942 long identity = Binder.clearCallingIdentity();
Tom O'Neilla206a0f2016-12-15 10:26:28 -08002943 mockProvider.setLocation(mock);
Mike Lockwood95427cd2009-05-07 13:27:54 -04002944 Binder.restoreCallingIdentity(identity);
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 clearTestProviderLocation(String provider, 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 Lockwood7ec434e2009-03-27 07:46:48 -07002959 mockProvider.clearLocation();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002960 }
2961 }
2962
Nick Pellye0fd6932012-07-11 10:26:13 -07002963 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002964 public void setTestProviderEnabled(String provider, boolean enabled, String opPackageName) {
2965 if (!canCallerAccessMockLocation(opPackageName)) {
2966 return;
2967 }
2968
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002969 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002970 MockProvider mockProvider = mMockProviders.get(provider);
2971 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002972 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2973 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002974 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002975 if (enabled) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002976 mockProvider.enable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002977 mEnabledProviders.add(provider);
2978 mDisabledProviders.remove(provider);
2979 } else {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002980 mockProvider.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002981 mEnabledProviders.remove(provider);
2982 mDisabledProviders.add(provider);
2983 }
2984 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04002985 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002986 }
2987 }
2988
Nick Pellye0fd6932012-07-11 10:26:13 -07002989 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002990 public void clearTestProviderEnabled(String provider, String opPackageName) {
2991 if (!canCallerAccessMockLocation(opPackageName)) {
2992 return;
2993 }
2994
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002995 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002996 MockProvider mockProvider = mMockProviders.get(provider);
2997 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002998 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2999 }
Mike Lockwood86328a92009-10-23 08:38:25 -04003000 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003001 mEnabledProviders.remove(provider);
3002 mDisabledProviders.remove(provider);
3003 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04003004 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003005 }
3006 }
3007
Nick Pellye0fd6932012-07-11 10:26:13 -07003008 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003009 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime,
3010 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.setStatus(status, extras, updateTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003021 }
3022 }
3023
Nick Pellye0fd6932012-07-11 10:26:13 -07003024 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003025 public void clearTestProviderStatus(String provider, String opPackageName) {
3026 if (!canCallerAccessMockLocation(opPackageName)) {
3027 return;
3028 }
3029
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003030 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003031 MockProvider mockProvider = mMockProviders.get(provider);
3032 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003033 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3034 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003035 mockProvider.clearStatus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003036 }
3037 }
3038
3039 private void log(String log) {
3040 if (Log.isLoggable(TAG, Log.VERBOSE)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003041 Slog.d(TAG, log);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003042 }
3043 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003044
3045 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003046 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003047 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Nick Pellye0fd6932012-07-11 10:26:13 -07003048
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003049 synchronized (mLock) {
Siddharth Raybb608c82017-03-16 11:33:34 -07003050 if (args.length > 0 && args[0].equals("--gnssmetrics")) {
3051 if (mGnssMetricsProvider != null) {
3052 pw.append(mGnssMetricsProvider.getGnssMetricsAsProtoString());
3053 }
3054 return;
3055 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003056 pw.println("Current Location Manager state:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003057 pw.println(" Location Listeners:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003058 for (Receiver receiver : mReceivers.values()) {
3059 pw.println(" " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003060 }
David Christie2ff96af2014-01-30 16:09:37 -08003061 pw.println(" Active Records by Provider:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003062 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
3063 pw.println(" " + entry.getKey() + ":");
3064 for (UpdateRecord record : entry.getValue()) {
3065 pw.println(" " + record);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066 }
3067 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003068 pw.println(" Overlay Provider Packages:");
3069 for (LocationProviderInterface provider : mProviders) {
3070 if (provider instanceof LocationProviderProxy) {
3071 pw.println(" " + provider.getName() + ": "
3072 + ((LocationProviderProxy) provider).getConnectedPackageName());
3073 }
3074 }
David Christie2ff96af2014-01-30 16:09:37 -08003075 pw.println(" Historical Records by Provider:");
3076 for (Map.Entry<PackageProviderKey, PackageStatistics> entry
3077 : mRequestStatistics.statistics.entrySet()) {
3078 PackageProviderKey key = entry.getKey();
3079 PackageStatistics stats = entry.getValue();
3080 pw.println(" " + key.packageName + ": " + key.providerName + ": " + stats);
3081 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003082 pw.println(" Last Known Locations:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003083 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
3084 String provider = entry.getKey();
3085 Location location = entry.getValue();
3086 pw.println(" " + provider + ": " + location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003087 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003088
David Christie1b9b7b12013-04-15 15:31:11 -07003089 pw.println(" Last Known Locations Coarse Intervals:");
3090 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
3091 String provider = entry.getKey();
3092 Location location = entry.getValue();
3093 pw.println(" " + provider + ": " + location);
3094 }
3095
Nick Pellye0fd6932012-07-11 10:26:13 -07003096 mGeofenceManager.dump(pw);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003098 if (mEnabledProviders.size() > 0) {
3099 pw.println(" Enabled Providers:");
3100 for (String i : mEnabledProviders) {
3101 pw.println(" " + i);
3102 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003104 }
3105 if (mDisabledProviders.size() > 0) {
3106 pw.println(" Disabled Providers:");
3107 for (String i : mDisabledProviders) {
3108 pw.println(" " + i);
3109 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003110 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07003111 pw.append(" ");
3112 mBlacklist.dump(pw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003113 if (mMockProviders.size() > 0) {
3114 pw.println(" Mock Providers:");
3115 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003116 i.getValue().dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003117 }
3118 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003119
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08003120 if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
3121 pw.println(" Throttling Whitelisted Packages:");
3122 for (String packageName : mBackgroundThrottlePackageWhitelist) {
3123 pw.println(" " + packageName);
3124 }
3125 }
3126
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003127 pw.append(" fudger: ");
3128 mLocationFudger.dump(fd, pw, args);
3129
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003130 if (args.length > 0 && "short".equals(args[0])) {
3131 return;
3132 }
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003133 for (LocationProviderInterface provider: mProviders) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003134 pw.print(provider.getName() + " Internal State");
3135 if (provider instanceof LocationProviderProxy) {
3136 LocationProviderProxy proxy = (LocationProviderProxy) provider;
3137 pw.print(" (" + proxy.getConnectedPackageName() + ")");
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003138 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003139 pw.println(":");
3140 provider.dump(fd, pw, args);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003141 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08003142 if (mGnssBatchingInProgress) {
3143 pw.println(" GNSS batching in progress");
3144 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003145 }
3146 }
3147}