blob: d814b9c9f1fad080cd4ee555f9c01cc48fd03d95 [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 Nagarkarbfd1f682020-01-16 10:50:14 -080019import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
20import static android.Manifest.permission.ACCESS_FINE_LOCATION;
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -080021import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
22import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
Maggieaa080f92018-01-04 15:35:11 -080023import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -080024import static android.location.LocationManager.FUSED_PROVIDER;
25import static android.location.LocationManager.GPS_PROVIDER;
26import static android.location.LocationManager.NETWORK_PROVIDER;
27import static android.location.LocationManager.PASSIVE_PROVIDER;
Kweku Adams4fb074e2019-02-01 16:03:27 -080028import static android.os.PowerManager.locationPowerSaveModeToString;
Maggieaa080f92018-01-04 15:35:11 -080029
Soonil Nagarkar77a92272020-02-11 14:04:39 -080030import static java.util.concurrent.TimeUnit.NANOSECONDS;
31
Wei Wang980b7c22018-12-06 17:53:00 -080032import android.Manifest;
Wyatt Rileycf879db2017-01-12 13:57:38 -080033import android.annotation.NonNull;
Wyatt Riley49097c02018-03-15 09:14:43 -070034import android.annotation.Nullable;
Soonil Nagarkar77a92272020-02-11 14:04:39 -080035import android.annotation.UserIdInt;
Soonil Nagarkar41a36542020-02-06 09:47:52 -080036import android.app.ActivityManager;
Maggieaa080f92018-01-04 15:35:11 -080037import android.app.AppOpsManager;
38import android.app.PendingIntent;
39import android.content.BroadcastReceiver;
Maggieaa080f92018-01-04 15:35:11 -080040import android.content.Context;
41import android.content.Intent;
42import android.content.IntentFilter;
Maggieaa080f92018-01-04 15:35:11 -080043import android.content.pm.PackageManager;
Maggieaa080f92018-01-04 15:35:11 -080044import android.location.Address;
45import android.location.Criteria;
46import android.location.GeocoderParams;
47import android.location.Geofence;
gomo226b7b72018-12-12 16:49:39 -080048import android.location.GnssMeasurementCorrections;
Yu-Han Yang519694b2020-01-14 10:51:41 -080049import android.location.GnssRequest;
Maggieaa080f92018-01-04 15:35:11 -080050import android.location.IBatchedLocationCallback;
Sasha Kuznetsova68a7a32020-02-11 06:00:10 +000051import android.location.IGnssAntennaInfoListener;
Maggieaa080f92018-01-04 15:35:11 -080052import android.location.IGnssMeasurementsListener;
53import android.location.IGnssNavigationMessageListener;
54import android.location.IGnssStatusListener;
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -080055import android.location.IGpsGeofenceHardware;
Maggieaa080f92018-01-04 15:35:11 -080056import android.location.ILocationListener;
57import android.location.ILocationManager;
Maggieaa080f92018-01-04 15:35:11 -080058import android.location.Location;
59import android.location.LocationManager;
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -080060import android.location.LocationManagerInternal;
Maggieaa080f92018-01-04 15:35:11 -080061import android.location.LocationRequest;
Chad Brubakerf1133332019-03-15 14:13:59 -070062import android.location.LocationTime;
Maggieaa080f92018-01-04 15:35:11 -080063import android.os.Binder;
64import android.os.Bundle;
Soonil Nagarkar905e7222019-10-01 12:03:29 -070065import android.os.CancellationSignal;
Maggieaa080f92018-01-04 15:35:11 -080066import android.os.Handler;
67import android.os.IBinder;
Soonil Nagarkar905e7222019-10-01 12:03:29 -070068import android.os.ICancellationSignal;
Maggieaa080f92018-01-04 15:35:11 -080069import android.os.PowerManager;
Kweku Adams4fb074e2019-02-01 16:03:27 -080070import android.os.PowerManager.ServiceType;
71import android.os.PowerManagerInternal;
Maggieaa080f92018-01-04 15:35:11 -080072import android.os.Process;
73import android.os.RemoteException;
74import android.os.SystemClock;
75import android.os.UserHandle;
Maggieaa080f92018-01-04 15:35:11 -080076import android.os.WorkSource;
Narayan Kamath32684dd2018-01-08 17:32:51 +000077import android.os.WorkSource.WorkChain;
Hongyi Zhang700137e2019-05-23 21:19:36 -070078import android.stats.location.LocationStatsEnums;
Maggieaa080f92018-01-04 15:35:11 -080079import android.text.TextUtils;
Maggieaa080f92018-01-04 15:35:11 -080080import android.util.EventLog;
81import android.util.Log;
Soonil Nagarkar06e37f62019-12-04 16:05:08 -080082import android.util.SparseArray;
WyattRileyba6072f2019-04-18 07:37:52 -070083import android.util.TimeUtils;
Yu-Han Yanga4d250e2018-10-02 21:29:20 -070084
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -080085import com.android.internal.annotations.GuardedBy;
destradaaea8a8a62014-06-23 18:19:03 -070086import com.android.internal.content.PackageMonitor;
87import com.android.internal.location.ProviderProperties;
88import com.android.internal.location.ProviderRequest;
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -080089import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060090import com.android.internal.util.DumpUtils;
Soonil Nagarkar1c572552019-07-10 13:31:47 -070091import com.android.internal.util.IndentingPrintWriter;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -080092import com.android.internal.util.Preconditions;
Soonil Nagarkar1575a042018-10-24 17:54:54 -070093import com.android.server.location.AbstractLocationProvider;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -080094import com.android.server.location.AbstractLocationProvider.State;
Soonil Nagarkarb6375a42020-01-29 15:23:06 -080095import com.android.server.location.AppForegroundHelper;
Anil Admal08b96122019-01-30 16:55:05 -080096import com.android.server.location.CallerIdentity;
destradaaea8a8a62014-06-23 18:19:03 -070097import com.android.server.location.GeocoderProxy;
98import com.android.server.location.GeofenceManager;
99import com.android.server.location.GeofenceProxy;
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800100import com.android.server.location.HardwareActivityRecognitionProxy;
destradaaea8a8a62014-06-23 18:19:03 -0700101import com.android.server.location.LocationFudger;
destradaaea8a8a62014-06-23 18:19:03 -0700102import com.android.server.location.LocationProviderProxy;
103import com.android.server.location.LocationRequestStatistics;
104import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
105import com.android.server.location.LocationRequestStatistics.PackageStatistics;
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800106import com.android.server.location.LocationUsageLogger;
destradaaea8a8a62014-06-23 18:19:03 -0700107import com.android.server.location.MockProvider;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800108import com.android.server.location.MockableLocationProvider;
destradaaea8a8a62014-06-23 18:19:03 -0700109import com.android.server.location.PassiveProvider;
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800110import com.android.server.location.SettingsHelper;
111import com.android.server.location.UserInfoHelper;
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800112import com.android.server.location.UserInfoHelper.UserListener;
Soonil Nagarkarf20d10e2020-01-27 11:05:40 -0800113import com.android.server.location.gnss.GnssManagerService;
Todd Kennedy583378d2019-07-12 06:50:30 -0700114import com.android.server.pm.permission.PermissionManagerServiceInternal;
Yu-Han Yanga4d250e2018-10-02 21:29:20 -0700115
Soonil Nagarkarae6ce772019-05-01 13:16:17 -0700116import java.io.ByteArrayOutputStream;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400117import java.io.FileDescriptor;
Soonil Nagarkarae6ce772019-05-01 13:16:17 -0700118import java.io.PrintStream;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400119import java.io.PrintWriter;
120import java.util.ArrayList;
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -0800121import java.util.Collections;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400122import java.util.HashMap;
123import java.util.HashSet;
124import java.util.List;
125import java.util.Map;
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800126import java.util.Map.Entry;
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +0000127import java.util.Objects;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800128import java.util.Set;
WyattRileyd6b82a62019-12-30 18:12:50 -0800129import java.util.TreeMap;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800130import java.util.concurrent.CopyOnWriteArrayList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131
132/**
133 * The service class that manages LocationProviders and issues location
134 * updates and alerts.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 */
Victoria Lease5cd731a2012-12-19 15:04:21 -0800136public class LocationManagerService extends ILocationManager.Stub {
Soonil Nagarkar141417a2019-10-28 11:12:48 -0700137
138 /**
139 * Controls lifecycle of LocationManagerService.
140 */
141 public static class Lifecycle extends SystemService {
142
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800143 private final LocationManagerService mService;
Soonil Nagarkar141417a2019-10-28 11:12:48 -0700144
145 public Lifecycle(Context context) {
146 super(context);
147 mService = new LocationManagerService(context);
148 }
149
150 @Override
151 public void onStart() {
Tim Murrayb5e11532019-11-12 18:23:50 -0800152 // enable client caches by doing the first invalidate
153 LocationManager.invalidateLocalLocationEnabledCaches();
154
Soonil Nagarkar141417a2019-10-28 11:12:48 -0700155 publishBinderService(Context.LOCATION_SERVICE, mService);
Tim Murrayb5e11532019-11-12 18:23:50 -0800156 // disable caching for whatever process contains LocationManagerService
157 ((LocationManager) mService.mContext.getSystemService(LocationManager.class))
158 .disableLocalLocationEnabledCaches();
Soonil Nagarkar141417a2019-10-28 11:12:48 -0700159 }
160
161 @Override
162 public void onBootPhase(int phase) {
Soonil Nagarkar37096062019-11-25 13:24:48 -0800163 if (phase == PHASE_SYSTEM_SERVICES_READY) {
164 // the location service must be functioning after this boot phase
165 mService.onSystemReady();
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800166 } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
Soonil Nagarkar37096062019-11-25 13:24:48 -0800167 // some providers rely on third party code, so we wait to initialize
168 // providers until third party code is allowed to run
169 mService.onSystemThirdPartyAppsCanStart();
Soonil Nagarkar141417a2019-10-28 11:12:48 -0700170 }
171 }
172 }
173
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800174 public static final String TAG = "LocationManagerService";
JP Abgrallf79811e72013-02-01 18:45:05 -0800175 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700176
Olivier Gaillard7a222662017-11-20 16:07:24 +0000177 private static final String WAKELOCK_KEY = "*location*";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178
Victoria Lease37425c32012-10-16 16:08:48 -0700179 private static final int RESOLUTION_LEVEL_NONE = 0;
Victoria Lease37425c32012-10-16 16:08:48 -0700180 private static final int RESOLUTION_LEVEL_COARSE = 1;
Victoria Lease37425c32012-10-16 16:08:48 -0700181 private static final int RESOLUTION_LEVEL_FINE = 2;
182
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700183 private static final String NETWORK_LOCATION_SERVICE_ACTION =
Stan Chesnutt39062dd2013-07-22 14:33:30 -0700184 "com.android.location.service.v3.NetworkLocationProvider";
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700185 private static final String FUSED_LOCATION_SERVICE_ACTION =
186 "com.android.location.service.FusedLocationProvider";
187
David Christie0b837452013-07-29 16:02:13 -0700188 // The maximum interval a location request can have and still be considered "high power".
189 private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
190
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800191 // The fastest interval that applications can receive coarse locations
192 private static final long FASTEST_COARSE_INTERVAL_MS = 10 * 60 * 1000;
193
Soonil Nagarkar905e7222019-10-01 12:03:29 -0700194 // maximum age of a location before it is no longer considered "current"
195 private static final long MAX_CURRENT_LOCATION_AGE_MS = 10 * 1000;
196
Nick Pellyf1be6862012-05-15 10:53:42 -0700197 // Location Providers may sometimes deliver location updates
198 // slightly faster that requested - provide grace period so
199 // we don't unnecessarily filter events that are otherwise on
200 // time
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700201 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
Nick Pellyf1be6862012-05-15 10:53:42 -0700202
Philip P. Moltmann12ac3f42020-03-05 15:01:29 -0800203 private static final String ATTRIBUTION_TAG = "LocationService";
Philip P. Moltmann41ace3b2020-02-19 21:49:15 +0000204
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700205 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
206
Soonil Nagarkar68257742019-01-09 19:42:34 +0000207 private final Object mLock = new Object();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800208 private final Context mContext;
209 private final Handler mHandler;
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800210 private final LocalService mLocalService;
211 private final UserInfoHelper mUserInfoHelper;
212 private final SettingsHelper mSettingsHelper;
213 private final AppForegroundHelper mAppForegroundHelper;
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800214 private final LocationUsageLogger mLocationUsageLogger;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700215
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800216 @Nullable private GnssManagerService mGnssManagerService = null;
217
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800218 private final PassiveLocationProviderManager mPassiveManager;
219
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800220 private AppOpsManager mAppOps;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700221 private PackageManager mPackageManager;
Victoria Lease0aa28602013-05-29 15:28:26 -0700222 private PowerManager mPowerManager;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800223
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800224 private GeofenceManager mGeofenceManager;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700225 private GeocoderProxy mGeocodeProvider;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800226
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800227 @GuardedBy("mLock")
Wei Wang114922a2019-01-30 18:19:35 -0800228 private String mExtraLocationControllerPackage;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800229 @GuardedBy("mLock")
Wei Wang114922a2019-01-30 18:19:35 -0800230 private boolean mExtraLocationControllerPackageEnabled;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700231
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800232 // @GuardedBy("mLock")
233 // hold lock for write or to prevent write, no lock for read
234 private final CopyOnWriteArrayList<LocationProviderManager> mProviderManagers =
235 new CopyOnWriteArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800237 @GuardedBy("mLock")
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800238 private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700239 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800240 new HashMap<>();
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700241
David Christie2ff96af2014-01-30 16:09:37 -0800242 private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics();
243
Kweku Adams4fb074e2019-02-01 16:03:27 -0800244 @GuardedBy("mLock")
245 @PowerManager.LocationPowerSaveMode
246 private int mBatterySaverMode;
247
Soonil Nagarkar141417a2019-10-28 11:12:48 -0700248 private LocationManagerService(Context context) {
Philip P. Moltmann12ac3f42020-03-05 15:01:29 -0800249 mContext = context.createAttributionContext(ATTRIBUTION_TAG);
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -0800250 mHandler = FgThread.getHandler();
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800251 mLocalService = new LocalService();
252
253 LocalServices.addService(LocationManagerInternal.class, mLocalService);
254
255 mUserInfoHelper = new UserInfoHelper(mContext);
256 mSettingsHelper = new SettingsHelper(mContext, mHandler);
257 mAppForegroundHelper = new AppForegroundHelper(mContext);
Hongyi Zhang700137e2019-05-23 21:19:36 -0700258 mLocationUsageLogger = new LocationUsageLogger();
The Android Open Source Project4df24232009-03-05 14:34:35 -0800259
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800260 // set up passive provider - we do this early because it has no dependencies on system
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800261 // services or external code that isn't ready yet, and because this allows the variable to
262 // be final. other more complex providers are initialized later, when system services are
263 // ready
264 mPassiveManager = new PassiveLocationProviderManager();
265 mProviderManagers.add(mPassiveManager);
266 mPassiveManager.setRealProvider(new PassiveProvider(mContext));
267
Svet Ganovadc1cf42015-06-15 16:36:24 -0700268 // Let the package manager query which are the default location
269 // providers as they get certain permissions granted by default.
Todd Kennedy583378d2019-07-12 06:50:30 -0700270 PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
271 PermissionManagerServiceInternal.class);
272 permissionManagerInternal.setLocationPackagesProvider(
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700273 userId -> mContext.getResources().getStringArray(
274 com.android.internal.R.array.config_locationProviderPackageNames));
Todd Kennedy583378d2019-07-12 06:50:30 -0700275 permissionManagerInternal.setLocationExtraPackagesProvider(
Wei Wangffb94e62019-01-14 00:05:45 -0800276 userId -> mContext.getResources().getStringArray(
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700277 com.android.internal.R.array.config_locationExtraPackageNames));
Svet Ganovadc1cf42015-06-15 16:36:24 -0700278
Soonil Nagarkar37096062019-11-25 13:24:48 -0800279 // most startup is deferred until systemReady()
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700280 }
281
Soonil Nagarkar37096062019-11-25 13:24:48 -0800282 private void onSystemReady() {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800283 mUserInfoHelper.onSystemReady();
284 mSettingsHelper.onSystemReady();
285 mAppForegroundHelper.onSystemReady();
286
Soonil Nagarkar68257742019-01-09 19:42:34 +0000287 synchronized (mLock) {
Soonil Nagarkar37096062019-11-25 13:24:48 -0800288 mPackageManager = mContext.getPackageManager();
289 mAppOps = mContext.getSystemService(AppOpsManager.class);
290 mPowerManager = mContext.getSystemService(PowerManager.class);
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800291 mGeofenceManager = new GeofenceManager(mContext, mSettingsHelper);
Soonil Nagarkar37096062019-11-25 13:24:48 -0800292
293 PowerManagerInternal localPowerManager =
294 LocalServices.getService(PowerManagerInternal.class);
295
296 // add listeners
297 mAppOps.startWatchingMode(
298 AppOpsManager.OP_COARSE_LOCATION,
299 null,
300 AppOpsManager.WATCH_FOREGROUND_CHANGES,
301 new AppOpsManager.OnOpChangedInternalListener() {
302 public void onOpChanged(int op, String packageName) {
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800303 // onOpChanged invoked on ui thread, move to our thread to reduce risk
304 // of blocking ui thread
Soonil Nagarkar387a2d02020-01-31 23:04:04 -0800305 mHandler.post(() -> onAppOpChanged(packageName));
Soonil Nagarkar37096062019-11-25 13:24:48 -0800306 }
307 });
308 mPackageManager.addOnPermissionsChangeListener(
309 uid -> {
310 // listener invoked on ui thread, move to our thread to reduce risk of
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800311 // blocking ui thread
Soonil Nagarkar37096062019-11-25 13:24:48 -0800312 mHandler.post(() -> {
313 synchronized (mLock) {
314 onPermissionsChangedLocked();
315 }
316 });
317 });
Soonil Nagarkar37096062019-11-25 13:24:48 -0800318
319 localPowerManager.registerLowPowerModeObserver(ServiceType.LOCATION,
320 state -> {
321 // listener invoked on ui thread, move to our thread to reduce risk of
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800322 // blocking ui thread
Soonil Nagarkar37096062019-11-25 13:24:48 -0800323 mHandler.post(() -> {
324 synchronized (mLock) {
325 onBatterySaverModeChangedLocked(state.locationMode);
326 }
327 });
328 });
329 mBatterySaverMode = mPowerManager.getLocationPowerSaveMode();
330
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800331 mSettingsHelper.addOnLocationEnabledChangedListener(this::onLocationModeChanged);
332 mSettingsHelper.addOnBackgroundThrottleIntervalChangedListener(
333 this::onBackgroundThrottleIntervalChanged);
334 mSettingsHelper.addOnBackgroundThrottlePackageWhitelistChangedListener(
335 this::onBackgroundThrottleWhitelistChanged);
336 mSettingsHelper.addOnIgnoreSettingsPackageWhitelistChangedListener(
337 this::onIgnoreSettingsWhitelistChanged);
Soonil Nagarkar37096062019-11-25 13:24:48 -0800338
339 new PackageMonitor() {
340 @Override
341 public void onPackageDisappeared(String packageName, int reason) {
342 synchronized (mLock) {
343 LocationManagerService.this.onPackageDisappearedLocked(packageName);
344 }
345 }
346 }.register(mContext, mHandler.getLooper(), true);
347
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800348 mUserInfoHelper.addListener(this::onUserChanged);
349
350 mAppForegroundHelper.addListener(this::onAppForegroundChanged);
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800351
Soonil Nagarkar37096062019-11-25 13:24:48 -0800352 IntentFilter intentFilter = new IntentFilter();
Soonil Nagarkar37096062019-11-25 13:24:48 -0800353 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
354 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
355
356 mContext.registerReceiverAsUser(new BroadcastReceiver() {
357 @Override
358 public void onReceive(Context context, Intent intent) {
359 final String action = intent.getAction();
360 if (action == null) {
361 return;
362 }
363 synchronized (mLock) {
364 switch (action) {
Soonil Nagarkar37096062019-11-25 13:24:48 -0800365 case Intent.ACTION_SCREEN_ON:
366 case Intent.ACTION_SCREEN_OFF:
367 onScreenStateChangedLocked();
368 break;
369 }
370 }
371 }
372 }, UserHandle.ALL, intentFilter, null, mHandler);
373
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800374 // initialize the current users. we would get the user started notifications for these
375 // users eventually anyways, but this takes care of it as early as possible.
376 for (int userId: mUserInfoHelper.getCurrentUserIds()) {
377 onUserChanged(userId, UserListener.USER_STARTED);
378 }
Victoria Lease5cd731a2012-12-19 15:04:21 -0800379 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800380 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700381
Soonil Nagarkar37096062019-11-25 13:24:48 -0800382 private void onSystemThirdPartyAppsCanStart() {
383 synchronized (mLock) {
384 // prepare providers
385 initializeProvidersLocked();
386 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700387 }
388
Soonil Nagarkar387a2d02020-01-31 23:04:04 -0800389 private void onAppOpChanged(String packageName) {
390 synchronized (mLock) {
391 for (Receiver receiver : mReceivers.values()) {
392 if (receiver.mCallerIdentity.mPackageName.equals(packageName)) {
393 receiver.updateMonitoring(true);
394 }
395 }
396
397 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
398 for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
399 String provider = entry.getKey();
400 for (UpdateRecord record : entry.getValue()) {
401 if (record.mReceiver.mCallerIdentity.mPackageName.equals(packageName)) {
402 affectedProviders.add(provider);
403 }
404 }
405 }
406 for (String provider : affectedProviders) {
407 applyRequirementsLocked(provider);
408 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800409 }
410 }
411
412 @GuardedBy("mLock")
413 private void onPermissionsChangedLocked() {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800414 for (LocationProviderManager manager : mProviderManagers) {
415 applyRequirementsLocked(manager);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800416 }
417 }
418
419 @GuardedBy("mLock")
Kweku Adams4fb074e2019-02-01 16:03:27 -0800420 private void onBatterySaverModeChangedLocked(int newLocationMode) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700421 if (mBatterySaverMode == newLocationMode) {
422 return;
423 }
424
Kweku Adams4fb074e2019-02-01 16:03:27 -0800425 if (D) {
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800426 Log.d(TAG,
Kweku Adams4fb074e2019-02-01 16:03:27 -0800427 "Battery Saver location mode changed from "
428 + locationPowerSaveModeToString(mBatterySaverMode) + " to "
429 + locationPowerSaveModeToString(newLocationMode));
430 }
431
Kweku Adams4fb074e2019-02-01 16:03:27 -0800432 mBatterySaverMode = newLocationMode;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700433
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800434 for (LocationProviderManager manager : mProviderManagers) {
435 applyRequirementsLocked(manager);
Kweku Adams4fb074e2019-02-01 16:03:27 -0800436 }
437 }
438
439 @GuardedBy("mLock")
440 private void onScreenStateChangedLocked() {
441 if (mBatterySaverMode == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800442 for (LocationProviderManager manager : mProviderManagers) {
443 applyRequirementsLocked(manager);
Kweku Adams4fb074e2019-02-01 16:03:27 -0800444 }
445 }
446 }
447
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800448 private void onLocationModeChanged(int userId) {
449 boolean enabled = mSettingsHelper.isLocationEnabled(userId);
Tim Murrayb5e11532019-11-12 18:23:50 -0800450 LocationManager.invalidateLocalLocationEnabledCaches();
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800451
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800452 if (D) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800453 Log.d(TAG, "[u" + userId + "] location enabled = " + enabled);
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800454 }
455
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800456 Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION)
457 .putExtra(LocationManager.EXTRA_LOCATION_ENABLED, enabled)
458 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
459 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
460 mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800461
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800462 synchronized (mLock) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800463 for (LocationProviderManager manager : mProviderManagers) {
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800464 manager.onEnabledChangedLocked(userId);
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800465 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800466 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800467 }
468
469 @GuardedBy("mLock")
470 private void onPackageDisappearedLocked(String packageName) {
471 ArrayList<Receiver> deadReceivers = null;
472
473 for (Receiver receiver : mReceivers.values()) {
Anil Admal08b96122019-01-30 16:55:05 -0800474 if (receiver.mCallerIdentity.mPackageName.equals(packageName)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800475 if (deadReceivers == null) {
476 deadReceivers = new ArrayList<>();
477 }
478 deadReceivers.add(receiver);
479 }
480 }
481
482 // perform removal outside of mReceivers loop
483 if (deadReceivers != null) {
484 for (Receiver receiver : deadReceivers) {
485 removeUpdatesLocked(receiver);
486 }
487 }
488 }
489
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800490 private void onAppForegroundChanged(int uid, boolean foreground) {
491 synchronized (mLock) {
492 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
493 for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
494 String provider = entry.getKey();
495 for (UpdateRecord record : entry.getValue()) {
496 if (record.mReceiver.mCallerIdentity.mUid == uid
497 && record.mIsForegroundUid != foreground) {
498 record.updateForeground(foreground);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800499
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800500 if (!isThrottlingExempt(record.mReceiver.mCallerIdentity)) {
501 affectedProviders.add(provider);
502 }
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700503 }
504 }
505 }
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800506 for (String provider : affectedProviders) {
507 applyRequirementsLocked(provider);
508 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800509 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800510 }
511
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800512 private void onBackgroundThrottleIntervalChanged() {
513 synchronized (mLock) {
514 for (LocationProviderManager manager : mProviderManagers) {
515 applyRequirementsLocked(manager);
516 }
Soonil Nagarkar68257742019-01-09 19:42:34 +0000517 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -0800518 }
519
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800520 private void onBackgroundThrottleWhitelistChanged() {
521 synchronized (mLock) {
522 for (LocationProviderManager manager : mProviderManagers) {
523 applyRequirementsLocked(manager);
524 }
Soonil Nagarkar68257742019-01-09 19:42:34 +0000525 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -0800526 }
527
Soonil Nagarkarb6375a42020-01-29 15:23:06 -0800528 private void onIgnoreSettingsWhitelistChanged() {
529 synchronized (mLock) {
530 for (LocationProviderManager manager : mProviderManagers) {
531 applyRequirementsLocked(manager);
532 }
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800533 }
534 }
535
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800536 @GuardedBy("mLock")
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800537 private void initializeProvidersLocked() {
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800538 LocationProviderProxy networkProvider = LocationProviderProxy.createAndRegister(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700539 mContext,
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700540 NETWORK_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700541 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800542 com.android.internal.R.string.config_networkLocationProviderPackageName);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700543 if (networkProvider != null) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800544 LocationProviderManager networkManager = new LocationProviderManager(NETWORK_PROVIDER);
545 mProviderManagers.add(networkManager);
546 networkManager.setRealProvider(networkProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700547 } else {
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800548 Log.w(TAG, "no network location provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700549 }
550
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800551 // ensure that a fused provider exists which will work in direct boot
552 Preconditions.checkState(!mContext.getPackageManager().queryIntentServicesAsUser(
553 new Intent(FUSED_LOCATION_SERVICE_ACTION),
554 MATCH_DIRECT_BOOT_AWARE | MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM).isEmpty(),
555 "Unable to find a direct boot aware fused location provider");
556
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700557 // bind to fused provider
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800558 LocationProviderProxy fusedProvider = LocationProviderProxy.createAndRegister(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700559 mContext,
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700560 FUSED_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700561 com.android.internal.R.bool.config_enableFusedLocationOverlay,
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800562 com.android.internal.R.string.config_fusedLocationProviderPackageName);
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700563 if (fusedProvider != null) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800564 LocationProviderManager fusedManager = new LocationProviderManager(FUSED_PROVIDER);
565 mProviderManagers.add(fusedManager);
566 fusedManager.setRealProvider(fusedProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700567 } else {
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800568 Log.e(TAG, "no fused location provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700569 }
570
571 // bind to geocoder provider
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800572 mGeocodeProvider = GeocoderProxy.createAndRegister(mContext);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700573 if (mGeocodeProvider == null) {
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800574 Log.e(TAG, "no geocoder provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700575 }
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700576
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800577 // bind to geofence proxy
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700578 if (mGnssManagerService != null) {
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800579 IGpsGeofenceHardware gpsGeofenceHardware = mGnssManagerService.getGpsGeofenceProxy();
580 if (gpsGeofenceHardware != null) {
581 GeofenceProxy provider = GeofenceProxy.createAndBind(mContext, gpsGeofenceHardware);
582 if (provider == null) {
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800583 Log.e(TAG, "unable to bind to GeofenceProxy");
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800584 }
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700585 }
destradaa0682809a2013-08-12 18:50:30 -0700586 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900587
Brian Duddiecfa5b5b2019-01-22 18:01:40 +0000588 // bind to hardware activity recognition
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800589 HardwareActivityRecognitionProxy hardwareActivityRecognitionProxy =
590 HardwareActivityRecognitionProxy.createAndRegister(mContext);
591 if (hardwareActivityRecognitionProxy == null) {
592 Log.e(TAG, "unable to bind ActivityRecognitionProxy");
Brian Duddiecfa5b5b2019-01-22 18:01:40 +0000593 }
594
Soonil Nagarkar6d21a4d2020-01-22 16:21:00 -0800595 String[] testProviderStrings = mContext.getResources().getStringArray(
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900596 com.android.internal.R.array.config_testLocationProviders);
597 for (String testProviderString : testProviderStrings) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -0800598 String[] fragments = testProviderString.split(",");
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900599 String name = fragments[0].trim();
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900600 ProviderProperties properties = new ProviderProperties(
601 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
602 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
603 Boolean.parseBoolean(fragments[3]) /* requiresCell */,
604 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
605 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
606 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
607 Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
608 Integer.parseInt(fragments[8]) /* powerRequirement */,
609 Integer.parseInt(fragments[9]) /* accuracy */);
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800610 addTestProvider(name, properties, mContext.getOpPackageName());
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900611 }
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800612
613 // initialize gnss last because it has no awareness of boot phases and blindly assumes that
614 // all other location providers are loaded at initialization
615 if (GnssManagerService.isGnssSupported()) {
616 mGnssManagerService = new GnssManagerService(mContext, mSettingsHelper,
617 mAppForegroundHelper, mLocationUsageLogger);
618 mGnssManagerService.onSystemReady();
619
620 LocationProviderManager gnssManager = new LocationProviderManager(GPS_PROVIDER);
621 mProviderManagers.add(gnssManager);
622 gnssManager.setRealProvider(mGnssManagerService.getGnssLocationProvider());
623 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700624 }
Mike Lockwood9637d472009-04-02 21:41:57 -0700625
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800626 private void onUserChanged(@UserIdInt int userId, @UserListener.UserChange int change) {
627 switch (change) {
628 case UserListener.USER_SWITCHED:
629 if (D) {
630 Log.d(TAG, "user " + userId + " current status changed");
631 }
632 synchronized (mLock) {
633 for (LocationProviderManager manager : mProviderManagers) {
634 manager.onEnabledChangedLocked(userId);
635 }
636 }
637 break;
638 case UserListener.USER_STARTED:
639 if (D) {
640 Log.d(TAG, "user " + userId + " started");
641 }
642 synchronized (mLock) {
643 for (LocationProviderManager manager : mProviderManagers) {
644 manager.onUserStarted(userId);
645 }
646 }
647 break;
648 case UserListener.USER_STOPPED:
649 if (D) {
650 Log.d(TAG, "user " + userId + " stopped");
651 }
652 synchronized (mLock) {
653 for (LocationProviderManager manager : mProviderManagers) {
654 manager.onUserStopped(userId);
655 }
656 }
657 break;
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800658 }
Victoria Lease38389b62012-09-30 11:44:22 -0700659 }
660
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700661 /**
662 * Location provider manager, manages a LocationProvider.
663 */
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800664 class LocationProviderManager implements MockableLocationProvider.Listener {
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700665
666 private final String mName;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700667
Soonil Nagarkar070e54d2020-02-18 11:26:02 -0800668 private final LocationFudger mLocationFudger;
669
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800670 // if the provider is enabled for a given user id - null or not present means unknown
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800671 @GuardedBy("mLock")
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800672 private final SparseArray<Boolean> mEnabled;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700673
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800674 // last location for a given user
675 @GuardedBy("mLock")
676 private final SparseArray<Location> mLastLocation;
677
678 // last coarse location for a given user
679 @GuardedBy("mLock")
680 private final SparseArray<Location> mLastCoarseLocation;
681
682 // acquiring mLock makes operations on mProvider atomic, but is otherwise unnecessary
683 protected final MockableLocationProvider mProvider;
684
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800685 private LocationProviderManager(String name) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800686 mName = name;
Soonil Nagarkar070e54d2020-02-18 11:26:02 -0800687 mLocationFudger = new LocationFudger(mSettingsHelper.getCoarseLocationAccuracyM());
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800688 mEnabled = new SparseArray<>(2);
689 mLastLocation = new SparseArray<>(2);
690 mLastCoarseLocation = new SparseArray<>(2);
Soonil Nagarkar42da1b12019-01-22 11:29:27 -0800691
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800692 // initialize last since this lets our reference escape
Soonil Nagarkar17d8c832020-01-29 18:02:53 -0800693 mProvider = new MockableLocationProvider(mLock, this);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800694 }
695
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700696 public String getName() {
697 return mName;
698 }
699
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800700 public boolean hasProvider() {
701 return mProvider.getProvider() != null;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700702 }
703
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800704 public void setRealProvider(AbstractLocationProvider provider) {
705 mProvider.setRealProvider(provider);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800706 }
707
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800708 public void setMockProvider(@Nullable MockProvider provider) {
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800709 synchronized (mLock) {
710 mProvider.setMockProvider(provider);
711
Soonil Nagarkar070e54d2020-02-18 11:26:02 -0800712 // when removing a mock provider, also clear any mock last locations and reset the
713 // location fudger. the mock provider could have been used to infer the current
714 // location fudger offsets.
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800715 if (provider == null) {
716 for (int i = 0; i < mLastLocation.size(); i++) {
717 Location lastLocation = mLastLocation.valueAt(i);
718 if (lastLocation != null && lastLocation.isFromMockProvider()) {
719 mLastLocation.setValueAt(i, null);
720 }
721 }
722
723 for (int i = 0; i < mLastCoarseLocation.size(); i++) {
724 Location lastCoarseLocation = mLastCoarseLocation.valueAt(i);
725 if (lastCoarseLocation != null && lastCoarseLocation.isFromMockProvider()) {
726 mLastCoarseLocation.setValueAt(i, null);
727 }
728 }
Soonil Nagarkar070e54d2020-02-18 11:26:02 -0800729
730 mLocationFudger.resetOffsets();
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800731 }
732 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800733 }
734
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800735 public Set<String> getPackages() {
736 return mProvider.getState().providerPackageNames;
737 }
738
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700739 @Nullable
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800740 public ProviderProperties getProperties() {
741 return mProvider.getState().properties;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700742 }
743
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800744 @Nullable
745 public Location getLastFineLocation(int userId) {
746 synchronized (mLock) {
747 return mLastLocation.get(userId);
748 }
749 }
750
751 @Nullable
752 public Location getLastCoarseLocation(int userId) {
753 synchronized (mLock) {
754 return mLastCoarseLocation.get(userId);
755 }
756 }
757
758 public void injectLastLocation(Location location, int userId) {
759 synchronized (mLock) {
760 if (mLastLocation.get(userId) == null) {
761 setLastLocation(location, userId);
762 }
763 }
764 }
765
766 private void setLastLocation(Location location, int userId) {
767 synchronized (mLock) {
768 mLastLocation.put(userId, location);
769
770 // update last coarse interval only if enough time has passed
771 long timeDeltaMs = Long.MAX_VALUE;
772 Location coarseLocation = mLastCoarseLocation.get(userId);
773 if (coarseLocation != null) {
774 timeDeltaMs = NANOSECONDS.toMillis(location.getElapsedRealtimeNanos())
775 - NANOSECONDS.toMillis(coarseLocation.getElapsedRealtimeNanos());
776 }
777 if (timeDeltaMs > FASTEST_COARSE_INTERVAL_MS) {
778 mLastCoarseLocation.put(userId, mLocationFudger.createCoarse(location));
779 }
780 }
781 }
782
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800783 public void setMockProviderAllowed(boolean enabled) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800784 synchronized (mLock) {
785 if (!mProvider.isMock()) {
786 throw new IllegalArgumentException(mName + " provider is not a test provider");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800787 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800788
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800789 mProvider.setMockProviderAllowed(enabled);
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800790 }
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700791 }
792
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800793 public void setMockProviderLocation(Location location) {
794 synchronized (mLock) {
795 if (!mProvider.isMock()) {
796 throw new IllegalArgumentException(mName + " provider is not a test provider");
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700797 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800798
799 String locationProvider = location.getProvider();
800 if (!TextUtils.isEmpty(locationProvider) && !mName.equals(locationProvider)) {
801 // The location has an explicit provider that is different from the mock
802 // provider name. The caller may be trying to fool us via b/33091107.
803 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
804 mName + "!=" + locationProvider);
805 }
806
807 mProvider.setMockProviderLocation(location);
808 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700809 }
810
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800811 public List<LocationRequest> getMockProviderRequests() {
812 synchronized (mLock) {
813 if (!mProvider.isMock()) {
814 throw new IllegalArgumentException(mName + " provider is not a test provider");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800815 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800816
817 return mProvider.getCurrentRequest().locationRequests;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800818 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800819 }
820
821 public void setRequest(ProviderRequest request) {
822 mProvider.setRequest(request);
823 }
824
825 public void sendExtraCommand(int uid, int pid, String command, Bundle extras) {
826 mProvider.sendExtraCommand(uid, pid, command, extras);
827 }
828
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800829 @GuardedBy("mLock")
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700830 @Override
831 public void onReportLocation(Location location) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800832 // don't validate mock locations
833 if (!location.isFromMockProvider()) {
834 if (location.getLatitude() == 0 && location.getLongitude() == 0) {
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800835 Log.w(TAG, "blocking 0,0 location from " + mName + " provider");
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800836 return;
837 }
Soonil Nagarkar7fc24c62019-10-18 17:32:38 -0700838 }
839
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800840 if (!location.isComplete()) {
841 Log.w(TAG, "blocking incomplete location from " + mName + " provider");
842 return;
843 }
844
845 // update last location if the provider is enabled or if servicing a bypass request
846 boolean locationSettingsIgnored = mProvider.getCurrentRequest().locationSettingsIgnored;
847 for (int userId : mUserInfoHelper.getCurrentUserIds()) {
848 if (locationSettingsIgnored || isEnabled(userId)) {
849 setLastLocation(location, userId);
850 }
851 }
852
853 handleLocationChangedLocked(this, location, mLocationFudger.createCoarse(location));
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700854 }
855
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800856 @GuardedBy("mLock")
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700857 @Override
858 public void onReportLocation(List<Location> locations) {
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800859 if (mGnssManagerService == null || !GPS_PROVIDER.equals(mName)) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800860 return;
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700861 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800862
863 mGnssManagerService.onReportLocation(locations);
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700864 }
865
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800866 @GuardedBy("mLock")
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700867 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800868 public void onStateChanged(State oldState, State newState) {
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800869 if (oldState.allowed != newState.allowed) {
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800870 onEnabledChangedLocked(UserHandle.USER_ALL);
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700871 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700872 }
873
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800874 public void onUserStarted(int userId) {
875 synchronized (mLock) {
876 // clear the user's enabled state in order to force a reevalution of whether the
877 // provider is enabled or disabled for the given user. we clear the user's state
878 // first to ensure that a user starting never causes any change notifications. it's
879 // possible for us to observe a user before we observe it's been started (for
880 // example, another component gets a user started notification before us and
881 // registers a location request immediately), which would cause us to already have
882 // some state in place. when we eventually do get the user started notification
883 // ourselves we don't want to send a change notification based on the prior state
884 mEnabled.put(userId, null);
885 onEnabledChangedLocked(userId);
886 }
887 }
888
889 public void onUserStopped(int userId) {
890 synchronized (mLock) {
891 mEnabled.remove(userId);
892 mLastLocation.remove(userId);
893 mLastCoarseLocation.remove(userId);
894 }
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800895 }
896
897 public boolean isEnabled(int userId) {
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800898 if (userId == UserHandle.USER_NULL) {
899 // used during initialization - ignore since many lower level operations (checking
900 // settings for instance) do not support the null user
901 return false;
902 }
903
Soonil Nagarkar66c0bac2019-01-15 13:36:44 -0800904 synchronized (mLock) {
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800905 Boolean enabled = mEnabled.get(userId);
906 if (enabled == null) {
907 // this generally shouldn't occur, but might be possible due to race conditions
908 // on when we are notified of new users
909 Log.w(TAG, mName + " provider saw user " + userId + " unexpectedly");
910 onEnabledChangedLocked(userId);
911 enabled = Objects.requireNonNull(mEnabled.get(userId));
912 }
913
914 return enabled;
Soonil Nagarkar66c0bac2019-01-15 13:36:44 -0800915 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700916 }
917
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800918 @GuardedBy("mLock")
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800919 public void onEnabledChangedLocked(int userId) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800920 if (userId == UserHandle.USER_NULL) {
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800921 // used during initialization - ignore since many lower level operations (checking
922 // settings for instance) do not support the null user
923 return;
924 } else if (userId == UserHandle.USER_ALL) {
925 // we know enabled changes can only happen for current users since providers are
926 // always disabled for all non-current users
927 for (int currentUserId : mUserInfoHelper.getCurrentUserIds()) {
928 onEnabledChangedLocked(currentUserId);
929 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800930 return;
931 }
932
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800933 // if any property that contributes to "enabled" here changes state, it MUST result
934 // in a direct or indrect call to onEnabledChangedLocked. this allows the provider to
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800935 // guarantee that it will always eventually reach the correct state.
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800936 boolean enabled = mProvider.getState().allowed
937 && mUserInfoHelper.isCurrentUserId(userId)
938 && mSettingsHelper.isLocationEnabled(userId);
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800939
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800940 Boolean wasEnabled = mEnabled.get(userId);
941 if (wasEnabled != null && wasEnabled == enabled) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800942 return;
943 }
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800944
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800945 mEnabled.put(userId, enabled);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800946
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800947 if (D) {
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -0800948 Log.d(TAG, "[u" + userId + "] " + mName + " provider enabled = " + enabled);
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800949 }
950
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800951 // clear last locations if we become disabled and if not servicing a bypass request
952 if (!enabled && !mProvider.getCurrentRequest().locationSettingsIgnored) {
953 mLastLocation.put(userId, null);
954 mLastCoarseLocation.put(userId, null);
Soonil Nagarkar57f4b7b2019-12-09 10:19:18 -0800955 }
956
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800957 // update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility
958 mSettingsHelper.setLocationProviderAllowed(mName, enabled, userId);
959
960 // do not send change notifications if we just saw this user for the first time
961 if (wasEnabled != null) {
962 // fused and passive provider never get public updates for legacy reasons
963 if (!FUSED_PROVIDER.equals(mName) && !PASSIVE_PROVIDER.equals(mName)) {
964 Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION)
965 .putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName)
966 .putExtra(LocationManager.EXTRA_PROVIDER_ENABLED, enabled)
967 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
968 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
969 mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
970 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800971 }
972
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800973 updateProviderEnabledLocked(this, enabled);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800974 }
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800975
976 public void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
977 synchronized (mLock) {
978 pw.print(mName + " provider");
979 if (mProvider.isMock()) {
980 pw.print(" [mock]");
981 }
982 pw.println(":");
983
984 pw.increaseIndent();
985
Soonil Nagarkar77a92272020-02-11 14:04:39 -0800986 // for now we only dump for the parent user
987 int userId = mUserInfoHelper.getCurrentUserIds()[0];
988 pw.println("last location=" + mLastLocation.get(userId));
989 pw.println("last coarse location=" + mLastCoarseLocation.get(userId));
990 pw.println("enabled=" + isEnabled(userId));
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800991 }
992
993 mProvider.dump(fd, pw, args);
994
995 pw.decreaseIndent();
996 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800997 }
998
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800999 class PassiveLocationProviderManager extends LocationProviderManager {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001000
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001001 private PassiveLocationProviderManager() {
1002 super(PASSIVE_PROVIDER);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001003 }
1004
1005 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001006 public void setRealProvider(AbstractLocationProvider provider) {
1007 Preconditions.checkArgument(provider instanceof PassiveProvider);
1008 super.setRealProvider(provider);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001009 }
1010
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001011 @Override
1012 public void setMockProvider(@Nullable MockProvider provider) {
1013 if (provider != null) {
1014 throw new IllegalArgumentException("Cannot mock the passive provider");
1015 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001016 }
1017
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001018 public void updateLocation(Location location) {
1019 synchronized (mLock) {
1020 PassiveProvider passiveProvider = (PassiveProvider) mProvider.getProvider();
1021 Preconditions.checkState(passiveProvider != null);
1022
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001023 long identity = Binder.clearCallingIdentity();
1024 try {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001025 passiveProvider.updateLocation(location);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001026 } finally {
1027 Binder.restoreCallingIdentity(identity);
Soonil Nagarkar68257742019-01-09 19:42:34 +00001028 }
1029 }
1030 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001031 }
1032
Victoria Lease38389b62012-09-30 11:44:22 -07001033 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001034 * A wrapper class holding either an ILocationListener or a PendingIntent to receive
1035 * location updates.
1036 */
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001037 private final class Receiver extends LocationManagerServiceUtils.LinkedListenerBase implements
1038 PendingIntent.OnFinished {
Yu-Han Yang24189822018-07-11 15:24:11 -07001039 private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001040 private final int mAllowedResolutionLevel; // resolution level allowed to receiver
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001041
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001042 private final ILocationListener mListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001043 final PendingIntent mPendingIntent;
David Christie82edc9b2013-07-19 11:31:42 -07001044 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001045 private final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
1046 private final Object mKey;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001047
gomo48f1a642017-11-10 20:35:46 -08001048 final HashMap<String, UpdateRecord> mUpdateRecords = new HashMap<>();
Nick Pellyf1be6862012-05-15 10:53:42 -07001049
David Christie0b837452013-07-29 16:02:13 -07001050 // True if app ops has started monitoring this receiver for locations.
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001051 private boolean mOpMonitoring;
David Christie0b837452013-07-29 16:02:13 -07001052 // True if app ops has started monitoring this receiver for high power (gps) locations.
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001053 private boolean mOpHighPowerMonitoring;
1054 private int mPendingBroadcasts;
Victoria Lease0aa28602013-05-29 15:28:26 -07001055 PowerManager.WakeLock mWakeLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001056
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001057 private Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001058 String packageName, @Nullable String featureId, WorkSource workSource,
1059 boolean hideFromAppOps, @NonNull String listenerIdentifier) {
1060 super(new CallerIdentity(uid, pid, packageName, featureId, listenerIdentifier),
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001061 "LocationListener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001062 mListener = listener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 mPendingIntent = intent;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001064 if (listener != null) {
1065 mKey = listener.asBinder();
1066 } else {
1067 mKey = intent;
1068 }
Victoria Lease37425c32012-10-16 16:08:48 -07001069 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
Narayan Kamath32684dd2018-01-08 17:32:51 +00001070 if (workSource != null && workSource.isEmpty()) {
David Christie82edc9b2013-07-19 11:31:42 -07001071 workSource = null;
1072 }
1073 mWorkSource = workSource;
David Christie40e57822013-07-30 11:36:48 -07001074 mHideFromAppOps = hideFromAppOps;
Victoria Lease0aa28602013-05-29 15:28:26 -07001075
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001076 updateMonitoring(true);
1077
Victoria Lease0aa28602013-05-29 15:28:26 -07001078 // construct/configure wakelock
1079 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
David Christie82edc9b2013-07-19 11:31:42 -07001080 if (workSource == null) {
Anil Admal08b96122019-01-30 16:55:05 -08001081 workSource = new WorkSource(mCallerIdentity.mUid, mCallerIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001082 }
1083 mWakeLock.setWorkSource(workSource);
Yu-Han Yang24189822018-07-11 15:24:11 -07001084
1085 // For a non-reference counted wakelock, each acquire will reset the timeout, and we
1086 // only need to release it once.
1087 mWakeLock.setReferenceCounted(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 }
1089
1090 @Override
1091 public boolean equals(Object otherObj) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001092 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 }
1094
1095 @Override
1096 public int hashCode() {
1097 return mKey.hashCode();
1098 }
Mike Lockwood3681f262009-05-12 10:52:03 -04001099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 @Override
1101 public String toString() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001102 StringBuilder s = new StringBuilder();
1103 s.append("Reciever[");
1104 s.append(Integer.toHexString(System.identityHashCode(this)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 if (mListener != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001106 s.append(" listener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001108 s.append(" intent");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001109 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001110 for (String p : mUpdateRecords.keySet()) {
1111 s.append(" ").append(mUpdateRecords.get(p).toString());
1112 }
Wei Wangdd070f22018-06-21 11:29:40 -07001113 s.append(" monitoring location: ").append(mOpMonitoring);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001114 s.append("]");
1115 return s.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001116 }
1117
David Christie15b31912013-08-13 15:54:32 -07001118 /**
1119 * Update AppOp monitoring for this receiver.
1120 *
1121 * @param allow If true receiver is currently active, if false it's been removed.
1122 */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001123 public void updateMonitoring(boolean allow) {
David Christie40e57822013-07-30 11:36:48 -07001124 if (mHideFromAppOps) {
1125 return;
1126 }
1127
David Christie15b31912013-08-13 15:54:32 -07001128 boolean requestingLocation = false;
1129 boolean requestingHighPowerLocation = false;
1130 if (allow) {
1131 // See if receiver has any enabled update records. Also note if any update records
1132 // are high power (has a high power provider with an interval under a threshold).
1133 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001134 LocationProviderManager manager = getLocationProviderManager(
Soonil Nagarkar3f128402019-12-12 08:31:27 -08001135 updateRecord.mProvider);
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001136 if (manager == null) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001137 continue;
1138 }
Soonil Nagarkar77a92272020-02-11 14:04:39 -08001139 if (!manager.isEnabled(UserHandle.getUserId(mCallerIdentity.mUid))
1140 && !isSettingsExempt(updateRecord)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001141 continue;
1142 }
1143
1144 requestingLocation = true;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001145 ProviderProperties properties = manager.getProperties();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001146 if (properties != null
1147 && properties.mPowerRequirement == Criteria.POWER_HIGH
1148 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
1149 requestingHighPowerLocation = true;
1150 break;
David Christie15b31912013-08-13 15:54:32 -07001151 }
1152 }
1153 }
1154
David Christie0b837452013-07-29 16:02:13 -07001155 // First update monitoring of any location request (including high power).
David Christie15b31912013-08-13 15:54:32 -07001156 mOpMonitoring = updateMonitoring(
1157 requestingLocation,
1158 mOpMonitoring,
David Christie0b837452013-07-29 16:02:13 -07001159 AppOpsManager.OP_MONITOR_LOCATION);
1160
1161 // Now update monitoring of high power requests only.
David Christiec750c1f2013-08-08 12:56:57 -07001162 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
David Christie15b31912013-08-13 15:54:32 -07001163 mOpHighPowerMonitoring = updateMonitoring(
1164 requestingHighPowerLocation,
1165 mOpHighPowerMonitoring,
David Christie0b837452013-07-29 16:02:13 -07001166 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
David Christiec750c1f2013-08-08 12:56:57 -07001167 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
David Christie15b31912013-08-13 15:54:32 -07001168 // Send an intent to notify that a high power request has been added/removed.
David Christiec750c1f2013-08-08 12:56:57 -07001169 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
1170 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
1171 }
David Christie0b837452013-07-29 16:02:13 -07001172 }
1173
1174 /**
1175 * Update AppOps monitoring for a single location request and op type.
1176 *
gomo48f1a642017-11-10 20:35:46 -08001177 * @param allowMonitoring True if monitoring is allowed for this request/op.
David Christie0b837452013-07-29 16:02:13 -07001178 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
gomo48f1a642017-11-10 20:35:46 -08001179 * @param op AppOps code for the op to update.
David Christie0b837452013-07-29 16:02:13 -07001180 * @return True if monitoring is on for this request/op after updating.
1181 */
1182 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
1183 int op) {
1184 if (!currentlyMonitoring) {
1185 if (allowMonitoring) {
Anil Admal08b96122019-01-30 16:55:05 -08001186 return mAppOps.startOpNoThrow(op, mCallerIdentity.mUid,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001187 mCallerIdentity.mPackageName, false, mCallerIdentity.mFeatureId, null)
1188 == AppOpsManager.MODE_ALLOWED;
David Christie0b837452013-07-29 16:02:13 -07001189 }
1190 } else {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001191 if (!allowMonitoring
Wei Wang16276a42019-02-04 18:23:31 -08001192 || mAppOps.checkOpNoThrow(op, mCallerIdentity.mUid,
Anil Admal08b96122019-01-30 16:55:05 -08001193 mCallerIdentity.mPackageName) != AppOpsManager.MODE_ALLOWED) {
1194 mAppOps.finishOp(op, mCallerIdentity.mUid, mCallerIdentity.mPackageName);
David Christie0b837452013-07-29 16:02:13 -07001195 return false;
1196 }
1197 }
1198
1199 return currentlyMonitoring;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001200 }
1201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001202 public boolean isListener() {
1203 return mListener != null;
1204 }
1205
1206 public boolean isPendingIntent() {
1207 return mPendingIntent != null;
1208 }
1209
1210 public ILocationListener getListener() {
1211 if (mListener != null) {
1212 return mListener;
1213 }
1214 throw new IllegalStateException("Request for non-existent listener");
1215 }
1216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001217 public boolean callLocationChangedLocked(Location location) {
1218 if (mListener != null) {
1219 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001220 mListener.onLocationChanged(new Location(location));
1221 // call this after broadcasting so we do not increment
1222 // if we throw an exception.
1223 incrementPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001224 } catch (RemoteException e) {
1225 return false;
1226 }
1227 } else {
1228 Intent locationChanged = new Intent();
gomo48f1a642017-11-10 20:35:46 -08001229 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED,
1230 new Location(location));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001232 mPendingIntent.send(mContext, 0, locationChanged, this, mHandler,
1233 getResolutionPermission(mAllowedResolutionLevel),
1234 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
1235 // call this after broadcasting so we do not increment
1236 // if we throw an exception.
1237 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001238 } catch (PendingIntent.CanceledException e) {
1239 return false;
1240 }
1241 }
1242 return true;
1243 }
1244
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001245 private boolean callProviderEnabledLocked(String provider, boolean enabled) {
David Christie15b31912013-08-13 15:54:32 -07001246 // First update AppOp monitoring.
1247 // An app may get/lose location access as providers are enabled/disabled.
1248 updateMonitoring(true);
1249
Mike Lockwood48f17512009-04-23 09:12:08 -07001250 if (mListener != null) {
1251 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001252 if (enabled) {
1253 mListener.onProviderEnabled(provider);
1254 } else {
1255 mListener.onProviderDisabled(provider);
Mike Lockwood48f17512009-04-23 09:12:08 -07001256 }
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001257 // call this after broadcasting so we do not increment
1258 // if we throw an exception.
1259 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001260 } catch (RemoteException e) {
1261 return false;
1262 }
1263 } else {
1264 Intent providerIntent = new Intent();
1265 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1266 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001267 mPendingIntent.send(mContext, 0, providerIntent, this, mHandler,
1268 getResolutionPermission(mAllowedResolutionLevel),
1269 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
1270 // call this after broadcasting so we do not increment
1271 // if we throw an exception.
1272 incrementPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001273 } catch (PendingIntent.CanceledException e) {
1274 return false;
1275 }
1276 }
1277 return true;
1278 }
1279
Soonil Nagarkar39d614a2019-10-31 12:10:31 -07001280 public void callRemovedLocked() {
1281 if (mListener != null) {
1282 try {
1283 mListener.onRemoved();
1284 } catch (RemoteException e) {
1285 // doesn't matter
1286 }
1287 }
1288 }
1289
Nick Pellyf1be6862012-05-15 10:53:42 -07001290 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001291 public void binderDied() {
Anil Admal98d49b72019-02-06 15:26:33 -08001292 if (D) Log.d(TAG, "Remote " + mListenerName + " died.");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001293
Soonil Nagarkar68257742019-01-09 19:42:34 +00001294 synchronized (mLock) {
1295 removeUpdatesLocked(this);
Soonil Nagarkar68257742019-01-09 19:42:34 +00001296 clearPendingBroadcastsLocked();
1297 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001298 }
1299
Nick Pellye0fd6932012-07-11 10:26:13 -07001300 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001301 public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1302 int resultCode, String resultData, Bundle resultExtras) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001303 synchronized (mLock) {
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001304 decrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001305 }
1306 }
1307
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001308 // this must be called while synchronized by caller in a synchronized block
1309 // containing the sending of the broadcaset
1310 private void incrementPendingBroadcastsLocked() {
Yu-Han Yang24189822018-07-11 15:24:11 -07001311 mPendingBroadcasts++;
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001312 // so wakelock calls will succeed
1313 long identity = Binder.clearCallingIdentity();
1314 try {
1315 mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
1316 } finally {
1317 Binder.restoreCallingIdentity(identity);
1318 }
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001319 }
1320
1321 private void decrementPendingBroadcastsLocked() {
1322 if (--mPendingBroadcasts == 0) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001323 // so wakelock calls will succeed
1324 long identity = Binder.clearCallingIdentity();
1325 try {
1326 if (mWakeLock.isHeld()) {
1327 mWakeLock.release();
1328 }
1329 } finally {
1330 Binder.restoreCallingIdentity(identity);
Victoria Lease0aa28602013-05-29 15:28:26 -07001331 }
1332 }
1333 }
1334
1335 public void clearPendingBroadcastsLocked() {
1336 if (mPendingBroadcasts > 0) {
1337 mPendingBroadcasts = 0;
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001338 // so wakelock calls will succeed
1339 long identity = Binder.clearCallingIdentity();
1340 try {
1341 if (mWakeLock.isHeld()) {
1342 mWakeLock.release();
1343 }
1344 } finally {
1345 Binder.restoreCallingIdentity(identity);
Victoria Lease0aa28602013-05-29 15:28:26 -07001346 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001347 }
1348 }
1349 }
1350
Nick Pellye0fd6932012-07-11 10:26:13 -07001351 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001352 public void locationCallbackFinished(ILocationListener listener) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001353 //Do not use getReceiverLocked here as that will add the ILocationListener to
Joshua Bartel080b61b2009-10-05 12:44:46 -04001354 //the receiver list if it is not found. If it is not found then the
1355 //LocationListener was removed when it had a pending broadcast and should
1356 //not be added back.
Soonil Nagarkar68257742019-01-09 19:42:34 +00001357 synchronized (mLock) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001358 Receiver receiver = mReceivers.get(listener.asBinder());
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001359 if (receiver != null) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001360 receiver.decrementPendingBroadcastsLocked();
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001361 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00001362 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363 }
1364
Lifu Tang82f893d2016-01-21 18:15:33 -08001365 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001366 public int getGnssYearOfHardware() {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001367 return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001368 }
1369
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001370 @Override
Wyatt Riley49097c02018-03-15 09:14:43 -07001371 @Nullable
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001372 public String getGnssHardwareModelName() {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001373 return mGnssManagerService == null ? "" : mGnssManagerService.getGnssHardwareModelName();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001374 }
1375
Wyatt Rileycf879db2017-01-12 13:57:38 -08001376 @Override
1377 public int getGnssBatchSize(String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001378 return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssBatchSize(packageName);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001379 }
1380
Wyatt Rileycf879db2017-01-12 13:57:38 -08001381 @Override
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001382 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001383 String featureId, String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00001384 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001385
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001386 return mGnssManagerService != null && mGnssManagerService.addGnssBatchingCallback(
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001387 callback, packageName, featureId, listenerIdentifier);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001388 }
1389
Wyatt Rileycf879db2017-01-12 13:57:38 -08001390 @Override
1391 public void removeGnssBatchingCallback() {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001392 if (mGnssManagerService != null) mGnssManagerService.removeGnssBatchingCallback();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001393 }
1394
Wyatt Rileycf879db2017-01-12 13:57:38 -08001395 @Override
1396 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001397 return mGnssManagerService != null && mGnssManagerService.startGnssBatch(periodNanos,
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001398 wakeOnFifoFull, packageName);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001399 }
1400
Wyatt Rileycf879db2017-01-12 13:57:38 -08001401 @Override
1402 public void flushGnssBatch(String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001403 if (mGnssManagerService != null) mGnssManagerService.flushGnssBatch(packageName);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001404 }
1405
Wyatt Rileycf879db2017-01-12 13:57:38 -08001406 @Override
1407 public boolean stopGnssBatch() {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001408 return mGnssManagerService != null && mGnssManagerService.stopGnssBatch();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001409 }
1410
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001411 @Nullable
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001412 private LocationProviderManager getLocationProviderManager(String providerName) {
1413 for (LocationProviderManager manager : mProviderManagers) {
1414 if (providerName.equals(manager.getName())) {
1415 return manager;
Soonil Nagarkar68257742019-01-09 19:42:34 +00001416 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001417 }
1418
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001419 return null;
Maggie2a9409e2018-03-21 11:47:28 -07001420 }
1421
Victoria Lease37425c32012-10-16 16:08:48 -07001422 private String getResolutionPermission(int resolutionLevel) {
1423 switch (resolutionLevel) {
1424 case RESOLUTION_LEVEL_FINE:
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001425 return ACCESS_FINE_LOCATION;
Victoria Lease37425c32012-10-16 16:08:48 -07001426 case RESOLUTION_LEVEL_COARSE:
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001427 return ACCESS_COARSE_LOCATION;
Victoria Lease37425c32012-10-16 16:08:48 -07001428 default:
1429 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001430 }
Victoria Leaseda479c52012-10-15 15:24:16 -07001431 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001432
Victoria Lease37425c32012-10-16 16:08:48 -07001433 private int getAllowedResolutionLevel(int pid, int uid) {
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001434 if (mContext.checkPermission(ACCESS_FINE_LOCATION, pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001435 return RESOLUTION_LEVEL_FINE;
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001436 } else if (mContext.checkPermission(ACCESS_COARSE_LOCATION, pid, uid)
1437 == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001438 return RESOLUTION_LEVEL_COARSE;
1439 } else {
1440 return RESOLUTION_LEVEL_NONE;
Victoria Leaseda479c52012-10-15 15:24:16 -07001441 }
Victoria Lease4fab68b2012-09-13 13:20:59 -07001442 }
1443
Victoria Lease37425c32012-10-16 16:08:48 -07001444 private int getCallerAllowedResolutionLevel() {
1445 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
1446 }
1447
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001448 private boolean checkCallingOrSelfLocationPermission() {
1449 return mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED
1450 || mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
1451 == PERMISSION_GRANTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001452 }
1453
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001454 private void enforceCallingOrSelfLocationPermission() {
1455 if (checkCallingOrSelfLocationPermission()) {
1456 return;
Victoria Lease8dbb6342012-09-21 16:55:53 -07001457 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001458
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001459 throw new SecurityException("uid " + Binder.getCallingUid() + " does not have "
Wei Wang9e33ab42020-02-13 17:12:13 -08001460 + ACCESS_COARSE_LOCATION + " or " + ACCESS_FINE_LOCATION + ".");
Victoria Leaseda479c52012-10-15 15:24:16 -07001461 }
1462
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001463 private void enforceCallingOrSelfPackageName(String packageName) {
1464 int uid = Binder.getCallingUid();
1465 if (ArrayUtils.contains(mPackageManager.getPackagesForUid(uid), packageName)) {
1466 return;
Victoria Leaseda479c52012-10-15 15:24:16 -07001467 }
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001468
1469 throw new SecurityException("invalid package \"" + packageName + "\" for uid " + uid);
Victoria Lease8dbb6342012-09-21 16:55:53 -07001470 }
1471
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001472 public static int resolutionLevelToOp(int allowedResolutionLevel) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001473 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
1474 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001475 return AppOpsManager.OP_COARSE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001476 } else {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001477 return AppOpsManager.OP_FINE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001478 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001479 }
1480 return -1;
1481 }
1482
Wei Wangb86334f2018-07-03 16:33:24 -07001483 private static String resolutionLevelToOpStr(int allowedResolutionLevel) {
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001484 switch (allowedResolutionLevel) {
Wei Wangb86334f2018-07-03 16:33:24 -07001485 case RESOLUTION_LEVEL_COARSE:
1486 return AppOpsManager.OPSTR_COARSE_LOCATION;
1487 case RESOLUTION_LEVEL_FINE:
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001488 // fall through
Wei Wangb86334f2018-07-03 16:33:24 -07001489 case RESOLUTION_LEVEL_NONE:
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001490 // fall through
Wei Wangb86334f2018-07-03 16:33:24 -07001491 default:
1492 // Use the most restrictive ops if not sure.
1493 return AppOpsManager.OPSTR_FINE_LOCATION;
1494 }
1495 }
1496
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001497 private boolean reportLocationAccessNoThrow(int pid, int uid, String packageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001498 @Nullable String featureId, int allowedResolutionLevel, @Nullable String message) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001499 int op = resolutionLevelToOp(allowedResolutionLevel);
1500 if (op >= 0) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001501 if (mAppOps.noteOpNoThrow(op, uid, packageName, featureId, message)
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001502 != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001503 return false;
1504 }
1505 }
David Christieb870dbf2015-06-22 12:42:53 -07001506
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001507 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001508 }
1509
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001510 private boolean checkLocationAccess(int pid, int uid, String packageName,
1511 int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001512 int op = resolutionLevelToOp(allowedResolutionLevel);
1513 if (op >= 0) {
Wei Wang16276a42019-02-04 18:23:31 -08001514 if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001515 return false;
1516 }
1517 }
David Christieb870dbf2015-06-22 12:42:53 -07001518
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001519 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001520 }
1521
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001522 /**
Maggie91e630c2018-01-24 17:31:46 -08001523 * Returns all providers by name, including passive and the ones that are not permitted to
1524 * be accessed by the calling activity or are currently disabled, but excluding fused.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001525 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001526 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001527 public List<String> getAllProviders() {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001528 ArrayList<String> providers = new ArrayList<>(mProviderManagers.size());
1529 for (LocationProviderManager manager : mProviderManagers) {
1530 if (FUSED_PROVIDER.equals(manager.getName())) {
1531 continue;
Maggie91e630c2018-01-24 17:31:46 -08001532 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001533 providers.add(manager.getName());
Maggie91e630c2018-01-24 17:31:46 -08001534 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001535 return providers;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001536 }
1537
Mike Lockwood03ca2162010-04-01 08:10:09 -07001538 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001539 * Return all providers by name, that match criteria and are optionally
1540 * enabled.
1541 * Can return passive provider, but never returns fused provider.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001542 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001543 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001544 public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001545 if (!checkCallingOrSelfLocationPermission()) {
1546 return Collections.emptyList();
1547 }
1548
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001549 synchronized (mLock) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001550 ArrayList<String> providers = new ArrayList<>(mProviderManagers.size());
1551 for (LocationProviderManager manager : mProviderManagers) {
1552 String name = manager.getName();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001553 if (FUSED_PROVIDER.equals(name)) {
1554 continue;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001555 }
Soonil Nagarkar77a92272020-02-11 14:04:39 -08001556 if (enabledOnly && !manager.isEnabled(UserHandle.getCallingUserId())) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001557 continue;
1558 }
1559 if (criteria != null
1560 && !android.location.LocationProvider.propertiesMeetCriteria(
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001561 name, manager.getProperties(), criteria)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001562 continue;
1563 }
1564 providers.add(name);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001565 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001566 return providers;
Soonil Nagarkar68257742019-01-09 19:42:34 +00001567 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001568 }
1569
1570 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001571 * Return the name of the best provider given a Criteria object.
1572 * This method has been deprecated from the public API,
Victoria Lease8dbb6342012-09-21 16:55:53 -07001573 * and the whole LocationProvider (including #meetsCriteria)
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001574 * has been deprecated as well. So this method now uses
1575 * some simplified logic.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001576 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001577 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001578 public String getBestProvider(Criteria criteria, boolean enabledOnly) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001579 List<String> providers = getProviders(criteria, enabledOnly);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001580 if (providers.isEmpty()) {
1581 providers = getProviders(null, enabledOnly);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08001582 }
1583
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001584 if (!providers.isEmpty()) {
1585 if (providers.contains(GPS_PROVIDER)) {
1586 return GPS_PROVIDER;
1587 } else if (providers.contains(NETWORK_PROVIDER)) {
1588 return NETWORK_PROVIDER;
1589 } else {
1590 return providers.get(0);
1591 }
1592 }
1593
Mike Lockwood03ca2162010-04-01 08:10:09 -07001594 return null;
1595 }
1596
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001597 @GuardedBy("mLock")
Soonil Nagarkar77a92272020-02-11 14:04:39 -08001598 private void updateProviderEnabledLocked(LocationProviderManager manager, boolean enabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 ArrayList<Receiver> deadReceivers = null;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001600 ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 if (records != null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001602 for (UpdateRecord record : records) {
Soonil Nagarkar77a92272020-02-11 14:04:39 -08001603 if (!mUserInfoHelper.isCurrentUserId(
Anil Admal08b96122019-01-30 16:55:05 -08001604 UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001605 continue;
1606 }
1607
Kweku Adams5e0052b2019-02-22 15:17:52 -08001608 // requests that ignore location settings will never provide notifications
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001609 if (isSettingsExempt(record)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001610 continue;
1611 }
1612
1613 // Sends a notification message to the receiver
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08001614 if (!record.mReceiver.callProviderEnabledLocked(manager.getName(), enabled)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001615 if (deadReceivers == null) {
1616 deadReceivers = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001617 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001618 deadReceivers.add(record.mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001620 }
1621 }
1622
1623 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001624 for (int i = deadReceivers.size() - 1; i >= 0; i--) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00001625 removeUpdatesLocked(deadReceivers.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001626 }
1627 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001628
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001629 applyRequirementsLocked(manager);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001630 }
1631
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001632 @GuardedBy("mLock")
1633 private void applyRequirementsLocked(String providerName) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001634 LocationProviderManager manager = getLocationProviderManager(providerName);
1635 if (manager != null) {
1636 applyRequirementsLocked(manager);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001637 }
1638 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001639
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001640 @GuardedBy("mLock")
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001641 private void applyRequirementsLocked(LocationProviderManager manager) {
1642 ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName());
1643 ProviderRequest.Builder providerRequest = new ProviderRequest.Builder();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001644
Soonil Nagarkar04cff6c2019-03-19 11:29:52 -07001645 // if provider is not active, it should not respond to requests
1646
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001647 if (mProviderManagers.contains(manager) && records != null && !records.isEmpty()) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001648 long backgroundThrottleInterval = mSettingsHelper.getBackgroundThrottleIntervalMs();
Kweku Adams5e0052b2019-02-22 15:17:52 -08001649
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001650 ArrayList<LocationRequest> requests = new ArrayList<>(records.size());
1651
Kweku Adams5e0052b2019-02-22 15:17:52 -08001652 final boolean isForegroundOnlyMode =
Kweku Adams4fb074e2019-02-01 16:03:27 -08001653 mBatterySaverMode == PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
1654 final boolean shouldThrottleRequests =
1655 mBatterySaverMode
1656 == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF
1657 && !mPowerManager.isInteractive();
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001658 // initialize the low power mode to true and set to false if any of the records requires
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001659 providerRequest.setLowPowerMode(true);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001660 for (UpdateRecord record : records) {
Soonil Nagarkar77a92272020-02-11 14:04:39 -08001661 int userId = UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid);
1662 if (!mUserInfoHelper.isCurrentUserId(userId)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001663 continue;
1664 }
1665 if (!checkLocationAccess(
Anil Admal08b96122019-01-30 16:55:05 -08001666 record.mReceiver.mCallerIdentity.mPid,
1667 record.mReceiver.mCallerIdentity.mUid,
1668 record.mReceiver.mCallerIdentity.mPackageName,
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001669 record.mReceiver.mAllowedResolutionLevel)) {
1670 continue;
1671 }
Kweku Adams4fb074e2019-02-01 16:03:27 -08001672 final boolean isBatterySaverDisablingLocation = shouldThrottleRequests
1673 || (isForegroundOnlyMode && !record.mIsForegroundUid);
Soonil Nagarkar77a92272020-02-11 14:04:39 -08001674 if (!manager.isEnabled(userId) || isBatterySaverDisablingLocation) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001675 if (isSettingsExempt(record)) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001676 providerRequest.setLocationSettingsIgnored(true);
1677 providerRequest.setLowPowerMode(false);
Soonil Nagarkar35c3b912019-01-31 10:31:24 -08001678 } else {
1679 continue;
1680 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001681 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001682
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001683 LocationRequest locationRequest = record.mRealRequest;
1684 long interval = locationRequest.getInterval();
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001685
Soonil Nagarkar509580f2019-02-06 15:57:26 -08001686
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001687 // if we're forcing location, don't apply any throttling
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001688 if (!providerRequest.isLocationSettingsIgnored() && !isThrottlingExempt(
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001689 record.mReceiver.mCallerIdentity)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001690 if (!record.mIsForegroundUid) {
1691 interval = Math.max(interval, backgroundThrottleInterval);
Victoria Leaseb711d572012-10-02 13:14:11 -07001692 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001693 if (interval != locationRequest.getInterval()) {
1694 locationRequest = new LocationRequest(locationRequest);
1695 locationRequest.setInterval(interval);
1696 }
1697 }
1698
1699 record.mRequest = locationRequest;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001700 requests.add(locationRequest);
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001701 if (!locationRequest.isLowPowerMode()) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001702 providerRequest.setLowPowerMode(false);
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001703 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001704 if (interval < providerRequest.getInterval()) {
1705 providerRequest.setInterval(interval);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001706 }
1707 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001708
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001709 providerRequest.setLocationRequests(requests);
1710
1711 if (providerRequest.getInterval() < Long.MAX_VALUE) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001712 // calculate who to blame for power
1713 // This is somewhat arbitrary. We pick a threshold interval
1714 // that is slightly higher that the minimum interval, and
1715 // spread the blame across all applications with a request
1716 // under that threshold.
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001717 // TODO: overflow
1718 long thresholdInterval = (providerRequest.getInterval() + 1000) * 3 / 2;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001719 for (UpdateRecord record : records) {
Soonil Nagarkar77a92272020-02-11 14:04:39 -08001720 if (mUserInfoHelper.isCurrentUserId(
Anil Admal08b96122019-01-30 16:55:05 -08001721 UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001722 LocationRequest locationRequest = record.mRequest;
Svet Ganove998c732016-06-10 00:12:38 -07001723
1724 // Don't assign battery blame for update records whose
1725 // client has no permission to receive location data.
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001726 if (!providerRequest.getLocationRequests().contains(locationRequest)) {
Svet Ganove998c732016-06-10 00:12:38 -07001727 continue;
1728 }
1729
Victoria Leaseb711d572012-10-02 13:14:11 -07001730 if (locationRequest.getInterval() <= thresholdInterval) {
David Christiee55c9682013-08-22 10:10:34 -07001731 if (record.mReceiver.mWorkSource != null
Narayan Kamath32684dd2018-01-08 17:32:51 +00001732 && isValidWorkSource(record.mReceiver.mWorkSource)) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001733 providerRequest.getWorkSource().add(record.mReceiver.mWorkSource);
David Christie82edc9b2013-07-19 11:31:42 -07001734 } else {
Narayan Kamath32684dd2018-01-08 17:32:51 +00001735 // Assign blame to caller if there's no WorkSource associated with
1736 // the request or if it's invalid.
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001737 providerRequest.getWorkSource().add(
Anil Admal08b96122019-01-30 16:55:05 -08001738 record.mReceiver.mCallerIdentity.mUid,
1739 record.mReceiver.mCallerIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001740 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001741 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001742 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001743 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001744 }
1745 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001746
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001747 manager.setRequest(providerRequest.build());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001748 }
1749
Narayan Kamath32684dd2018-01-08 17:32:51 +00001750 /**
1751 * Whether a given {@code WorkSource} associated with a Location request is valid.
1752 */
1753 private static boolean isValidWorkSource(WorkSource workSource) {
1754 if (workSource.size() > 0) {
1755 // If the WorkSource has one or more non-chained UIDs, make sure they're accompanied
1756 // by tags.
Suprabh Shuklaf7cffa72019-11-08 17:03:03 -08001757 return workSource.getPackageName(0) != null;
Narayan Kamath32684dd2018-01-08 17:32:51 +00001758 } else {
1759 // For now, make sure callers have supplied an attribution tag for use with
1760 // AppOpsManager. This might be relaxed in the future.
Suprabh Shuklaf7cffa72019-11-08 17:03:03 -08001761 final List<WorkChain> workChains = workSource.getWorkChains();
Narayan Kamath32684dd2018-01-08 17:32:51 +00001762 return workChains != null && !workChains.isEmpty() &&
1763 workChains.get(0).getAttributionTag() != null;
1764 }
1765 }
1766
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001767 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001768 public String[] getBackgroundThrottlingWhitelist() {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001769 return mSettingsHelper.getBackgroundThrottlePackageWhitelist().toArray(new String[0]);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001770 }
1771
Soonil Nagarkar5140e4f2019-02-14 17:21:33 -08001772 @Override
1773 public String[] getIgnoreSettingsWhitelist() {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001774 return mSettingsHelper.getIgnoreSettingsPackageWhitelist().toArray(new String[0]);
Soonil Nagarkar5140e4f2019-02-14 17:21:33 -08001775 }
1776
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001777 private boolean isThrottlingExempt(CallerIdentity callerIdentity) {
Anil Admal08b96122019-01-30 16:55:05 -08001778 if (callerIdentity.mUid == Process.SYSTEM_UID) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001779 return true;
1780 }
1781
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001782 if (mSettingsHelper.getBackgroundThrottlePackageWhitelist().contains(
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07001783 callerIdentity.mPackageName)) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001784 return true;
1785 }
1786
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001787 return mLocalService.isProviderPackage(callerIdentity.mPackageName);
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001788
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001789 }
1790
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001791 private boolean isSettingsExempt(UpdateRecord record) {
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001792 if (!record.mRealRequest.isLocationSettingsIgnored()) {
1793 return false;
1794 }
1795
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001796 if (mSettingsHelper.getIgnoreSettingsPackageWhitelist().contains(
Anil Admal08b96122019-01-30 16:55:05 -08001797 record.mReceiver.mCallerIdentity.mPackageName)) {
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001798 return true;
1799 }
1800
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001801 return mLocalService.isProviderPackage(record.mReceiver.mCallerIdentity.mPackageName);
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001802
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001803 }
1804
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805 private class UpdateRecord {
1806 final String mProvider;
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001807 private final LocationRequest mRealRequest; // original request from client
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001808 LocationRequest mRequest; // possibly throttled version of the request
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001809 private final Receiver mReceiver;
1810 private boolean mIsForegroundUid;
1811 private Location mLastFixBroadcast;
Soonil Nagarkarae6ce772019-05-01 13:16:17 -07001812 private Throwable mStackTrace; // for debugging only
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08001813 private long mExpirationRealtimeMs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814
1815 /**
1816 * Note: must be constructed with lock held.
1817 */
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001818 private UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08001819 mExpirationRealtimeMs = request.getExpirationRealtimeMs(SystemClock.elapsedRealtime());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 mProvider = provider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001821 mRealRequest = request;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001822 mRequest = request;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001823 mReceiver = receiver;
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001824 mIsForegroundUid = mAppForegroundHelper.isAppForeground(mReceiver.mCallerIdentity.mUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001825
Soonil Nagarkarae6ce772019-05-01 13:16:17 -07001826 if (D && receiver.mCallerIdentity.mPid == Process.myPid()) {
1827 mStackTrace = new Throwable();
1828 }
1829
Soonil Nagarkar77a92272020-02-11 14:04:39 -08001830 ArrayList<UpdateRecord> records = mRecordsByProvider.computeIfAbsent(provider,
1831 k -> new ArrayList<>());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832 if (!records.contains(this)) {
1833 records.add(this);
1834 }
David Christie2ff96af2014-01-30 16:09:37 -08001835
1836 // Update statistics for historical location requests by package/provider
1837 mRequestStatistics.startRequesting(
Wei Wang9e33ab42020-02-13 17:12:13 -08001838 mReceiver.mCallerIdentity.mPackageName, mReceiver.mCallerIdentity.mFeatureId,
1839 provider, request.getInterval(), mIsForegroundUid);
Wyatt Rileyf7075e02018-04-12 17:54:26 -07001840 }
1841
1842 /**
1843 * Method to be called when record changes foreground/background
1844 */
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001845 private void updateForeground(boolean isForeground) {
Wyatt Rileyf7075e02018-04-12 17:54:26 -07001846 mIsForegroundUid = isForeground;
1847 mRequestStatistics.updateForeground(
Wei Wang9e33ab42020-02-13 17:12:13 -08001848 mReceiver.mCallerIdentity.mPackageName, mReceiver.mCallerIdentity.mFeatureId,
1849 mProvider, isForeground);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001850 }
1851
1852 /**
David Christie2ff96af2014-01-30 16:09:37 -08001853 * Method to be called when a record will no longer be used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001854 */
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001855 private void disposeLocked(boolean removeReceiver) {
Hongyi Zhang700137e2019-05-23 21:19:36 -07001856 String packageName = mReceiver.mCallerIdentity.mPackageName;
Wei Wang9e33ab42020-02-13 17:12:13 -08001857 mRequestStatistics.stopRequesting(packageName, mReceiver.mCallerIdentity.mFeatureId,
1858 mProvider);
Hongyi Zhang700137e2019-05-23 21:19:36 -07001859
1860 mLocationUsageLogger.logLocationApiUsage(
1861 LocationStatsEnums.USAGE_ENDED,
1862 LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
1863 packageName,
1864 mRealRequest,
1865 mReceiver.isListener(),
1866 mReceiver.isPendingIntent(),
Hongyi Zhang0e9ea752019-06-09 22:49:25 -07001867 /* geofence= */ null,
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08001868 mAppForegroundHelper.getImportance(mReceiver.mCallerIdentity.mUid));
David Christie2ff96af2014-01-30 16:09:37 -08001869
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001870 // remove from mRecordsByProvider
1871 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
1872 if (globalRecords != null) {
1873 globalRecords.remove(this);
1874 }
1875
1876 if (!removeReceiver) return; // the caller will handle the rest
1877
1878 // remove from Receiver#mUpdateRecords
1879 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001880 receiverRecords.remove(this.mProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001881
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001882 // and also remove the Receiver if it has no more update records
1883 if (receiverRecords.size() == 0) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00001884 removeUpdatesLocked(mReceiver);
Mike Lockwood3a76fd62009-09-01 07:26:56 -04001885 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001886 }
1887
1888 @Override
1889 public String toString() {
Soonil Nagarkarae6ce772019-05-01 13:16:17 -07001890 StringBuilder b = new StringBuilder("UpdateRecord[");
1891 b.append(mProvider).append(" ");
1892 b.append(mReceiver.mCallerIdentity.mPackageName);
Wei Wang9e33ab42020-02-13 17:12:13 -08001893 String featureId = mReceiver.mCallerIdentity.mFeatureId;
1894 if (featureId != null) {
1895 b.append(" ").append(featureId).append(" ");
1896 }
Soonil Nagarkarae6ce772019-05-01 13:16:17 -07001897 b.append("(").append(mReceiver.mCallerIdentity.mUid);
1898 if (mIsForegroundUid) {
1899 b.append(" foreground");
1900 } else {
1901 b.append(" background");
1902 }
1903 b.append(") ");
1904 b.append(mRealRequest).append(" ").append(mReceiver.mWorkSource);
1905
1906 if (mStackTrace != null) {
1907 ByteArrayOutputStream tmp = new ByteArrayOutputStream();
1908 mStackTrace.printStackTrace(new PrintStream(tmp));
1909 b.append("\n\n").append(tmp.toString()).append("\n");
1910 }
1911
1912 b.append("]");
1913 return b.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001914 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001915 }
1916
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001917 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00001918 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001919 String packageName, @Nullable String featureId, WorkSource workSource,
1920 boolean hideFromAppOps, @NonNull String listenerIdentifier) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001921 IBinder binder = listener.asBinder();
1922 Receiver receiver = mReceivers.get(binder);
1923 if (receiver == null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001924 receiver = new Receiver(listener, null, pid, uid, packageName, featureId, workSource,
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001925 hideFromAppOps, listenerIdentifier);
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001926 if (!receiver.linkToListenerDeathNotificationLocked(
1927 receiver.getListener().asBinder())) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001928 return null;
1929 }
Wen Jingcb3ab222014-03-27 13:42:59 +08001930 mReceivers.put(binder, receiver);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001931 }
1932 return receiver;
1933 }
1934
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001935 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00001936 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001937 @Nullable String featureId, WorkSource workSource, boolean hideFromAppOps,
1938 @NonNull String listenerIdentifier) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001939 Receiver receiver = mReceivers.get(intent);
1940 if (receiver == null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001941 receiver = new Receiver(null, intent, pid, uid, packageName, featureId, workSource,
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001942 hideFromAppOps, listenerIdentifier);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001943 mReceivers.put(intent, receiver);
1944 }
1945 return receiver;
1946 }
1947
Victoria Lease37425c32012-10-16 16:08:48 -07001948 /**
1949 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
1950 * and consistency requirements.
1951 *
1952 * @param request the LocationRequest from which to create a sanitized version
Victoria Lease37425c32012-10-16 16:08:48 -07001953 * @return a version of request that meets the given resolution and consistency requirements
1954 * @hide
1955 */
gomo48f1a642017-11-10 20:35:46 -08001956 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel,
1957 boolean callerHasLocationHardwarePermission) {
Victoria Lease37425c32012-10-16 16:08:48 -07001958 LocationRequest sanitizedRequest = new LocationRequest(request);
gomo48f1a642017-11-10 20:35:46 -08001959 if (!callerHasLocationHardwarePermission) {
1960 // allow setting low power mode only for callers with location hardware permission
1961 sanitizedRequest.setLowPowerMode(false);
1962 }
Victoria Lease37425c32012-10-16 16:08:48 -07001963 if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
1964 switch (sanitizedRequest.getQuality()) {
Victoria Lease09016ab2012-09-16 12:33:15 -07001965 case LocationRequest.ACCURACY_FINE:
Victoria Lease37425c32012-10-16 16:08:48 -07001966 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
Victoria Lease09016ab2012-09-16 12:33:15 -07001967 break;
1968 case LocationRequest.POWER_HIGH:
Victoria Lease37425c32012-10-16 16:08:48 -07001969 sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
Victoria Lease09016ab2012-09-16 12:33:15 -07001970 break;
1971 }
1972 // throttle
Soonil Nagarkar77a92272020-02-11 14:04:39 -08001973 if (sanitizedRequest.getInterval() < FASTEST_COARSE_INTERVAL_MS) {
1974 sanitizedRequest.setInterval(FASTEST_COARSE_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001975 }
Soonil Nagarkar77a92272020-02-11 14:04:39 -08001976 if (sanitizedRequest.getFastestInterval() < FASTEST_COARSE_INTERVAL_MS) {
1977 sanitizedRequest.setFastestInterval(FASTEST_COARSE_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001978 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07001979 }
Nick Pelly4e31c4f2012-08-13 19:35:39 -07001980 // make getFastestInterval() the minimum of interval and fastest interval
Victoria Lease37425c32012-10-16 16:08:48 -07001981 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001982 sanitizedRequest.setFastestInterval(request.getInterval());
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001983 }
Victoria Lease37425c32012-10-16 16:08:48 -07001984 return sanitizedRequest;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001985 }
1986
Nick Pellye0fd6932012-07-11 10:26:13 -07001987 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001988 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001989 PendingIntent intent, String packageName, String featureId,
1990 String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00001991 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001992
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08001993 enforceCallingOrSelfLocationPermission();
1994 enforceCallingOrSelfPackageName(packageName);
1995
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001996 synchronized (mLock) {
1997 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001998 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001999 WorkSource workSource = request.getWorkSource();
2000 if (workSource != null && !workSource.isEmpty()) {
2001 mContext.enforceCallingOrSelfPermission(
2002 Manifest.permission.UPDATE_DEVICE_STATS, null);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002003 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002004 boolean hideFromAppOps = request.getHideFromAppOps();
2005 if (hideFromAppOps) {
2006 mContext.enforceCallingOrSelfPermission(
2007 Manifest.permission.UPDATE_APP_OPS_STATS, null);
2008 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002009 if (request.isLocationSettingsIgnored()) {
2010 mContext.enforceCallingOrSelfPermission(
2011 Manifest.permission.WRITE_SECURE_SETTINGS, null);
2012 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002013 boolean callerHasLocationHardwarePermission =
2014 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
2015 == PERMISSION_GRANTED;
2016 LocationRequest sanitizedRequest = createSanitizedRequest(request,
2017 allowedResolutionLevel,
2018 callerHasLocationHardwarePermission);
2019
2020 final int pid = Binder.getCallingPid();
2021 final int uid = Binder.getCallingUid();
2022
2023 long identity = Binder.clearCallingIdentity();
2024 try {
2025
2026 // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2027 // a location.
2028 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
2029
2030 if (intent == null && listener == null) {
2031 throw new IllegalArgumentException("need either listener or intent");
2032 } else if (intent != null && listener != null) {
2033 throw new IllegalArgumentException(
2034 "cannot register both listener and intent");
2035 }
2036
Hongyi Zhang700137e2019-05-23 21:19:36 -07002037 mLocationUsageLogger.logLocationApiUsage(
2038 LocationStatsEnums.USAGE_STARTED,
2039 LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
2040 packageName, request, listener != null, intent != null,
Hongyi Zhang0e9ea752019-06-09 22:49:25 -07002041 /* geofence= */ null,
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002042 mAppForegroundHelper.getImportance(uid));
Hongyi Zhang700137e2019-05-23 21:19:36 -07002043
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002044 Receiver receiver;
2045 if (intent != null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002046 receiver = getReceiverLocked(intent, pid, uid, packageName, featureId,
2047 workSource, hideFromAppOps, listenerIdentifier);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002048 } else {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002049 receiver = getReceiverLocked(listener, pid, uid, packageName, featureId,
2050 workSource, hideFromAppOps, listenerIdentifier);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002051 }
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002052 requestLocationUpdatesLocked(sanitizedRequest, receiver);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002053 } finally {
2054 Binder.restoreCallingIdentity(identity);
2055 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002056 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002057 }
2058
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002059 @GuardedBy("mLock")
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002060 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002061 // Figure out the provider. Either its explicitly request (legacy use cases), or
2062 // use the fused provider
2063 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2064 String name = request.getProvider();
Victoria Lease09016ab2012-09-16 12:33:15 -07002065 if (name == null) {
2066 throw new IllegalArgumentException("provider name must not be null");
2067 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -07002068
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002069 LocationProviderManager manager = getLocationProviderManager(name);
2070 if (manager == null) {
Victoria Leaseb30f3832013-10-13 12:15:40 -07002071 throw new IllegalArgumentException("provider doesn't exist: " + name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002072 }
2073
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002074 UpdateRecord record = new UpdateRecord(name, request, receiver);
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002075
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002076 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
2077 if (oldRecord != null) {
2078 oldRecord.disposeLocked(false);
2079 }
2080
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002081 int userId = UserHandle.getUserId(receiver.mCallerIdentity.mUid);
2082 if (!manager.isEnabled(userId) && !isSettingsExempt(record)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002083 // Notify the listener that updates are currently disabled - but only if the request
2084 // does not ignore location settings
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002085 receiver.callProviderEnabledLocked(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002086 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002087
2088 applyRequirementsLocked(name);
2089
David Christie0b837452013-07-29 16:02:13 -07002090 // Update the monitoring here just in case multiple location requests were added to the
2091 // same receiver (this request may be high power and the initial might not have been).
2092 receiver.updateMonitoring(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002093 }
2094
Nick Pellye0fd6932012-07-11 10:26:13 -07002095 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002096 public void removeUpdates(ILocationListener listener, PendingIntent intent,
Soonil Nagarkar68257742019-01-09 19:42:34 +00002097 String packageName) {
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002098 enforceCallingOrSelfPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002099
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002100 int pid = Binder.getCallingPid();
2101 int uid = Binder.getCallingUid();
2102
2103 if (intent == null && listener == null) {
2104 throw new IllegalArgumentException("need either listener or intent");
2105 } else if (intent != null && listener != null) {
2106 throw new IllegalArgumentException("cannot register both listener and intent");
2107 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002108
Soonil Nagarkar68257742019-01-09 19:42:34 +00002109 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002110 Receiver receiver;
2111 if (intent != null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002112 receiver = getReceiverLocked(intent, pid, uid, packageName, null, null, false, "");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002113 } else {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002114 receiver = getReceiverLocked(listener, pid, uid, packageName, null, null, false,
2115 "");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002116 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002117
Soonil Nagarkar68257742019-01-09 19:42:34 +00002118 long identity = Binder.clearCallingIdentity();
2119 try {
2120 removeUpdatesLocked(receiver);
2121 } finally {
2122 Binder.restoreCallingIdentity(identity);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002123 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002124 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002125 }
2126
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002127 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00002128 private void removeUpdatesLocked(Receiver receiver) {
Dianne Hackborn7ff30112012-11-08 11:12:09 -08002129 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002130
2131 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002132 receiver.unlinkFromListenerDeathNotificationLocked(
2133 receiver.getListener().asBinder());
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08002134 receiver.clearPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002135 }
2136
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07002137 receiver.updateMonitoring(false);
2138
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002139 // Record which providers were associated with this listener
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002140 HashSet<String> providers = new HashSet<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002141 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2142 if (oldRecords != null) {
2143 // Call dispose() on the obsolete update records.
2144 for (UpdateRecord record : oldRecords.values()) {
David Christie2ff96af2014-01-30 16:09:37 -08002145 // Update statistics for historical location requests by package/provider
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002146 record.disposeLocked(false);
2147 }
2148 // Accumulate providers
2149 providers.addAll(oldRecords.keySet());
2150 }
2151
2152 // update provider
2153 for (String provider : providers) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002154 applyRequirementsLocked(provider);
2155 }
2156 }
2157
Nick Pellye0fd6932012-07-11 10:26:13 -07002158 @Override
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002159 public Location getLastLocation(LocationRequest request, String packageName, String featureId) {
2160 if (request == null) {
2161 request = DEFAULT_LOCATION_REQUEST;
2162 }
2163
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002164 enforceCallingOrSelfLocationPermission();
2165 enforceCallingOrSelfPackageName(packageName);
2166
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002167 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2168 if (!reportLocationAccessNoThrow(Binder.getCallingPid(), Binder.getCallingUid(),
2169 packageName, featureId, allowedResolutionLevel, null)) {
2170 if (D) {
2171 Log.d(TAG, "not returning last loc for no op app: " + packageName);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002172 }
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002173 return null;
2174 }
2175
2176 int userId = UserHandle.getCallingUserId();
2177
2178 if (mSettingsHelper.isLocationPackageBlacklisted(userId, packageName)) {
2179 return null;
2180 }
2181
2182 if (!mUserInfoHelper.isCurrentUserId(userId)) {
2183 return null;
2184 }
2185
2186 synchronized (mLock) {
2187 LocationProviderManager manager = getLocationProviderManager(request.getProvider());
2188 if (manager == null) {
2189 return null;
2190 }
2191
2192 if (!manager.isEnabled(userId) && !request.isLocationSettingsIgnored()) {
2193 return null;
2194 }
2195
2196 Location location;
2197 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2198 location = manager.getLastCoarseLocation(userId);
2199 } else {
2200 location = manager.getLastFineLocation(userId);
2201 }
2202 if (location == null) {
2203 return null;
2204 }
2205
2206 // Don't return stale location to apps with foreground-only location permission.
2207 String op = resolutionLevelToOpStr(allowedResolutionLevel);
2208 long locationAgeMs = NANOSECONDS.toMillis(
2209 SystemClock.elapsedRealtime() - location.getElapsedRealtimeNanos());
2210 if (locationAgeMs > mSettingsHelper.getMaxLastLocationAgeMs()
2211 && (mAppOps.unsafeCheckOp(op, Binder.getCallingUid(), packageName)
2212 == AppOpsManager.MODE_FOREGROUND)) {
2213 return null;
2214 }
2215
2216 // make a defensive copy - the client could be in the same process as us
2217 return new Location(location);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002218 }
2219 }
2220
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002221 @Override
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002222 public boolean getCurrentLocation(LocationRequest locationRequest,
2223 ICancellationSignal remoteCancellationSignal, ILocationListener listener,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002224 String packageName, String featureId, String listenerIdentifier) {
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002225 // side effect of validating locationRequest and packageName
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002226 Location lastLocation = getLastLocation(locationRequest, packageName, featureId);
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002227 if (lastLocation != null) {
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002228 long locationAgeMs = NANOSECONDS.toMillis(
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002229 SystemClock.elapsedRealtimeNanos() - lastLocation.getElapsedRealtimeNanos());
2230
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002231 if (locationAgeMs < MAX_CURRENT_LOCATION_AGE_MS) {
2232 try {
2233 listener.onLocationChanged(lastLocation);
2234 return true;
2235 } catch (RemoteException e) {
2236 Log.w(TAG, e);
2237 return false;
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002238 }
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002239 }
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002240
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002241 if (!mAppForegroundHelper.isAppForeground(Binder.getCallingUid())) {
2242 if (locationAgeMs < mSettingsHelper.getBackgroundThrottleIntervalMs()) {
2243 // not allowed to request new locations, so we can't return anything
2244 return false;
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002245 }
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002246 }
2247 }
2248
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002249 requestLocationUpdates(locationRequest, listener, null, packageName, featureId,
2250 listenerIdentifier);
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002251 CancellationSignal cancellationSignal = CancellationSignal.fromTransport(
2252 remoteCancellationSignal);
2253 if (cancellationSignal != null) {
2254 cancellationSignal.setOnCancelListener(
2255 () -> removeUpdates(listener, null, packageName));
2256 }
2257 return true;
2258 }
2259
2260 @Override
Chad Brubakerf1133332019-03-15 14:13:59 -07002261 public LocationTime getGnssTimeMillis() {
2262 synchronized (mLock) {
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002263 LocationProviderManager gpsManager = getLocationProviderManager(GPS_PROVIDER);
2264 if (gpsManager == null) {
2265 return null;
2266 }
2267
2268 Location location = gpsManager.getLastFineLocation(UserHandle.getCallingUserId());
Chad Brubakerf1133332019-03-15 14:13:59 -07002269 if (location == null) {
2270 return null;
2271 }
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002272
Chad Brubakerf1133332019-03-15 14:13:59 -07002273 long currentNanos = SystemClock.elapsedRealtimeNanos();
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002274 long deltaMs = NANOSECONDS.toMillis(
2275 currentNanos - location.getElapsedRealtimeNanos());
Chad Brubakerf1133332019-03-15 14:13:59 -07002276 return new LocationTime(location.getTime() + deltaMs, currentNanos);
2277 }
2278 }
2279
2280 @Override
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002281 public void injectLocation(Location location) {
Soonil Nagarkar41a36542020-02-06 09:47:52 -08002282 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, null);
2283 mContext.enforceCallingPermission(ACCESS_FINE_LOCATION, null);
2284
2285 Preconditions.checkArgument(location.isComplete());
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002286
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002287 int userId = UserHandle.getCallingUserId();
Soonil Nagarkar68257742019-01-09 19:42:34 +00002288 synchronized (mLock) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002289 LocationProviderManager manager = getLocationProviderManager(location.getProvider());
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002290 if (manager != null && manager.isEnabled(userId)) {
2291 manager.injectLastLocation(Objects.requireNonNull(location), userId);
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002292 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002293 }
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002294 }
2295
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002296 @Override
2297 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002298 String packageName, String featureId, String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002299 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002300
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002301 mContext.enforceCallingOrSelfPermission(ACCESS_FINE_LOCATION, null);
2302 enforceCallingOrSelfPackageName(packageName);
2303
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002304 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002305 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002306 if (intent == null) {
2307 throw new IllegalArgumentException("invalid pending intent: " + null);
Victoria Lease56e675b2012-11-05 19:25:06 -08002308 }
Soonil Nagarkar8c4655e2019-02-27 13:00:56 -08002309 // Require that caller can manage given document
2310 boolean callerHasLocationHardwarePermission =
2311 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
2312 == PERMISSION_GRANTED;
2313 LocationRequest sanitizedRequest = createSanitizedRequest(request,
2314 allowedResolutionLevel,
2315 callerHasLocationHardwarePermission);
2316
2317 if (D) {
2318 Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
2319 }
2320
2321 // geo-fence manager uses the public location API, need to clear identity
2322 int uid = Binder.getCallingUid();
2323 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
2324 // temporary measure until geofences work for secondary users
2325 Log.w(TAG, "proximity alerts are currently available only to the primary user");
2326 return;
2327 }
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002328
2329 mLocationUsageLogger.logLocationApiUsage(
2330 LocationStatsEnums.USAGE_STARTED,
2331 LocationStatsEnums.API_REQUEST_GEOFENCE,
2332 packageName,
2333 request,
2334 /* hasListener= */ false,
2335 true,
2336 geofence,
2337 mAppForegroundHelper.getImportance(uid));
2338
Soonil Nagarkar8c4655e2019-02-27 13:00:56 -08002339 long identity = Binder.clearCallingIdentity();
2340 try {
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002341 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002342 uid, packageName, featureId, listenerIdentifier);
Soonil Nagarkar8c4655e2019-02-27 13:00:56 -08002343 } finally {
2344 Binder.restoreCallingIdentity(identity);
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002345 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002346 }
2347
2348 @Override
2349 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002350 if (intent == null) {
2351 throw new IllegalArgumentException("invalid pending intent: " + null);
2352 }
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002353 enforceCallingOrSelfPackageName(packageName);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002354
2355 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2356
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002357 mLocationUsageLogger.logLocationApiUsage(
2358 LocationStatsEnums.USAGE_ENDED,
2359 LocationStatsEnums.API_REQUEST_GEOFENCE,
2360 packageName,
2361 /* LocationRequest= */ null,
2362 /* hasListener= */ false,
2363 true,
2364 geofence,
2365 mAppForegroundHelper.getImportance(Binder.getCallingUid()));
2366
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002367 // geo-fence manager uses the public location API, need to clear identity
2368 long identity = Binder.clearCallingIdentity();
2369 try {
2370 mGeofenceManager.removeFence(geofence, intent);
2371 } finally {
2372 Binder.restoreCallingIdentity(identity);
2373 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002374 }
2375
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002376 @Override
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002377 public boolean registerGnssStatusCallback(IGnssStatusListener listener, String packageName,
2378 String featureId) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002379 return mGnssManagerService != null && mGnssManagerService.registerGnssStatusCallback(
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002380 listener, packageName, featureId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002381 }
2382
Nick Pellye0fd6932012-07-11 10:26:13 -07002383 @Override
Anil Admal98d49b72019-02-06 15:26:33 -08002384 public void unregisterGnssStatusCallback(IGnssStatusListener listener) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002385 if (mGnssManagerService != null) mGnssManagerService.unregisterGnssStatusCallback(listener);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002386 }
2387
Nick Pellye0fd6932012-07-11 10:26:13 -07002388 @Override
Yu-Han Yang519694b2020-01-14 10:51:41 -08002389 public boolean addGnssMeasurementsListener(@Nullable GnssRequest request,
2390 IGnssMeasurementsListener listener,
2391 String packageName, String featureId,
2392 String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002393 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002394
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002395 return mGnssManagerService != null && mGnssManagerService.addGnssMeasurementsListener(
Yu-Han Yang519694b2020-01-14 10:51:41 -08002396 request, listener, packageName, featureId, listenerIdentifier);
Anil Admal52686f82019-02-13 19:04:10 -08002397 }
2398
2399 @Override
2400 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002401 if (mGnssManagerService != null) {
2402 mGnssManagerService.removeGnssMeasurementsListener(
2403 listener);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002404 }
destradaaea8a8a62014-06-23 18:19:03 -07002405 }
2406
2407 @Override
gomo226b7b72018-12-12 16:49:39 -08002408 public void injectGnssMeasurementCorrections(
2409 GnssMeasurementCorrections measurementCorrections, String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002410 if (mGnssManagerService != null) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002411 mGnssManagerService.injectGnssMeasurementCorrections(measurementCorrections,
2412 packageName);
gomo226b7b72018-12-12 16:49:39 -08002413 }
2414 }
2415
2416 @Override
Anil Admal99349782019-03-19 18:58:42 -07002417 public long getGnssCapabilities(String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002418 return mGnssManagerService == null ? 0L : mGnssManagerService.getGnssCapabilities(
2419 packageName);
gomo226b7b72018-12-12 16:49:39 -08002420 }
2421
2422 @Override
Sasha Kuznetsova68a7a32020-02-11 06:00:10 +00002423 public boolean addGnssAntennaInfoListener(IGnssAntennaInfoListener listener,
2424 String packageName, String featureId, String listenerIdentifier) {
2425 Objects.requireNonNull(listenerIdentifier);
2426
2427 return mGnssManagerService != null && mGnssManagerService.addGnssAntennaInfoListener(
2428 listener, packageName, featureId, listenerIdentifier);
2429 }
2430
2431 @Override
2432 public void removeGnssAntennaInfoListener(IGnssAntennaInfoListener listener) {
2433 if (mGnssManagerService != null) {
2434 mGnssManagerService.removeGnssAntennaInfoListener(listener);
2435 }
2436 }
2437
2438 @Override
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002439 public boolean addGnssNavigationMessageListener(IGnssNavigationMessageListener listener,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002440 String packageName, String featureId, String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002441 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002442
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002443 return mGnssManagerService != null && mGnssManagerService.addGnssNavigationMessageListener(
2444 listener, packageName, featureId, listenerIdentifier);
destradaa4b3e3932014-07-21 18:01:47 -07002445 }
2446
2447 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002448 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002449 if (mGnssManagerService != null) {
2450 mGnssManagerService.removeGnssNavigationMessageListener(
2451 listener);
2452 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002453 }
2454
2455 @Override
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002456 public boolean sendExtraCommand(String providerName, String command, Bundle extras) {
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002457 Objects.requireNonNull(providerName);
2458 Objects.requireNonNull(command);
Soonil Nagarkar3f128402019-12-12 08:31:27 -08002459
2460 mContext.enforceCallingOrSelfPermission(
2461 Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, null);
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002462 enforceCallingOrSelfLocationPermission();
Soonil Nagarkar3f128402019-12-12 08:31:27 -08002463
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002464 mLocationUsageLogger.logLocationApiUsage(
2465 LocationStatsEnums.USAGE_STARTED,
2466 LocationStatsEnums.API_SEND_EXTRA_COMMAND,
2467 providerName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002468
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002469 LocationProviderManager manager = getLocationProviderManager(providerName);
2470 if (manager != null) {
2471 manager.sendExtraCommand(Binder.getCallingUid(), Binder.getCallingPid(), command,
2472 extras);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002473 }
Soonil Nagarkarbfd1f682020-01-16 10:50:14 -08002474
2475 mLocationUsageLogger.logLocationApiUsage(
2476 LocationStatsEnums.USAGE_ENDED,
2477 LocationStatsEnums.API_SEND_EXTRA_COMMAND,
2478 providerName);
2479
2480 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002481 }
2482
Nick Pellye0fd6932012-07-11 10:26:13 -07002483 @Override
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002484 public ProviderProperties getProviderProperties(String providerName) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002485 LocationProviderManager manager = getLocationProviderManager(providerName);
2486 if (manager == null) {
2487 return null;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002488 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002489 return manager.getProperties();
Jason Monkb71218a2015-06-17 14:44:39 -04002490 }
2491
Wei Wang980b7c22018-12-06 17:53:00 -08002492 @Override
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08002493 public boolean isProviderPackage(String packageName) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002494 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, null);
2495 return mLocalService.isProviderPackage(packageName);
Maggie2a9409e2018-03-21 11:47:28 -07002496 }
2497
Maggie2a9409e2018-03-21 11:47:28 -07002498 @Override
Wei Wang9f52d552019-10-02 14:49:02 -07002499 public List<String> getProviderPackages(String providerName) {
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002500 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, null);
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002501 LocationProviderManager manager = getLocationProviderManager(providerName);
2502 return manager == null ? Collections.emptyList() : new ArrayList<>(manager.getPackages());
Wei Wang9f52d552019-10-02 14:49:02 -07002503 }
2504
2505 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002506 public void setExtraLocationControllerPackage(String packageName) {
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002507 mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
2508 Manifest.permission.LOCATION_HARDWARE + " permission required");
Soonil Nagarkar68257742019-01-09 19:42:34 +00002509 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002510 mExtraLocationControllerPackage = packageName;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002511 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002512 }
2513
2514 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002515 public String getExtraLocationControllerPackage() {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002516 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002517 return mExtraLocationControllerPackage;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002518 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002519 }
2520
2521 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002522 public void setExtraLocationControllerPackageEnabled(boolean enabled) {
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002523 mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
2524 Manifest.permission.LOCATION_HARDWARE + " permission required");
Soonil Nagarkar68257742019-01-09 19:42:34 +00002525 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002526 mExtraLocationControllerPackageEnabled = enabled;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002527 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002528 }
2529
2530 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002531 public boolean isExtraLocationControllerPackageEnabled() {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002532 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002533 return mExtraLocationControllerPackageEnabled
2534 && (mExtraLocationControllerPackage != null);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002535 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002536 }
2537
2538 @Override
Tim Murray270296d2019-11-12 13:29:34 -08002539 public void setLocationEnabledForUser(boolean enabled, int userId) {
2540 if (UserHandle.getCallingUserId() != userId) {
2541 mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS,
2542 null);
2543 }
2544 mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS,
2545 "Requires WRITE_SECURE_SETTINGS permission");
Tim Murrayb5e11532019-11-12 18:23:50 -08002546
2547 LocationManager.invalidateLocalLocationEnabledCaches();
Tim Murray270296d2019-11-12 13:29:34 -08002548 mSettingsHelper.setLocationEnabled(enabled, userId);
2549 }
2550
2551 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002552 public boolean isLocationEnabledForUser(int userId) {
Soonil Nagarkar41a36542020-02-06 09:47:52 -08002553 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2554 userId, false, false, "isLocationEnabledForUser", null);
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002555 return mSettingsHelper.isLocationEnabled(userId);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002556 }
2557
Maggie2a9409e2018-03-21 11:47:28 -07002558 @Override
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002559 public boolean isProviderEnabledForUser(String provider, int userId) {
Soonil Nagarkar41a36542020-02-06 09:47:52 -08002560 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2561 userId, false, false, "isProviderEnabledForUser", null);
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002562
Maggie2a9409e2018-03-21 11:47:28 -07002563 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2564 // so we discourage its use
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002565 if (FUSED_PROVIDER.equals(provider)) return false;
Maggie2a9409e2018-03-21 11:47:28 -07002566
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002567 return mLocalService.isProviderEnabledForUser(provider, userId);
Maggie2a9409e2018-03-21 11:47:28 -07002568 }
2569
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002570 @GuardedBy("mLock")
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002571 private static boolean shouldBroadcastSafeLocked(
Laurent Tu75defb62012-11-01 16:21:52 -07002572 Location loc, Location lastLoc, UpdateRecord record, long now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002573 // Always broadcast the first update
2574 if (lastLoc == null) {
2575 return true;
2576 }
2577
Nick Pellyf1be6862012-05-15 10:53:42 -07002578 // Check whether sufficient time has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002579 long minTime = record.mRealRequest.getFastestInterval();
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002580 long deltaMs = NANOSECONDS.toMillis(
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002581 loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos());
2582 if (deltaMs < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002583 return false;
2584 }
2585
2586 // Check whether sufficient distance has been traveled
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002587 double minDistance = record.mRealRequest.getSmallestDisplacement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002588 if (minDistance > 0.0) {
2589 if (loc.distanceTo(lastLoc) <= minDistance) {
2590 return false;
2591 }
2592 }
2593
Laurent Tu75defb62012-11-01 16:21:52 -07002594 // Check whether sufficient number of udpates is left
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002595 if (record.mRealRequest.getNumUpdates() <= 0) {
Laurent Tu75defb62012-11-01 16:21:52 -07002596 return false;
2597 }
2598
2599 // Check whether the expiry date has passed
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08002600 return record.mExpirationRealtimeMs >= now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002601 }
2602
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002603 @GuardedBy("mLock")
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002604 private void handleLocationChangedLocked(LocationProviderManager manager, Location location,
2605 Location coarseLocation) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002606 if (!mProviderManagers.contains(manager)) {
2607 Log.w(TAG, "received location from unknown provider: " + manager.getName());
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002608 return;
2609 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002610
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002611 // notify passive provider
2612 if (manager != mPassiveManager) {
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002613 mPassiveManager.updateLocation(location);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002614 }
2615
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002616 long now = SystemClock.elapsedRealtime();
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002617
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002618 ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName());
Laurent Tu60ec50a2012-10-04 17:00:10 -07002619 if (records == null || records.size() == 0) return;
2620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002621 ArrayList<Receiver> deadReceivers = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002622 ArrayList<UpdateRecord> deadUpdateRecords = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07002623
Soonil Nagarkar94749f72018-11-08 11:46:43 -08002624 // Broadcast location to all listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002625 for (UpdateRecord r : records) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002626 Receiver receiver = r.mReceiver;
Mike Lockwood03ca2162010-04-01 08:10:09 -07002627 boolean receiverDead = false;
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002628 int userId = UserHandle.getUserId(receiver.mCallerIdentity.mUid);
Nick Pelly4035f5a2012-08-17 14:43:49 -07002629
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002630
2631 if (!manager.isEnabled(userId) && !isSettingsExempt(r)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002632 continue;
2633 }
2634
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002635 if (!mUserInfoHelper.isCurrentUserId(userId)
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08002636 && !isProviderPackage(receiver.mCallerIdentity.mPackageName)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002637 if (D) {
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002638 Log.d(TAG, "skipping loc update for background user " + userId
2639 + " (app: " + receiver.mCallerIdentity.mPackageName + ")");
Victoria Leaseb711d572012-10-02 13:14:11 -07002640 }
2641 continue;
2642 }
2643
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002644 if (mSettingsHelper.isLocationPackageBlacklisted(userId,
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07002645 receiver.mCallerIdentity.mPackageName)) {
gomo48f1a642017-11-10 20:35:46 -08002646 if (D) {
2647 Log.d(TAG, "skipping loc update for blacklisted app: " +
Anil Admal08b96122019-01-30 16:55:05 -08002648 receiver.mCallerIdentity.mPackageName);
gomo48f1a642017-11-10 20:35:46 -08002649 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07002650 continue;
2651 }
2652
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002653 Location notifyLocation;
Victoria Lease37425c32012-10-16 16:08:48 -07002654 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2655 notifyLocation = coarseLocation; // use coarse location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002656 } else {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002657 notifyLocation = location; // use fine location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002658 }
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002659 if (shouldBroadcastSafeLocked(notifyLocation, r.mLastFixBroadcast, r, now)) {
2660 r.mLastFixBroadcast = notifyLocation;
2661 // Report location access before delivering location to the client. This will
2662 // note location delivery to appOps, so it should be called only when a
2663 // location is really being delivered to the client.
2664 if (!reportLocationAccessNoThrow(
2665 receiver.mCallerIdentity.mPid,
2666 receiver.mCallerIdentity.mUid,
2667 receiver.mCallerIdentity.mPackageName,
2668 receiver.mCallerIdentity.mFeatureId,
2669 receiver.mAllowedResolutionLevel,
2670 "Location sent to " + receiver.mCallerIdentity.mListenerIdentifier)) {
2671 if (D) {
2672 Log.d(TAG, "skipping loc update for no op app: "
2673 + receiver.mCallerIdentity.mPackageName);
Victoria Lease09016ab2012-09-16 12:33:15 -07002674 }
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002675 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002676 }
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002677 if (!receiver.callLocationChangedLocked(notifyLocation)) {
2678 Log.w(TAG, "RemoteException calling onLocationChanged on "
2679 + receiver);
2680 receiverDead = true;
2681 }
2682 r.mRealRequest.decrementNumUpdates();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002683 }
2684
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002685 // track expired records
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08002686 if (r.mRealRequest.getNumUpdates() <= 0 || r.mExpirationRealtimeMs < now) {
Soonil Nagarkar39d614a2019-10-31 12:10:31 -07002687 // notify the client it can remove this listener
2688 r.mReceiver.callRemovedLocked();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002689 if (deadUpdateRecords == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002690 deadUpdateRecords = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002691 }
2692 deadUpdateRecords.add(r);
2693 }
2694 // track dead receivers
2695 if (receiverDead) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002696 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002697 deadReceivers = new ArrayList<>();
Mike Lockwood03ca2162010-04-01 08:10:09 -07002698 }
2699 if (!deadReceivers.contains(receiver)) {
2700 deadReceivers.add(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002701 }
2702 }
2703 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002704
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002705 // remove dead records and receivers outside the loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002706 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002707 for (Receiver receiver : deadReceivers) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002708 removeUpdatesLocked(receiver);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002709 }
2710 }
2711 if (deadUpdateRecords != null) {
2712 for (UpdateRecord r : deadUpdateRecords) {
2713 r.disposeLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002715 applyRequirementsLocked(manager);
Victoria Lease8b38b292012-12-04 15:04:43 -08002716 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002717 }
2718
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 // Geocoder
2720
Nick Pellye0fd6932012-07-11 10:26:13 -07002721 @Override
Mike Lockwoode15735a2010-09-20 17:48:47 -04002722 public boolean geocoderIsPresent() {
Mark Vandevoorde01ac80b2010-05-21 15:43:26 -07002723 return mGeocodeProvider != null;
2724 }
2725
Nick Pellye0fd6932012-07-11 10:26:13 -07002726 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 public String getFromLocation(double latitude, double longitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002728 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002729 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002730 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
2731 params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002732 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002733 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734 }
2735
Mike Lockwooda55c3212009-04-15 11:10:11 -04002736
Nick Pellye0fd6932012-07-11 10:26:13 -07002737 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002738 public String getFromLocationName(String locationName,
Mike Lockwooda55c3212009-04-15 11:10:11 -04002739 double lowerLeftLatitude, double lowerLeftLongitude,
2740 double upperRightLatitude, double upperRightLongitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002741 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002742
2743 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002744 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
2745 lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
2746 maxResults, params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002747 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002748 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002749 }
2750
2751 // Mock Providers
2752
Nick Pellye0fd6932012-07-11 10:26:13 -07002753 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002754 public void addTestProvider(String provider, ProviderProperties properties,
2755 String packageName) {
2756 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2757 != AppOpsManager.MODE_ALLOWED) {
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002758 return;
2759 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002760
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002761 synchronized (mLock) {
2762 LocationProviderManager manager = getLocationProviderManager(provider);
2763 if (manager == null) {
2764 manager = new LocationProviderManager(provider);
2765 mProviderManagers.add(manager);
2766 }
2767
Soonil Nagarkar17d8c832020-01-29 18:02:53 -08002768 manager.setMockProvider(new MockProvider(properties));
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002769 }
2770 }
2771
2772 @Override
2773 public void removeTestProvider(String provider, String packageName) {
2774 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2775 != AppOpsManager.MODE_ALLOWED) {
2776 return;
Mike Lockwooda4903f22010-02-17 06:42:23 -05002777 }
2778
Soonil Nagarkar68257742019-01-09 19:42:34 +00002779 synchronized (mLock) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002780 LocationProviderManager manager = getLocationProviderManager(provider);
2781 if (manager == null) {
2782 return;
2783 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002784
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002785 manager.setMockProvider(null);
2786 if (!manager.hasProvider()) {
2787 mProviderManagers.remove(manager);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002788 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002789 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09002790 }
2791
Nick Pellye0fd6932012-07-11 10:26:13 -07002792 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002793 public void setTestProviderLocation(String provider, Location location, String packageName) {
Soonil Nagarkar41a36542020-02-06 09:47:52 -08002794 Preconditions.checkArgument(location.isComplete(),
2795 "incomplete location object, missing timestamp or accuracy?");
2796
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002797 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2798 != AppOpsManager.MODE_ALLOWED) {
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002799 return;
2800 }
2801
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002802 LocationProviderManager manager = getLocationProviderManager(provider);
2803 if (manager == null) {
2804 throw new IllegalArgumentException("provider doesn't exist: " + provider);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002805 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002806
2807 manager.setMockProviderLocation(location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002808 }
2809
Nick Pellye0fd6932012-07-11 10:26:13 -07002810 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002811 public void setTestProviderEnabled(String provider, boolean enabled, String packageName) {
2812 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2813 != AppOpsManager.MODE_ALLOWED) {
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002814 return;
2815 }
2816
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002817 LocationProviderManager manager = getLocationProviderManager(provider);
2818 if (manager == null) {
2819 throw new IllegalArgumentException("provider doesn't exist: " + provider);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002820 }
2821
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08002822 manager.setMockProviderAllowed(enabled);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002823 }
2824
2825 @Override
Kweku Adams4fb074e2019-02-01 16:03:27 -08002826 @NonNull
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002827 public List<LocationRequest> getTestProviderCurrentRequests(String provider,
2828 String packageName) {
2829 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2830 != AppOpsManager.MODE_ALLOWED) {
Kweku Adams4fb074e2019-02-01 16:03:27 -08002831 return Collections.emptyList();
2832 }
2833
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002834 LocationProviderManager manager = getLocationProviderManager(provider);
2835 if (manager == null) {
2836 throw new IllegalArgumentException("provider doesn't exist: " + provider);
Kweku Adams4fb074e2019-02-01 16:03:27 -08002837 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002838
2839 return manager.getMockProviderRequests();
Kweku Adams4fb074e2019-02-01 16:03:27 -08002840 }
2841
2842 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002843 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002844 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) {
2845 return;
2846 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002847
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002848 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
2849
Soonil Nagarkar68257742019-01-09 19:42:34 +00002850 synchronized (mLock) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002851 if (mGnssManagerService != null && args.length > 0 && args[0].equals("--gnssmetrics")) {
2852 mGnssManagerService.dump(fd, pw, args);
Blake Kragten47014d22019-12-06 14:18:38 -08002853 return;
Siddharth Raybb608c82017-03-16 11:33:34 -07002854 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002855
2856 ipw.println("Location Manager State:");
2857 ipw.increaseIndent();
2858 ipw.print("Current System Time: "
WyattRileyba6072f2019-04-18 07:37:52 -07002859 + TimeUtils.logTimeOfDay(System.currentTimeMillis()));
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002860 ipw.println(", Current Elapsed Time: "
WyattRileyba6072f2019-04-18 07:37:52 -07002861 + TimeUtils.formatDuration(SystemClock.elapsedRealtime()));
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08002862
2863 ipw.println("User Info:");
2864 ipw.increaseIndent();
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002865 mUserInfoHelper.dump(fd, ipw, args);
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08002866 ipw.decreaseIndent();
2867
2868 ipw.println("Location Settings:");
2869 ipw.increaseIndent();
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002870 mSettingsHelper.dump(fd, ipw, args);
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08002871 ipw.decreaseIndent();
2872
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002873 ipw.println("Battery Saver Location Mode: "
Kweku Adams4fb074e2019-02-01 16:03:27 -08002874 + locationPowerSaveModeToString(mBatterySaverMode));
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002875
2876 ipw.println("Location Listeners:");
2877 ipw.increaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002878 for (Receiver receiver : mReceivers.values()) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002879 ipw.println(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002880 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002881 ipw.decreaseIndent();
2882
2883 ipw.println("Active Records by Provider:");
2884 ipw.increaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002885 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002886 ipw.println(entry.getKey() + ":");
2887 ipw.increaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002888 for (UpdateRecord record : entry.getValue()) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002889 ipw.println(record);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002890 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002891 ipw.decreaseIndent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002892 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002893 ipw.decreaseIndent();
Anil Admal98d49b72019-02-06 15:26:33 -08002894
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002895 ipw.println("Historical Records by Provider:");
2896 ipw.increaseIndent();
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002897 TreeMap<PackageProviderKey, PackageStatistics> sorted = new TreeMap<>(
2898 mRequestStatistics.statistics);
David Christie2ff96af2014-01-30 16:09:37 -08002899 for (Map.Entry<PackageProviderKey, PackageStatistics> entry
WyattRileyd6b82a62019-12-30 18:12:50 -08002900 : sorted.entrySet()) {
David Christie2ff96af2014-01-30 16:09:37 -08002901 PackageProviderKey key = entry.getKey();
Wei Wang9e33ab42020-02-13 17:12:13 -08002902 ipw.println(key.mPackageName + ": " + key.mProviderName + ": " + entry.getValue());
David Christie2ff96af2014-01-30 16:09:37 -08002903 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002904 ipw.decreaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002905
WyattRileyfa1ef8d32019-12-30 17:19:55 -08002906 mRequestStatistics.history.dump(ipw);
2907
Tyler Trephan2f3ee9a2019-03-21 10:54:22 -07002908 if (mGeofenceManager != null) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002909 ipw.println("Geofences:");
2910 ipw.increaseIndent();
2911 mGeofenceManager.dump(ipw);
2912 ipw.decreaseIndent();
Tyler Trephan2f3ee9a2019-03-21 10:54:22 -07002913 }
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002914
Wei Wang114922a2019-01-30 18:19:35 -08002915 if (mExtraLocationControllerPackage != null) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002916 ipw.println("Location Controller Extra Package: " + mExtraLocationControllerPackage
2917 + (mExtraLocationControllerPackageEnabled ? " [enabled]" : "[disabled]"));
Wei Wang980b7c22018-12-06 17:53:00 -08002918 }
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002919 }
Wei Wang980b7c22018-12-06 17:53:00 -08002920
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002921 ipw.println("Location Providers:");
2922 ipw.increaseIndent();
2923 for (LocationProviderManager manager : mProviderManagers) {
2924 manager.dump(fd, ipw, args);
2925 }
2926 ipw.decreaseIndent();
Anil Admal98d49b72019-02-06 15:26:33 -08002927
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002928 synchronized (mLock) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002929 if (mGnssManagerService != null) {
2930 ipw.println("GNSS:");
2931 ipw.increaseIndent();
2932 mGnssManagerService.dump(fd, ipw, args);
2933 ipw.decreaseIndent();
2934 }
Anil Admal98d49b72019-02-06 15:26:33 -08002935 }
2936 }
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08002937
2938 private class LocalService extends LocationManagerInternal {
2939
2940 @Override
Soonil Nagarkar77a92272020-02-11 14:04:39 -08002941 public boolean isProviderEnabledForUser(@NonNull String provider, int userId) {
2942 synchronized (mLock) {
2943 LocationProviderManager manager = getLocationProviderManager(provider);
2944 if (manager == null) {
2945 return false;
2946 }
2947
2948 return manager.isEnabled(userId);
2949 }
2950 }
2951
2952 @Override
Soonil Nagarkarb6375a42020-01-29 15:23:06 -08002953 public boolean isProviderPackage(String packageName) {
2954 for (LocationProviderManager manager : mProviderManagers) {
2955 if (manager.getPackages().contains(packageName)) {
2956 return true;
2957 }
2958 }
2959 return false;
2960 }
2961
2962 @Override
2963 public void sendNiResponse(int notifId, int userResponse) {
2964 if (mGnssManagerService != null) {
2965 mGnssManagerService.sendNiResponse(notifId, userResponse);
2966 }
2967 }
Soonil Nagarkar980ce6a2020-01-23 18:06:31 -08002968 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002969}