blob: 72754616133ae6436b9ddad3e9e7c201f6ea4f0e [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
Wyatt Rileycf879db2017-01-12 13:57:38 -0800246 private GnssLocationProvider.GnssBatchingProvider mGnssBatchingProvider;
Siddharth Raybb608c82017-03-16 11:33:34 -0700247 private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800248 private IBatchedLocationCallback mGnssBatchingCallback;
249 private LinkedCallback mGnssBatchingDeathCallback;
250 private boolean mGnssBatchingInProgress = false;
251
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700252 public LocationManagerService(Context context) {
253 super();
254 mContext = context;
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800255 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800256
Svet Ganovadc1cf42015-06-15 16:36:24 -0700257 // Let the package manager query which are the default location
258 // providers as they get certain permissions granted by default.
259 PackageManagerInternal packageManagerInternal = LocalServices.getService(
260 PackageManagerInternal.class);
261 packageManagerInternal.setLocationPackagesProvider(
262 new PackageManagerInternal.PackagesProvider() {
263 @Override
264 public String[] getPackages(int userId) {
265 return mContext.getResources().getStringArray(
266 com.android.internal.R.array.config_locationProviderPackageNames);
267 }
268 });
269
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700270 if (D) Log.d(TAG, "Constructed");
271
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700272 // most startup is deferred until systemRunning()
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700273 }
274
Svetoslav Ganova0027152013-06-25 14:59:53 -0700275 public void systemRunning() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700276 synchronized (mLock) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700277 if (D) Log.d(TAG, "systemRunning()");
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700278
Victoria Lease5cd731a2012-12-19 15:04:21 -0800279 // fetch package manager
280 mPackageManager = mContext.getPackageManager();
281
Victoria Lease0aa28602013-05-29 15:28:26 -0700282 // fetch power manager
283 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
Victoria Lease5cd731a2012-12-19 15:04:21 -0800284
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800285 // fetch activity manager
286 mActivityManager
287 = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
288
Victoria Lease5cd731a2012-12-19 15:04:21 -0800289 // prepare worker thread
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700290 mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper());
Victoria Lease5cd731a2012-12-19 15:04:21 -0800291
292 // prepare mLocationHandler's dependents
293 mLocationFudger = new LocationFudger(mContext, mLocationHandler);
294 mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
295 mBlacklist.init();
296 mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
297
Dianne Hackbornc2293022013-02-06 23:14:49 -0800298 // Monitor for app ops mode changes.
Dianne Hackborn9bb0ee92013-09-22 12:31:38 -0700299 AppOpsManager.OnOpChangedListener callback
300 = new AppOpsManager.OnOpChangedInternalListener() {
301 public void onOpChanged(int op, String packageName) {
Dianne Hackbornc2293022013-02-06 23:14:49 -0800302 synchronized (mLock) {
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700303 for (Receiver receiver : mReceivers.values()) {
304 receiver.updateMonitoring(true);
305 }
Dianne Hackbornc2293022013-02-06 23:14:49 -0800306 applyAllProviderRequirementsLocked();
307 }
308 }
309 };
310 mAppOps.startWatchingMode(AppOpsManager.OP_COARSE_LOCATION, null, callback);
311
David Christieb870dbf2015-06-22 12:42:53 -0700312 PackageManager.OnPermissionsChangedListener permissionListener
313 = new PackageManager.OnPermissionsChangedListener() {
314 @Override
315 public void onPermissionsChanged(final int uid) {
316 synchronized (mLock) {
317 applyAllProviderRequirementsLocked();
318 }
319 }
320 };
321 mPackageManager.addOnPermissionsChangeListener(permissionListener);
322
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800323 // listen for background/foreground changes
324 ActivityManager.OnUidImportanceListener uidImportanceListener
325 = new ActivityManager.OnUidImportanceListener() {
326 @Override
327 public void onUidImportance(int uid, int importance) {
328 boolean foreground = isImportanceForeground(importance);
329 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
330 synchronized (mLock) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800331 for (Entry<String, ArrayList<UpdateRecord>> entry
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800332 : mRecordsByProvider.entrySet()) {
333 String provider = entry.getKey();
334 for (UpdateRecord record : entry.getValue()) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800335 if (record.mReceiver.mIdentity.mUid == uid
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800336 && record.mIsForegroundUid != foreground) {
337 if (D) Log.d(TAG, "request from uid " + uid + " is now "
338 + (foreground ? "foreground" : "background)"));
339 record.mIsForegroundUid = foreground;
340
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800341 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800342 affectedProviders.add(provider);
343 }
344 }
345 }
346 }
347 for (String provider : affectedProviders) {
348 applyRequirementsLocked(provider);
349 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800350
351 for (Entry<IGnssMeasurementsListener, Identity> entry
352 : mGnssMeasurementsListeners.entrySet()) {
353 if (entry.getValue().mUid == uid) {
354 if (D) Log.d(TAG, "gnss measurements listener from uid " + uid
355 + " is now " + (foreground ? "foreground" : "background)"));
356 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
357 mGnssMeasurementsProvider.addListener(entry.getKey());
358 } else {
359 mGnssMeasurementsProvider.removeListener(entry.getKey());
360 }
361 }
362 }
363
364 for (Entry<IGnssNavigationMessageListener, Identity> entry
365 : mGnssNavigationMessageListeners.entrySet()) {
366 if (entry.getValue().mUid == uid) {
367 if (D) Log.d(TAG, "gnss navigation message listener from uid "
368 + uid + " is now "
369 + (foreground ? "foreground" : "background)"));
370 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
371 mGnssNavigationMessageProvider.addListener(entry.getKey());
372 } else {
373 mGnssNavigationMessageProvider.removeListener(entry.getKey());
374 }
375 }
376 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800377 }
378
379 }
380 };
381 mActivityManager.addOnUidImportanceListener(uidImportanceListener,
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700382 FOREGROUND_IMPORTANCE_CUTOFF);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800383
Amith Yamasanib27528d2014-06-05 15:02:10 -0700384 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
385 updateUserProfiles(mCurrentUserId);
386
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800387 updateBackgroundThrottlingWhitelistLocked();
Soonil Nagarkar2b565df2017-02-14 13:33:23 -0800388
Victoria Lease5cd731a2012-12-19 15:04:21 -0800389 // prepare providers
390 loadProvidersLocked();
391 updateProvidersLocked();
392 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700393
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700394 // listen for settings changes
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700395 mContext.getContentResolver().registerContentObserver(
Laurent Tu75defb62012-11-01 16:21:52 -0700396 Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700397 new ContentObserver(mLocationHandler) {
Victoria Lease5cd731a2012-12-19 15:04:21 -0800398 @Override
399 public void onChange(boolean selfChange) {
400 synchronized (mLock) {
401 updateProvidersLocked();
402 }
403 }
404 }, UserHandle.USER_ALL);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800405 mContext.getContentResolver().registerContentObserver(
406 Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS),
407 true,
408 new ContentObserver(mLocationHandler) {
409 @Override
410 public void onChange(boolean selfChange) {
411 synchronized (mLock) {
412 updateProvidersLocked();
413 }
414 }
415 }, UserHandle.USER_ALL);
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800416 mContext.getContentResolver().registerContentObserver(
417 Settings.Global.getUriFor(
418 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
419 true,
420 new ContentObserver(mLocationHandler) {
421 @Override
422 public void onChange(boolean selfChange) {
423 synchronized (mLock) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800424 updateBackgroundThrottlingWhitelistLocked();
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -0800425 updateProvidersLocked();
426 }
427 }
428 }, UserHandle.USER_ALL);
Victoria Lease5cd731a2012-12-19 15:04:21 -0800429 mPackageMonitor.register(mContext, mLocationHandler.getLooper(), true);
Brian Muramatsubb95cb92012-08-29 10:43:21 -0700430
Victoria Lease38389b62012-09-30 11:44:22 -0700431 // listen for user change
432 IntentFilter intentFilter = new IntentFilter();
433 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700434 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
435 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
destradaab9026982015-08-27 17:34:54 -0700436 intentFilter.addAction(Intent.ACTION_SHUTDOWN);
Victoria Lease38389b62012-09-30 11:44:22 -0700437
438 mContext.registerReceiverAsUser(new BroadcastReceiver() {
439 @Override
440 public void onReceive(Context context, Intent intent) {
441 String action = intent.getAction();
442 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
443 switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
Amith Yamasanib27528d2014-06-05 15:02:10 -0700444 } else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)
445 || Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
446 updateUserProfiles(mCurrentUserId);
destradaab9026982015-08-27 17:34:54 -0700447 } else if (Intent.ACTION_SHUTDOWN.equals(action)) {
Wyatt Rileya8037ff2016-08-04 16:10:06 -0700448 // shutdown only if UserId indicates whole system, not just one user
449 if(D) Log.d(TAG, "Shutdown received with UserId: " + getSendingUserId());
450 if (getSendingUserId() == UserHandle.USER_ALL) {
451 shutdownComponents();
452 }
Victoria Lease38389b62012-09-30 11:44:22 -0700453 }
454 }
Victoria Lease5cd731a2012-12-19 15:04:21 -0800455 }, UserHandle.ALL, intentFilter, null, mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700456 }
457
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800458 private static boolean isImportanceForeground(int importance) {
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700459 return importance <= FOREGROUND_IMPORTANCE_CUTOFF;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800460 }
461
Amith Yamasanib27528d2014-06-05 15:02:10 -0700462 /**
destradaab9026982015-08-27 17:34:54 -0700463 * Provides a way for components held by the {@link LocationManagerService} to clean-up
464 * gracefully on system's shutdown.
465 *
466 * NOTES:
467 * 1) Only provides a chance to clean-up on an opt-in basis. This guarantees back-compat
468 * support for components that do not wish to handle such event.
469 */
470 private void shutdownComponents() {
471 if(D) Log.d(TAG, "Shutting down components...");
472
473 LocationProviderInterface gpsProvider = mProvidersByName.get(LocationManager.GPS_PROVIDER);
474 if (gpsProvider != null && gpsProvider.isEnabled()) {
475 gpsProvider.disable();
476 }
477
destradaa2e385072015-10-14 16:45:58 -0700478 // it is needed to check if FLP HW provider is supported before accessing the instance, this
479 // avoids an exception to be thrown by the singleton factory method
480 if (FlpHardwareProvider.isSupported()) {
481 FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
destradaab9026982015-08-27 17:34:54 -0700482 flpHardwareProvider.cleanup();
483 }
484 }
485
486 /**
Amith Yamasanib27528d2014-06-05 15:02:10 -0700487 * Makes a list of userids that are related to the current user. This is
488 * relevant when using managed profiles. Otherwise the list only contains
489 * the current user.
490 *
491 * @param currentUserId the current user, who might have an alter-ego.
492 */
493 void updateUserProfiles(int currentUserId) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700494 int[] profileIds = mUserManager.getProfileIdsWithDisabled(currentUserId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700495 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700496 mCurrentUserProfiles = profileIds;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700497 }
498 }
499
500 /**
501 * Checks if the specified userId matches any of the current foreground
502 * users stored in mCurrentUserProfiles.
503 */
504 private boolean isCurrentProfile(int userId) {
505 synchronized (mLock) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700506 return ArrayUtils.contains(mCurrentUserProfiles, userId);
Amith Yamasanib27528d2014-06-05 15:02:10 -0700507 }
508 }
509
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500510 private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) {
511 PackageManager pm = mContext.getPackageManager();
512 String systemPackageName = mContext.getPackageName();
513 ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
514
515 List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
516 new Intent(FUSED_LOCATION_SERVICE_ACTION),
517 PackageManager.GET_META_DATA, mCurrentUserId);
518 for (ResolveInfo rInfo : rInfos) {
519 String packageName = rInfo.serviceInfo.packageName;
520
521 // Check that the signature is in the list of supported sigs. If it's not in
522 // this list the standard provider binding logic won't bind to it.
523 try {
524 PackageInfo pInfo;
525 pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
526 if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
527 Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
528 ", but has wrong signature, ignoring");
529 continue;
530 }
531 } catch (NameNotFoundException e) {
532 Log.e(TAG, "missing package: " + packageName);
533 continue;
534 }
535
536 // Get the version info
537 if (rInfo.serviceInfo.metaData == null) {
538 Log.w(TAG, "Found fused provider without metadata: " + packageName);
539 continue;
540 }
541
542 int version = rInfo.serviceInfo.metaData.getInt(
543 ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
544 if (version == 0) {
545 // This should be the fallback fused location provider.
546
547 // Make sure it's in the system partition.
548 if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
549 if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
550 continue;
551 }
552
553 // Check that the fallback is signed the same as the OS
554 // as a proxy for coreApp="true"
555 if (pm.checkSignatures(systemPackageName, packageName)
556 != PackageManager.SIGNATURE_MATCH) {
557 if (D) Log.d(TAG, "Fallback candidate not signed the same as system: "
558 + packageName);
559 continue;
560 }
561
562 // Found a valid fallback.
563 if (D) Log.d(TAG, "Found fallback provider: " + packageName);
564 return;
565 } else {
566 if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
567 }
568 }
569
570 throw new IllegalStateException("Unable to find a fused location provider that is in the "
571 + "system partition with version 0 and signed with the platform certificate. "
572 + "Such a package is needed to provide a default fused location provider in the "
573 + "event that no other fused location provider has been installed or is currently "
574 + "available. For example, coreOnly boot mode when decrypting the data "
575 + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
576 }
577
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700578 private void loadProvidersLocked() {
Victoria Lease5c24fd02012-10-01 11:00:50 -0700579 // create a passive location provider, which is always enabled
580 PassiveProvider passiveProvider = new PassiveProvider(this);
581 addProviderLocked(passiveProvider);
582 mEnabledProviders.add(passiveProvider.getName());
583 mPassiveProvider = passiveProvider;
584
Lifu Tang30f95a72016-01-07 23:20:38 -0800585 if (GnssLocationProvider.isSupported()) {
Wei Liu5241a4c2015-05-11 14:00:36 -0700586 // Create a gps location provider
Lifu Tang30f95a72016-01-07 23:20:38 -0800587 GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this,
Wei Liu5241a4c2015-05-11 14:00:36 -0700588 mLocationHandler.getLooper());
Lifu Tang9363b942016-02-16 18:07:00 -0800589 mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
Wyatt Rileycf879db2017-01-12 13:57:38 -0800590 mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider();
Siddharth Raybb608c82017-03-16 11:33:34 -0700591 mGnssMetricsProvider = gnssProvider.getGnssMetricsProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800592 mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
593 mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
594 addProviderLocked(gnssProvider);
595 mRealProviders.put(LocationManager.GPS_PROVIDER, gnssProvider);
Lifu Tang818aa2c2016-02-01 01:52:00 -0800596 mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
597 mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider();
Lifu Tang30f95a72016-01-07 23:20:38 -0800598 mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700599 }
600
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700601 /*
602 Load package name(s) containing location provider support.
603 These packages can contain services implementing location providers:
604 Geocoder Provider, Network Location Provider, and
605 Fused Location Provider. They will each be searched for
606 service components implementing these providers.
607 The location framework also has support for installation
608 of new location providers at run-time. The new package does not
609 have to be explicitly listed here, however it must have a signature
610 that matches the signature of at least one package on this list.
611 */
612 Resources resources = mContext.getResources();
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800613 ArrayList<String> providerPackageNames = new ArrayList<>();
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500614 String[] pkgs = resources.getStringArray(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700615 com.android.internal.R.array.config_locationProviderPackageNames);
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500616 if (D) Log.d(TAG, "certificates for location providers pulled from: " +
617 Arrays.toString(pkgs));
618 if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));
619
620 ensureFallbackFusedProviderPresentLocked(providerPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700621
622 // bind to network provider
623 LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
624 mContext,
625 LocationManager.NETWORK_PROVIDER,
626 NETWORK_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700627 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
628 com.android.internal.R.string.config_networkLocationProviderPackageName,
629 com.android.internal.R.array.config_locationProviderPackageNames,
630 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700631 if (networkProvider != null) {
632 mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
633 mProxyProviders.add(networkProvider);
634 addProviderLocked(networkProvider);
635 } else {
636 Slog.w(TAG, "no network location provider found");
637 }
638
639 // bind to fused provider
640 LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind(
641 mContext,
642 LocationManager.FUSED_PROVIDER,
643 FUSED_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700644 com.android.internal.R.bool.config_enableFusedLocationOverlay,
645 com.android.internal.R.string.config_fusedLocationProviderPackageName,
646 com.android.internal.R.array.config_locationProviderPackageNames,
647 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700648 if (fusedLocationProvider != null) {
649 addProviderLocked(fusedLocationProvider);
650 mProxyProviders.add(fusedLocationProvider);
651 mEnabledProviders.add(fusedLocationProvider.getName());
Kenny Rootc3575182012-10-09 12:44:40 -0700652 mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700653 } else {
654 Slog.e(TAG, "no fused location provider found",
655 new IllegalStateException("Location service needs a fused location provider"));
656 }
657
658 // bind to geocoder provider
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700659 mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
660 com.android.internal.R.bool.config_enableGeocoderOverlay,
661 com.android.internal.R.string.config_geocoderProviderPackageName,
662 com.android.internal.R.array.config_locationProviderPackageNames,
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800663 mLocationHandler);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700664 if (mGeocodeProvider == null) {
665 Slog.e(TAG, "no geocoder provider found");
666 }
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700667
destradaaa4fa3b52014-07-09 10:46:39 -0700668 // bind to fused hardware provider if supported
destradaabeea4422014-07-30 18:17:21 -0700669 // in devices without support, requesting an instance of FlpHardwareProvider will raise an
670 // exception, so make sure we only do that when supported
671 FlpHardwareProvider flpHardwareProvider;
destradaa5ce66d82014-05-28 18:24:08 -0700672 if (FlpHardwareProvider.isSupported()) {
destradaabeea4422014-07-30 18:17:21 -0700673 flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
destradaaf9a274c2014-07-25 15:11:56 -0700674 FusedProxy fusedProxy = FusedProxy.createAndBind(
675 mContext,
676 mLocationHandler,
677 flpHardwareProvider.getLocationHardware(),
678 com.android.internal.R.bool.config_enableHardwareFlpOverlay,
679 com.android.internal.R.string.config_hardwareFlpPackageName,
680 com.android.internal.R.array.config_locationProviderPackageNames);
681 if (fusedProxy == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700682 Slog.d(TAG, "Unable to bind FusedProxy.");
destradaaf9a274c2014-07-25 15:11:56 -0700683 }
destradaacfbdcd22014-04-30 11:29:11 -0700684 } else {
destradaabeea4422014-07-30 18:17:21 -0700685 flpHardwareProvider = null;
destradaa6b4893a2016-05-03 15:33:43 -0700686 Slog.d(TAG, "FLP HAL not supported");
destradaaf9a274c2014-07-25 15:11:56 -0700687 }
688
689 // bind to geofence provider
690 GeofenceProxy provider = GeofenceProxy.createAndBind(
691 mContext,com.android.internal.R.bool.config_enableGeofenceOverlay,
692 com.android.internal.R.string.config_geofenceProviderPackageName,
693 com.android.internal.R.array.config_locationProviderPackageNames,
694 mLocationHandler,
Wei Liu5241a4c2015-05-11 14:00:36 -0700695 mGpsGeofenceProxy,
destradaabeea4422014-07-30 18:17:21 -0700696 flpHardwareProvider != null ? flpHardwareProvider.getGeofenceHardware() : null);
destradaaf9a274c2014-07-25 15:11:56 -0700697 if (provider == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700698 Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
destradaa0682809a2013-08-12 18:50:30 -0700699 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900700
destradaa6e2fe752015-06-23 17:25:53 -0700701 // bind to hardware activity recognition
702 boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
703 ActivityRecognitionHardware activityRecognitionHardware = null;
704 if (activityRecognitionHardwareIsSupported) {
705 activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
destradaaa4fa3b52014-07-09 10:46:39 -0700706 } else {
destradaa6b4893a2016-05-03 15:33:43 -0700707 Slog.d(TAG, "Hardware Activity-Recognition not supported.");
destradaaa4fa3b52014-07-09 10:46:39 -0700708 }
destradaa6e2fe752015-06-23 17:25:53 -0700709 ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
710 mContext,
711 mLocationHandler,
712 activityRecognitionHardwareIsSupported,
713 activityRecognitionHardware,
714 com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
715 com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
716 com.android.internal.R.array.config_locationProviderPackageNames);
717 if (proxy == null) {
destradaa6b4893a2016-05-03 15:33:43 -0700718 Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
destradaa6e2fe752015-06-23 17:25:53 -0700719 }
destradaaa4fa3b52014-07-09 10:46:39 -0700720
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900721 String[] testProviderStrings = resources.getStringArray(
722 com.android.internal.R.array.config_testLocationProviders);
723 for (String testProviderString : testProviderStrings) {
724 String fragments[] = testProviderString.split(",");
725 String name = fragments[0].trim();
726 if (mProvidersByName.get(name) != null) {
727 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
728 }
729 ProviderProperties properties = new ProviderProperties(
730 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
731 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
732 Boolean.parseBoolean(fragments[3]) /* requiresCell */,
733 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
734 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
735 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
736 Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
737 Integer.parseInt(fragments[8]) /* powerRequirement */,
738 Integer.parseInt(fragments[9]) /* accuracy */);
739 addTestProviderLocked(name, properties);
740 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700741 }
Mike Lockwood9637d472009-04-02 21:41:57 -0700742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743 /**
Victoria Lease38389b62012-09-30 11:44:22 -0700744 * Called when the device's active user changes.
745 * @param userId the new active user's UserId
746 */
747 private void switchUser(int userId) {
Jianzheng Zhoud5c69462013-10-10 14:02:09 +0800748 if (mCurrentUserId == userId) {
749 return;
750 }
Victoria Lease83762d22012-10-03 13:51:17 -0700751 mBlacklist.switchUser(userId);
Victoria Lease03cdd3d2013-02-01 15:15:54 -0800752 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED);
Victoria Lease38389b62012-09-30 11:44:22 -0700753 synchronized (mLock) {
Victoria Leaseb711d572012-10-02 13:14:11 -0700754 mLastLocation.clear();
David Christie1b9b7b12013-04-15 15:31:11 -0700755 mLastLocationCoarseInterval.clear();
Victoria Leaseb711d572012-10-02 13:14:11 -0700756 for (LocationProviderInterface p : mProviders) {
Amith Yamasanib27528d2014-06-05 15:02:10 -0700757 updateProviderListenersLocked(p.getName(), false);
Victoria Leaseb711d572012-10-02 13:14:11 -0700758 }
Victoria Lease38389b62012-09-30 11:44:22 -0700759 mCurrentUserId = userId;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700760 updateUserProfiles(userId);
Victoria Leaseb711d572012-10-02 13:14:11 -0700761 updateProvidersLocked();
Victoria Lease38389b62012-09-30 11:44:22 -0700762 }
763 }
764
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800765 private static final class Identity {
766 final int mUid;
767 final int mPid;
768 final String mPackageName;
769
770 Identity(int uid, int pid, String packageName) {
771 mUid = uid;
772 mPid = pid;
773 mPackageName = packageName;
774 }
775 }
776
Victoria Lease38389b62012-09-30 11:44:22 -0700777 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778 * A wrapper class holding either an ILocationListener or a PendingIntent to receive
779 * location updates.
780 */
Mike Lockwood48f17512009-04-23 09:12:08 -0700781 private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800782 final Identity mIdentity;
Victoria Lease37425c32012-10-16 16:08:48 -0700783 final int mAllowedResolutionLevel; // resolution level allowed to receiver
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700784
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800785 final ILocationListener mListener;
786 final PendingIntent mPendingIntent;
David Christie82edc9b2013-07-19 11:31:42 -0700787 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
David Christie40e57822013-07-30 11:36:48 -0700788 final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789 final Object mKey;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700790
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800791 final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<>();
Nick Pellyf1be6862012-05-15 10:53:42 -0700792
David Christie0b837452013-07-29 16:02:13 -0700793 // True if app ops has started monitoring this receiver for locations.
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700794 boolean mOpMonitoring;
David Christie0b837452013-07-29 16:02:13 -0700795 // True if app ops has started monitoring this receiver for high power (gps) locations.
796 boolean mOpHighPowerMonitoring;
Mike Lockwood48f17512009-04-23 09:12:08 -0700797 int mPendingBroadcasts;
Victoria Lease0aa28602013-05-29 15:28:26 -0700798 PowerManager.WakeLock mWakeLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800799
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700800 Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -0700801 String packageName, WorkSource workSource, boolean hideFromAppOps) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800802 mListener = listener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800803 mPendingIntent = intent;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700804 if (listener != null) {
805 mKey = listener.asBinder();
806 } else {
807 mKey = intent;
808 }
Victoria Lease37425c32012-10-16 16:08:48 -0700809 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800810 mIdentity = new Identity(uid, pid, packageName);
David Christie82edc9b2013-07-19 11:31:42 -0700811 if (workSource != null && workSource.size() <= 0) {
812 workSource = null;
813 }
814 mWorkSource = workSource;
David Christie40e57822013-07-30 11:36:48 -0700815 mHideFromAppOps = hideFromAppOps;
Victoria Lease0aa28602013-05-29 15:28:26 -0700816
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700817 updateMonitoring(true);
818
Victoria Lease0aa28602013-05-29 15:28:26 -0700819 // construct/configure wakelock
820 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
David Christie82edc9b2013-07-19 11:31:42 -0700821 if (workSource == null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800822 workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -0700823 }
824 mWakeLock.setWorkSource(workSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825 }
826
827 @Override
828 public boolean equals(Object otherObj) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800829 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800830 }
831
832 @Override
833 public int hashCode() {
834 return mKey.hashCode();
835 }
Mike Lockwood3681f262009-05-12 10:52:03 -0400836
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800837 @Override
838 public String toString() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700839 StringBuilder s = new StringBuilder();
840 s.append("Reciever[");
841 s.append(Integer.toHexString(System.identityHashCode(this)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800842 if (mListener != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700843 s.append(" listener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800844 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700845 s.append(" intent");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700847 for (String p : mUpdateRecords.keySet()) {
848 s.append(" ").append(mUpdateRecords.get(p).toString());
849 }
850 s.append("]");
851 return s.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800852 }
853
David Christie15b31912013-08-13 15:54:32 -0700854 /**
855 * Update AppOp monitoring for this receiver.
856 *
857 * @param allow If true receiver is currently active, if false it's been removed.
858 */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700859 public void updateMonitoring(boolean allow) {
David Christie40e57822013-07-30 11:36:48 -0700860 if (mHideFromAppOps) {
861 return;
862 }
863
David Christie15b31912013-08-13 15:54:32 -0700864 boolean requestingLocation = false;
865 boolean requestingHighPowerLocation = false;
866 if (allow) {
867 // See if receiver has any enabled update records. Also note if any update records
868 // are high power (has a high power provider with an interval under a threshold).
869 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
870 if (isAllowedByCurrentUserSettingsLocked(updateRecord.mProvider)) {
871 requestingLocation = true;
872 LocationProviderInterface locationProvider
David Christie2ff96af2014-01-30 16:09:37 -0800873 = mProvidersByName.get(updateRecord.mProvider);
David Christie15b31912013-08-13 15:54:32 -0700874 ProviderProperties properties = locationProvider != null
875 ? locationProvider.getProperties() : null;
876 if (properties != null
877 && properties.mPowerRequirement == Criteria.POWER_HIGH
878 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
879 requestingHighPowerLocation = true;
880 break;
881 }
882 }
883 }
884 }
885
David Christie0b837452013-07-29 16:02:13 -0700886 // First update monitoring of any location request (including high power).
David Christie15b31912013-08-13 15:54:32 -0700887 mOpMonitoring = updateMonitoring(
888 requestingLocation,
889 mOpMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700890 AppOpsManager.OP_MONITOR_LOCATION);
891
892 // Now update monitoring of high power requests only.
David Christiec750c1f2013-08-08 12:56:57 -0700893 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
David Christie15b31912013-08-13 15:54:32 -0700894 mOpHighPowerMonitoring = updateMonitoring(
895 requestingHighPowerLocation,
896 mOpHighPowerMonitoring,
David Christie0b837452013-07-29 16:02:13 -0700897 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
David Christiec750c1f2013-08-08 12:56:57 -0700898 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
David Christie15b31912013-08-13 15:54:32 -0700899 // Send an intent to notify that a high power request has been added/removed.
David Christiec750c1f2013-08-08 12:56:57 -0700900 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
901 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
902 }
David Christie0b837452013-07-29 16:02:13 -0700903 }
904
905 /**
906 * Update AppOps monitoring for a single location request and op type.
907 *
908 * @param allowMonitoring True if monitoring is allowed for this request/op.
909 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
910 * @param op AppOps code for the op to update.
911 * @return True if monitoring is on for this request/op after updating.
912 */
913 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
914 int op) {
915 if (!currentlyMonitoring) {
916 if (allowMonitoring) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800917 return mAppOps.startOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700918 == AppOpsManager.MODE_ALLOWED;
919 }
920 } else {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800921 if (!allowMonitoring
922 || mAppOps.checkOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
David Christie0b837452013-07-29 16:02:13 -0700923 != AppOpsManager.MODE_ALLOWED) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800924 mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName);
David Christie0b837452013-07-29 16:02:13 -0700925 return false;
926 }
927 }
928
929 return currentlyMonitoring;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -0700930 }
931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800932 public boolean isListener() {
933 return mListener != null;
934 }
935
936 public boolean isPendingIntent() {
937 return mPendingIntent != null;
938 }
939
940 public ILocationListener getListener() {
941 if (mListener != null) {
942 return mListener;
943 }
944 throw new IllegalStateException("Request for non-existent listener");
945 }
946
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
948 if (mListener != null) {
949 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700950 synchronized (this) {
951 // synchronize to ensure incrementPendingBroadcastsLocked()
952 // is called before decrementPendingBroadcasts()
953 mListener.onStatusChanged(provider, status, extras);
Nick Pellye0fd6932012-07-11 10:26:13 -0700954 // call this after broadcasting so we do not increment
955 // if we throw an exeption.
956 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -0700957 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800958 } catch (RemoteException e) {
959 return false;
960 }
961 } else {
962 Intent statusChanged = new Intent();
Victoria Lease61ecb022012-11-13 15:12:51 -0800963 statusChanged.putExtras(new Bundle(extras));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
965 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700966 synchronized (this) {
967 // synchronize to ensure incrementPendingBroadcastsLocked()
968 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700969 mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -0700970 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -0700971 // call this after broadcasting so we do not increment
972 // if we throw an exeption.
973 incrementPendingBroadcastsLocked();
974 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 } catch (PendingIntent.CanceledException e) {
976 return false;
977 }
978 }
979 return true;
980 }
981
982 public boolean callLocationChangedLocked(Location location) {
983 if (mListener != null) {
984 try {
Mike Lockwood48f17512009-04-23 09:12:08 -0700985 synchronized (this) {
986 // synchronize to ensure incrementPendingBroadcastsLocked()
987 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c5406a2012-11-29 16:18:01 -0800988 mListener.onLocationChanged(new Location(location));
Nick Pellye0fd6932012-07-11 10:26:13 -0700989 // call this after broadcasting so we do not increment
990 // if we throw an exeption.
991 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -0700992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 } catch (RemoteException e) {
994 return false;
995 }
996 } else {
997 Intent locationChanged = new Intent();
Victoria Lease61ecb022012-11-13 15:12:51 -0800998 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, new Location(location));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 try {
Mike Lockwood48f17512009-04-23 09:12:08 -07001000 synchronized (this) {
1001 // synchronize to ensure incrementPendingBroadcastsLocked()
1002 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001003 mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -07001004 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -07001005 // call this after broadcasting so we do not increment
1006 // if we throw an exeption.
1007 incrementPendingBroadcastsLocked();
1008 }
1009 } catch (PendingIntent.CanceledException e) {
1010 return false;
1011 }
1012 }
1013 return true;
1014 }
1015
1016 public boolean callProviderEnabledLocked(String provider, boolean enabled) {
David Christie15b31912013-08-13 15:54:32 -07001017 // First update AppOp monitoring.
1018 // An app may get/lose location access as providers are enabled/disabled.
1019 updateMonitoring(true);
1020
Mike Lockwood48f17512009-04-23 09:12:08 -07001021 if (mListener != null) {
1022 try {
1023 synchronized (this) {
1024 // synchronize to ensure incrementPendingBroadcastsLocked()
1025 // is called before decrementPendingBroadcasts()
1026 if (enabled) {
1027 mListener.onProviderEnabled(provider);
1028 } else {
1029 mListener.onProviderDisabled(provider);
1030 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001031 // call this after broadcasting so we do not increment
1032 // if we throw an exeption.
1033 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001034 }
1035 } catch (RemoteException e) {
1036 return false;
1037 }
1038 } else {
1039 Intent providerIntent = new Intent();
1040 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1041 try {
1042 synchronized (this) {
1043 // synchronize to ensure incrementPendingBroadcastsLocked()
1044 // is called before decrementPendingBroadcasts()
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001045 mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
Victoria Lease37425c32012-10-16 16:08:48 -07001046 getResolutionPermission(mAllowedResolutionLevel));
Mike Lockwood48f17512009-04-23 09:12:08 -07001047 // call this after broadcasting so we do not increment
1048 // if we throw an exeption.
1049 incrementPendingBroadcastsLocked();
1050 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001051 } catch (PendingIntent.CanceledException e) {
1052 return false;
1053 }
1054 }
1055 return true;
1056 }
1057
Nick Pellyf1be6862012-05-15 10:53:42 -07001058 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001059 public void binderDied() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001060 if (D) Log.d(TAG, "Location listener died");
1061
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001062 synchronized (mLock) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 removeUpdatesLocked(this);
1064 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001065 synchronized (this) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001066 clearPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001067 }
1068 }
1069
Nick Pellye0fd6932012-07-11 10:26:13 -07001070 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001071 public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1072 int resultCode, String resultData, Bundle resultExtras) {
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001073 synchronized (this) {
1074 decrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001075 }
1076 }
1077
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001078 // this must be called while synchronized by caller in a synchronized block
1079 // containing the sending of the broadcaset
1080 private void incrementPendingBroadcastsLocked() {
1081 if (mPendingBroadcasts++ == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001082 mWakeLock.acquire();
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001083 }
1084 }
1085
1086 private void decrementPendingBroadcastsLocked() {
1087 if (--mPendingBroadcasts == 0) {
Victoria Lease0aa28602013-05-29 15:28:26 -07001088 if (mWakeLock.isHeld()) {
1089 mWakeLock.release();
1090 }
1091 }
1092 }
1093
1094 public void clearPendingBroadcastsLocked() {
1095 if (mPendingBroadcasts > 0) {
1096 mPendingBroadcasts = 0;
1097 if (mWakeLock.isHeld()) {
1098 mWakeLock.release();
1099 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001100 }
1101 }
1102 }
1103
Nick Pellye0fd6932012-07-11 10:26:13 -07001104 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001105 public void locationCallbackFinished(ILocationListener listener) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001106 //Do not use getReceiverLocked here as that will add the ILocationListener to
Joshua Bartel080b61b2009-10-05 12:44:46 -04001107 //the receiver list if it is not found. If it is not found then the
1108 //LocationListener was removed when it had a pending broadcast and should
1109 //not be added back.
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001110 synchronized (mLock) {
1111 IBinder binder = listener.asBinder();
1112 Receiver receiver = mReceivers.get(binder);
1113 if (receiver != null) {
1114 synchronized (receiver) {
1115 // so wakelock calls will succeed
1116 long identity = Binder.clearCallingIdentity();
1117 receiver.decrementPendingBroadcastsLocked();
1118 Binder.restoreCallingIdentity(identity);
David Christie2ff96af2014-01-30 16:09:37 -08001119 }
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 }
1122 }
1123
Lifu Tang82f893d2016-01-21 18:15:33 -08001124 /**
Lifu Tang9363b942016-02-16 18:07:00 -08001125 * Returns the system information of the GNSS hardware.
Lifu Tang82f893d2016-01-21 18:15:33 -08001126 */
1127 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001128 public int getGnssYearOfHardware() {
Wyatt Rileycf879db2017-01-12 13:57:38 -08001129 if (mGnssSystemInfoProvider != null) {
Lifu Tang9363b942016-02-16 18:07:00 -08001130 return mGnssSystemInfoProvider.getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001131 } else {
1132 return 0;
1133 }
1134 }
1135
Wyatt Rileycf879db2017-01-12 13:57:38 -08001136 /**
1137 * Runs some checks for GNSS (FINE) level permissions, used by several methods which directly
1138 * (try to) access GNSS information at this layer.
1139 */
1140 private boolean hasGnssPermissions(String packageName) {
1141 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
1142 checkResolutionLevelIsSufficientForProviderUse(
1143 allowedResolutionLevel,
1144 LocationManager.GPS_PROVIDER);
1145
1146 int pid = Binder.getCallingPid();
1147 int uid = Binder.getCallingUid();
1148 long identity = Binder.clearCallingIdentity();
1149 boolean hasLocationAccess;
1150 try {
1151 hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
1152 } finally {
1153 Binder.restoreCallingIdentity(identity);
1154 }
1155
1156 return hasLocationAccess;
1157 }
1158
1159 /**
1160 * Returns the GNSS batching size, if available.
1161 */
1162 @Override
1163 public int getGnssBatchSize(String packageName) {
1164 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1165 "Location Hardware permission not granted to access hardware batching");
1166
1167 if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
1168 return mGnssBatchingProvider.getSize();
1169 } else {
1170 return 0;
1171 }
1172 }
1173
1174 /**
1175 * Adds a callback for GNSS Batching events, if permissions allow, which are transported
1176 * to potentially multiple listeners by the BatchedLocationCallbackTransport above this.
1177 */
1178 @Override
1179 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) {
1180 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1181 "Location Hardware permission not granted to access hardware batching");
1182
1183 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1184 return false;
1185 }
1186
1187 mGnssBatchingCallback = callback;
1188 mGnssBatchingDeathCallback = new LinkedCallback(callback);
1189 try {
1190 callback.asBinder().linkToDeath(mGnssBatchingDeathCallback, 0 /* flags */);
1191 } catch (RemoteException e) {
1192 // if the remote process registering the listener is already dead, just swallow the
1193 // exception and return
1194 Log.e(TAG, "Remote listener already died.", e);
1195 return false;
1196 }
1197
1198 return true;
1199 }
1200
1201 private class LinkedCallback implements IBinder.DeathRecipient {
1202 private final IBatchedLocationCallback mCallback;
1203
1204 public LinkedCallback(@NonNull IBatchedLocationCallback callback) {
1205 mCallback = callback;
1206 }
1207
1208 @NonNull
1209 public IBatchedLocationCallback getUnderlyingListener() {
1210 return mCallback;
1211 }
1212
1213 @Override
1214 public void binderDied() {
1215 Log.d(TAG, "Remote Batching Callback died: " + mCallback);
1216 stopGnssBatch();
1217 removeGnssBatchingCallback();
1218 }
1219 }
1220
1221 /**
1222 * Removes callback for GNSS batching
1223 */
1224 @Override
1225 public void removeGnssBatchingCallback() {
1226 try {
1227 mGnssBatchingCallback.asBinder().unlinkToDeath(mGnssBatchingDeathCallback,
1228 0 /* flags */);
1229 } catch (NoSuchElementException e) {
1230 // if the death callback isn't connected (it should be...), log error, swallow the
1231 // exception and return
1232 Log.e(TAG, "Couldn't unlink death callback.", e);
1233 }
1234 mGnssBatchingCallback = null;
1235 mGnssBatchingDeathCallback = null;
1236 }
1237
1238
1239 /**
1240 * Starts GNSS batching, if available.
1241 */
1242 @Override
1243 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
1244 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1245 "Location Hardware permission not granted to access hardware batching");
1246
1247 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1248 return false;
1249 }
1250
1251 if (mGnssBatchingInProgress) {
1252 // Current design does not expect multiple starts to be called repeatedly
1253 Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch");
1254 // Try to clean up anyway, and continue
1255 stopGnssBatch();
1256 }
1257
1258 mGnssBatchingInProgress = true;
1259 return mGnssBatchingProvider.start(periodNanos, wakeOnFifoFull);
1260 }
1261
1262 /**
1263 * Flushes a GNSS batch in progress
1264 */
1265 @Override
1266 public void flushGnssBatch(String packageName) {
1267 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1268 "Location Hardware permission not granted to access hardware batching");
1269
1270 if (!hasGnssPermissions(packageName)) {
1271 Log.e(TAG, "flushGnssBatch called without GNSS permissions");
1272 return;
1273 }
1274
1275 if (!mGnssBatchingInProgress) {
1276 Log.w(TAG, "flushGnssBatch called with no batch in progress");
1277 }
1278
1279 if (mGnssBatchingProvider != null) {
1280 mGnssBatchingProvider.flush();
1281 }
1282 }
1283
1284 /**
1285 * Stops GNSS batching
1286 */
1287 @Override
1288 public boolean stopGnssBatch() {
1289 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1290 "Location Hardware permission not granted to access hardware batching");
1291
1292 if (mGnssBatchingProvider != null) {
1293 mGnssBatchingInProgress = false;
1294 return mGnssBatchingProvider.stop();
1295 } else {
1296 return false;
1297 }
1298 }
1299
1300 @Override
1301 public void reportLocationBatch(List<Location> locations) {
1302 checkCallerIsProvider();
1303
1304 // Currently used only for GNSS locations - update permissions check if changed
1305 if (isAllowedByCurrentUserSettingsLocked(LocationManager.GPS_PROVIDER)) {
1306 if (mGnssBatchingCallback == null) {
1307 Slog.e(TAG, "reportLocationBatch() called without active Callback");
1308 return;
1309 }
1310 try {
1311 mGnssBatchingCallback.onLocationBatch(locations);
1312 } catch (RemoteException e) {
1313 Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e);
1314 }
1315 } else {
1316 Slog.w(TAG, "reportLocationBatch() called without user permission, locations blocked");
1317 }
1318 }
1319
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001320 private void addProviderLocked(LocationProviderInterface provider) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001321 mProviders.add(provider);
1322 mProvidersByName.put(provider.getName(), provider);
1323 }
1324
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001325 private void removeProviderLocked(LocationProviderInterface provider) {
1326 provider.disable();
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001327 mProviders.remove(provider);
1328 mProvidersByName.remove(provider.getName());
1329 }
1330
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001331 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001332 * Returns "true" if access to the specified location provider is allowed by the current
1333 * user's settings. Access to all location providers is forbidden to non-location-provider
1334 * processes belonging to background users.
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001335 *
1336 * @param provider the name of the location provider
Victoria Lease03cdd3d2013-02-01 15:15:54 -08001337 */
Victoria Lease09eeaec2013-02-05 11:34:13 -08001338 private boolean isAllowedByCurrentUserSettingsLocked(String provider) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001339 if (mEnabledProviders.contains(provider)) {
1340 return true;
1341 }
1342 if (mDisabledProviders.contains(provider)) {
1343 return false;
1344 }
1345 // Use system settings
1346 ContentResolver resolver = mContext.getContentResolver();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001347
Victoria Leaseb711d572012-10-02 13:14:11 -07001348 return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001349 }
1350
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001351 /**
Victoria Lease09eeaec2013-02-05 11:34:13 -08001352 * Returns "true" if access to the specified location provider is allowed by the specified
1353 * user's settings. Access to all location providers is forbidden to non-location-provider
1354 * processes belonging to background users.
1355 *
1356 * @param provider the name of the location provider
1357 * @param uid the requestor's UID
Victoria Lease09eeaec2013-02-05 11:34:13 -08001358 */
1359 private boolean isAllowedByUserSettingsLocked(String provider, int uid) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001360 if (!isCurrentProfile(UserHandle.getUserId(uid)) && !isUidALocationProvider(uid)) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08001361 return false;
1362 }
1363 return isAllowedByCurrentUserSettingsLocked(provider);
1364 }
1365
1366 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001367 * Returns the permission string associated with the specified resolution level.
1368 *
1369 * @param resolutionLevel the resolution level
1370 * @return the permission string
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001371 */
Victoria Lease37425c32012-10-16 16:08:48 -07001372 private String getResolutionPermission(int resolutionLevel) {
1373 switch (resolutionLevel) {
1374 case RESOLUTION_LEVEL_FINE:
1375 return android.Manifest.permission.ACCESS_FINE_LOCATION;
1376 case RESOLUTION_LEVEL_COARSE:
1377 return android.Manifest.permission.ACCESS_COARSE_LOCATION;
1378 default:
1379 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380 }
Victoria Leaseda479c52012-10-15 15:24:16 -07001381 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001382
Victoria Leaseda479c52012-10-15 15:24:16 -07001383 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001384 * Returns the resolution level allowed to the given PID/UID pair.
1385 *
1386 * @param pid the PID
1387 * @param uid the UID
1388 * @return resolution level allowed to the pid/uid pair
Victoria Leaseda479c52012-10-15 15:24:16 -07001389 */
Victoria Lease37425c32012-10-16 16:08:48 -07001390 private int getAllowedResolutionLevel(int pid, int uid) {
1391 if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
1392 pid, uid) == PackageManager.PERMISSION_GRANTED) {
1393 return RESOLUTION_LEVEL_FINE;
1394 } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
1395 pid, uid) == PackageManager.PERMISSION_GRANTED) {
1396 return RESOLUTION_LEVEL_COARSE;
1397 } else {
1398 return RESOLUTION_LEVEL_NONE;
Victoria Leaseda479c52012-10-15 15:24:16 -07001399 }
Victoria Lease4fab68b2012-09-13 13:20:59 -07001400 }
1401
1402 /**
Victoria Lease37425c32012-10-16 16:08:48 -07001403 * Returns the resolution level allowed to the caller
1404 *
1405 * @return resolution level allowed to caller
Victoria Lease4fab68b2012-09-13 13:20:59 -07001406 */
Victoria Lease37425c32012-10-16 16:08:48 -07001407 private int getCallerAllowedResolutionLevel() {
1408 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
1409 }
1410
1411 /**
1412 * Throw SecurityException if specified resolution level is insufficient to use geofences.
1413 *
1414 * @param allowedResolutionLevel resolution level allowed to caller
1415 */
1416 private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
1417 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Lease4fab68b2012-09-13 13:20:59 -07001418 throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
1419 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001420 }
1421
Victoria Lease37425c32012-10-16 16:08:48 -07001422 /**
1423 * Return the minimum resolution level required to use the specified location provider.
1424 *
1425 * @param provider the name of the location provider
1426 * @return minimum resolution level required for provider
1427 */
1428 private int getMinimumResolutionLevelForProviderUse(String provider) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001429 if (LocationManager.GPS_PROVIDER.equals(provider) ||
1430 LocationManager.PASSIVE_PROVIDER.equals(provider)) {
1431 // gps and passive providers require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001432 return RESOLUTION_LEVEL_FINE;
Victoria Lease8dbb6342012-09-21 16:55:53 -07001433 } else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
1434 LocationManager.FUSED_PROVIDER.equals(provider)) {
1435 // network and fused providers are ok with COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001436 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001437 } else {
1438 // mock providers
1439 LocationProviderInterface lp = mMockProviders.get(provider);
1440 if (lp != null) {
1441 ProviderProperties properties = lp.getProperties();
1442 if (properties != null) {
1443 if (properties.mRequiresSatellite) {
1444 // provider requiring satellites require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001445 return RESOLUTION_LEVEL_FINE;
Laurent Tu941221c2012-10-04 14:21:52 -07001446 } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
1447 // provider requiring network and or cell require COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001448 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001449 }
1450 }
1451 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001452 }
Victoria Lease37425c32012-10-16 16:08:48 -07001453 return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
Victoria Leaseda479c52012-10-15 15:24:16 -07001454 }
1455
Victoria Lease37425c32012-10-16 16:08:48 -07001456 /**
1457 * Throw SecurityException if specified resolution level is insufficient to use the named
1458 * location provider.
1459 *
1460 * @param allowedResolutionLevel resolution level allowed to caller
1461 * @param providerName the name of the location provider
1462 */
1463 private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel,
1464 String providerName) {
1465 int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName);
1466 if (allowedResolutionLevel < requiredResolutionLevel) {
1467 switch (requiredResolutionLevel) {
1468 case RESOLUTION_LEVEL_FINE:
1469 throw new SecurityException("\"" + providerName + "\" location provider " +
1470 "requires ACCESS_FINE_LOCATION permission.");
1471 case RESOLUTION_LEVEL_COARSE:
1472 throw new SecurityException("\"" + providerName + "\" location provider " +
1473 "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
1474 default:
1475 throw new SecurityException("Insufficient permission for \"" + providerName +
1476 "\" location provider.");
Victoria Leaseda479c52012-10-15 15:24:16 -07001477 }
1478 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001479 }
1480
David Christie82edc9b2013-07-19 11:31:42 -07001481 /**
1482 * Throw SecurityException if WorkSource use is not allowed (i.e. can't blame other packages
1483 * for battery).
1484 */
David Christie40e57822013-07-30 11:36:48 -07001485 private void checkDeviceStatsAllowed() {
David Christie82edc9b2013-07-19 11:31:42 -07001486 mContext.enforceCallingOrSelfPermission(
1487 android.Manifest.permission.UPDATE_DEVICE_STATS, null);
1488 }
1489
David Christie40e57822013-07-30 11:36:48 -07001490 private void checkUpdateAppOpsAllowed() {
1491 mContext.enforceCallingOrSelfPermission(
1492 android.Manifest.permission.UPDATE_APP_OPS_STATS, null);
1493 }
1494
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001495 public static int resolutionLevelToOp(int allowedResolutionLevel) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001496 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
1497 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001498 return AppOpsManager.OP_COARSE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001499 } else {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001500 return AppOpsManager.OP_FINE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001501 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001502 }
1503 return -1;
1504 }
1505
David Christieb870dbf2015-06-22 12:42:53 -07001506 boolean reportLocationAccessNoThrow(
1507 int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001508 int op = resolutionLevelToOp(allowedResolutionLevel);
1509 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001510 if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1511 return false;
1512 }
1513 }
David Christieb870dbf2015-06-22 12:42:53 -07001514
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001515 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001516 }
1517
David Christieb870dbf2015-06-22 12:42:53 -07001518 boolean checkLocationAccess(int pid, int uid, String packageName, int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001519 int op = resolutionLevelToOp(allowedResolutionLevel);
1520 if (op >= 0) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001521 if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1522 return false;
1523 }
1524 }
David Christieb870dbf2015-06-22 12:42:53 -07001525
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001526 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001527 }
1528
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001529 /**
1530 * Returns all providers by name, including passive, but excluding
Laurent Tu0d21e212012-10-02 15:33:48 -07001531 * fused, also including ones that are not permitted to
1532 * be accessed by the calling activity or are currently disabled.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001533 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001534 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001535 public List<String> getAllProviders() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001536 ArrayList<String> out;
1537 synchronized (mLock) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001538 out = new ArrayList<>(mProviders.size());
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001539 for (LocationProviderInterface provider : mProviders) {
1540 String name = provider.getName();
1541 if (LocationManager.FUSED_PROVIDER.equals(name)) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07001542 continue;
1543 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001544 out.add(name);
1545 }
1546 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001547
1548 if (D) Log.d(TAG, "getAllProviders()=" + out);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549 return out;
1550 }
1551
Mike Lockwood03ca2162010-04-01 08:10:09 -07001552 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001553 * Return all providers by name, that match criteria and are optionally
1554 * enabled.
1555 * Can return passive provider, but never returns fused provider.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001556 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001557 @Override
1558 public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
Victoria Lease37425c32012-10-16 16:08:48 -07001559 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001560 ArrayList<String> out;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001561 int uid = Binder.getCallingUid();
Victoria Lease269518e2012-10-29 08:25:39 -07001562 long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07001563 try {
1564 synchronized (mLock) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001565 out = new ArrayList<>(mProviders.size());
Victoria Leaseb711d572012-10-02 13:14:11 -07001566 for (LocationProviderInterface provider : mProviders) {
1567 String name = provider.getName();
1568 if (LocationManager.FUSED_PROVIDER.equals(name)) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001569 continue;
1570 }
Victoria Lease37425c32012-10-16 16:08:48 -07001571 if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08001572 if (enabledOnly && !isAllowedByUserSettingsLocked(name, uid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001573 continue;
1574 }
1575 if (criteria != null && !LocationProvider.propertiesMeetCriteria(
1576 name, provider.getProperties(), criteria)) {
1577 continue;
1578 }
1579 out.add(name);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001580 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001581 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001582 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001583 } finally {
1584 Binder.restoreCallingIdentity(identity);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001585 }
1586
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001587 if (D) Log.d(TAG, "getProviders()=" + out);
1588 return out;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001589 }
1590
1591 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001592 * Return the name of the best provider given a Criteria object.
1593 * This method has been deprecated from the public API,
Victoria Lease8dbb6342012-09-21 16:55:53 -07001594 * and the whole LocationProvider (including #meetsCriteria)
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001595 * has been deprecated as well. So this method now uses
1596 * some simplified logic.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001597 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001598 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001599 public String getBestProvider(Criteria criteria, boolean enabledOnly) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001600 String result = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001601
1602 List<String> providers = getProviders(criteria, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001603 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001604 result = pickBest(providers);
1605 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1606 return result;
1607 }
1608 providers = getProviders(null, enabledOnly);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001609 if (!providers.isEmpty()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001610 result = pickBest(providers);
1611 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1612 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001613 }
1614
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001615 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001616 return null;
1617 }
1618
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001619 private String pickBest(List<String> providers) {
Victoria Lease1925e292012-09-24 17:00:18 -07001620 if (providers.contains(LocationManager.GPS_PROVIDER)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001621 return LocationManager.GPS_PROVIDER;
Victoria Lease1925e292012-09-24 17:00:18 -07001622 } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
1623 return LocationManager.NETWORK_PROVIDER;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001624 } else {
1625 return providers.get(0);
1626 }
1627 }
1628
Nick Pellye0fd6932012-07-11 10:26:13 -07001629 @Override
Mike Lockwood03ca2162010-04-01 08:10:09 -07001630 public boolean providerMeetsCriteria(String provider, Criteria criteria) {
1631 LocationProviderInterface p = mProvidersByName.get(provider);
1632 if (p == null) {
1633 throw new IllegalArgumentException("provider=" + provider);
1634 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001635
1636 boolean result = LocationProvider.propertiesMeetCriteria(
1637 p.getName(), p.getProperties(), criteria);
1638 if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result);
1639 return result;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001640 }
1641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001642 private void updateProvidersLocked() {
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001643 boolean changesMade = false;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001644 for (int i = mProviders.size() - 1; i >= 0; i--) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001645 LocationProviderInterface p = mProviders.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 boolean isEnabled = p.isEnabled();
1647 String name = p.getName();
Victoria Lease09eeaec2013-02-05 11:34:13 -08001648 boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649 if (isEnabled && !shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001650 updateProviderListenersLocked(name, false);
David Christieb084fef2013-12-18 14:33:57 -08001651 // If any provider has been disabled, clear all last locations for all providers.
1652 // This is to be on the safe side in case a provider has location derived from
1653 // this disabled provider.
1654 mLastLocation.clear();
1655 mLastLocationCoarseInterval.clear();
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001656 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001657 } else if (!isEnabled && shouldBeEnabled) {
Amith Yamasanib27528d2014-06-05 15:02:10 -07001658 updateProviderListenersLocked(name, true);
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001659 changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001660 }
Brad Fitzpatrick0c5a0402010-08-27 14:01:23 -07001661 }
1662 if (changesMade) {
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001663 mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
1664 UserHandle.ALL);
Tom O'Neill40a86c22013-09-03 18:05:13 -07001665 mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
1666 UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001667 }
1668 }
1669
Amith Yamasanib27528d2014-06-05 15:02:10 -07001670 private void updateProviderListenersLocked(String provider, boolean enabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001671 int listeners = 0;
1672
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001673 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001674 if (p == null) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675
1676 ArrayList<Receiver> deadReceivers = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07001677
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001678 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1679 if (records != null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001680 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001681 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001682 // Sends a notification message to the receiver
1683 if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
1684 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001685 deadReceivers = new ArrayList<>();
Victoria Leaseb711d572012-10-02 13:14:11 -07001686 }
1687 deadReceivers.add(record.mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001688 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001689 listeners++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001691 }
1692 }
1693
1694 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001695 for (int i = deadReceivers.size() - 1; i >= 0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001696 removeUpdatesLocked(deadReceivers.get(i));
1697 }
1698 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001699
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001700 if (enabled) {
1701 p.enable();
1702 if (listeners > 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001703 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 }
1705 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001706 p.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001707 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708 }
1709
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001710 private void applyRequirementsLocked(String provider) {
1711 LocationProviderInterface p = mProvidersByName.get(provider);
1712 if (p == null) return;
1713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001714 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001715 WorkSource worksource = new WorkSource();
1716 ProviderRequest providerRequest = new ProviderRequest();
1717
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001718 ContentResolver resolver = mContext.getContentResolver();
1719 long backgroundThrottleInterval = Settings.Global.getLong(
1720 resolver,
1721 Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
1722 DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
1723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001724 if (records != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001725 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001726 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
David Christieb870dbf2015-06-22 12:42:53 -07001727 if (checkLocationAccess(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001728 record.mReceiver.mIdentity.mPid,
1729 record.mReceiver.mIdentity.mUid,
1730 record.mReceiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001731 record.mReceiver.mAllowedResolutionLevel)) {
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001732 LocationRequest locationRequest = record.mRealRequest;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001733 long interval = locationRequest.getInterval();
1734
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001735 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001736 if (!record.mIsForegroundUid) {
1737 interval = Math.max(interval, backgroundThrottleInterval);
1738 }
1739 if (interval != locationRequest.getInterval()) {
1740 locationRequest = new LocationRequest(locationRequest);
1741 locationRequest.setInterval(interval);
1742 }
1743 }
1744
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001745 record.mRequest = locationRequest;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001746 providerRequest.locationRequests.add(locationRequest);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001747 if (interval < providerRequest.interval) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001748 providerRequest.reportLocation = true;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001749 providerRequest.interval = interval;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001750 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001751 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001752 }
1753 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001754
1755 if (providerRequest.reportLocation) {
1756 // calculate who to blame for power
1757 // This is somewhat arbitrary. We pick a threshold interval
1758 // that is slightly higher that the minimum interval, and
1759 // spread the blame across all applications with a request
1760 // under that threshold.
1761 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
1762 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001763 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001764 LocationRequest locationRequest = record.mRequest;
Svet Ganove998c732016-06-10 00:12:38 -07001765
1766 // Don't assign battery blame for update records whose
1767 // client has no permission to receive location data.
1768 if (!providerRequest.locationRequests.contains(locationRequest)) {
1769 continue;
1770 }
1771
Victoria Leaseb711d572012-10-02 13:14:11 -07001772 if (locationRequest.getInterval() <= thresholdInterval) {
David Christiee55c9682013-08-22 10:10:34 -07001773 if (record.mReceiver.mWorkSource != null
1774 && record.mReceiver.mWorkSource.size() > 0
1775 && record.mReceiver.mWorkSource.getName(0) != null) {
David Christie82edc9b2013-07-19 11:31:42 -07001776 // Assign blame to another work source.
David Christiee55c9682013-08-22 10:10:34 -07001777 // Can only assign blame if the WorkSource contains names.
David Christie82edc9b2013-07-19 11:31:42 -07001778 worksource.add(record.mReceiver.mWorkSource);
1779 } else {
1780 // Assign blame to caller.
1781 worksource.add(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001782 record.mReceiver.mIdentity.mUid,
1783 record.mReceiver.mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001784 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001785 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001786 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001787 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001788 }
1789 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001790
1791 if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
1792 p.setRequest(providerRequest, worksource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001793 }
1794
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001795 @Override
1796 public String[] getBackgroundThrottlingWhitelist() {
1797 synchronized (mLock) {
1798 return mBackgroundThrottlePackageWhitelist.toArray(
1799 new String[mBackgroundThrottlePackageWhitelist.size()]);
1800 }
1801 }
1802
1803 private void updateBackgroundThrottlingWhitelistLocked() {
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001804 String setting = Settings.Global.getString(
1805 mContext.getContentResolver(),
1806 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
1807 if (setting == null) {
1808 setting = "";
1809 }
1810
1811 mBackgroundThrottlePackageWhitelist.clear();
1812 mBackgroundThrottlePackageWhitelist.addAll(
1813 SystemConfig.getInstance().getAllowUnthrottledLocation());
1814 mBackgroundThrottlePackageWhitelist.addAll(
1815 Arrays.asList(setting.split(",")));
1816 }
1817
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001818 private boolean isThrottlingExemptLocked(Identity identity) {
1819 if (identity.mUid == Process.SYSTEM_UID) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001820 return true;
1821 }
1822
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001823 if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001824 return true;
1825 }
1826
1827 for (LocationProviderProxy provider : mProxyProviders) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001828 if (identity.mPackageName.equals(provider.getConnectedPackageName())) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001829 return true;
1830 }
1831 }
1832
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001833 return false;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001834 }
1835
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001836 private class UpdateRecord {
1837 final String mProvider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001838 final LocationRequest mRealRequest; // original request from client
1839 LocationRequest mRequest; // possibly throttled version of the request
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 final Receiver mReceiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001841 boolean mIsForegroundUid;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001842 Location mLastFixBroadcast;
1843 long mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844
1845 /**
1846 * Note: must be constructed with lock held.
1847 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001848 UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001849 mProvider = provider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001850 mRealRequest = request;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001851 mRequest = request;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001852 mReceiver = receiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001853 mIsForegroundUid = isImportanceForeground(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001854 mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001855
1856 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1857 if (records == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001858 records = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001859 mRecordsByProvider.put(provider, records);
1860 }
1861 if (!records.contains(this)) {
1862 records.add(this);
1863 }
David Christie2ff96af2014-01-30 16:09:37 -08001864
1865 // Update statistics for historical location requests by package/provider
1866 mRequestStatistics.startRequesting(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001867 mReceiver.mIdentity.mPackageName, provider, request.getInterval());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001868 }
1869
1870 /**
David Christie2ff96af2014-01-30 16:09:37 -08001871 * Method to be called when a record will no longer be used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001872 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001873 void disposeLocked(boolean removeReceiver) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001874 mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider);
David Christie2ff96af2014-01-30 16:09:37 -08001875
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001876 // remove from mRecordsByProvider
1877 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
1878 if (globalRecords != null) {
1879 globalRecords.remove(this);
1880 }
1881
1882 if (!removeReceiver) return; // the caller will handle the rest
1883
1884 // remove from Receiver#mUpdateRecords
1885 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
1886 if (receiverRecords != null) {
1887 receiverRecords.remove(this.mProvider);
1888
1889 // and also remove the Receiver if it has no more update records
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001890 if (receiverRecords.size() == 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001891 removeUpdatesLocked(mReceiver);
1892 }
Mike Lockwood3a76fd62009-09-01 07:26:56 -04001893 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001894 }
1895
1896 @Override
1897 public String toString() {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001898 return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
1899 + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground" : " background")
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001900 + ")" + " " + mRealRequest + "]";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001901 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001902 }
1903
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001904 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -07001905 String packageName, WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001906 IBinder binder = listener.asBinder();
1907 Receiver receiver = mReceivers.get(binder);
1908 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07001909 receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
1910 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001911 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001912 receiver.getListener().asBinder().linkToDeath(receiver, 0);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001913 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001914 Slog.e(TAG, "linkToDeath failed:", e);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001915 return null;
1916 }
Wen Jingcb3ab222014-03-27 13:42:59 +08001917 mReceivers.put(binder, receiver);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001918 }
1919 return receiver;
1920 }
1921
David Christie82edc9b2013-07-19 11:31:42 -07001922 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
David Christie40e57822013-07-30 11:36:48 -07001923 WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001924 Receiver receiver = mReceivers.get(intent);
1925 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07001926 receiver = new Receiver(null, intent, pid, uid, packageName, workSource,
1927 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001928 mReceivers.put(intent, receiver);
1929 }
1930 return receiver;
1931 }
1932
Victoria Lease37425c32012-10-16 16:08:48 -07001933 /**
1934 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
1935 * and consistency requirements.
1936 *
1937 * @param request the LocationRequest from which to create a sanitized version
Victoria Lease37425c32012-10-16 16:08:48 -07001938 * @return a version of request that meets the given resolution and consistency requirements
1939 * @hide
1940 */
1941 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel) {
1942 LocationRequest sanitizedRequest = new LocationRequest(request);
1943 if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
1944 switch (sanitizedRequest.getQuality()) {
Victoria Lease09016ab2012-09-16 12:33:15 -07001945 case LocationRequest.ACCURACY_FINE:
Victoria Lease37425c32012-10-16 16:08:48 -07001946 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
Victoria Lease09016ab2012-09-16 12:33:15 -07001947 break;
1948 case LocationRequest.POWER_HIGH:
Victoria Lease37425c32012-10-16 16:08:48 -07001949 sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
Victoria Lease09016ab2012-09-16 12:33:15 -07001950 break;
1951 }
1952 // throttle
Victoria Lease37425c32012-10-16 16:08:48 -07001953 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1954 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001955 }
Victoria Lease37425c32012-10-16 16:08:48 -07001956 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1957 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001958 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07001959 }
Nick Pelly4e31c4f2012-08-13 19:35:39 -07001960 // make getFastestInterval() the minimum of interval and fastest interval
Victoria Lease37425c32012-10-16 16:08:48 -07001961 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07001962 request.setFastestInterval(request.getInterval());
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001963 }
Victoria Lease37425c32012-10-16 16:08:48 -07001964 return sanitizedRequest;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001965 }
1966
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001967 private void checkPackageName(String packageName) {
Nick Pellye0fd6932012-07-11 10:26:13 -07001968 if (packageName == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001969 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07001970 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001971 int uid = Binder.getCallingUid();
Nick Pellye0fd6932012-07-11 10:26:13 -07001972 String[] packages = mPackageManager.getPackagesForUid(uid);
1973 if (packages == null) {
1974 throw new SecurityException("invalid UID " + uid);
1975 }
1976 for (String pkg : packages) {
1977 if (packageName.equals(pkg)) return;
1978 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001979 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07001980 }
1981
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001982 private void checkPendingIntent(PendingIntent intent) {
1983 if (intent == null) {
1984 throw new IllegalArgumentException("invalid pending intent: " + intent);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001985 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001986 }
1987
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001988 private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent,
David Christie40e57822013-07-30 11:36:48 -07001989 int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001990 if (intent == null && listener == null) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001991 throw new IllegalArgumentException("need either listener or intent");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001992 } else if (intent != null && listener != null) {
1993 throw new IllegalArgumentException("cannot register both listener and intent");
1994 } else if (intent != null) {
1995 checkPendingIntent(intent);
David Christie40e57822013-07-30 11:36:48 -07001996 return getReceiverLocked(intent, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001997 } else {
David Christie40e57822013-07-30 11:36:48 -07001998 return getReceiverLocked(listener, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001999 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002000 }
2001
Nick Pellye0fd6932012-07-11 10:26:13 -07002002 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002003 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
2004 PendingIntent intent, String packageName) {
2005 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2006 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002007 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2008 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2009 request.getProvider());
David Christie82edc9b2013-07-19 11:31:42 -07002010 WorkSource workSource = request.getWorkSource();
2011 if (workSource != null && workSource.size() > 0) {
David Christie40e57822013-07-30 11:36:48 -07002012 checkDeviceStatsAllowed();
2013 }
2014 boolean hideFromAppOps = request.getHideFromAppOps();
2015 if (hideFromAppOps) {
2016 checkUpdateAppOpsAllowed();
David Christie82edc9b2013-07-19 11:31:42 -07002017 }
Victoria Lease37425c32012-10-16 16:08:48 -07002018 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002019
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002020 final int pid = Binder.getCallingPid();
2021 final int uid = Binder.getCallingUid();
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002022 // providers may use public location API's, need to clear identity
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002023 long identity = Binder.clearCallingIdentity();
2024 try {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002025 // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2026 // a location.
David Christieb870dbf2015-06-22 12:42:53 -07002027 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002028
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002029 synchronized (mLock) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002030 Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
David Christie40e57822013-07-30 11:36:48 -07002031 packageName, workSource, hideFromAppOps);
Victoria Lease37425c32012-10-16 16:08:48 -07002032 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
Mike Lockwood2d4d1bf2010-10-18 17:06:26 -04002033 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002034 } finally {
2035 Binder.restoreCallingIdentity(identity);
2036 }
2037 }
2038
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002039 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
2040 int pid, int uid, String packageName) {
2041 // Figure out the provider. Either its explicitly request (legacy use cases), or
2042 // use the fused provider
2043 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2044 String name = request.getProvider();
Victoria Lease09016ab2012-09-16 12:33:15 -07002045 if (name == null) {
2046 throw new IllegalArgumentException("provider name must not be null");
2047 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -07002048
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002049 LocationProviderInterface provider = mProvidersByName.get(name);
2050 if (provider == null) {
Victoria Leaseb30f3832013-10-13 12:15:40 -07002051 throw new IllegalArgumentException("provider doesn't exist: " + name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002052 }
2053
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002054 UpdateRecord record = new UpdateRecord(name, request, receiver);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002055 if (D) Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
2056 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
2057 + (record.mIsForegroundUid ? "foreground" : "background")
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002058 + (isThrottlingExemptLocked(receiver.mIdentity)
2059 ? " [whitelisted]" : "") + ")");
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002060
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002061 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
2062 if (oldRecord != null) {
2063 oldRecord.disposeLocked(false);
2064 }
2065
Victoria Lease09eeaec2013-02-05 11:34:13 -08002066 boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002067 if (isProviderEnabled) {
2068 applyRequirementsLocked(name);
2069 } else {
2070 // Notify the listener that updates are currently disabled
2071 receiver.callProviderEnabledLocked(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002072 }
David Christie0b837452013-07-29 16:02:13 -07002073 // Update the monitoring here just in case multiple location requests were added to the
2074 // same receiver (this request may be high power and the initial might not have been).
2075 receiver.updateMonitoring(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002076 }
2077
Nick Pellye0fd6932012-07-11 10:26:13 -07002078 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002079 public void removeUpdates(ILocationListener listener, PendingIntent intent,
2080 String packageName) {
2081 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002082
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002083 final int pid = Binder.getCallingPid();
2084 final int uid = Binder.getCallingUid();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002085
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002086 synchronized (mLock) {
David Christie82edc9b2013-07-19 11:31:42 -07002087 WorkSource workSource = null;
David Christie40e57822013-07-30 11:36:48 -07002088 boolean hideFromAppOps = false;
2089 Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid,
2090 packageName, workSource, hideFromAppOps);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002091
2092 // providers may use public location API's, need to clear identity
2093 long identity = Binder.clearCallingIdentity();
2094 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002095 removeUpdatesLocked(receiver);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002096 } finally {
2097 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002098 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002099 }
2100 }
2101
2102 private void removeUpdatesLocked(Receiver receiver) {
Dianne Hackborn7ff30112012-11-08 11:12:09 -08002103 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002104
2105 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
2106 receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
2107 synchronized (receiver) {
Victoria Lease0aa28602013-05-29 15:28:26 -07002108 receiver.clearPendingBroadcastsLocked();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002109 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002110 }
2111
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07002112 receiver.updateMonitoring(false);
2113
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002114 // Record which providers were associated with this listener
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002115 HashSet<String> providers = new HashSet<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002116 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2117 if (oldRecords != null) {
2118 // Call dispose() on the obsolete update records.
2119 for (UpdateRecord record : oldRecords.values()) {
David Christie2ff96af2014-01-30 16:09:37 -08002120 // Update statistics for historical location requests by package/provider
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002121 record.disposeLocked(false);
2122 }
2123 // Accumulate providers
2124 providers.addAll(oldRecords.keySet());
2125 }
2126
2127 // update provider
2128 for (String provider : providers) {
2129 // If provider is already disabled, don't need to do anything
Victoria Lease09eeaec2013-02-05 11:34:13 -08002130 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002131 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002132 }
2133
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002134 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002135 }
2136 }
2137
Dianne Hackbornc2293022013-02-06 23:14:49 -08002138 private void applyAllProviderRequirementsLocked() {
2139 for (LocationProviderInterface p : mProviders) {
2140 // If provider is already disabled, don't need to do anything
Dianne Hackborn64d41d72013-02-07 00:33:31 -08002141 if (!isAllowedByCurrentUserSettingsLocked(p.getName())) {
Dianne Hackbornc2293022013-02-06 23:14:49 -08002142 continue;
2143 }
2144
2145 applyRequirementsLocked(p.getName());
2146 }
2147 }
2148
Nick Pellye0fd6932012-07-11 10:26:13 -07002149 @Override
Nick Pelly4035f5a2012-08-17 14:43:49 -07002150 public Location getLastLocation(LocationRequest request, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002151 if (D) Log.d(TAG, "getLastLocation: " + request);
2152 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002153 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly4035f5a2012-08-17 14:43:49 -07002154 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002155 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2156 request.getProvider());
2157 // no need to sanitize this request, as only the provider name is used
Nick Pelly4035f5a2012-08-17 14:43:49 -07002158
David Christieb870dbf2015-06-22 12:42:53 -07002159 final int pid = Binder.getCallingPid();
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002160 final int uid = Binder.getCallingUid();
2161 final long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07002162 try {
2163 if (mBlacklist.isBlacklisted(packageName)) {
2164 if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
2165 packageName);
Victoria Lease09016ab2012-09-16 12:33:15 -07002166 return null;
2167 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002168
David Christieb870dbf2015-06-22 12:42:53 -07002169 if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel)) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002170 if (D) Log.d(TAG, "not returning last loc for no op app: " +
2171 packageName);
2172 return null;
2173 }
2174
Victoria Leaseb711d572012-10-02 13:14:11 -07002175 synchronized (mLock) {
2176 // Figure out the provider. Either its explicitly request (deprecated API's),
2177 // or use the fused provider
2178 String name = request.getProvider();
2179 if (name == null) name = LocationManager.FUSED_PROVIDER;
2180 LocationProviderInterface provider = mProvidersByName.get(name);
2181 if (provider == null) return null;
2182
Victoria Lease09eeaec2013-02-05 11:34:13 -08002183 if (!isAllowedByUserSettingsLocked(name, uid)) return null;
Victoria Leaseb711d572012-10-02 13:14:11 -07002184
David Christie1b9b7b12013-04-15 15:31:11 -07002185 Location location;
2186 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2187 // Make sure that an app with coarse permissions can't get frequent location
2188 // updates by calling LocationManager.getLastKnownLocation repeatedly.
2189 location = mLastLocationCoarseInterval.get(name);
2190 } else {
2191 location = mLastLocation.get(name);
2192 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002193 if (location == null) {
2194 return null;
2195 }
Victoria Lease37425c32012-10-16 16:08:48 -07002196 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002197 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2198 if (noGPSLocation != null) {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002199 return new Location(mLocationFudger.getOrCreate(noGPSLocation));
Victoria Leaseb711d572012-10-02 13:14:11 -07002200 }
Victoria Lease37425c32012-10-16 16:08:48 -07002201 } else {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002202 return new Location(location);
Victoria Lease09016ab2012-09-16 12:33:15 -07002203 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002204 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002205 return null;
2206 } finally {
2207 Binder.restoreCallingIdentity(identity);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002208 }
2209 }
2210
2211 @Override
2212 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
2213 String packageName) {
2214 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002215 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2216 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002217 checkPendingIntent(intent);
2218 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002219 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2220 request.getProvider());
2221 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002222
Victoria Lease37425c32012-10-16 16:08:48 -07002223 if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002224
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002225 // geo-fence manager uses the public location API, need to clear identity
2226 int uid = Binder.getCallingUid();
Xiaohui Chena4490622015-09-22 15:29:31 -07002227 // TODO: http://b/23822629
2228 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
Victoria Lease56e675b2012-11-05 19:25:06 -08002229 // temporary measure until geofences work for secondary users
2230 Log.w(TAG, "proximity alerts are currently available only to the primary user");
2231 return;
2232 }
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002233 long identity = Binder.clearCallingIdentity();
2234 try {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002235 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
2236 uid, packageName);
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002237 } finally {
2238 Binder.restoreCallingIdentity(identity);
2239 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002240 }
2241
2242 @Override
2243 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002244 checkPendingIntent(intent);
2245 checkPackageName(packageName);
2246
2247 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2248
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002249 // geo-fence manager uses the public location API, need to clear identity
2250 long identity = Binder.clearCallingIdentity();
2251 try {
2252 mGeofenceManager.removeFence(geofence, intent);
2253 } finally {
2254 Binder.restoreCallingIdentity(identity);
2255 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002256 }
2257
2258
2259 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002260 public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002261 if (!hasGnssPermissions(packageName) || mGnssStatusProvider == null) {
Takayuki Hoshib254ab6a2014-10-23 16:46:02 +09002262 return false;
2263 }
2264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002265 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002266 mGnssStatusProvider.registerGnssStatusCallback(callback);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002267 } catch (RemoteException e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002268 Slog.e(TAG, "mGpsStatusProvider.registerGnssStatusCallback failed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269 return false;
2270 }
2271 return true;
2272 }
2273
Nick Pellye0fd6932012-07-11 10:26:13 -07002274 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002275 public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002276 synchronized (mLock) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002277 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002278 mGnssStatusProvider.unregisterGnssStatusCallback(callback);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002279 } catch (Exception e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002280 Slog.e(TAG, "mGpsStatusProvider.unregisterGnssStatusCallback failed", e);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002281 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002282 }
2283 }
2284
Nick Pellye0fd6932012-07-11 10:26:13 -07002285 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002286 public boolean addGnssMeasurementsListener(
2287 IGnssMeasurementsListener listener,
destradaaea8a8a62014-06-23 18:19:03 -07002288 String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002289 if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
destradaaea8a8a62014-06-23 18:19:03 -07002290 return false;
2291 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002292
2293 synchronized (mLock) {
2294 Identity callerIdentity
2295 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
2296 mGnssMeasurementsListeners.put(listener, callerIdentity);
2297 long identity = Binder.clearCallingIdentity();
2298 try {
2299 if (isThrottlingExemptLocked(callerIdentity)
2300 || isImportanceForeground(
2301 mActivityManager.getPackageImportance(packageName))) {
2302 return mGnssMeasurementsProvider.addListener(listener);
2303 }
2304 } finally {
2305 Binder.restoreCallingIdentity(identity);
2306 }
2307
2308 return true;
2309 }
destradaaea8a8a62014-06-23 18:19:03 -07002310 }
2311
2312 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002313 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
2314 if (mGnssMeasurementsProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002315 synchronized (mLock) {
2316 mGnssMeasurementsListeners.remove(listener);
2317 mGnssMeasurementsProvider.removeListener(listener);
2318 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002319 }
destradaaea8a8a62014-06-23 18:19:03 -07002320 }
2321
2322 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002323 public boolean addGnssNavigationMessageListener(
2324 IGnssNavigationMessageListener listener,
destradaa4b3e3932014-07-21 18:01:47 -07002325 String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002326 if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) {
destradaa4b3e3932014-07-21 18:01:47 -07002327 return false;
2328 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002329
2330 synchronized (mLock) {
2331 Identity callerIdentity
2332 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
2333 mGnssNavigationMessageListeners.put(listener, callerIdentity);
2334 long identity = Binder.clearCallingIdentity();
2335 try {
2336 if (isThrottlingExemptLocked(callerIdentity)
2337 || isImportanceForeground(
2338 mActivityManager.getPackageImportance(packageName))) {
2339 return mGnssNavigationMessageProvider.addListener(listener);
2340 }
2341 } finally {
2342 Binder.restoreCallingIdentity(identity);
2343 }
2344
2345 return true;
2346 }
destradaa4b3e3932014-07-21 18:01:47 -07002347 }
2348
2349 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002350 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
2351 if (mGnssNavigationMessageProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002352 synchronized (mLock) {
2353 mGnssNavigationMessageListeners.remove(listener);
2354 mGnssNavigationMessageProvider.removeListener(listener);
2355 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002356 }
destradaa4b3e3932014-07-21 18:01:47 -07002357 }
2358
2359 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002360 public boolean sendExtraCommand(String provider, String command, Bundle extras) {
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002361 if (provider == null) {
2362 // throw NullPointerException to remain compatible with previous implementation
2363 throw new NullPointerException();
2364 }
Victoria Lease37425c32012-10-16 16:08:48 -07002365 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2366 provider);
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002368 // and check for ACCESS_LOCATION_EXTRA_COMMANDS
Mike Lockwoodb7e99222009-07-07 13:18:21 -04002369 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002370 != PackageManager.PERMISSION_GRANTED)) {
2371 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
2372 }
2373
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002374 synchronized (mLock) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002375 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002376 if (p == null) return false;
Nick Pellye0fd6932012-07-11 10:26:13 -07002377
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002378 return p.sendExtraCommand(command, extras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002379 }
2380 }
2381
Nick Pellye0fd6932012-07-11 10:26:13 -07002382 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002383 public boolean sendNiResponse(int notifId, int userResponse) {
Mike Lockwood18ad9f62009-08-27 14:01:23 -07002384 if (Binder.getCallingUid() != Process.myUid()) {
2385 throw new SecurityException(
2386 "calling sendNiResponse from outside of the system is not allowed");
2387 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002388 try {
2389 return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002390 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002391 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
Danke Xie22d1f9f2009-08-18 18:28:45 -04002392 return false;
2393 }
2394 }
2395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002396 /**
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002397 * @return null if the provider does not exist
Alexey Tarasovf2db9fb2009-09-01 02:37:07 +11002398 * @throws SecurityException if the provider is not allowed to be
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002399 * accessed by the caller
2400 */
Nick Pellye0fd6932012-07-11 10:26:13 -07002401 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002402 public ProviderProperties getProviderProperties(String provider) {
Laurent Tub7f9d252012-10-16 14:25:00 -07002403 if (mProvidersByName.get(provider) == null) {
David Christie2ff96af2014-01-30 16:09:37 -08002404 return null;
Laurent Tub7f9d252012-10-16 14:25:00 -07002405 }
2406
Victoria Lease37425c32012-10-16 16:08:48 -07002407 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2408 provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002409
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002410 LocationProviderInterface p;
2411 synchronized (mLock) {
2412 p = mProvidersByName.get(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002413 }
2414
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002415 if (p == null) return null;
2416 return p.getProperties();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002417 }
2418
Jason Monkb71218a2015-06-17 14:44:39 -04002419 /**
2420 * @return null if the provider does not exist
2421 * @throws SecurityException if the provider is not allowed to be
2422 * accessed by the caller
2423 */
2424 @Override
2425 public String getNetworkProviderPackage() {
2426 LocationProviderInterface p;
2427 synchronized (mLock) {
2428 if (mProvidersByName.get(LocationManager.NETWORK_PROVIDER) == null) {
2429 return null;
2430 }
2431 p = mProvidersByName.get(LocationManager.NETWORK_PROVIDER);
2432 }
2433
2434 if (p instanceof LocationProviderProxy) {
2435 return ((LocationProviderProxy) p).getConnectedPackageName();
2436 }
2437 return null;
2438 }
2439
Nick Pellye0fd6932012-07-11 10:26:13 -07002440 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002441 public boolean isProviderEnabled(String provider) {
Tom O'Neilld5759432013-09-11 11:03:03 -07002442 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2443 // so we discourage its use
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002444 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
2445
Victoria Lease09eeaec2013-02-05 11:34:13 -08002446 int uid = Binder.getCallingUid();
Victoria Lease269518e2012-10-29 08:25:39 -07002447 long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07002448 try {
2449 synchronized (mLock) {
2450 LocationProviderInterface p = mProvidersByName.get(provider);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002451 return p != null && isAllowedByUserSettingsLocked(provider, uid);
Victoria Leaseb711d572012-10-02 13:14:11 -07002452 }
2453 } finally {
2454 Binder.restoreCallingIdentity(identity);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002455 }
2456 }
2457
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002458 /**
2459 * Returns "true" if the UID belongs to a bound location provider.
2460 *
2461 * @param uid the uid
2462 * @return true if uid belongs to a bound location provider
2463 */
2464 private boolean isUidALocationProvider(int uid) {
2465 if (uid == Process.SYSTEM_UID) {
2466 return true;
2467 }
2468 if (mGeocodeProvider != null) {
David Christie1f141c12014-05-14 15:11:15 -07002469 if (doesUidHavePackage(uid, mGeocodeProvider.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002470 }
2471 for (LocationProviderProxy proxy : mProxyProviders) {
David Christie1f141c12014-05-14 15:11:15 -07002472 if (doesUidHavePackage(uid, proxy.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002473 }
2474 return false;
2475 }
2476
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002477 private void checkCallerIsProvider() {
2478 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
2479 == PackageManager.PERMISSION_GRANTED) {
2480 return;
2481 }
2482
2483 // Previously we only used the INSTALL_LOCATION_PROVIDER
2484 // check. But that is system or signature
2485 // protection level which is not flexible enough for
2486 // providers installed oustide the system image. So
2487 // also allow providers with a UID matching the
2488 // currently bound package name
2489
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002490 if (isUidALocationProvider(Binder.getCallingUid())) {
2491 return;
2492 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002493
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002494 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
2495 "or UID of a currently bound location provider");
2496 }
2497
David Christie1f141c12014-05-14 15:11:15 -07002498 /**
2499 * Returns true if the given package belongs to the given uid.
2500 */
2501 private boolean doesUidHavePackage(int uid, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002502 if (packageName == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002503 return false;
2504 }
David Christie1f141c12014-05-14 15:11:15 -07002505 String[] packageNames = mPackageManager.getPackagesForUid(uid);
2506 if (packageNames == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002507 return false;
2508 }
David Christie1f141c12014-05-14 15:11:15 -07002509 for (String name : packageNames) {
2510 if (packageName.equals(name)) {
2511 return true;
2512 }
2513 }
2514 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002515 }
2516
Nick Pellye0fd6932012-07-11 10:26:13 -07002517 @Override
Mike Lockwooda4903f22010-02-17 06:42:23 -05002518 public void reportLocation(Location location, boolean passive) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002519 checkCallerIsProvider();
Mike Lockwood275555c2009-05-01 11:30:34 -04002520
Nick Pelly2eeeec22012-07-18 13:13:37 -07002521 if (!location.isComplete()) {
2522 Log.w(TAG, "Dropping incomplete location: " + location);
2523 return;
2524 }
2525
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002526 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location);
2527 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location);
Mike Lockwooda4903f22010-02-17 06:42:23 -05002528 m.arg1 = (passive ? 1 : 0);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002529 mLocationHandler.sendMessageAtFrontOfQueue(m);
2530 }
2531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002532
Laurent Tu75defb62012-11-01 16:21:52 -07002533 private static boolean shouldBroadcastSafe(
2534 Location loc, Location lastLoc, UpdateRecord record, long now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002535 // Always broadcast the first update
2536 if (lastLoc == null) {
2537 return true;
2538 }
2539
Nick Pellyf1be6862012-05-15 10:53:42 -07002540 // Check whether sufficient time has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002541 long minTime = record.mRealRequest.getFastestInterval();
David Christie1b9b7b12013-04-15 15:31:11 -07002542 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
2543 / NANOS_PER_MILLI;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002544 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002545 return false;
2546 }
2547
2548 // Check whether sufficient distance has been traveled
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002549 double minDistance = record.mRealRequest.getSmallestDisplacement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002550 if (minDistance > 0.0) {
2551 if (loc.distanceTo(lastLoc) <= minDistance) {
2552 return false;
2553 }
2554 }
2555
Laurent Tu75defb62012-11-01 16:21:52 -07002556 // Check whether sufficient number of udpates is left
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002557 if (record.mRealRequest.getNumUpdates() <= 0) {
Laurent Tu75defb62012-11-01 16:21:52 -07002558 return false;
2559 }
2560
2561 // Check whether the expiry date has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002562 return record.mRealRequest.getExpireAt() >= now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002563 }
2564
Mike Lockwooda4903f22010-02-17 06:42:23 -05002565 private void handleLocationChangedLocked(Location location, boolean passive) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002566 if (D) Log.d(TAG, "incoming location: " + location);
2567
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002568 long now = SystemClock.elapsedRealtime();
Mike Lockwooda4903f22010-02-17 06:42:23 -05002569 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570
Laurent Tu60ec50a2012-10-04 17:00:10 -07002571 // Skip if the provider is unknown.
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002572 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002573 if (p == null) return;
2574
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002575 // Update last known locations
Victoria Lease09016ab2012-09-16 12:33:15 -07002576 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002577 Location lastNoGPSLocation;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002578 Location lastLocation = mLastLocation.get(provider);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002579 if (lastLocation == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002580 lastLocation = new Location(provider);
2581 mLastLocation.put(provider, lastLocation);
Victoria Lease09016ab2012-09-16 12:33:15 -07002582 } else {
2583 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2584 if (noGPSLocation == null && lastNoGPSLocation != null) {
2585 // New location has no no-GPS location: adopt last no-GPS location. This is set
2586 // directly into location because we do not want to notify COARSE clients.
2587 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
2588 }
Mike Lockwood4e50b782009-04-03 08:24:43 -07002589 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002590 lastLocation.set(location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002591
David Christie1b9b7b12013-04-15 15:31:11 -07002592 // Update last known coarse interval location if enough time has passed.
2593 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider);
2594 if (lastLocationCoarseInterval == null) {
2595 lastLocationCoarseInterval = new Location(location);
2596 mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval);
2597 }
2598 long timeDiffNanos = location.getElapsedRealtimeNanos()
2599 - lastLocationCoarseInterval.getElapsedRealtimeNanos();
2600 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
2601 lastLocationCoarseInterval.set(location);
2602 }
2603 // Don't ever return a coarse location that is more recent than the allowed update
2604 // interval (i.e. don't allow an app to keep registering and unregistering for
2605 // location updates to overcome the minimum interval).
2606 noGPSLocation =
2607 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2608
Laurent Tu60ec50a2012-10-04 17:00:10 -07002609 // Skip if there are no UpdateRecords for this provider.
2610 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
2611 if (records == null || records.size() == 0) return;
2612
Victoria Lease09016ab2012-09-16 12:33:15 -07002613 // Fetch coarse location
2614 Location coarseLocation = null;
David Christie1b9b7b12013-04-15 15:31:11 -07002615 if (noGPSLocation != null) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002616 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
2617 }
2618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002619 // Fetch latest status update time
2620 long newStatusUpdateTime = p.getStatusUpdateTime();
2621
David Christie2ff96af2014-01-30 16:09:37 -08002622 // Get latest status
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002623 Bundle extras = new Bundle();
2624 int status = p.getStatus(extras);
2625
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002626 ArrayList<Receiver> deadReceivers = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002627 ArrayList<UpdateRecord> deadUpdateRecords = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07002628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002629 // Broadcast location or status to all listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002630 for (UpdateRecord r : records) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002631 Receiver receiver = r.mReceiver;
Mike Lockwood03ca2162010-04-01 08:10:09 -07002632 boolean receiverDead = false;
Nick Pelly4035f5a2012-08-17 14:43:49 -07002633
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002634 int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid);
2635 if (!isCurrentProfile(receiverUserId)
2636 && !isUidALocationProvider(receiver.mIdentity.mUid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002637 if (D) {
Victoria Lease269518e2012-10-29 08:25:39 -07002638 Log.d(TAG, "skipping loc update for background user " + receiverUserId +
Victoria Leaseb711d572012-10-02 13:14:11 -07002639 " (current user: " + mCurrentUserId + ", app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002640 receiver.mIdentity.mPackageName + ")");
Victoria Leaseb711d572012-10-02 13:14:11 -07002641 }
2642 continue;
2643 }
2644
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002645 if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) {
Nick Pelly4035f5a2012-08-17 14:43:49 -07002646 if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002647 receiver.mIdentity.mPackageName);
Nick Pelly4035f5a2012-08-17 14:43:49 -07002648 continue;
2649 }
2650
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002651 if (!reportLocationAccessNoThrow(
2652 receiver.mIdentity.mPid,
2653 receiver.mIdentity.mUid,
2654 receiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002655 receiver.mAllowedResolutionLevel)) {
2656 if (D) Log.d(TAG, "skipping loc update for no op app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002657 receiver.mIdentity.mPackageName);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002658 continue;
2659 }
2660
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002661 Location notifyLocation;
Victoria Lease37425c32012-10-16 16:08:48 -07002662 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2663 notifyLocation = coarseLocation; // use coarse location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002664 } else {
Victoria Lease37425c32012-10-16 16:08:48 -07002665 notifyLocation = lastLocation; // use fine location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002666 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002667 if (notifyLocation != null) {
2668 Location lastLoc = r.mLastFixBroadcast;
Laurent Tu75defb62012-11-01 16:21:52 -07002669 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002670 if (lastLoc == null) {
2671 lastLoc = new Location(notifyLocation);
2672 r.mLastFixBroadcast = lastLoc;
2673 } else {
2674 lastLoc.set(notifyLocation);
2675 }
2676 if (!receiver.callLocationChangedLocked(notifyLocation)) {
2677 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
2678 receiverDead = true;
2679 }
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002680 r.mRealRequest.decrementNumUpdates();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002681 }
2682 }
2683
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002684 long prevStatusUpdateTime = r.mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002685 if ((newStatusUpdateTime > prevStatusUpdateTime) &&
Victoria Lease09016ab2012-09-16 12:33:15 -07002686 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002687
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002688 r.mLastStatusBroadcast = newStatusUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002689 if (!receiver.callStatusChangedLocked(provider, status, extras)) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002690 receiverDead = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002691 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
Mike Lockwood03ca2162010-04-01 08:10:09 -07002692 }
2693 }
2694
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002695 // track expired records
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002696 if (r.mRealRequest.getNumUpdates() <= 0 || r.mRealRequest.getExpireAt() < now) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002697 if (deadUpdateRecords == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002698 deadUpdateRecords = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002699 }
2700 deadUpdateRecords.add(r);
2701 }
2702 // track dead receivers
2703 if (receiverDead) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002704 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002705 deadReceivers = new ArrayList<>();
Mike Lockwood03ca2162010-04-01 08:10:09 -07002706 }
2707 if (!deadReceivers.contains(receiver)) {
2708 deadReceivers.add(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002709 }
2710 }
2711 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002712
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002713 // remove dead records and receivers outside the loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002715 for (Receiver receiver : deadReceivers) {
2716 removeUpdatesLocked(receiver);
2717 }
2718 }
2719 if (deadUpdateRecords != null) {
2720 for (UpdateRecord r : deadUpdateRecords) {
2721 r.disposeLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002722 }
Victoria Lease8b38b292012-12-04 15:04:43 -08002723 applyRequirementsLocked(provider);
2724 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002725 }
2726
2727 private class LocationWorkerHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08002728 public LocationWorkerHandler(Looper looper) {
2729 super(looper, null, true);
2730 }
2731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002732 @Override
2733 public void handleMessage(Message msg) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002734 switch (msg.what) {
2735 case MSG_LOCATION_CHANGED:
2736 handleLocationChanged((Location) msg.obj, msg.arg1 == 1);
2737 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002738 }
2739 }
2740 }
2741
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002742 private boolean isMockProvider(String provider) {
2743 synchronized (mLock) {
2744 return mMockProviders.containsKey(provider);
2745 }
2746 }
2747
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002748 private void handleLocationChanged(Location location, boolean passive) {
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002749 // create a working copy of the incoming Location so that the service can modify it without
2750 // disturbing the caller's copy
2751 Location myLocation = new Location(location);
2752 String provider = myLocation.getProvider();
2753
2754 // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this
2755 // bit if location did not come from a mock provider because passive/fused providers can
2756 // forward locations from mock providers, and should not grant them legitimacy in doing so.
2757 if (!myLocation.isFromMockProvider() && isMockProvider(provider)) {
2758 myLocation.setIsFromMockProvider(true);
2759 }
Jeff Sharkey5e613312012-01-30 11:16:20 -08002760
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002761 synchronized (mLock) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08002762 if (isAllowedByCurrentUserSettingsLocked(provider)) {
2763 if (!passive) {
2764 // notify passive provider of the new location
2765 mPassiveProvider.updateLocation(myLocation);
2766 }
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002767 handleLocationChangedLocked(myLocation, passive);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002768 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002769 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002770 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002771
Mike Lockwoode97ae402010-09-29 15:23:46 -04002772 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
2773 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002774 public void onPackageDisappeared(String packageName, int reason) {
2775 // remove all receivers associated with this package name
2776 synchronized (mLock) {
2777 ArrayList<Receiver> deadReceivers = null;
2778
2779 for (Receiver receiver : mReceivers.values()) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002780 if (receiver.mIdentity.mPackageName.equals(packageName)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002781 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002782 deadReceivers = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002783 }
2784 deadReceivers.add(receiver);
2785 }
2786 }
2787
2788 // perform removal outside of mReceivers loop
2789 if (deadReceivers != null) {
2790 for (Receiver receiver : deadReceivers) {
2791 removeUpdatesLocked(receiver);
2792 }
2793 }
2794 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002795 }
Mike Lockwoode97ae402010-09-29 15:23:46 -04002796 };
2797
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002798 // Geocoder
2799
Nick Pellye0fd6932012-07-11 10:26:13 -07002800 @Override
Mike Lockwoode15735a2010-09-20 17:48:47 -04002801 public boolean geocoderIsPresent() {
Mark Vandevoorde01ac80b2010-05-21 15:43:26 -07002802 return mGeocodeProvider != null;
2803 }
2804
Nick Pellye0fd6932012-07-11 10:26:13 -07002805 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002806 public String getFromLocation(double latitude, double longitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002807 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002808 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002809 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
2810 params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002811 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002812 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002813 }
2814
Mike Lockwooda55c3212009-04-15 11:10:11 -04002815
Nick Pellye0fd6932012-07-11 10:26:13 -07002816 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002817 public String getFromLocationName(String locationName,
Mike Lockwooda55c3212009-04-15 11:10:11 -04002818 double lowerLeftLatitude, double lowerLeftLongitude,
2819 double upperRightLatitude, double upperRightLongitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002820 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002821
2822 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002823 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
2824 lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
2825 maxResults, params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002826 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002827 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002828 }
2829
2830 // Mock Providers
2831
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002832 private boolean canCallerAccessMockLocation(String opPackageName) {
2833 return mAppOps.noteOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(),
2834 opPackageName) == AppOpsManager.MODE_ALLOWED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002835 }
2836
Nick Pellye0fd6932012-07-11 10:26:13 -07002837 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002838 public void addTestProvider(String name, ProviderProperties properties, String opPackageName) {
2839 if (!canCallerAccessMockLocation(opPackageName)) {
2840 return;
2841 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002842
Mike Lockwooda4903f22010-02-17 06:42:23 -05002843 if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
2844 throw new IllegalArgumentException("Cannot mock the passive location provider");
2845 }
2846
Mike Lockwood86328a92009-10-23 08:38:25 -04002847 long identity = Binder.clearCallingIdentity();
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002848 synchronized (mLock) {
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002849 // remove the real provider if we are replacing GPS or network provider
2850 if (LocationManager.GPS_PROVIDER.equals(name)
Nick Pelly1332b532012-08-21 16:25:47 -07002851 || LocationManager.NETWORK_PROVIDER.equals(name)
2852 || LocationManager.FUSED_PROVIDER.equals(name)) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002853 LocationProviderInterface p = mProvidersByName.get(name);
2854 if (p != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002855 removeProviderLocked(p);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002856 }
2857 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09002858 addTestProviderLocked(name, properties);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002859 updateProvidersLocked();
2860 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002861 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002862 }
2863
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09002864 private void addTestProviderLocked(String name, ProviderProperties properties) {
2865 if (mProvidersByName.get(name) != null) {
2866 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
2867 }
2868 MockProvider provider = new MockProvider(name, this, properties);
2869 addProviderLocked(provider);
2870 mMockProviders.put(name, provider);
2871 mLastLocation.put(name, null);
2872 mLastLocationCoarseInterval.put(name, null);
2873 }
2874
Nick Pellye0fd6932012-07-11 10:26:13 -07002875 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002876 public void removeTestProvider(String provider, String opPackageName) {
2877 if (!canCallerAccessMockLocation(opPackageName)) {
2878 return;
2879 }
2880
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002881 synchronized (mLock) {
Tom O'Neill07ee5d12014-03-03 17:48:35 -08002882
2883 // These methods can't be called after removing the test provider, so first make sure
Tom O'Neillfe6d3c52014-03-04 08:26:17 -08002884 // we don't leave anything dangling.
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002885 clearTestProviderEnabled(provider, opPackageName);
2886 clearTestProviderLocation(provider, opPackageName);
2887 clearTestProviderStatus(provider, opPackageName);
Tom O'Neill07ee5d12014-03-03 17:48:35 -08002888
You Kima6d0b6f2012-10-28 03:58:44 +09002889 MockProvider mockProvider = mMockProviders.remove(provider);
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002890 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002891 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2892 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002893 long identity = Binder.clearCallingIdentity();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002894 removeProviderLocked(mProvidersByName.get(provider));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002895
2896 // reinstate real provider if available
2897 LocationProviderInterface realProvider = mRealProviders.get(provider);
2898 if (realProvider != null) {
2899 addProviderLocked(realProvider);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002900 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002901 mLastLocation.put(provider, null);
David Christie1b9b7b12013-04-15 15:31:11 -07002902 mLastLocationCoarseInterval.put(provider, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002903 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04002904 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002905 }
2906 }
2907
Nick Pellye0fd6932012-07-11 10:26:13 -07002908 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002909 public void setTestProviderLocation(String provider, Location loc, String opPackageName) {
2910 if (!canCallerAccessMockLocation(opPackageName)) {
2911 return;
2912 }
2913
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002914 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002915 MockProvider mockProvider = mMockProviders.get(provider);
2916 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002917 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2918 }
Tom O'Neilla206a0f2016-12-15 10:26:28 -08002919
2920 // Ensure that the location is marked as being mock. There's some logic to do this in
2921 // handleLocationChanged(), but it fails if loc has the wrong provider (bug 33091107).
2922 Location mock = new Location(loc);
2923 mock.setIsFromMockProvider(true);
2924
2925 if (!TextUtils.isEmpty(loc.getProvider()) && !provider.equals(loc.getProvider())) {
2926 // The location has an explicit provider that is different from the mock provider
2927 // name. The caller may be trying to fool us via bug 33091107.
2928 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
2929 provider + "!=" + loc.getProvider());
2930 }
2931
Mike Lockwood95427cd2009-05-07 13:27:54 -04002932 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
2933 long identity = Binder.clearCallingIdentity();
Tom O'Neilla206a0f2016-12-15 10:26:28 -08002934 mockProvider.setLocation(mock);
Mike Lockwood95427cd2009-05-07 13:27:54 -04002935 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002936 }
2937 }
2938
Nick Pellye0fd6932012-07-11 10:26:13 -07002939 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002940 public void clearTestProviderLocation(String provider, String opPackageName) {
2941 if (!canCallerAccessMockLocation(opPackageName)) {
2942 return;
2943 }
2944
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002945 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002946 MockProvider mockProvider = mMockProviders.get(provider);
2947 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002948 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2949 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002950 mockProvider.clearLocation();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002951 }
2952 }
2953
Nick Pellye0fd6932012-07-11 10:26:13 -07002954 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002955 public void setTestProviderEnabled(String provider, boolean enabled, String opPackageName) {
2956 if (!canCallerAccessMockLocation(opPackageName)) {
2957 return;
2958 }
2959
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002960 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002961 MockProvider mockProvider = mMockProviders.get(provider);
2962 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002963 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2964 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002965 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002966 if (enabled) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002967 mockProvider.enable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002968 mEnabledProviders.add(provider);
2969 mDisabledProviders.remove(provider);
2970 } else {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002971 mockProvider.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002972 mEnabledProviders.remove(provider);
2973 mDisabledProviders.add(provider);
2974 }
2975 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04002976 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002977 }
2978 }
2979
Nick Pellye0fd6932012-07-11 10:26:13 -07002980 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002981 public void clearTestProviderEnabled(String provider, String opPackageName) {
2982 if (!canCallerAccessMockLocation(opPackageName)) {
2983 return;
2984 }
2985
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002986 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002987 MockProvider mockProvider = mMockProviders.get(provider);
2988 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002989 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2990 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002991 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002992 mEnabledProviders.remove(provider);
2993 mDisabledProviders.remove(provider);
2994 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04002995 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002996 }
2997 }
2998
Nick Pellye0fd6932012-07-11 10:26:13 -07002999 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003000 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime,
3001 String opPackageName) {
3002 if (!canCallerAccessMockLocation(opPackageName)) {
3003 return;
3004 }
3005
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003006 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003007 MockProvider mockProvider = mMockProviders.get(provider);
3008 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003009 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3010 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003011 mockProvider.setStatus(status, extras, updateTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003012 }
3013 }
3014
Nick Pellye0fd6932012-07-11 10:26:13 -07003015 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003016 public void clearTestProviderStatus(String provider, String opPackageName) {
3017 if (!canCallerAccessMockLocation(opPackageName)) {
3018 return;
3019 }
3020
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003021 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003022 MockProvider mockProvider = mMockProviders.get(provider);
3023 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003024 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3025 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003026 mockProvider.clearStatus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003027 }
3028 }
3029
3030 private void log(String log) {
3031 if (Log.isLoggable(TAG, Log.VERBOSE)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003032 Slog.d(TAG, log);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003033 }
3034 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003035
3036 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003037 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003038 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Nick Pellye0fd6932012-07-11 10:26:13 -07003039
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003040 synchronized (mLock) {
Siddharth Raybb608c82017-03-16 11:33:34 -07003041 if (args.length > 0 && args[0].equals("--gnssmetrics")) {
3042 if (mGnssMetricsProvider != null) {
3043 pw.append(mGnssMetricsProvider.getGnssMetricsAsProtoString());
3044 }
3045 return;
3046 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003047 pw.println("Current Location Manager state:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003048 pw.println(" Location Listeners:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003049 for (Receiver receiver : mReceivers.values()) {
3050 pw.println(" " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003051 }
David Christie2ff96af2014-01-30 16:09:37 -08003052 pw.println(" Active Records by Provider:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003053 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
3054 pw.println(" " + entry.getKey() + ":");
3055 for (UpdateRecord record : entry.getValue()) {
3056 pw.println(" " + record);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003057 }
3058 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003059 pw.println(" Overlay Provider Packages:");
3060 for (LocationProviderInterface provider : mProviders) {
3061 if (provider instanceof LocationProviderProxy) {
3062 pw.println(" " + provider.getName() + ": "
3063 + ((LocationProviderProxy) provider).getConnectedPackageName());
3064 }
3065 }
David Christie2ff96af2014-01-30 16:09:37 -08003066 pw.println(" Historical Records by Provider:");
3067 for (Map.Entry<PackageProviderKey, PackageStatistics> entry
3068 : mRequestStatistics.statistics.entrySet()) {
3069 PackageProviderKey key = entry.getKey();
3070 PackageStatistics stats = entry.getValue();
3071 pw.println(" " + key.packageName + ": " + key.providerName + ": " + stats);
3072 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003073 pw.println(" Last Known Locations:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003074 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
3075 String provider = entry.getKey();
3076 Location location = entry.getValue();
3077 pw.println(" " + provider + ": " + location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003078 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003079
David Christie1b9b7b12013-04-15 15:31:11 -07003080 pw.println(" Last Known Locations Coarse Intervals:");
3081 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
3082 String provider = entry.getKey();
3083 Location location = entry.getValue();
3084 pw.println(" " + provider + ": " + location);
3085 }
3086
Nick Pellye0fd6932012-07-11 10:26:13 -07003087 mGeofenceManager.dump(pw);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003089 if (mEnabledProviders.size() > 0) {
3090 pw.println(" Enabled Providers:");
3091 for (String i : mEnabledProviders) {
3092 pw.println(" " + i);
3093 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003094
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003095 }
3096 if (mDisabledProviders.size() > 0) {
3097 pw.println(" Disabled Providers:");
3098 for (String i : mDisabledProviders) {
3099 pw.println(" " + i);
3100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003101 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07003102 pw.append(" ");
3103 mBlacklist.dump(pw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003104 if (mMockProviders.size() > 0) {
3105 pw.println(" Mock Providers:");
3106 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003107 i.getValue().dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003108 }
3109 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003110
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08003111 if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
3112 pw.println(" Throttling Whitelisted Packages:");
3113 for (String packageName : mBackgroundThrottlePackageWhitelist) {
3114 pw.println(" " + packageName);
3115 }
3116 }
3117
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003118 pw.append(" fudger: ");
3119 mLocationFudger.dump(fd, pw, args);
3120
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003121 if (args.length > 0 && "short".equals(args[0])) {
3122 return;
3123 }
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003124 for (LocationProviderInterface provider: mProviders) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003125 pw.print(provider.getName() + " Internal State");
3126 if (provider instanceof LocationProviderProxy) {
3127 LocationProviderProxy proxy = (LocationProviderProxy) provider;
3128 pw.print(" (" + proxy.getConnectedPackageName() + ")");
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003129 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003130 pw.println(":");
3131 provider.dump(fd, pw, args);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003132 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08003133 if (mGnssBatchingInProgress) {
3134 pw.println(" GNSS batching in progress");
3135 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003136 }
3137 }
3138}