blob: b4270cf153cc4cc1dee95e1f70396cf3f773a10c [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)) {
1732 LocationRequest locationRequest = record.mRequest;
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
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001745 providerRequest.locationRequests.add(locationRequest);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001746 if (interval < providerRequest.interval) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001747 providerRequest.reportLocation = true;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001748 providerRequest.interval = interval;
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001749 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001750 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001751 }
1752 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001753
1754 if (providerRequest.reportLocation) {
1755 // calculate who to blame for power
1756 // This is somewhat arbitrary. We pick a threshold interval
1757 // that is slightly higher that the minimum interval, and
1758 // spread the blame across all applications with a request
1759 // under that threshold.
1760 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
1761 for (UpdateRecord record : records) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001762 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001763 LocationRequest locationRequest = record.mRequest;
Svet Ganove998c732016-06-10 00:12:38 -07001764
1765 // Don't assign battery blame for update records whose
1766 // client has no permission to receive location data.
1767 if (!providerRequest.locationRequests.contains(locationRequest)) {
1768 continue;
1769 }
1770
Victoria Leaseb711d572012-10-02 13:14:11 -07001771 if (locationRequest.getInterval() <= thresholdInterval) {
David Christiee55c9682013-08-22 10:10:34 -07001772 if (record.mReceiver.mWorkSource != null
1773 && record.mReceiver.mWorkSource.size() > 0
1774 && record.mReceiver.mWorkSource.getName(0) != null) {
David Christie82edc9b2013-07-19 11:31:42 -07001775 // Assign blame to another work source.
David Christiee55c9682013-08-22 10:10:34 -07001776 // Can only assign blame if the WorkSource contains names.
David Christie82edc9b2013-07-19 11:31:42 -07001777 worksource.add(record.mReceiver.mWorkSource);
1778 } else {
1779 // Assign blame to caller.
1780 worksource.add(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001781 record.mReceiver.mIdentity.mUid,
1782 record.mReceiver.mIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001783 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001784 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001785 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001786 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 }
1788 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001789
1790 if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
1791 p.setRequest(providerRequest, worksource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 }
1793
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001794 @Override
1795 public String[] getBackgroundThrottlingWhitelist() {
1796 synchronized (mLock) {
1797 return mBackgroundThrottlePackageWhitelist.toArray(
1798 new String[mBackgroundThrottlePackageWhitelist.size()]);
1799 }
1800 }
1801
1802 private void updateBackgroundThrottlingWhitelistLocked() {
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08001803 String setting = Settings.Global.getString(
1804 mContext.getContentResolver(),
1805 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
1806 if (setting == null) {
1807 setting = "";
1808 }
1809
1810 mBackgroundThrottlePackageWhitelist.clear();
1811 mBackgroundThrottlePackageWhitelist.addAll(
1812 SystemConfig.getInstance().getAllowUnthrottledLocation());
1813 mBackgroundThrottlePackageWhitelist.addAll(
1814 Arrays.asList(setting.split(",")));
1815 }
1816
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001817 private boolean isThrottlingExemptLocked(Identity identity) {
1818 if (identity.mUid == Process.SYSTEM_UID) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001819 return true;
1820 }
1821
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001822 if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001823 return true;
1824 }
1825
1826 for (LocationProviderProxy provider : mProxyProviders) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001827 if (identity.mPackageName.equals(provider.getConnectedPackageName())) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001828 return true;
1829 }
1830 }
1831
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001832 return false;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001833 }
1834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001835 private class UpdateRecord {
1836 final String mProvider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001837 final LocationRequest mRequest;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001838 final Receiver mReceiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001839 boolean mIsForegroundUid;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001840 Location mLastFixBroadcast;
1841 long mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001842
1843 /**
1844 * Note: must be constructed with lock held.
1845 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001846 UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 mProvider = provider;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001848 mRequest = request;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001849 mReceiver = receiver;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001850 mIsForegroundUid = isImportanceForeground(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001851 mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001852
1853 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1854 if (records == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001855 records = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 mRecordsByProvider.put(provider, records);
1857 }
1858 if (!records.contains(this)) {
1859 records.add(this);
1860 }
David Christie2ff96af2014-01-30 16:09:37 -08001861
1862 // Update statistics for historical location requests by package/provider
1863 mRequestStatistics.startRequesting(
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001864 mReceiver.mIdentity.mPackageName, provider, request.getInterval());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001865 }
1866
1867 /**
David Christie2ff96af2014-01-30 16:09:37 -08001868 * Method to be called when a record will no longer be used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001870 void disposeLocked(boolean removeReceiver) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001871 mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider);
David Christie2ff96af2014-01-30 16:09:37 -08001872
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001873 // remove from mRecordsByProvider
1874 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
1875 if (globalRecords != null) {
1876 globalRecords.remove(this);
1877 }
1878
1879 if (!removeReceiver) return; // the caller will handle the rest
1880
1881 // remove from Receiver#mUpdateRecords
1882 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
1883 if (receiverRecords != null) {
1884 receiverRecords.remove(this.mProvider);
1885
1886 // and also remove the Receiver if it has no more update records
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001887 if (receiverRecords.size() == 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001888 removeUpdatesLocked(mReceiver);
1889 }
Mike Lockwood3a76fd62009-09-01 07:26:56 -04001890 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001891 }
1892
1893 @Override
1894 public String toString() {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001895 return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
1896 + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground" : " background")
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001897 + ")" + " " + mRequest + "]";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001898 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001899 }
1900
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001901 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
David Christie40e57822013-07-30 11:36:48 -07001902 String packageName, WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001903 IBinder binder = listener.asBinder();
1904 Receiver receiver = mReceivers.get(binder);
1905 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07001906 receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
1907 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001908 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001909 receiver.getListener().asBinder().linkToDeath(receiver, 0);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001910 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001911 Slog.e(TAG, "linkToDeath failed:", e);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001912 return null;
1913 }
Wen Jingcb3ab222014-03-27 13:42:59 +08001914 mReceivers.put(binder, receiver);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001915 }
1916 return receiver;
1917 }
1918
David Christie82edc9b2013-07-19 11:31:42 -07001919 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
David Christie40e57822013-07-30 11:36:48 -07001920 WorkSource workSource, boolean hideFromAppOps) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001921 Receiver receiver = mReceivers.get(intent);
1922 if (receiver == null) {
David Christie40e57822013-07-30 11:36:48 -07001923 receiver = new Receiver(null, intent, pid, uid, packageName, workSource,
1924 hideFromAppOps);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001925 mReceivers.put(intent, receiver);
1926 }
1927 return receiver;
1928 }
1929
Victoria Lease37425c32012-10-16 16:08:48 -07001930 /**
1931 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
1932 * and consistency requirements.
1933 *
1934 * @param request the LocationRequest from which to create a sanitized version
Victoria Lease37425c32012-10-16 16:08:48 -07001935 * @return a version of request that meets the given resolution and consistency requirements
1936 * @hide
1937 */
1938 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel) {
1939 LocationRequest sanitizedRequest = new LocationRequest(request);
1940 if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
1941 switch (sanitizedRequest.getQuality()) {
Victoria Lease09016ab2012-09-16 12:33:15 -07001942 case LocationRequest.ACCURACY_FINE:
Victoria Lease37425c32012-10-16 16:08:48 -07001943 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
Victoria Lease09016ab2012-09-16 12:33:15 -07001944 break;
1945 case LocationRequest.POWER_HIGH:
Victoria Lease37425c32012-10-16 16:08:48 -07001946 sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
Victoria Lease09016ab2012-09-16 12:33:15 -07001947 break;
1948 }
1949 // throttle
Victoria Lease37425c32012-10-16 16:08:48 -07001950 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1951 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001952 }
Victoria Lease37425c32012-10-16 16:08:48 -07001953 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1954 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001955 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07001956 }
Nick Pelly4e31c4f2012-08-13 19:35:39 -07001957 // make getFastestInterval() the minimum of interval and fastest interval
Victoria Lease37425c32012-10-16 16:08:48 -07001958 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07001959 request.setFastestInterval(request.getInterval());
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001960 }
Victoria Lease37425c32012-10-16 16:08:48 -07001961 return sanitizedRequest;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001962 }
1963
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001964 private void checkPackageName(String packageName) {
Nick Pellye0fd6932012-07-11 10:26:13 -07001965 if (packageName == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001966 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07001967 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001968 int uid = Binder.getCallingUid();
Nick Pellye0fd6932012-07-11 10:26:13 -07001969 String[] packages = mPackageManager.getPackagesForUid(uid);
1970 if (packages == null) {
1971 throw new SecurityException("invalid UID " + uid);
1972 }
1973 for (String pkg : packages) {
1974 if (packageName.equals(pkg)) return;
1975 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001976 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07001977 }
1978
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001979 private void checkPendingIntent(PendingIntent intent) {
1980 if (intent == null) {
1981 throw new IllegalArgumentException("invalid pending intent: " + intent);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001982 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001983 }
1984
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001985 private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent,
David Christie40e57822013-07-30 11:36:48 -07001986 int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001987 if (intent == null && listener == null) {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08001988 throw new IllegalArgumentException("need either listener or intent");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001989 } else if (intent != null && listener != null) {
1990 throw new IllegalArgumentException("cannot register both listener and intent");
1991 } else if (intent != null) {
1992 checkPendingIntent(intent);
David Christie40e57822013-07-30 11:36:48 -07001993 return getReceiverLocked(intent, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001994 } else {
David Christie40e57822013-07-30 11:36:48 -07001995 return getReceiverLocked(listener, pid, uid, packageName, workSource, hideFromAppOps);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001996 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001997 }
1998
Nick Pellye0fd6932012-07-11 10:26:13 -07001999 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002000 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
2001 PendingIntent intent, String packageName) {
2002 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2003 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002004 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2005 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2006 request.getProvider());
David Christie82edc9b2013-07-19 11:31:42 -07002007 WorkSource workSource = request.getWorkSource();
2008 if (workSource != null && workSource.size() > 0) {
David Christie40e57822013-07-30 11:36:48 -07002009 checkDeviceStatsAllowed();
2010 }
2011 boolean hideFromAppOps = request.getHideFromAppOps();
2012 if (hideFromAppOps) {
2013 checkUpdateAppOpsAllowed();
David Christie82edc9b2013-07-19 11:31:42 -07002014 }
Victoria Lease37425c32012-10-16 16:08:48 -07002015 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002016
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002017 final int pid = Binder.getCallingPid();
2018 final int uid = Binder.getCallingUid();
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002019 // providers may use public location API's, need to clear identity
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002020 long identity = Binder.clearCallingIdentity();
2021 try {
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002022 // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2023 // a location.
David Christieb870dbf2015-06-22 12:42:53 -07002024 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002025
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002026 synchronized (mLock) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002027 Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
David Christie40e57822013-07-30 11:36:48 -07002028 packageName, workSource, hideFromAppOps);
Victoria Lease37425c32012-10-16 16:08:48 -07002029 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
Mike Lockwood2d4d1bf2010-10-18 17:06:26 -04002030 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002031 } finally {
2032 Binder.restoreCallingIdentity(identity);
2033 }
2034 }
2035
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002036 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
2037 int pid, int uid, String packageName) {
2038 // Figure out the provider. Either its explicitly request (legacy use cases), or
2039 // use the fused provider
2040 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2041 String name = request.getProvider();
Victoria Lease09016ab2012-09-16 12:33:15 -07002042 if (name == null) {
2043 throw new IllegalArgumentException("provider name must not be null");
2044 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -07002045
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002046 LocationProviderInterface provider = mProvidersByName.get(name);
2047 if (provider == null) {
Victoria Leaseb30f3832013-10-13 12:15:40 -07002048 throw new IllegalArgumentException("provider doesn't exist: " + name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002049 }
2050
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002051 UpdateRecord record = new UpdateRecord(name, request, receiver);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002052 if (D) Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
2053 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
2054 + (record.mIsForegroundUid ? "foreground" : "background")
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002055 + (isThrottlingExemptLocked(receiver.mIdentity)
2056 ? " [whitelisted]" : "") + ")");
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002057
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002058 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
2059 if (oldRecord != null) {
2060 oldRecord.disposeLocked(false);
2061 }
2062
Victoria Lease09eeaec2013-02-05 11:34:13 -08002063 boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002064 if (isProviderEnabled) {
2065 applyRequirementsLocked(name);
2066 } else {
2067 // Notify the listener that updates are currently disabled
2068 receiver.callProviderEnabledLocked(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002069 }
David Christie0b837452013-07-29 16:02:13 -07002070 // Update the monitoring here just in case multiple location requests were added to the
2071 // same receiver (this request may be high power and the initial might not have been).
2072 receiver.updateMonitoring(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002073 }
2074
Nick Pellye0fd6932012-07-11 10:26:13 -07002075 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002076 public void removeUpdates(ILocationListener listener, PendingIntent intent,
2077 String packageName) {
2078 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002079
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002080 final int pid = Binder.getCallingPid();
2081 final int uid = Binder.getCallingUid();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002082
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002083 synchronized (mLock) {
David Christie82edc9b2013-07-19 11:31:42 -07002084 WorkSource workSource = null;
David Christie40e57822013-07-30 11:36:48 -07002085 boolean hideFromAppOps = false;
2086 Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid,
2087 packageName, workSource, hideFromAppOps);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002088
2089 // providers may use public location API's, need to clear identity
2090 long identity = Binder.clearCallingIdentity();
2091 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002092 removeUpdatesLocked(receiver);
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07002093 } finally {
2094 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002095 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002096 }
2097 }
2098
2099 private void removeUpdatesLocked(Receiver receiver) {
Dianne Hackborn7ff30112012-11-08 11:12:09 -08002100 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002101
2102 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
2103 receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
2104 synchronized (receiver) {
Victoria Lease0aa28602013-05-29 15:28:26 -07002105 receiver.clearPendingBroadcastsLocked();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002106 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002107 }
2108
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07002109 receiver.updateMonitoring(false);
2110
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002111 // Record which providers were associated with this listener
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002112 HashSet<String> providers = new HashSet<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002113 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2114 if (oldRecords != null) {
2115 // Call dispose() on the obsolete update records.
2116 for (UpdateRecord record : oldRecords.values()) {
David Christie2ff96af2014-01-30 16:09:37 -08002117 // Update statistics for historical location requests by package/provider
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002118 record.disposeLocked(false);
2119 }
2120 // Accumulate providers
2121 providers.addAll(oldRecords.keySet());
2122 }
2123
2124 // update provider
2125 for (String provider : providers) {
2126 // If provider is already disabled, don't need to do anything
Victoria Lease09eeaec2013-02-05 11:34:13 -08002127 if (!isAllowedByCurrentUserSettingsLocked(provider)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002128 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002129 }
2130
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002131 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002132 }
2133 }
2134
Dianne Hackbornc2293022013-02-06 23:14:49 -08002135 private void applyAllProviderRequirementsLocked() {
2136 for (LocationProviderInterface p : mProviders) {
2137 // If provider is already disabled, don't need to do anything
Dianne Hackborn64d41d72013-02-07 00:33:31 -08002138 if (!isAllowedByCurrentUserSettingsLocked(p.getName())) {
Dianne Hackbornc2293022013-02-06 23:14:49 -08002139 continue;
2140 }
2141
2142 applyRequirementsLocked(p.getName());
2143 }
2144 }
2145
Nick Pellye0fd6932012-07-11 10:26:13 -07002146 @Override
Nick Pelly4035f5a2012-08-17 14:43:49 -07002147 public Location getLastLocation(LocationRequest request, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002148 if (D) Log.d(TAG, "getLastLocation: " + request);
2149 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002150 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Nick Pelly4035f5a2012-08-17 14:43:49 -07002151 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002152 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2153 request.getProvider());
2154 // no need to sanitize this request, as only the provider name is used
Nick Pelly4035f5a2012-08-17 14:43:49 -07002155
David Christieb870dbf2015-06-22 12:42:53 -07002156 final int pid = Binder.getCallingPid();
Dianne Hackborna06de0f2012-12-11 16:34:47 -08002157 final int uid = Binder.getCallingUid();
2158 final long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07002159 try {
2160 if (mBlacklist.isBlacklisted(packageName)) {
2161 if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
2162 packageName);
Victoria Lease09016ab2012-09-16 12:33:15 -07002163 return null;
2164 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002165
David Christieb870dbf2015-06-22 12:42:53 -07002166 if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel)) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002167 if (D) Log.d(TAG, "not returning last loc for no op app: " +
2168 packageName);
2169 return null;
2170 }
2171
Victoria Leaseb711d572012-10-02 13:14:11 -07002172 synchronized (mLock) {
2173 // Figure out the provider. Either its explicitly request (deprecated API's),
2174 // or use the fused provider
2175 String name = request.getProvider();
2176 if (name == null) name = LocationManager.FUSED_PROVIDER;
2177 LocationProviderInterface provider = mProvidersByName.get(name);
2178 if (provider == null) return null;
2179
Victoria Lease09eeaec2013-02-05 11:34:13 -08002180 if (!isAllowedByUserSettingsLocked(name, uid)) return null;
Victoria Leaseb711d572012-10-02 13:14:11 -07002181
David Christie1b9b7b12013-04-15 15:31:11 -07002182 Location location;
2183 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2184 // Make sure that an app with coarse permissions can't get frequent location
2185 // updates by calling LocationManager.getLastKnownLocation repeatedly.
2186 location = mLastLocationCoarseInterval.get(name);
2187 } else {
2188 location = mLastLocation.get(name);
2189 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002190 if (location == null) {
2191 return null;
2192 }
Victoria Lease37425c32012-10-16 16:08:48 -07002193 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002194 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2195 if (noGPSLocation != null) {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002196 return new Location(mLocationFudger.getOrCreate(noGPSLocation));
Victoria Leaseb711d572012-10-02 13:14:11 -07002197 }
Victoria Lease37425c32012-10-16 16:08:48 -07002198 } else {
Dianne Hackborn6c5406a2012-11-29 16:18:01 -08002199 return new Location(location);
Victoria Lease09016ab2012-09-16 12:33:15 -07002200 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002201 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002202 return null;
2203 } finally {
2204 Binder.restoreCallingIdentity(identity);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002205 }
2206 }
2207
2208 @Override
2209 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
2210 String packageName) {
2211 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002212 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2213 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002214 checkPendingIntent(intent);
2215 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002216 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2217 request.getProvider());
2218 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002219
Victoria Lease37425c32012-10-16 16:08:48 -07002220 if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002221
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002222 // geo-fence manager uses the public location API, need to clear identity
2223 int uid = Binder.getCallingUid();
Xiaohui Chena4490622015-09-22 15:29:31 -07002224 // TODO: http://b/23822629
2225 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
Victoria Lease56e675b2012-11-05 19:25:06 -08002226 // temporary measure until geofences work for secondary users
2227 Log.w(TAG, "proximity alerts are currently available only to the primary user");
2228 return;
2229 }
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002230 long identity = Binder.clearCallingIdentity();
2231 try {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002232 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
2233 uid, packageName);
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002234 } finally {
2235 Binder.restoreCallingIdentity(identity);
2236 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002237 }
2238
2239 @Override
2240 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002241 checkPendingIntent(intent);
2242 checkPackageName(packageName);
2243
2244 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2245
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002246 // geo-fence manager uses the public location API, need to clear identity
2247 long identity = Binder.clearCallingIdentity();
2248 try {
2249 mGeofenceManager.removeFence(geofence, intent);
2250 } finally {
2251 Binder.restoreCallingIdentity(identity);
2252 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002253 }
2254
2255
2256 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002257 public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002258 if (!hasGnssPermissions(packageName) || mGnssStatusProvider == null) {
Takayuki Hoshib254ab6a2014-10-23 16:46:02 +09002259 return false;
2260 }
2261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002262 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002263 mGnssStatusProvider.registerGnssStatusCallback(callback);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002264 } catch (RemoteException e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002265 Slog.e(TAG, "mGpsStatusProvider.registerGnssStatusCallback failed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002266 return false;
2267 }
2268 return true;
2269 }
2270
Nick Pellye0fd6932012-07-11 10:26:13 -07002271 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -08002272 public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002273 synchronized (mLock) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002274 try {
Lifu Tang30f95a72016-01-07 23:20:38 -08002275 mGnssStatusProvider.unregisterGnssStatusCallback(callback);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002276 } catch (Exception e) {
Lifu Tang30f95a72016-01-07 23:20:38 -08002277 Slog.e(TAG, "mGpsStatusProvider.unregisterGnssStatusCallback failed", e);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04002278 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002279 }
2280 }
2281
Nick Pellye0fd6932012-07-11 10:26:13 -07002282 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002283 public boolean addGnssMeasurementsListener(
2284 IGnssMeasurementsListener listener,
destradaaea8a8a62014-06-23 18:19:03 -07002285 String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002286 if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
destradaaea8a8a62014-06-23 18:19:03 -07002287 return false;
2288 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002289
2290 synchronized (mLock) {
2291 Identity callerIdentity
2292 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
2293 mGnssMeasurementsListeners.put(listener, callerIdentity);
2294 long identity = Binder.clearCallingIdentity();
2295 try {
2296 if (isThrottlingExemptLocked(callerIdentity)
2297 || isImportanceForeground(
2298 mActivityManager.getPackageImportance(packageName))) {
2299 return mGnssMeasurementsProvider.addListener(listener);
2300 }
2301 } finally {
2302 Binder.restoreCallingIdentity(identity);
2303 }
2304
2305 return true;
2306 }
destradaaea8a8a62014-06-23 18:19:03 -07002307 }
2308
2309 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002310 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
2311 if (mGnssMeasurementsProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002312 synchronized (mLock) {
2313 mGnssMeasurementsListeners.remove(listener);
2314 mGnssMeasurementsProvider.removeListener(listener);
2315 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002316 }
destradaaea8a8a62014-06-23 18:19:03 -07002317 }
2318
2319 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002320 public boolean addGnssNavigationMessageListener(
2321 IGnssNavigationMessageListener listener,
destradaa4b3e3932014-07-21 18:01:47 -07002322 String packageName) {
Wyatt Rileycf879db2017-01-12 13:57:38 -08002323 if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) {
destradaa4b3e3932014-07-21 18:01:47 -07002324 return false;
2325 }
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002326
2327 synchronized (mLock) {
2328 Identity callerIdentity
2329 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
2330 mGnssNavigationMessageListeners.put(listener, callerIdentity);
2331 long identity = Binder.clearCallingIdentity();
2332 try {
2333 if (isThrottlingExemptLocked(callerIdentity)
2334 || isImportanceForeground(
2335 mActivityManager.getPackageImportance(packageName))) {
2336 return mGnssNavigationMessageProvider.addListener(listener);
2337 }
2338 } finally {
2339 Binder.restoreCallingIdentity(identity);
2340 }
2341
2342 return true;
2343 }
destradaa4b3e3932014-07-21 18:01:47 -07002344 }
2345
2346 @Override
Lifu Tang818aa2c2016-02-01 01:52:00 -08002347 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
2348 if (mGnssNavigationMessageProvider != null) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002349 synchronized (mLock) {
2350 mGnssNavigationMessageListeners.remove(listener);
2351 mGnssNavigationMessageProvider.removeListener(listener);
2352 }
Wei Liu5241a4c2015-05-11 14:00:36 -07002353 }
destradaa4b3e3932014-07-21 18:01:47 -07002354 }
2355
2356 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002357 public boolean sendExtraCommand(String provider, String command, Bundle extras) {
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002358 if (provider == null) {
2359 // throw NullPointerException to remain compatible with previous implementation
2360 throw new NullPointerException();
2361 }
Victoria Lease37425c32012-10-16 16:08:48 -07002362 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2363 provider);
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002365 // and check for ACCESS_LOCATION_EXTRA_COMMANDS
Mike Lockwoodb7e99222009-07-07 13:18:21 -04002366 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002367 != PackageManager.PERMISSION_GRANTED)) {
2368 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
2369 }
2370
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002371 synchronized (mLock) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002372 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002373 if (p == null) return false;
Nick Pellye0fd6932012-07-11 10:26:13 -07002374
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002375 return p.sendExtraCommand(command, extras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002376 }
2377 }
2378
Nick Pellye0fd6932012-07-11 10:26:13 -07002379 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002380 public boolean sendNiResponse(int notifId, int userResponse) {
Mike Lockwood18ad9f62009-08-27 14:01:23 -07002381 if (Binder.getCallingUid() != Process.myUid()) {
2382 throw new SecurityException(
2383 "calling sendNiResponse from outside of the system is not allowed");
2384 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002385 try {
2386 return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002387 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002388 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
Danke Xie22d1f9f2009-08-18 18:28:45 -04002389 return false;
2390 }
2391 }
2392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002393 /**
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002394 * @return null if the provider does not exist
Alexey Tarasovf2db9fb2009-09-01 02:37:07 +11002395 * @throws SecurityException if the provider is not allowed to be
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002396 * accessed by the caller
2397 */
Nick Pellye0fd6932012-07-11 10:26:13 -07002398 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002399 public ProviderProperties getProviderProperties(String provider) {
Laurent Tub7f9d252012-10-16 14:25:00 -07002400 if (mProvidersByName.get(provider) == null) {
David Christie2ff96af2014-01-30 16:09:37 -08002401 return null;
Laurent Tub7f9d252012-10-16 14:25:00 -07002402 }
2403
Victoria Lease37425c32012-10-16 16:08:48 -07002404 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2405 provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002406
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002407 LocationProviderInterface p;
2408 synchronized (mLock) {
2409 p = mProvidersByName.get(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002410 }
2411
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002412 if (p == null) return null;
2413 return p.getProperties();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002414 }
2415
Jason Monkb71218a2015-06-17 14:44:39 -04002416 /**
2417 * @return null if the provider does not exist
2418 * @throws SecurityException if the provider is not allowed to be
2419 * accessed by the caller
2420 */
2421 @Override
2422 public String getNetworkProviderPackage() {
2423 LocationProviderInterface p;
2424 synchronized (mLock) {
2425 if (mProvidersByName.get(LocationManager.NETWORK_PROVIDER) == null) {
2426 return null;
2427 }
2428 p = mProvidersByName.get(LocationManager.NETWORK_PROVIDER);
2429 }
2430
2431 if (p instanceof LocationProviderProxy) {
2432 return ((LocationProviderProxy) p).getConnectedPackageName();
2433 }
2434 return null;
2435 }
2436
Nick Pellye0fd6932012-07-11 10:26:13 -07002437 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002438 public boolean isProviderEnabled(String provider) {
Tom O'Neilld5759432013-09-11 11:03:03 -07002439 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2440 // so we discourage its use
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002441 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
2442
Victoria Lease09eeaec2013-02-05 11:34:13 -08002443 int uid = Binder.getCallingUid();
Victoria Lease269518e2012-10-29 08:25:39 -07002444 long identity = Binder.clearCallingIdentity();
Victoria Leaseb711d572012-10-02 13:14:11 -07002445 try {
2446 synchronized (mLock) {
2447 LocationProviderInterface p = mProvidersByName.get(provider);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002448 return p != null && isAllowedByUserSettingsLocked(provider, uid);
Victoria Leaseb711d572012-10-02 13:14:11 -07002449 }
2450 } finally {
2451 Binder.restoreCallingIdentity(identity);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002452 }
2453 }
2454
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002455 /**
2456 * Returns "true" if the UID belongs to a bound location provider.
2457 *
2458 * @param uid the uid
2459 * @return true if uid belongs to a bound location provider
2460 */
2461 private boolean isUidALocationProvider(int uid) {
2462 if (uid == Process.SYSTEM_UID) {
2463 return true;
2464 }
2465 if (mGeocodeProvider != null) {
David Christie1f141c12014-05-14 15:11:15 -07002466 if (doesUidHavePackage(uid, mGeocodeProvider.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002467 }
2468 for (LocationProviderProxy proxy : mProxyProviders) {
David Christie1f141c12014-05-14 15:11:15 -07002469 if (doesUidHavePackage(uid, proxy.getConnectedPackageName())) return true;
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002470 }
2471 return false;
2472 }
2473
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002474 private void checkCallerIsProvider() {
2475 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
2476 == PackageManager.PERMISSION_GRANTED) {
2477 return;
2478 }
2479
2480 // Previously we only used the INSTALL_LOCATION_PROVIDER
2481 // check. But that is system or signature
2482 // protection level which is not flexible enough for
2483 // providers installed oustide the system image. So
2484 // also allow providers with a UID matching the
2485 // currently bound package name
2486
Victoria Lease03cdd3d2013-02-01 15:15:54 -08002487 if (isUidALocationProvider(Binder.getCallingUid())) {
2488 return;
2489 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002490
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002491 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
2492 "or UID of a currently bound location provider");
2493 }
2494
David Christie1f141c12014-05-14 15:11:15 -07002495 /**
2496 * Returns true if the given package belongs to the given uid.
2497 */
2498 private boolean doesUidHavePackage(int uid, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002499 if (packageName == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002500 return false;
2501 }
David Christie1f141c12014-05-14 15:11:15 -07002502 String[] packageNames = mPackageManager.getPackagesForUid(uid);
2503 if (packageNames == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002504 return false;
2505 }
David Christie1f141c12014-05-14 15:11:15 -07002506 for (String name : packageNames) {
2507 if (packageName.equals(name)) {
2508 return true;
2509 }
2510 }
2511 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002512 }
2513
Nick Pellye0fd6932012-07-11 10:26:13 -07002514 @Override
Mike Lockwooda4903f22010-02-17 06:42:23 -05002515 public void reportLocation(Location location, boolean passive) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002516 checkCallerIsProvider();
Mike Lockwood275555c2009-05-01 11:30:34 -04002517
Nick Pelly2eeeec22012-07-18 13:13:37 -07002518 if (!location.isComplete()) {
2519 Log.w(TAG, "Dropping incomplete location: " + location);
2520 return;
2521 }
2522
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002523 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location);
2524 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location);
Mike Lockwooda4903f22010-02-17 06:42:23 -05002525 m.arg1 = (passive ? 1 : 0);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002526 mLocationHandler.sendMessageAtFrontOfQueue(m);
2527 }
2528
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002529
Laurent Tu75defb62012-11-01 16:21:52 -07002530 private static boolean shouldBroadcastSafe(
2531 Location loc, Location lastLoc, UpdateRecord record, long now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002532 // Always broadcast the first update
2533 if (lastLoc == null) {
2534 return true;
2535 }
2536
Nick Pellyf1be6862012-05-15 10:53:42 -07002537 // Check whether sufficient time has passed
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002538 long minTime = record.mRequest.getFastestInterval();
David Christie1b9b7b12013-04-15 15:31:11 -07002539 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
2540 / NANOS_PER_MILLI;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002541 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002542 return false;
2543 }
2544
2545 // Check whether sufficient distance has been traveled
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002546 double minDistance = record.mRequest.getSmallestDisplacement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002547 if (minDistance > 0.0) {
2548 if (loc.distanceTo(lastLoc) <= minDistance) {
2549 return false;
2550 }
2551 }
2552
Laurent Tu75defb62012-11-01 16:21:52 -07002553 // Check whether sufficient number of udpates is left
2554 if (record.mRequest.getNumUpdates() <= 0) {
2555 return false;
2556 }
2557
2558 // Check whether the expiry date has passed
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002559 return record.mRequest.getExpireAt() >= now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002560 }
2561
Mike Lockwooda4903f22010-02-17 06:42:23 -05002562 private void handleLocationChangedLocked(Location location, boolean passive) {
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002563 if (D) Log.d(TAG, "incoming location: " + location);
2564
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002565 long now = SystemClock.elapsedRealtime();
Mike Lockwooda4903f22010-02-17 06:42:23 -05002566 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002567
Laurent Tu60ec50a2012-10-04 17:00:10 -07002568 // Skip if the provider is unknown.
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002569 LocationProviderInterface p = mProvidersByName.get(provider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002570 if (p == null) return;
2571
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002572 // Update last known locations
Victoria Lease09016ab2012-09-16 12:33:15 -07002573 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002574 Location lastNoGPSLocation;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002575 Location lastLocation = mLastLocation.get(provider);
Mike Lockwood4e50b782009-04-03 08:24:43 -07002576 if (lastLocation == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002577 lastLocation = new Location(provider);
2578 mLastLocation.put(provider, lastLocation);
Victoria Lease09016ab2012-09-16 12:33:15 -07002579 } else {
2580 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2581 if (noGPSLocation == null && lastNoGPSLocation != null) {
2582 // New location has no no-GPS location: adopt last no-GPS location. This is set
2583 // directly into location because we do not want to notify COARSE clients.
2584 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
2585 }
Mike Lockwood4e50b782009-04-03 08:24:43 -07002586 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002587 lastLocation.set(location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002588
David Christie1b9b7b12013-04-15 15:31:11 -07002589 // Update last known coarse interval location if enough time has passed.
2590 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider);
2591 if (lastLocationCoarseInterval == null) {
2592 lastLocationCoarseInterval = new Location(location);
2593 mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval);
2594 }
2595 long timeDiffNanos = location.getElapsedRealtimeNanos()
2596 - lastLocationCoarseInterval.getElapsedRealtimeNanos();
2597 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
2598 lastLocationCoarseInterval.set(location);
2599 }
2600 // Don't ever return a coarse location that is more recent than the allowed update
2601 // interval (i.e. don't allow an app to keep registering and unregistering for
2602 // location updates to overcome the minimum interval).
2603 noGPSLocation =
2604 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2605
Laurent Tu60ec50a2012-10-04 17:00:10 -07002606 // Skip if there are no UpdateRecords for this provider.
2607 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
2608 if (records == null || records.size() == 0) return;
2609
Victoria Lease09016ab2012-09-16 12:33:15 -07002610 // Fetch coarse location
2611 Location coarseLocation = null;
David Christie1b9b7b12013-04-15 15:31:11 -07002612 if (noGPSLocation != null) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002613 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
2614 }
2615
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002616 // Fetch latest status update time
2617 long newStatusUpdateTime = p.getStatusUpdateTime();
2618
David Christie2ff96af2014-01-30 16:09:37 -08002619 // Get latest status
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002620 Bundle extras = new Bundle();
2621 int status = p.getStatus(extras);
2622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002623 ArrayList<Receiver> deadReceivers = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002624 ArrayList<UpdateRecord> deadUpdateRecords = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07002625
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002626 // Broadcast location or status to all listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002627 for (UpdateRecord r : records) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002628 Receiver receiver = r.mReceiver;
Mike Lockwood03ca2162010-04-01 08:10:09 -07002629 boolean receiverDead = false;
Nick Pelly4035f5a2012-08-17 14:43:49 -07002630
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002631 int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid);
2632 if (!isCurrentProfile(receiverUserId)
2633 && !isUidALocationProvider(receiver.mIdentity.mUid)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002634 if (D) {
Victoria Lease269518e2012-10-29 08:25:39 -07002635 Log.d(TAG, "skipping loc update for background user " + receiverUserId +
Victoria Leaseb711d572012-10-02 13:14:11 -07002636 " (current user: " + mCurrentUserId + ", app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002637 receiver.mIdentity.mPackageName + ")");
Victoria Leaseb711d572012-10-02 13:14:11 -07002638 }
2639 continue;
2640 }
2641
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002642 if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) {
Nick Pelly4035f5a2012-08-17 14:43:49 -07002643 if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002644 receiver.mIdentity.mPackageName);
Nick Pelly4035f5a2012-08-17 14:43:49 -07002645 continue;
2646 }
2647
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002648 if (!reportLocationAccessNoThrow(
2649 receiver.mIdentity.mPid,
2650 receiver.mIdentity.mUid,
2651 receiver.mIdentity.mPackageName,
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002652 receiver.mAllowedResolutionLevel)) {
2653 if (D) Log.d(TAG, "skipping loc update for no op app: " +
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002654 receiver.mIdentity.mPackageName);
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08002655 continue;
2656 }
2657
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002658 Location notifyLocation;
Victoria Lease37425c32012-10-16 16:08:48 -07002659 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2660 notifyLocation = coarseLocation; // use coarse location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002661 } else {
Victoria Lease37425c32012-10-16 16:08:48 -07002662 notifyLocation = lastLocation; // use fine location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002663 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002664 if (notifyLocation != null) {
2665 Location lastLoc = r.mLastFixBroadcast;
Laurent Tu75defb62012-11-01 16:21:52 -07002666 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002667 if (lastLoc == null) {
2668 lastLoc = new Location(notifyLocation);
2669 r.mLastFixBroadcast = lastLoc;
2670 } else {
2671 lastLoc.set(notifyLocation);
2672 }
2673 if (!receiver.callLocationChangedLocked(notifyLocation)) {
2674 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
2675 receiverDead = true;
2676 }
Laurent Tu75defb62012-11-01 16:21:52 -07002677 r.mRequest.decrementNumUpdates();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002678 }
2679 }
2680
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002681 long prevStatusUpdateTime = r.mLastStatusBroadcast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002682 if ((newStatusUpdateTime > prevStatusUpdateTime) &&
Victoria Lease09016ab2012-09-16 12:33:15 -07002683 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002684
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002685 r.mLastStatusBroadcast = newStatusUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002686 if (!receiver.callStatusChangedLocked(provider, status, extras)) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002687 receiverDead = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002688 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
Mike Lockwood03ca2162010-04-01 08:10:09 -07002689 }
2690 }
2691
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002692 // track expired records
Laurent Tu75defb62012-11-01 16:21:52 -07002693 if (r.mRequest.getNumUpdates() <= 0 || r.mRequest.getExpireAt() < now) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002694 if (deadUpdateRecords == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002695 deadUpdateRecords = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002696 }
2697 deadUpdateRecords.add(r);
2698 }
2699 // track dead receivers
2700 if (receiverDead) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002701 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002702 deadReceivers = new ArrayList<>();
Mike Lockwood03ca2162010-04-01 08:10:09 -07002703 }
2704 if (!deadReceivers.contains(receiver)) {
2705 deadReceivers.add(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002706 }
2707 }
2708 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002709
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002710 // remove dead records and receivers outside the loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002711 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002712 for (Receiver receiver : deadReceivers) {
2713 removeUpdatesLocked(receiver);
2714 }
2715 }
2716 if (deadUpdateRecords != null) {
2717 for (UpdateRecord r : deadUpdateRecords) {
2718 r.disposeLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 }
Victoria Lease8b38b292012-12-04 15:04:43 -08002720 applyRequirementsLocked(provider);
2721 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002722 }
2723
2724 private class LocationWorkerHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08002725 public LocationWorkerHandler(Looper looper) {
2726 super(looper, null, true);
2727 }
2728
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002729 @Override
2730 public void handleMessage(Message msg) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002731 switch (msg.what) {
2732 case MSG_LOCATION_CHANGED:
2733 handleLocationChanged((Location) msg.obj, msg.arg1 == 1);
2734 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002735 }
2736 }
2737 }
2738
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002739 private boolean isMockProvider(String provider) {
2740 synchronized (mLock) {
2741 return mMockProviders.containsKey(provider);
2742 }
2743 }
2744
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002745 private void handleLocationChanged(Location location, boolean passive) {
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002746 // create a working copy of the incoming Location so that the service can modify it without
2747 // disturbing the caller's copy
2748 Location myLocation = new Location(location);
2749 String provider = myLocation.getProvider();
2750
2751 // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this
2752 // bit if location did not come from a mock provider because passive/fused providers can
2753 // forward locations from mock providers, and should not grant them legitimacy in doing so.
2754 if (!myLocation.isFromMockProvider() && isMockProvider(provider)) {
2755 myLocation.setIsFromMockProvider(true);
2756 }
Jeff Sharkey5e613312012-01-30 11:16:20 -08002757
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002758 synchronized (mLock) {
Victoria Lease09eeaec2013-02-05 11:34:13 -08002759 if (isAllowedByCurrentUserSettingsLocked(provider)) {
2760 if (!passive) {
2761 // notify passive provider of the new location
2762 mPassiveProvider.updateLocation(myLocation);
2763 }
Victoria Lease54ca7ae2013-01-08 09:39:50 -08002764 handleLocationChangedLocked(myLocation, passive);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002765 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002766 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002767 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002768
Mike Lockwoode97ae402010-09-29 15:23:46 -04002769 private final PackageMonitor mPackageMonitor = new PackageMonitor() {
2770 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002771 public void onPackageDisappeared(String packageName, int reason) {
2772 // remove all receivers associated with this package name
2773 synchronized (mLock) {
2774 ArrayList<Receiver> deadReceivers = null;
2775
2776 for (Receiver receiver : mReceivers.values()) {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002777 if (receiver.mIdentity.mPackageName.equals(packageName)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002778 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002779 deadReceivers = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002780 }
2781 deadReceivers.add(receiver);
2782 }
2783 }
2784
2785 // perform removal outside of mReceivers loop
2786 if (deadReceivers != null) {
2787 for (Receiver receiver : deadReceivers) {
2788 removeUpdatesLocked(receiver);
2789 }
2790 }
2791 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002792 }
Mike Lockwoode97ae402010-09-29 15:23:46 -04002793 };
2794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002795 // Geocoder
2796
Nick Pellye0fd6932012-07-11 10:26:13 -07002797 @Override
Mike Lockwoode15735a2010-09-20 17:48:47 -04002798 public boolean geocoderIsPresent() {
Mark Vandevoorde01ac80b2010-05-21 15:43:26 -07002799 return mGeocodeProvider != null;
2800 }
2801
Nick Pellye0fd6932012-07-11 10:26:13 -07002802 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002803 public String getFromLocation(double latitude, double longitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002804 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002805 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002806 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
2807 params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002808 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002809 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002810 }
2811
Mike Lockwooda55c3212009-04-15 11:10:11 -04002812
Nick Pellye0fd6932012-07-11 10:26:13 -07002813 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002814 public String getFromLocationName(String locationName,
Mike Lockwooda55c3212009-04-15 11:10:11 -04002815 double lowerLeftLatitude, double lowerLeftLongitude,
2816 double upperRightLatitude, double upperRightLongitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002817 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002818
2819 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002820 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
2821 lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
2822 maxResults, params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002823 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002824 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002825 }
2826
2827 // Mock Providers
2828
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002829 private boolean canCallerAccessMockLocation(String opPackageName) {
2830 return mAppOps.noteOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(),
2831 opPackageName) == AppOpsManager.MODE_ALLOWED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002832 }
2833
Nick Pellye0fd6932012-07-11 10:26:13 -07002834 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002835 public void addTestProvider(String name, ProviderProperties properties, String opPackageName) {
2836 if (!canCallerAccessMockLocation(opPackageName)) {
2837 return;
2838 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002839
Mike Lockwooda4903f22010-02-17 06:42:23 -05002840 if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
2841 throw new IllegalArgumentException("Cannot mock the passive location provider");
2842 }
2843
Mike Lockwood86328a92009-10-23 08:38:25 -04002844 long identity = Binder.clearCallingIdentity();
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002845 synchronized (mLock) {
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002846 // remove the real provider if we are replacing GPS or network provider
2847 if (LocationManager.GPS_PROVIDER.equals(name)
Nick Pelly1332b532012-08-21 16:25:47 -07002848 || LocationManager.NETWORK_PROVIDER.equals(name)
2849 || LocationManager.FUSED_PROVIDER.equals(name)) {
Mike Lockwoodd03ff942010-02-09 08:46:14 -05002850 LocationProviderInterface p = mProvidersByName.get(name);
2851 if (p != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002852 removeProviderLocked(p);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002853 }
2854 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09002855 addTestProviderLocked(name, properties);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002856 updateProvidersLocked();
2857 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002858 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002859 }
2860
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09002861 private void addTestProviderLocked(String name, ProviderProperties properties) {
2862 if (mProvidersByName.get(name) != null) {
2863 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
2864 }
2865 MockProvider provider = new MockProvider(name, this, properties);
2866 addProviderLocked(provider);
2867 mMockProviders.put(name, provider);
2868 mLastLocation.put(name, null);
2869 mLastLocationCoarseInterval.put(name, null);
2870 }
2871
Nick Pellye0fd6932012-07-11 10:26:13 -07002872 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002873 public void removeTestProvider(String provider, String opPackageName) {
2874 if (!canCallerAccessMockLocation(opPackageName)) {
2875 return;
2876 }
2877
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002878 synchronized (mLock) {
Tom O'Neill07ee5d12014-03-03 17:48:35 -08002879
2880 // These methods can't be called after removing the test provider, so first make sure
Tom O'Neillfe6d3c52014-03-04 08:26:17 -08002881 // we don't leave anything dangling.
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002882 clearTestProviderEnabled(provider, opPackageName);
2883 clearTestProviderLocation(provider, opPackageName);
2884 clearTestProviderStatus(provider, opPackageName);
Tom O'Neill07ee5d12014-03-03 17:48:35 -08002885
You Kima6d0b6f2012-10-28 03:58:44 +09002886 MockProvider mockProvider = mMockProviders.remove(provider);
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002887 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002888 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2889 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002890 long identity = Binder.clearCallingIdentity();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002891 removeProviderLocked(mProvidersByName.get(provider));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002892
2893 // reinstate real provider if available
2894 LocationProviderInterface realProvider = mRealProviders.get(provider);
2895 if (realProvider != null) {
2896 addProviderLocked(realProvider);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002897 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002898 mLastLocation.put(provider, null);
David Christie1b9b7b12013-04-15 15:31:11 -07002899 mLastLocationCoarseInterval.put(provider, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002900 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04002901 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002902 }
2903 }
2904
Nick Pellye0fd6932012-07-11 10:26:13 -07002905 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002906 public void setTestProviderLocation(String provider, Location loc, String opPackageName) {
2907 if (!canCallerAccessMockLocation(opPackageName)) {
2908 return;
2909 }
2910
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002911 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002912 MockProvider mockProvider = mMockProviders.get(provider);
2913 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002914 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2915 }
Tom O'Neilla206a0f2016-12-15 10:26:28 -08002916
2917 // Ensure that the location is marked as being mock. There's some logic to do this in
2918 // handleLocationChanged(), but it fails if loc has the wrong provider (bug 33091107).
2919 Location mock = new Location(loc);
2920 mock.setIsFromMockProvider(true);
2921
2922 if (!TextUtils.isEmpty(loc.getProvider()) && !provider.equals(loc.getProvider())) {
2923 // The location has an explicit provider that is different from the mock provider
2924 // name. The caller may be trying to fool us via bug 33091107.
2925 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
2926 provider + "!=" + loc.getProvider());
2927 }
2928
Mike Lockwood95427cd2009-05-07 13:27:54 -04002929 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
2930 long identity = Binder.clearCallingIdentity();
Tom O'Neilla206a0f2016-12-15 10:26:28 -08002931 mockProvider.setLocation(mock);
Mike Lockwood95427cd2009-05-07 13:27:54 -04002932 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002933 }
2934 }
2935
Nick Pellye0fd6932012-07-11 10:26:13 -07002936 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002937 public void clearTestProviderLocation(String provider, String opPackageName) {
2938 if (!canCallerAccessMockLocation(opPackageName)) {
2939 return;
2940 }
2941
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002942 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002943 MockProvider mockProvider = mMockProviders.get(provider);
2944 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002945 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2946 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002947 mockProvider.clearLocation();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002948 }
2949 }
2950
Nick Pellye0fd6932012-07-11 10:26:13 -07002951 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002952 public void setTestProviderEnabled(String provider, boolean enabled, String opPackageName) {
2953 if (!canCallerAccessMockLocation(opPackageName)) {
2954 return;
2955 }
2956
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002957 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002958 MockProvider mockProvider = mMockProviders.get(provider);
2959 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002960 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2961 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002962 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002963 if (enabled) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002964 mockProvider.enable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002965 mEnabledProviders.add(provider);
2966 mDisabledProviders.remove(provider);
2967 } else {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002968 mockProvider.disable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002969 mEnabledProviders.remove(provider);
2970 mDisabledProviders.add(provider);
2971 }
2972 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04002973 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002974 }
2975 }
2976
Nick Pellye0fd6932012-07-11 10:26:13 -07002977 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002978 public void clearTestProviderEnabled(String provider, String opPackageName) {
2979 if (!canCallerAccessMockLocation(opPackageName)) {
2980 return;
2981 }
2982
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002983 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07002984 MockProvider mockProvider = mMockProviders.get(provider);
2985 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002986 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2987 }
Mike Lockwood86328a92009-10-23 08:38:25 -04002988 long identity = Binder.clearCallingIdentity();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002989 mEnabledProviders.remove(provider);
2990 mDisabledProviders.remove(provider);
2991 updateProvidersLocked();
Mike Lockwood86328a92009-10-23 08:38:25 -04002992 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002993 }
2994 }
2995
Nick Pellye0fd6932012-07-11 10:26:13 -07002996 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002997 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime,
2998 String opPackageName) {
2999 if (!canCallerAccessMockLocation(opPackageName)) {
3000 return;
3001 }
3002
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003003 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003004 MockProvider mockProvider = mMockProviders.get(provider);
3005 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003006 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3007 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003008 mockProvider.setStatus(status, extras, updateTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003009 }
3010 }
3011
Nick Pellye0fd6932012-07-11 10:26:13 -07003012 @Override
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003013 public void clearTestProviderStatus(String provider, String opPackageName) {
3014 if (!canCallerAccessMockLocation(opPackageName)) {
3015 return;
3016 }
3017
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003018 synchronized (mLock) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003019 MockProvider mockProvider = mMockProviders.get(provider);
3020 if (mockProvider == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003021 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3022 }
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003023 mockProvider.clearStatus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003024 }
3025 }
3026
3027 private void log(String log) {
3028 if (Log.isLoggable(TAG, Log.VERBOSE)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003029 Slog.d(TAG, log);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003030 }
3031 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003032
3033 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003034 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003035 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Nick Pellye0fd6932012-07-11 10:26:13 -07003036
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04003037 synchronized (mLock) {
Siddharth Raybb608c82017-03-16 11:33:34 -07003038 if (args.length > 0 && args[0].equals("--gnssmetrics")) {
3039 if (mGnssMetricsProvider != null) {
3040 pw.append(mGnssMetricsProvider.getGnssMetricsAsProtoString());
3041 }
3042 return;
3043 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003044 pw.println("Current Location Manager state:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003045 pw.println(" Location Listeners:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003046 for (Receiver receiver : mReceivers.values()) {
3047 pw.println(" " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003048 }
David Christie2ff96af2014-01-30 16:09:37 -08003049 pw.println(" Active Records by Provider:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003050 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
3051 pw.println(" " + entry.getKey() + ":");
3052 for (UpdateRecord record : entry.getValue()) {
3053 pw.println(" " + record);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 }
3055 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003056 pw.println(" Overlay Provider Packages:");
3057 for (LocationProviderInterface provider : mProviders) {
3058 if (provider instanceof LocationProviderProxy) {
3059 pw.println(" " + provider.getName() + ": "
3060 + ((LocationProviderProxy) provider).getConnectedPackageName());
3061 }
3062 }
David Christie2ff96af2014-01-30 16:09:37 -08003063 pw.println(" Historical Records by Provider:");
3064 for (Map.Entry<PackageProviderKey, PackageStatistics> entry
3065 : mRequestStatistics.statistics.entrySet()) {
3066 PackageProviderKey key = entry.getKey();
3067 PackageStatistics stats = entry.getValue();
3068 pw.println(" " + key.packageName + ": " + key.providerName + ": " + stats);
3069 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003070 pw.println(" Last Known Locations:");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003071 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
3072 String provider = entry.getKey();
3073 Location location = entry.getValue();
3074 pw.println(" " + provider + ": " + location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003075 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003076
David Christie1b9b7b12013-04-15 15:31:11 -07003077 pw.println(" Last Known Locations Coarse Intervals:");
3078 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
3079 String provider = entry.getKey();
3080 Location location = entry.getValue();
3081 pw.println(" " + provider + ": " + location);
3082 }
3083
Nick Pellye0fd6932012-07-11 10:26:13 -07003084 mGeofenceManager.dump(pw);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086 if (mEnabledProviders.size() > 0) {
3087 pw.println(" Enabled Providers:");
3088 for (String i : mEnabledProviders) {
3089 pw.println(" " + i);
3090 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003091
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003092 }
3093 if (mDisabledProviders.size() > 0) {
3094 pw.println(" Disabled Providers:");
3095 for (String i : mDisabledProviders) {
3096 pw.println(" " + i);
3097 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003098 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07003099 pw.append(" ");
3100 mBlacklist.dump(pw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003101 if (mMockProviders.size() > 0) {
3102 pw.println(" Mock Providers:");
3103 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
Mike Lockwood7ec434e2009-03-27 07:46:48 -07003104 i.getValue().dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003105 }
3106 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003107
Soonil Nagarkar2b565df2017-02-14 13:33:23 -08003108 if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
3109 pw.println(" Throttling Whitelisted Packages:");
3110 for (String packageName : mBackgroundThrottlePackageWhitelist) {
3111 pw.println(" " + packageName);
3112 }
3113 }
3114
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003115 pw.append(" fudger: ");
3116 mLocationFudger.dump(fd, pw, args);
3117
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003118 if (args.length > 0 && "short".equals(args[0])) {
3119 return;
3120 }
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003121 for (LocationProviderInterface provider: mProviders) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003122 pw.print(provider.getName() + " Internal State");
3123 if (provider instanceof LocationProviderProxy) {
3124 LocationProviderProxy proxy = (LocationProviderProxy) provider;
3125 pw.print(" (" + proxy.getConnectedPackageName() + ")");
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003126 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003127 pw.println(":");
3128 provider.dump(fd, pw, args);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003129 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08003130 if (mGnssBatchingInProgress) {
3131 pw.println(" GNSS batching in progress");
3132 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003133 }
3134 }
3135}