blob: dc393d1609dec2ad27cf7ee67be8851c2b633261 [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
Maggieaa080f92018-01-04 15:35:11 -080019import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -080020import static android.location.LocationManager.FUSED_PROVIDER;
21import static android.location.LocationManager.GPS_PROVIDER;
22import static android.location.LocationManager.NETWORK_PROVIDER;
23import static android.location.LocationManager.PASSIVE_PROVIDER;
Kweku Adams4fb074e2019-02-01 16:03:27 -080024import static android.os.PowerManager.locationPowerSaveModeToString;
Maggieaa080f92018-01-04 15:35:11 -080025
Wei Wang980b7c22018-12-06 17:53:00 -080026import android.Manifest;
Wyatt Rileycf879db2017-01-12 13:57:38 -080027import android.annotation.NonNull;
Wyatt Riley49097c02018-03-15 09:14:43 -070028import android.annotation.Nullable;
Maggieaa080f92018-01-04 15:35:11 -080029import android.app.ActivityManager;
30import android.app.AppOpsManager;
31import android.app.PendingIntent;
32import android.content.BroadcastReceiver;
Maggieaa080f92018-01-04 15:35:11 -080033import android.content.Context;
34import android.content.Intent;
35import android.content.IntentFilter;
36import android.content.pm.ApplicationInfo;
37import android.content.pm.PackageInfo;
38import android.content.pm.PackageManager;
39import android.content.pm.PackageManager.NameNotFoundException;
Maggieaa080f92018-01-04 15:35:11 -080040import android.content.pm.ResolveInfo;
41import android.content.pm.Signature;
42import android.content.res.Resources;
Brian Duddiecfa5b5b2019-01-22 18:01:40 +000043import android.hardware.location.ActivityRecognitionHardware;
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;
Maggieaa080f92018-01-04 15:35:11 -080049import android.location.IBatchedLocationCallback;
50import android.location.IGnssMeasurementsListener;
51import android.location.IGnssNavigationMessageListener;
52import android.location.IGnssStatusListener;
Maggieaa080f92018-01-04 15:35:11 -080053import android.location.ILocationListener;
54import android.location.ILocationManager;
Maggieaa080f92018-01-04 15:35:11 -080055import android.location.Location;
56import android.location.LocationManager;
Maggieaa080f92018-01-04 15:35:11 -080057import android.location.LocationRequest;
Chad Brubakerf1133332019-03-15 14:13:59 -070058import android.location.LocationTime;
Maggieaa080f92018-01-04 15:35:11 -080059import android.os.Binder;
60import android.os.Bundle;
Soonil Nagarkar905e7222019-10-01 12:03:29 -070061import android.os.CancellationSignal;
Maggieaa080f92018-01-04 15:35:11 -080062import android.os.Handler;
63import android.os.IBinder;
Soonil Nagarkar905e7222019-10-01 12:03:29 -070064import android.os.ICancellationSignal;
Maggieaa080f92018-01-04 15:35:11 -080065import android.os.PowerManager;
Kweku Adams4fb074e2019-02-01 16:03:27 -080066import android.os.PowerManager.ServiceType;
67import android.os.PowerManagerInternal;
Maggieaa080f92018-01-04 15:35:11 -080068import android.os.Process;
69import android.os.RemoteException;
70import android.os.SystemClock;
71import android.os.UserHandle;
Maggieaa080f92018-01-04 15:35:11 -080072import android.os.WorkSource;
Narayan Kamath32684dd2018-01-08 17:32:51 +000073import android.os.WorkSource.WorkChain;
Hongyi Zhang700137e2019-05-23 21:19:36 -070074import android.stats.location.LocationStatsEnums;
Maggieaa080f92018-01-04 15:35:11 -080075import android.text.TextUtils;
Maggieaa080f92018-01-04 15:35:11 -080076import android.util.EventLog;
77import android.util.Log;
78import android.util.Slog;
Soonil Nagarkar06e37f62019-12-04 16:05:08 -080079import android.util.SparseArray;
WyattRileyba6072f2019-04-18 07:37:52 -070080import android.util.TimeUtils;
Yu-Han Yanga4d250e2018-10-02 21:29:20 -070081
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -080082import com.android.internal.annotations.GuardedBy;
destradaaea8a8a62014-06-23 18:19:03 -070083import com.android.internal.content.PackageMonitor;
84import com.android.internal.location.ProviderProperties;
85import com.android.internal.location.ProviderRequest;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060086import com.android.internal.util.DumpUtils;
Soonil Nagarkar1c572552019-07-10 13:31:47 -070087import com.android.internal.util.IndentingPrintWriter;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -080088import com.android.internal.util.Preconditions;
Soonil Nagarkar1575a042018-10-24 17:54:54 -070089import com.android.server.location.AbstractLocationProvider;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -080090import com.android.server.location.AbstractLocationProvider.State;
Brian Duddiecfa5b5b2019-01-22 18:01:40 +000091import com.android.server.location.ActivityRecognitionProxy;
Anil Admal08b96122019-01-30 16:55:05 -080092import com.android.server.location.CallerIdentity;
destradaaea8a8a62014-06-23 18:19:03 -070093import com.android.server.location.GeocoderProxy;
94import com.android.server.location.GeofenceManager;
95import com.android.server.location.GeofenceProxy;
destradaaea8a8a62014-06-23 18:19:03 -070096import com.android.server.location.LocationFudger;
destradaaea8a8a62014-06-23 18:19:03 -070097import com.android.server.location.LocationProviderProxy;
98import com.android.server.location.LocationRequestStatistics;
99import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
100import com.android.server.location.LocationRequestStatistics.PackageStatistics;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700101import com.android.server.location.LocationSettingsStore;
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800102import com.android.server.location.LocationUsageLogger;
destradaaea8a8a62014-06-23 18:19:03 -0700103import com.android.server.location.MockProvider;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800104import com.android.server.location.MockableLocationProvider;
destradaaea8a8a62014-06-23 18:19:03 -0700105import com.android.server.location.PassiveProvider;
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800106import com.android.server.location.UserInfoStore;
Todd Kennedy583378d2019-07-12 06:50:30 -0700107import com.android.server.pm.permission.PermissionManagerServiceInternal;
Yu-Han Yanga4d250e2018-10-02 21:29:20 -0700108
Soonil Nagarkarae6ce772019-05-01 13:16:17 -0700109import java.io.ByteArrayOutputStream;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400110import java.io.FileDescriptor;
Soonil Nagarkarae6ce772019-05-01 13:16:17 -0700111import java.io.PrintStream;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400112import java.io.PrintWriter;
113import java.util.ArrayList;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700114import java.util.Arrays;
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -0800115import java.util.Collections;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400116import java.util.HashMap;
117import java.util.HashSet;
118import java.util.List;
119import java.util.Map;
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800120import java.util.Map.Entry;
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +0000121import java.util.Objects;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800122import java.util.Set;
123import java.util.concurrent.CopyOnWriteArrayList;
Soonil Nagarkar905e7222019-10-01 12:03:29 -0700124import java.util.concurrent.TimeUnit;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125
126/**
127 * The service class that manages LocationProviders and issues location
128 * updates and alerts.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129 */
Victoria Lease5cd731a2012-12-19 15:04:21 -0800130public class LocationManagerService extends ILocationManager.Stub {
Soonil Nagarkar141417a2019-10-28 11:12:48 -0700131
132 /**
133 * Controls lifecycle of LocationManagerService.
134 */
135 public static class Lifecycle extends SystemService {
136
137 private LocationManagerService mService;
138
139 public Lifecycle(Context context) {
140 super(context);
141 mService = new LocationManagerService(context);
142 }
143
144 @Override
145 public void onStart() {
146 publishBinderService(Context.LOCATION_SERVICE, mService);
147 }
148
149 @Override
150 public void onBootPhase(int phase) {
Soonil Nagarkar37096062019-11-25 13:24:48 -0800151 if (phase == PHASE_SYSTEM_SERVICES_READY) {
152 // the location service must be functioning after this boot phase
153 mService.onSystemReady();
154 } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
155 // some providers rely on third party code, so we wait to initialize
156 // providers until third party code is allowed to run
157 mService.onSystemThirdPartyAppsCanStart();
Soonil Nagarkar141417a2019-10-28 11:12:48 -0700158 }
159 }
160 }
161
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800162 public static final String TAG = "LocationManagerService";
JP Abgrallf79811e72013-02-01 18:45:05 -0800163 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700164
Olivier Gaillard7a222662017-11-20 16:07:24 +0000165 private static final String WAKELOCK_KEY = "*location*";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166
Victoria Lease37425c32012-10-16 16:08:48 -0700167 private static final int RESOLUTION_LEVEL_NONE = 0;
Victoria Lease37425c32012-10-16 16:08:48 -0700168 private static final int RESOLUTION_LEVEL_COARSE = 1;
Victoria Lease37425c32012-10-16 16:08:48 -0700169 private static final int RESOLUTION_LEVEL_FINE = 2;
170
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700171 private static final String NETWORK_LOCATION_SERVICE_ACTION =
Stan Chesnutt39062dd2013-07-22 14:33:30 -0700172 "com.android.location.service.v3.NetworkLocationProvider";
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700173 private static final String FUSED_LOCATION_SERVICE_ACTION =
174 "com.android.location.service.FusedLocationProvider";
175
David Christie0b837452013-07-29 16:02:13 -0700176 // The maximum interval a location request can have and still be considered "high power".
177 private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
178
Soonil Nagarkar905e7222019-10-01 12:03:29 -0700179 // maximum age of a location before it is no longer considered "current"
180 private static final long MAX_CURRENT_LOCATION_AGE_MS = 10 * 1000;
181
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700182 private static final int FOREGROUND_IMPORTANCE_CUTOFF
gomo48f1a642017-11-10 20:35:46 -0800183 = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700184
Nick Pellyf1be6862012-05-15 10:53:42 -0700185 // Location Providers may sometimes deliver location updates
186 // slightly faster that requested - provide grace period so
187 // we don't unnecessarily filter events that are otherwise on
188 // time
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700189 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
Nick Pellyf1be6862012-05-15 10:53:42 -0700190
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700191 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
192
Soonil Nagarkar68257742019-01-09 19:42:34 +0000193 private final Object mLock = new Object();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800194 private final Context mContext;
195 private final Handler mHandler;
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800196 private final UserInfoStore mUserInfoStore;
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800197 private final LocationSettingsStore mSettingsStore;
198 private final LocationUsageLogger mLocationUsageLogger;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700199
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800200 private final PassiveLocationProviderManager mPassiveManager;
201
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800202 private AppOpsManager mAppOps;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700203 private PackageManager mPackageManager;
Victoria Lease0aa28602013-05-29 15:28:26 -0700204 private PowerManager mPowerManager;
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800205 private ActivityManager mActivityManager;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800206
207 private GeofenceManager mGeofenceManager;
208 private LocationFudger mLocationFudger;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700209 private GeocoderProxy mGeocodeProvider;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800210 @Nullable private GnssManagerService mGnssManagerService;
211
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800212 @GuardedBy("mLock")
Wei Wang114922a2019-01-30 18:19:35 -0800213 private String mExtraLocationControllerPackage;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800214 @GuardedBy("mLock")
Wei Wang114922a2019-01-30 18:19:35 -0800215 private boolean mExtraLocationControllerPackageEnabled;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700216
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800217 // @GuardedBy("mLock")
218 // hold lock for write or to prevent write, no lock for read
219 private final CopyOnWriteArrayList<LocationProviderManager> mProviderManagers =
220 new CopyOnWriteArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800222 @GuardedBy("mLock")
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800223 private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700224 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800225 new HashMap<>();
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700226
David Christie2ff96af2014-01-30 16:09:37 -0800227 private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics();
228
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700229 // mapping from provider name to last known location
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800230 @GuardedBy("mLock")
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800231 private final HashMap<String, Location> mLastLocation = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232
David Christie1b9b7b12013-04-15 15:31:11 -0700233 // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
234 // locations stored here are not fudged for coarse permissions.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800235 @GuardedBy("mLock")
David Christie1b9b7b12013-04-15 15:31:11 -0700236 private final HashMap<String, Location> mLastLocationCoarseInterval =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800237 new HashMap<>();
David Christie1b9b7b12013-04-15 15:31:11 -0700238
Kweku Adams4fb074e2019-02-01 16:03:27 -0800239 @GuardedBy("mLock")
240 @PowerManager.LocationPowerSaveMode
241 private int mBatterySaverMode;
242
Soonil Nagarkar141417a2019-10-28 11:12:48 -0700243 private LocationManagerService(Context context) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700244 mContext = context;
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -0800245 mHandler = FgThread.getHandler();
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800246 mUserInfoStore = new UserInfoStore(mContext);
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800247 mSettingsStore = new LocationSettingsStore(mContext, mHandler);
Hongyi Zhang700137e2019-05-23 21:19:36 -0700248 mLocationUsageLogger = new LocationUsageLogger();
The Android Open Source Project4df24232009-03-05 14:34:35 -0800249
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800250 // set up passive provider - we do this early because it has no dependencies on system
251 // services or external code that isn't ready yet, and because this allows the variable to
252 // be final. other more complex providers are initialized later, when system services are
253 // ready
254 mPassiveManager = new PassiveLocationProviderManager();
255 mProviderManagers.add(mPassiveManager);
256 mPassiveManager.setRealProvider(new PassiveProvider(mContext));
257
Svet Ganovadc1cf42015-06-15 16:36:24 -0700258 // Let the package manager query which are the default location
259 // providers as they get certain permissions granted by default.
Todd Kennedy583378d2019-07-12 06:50:30 -0700260 PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
261 PermissionManagerServiceInternal.class);
262 permissionManagerInternal.setLocationPackagesProvider(
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700263 userId -> mContext.getResources().getStringArray(
264 com.android.internal.R.array.config_locationProviderPackageNames));
Todd Kennedy583378d2019-07-12 06:50:30 -0700265 permissionManagerInternal.setLocationExtraPackagesProvider(
Wei Wangffb94e62019-01-14 00:05:45 -0800266 userId -> mContext.getResources().getStringArray(
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700267 com.android.internal.R.array.config_locationExtraPackageNames));
Svet Ganovadc1cf42015-06-15 16:36:24 -0700268
Soonil Nagarkar37096062019-11-25 13:24:48 -0800269 // most startup is deferred until systemReady()
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700270 }
271
Soonil Nagarkar37096062019-11-25 13:24:48 -0800272 private void onSystemReady() {
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800273 mUserInfoStore.onSystemReady();
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800274 mSettingsStore.onSystemReady();
275
Soonil Nagarkar68257742019-01-09 19:42:34 +0000276 synchronized (mLock) {
Soonil Nagarkar37096062019-11-25 13:24:48 -0800277 mPackageManager = mContext.getPackageManager();
278 mAppOps = mContext.getSystemService(AppOpsManager.class);
279 mPowerManager = mContext.getSystemService(PowerManager.class);
280 mActivityManager = mContext.getSystemService(ActivityManager.class);
Soonil Nagarkar37096062019-11-25 13:24:48 -0800281
Soonil Nagarkar37096062019-11-25 13:24:48 -0800282 mLocationFudger = new LocationFudger(mContext, mHandler);
283 mGeofenceManager = new GeofenceManager(mContext, mSettingsStore);
284
285 PowerManagerInternal localPowerManager =
286 LocalServices.getService(PowerManagerInternal.class);
287
288 // add listeners
289 mAppOps.startWatchingMode(
290 AppOpsManager.OP_COARSE_LOCATION,
291 null,
292 AppOpsManager.WATCH_FOREGROUND_CHANGES,
293 new AppOpsManager.OnOpChangedInternalListener() {
294 public void onOpChanged(int op, String packageName) {
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800295 // onOpChanged invoked on ui thread, move to our thread to reduce risk
296 // of blocking ui thread
Soonil Nagarkar37096062019-11-25 13:24:48 -0800297 mHandler.post(() -> {
298 synchronized (mLock) {
299 onAppOpChangedLocked();
300 }
301 });
302 }
303 });
304 mPackageManager.addOnPermissionsChangeListener(
305 uid -> {
306 // listener invoked on ui thread, move to our thread to reduce risk of
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800307 // blocking ui thread
Soonil Nagarkar37096062019-11-25 13:24:48 -0800308 mHandler.post(() -> {
309 synchronized (mLock) {
310 onPermissionsChangedLocked();
311 }
312 });
313 });
314 mActivityManager.addOnUidImportanceListener(
315 (uid, importance) -> {
316 // listener invoked on ui thread, move to our thread to reduce risk of
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800317 // blocking ui thread
Soonil Nagarkar37096062019-11-25 13:24:48 -0800318 mHandler.post(() -> {
319 synchronized (mLock) {
320 onUidImportanceChangedLocked(uid, importance);
321 }
322 });
323 },
324 FOREGROUND_IMPORTANCE_CUTOFF);
325
326 localPowerManager.registerLowPowerModeObserver(ServiceType.LOCATION,
327 state -> {
328 // listener invoked on ui thread, move to our thread to reduce risk of
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800329 // blocking ui thread
Soonil Nagarkar37096062019-11-25 13:24:48 -0800330 mHandler.post(() -> {
331 synchronized (mLock) {
332 onBatterySaverModeChangedLocked(state.locationMode);
333 }
334 });
335 });
336 mBatterySaverMode = mPowerManager.getLocationPowerSaveMode();
337
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800338 mSettingsStore.addOnLocationEnabledChangedListener((userId) -> {
Soonil Nagarkar37096062019-11-25 13:24:48 -0800339 synchronized (mLock) {
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800340 onLocationModeChangedLocked(userId);
Soonil Nagarkar37096062019-11-25 13:24:48 -0800341 }
342 });
Soonil Nagarkar37096062019-11-25 13:24:48 -0800343 mSettingsStore.addOnBackgroundThrottleIntervalChangedListener(() -> {
344 synchronized (mLock) {
345 onBackgroundThrottleIntervalChangedLocked();
346 }
347 });
348 mSettingsStore.addOnBackgroundThrottlePackageWhitelistChangedListener(() -> {
349 synchronized (mLock) {
350 onBackgroundThrottleWhitelistChangedLocked();
351 }
352 });
353 mSettingsStore.addOnIgnoreSettingsPackageWhitelistChangedListener(() -> {
354 synchronized (mLock) {
355 onIgnoreSettingsWhitelistChangedLocked();
356 }
357 });
358
359 new PackageMonitor() {
360 @Override
361 public void onPackageDisappeared(String packageName, int reason) {
362 synchronized (mLock) {
363 LocationManagerService.this.onPackageDisappearedLocked(packageName);
364 }
365 }
366 }.register(mContext, mHandler.getLooper(), true);
367
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800368 mUserInfoStore.addListener((oldUserId, newUserId) -> {
369 synchronized (mLock) {
370 onUserChangedLocked(oldUserId, newUserId);
371 }
372 });
373
Soonil Nagarkar37096062019-11-25 13:24:48 -0800374 IntentFilter intentFilter = new IntentFilter();
Soonil Nagarkar37096062019-11-25 13:24:48 -0800375 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
376 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
377
378 mContext.registerReceiverAsUser(new BroadcastReceiver() {
379 @Override
380 public void onReceive(Context context, Intent intent) {
381 final String action = intent.getAction();
382 if (action == null) {
383 return;
384 }
385 synchronized (mLock) {
386 switch (action) {
Soonil Nagarkar37096062019-11-25 13:24:48 -0800387 case Intent.ACTION_SCREEN_ON:
388 case Intent.ACTION_SCREEN_OFF:
389 onScreenStateChangedLocked();
390 break;
391 }
392 }
393 }
394 }, UserHandle.ALL, intentFilter, null, mHandler);
395
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800396 // switching the user from null to current here performs the bulk of the initialization
Soonil Nagarkar37096062019-11-25 13:24:48 -0800397 // work. the user being changed will cause a reload of all user specific settings, which
398 // causes initialization, and propagates changes until a steady state is reached
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800399 onUserChangedLocked(UserHandle.USER_NULL, mUserInfoStore.getCurrentUserId());
Victoria Lease5cd731a2012-12-19 15:04:21 -0800400 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800401 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700402
Soonil Nagarkar37096062019-11-25 13:24:48 -0800403 private void onSystemThirdPartyAppsCanStart() {
404 synchronized (mLock) {
405 // prepare providers
406 initializeProvidersLocked();
407 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700408 }
409
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800410 @GuardedBy("mLock")
411 private void onAppOpChangedLocked() {
412 for (Receiver receiver : mReceivers.values()) {
413 receiver.updateMonitoring(true);
414 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800415 for (LocationProviderManager manager : mProviderManagers) {
416 applyRequirementsLocked(manager);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800417 }
418 }
419
420 @GuardedBy("mLock")
421 private void onPermissionsChangedLocked() {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800422 for (LocationProviderManager manager : mProviderManagers) {
423 applyRequirementsLocked(manager);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800424 }
425 }
426
427 @GuardedBy("mLock")
Kweku Adams4fb074e2019-02-01 16:03:27 -0800428 private void onBatterySaverModeChangedLocked(int newLocationMode) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700429 if (mBatterySaverMode == newLocationMode) {
430 return;
431 }
432
Kweku Adams4fb074e2019-02-01 16:03:27 -0800433 if (D) {
434 Slog.d(TAG,
435 "Battery Saver location mode changed from "
436 + locationPowerSaveModeToString(mBatterySaverMode) + " to "
437 + locationPowerSaveModeToString(newLocationMode));
438 }
439
Kweku Adams4fb074e2019-02-01 16:03:27 -0800440 mBatterySaverMode = newLocationMode;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700441
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 @GuardedBy("mLock")
448 private void onScreenStateChangedLocked() {
449 if (mBatterySaverMode == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800450 for (LocationProviderManager manager : mProviderManagers) {
451 applyRequirementsLocked(manager);
Kweku Adams4fb074e2019-02-01 16:03:27 -0800452 }
453 }
454 }
455
456 @GuardedBy("mLock")
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800457 private void onLocationModeChangedLocked(int userId) {
458 if (D) {
459 Log.d(TAG, "[u" + userId + "] location enabled = " + isLocationEnabledForUser(userId));
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800460 }
461
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800462 Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION);
Soonil Nagarkar57f4b7b2019-12-09 10:19:18 -0800463 intent.putExtra(LocationManager.EXTRA_LOCATION_ENABLED, isLocationEnabledForUser(userId));
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800464 mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800465
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800466 for (LocationProviderManager manager : mProviderManagers) {
467 manager.onUseableChangedLocked(userId);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800468 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800469 }
470
471 @GuardedBy("mLock")
472 private void onPackageDisappearedLocked(String packageName) {
473 ArrayList<Receiver> deadReceivers = null;
474
475 for (Receiver receiver : mReceivers.values()) {
Anil Admal08b96122019-01-30 16:55:05 -0800476 if (receiver.mCallerIdentity.mPackageName.equals(packageName)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800477 if (deadReceivers == null) {
478 deadReceivers = new ArrayList<>();
479 }
480 deadReceivers.add(receiver);
481 }
482 }
483
484 // perform removal outside of mReceivers loop
485 if (deadReceivers != null) {
486 for (Receiver receiver : deadReceivers) {
487 removeUpdatesLocked(receiver);
488 }
489 }
490 }
491
492 @GuardedBy("mLock")
493 private void onUidImportanceChangedLocked(int uid, int importance) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700494 boolean foreground = LocationManagerServiceUtils.isImportanceForeground(importance);
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700495 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800496 for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
497 String provider = entry.getKey();
498 for (UpdateRecord record : entry.getValue()) {
Anil Admal08b96122019-01-30 16:55:05 -0800499 if (record.mReceiver.mCallerIdentity.mUid == uid
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800500 && record.mIsForegroundUid != foreground) {
gomo48f1a642017-11-10 20:35:46 -0800501 if (D) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800502 Log.d(TAG, "request from uid " + uid + " is now "
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700503 + LocationManagerServiceUtils.foregroundAsString(
504 foreground));
gomo48f1a642017-11-10 20:35:46 -0800505 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800506 record.updateForeground(foreground);
507
Anil Admal08b96122019-01-30 16:55:05 -0800508 if (!isThrottlingExemptLocked(record.mReceiver.mCallerIdentity)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800509 affectedProviders.add(provider);
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700510 }
511 }
512 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800513 }
514 for (String provider : affectedProviders) {
515 applyRequirementsLocked(provider);
516 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800517 }
518
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800519 @GuardedBy("mLock")
520 private void onBackgroundThrottleIntervalChangedLocked() {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800521 for (LocationProviderManager manager : mProviderManagers) {
522 applyRequirementsLocked(manager);
Soonil Nagarkar68257742019-01-09 19:42:34 +0000523 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -0800524 }
525
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800526 @GuardedBy("mLock")
527 private void onBackgroundThrottleWhitelistChangedLocked() {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800528 for (LocationProviderManager manager : mProviderManagers) {
529 applyRequirementsLocked(manager);
Soonil Nagarkar68257742019-01-09 19:42:34 +0000530 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -0800531 }
532
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800533 @GuardedBy("lock")
534 private void onIgnoreSettingsWhitelistChangedLocked() {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800535 for (LocationProviderManager manager : mProviderManagers) {
536 applyRequirementsLocked(manager);
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800537 }
538 }
539
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800540 @GuardedBy("mLock")
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700541 private void ensureFallbackFusedProviderPresentLocked(String[] pkgs) {
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500542 PackageManager pm = mContext.getPackageManager();
543 String systemPackageName = mContext.getPackageName();
544 ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
545
546 List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
547 new Intent(FUSED_LOCATION_SERVICE_ACTION),
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800548 PackageManager.GET_META_DATA, mUserInfoStore.getCurrentUserId());
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500549 for (ResolveInfo rInfo : rInfos) {
550 String packageName = rInfo.serviceInfo.packageName;
551
552 // Check that the signature is in the list of supported sigs. If it's not in
553 // this list the standard provider binding logic won't bind to it.
554 try {
555 PackageInfo pInfo;
556 pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
557 if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
558 Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
559 ", but has wrong signature, ignoring");
560 continue;
561 }
562 } catch (NameNotFoundException e) {
563 Log.e(TAG, "missing package: " + packageName);
564 continue;
565 }
566
567 // Get the version info
568 if (rInfo.serviceInfo.metaData == null) {
569 Log.w(TAG, "Found fused provider without metadata: " + packageName);
570 continue;
571 }
572
573 int version = rInfo.serviceInfo.metaData.getInt(
574 ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
575 if (version == 0) {
576 // This should be the fallback fused location provider.
577
578 // Make sure it's in the system partition.
579 if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
580 if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
581 continue;
582 }
583
584 // Check that the fallback is signed the same as the OS
585 // as a proxy for coreApp="true"
586 if (pm.checkSignatures(systemPackageName, packageName)
587 != PackageManager.SIGNATURE_MATCH) {
gomo48f1a642017-11-10 20:35:46 -0800588 if (D) {
589 Log.d(TAG, "Fallback candidate not signed the same as system: "
590 + packageName);
591 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500592 continue;
593 }
594
595 // Found a valid fallback.
596 if (D) Log.d(TAG, "Found fallback provider: " + packageName);
597 return;
598 } else {
599 if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
600 }
601 }
602
603 throw new IllegalStateException("Unable to find a fused location provider that is in the "
604 + "system partition with version 0 and signed with the platform certificate. "
605 + "Such a package is needed to provide a default fused location provider in the "
606 + "event that no other fused location provider has been installed or is currently "
607 + "available. For example, coreOnly boot mode when decrypting the data "
608 + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
609 }
610
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800611 @GuardedBy("mLock")
612 private void initializeProvidersLocked() {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700613 if (GnssManagerService.isGnssSupported()) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800614 mGnssManagerService = new GnssManagerService(this, mContext, mLocationUsageLogger);
615 LocationProviderManager gnssManager = new LocationProviderManager(GPS_PROVIDER);
616 mProviderManagers.add(gnssManager);
617 gnssManager.setRealProvider(mGnssManagerService.getGnssLocationProvider());
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700618 }
619
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700620 /*
621 Load package name(s) containing location provider support.
622 These packages can contain services implementing location providers:
623 Geocoder Provider, Network Location Provider, and
624 Fused Location Provider. They will each be searched for
625 service components implementing these providers.
626 The location framework also has support for installation
627 of new location providers at run-time. The new package does not
628 have to be explicitly listed here, however it must have a signature
629 that matches the signature of at least one package on this list.
630 */
631 Resources resources = mContext.getResources();
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500632 String[] pkgs = resources.getStringArray(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700633 com.android.internal.R.array.config_locationProviderPackageNames);
gomo48f1a642017-11-10 20:35:46 -0800634 if (D) {
635 Log.d(TAG, "certificates for location providers pulled from: " +
636 Arrays.toString(pkgs));
637 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500638
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700639 ensureFallbackFusedProviderPresentLocked(pkgs);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700640
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700641 LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
642 mContext,
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700643 NETWORK_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700644 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
645 com.android.internal.R.string.config_networkLocationProviderPackageName,
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700646 com.android.internal.R.array.config_locationProviderPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700647 if (networkProvider != null) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800648 LocationProviderManager networkManager = new LocationProviderManager(NETWORK_PROVIDER);
649 mProviderManagers.add(networkManager);
650 networkManager.setRealProvider(networkProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700651 } else {
gomo48f1a642017-11-10 20:35:46 -0800652 Slog.w(TAG, "no network location provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700653 }
654
655 // bind to fused provider
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700656 LocationProviderProxy fusedProvider = LocationProviderProxy.createAndBind(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700657 mContext,
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700658 FUSED_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700659 com.android.internal.R.bool.config_enableFusedLocationOverlay,
660 com.android.internal.R.string.config_fusedLocationProviderPackageName,
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700661 com.android.internal.R.array.config_locationProviderPackageNames);
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700662 if (fusedProvider != null) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800663 LocationProviderManager fusedManager = new LocationProviderManager(FUSED_PROVIDER);
664 mProviderManagers.add(fusedManager);
665 fusedManager.setRealProvider(fusedProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700666 } else {
667 Slog.e(TAG, "no fused location provider found",
668 new IllegalStateException("Location service needs a fused location provider"));
669 }
670
671 // bind to geocoder provider
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700672 mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
673 com.android.internal.R.bool.config_enableGeocoderOverlay,
674 com.android.internal.R.string.config_geocoderProviderPackageName,
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700675 com.android.internal.R.array.config_locationProviderPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700676 if (mGeocodeProvider == null) {
gomo48f1a642017-11-10 20:35:46 -0800677 Slog.e(TAG, "no geocoder provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700678 }
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700679
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700680 if (mGnssManagerService != null) {
681 // bind to geofence provider
682 GeofenceProxy provider = GeofenceProxy.createAndBind(
683 mContext, com.android.internal.R.bool.config_enableGeofenceOverlay,
684 com.android.internal.R.string.config_geofenceProviderPackageName,
685 com.android.internal.R.array.config_locationProviderPackageNames,
686 mGnssManagerService.getGpsGeofenceProxy(),
687 null);
688 if (provider == null) {
689 Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
690 }
destradaa0682809a2013-08-12 18:50:30 -0700691 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900692
Brian Duddiecfa5b5b2019-01-22 18:01:40 +0000693 // bind to hardware activity recognition
694 boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
695 ActivityRecognitionHardware activityRecognitionHardware = null;
696 if (activityRecognitionHardwareIsSupported) {
697 activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
698 } else {
699 Slog.d(TAG, "Hardware Activity-Recognition not supported.");
700 }
701 ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
702 mContext,
703 activityRecognitionHardwareIsSupported,
704 activityRecognitionHardware,
705 com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
706 com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
707 com.android.internal.R.array.config_locationProviderPackageNames);
708 if (proxy == null) {
709 Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
710 }
711
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900712 String[] testProviderStrings = resources.getStringArray(
713 com.android.internal.R.array.config_testLocationProviders);
714 for (String testProviderString : testProviderStrings) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -0800715 String[] fragments = testProviderString.split(",");
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900716 String name = fragments[0].trim();
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900717 ProviderProperties properties = new ProviderProperties(
718 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
719 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
720 Boolean.parseBoolean(fragments[3]) /* requiresCell */,
721 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
722 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
723 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
724 Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
725 Integer.parseInt(fragments[8]) /* powerRequirement */,
726 Integer.parseInt(fragments[9]) /* accuracy */);
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800727 addTestProvider(name, properties, mContext.getOpPackageName());
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900728 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700729 }
Mike Lockwood9637d472009-04-02 21:41:57 -0700730
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800731 @GuardedBy("mLock")
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800732 private void onUserChangedLocked(int oldUserId, int newUserId) {
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800733 if (D) {
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800734 Log.d(TAG, "foreground user is changing to " + newUserId);
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800735 }
736
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800737 for (LocationProviderManager manager : mProviderManagers) {
738 // update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility
739 mSettingsStore.setLocationProviderAllowed(manager.getName(),
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800740 manager.isUseable(newUserId), newUserId);
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800741
742 manager.onUseableChangedLocked(oldUserId);
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800743 manager.onUseableChangedLocked(newUserId);
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800744 }
Victoria Lease38389b62012-09-30 11:44:22 -0700745 }
746
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700747 /**
748 * Location provider manager, manages a LocationProvider.
749 */
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800750 class LocationProviderManager implements MockableLocationProvider.Listener {
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700751
752 private final String mName;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700753
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800754 // acquiring mLock makes operations on mProvider atomic, but is otherwise unnecessary
755 protected final MockableLocationProvider mProvider;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700756
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800757 // useable state for parent user ids, no entry implies false. location state is only kept
758 // for parent user ids, the location state for a profile user id is assumed to be the same
759 // as for the parent. if querying this structure, ensure that the user id being used is a
760 // parent id or the results may be incorrect.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800761 @GuardedBy("mLock")
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800762 private final SparseArray<Boolean> mUseable;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700763
Soonil Nagarkar3f128402019-12-12 08:31:27 -0800764 private LocationProviderManager(String name) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800765 mName = name;
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800766 mUseable = new SparseArray<>(1);
Soonil Nagarkar42da1b12019-01-22 11:29:27 -0800767
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800768 // initialize last since this lets our reference escape
769 mProvider = new MockableLocationProvider(mContext, mLock, this);
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800770
771 // we can assume all users start with unuseable location state since the initial state
772 // of all providers is disabled. no need to initialize mUseable further.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800773 }
774
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700775 public String getName() {
776 return mName;
777 }
778
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800779 public boolean hasProvider() {
780 return mProvider.getProvider() != null;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700781 }
782
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800783 public void setRealProvider(AbstractLocationProvider provider) {
784 mProvider.setRealProvider(provider);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800785 }
786
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800787 public void setMockProvider(@Nullable MockProvider provider) {
788 mProvider.setMockProvider(provider);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800789 }
790
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800791 public Set<String> getPackages() {
792 return mProvider.getState().providerPackageNames;
793 }
794
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700795 @Nullable
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800796 public ProviderProperties getProperties() {
797 return mProvider.getState().properties;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700798 }
799
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800800 public void setMockProviderEnabled(boolean enabled) {
801 synchronized (mLock) {
802 if (!mProvider.isMock()) {
803 throw new IllegalArgumentException(mName + " provider is not a test provider");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800804 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800805
806 mProvider.setMockProviderEnabled(enabled);
807 }
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700808 }
809
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800810 public void setMockProviderLocation(Location location) {
811 synchronized (mLock) {
812 if (!mProvider.isMock()) {
813 throw new IllegalArgumentException(mName + " provider is not a test provider");
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700814 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800815
816 String locationProvider = location.getProvider();
817 if (!TextUtils.isEmpty(locationProvider) && !mName.equals(locationProvider)) {
818 // The location has an explicit provider that is different from the mock
819 // provider name. The caller may be trying to fool us via b/33091107.
820 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
821 mName + "!=" + locationProvider);
822 }
823
824 mProvider.setMockProviderLocation(location);
825 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700826 }
827
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800828 public List<LocationRequest> getMockProviderRequests() {
829 synchronized (mLock) {
830 if (!mProvider.isMock()) {
831 throw new IllegalArgumentException(mName + " provider is not a test provider");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800832 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800833
834 return mProvider.getCurrentRequest().locationRequests;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800835 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800836 }
837
838 public void setRequest(ProviderRequest request) {
839 mProvider.setRequest(request);
840 }
841
842 public void sendExtraCommand(int uid, int pid, String command, Bundle extras) {
843 mProvider.sendExtraCommand(uid, pid, command, extras);
844 }
845
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800846 @GuardedBy("mLock")
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700847 @Override
848 public void onReportLocation(Location location) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800849 // don't validate mock locations
850 if (!location.isFromMockProvider()) {
851 if (location.getLatitude() == 0 && location.getLongitude() == 0) {
852 Slog.w(TAG, "blocking 0,0 location from " + mName + " provider");
853 return;
854 }
Soonil Nagarkar7fc24c62019-10-18 17:32:38 -0700855 }
856
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800857 handleLocationChangedLocked(location, this);
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700858 }
859
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800860 @GuardedBy("mLock")
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700861 @Override
862 public void onReportLocation(List<Location> locations) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700863 if (mGnssManagerService == null) {
864 return;
865 }
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700866
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800867 if (!GPS_PROVIDER.equals(mName) || !isUseable()) {
868 Slog.w(TAG, "reportLocationBatch() called without user permission");
869 return;
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700870 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800871
872 mGnssManagerService.onReportLocation(locations);
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700873 }
874
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800875 @GuardedBy("mLock")
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700876 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800877 public void onStateChanged(State oldState, State newState) {
878 if (oldState.enabled != newState.enabled) {
879 // it would be more correct to call this for all users, but we know this can
880 // only affect the current user since providers are disabled for non-current
881 // users
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800882 onUseableChangedLocked(mUserInfoStore.getCurrentUserId());
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700883 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700884 }
885
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800886 public boolean isUseable() {
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800887 return isUseable(mUserInfoStore.getCurrentUserId());
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800888 }
889
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800890 public boolean isUseable(int userId) {
Soonil Nagarkar66c0bac2019-01-15 13:36:44 -0800891 synchronized (mLock) {
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800892 // normalize user id to always refer to parent since profile state is always the
893 // same as parent state
894 userId = mUserInfoStore.getParentUserId(userId);
895
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800896 return mUseable.get(userId, Boolean.FALSE);
Soonil Nagarkar66c0bac2019-01-15 13:36:44 -0800897 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700898 }
899
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800900 @GuardedBy("mLock")
Soonil Nagarkar57f4b7b2019-12-09 10:19:18 -0800901 public void onUseableChangedLocked(int userId) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800902 if (userId == UserHandle.USER_NULL) {
903 // only used during initialization - we don't care about the null user
904 return;
905 }
906
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800907 // normalize user id to always refer to parent since profile state is always the same
908 // as parent state
909 userId = mUserInfoStore.getParentUserId(userId);
910
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800911 // if any property that contributes to "useability" here changes state, it MUST result
912 // in a direct or indrect call to onUseableChangedLocked. this allows the provider to
913 // guarantee that it will always eventually reach the correct state.
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800914 boolean useable = (userId == mUserInfoStore.getCurrentUserId())
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800915 && mSettingsStore.isLocationEnabled(userId) && mProvider.getState().enabled;
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800916
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800917 if (useable == isUseable(userId)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800918 return;
919 }
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800920
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800921 mUseable.put(userId, useable);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800922
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800923 if (D) {
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800924 Log.d(TAG, "[u" + userId + "] " + mName + " provider useable = " + useable);
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800925 }
926
Soonil Nagarkar57f4b7b2019-12-09 10:19:18 -0800927 // fused and passive provider never get public updates for legacy reasons
928 if (!FUSED_PROVIDER.equals(mName) && !PASSIVE_PROVIDER.equals(mName)) {
929 // update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800930 mSettingsStore.setLocationProviderAllowed(mName, useable, userId);
Soonil Nagarkar57f4b7b2019-12-09 10:19:18 -0800931
932 Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION);
933 intent.putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName);
934 intent.putExtra(LocationManager.EXTRA_PROVIDER_ENABLED, useable);
935 mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
936 }
937
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800938 if (!useable) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800939 // If any provider has been disabled, clear all last locations for all
940 // providers. This is to be on the safe side in case a provider has location
941 // derived from this disabled provider.
942 mLastLocation.clear();
943 mLastLocationCoarseInterval.clear();
944 }
945
946 updateProviderUseableLocked(this);
947 }
Soonil Nagarkar9ec01852020-01-10 13:42:38 -0800948
949 public void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
950 synchronized (mLock) {
951 pw.print(mName + " provider");
952 if (mProvider.isMock()) {
953 pw.print(" [mock]");
954 }
955 pw.println(":");
956
957 pw.increaseIndent();
958
959 boolean useable = isUseable();
960 pw.println("useable=" + useable);
961 if (!useable) {
962 pw.println("enabled=" + mProvider.getState().enabled);
963 }
964
965 pw.println("properties=" + mProvider.getState().properties);
966 }
967
968 mProvider.dump(fd, pw, args);
969
970 pw.decreaseIndent();
971 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800972 }
973
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800974 class PassiveLocationProviderManager extends LocationProviderManager {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800975
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800976 private PassiveLocationProviderManager() {
977 super(PASSIVE_PROVIDER);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800978 }
979
980 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800981 public void setRealProvider(AbstractLocationProvider provider) {
982 Preconditions.checkArgument(provider instanceof PassiveProvider);
983 super.setRealProvider(provider);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800984 }
985
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800986 @Override
987 public void setMockProvider(@Nullable MockProvider provider) {
988 if (provider != null) {
989 throw new IllegalArgumentException("Cannot mock the passive provider");
990 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800991 }
992
Soonil Nagarkar8df02f42020-01-08 13:23:26 -0800993 public void updateLocation(Location location) {
994 synchronized (mLock) {
995 PassiveProvider passiveProvider = (PassiveProvider) mProvider.getProvider();
996 Preconditions.checkState(passiveProvider != null);
997
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800998 long identity = Binder.clearCallingIdentity();
999 try {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001000 passiveProvider.updateLocation(location);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001001 } finally {
1002 Binder.restoreCallingIdentity(identity);
Soonil Nagarkar68257742019-01-09 19:42:34 +00001003 }
1004 }
1005 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001006 }
1007
Victoria Lease38389b62012-09-30 11:44:22 -07001008 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009 * A wrapper class holding either an ILocationListener or a PendingIntent to receive
1010 * location updates.
1011 */
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001012 private final class Receiver extends LocationManagerServiceUtils.LinkedListenerBase implements
1013 PendingIntent.OnFinished {
Yu-Han Yang24189822018-07-11 15:24:11 -07001014 private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001015 private final int mAllowedResolutionLevel; // resolution level allowed to receiver
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001016
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001017 private final ILocationListener mListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 final PendingIntent mPendingIntent;
David Christie82edc9b2013-07-19 11:31:42 -07001019 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001020 private final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
1021 private final Object mKey;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001022
gomo48f1a642017-11-10 20:35:46 -08001023 final HashMap<String, UpdateRecord> mUpdateRecords = new HashMap<>();
Nick Pellyf1be6862012-05-15 10:53:42 -07001024
David Christie0b837452013-07-29 16:02:13 -07001025 // True if app ops has started monitoring this receiver for locations.
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001026 private boolean mOpMonitoring;
David Christie0b837452013-07-29 16:02:13 -07001027 // True if app ops has started monitoring this receiver for high power (gps) locations.
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001028 private boolean mOpHighPowerMonitoring;
1029 private int mPendingBroadcasts;
Victoria Lease0aa28602013-05-29 15:28:26 -07001030 PowerManager.WakeLock mWakeLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001032 private Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001033 String packageName, @Nullable String featureId, WorkSource workSource,
1034 boolean hideFromAppOps, @NonNull String listenerIdentifier) {
1035 super(new CallerIdentity(uid, pid, packageName, featureId, listenerIdentifier),
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001036 "LocationListener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001037 mListener = listener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 mPendingIntent = intent;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001039 if (listener != null) {
1040 mKey = listener.asBinder();
1041 } else {
1042 mKey = intent;
1043 }
Victoria Lease37425c32012-10-16 16:08:48 -07001044 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
Narayan Kamath32684dd2018-01-08 17:32:51 +00001045 if (workSource != null && workSource.isEmpty()) {
David Christie82edc9b2013-07-19 11:31:42 -07001046 workSource = null;
1047 }
1048 mWorkSource = workSource;
David Christie40e57822013-07-30 11:36:48 -07001049 mHideFromAppOps = hideFromAppOps;
Victoria Lease0aa28602013-05-29 15:28:26 -07001050
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001051 updateMonitoring(true);
1052
Victoria Lease0aa28602013-05-29 15:28:26 -07001053 // construct/configure wakelock
1054 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
David Christie82edc9b2013-07-19 11:31:42 -07001055 if (workSource == null) {
Anil Admal08b96122019-01-30 16:55:05 -08001056 workSource = new WorkSource(mCallerIdentity.mUid, mCallerIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001057 }
1058 mWakeLock.setWorkSource(workSource);
Yu-Han Yang24189822018-07-11 15:24:11 -07001059
1060 // For a non-reference counted wakelock, each acquire will reset the timeout, and we
1061 // only need to release it once.
1062 mWakeLock.setReferenceCounted(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 }
1064
1065 @Override
1066 public boolean equals(Object otherObj) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001067 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001068 }
1069
1070 @Override
1071 public int hashCode() {
1072 return mKey.hashCode();
1073 }
Mike Lockwood3681f262009-05-12 10:52:03 -04001074
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001075 @Override
1076 public String toString() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001077 StringBuilder s = new StringBuilder();
1078 s.append("Reciever[");
1079 s.append(Integer.toHexString(System.identityHashCode(this)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001080 if (mListener != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001081 s.append(" listener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001083 s.append(" intent");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001085 for (String p : mUpdateRecords.keySet()) {
1086 s.append(" ").append(mUpdateRecords.get(p).toString());
1087 }
Wei Wangdd070f22018-06-21 11:29:40 -07001088 s.append(" monitoring location: ").append(mOpMonitoring);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001089 s.append("]");
1090 return s.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 }
1092
David Christie15b31912013-08-13 15:54:32 -07001093 /**
1094 * Update AppOp monitoring for this receiver.
1095 *
1096 * @param allow If true receiver is currently active, if false it's been removed.
1097 */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001098 public void updateMonitoring(boolean allow) {
David Christie40e57822013-07-30 11:36:48 -07001099 if (mHideFromAppOps) {
1100 return;
1101 }
1102
David Christie15b31912013-08-13 15:54:32 -07001103 boolean requestingLocation = false;
1104 boolean requestingHighPowerLocation = false;
1105 if (allow) {
1106 // See if receiver has any enabled update records. Also note if any update records
1107 // are high power (has a high power provider with an interval under a threshold).
1108 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001109 LocationProviderManager manager = getLocationProviderManager(
Soonil Nagarkar3f128402019-12-12 08:31:27 -08001110 updateRecord.mProvider);
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001111 if (manager == null) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001112 continue;
1113 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001114 if (!manager.isUseable() && !isSettingsExemptLocked(updateRecord)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001115 continue;
1116 }
1117
1118 requestingLocation = true;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001119 ProviderProperties properties = manager.getProperties();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001120 if (properties != null
1121 && properties.mPowerRequirement == Criteria.POWER_HIGH
1122 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
1123 requestingHighPowerLocation = true;
1124 break;
David Christie15b31912013-08-13 15:54:32 -07001125 }
1126 }
1127 }
1128
David Christie0b837452013-07-29 16:02:13 -07001129 // First update monitoring of any location request (including high power).
David Christie15b31912013-08-13 15:54:32 -07001130 mOpMonitoring = updateMonitoring(
1131 requestingLocation,
1132 mOpMonitoring,
David Christie0b837452013-07-29 16:02:13 -07001133 AppOpsManager.OP_MONITOR_LOCATION);
1134
1135 // Now update monitoring of high power requests only.
David Christiec750c1f2013-08-08 12:56:57 -07001136 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
David Christie15b31912013-08-13 15:54:32 -07001137 mOpHighPowerMonitoring = updateMonitoring(
1138 requestingHighPowerLocation,
1139 mOpHighPowerMonitoring,
David Christie0b837452013-07-29 16:02:13 -07001140 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
David Christiec750c1f2013-08-08 12:56:57 -07001141 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
David Christie15b31912013-08-13 15:54:32 -07001142 // Send an intent to notify that a high power request has been added/removed.
David Christiec750c1f2013-08-08 12:56:57 -07001143 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
1144 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
1145 }
David Christie0b837452013-07-29 16:02:13 -07001146 }
1147
1148 /**
1149 * Update AppOps monitoring for a single location request and op type.
1150 *
gomo48f1a642017-11-10 20:35:46 -08001151 * @param allowMonitoring True if monitoring is allowed for this request/op.
David Christie0b837452013-07-29 16:02:13 -07001152 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
gomo48f1a642017-11-10 20:35:46 -08001153 * @param op AppOps code for the op to update.
David Christie0b837452013-07-29 16:02:13 -07001154 * @return True if monitoring is on for this request/op after updating.
1155 */
1156 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
1157 int op) {
1158 if (!currentlyMonitoring) {
1159 if (allowMonitoring) {
Anil Admal08b96122019-01-30 16:55:05 -08001160 return mAppOps.startOpNoThrow(op, mCallerIdentity.mUid,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001161 mCallerIdentity.mPackageName, false, mCallerIdentity.mFeatureId, null)
1162 == AppOpsManager.MODE_ALLOWED;
David Christie0b837452013-07-29 16:02:13 -07001163 }
1164 } else {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001165 if (!allowMonitoring
Wei Wang16276a42019-02-04 18:23:31 -08001166 || mAppOps.checkOpNoThrow(op, mCallerIdentity.mUid,
Anil Admal08b96122019-01-30 16:55:05 -08001167 mCallerIdentity.mPackageName) != AppOpsManager.MODE_ALLOWED) {
1168 mAppOps.finishOp(op, mCallerIdentity.mUid, mCallerIdentity.mPackageName);
David Christie0b837452013-07-29 16:02:13 -07001169 return false;
1170 }
1171 }
1172
1173 return currentlyMonitoring;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001174 }
1175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001176 public boolean isListener() {
1177 return mListener != null;
1178 }
1179
1180 public boolean isPendingIntent() {
1181 return mPendingIntent != null;
1182 }
1183
1184 public ILocationListener getListener() {
1185 if (mListener != null) {
1186 return mListener;
1187 }
1188 throw new IllegalStateException("Request for non-existent listener");
1189 }
1190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001191 public boolean callLocationChangedLocked(Location location) {
1192 if (mListener != null) {
1193 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001194 mListener.onLocationChanged(new Location(location));
1195 // call this after broadcasting so we do not increment
1196 // if we throw an exception.
1197 incrementPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001198 } catch (RemoteException e) {
1199 return false;
1200 }
1201 } else {
1202 Intent locationChanged = new Intent();
gomo48f1a642017-11-10 20:35:46 -08001203 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED,
1204 new Location(location));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001206 mPendingIntent.send(mContext, 0, locationChanged, this, mHandler,
1207 getResolutionPermission(mAllowedResolutionLevel),
1208 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
1209 // call this after broadcasting so we do not increment
1210 // if we throw an exception.
1211 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001212 } catch (PendingIntent.CanceledException e) {
1213 return false;
1214 }
1215 }
1216 return true;
1217 }
1218
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001219 private boolean callProviderEnabledLocked(String provider, boolean enabled) {
David Christie15b31912013-08-13 15:54:32 -07001220 // First update AppOp monitoring.
1221 // An app may get/lose location access as providers are enabled/disabled.
1222 updateMonitoring(true);
1223
Mike Lockwood48f17512009-04-23 09:12:08 -07001224 if (mListener != null) {
1225 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001226 if (enabled) {
1227 mListener.onProviderEnabled(provider);
1228 } else {
1229 mListener.onProviderDisabled(provider);
Mike Lockwood48f17512009-04-23 09:12:08 -07001230 }
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001231 // call this after broadcasting so we do not increment
1232 // if we throw an exception.
1233 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001234 } catch (RemoteException e) {
1235 return false;
1236 }
1237 } else {
1238 Intent providerIntent = new Intent();
1239 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1240 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001241 mPendingIntent.send(mContext, 0, providerIntent, this, mHandler,
1242 getResolutionPermission(mAllowedResolutionLevel),
1243 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
1244 // call this after broadcasting so we do not increment
1245 // if we throw an exception.
1246 incrementPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001247 } catch (PendingIntent.CanceledException e) {
1248 return false;
1249 }
1250 }
1251 return true;
1252 }
1253
Soonil Nagarkar39d614a2019-10-31 12:10:31 -07001254 public void callRemovedLocked() {
1255 if (mListener != null) {
1256 try {
1257 mListener.onRemoved();
1258 } catch (RemoteException e) {
1259 // doesn't matter
1260 }
1261 }
1262 }
1263
Nick Pellyf1be6862012-05-15 10:53:42 -07001264 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001265 public void binderDied() {
Anil Admal98d49b72019-02-06 15:26:33 -08001266 if (D) Log.d(TAG, "Remote " + mListenerName + " died.");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001267
Soonil Nagarkar68257742019-01-09 19:42:34 +00001268 synchronized (mLock) {
1269 removeUpdatesLocked(this);
Soonil Nagarkar68257742019-01-09 19:42:34 +00001270 clearPendingBroadcastsLocked();
1271 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001272 }
1273
Nick Pellye0fd6932012-07-11 10:26:13 -07001274 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001275 public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1276 int resultCode, String resultData, Bundle resultExtras) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001277 synchronized (mLock) {
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001278 decrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001279 }
1280 }
1281
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001282 // this must be called while synchronized by caller in a synchronized block
1283 // containing the sending of the broadcaset
1284 private void incrementPendingBroadcastsLocked() {
Yu-Han Yang24189822018-07-11 15:24:11 -07001285 mPendingBroadcasts++;
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001286 // so wakelock calls will succeed
1287 long identity = Binder.clearCallingIdentity();
1288 try {
1289 mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
1290 } finally {
1291 Binder.restoreCallingIdentity(identity);
1292 }
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001293 }
1294
1295 private void decrementPendingBroadcastsLocked() {
1296 if (--mPendingBroadcasts == 0) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001297 // so wakelock calls will succeed
1298 long identity = Binder.clearCallingIdentity();
1299 try {
1300 if (mWakeLock.isHeld()) {
1301 mWakeLock.release();
1302 }
1303 } finally {
1304 Binder.restoreCallingIdentity(identity);
Victoria Lease0aa28602013-05-29 15:28:26 -07001305 }
1306 }
1307 }
1308
1309 public void clearPendingBroadcastsLocked() {
1310 if (mPendingBroadcasts > 0) {
1311 mPendingBroadcasts = 0;
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001312 // so wakelock calls will succeed
1313 long identity = Binder.clearCallingIdentity();
1314 try {
1315 if (mWakeLock.isHeld()) {
1316 mWakeLock.release();
1317 }
1318 } finally {
1319 Binder.restoreCallingIdentity(identity);
Victoria Lease0aa28602013-05-29 15:28:26 -07001320 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001321 }
1322 }
1323 }
1324
Nick Pellye0fd6932012-07-11 10:26:13 -07001325 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001326 public void locationCallbackFinished(ILocationListener listener) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001327 //Do not use getReceiverLocked here as that will add the ILocationListener to
Joshua Bartel080b61b2009-10-05 12:44:46 -04001328 //the receiver list if it is not found. If it is not found then the
1329 //LocationListener was removed when it had a pending broadcast and should
1330 //not be added back.
Soonil Nagarkar68257742019-01-09 19:42:34 +00001331 synchronized (mLock) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001332 Receiver receiver = mReceivers.get(listener.asBinder());
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001333 if (receiver != null) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001334 receiver.decrementPendingBroadcastsLocked();
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001335 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00001336 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001337 }
1338
Lifu Tang82f893d2016-01-21 18:15:33 -08001339 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001340 public int getGnssYearOfHardware() {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001341 return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001342 }
1343
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001344 @Override
Wyatt Riley49097c02018-03-15 09:14:43 -07001345 @Nullable
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001346 public String getGnssHardwareModelName() {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001347 return mGnssManagerService == null ? "" : mGnssManagerService.getGnssHardwareModelName();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001348 }
1349
Wyatt Rileycf879db2017-01-12 13:57:38 -08001350 @Override
1351 public int getGnssBatchSize(String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001352 return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssBatchSize(packageName);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001353 }
1354
Wyatt Rileycf879db2017-01-12 13:57:38 -08001355 @Override
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001356 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001357 String featureId, String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00001358 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001359
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001360 return mGnssManagerService != null && mGnssManagerService.addGnssBatchingCallback(
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001361 callback, packageName, featureId, listenerIdentifier);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001362 }
1363
Wyatt Rileycf879db2017-01-12 13:57:38 -08001364 @Override
1365 public void removeGnssBatchingCallback() {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001366 if (mGnssManagerService != null) mGnssManagerService.removeGnssBatchingCallback();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001367 }
1368
Wyatt Rileycf879db2017-01-12 13:57:38 -08001369 @Override
1370 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001371 return mGnssManagerService != null && mGnssManagerService.startGnssBatch(periodNanos,
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001372 wakeOnFifoFull, packageName);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001373 }
1374
Wyatt Rileycf879db2017-01-12 13:57:38 -08001375 @Override
1376 public void flushGnssBatch(String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001377 if (mGnssManagerService != null) mGnssManagerService.flushGnssBatch(packageName);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001378 }
1379
Wyatt Rileycf879db2017-01-12 13:57:38 -08001380 @Override
1381 public boolean stopGnssBatch() {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001382 return mGnssManagerService != null && mGnssManagerService.stopGnssBatch();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001383 }
1384
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001385 @Nullable
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001386 private LocationProviderManager getLocationProviderManager(String providerName) {
1387 for (LocationProviderManager manager : mProviderManagers) {
1388 if (providerName.equals(manager.getName())) {
1389 return manager;
Soonil Nagarkar68257742019-01-09 19:42:34 +00001390 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001391 }
1392
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001393 return null;
Maggie2a9409e2018-03-21 11:47:28 -07001394 }
1395
Victoria Lease37425c32012-10-16 16:08:48 -07001396 private String getResolutionPermission(int resolutionLevel) {
1397 switch (resolutionLevel) {
1398 case RESOLUTION_LEVEL_FINE:
1399 return android.Manifest.permission.ACCESS_FINE_LOCATION;
1400 case RESOLUTION_LEVEL_COARSE:
1401 return android.Manifest.permission.ACCESS_COARSE_LOCATION;
1402 default:
1403 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001404 }
Victoria Leaseda479c52012-10-15 15:24:16 -07001405 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001406
Victoria Lease37425c32012-10-16 16:08:48 -07001407 private int getAllowedResolutionLevel(int pid, int uid) {
1408 if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001409 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001410 return RESOLUTION_LEVEL_FINE;
1411 } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001412 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001413 return RESOLUTION_LEVEL_COARSE;
1414 } else {
1415 return RESOLUTION_LEVEL_NONE;
Victoria Leaseda479c52012-10-15 15:24:16 -07001416 }
Victoria Lease4fab68b2012-09-13 13:20:59 -07001417 }
1418
Victoria Lease37425c32012-10-16 16:08:48 -07001419 private int getCallerAllowedResolutionLevel() {
1420 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
1421 }
1422
Victoria Lease37425c32012-10-16 16:08:48 -07001423 private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
1424 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Lease4fab68b2012-09-13 13:20:59 -07001425 throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
1426 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 }
1428
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001429 @GuardedBy("mLock")
1430 private int getMinimumResolutionLevelForProviderUseLocked(String provider) {
1431 if (GPS_PROVIDER.equals(provider) || PASSIVE_PROVIDER.equals(provider)) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001432 // gps and passive providers require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001433 return RESOLUTION_LEVEL_FINE;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001434 } else if (NETWORK_PROVIDER.equals(provider) || FUSED_PROVIDER.equals(provider)) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001435 // network and fused providers are ok with COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001436 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001437 } else {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001438 for (LocationProviderManager lp : mProviderManagers) {
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001439 if (!lp.getName().equals(provider)) {
1440 continue;
1441 }
1442
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001443 ProviderProperties properties = lp.getProperties();
Laurent Tu941221c2012-10-04 14:21:52 -07001444 if (properties != null) {
1445 if (properties.mRequiresSatellite) {
1446 // provider requiring satellites require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001447 return RESOLUTION_LEVEL_FINE;
Laurent Tu941221c2012-10-04 14:21:52 -07001448 } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
1449 // provider requiring network and or cell require COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001450 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001451 }
1452 }
1453 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001454 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001455
Victoria Lease37425c32012-10-16 16:08:48 -07001456 return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
Victoria Leaseda479c52012-10-15 15:24:16 -07001457 }
1458
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001459 @GuardedBy("mLock")
1460 private void checkResolutionLevelIsSufficientForProviderUseLocked(int allowedResolutionLevel,
Victoria Lease37425c32012-10-16 16:08:48 -07001461 String providerName) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001462 int requiredResolutionLevel = getMinimumResolutionLevelForProviderUseLocked(providerName);
Victoria Lease37425c32012-10-16 16:08:48 -07001463 if (allowedResolutionLevel < requiredResolutionLevel) {
1464 switch (requiredResolutionLevel) {
1465 case RESOLUTION_LEVEL_FINE:
1466 throw new SecurityException("\"" + providerName + "\" location provider " +
1467 "requires ACCESS_FINE_LOCATION permission.");
1468 case RESOLUTION_LEVEL_COARSE:
1469 throw new SecurityException("\"" + providerName + "\" location provider " +
1470 "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
1471 default:
1472 throw new SecurityException("Insufficient permission for \"" + providerName +
1473 "\" location provider.");
Victoria Leaseda479c52012-10-15 15:24:16 -07001474 }
1475 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001476 }
1477
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001478 public static int resolutionLevelToOp(int allowedResolutionLevel) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001479 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
1480 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001481 return AppOpsManager.OP_COARSE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001482 } else {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001483 return AppOpsManager.OP_FINE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001484 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001485 }
1486 return -1;
1487 }
1488
Wei Wangb86334f2018-07-03 16:33:24 -07001489 private static String resolutionLevelToOpStr(int allowedResolutionLevel) {
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001490 switch (allowedResolutionLevel) {
Wei Wangb86334f2018-07-03 16:33:24 -07001491 case RESOLUTION_LEVEL_COARSE:
1492 return AppOpsManager.OPSTR_COARSE_LOCATION;
1493 case RESOLUTION_LEVEL_FINE:
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001494 // fall through
Wei Wangb86334f2018-07-03 16:33:24 -07001495 case RESOLUTION_LEVEL_NONE:
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001496 // fall through
Wei Wangb86334f2018-07-03 16:33:24 -07001497 default:
1498 // Use the most restrictive ops if not sure.
1499 return AppOpsManager.OPSTR_FINE_LOCATION;
1500 }
1501 }
1502
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001503 private boolean reportLocationAccessNoThrow(int pid, int uid, String packageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001504 @Nullable String featureId, int allowedResolutionLevel, @Nullable String message) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001505 int op = resolutionLevelToOp(allowedResolutionLevel);
1506 if (op >= 0) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001507 if (mAppOps.noteOpNoThrow(op, uid, packageName, featureId, message)
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001508 != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001509 return false;
1510 }
1511 }
David Christieb870dbf2015-06-22 12:42:53 -07001512
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001513 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001514 }
1515
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001516 private boolean checkLocationAccess(int pid, int uid, String packageName,
1517 int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001518 int op = resolutionLevelToOp(allowedResolutionLevel);
1519 if (op >= 0) {
Wei Wang16276a42019-02-04 18:23:31 -08001520 if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001521 return false;
1522 }
1523 }
David Christieb870dbf2015-06-22 12:42:53 -07001524
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001525 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001526 }
1527
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001528 /**
Maggie91e630c2018-01-24 17:31:46 -08001529 * Returns all providers by name, including passive and the ones that are not permitted to
1530 * be accessed by the calling activity or are currently disabled, but excluding fused.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001531 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001532 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001533 public List<String> getAllProviders() {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001534 ArrayList<String> providers = new ArrayList<>(mProviderManagers.size());
1535 for (LocationProviderManager manager : mProviderManagers) {
1536 if (FUSED_PROVIDER.equals(manager.getName())) {
1537 continue;
Maggie91e630c2018-01-24 17:31:46 -08001538 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001539 providers.add(manager.getName());
Maggie91e630c2018-01-24 17:31:46 -08001540 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001541 return providers;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 }
1543
Mike Lockwood03ca2162010-04-01 08:10:09 -07001544 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001545 * Return all providers by name, that match criteria and are optionally
1546 * enabled.
1547 * Can return passive provider, but never returns fused provider.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001548 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001549 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001550 public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
Victoria Lease37425c32012-10-16 16:08:48 -07001551 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001552 synchronized (mLock) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001553 ArrayList<String> providers = new ArrayList<>(mProviderManagers.size());
1554 for (LocationProviderManager manager : mProviderManagers) {
1555 String name = manager.getName();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001556 if (FUSED_PROVIDER.equals(name)) {
1557 continue;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001558 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001559 if (allowedResolutionLevel < getMinimumResolutionLevelForProviderUseLocked(name)) {
1560 continue;
1561 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001562 if (enabledOnly && !manager.isUseable()) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001563 continue;
1564 }
1565 if (criteria != null
1566 && !android.location.LocationProvider.propertiesMeetCriteria(
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001567 name, manager.getProperties(), criteria)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001568 continue;
1569 }
1570 providers.add(name);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001571 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001572 return providers;
Soonil Nagarkar68257742019-01-09 19:42:34 +00001573 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001574 }
1575
1576 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001577 * Return the name of the best provider given a Criteria object.
1578 * This method has been deprecated from the public API,
Victoria Lease8dbb6342012-09-21 16:55:53 -07001579 * and the whole LocationProvider (including #meetsCriteria)
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001580 * has been deprecated as well. So this method now uses
1581 * some simplified logic.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001582 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001583 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001584 public String getBestProvider(Criteria criteria, boolean enabledOnly) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001585 List<String> providers = getProviders(criteria, enabledOnly);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001586 if (providers.isEmpty()) {
1587 providers = getProviders(null, enabledOnly);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08001588 }
1589
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001590 if (!providers.isEmpty()) {
1591 if (providers.contains(GPS_PROVIDER)) {
1592 return GPS_PROVIDER;
1593 } else if (providers.contains(NETWORK_PROVIDER)) {
1594 return NETWORK_PROVIDER;
1595 } else {
1596 return providers.get(0);
1597 }
1598 }
1599
Mike Lockwood03ca2162010-04-01 08:10:09 -07001600 return null;
1601 }
1602
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001603 @GuardedBy("mLock")
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001604 private void updateProviderUseableLocked(LocationProviderManager manager) {
1605 boolean useable = manager.isUseable();
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001607 ArrayList<Receiver> deadReceivers = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07001608
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001609 ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 if (records != null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001611 for (UpdateRecord record : records) {
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08001612 if (!mUserInfoStore.isCurrentUserOrProfile(
Anil Admal08b96122019-01-30 16:55:05 -08001613 UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001614 continue;
1615 }
1616
Kweku Adams5e0052b2019-02-22 15:17:52 -08001617 // requests that ignore location settings will never provide notifications
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001618 if (isSettingsExemptLocked(record)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001619 continue;
1620 }
1621
1622 // Sends a notification message to the receiver
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001623 if (!record.mReceiver.callProviderEnabledLocked(manager.getName(), useable)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001624 if (deadReceivers == null) {
1625 deadReceivers = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001626 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001627 deadReceivers.add(record.mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001628 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 }
1630 }
1631
1632 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001633 for (int i = deadReceivers.size() - 1; i >= 0; i--) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00001634 removeUpdatesLocked(deadReceivers.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635 }
1636 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001637
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001638 applyRequirementsLocked(manager);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001639 }
1640
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001641 @GuardedBy("mLock")
1642 private void applyRequirementsLocked(String providerName) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001643 LocationProviderManager manager = getLocationProviderManager(providerName);
1644 if (manager != null) {
1645 applyRequirementsLocked(manager);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001646 }
1647 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001648
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001649 @GuardedBy("mLock")
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001650 private void applyRequirementsLocked(LocationProviderManager manager) {
1651 ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName());
1652 ProviderRequest.Builder providerRequest = new ProviderRequest.Builder();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001653
Soonil Nagarkar04cff6c2019-03-19 11:29:52 -07001654 // if provider is not active, it should not respond to requests
1655
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001656 if (mProviderManagers.contains(manager) && records != null && !records.isEmpty()) {
Kweku Adams5e0052b2019-02-22 15:17:52 -08001657 long backgroundThrottleInterval;
1658
1659 long identity = Binder.clearCallingIdentity();
1660 try {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07001661 backgroundThrottleInterval = mSettingsStore.getBackgroundThrottleIntervalMs();
Kweku Adams5e0052b2019-02-22 15:17:52 -08001662 } finally {
1663 Binder.restoreCallingIdentity(identity);
1664 }
1665
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001666 ArrayList<LocationRequest> requests = new ArrayList<>(records.size());
1667
Kweku Adams5e0052b2019-02-22 15:17:52 -08001668 final boolean isForegroundOnlyMode =
Kweku Adams4fb074e2019-02-01 16:03:27 -08001669 mBatterySaverMode == PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
1670 final boolean shouldThrottleRequests =
1671 mBatterySaverMode
1672 == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF
1673 && !mPowerManager.isInteractive();
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001674 // initialize the low power mode to true and set to false if any of the records requires
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001675 providerRequest.setLowPowerMode(true);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001676 for (UpdateRecord record : records) {
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08001677 if (!mUserInfoStore.isCurrentUserOrProfile(
Anil Admal08b96122019-01-30 16:55:05 -08001678 UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001679 continue;
1680 }
1681 if (!checkLocationAccess(
Anil Admal08b96122019-01-30 16:55:05 -08001682 record.mReceiver.mCallerIdentity.mPid,
1683 record.mReceiver.mCallerIdentity.mUid,
1684 record.mReceiver.mCallerIdentity.mPackageName,
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001685 record.mReceiver.mAllowedResolutionLevel)) {
1686 continue;
1687 }
Kweku Adams4fb074e2019-02-01 16:03:27 -08001688 final boolean isBatterySaverDisablingLocation = shouldThrottleRequests
1689 || (isForegroundOnlyMode && !record.mIsForegroundUid);
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001690 if (!manager.isUseable() || isBatterySaverDisablingLocation) {
Soonil Nagarkar35c3b912019-01-31 10:31:24 -08001691 if (isSettingsExemptLocked(record)) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001692 providerRequest.setLocationSettingsIgnored(true);
1693 providerRequest.setLowPowerMode(false);
Soonil Nagarkar35c3b912019-01-31 10:31:24 -08001694 } else {
1695 continue;
1696 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001697 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001698
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001699 LocationRequest locationRequest = record.mRealRequest;
1700 long interval = locationRequest.getInterval();
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001701
Soonil Nagarkar509580f2019-02-06 15:57:26 -08001702
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001703 // if we're forcing location, don't apply any throttling
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001704 if (!providerRequest.isLocationSettingsIgnored() && !isThrottlingExemptLocked(
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001705 record.mReceiver.mCallerIdentity)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001706 if (!record.mIsForegroundUid) {
1707 interval = Math.max(interval, backgroundThrottleInterval);
Victoria Leaseb711d572012-10-02 13:14:11 -07001708 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001709 if (interval != locationRequest.getInterval()) {
1710 locationRequest = new LocationRequest(locationRequest);
1711 locationRequest.setInterval(interval);
1712 }
1713 }
1714
1715 record.mRequest = locationRequest;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001716 requests.add(locationRequest);
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001717 if (!locationRequest.isLowPowerMode()) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001718 providerRequest.setLowPowerMode(false);
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001719 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001720 if (interval < providerRequest.getInterval()) {
1721 providerRequest.setInterval(interval);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001722 }
1723 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001724
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001725 providerRequest.setLocationRequests(requests);
1726
1727 if (providerRequest.getInterval() < Long.MAX_VALUE) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001728 // calculate who to blame for power
1729 // This is somewhat arbitrary. We pick a threshold interval
1730 // that is slightly higher that the minimum interval, and
1731 // spread the blame across all applications with a request
1732 // under that threshold.
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001733 // TODO: overflow
1734 long thresholdInterval = (providerRequest.getInterval() + 1000) * 3 / 2;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001735 for (UpdateRecord record : records) {
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08001736 if (mUserInfoStore.isCurrentUserOrProfile(
Anil Admal08b96122019-01-30 16:55:05 -08001737 UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001738 LocationRequest locationRequest = record.mRequest;
Svet Ganove998c732016-06-10 00:12:38 -07001739
1740 // Don't assign battery blame for update records whose
1741 // client has no permission to receive location data.
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001742 if (!providerRequest.getLocationRequests().contains(locationRequest)) {
Svet Ganove998c732016-06-10 00:12:38 -07001743 continue;
1744 }
1745
Victoria Leaseb711d572012-10-02 13:14:11 -07001746 if (locationRequest.getInterval() <= thresholdInterval) {
David Christiee55c9682013-08-22 10:10:34 -07001747 if (record.mReceiver.mWorkSource != null
Narayan Kamath32684dd2018-01-08 17:32:51 +00001748 && isValidWorkSource(record.mReceiver.mWorkSource)) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001749 providerRequest.getWorkSource().add(record.mReceiver.mWorkSource);
David Christie82edc9b2013-07-19 11:31:42 -07001750 } else {
Narayan Kamath32684dd2018-01-08 17:32:51 +00001751 // Assign blame to caller if there's no WorkSource associated with
1752 // the request or if it's invalid.
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001753 providerRequest.getWorkSource().add(
Anil Admal08b96122019-01-30 16:55:05 -08001754 record.mReceiver.mCallerIdentity.mUid,
1755 record.mReceiver.mCallerIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001756 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001757 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001758 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001759 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001760 }
1761 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001762
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08001763 manager.setRequest(providerRequest.build());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001764 }
1765
Narayan Kamath32684dd2018-01-08 17:32:51 +00001766 /**
1767 * Whether a given {@code WorkSource} associated with a Location request is valid.
1768 */
1769 private static boolean isValidWorkSource(WorkSource workSource) {
1770 if (workSource.size() > 0) {
1771 // If the WorkSource has one or more non-chained UIDs, make sure they're accompanied
1772 // by tags.
Suprabh Shuklaf7cffa72019-11-08 17:03:03 -08001773 return workSource.getPackageName(0) != null;
Narayan Kamath32684dd2018-01-08 17:32:51 +00001774 } else {
1775 // For now, make sure callers have supplied an attribution tag for use with
1776 // AppOpsManager. This might be relaxed in the future.
Suprabh Shuklaf7cffa72019-11-08 17:03:03 -08001777 final List<WorkChain> workChains = workSource.getWorkChains();
Narayan Kamath32684dd2018-01-08 17:32:51 +00001778 return workChains != null && !workChains.isEmpty() &&
1779 workChains.get(0).getAttributionTag() != null;
1780 }
1781 }
1782
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001783 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001784 public String[] getBackgroundThrottlingWhitelist() {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07001785 return mSettingsStore.getBackgroundThrottlePackageWhitelist().toArray(new String[0]);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001786 }
1787
Soonil Nagarkar5140e4f2019-02-14 17:21:33 -08001788 @Override
1789 public String[] getIgnoreSettingsWhitelist() {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07001790 return mSettingsStore.getIgnoreSettingsPackageWhitelist().toArray(new String[0]);
Soonil Nagarkar5140e4f2019-02-14 17:21:33 -08001791 }
1792
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001793 @GuardedBy("mLock")
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001794 public boolean isThrottlingExemptLocked(CallerIdentity callerIdentity) {
Anil Admal08b96122019-01-30 16:55:05 -08001795 if (callerIdentity.mUid == Process.SYSTEM_UID) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001796 return true;
1797 }
1798
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07001799 if (mSettingsStore.getBackgroundThrottlePackageWhitelist().contains(
1800 callerIdentity.mPackageName)) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001801 return true;
1802 }
1803
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001804 return isProviderPackage(callerIdentity.mPackageName);
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001805
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001806 }
1807
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001808 @GuardedBy("mLock")
1809 private boolean isSettingsExemptLocked(UpdateRecord record) {
1810 if (!record.mRealRequest.isLocationSettingsIgnored()) {
1811 return false;
1812 }
1813
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07001814 if (mSettingsStore.getIgnoreSettingsPackageWhitelist().contains(
Anil Admal08b96122019-01-30 16:55:05 -08001815 record.mReceiver.mCallerIdentity.mPackageName)) {
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001816 return true;
1817 }
1818
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001819 return isProviderPackage(record.mReceiver.mCallerIdentity.mPackageName);
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001820
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001821 }
1822
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001823 private class UpdateRecord {
1824 final String mProvider;
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001825 private final LocationRequest mRealRequest; // original request from client
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001826 LocationRequest mRequest; // possibly throttled version of the request
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001827 private final Receiver mReceiver;
1828 private boolean mIsForegroundUid;
1829 private Location mLastFixBroadcast;
Soonil Nagarkarae6ce772019-05-01 13:16:17 -07001830 private Throwable mStackTrace; // for debugging only
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08001831 private long mExpirationRealtimeMs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832
1833 /**
1834 * Note: must be constructed with lock held.
1835 */
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001836 private UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08001837 mExpirationRealtimeMs = request.getExpirationRealtimeMs(SystemClock.elapsedRealtime());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001838 mProvider = provider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07001839 mRealRequest = request;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001840 mRequest = request;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001841 mReceiver = receiver;
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001842 mIsForegroundUid =
1843 LocationManagerServiceUtils.isImportanceForeground(
1844 mActivityManager.getPackageImportance(
1845 mReceiver.mCallerIdentity.mPackageName));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001846
Soonil Nagarkarae6ce772019-05-01 13:16:17 -07001847 if (D && receiver.mCallerIdentity.mPid == Process.myPid()) {
1848 mStackTrace = new Throwable();
1849 }
1850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001851 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1852 if (records == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001853 records = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001854 mRecordsByProvider.put(provider, records);
1855 }
1856 if (!records.contains(this)) {
1857 records.add(this);
1858 }
David Christie2ff96af2014-01-30 16:09:37 -08001859
1860 // Update statistics for historical location requests by package/provider
1861 mRequestStatistics.startRequesting(
Anil Admal08b96122019-01-30 16:55:05 -08001862 mReceiver.mCallerIdentity.mPackageName, provider, request.getInterval(),
Wyatt Rileyf7075e02018-04-12 17:54:26 -07001863 mIsForegroundUid);
1864 }
1865
1866 /**
1867 * Method to be called when record changes foreground/background
1868 */
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001869 private void updateForeground(boolean isForeground) {
Wyatt Rileyf7075e02018-04-12 17:54:26 -07001870 mIsForegroundUid = isForeground;
1871 mRequestStatistics.updateForeground(
Anil Admal08b96122019-01-30 16:55:05 -08001872 mReceiver.mCallerIdentity.mPackageName, mProvider, isForeground);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001873 }
1874
1875 /**
David Christie2ff96af2014-01-30 16:09:37 -08001876 * Method to be called when a record will no longer be used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001877 */
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001878 private void disposeLocked(boolean removeReceiver) {
Hongyi Zhang700137e2019-05-23 21:19:36 -07001879 String packageName = mReceiver.mCallerIdentity.mPackageName;
1880 mRequestStatistics.stopRequesting(packageName, mProvider);
1881
1882 mLocationUsageLogger.logLocationApiUsage(
1883 LocationStatsEnums.USAGE_ENDED,
1884 LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
1885 packageName,
1886 mRealRequest,
1887 mReceiver.isListener(),
1888 mReceiver.isPendingIntent(),
Hongyi Zhang0e9ea752019-06-09 22:49:25 -07001889 /* geofence= */ null,
Hongyi Zhang700137e2019-05-23 21:19:36 -07001890 mActivityManager.getPackageImportance(packageName));
David Christie2ff96af2014-01-30 16:09:37 -08001891
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001892 // remove from mRecordsByProvider
1893 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
1894 if (globalRecords != null) {
1895 globalRecords.remove(this);
1896 }
1897
1898 if (!removeReceiver) return; // the caller will handle the rest
1899
1900 // remove from Receiver#mUpdateRecords
1901 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001902 receiverRecords.remove(this.mProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001903
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001904 // and also remove the Receiver if it has no more update records
1905 if (receiverRecords.size() == 0) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00001906 removeUpdatesLocked(mReceiver);
Mike Lockwood3a76fd62009-09-01 07:26:56 -04001907 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001908 }
1909
1910 @Override
1911 public String toString() {
Soonil Nagarkarae6ce772019-05-01 13:16:17 -07001912 StringBuilder b = new StringBuilder("UpdateRecord[");
1913 b.append(mProvider).append(" ");
1914 b.append(mReceiver.mCallerIdentity.mPackageName);
1915 b.append("(").append(mReceiver.mCallerIdentity.mUid);
1916 if (mIsForegroundUid) {
1917 b.append(" foreground");
1918 } else {
1919 b.append(" background");
1920 }
1921 b.append(") ");
1922 b.append(mRealRequest).append(" ").append(mReceiver.mWorkSource);
1923
1924 if (mStackTrace != null) {
1925 ByteArrayOutputStream tmp = new ByteArrayOutputStream();
1926 mStackTrace.printStackTrace(new PrintStream(tmp));
1927 b.append("\n\n").append(tmp.toString()).append("\n");
1928 }
1929
1930 b.append("]");
1931 return b.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001932 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001933 }
1934
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001935 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00001936 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001937 String packageName, @Nullable String featureId, WorkSource workSource,
1938 boolean hideFromAppOps, @NonNull String listenerIdentifier) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001939 IBinder binder = listener.asBinder();
1940 Receiver receiver = mReceivers.get(binder);
1941 if (receiver == null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001942 receiver = new Receiver(listener, null, pid, uid, packageName, featureId, workSource,
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001943 hideFromAppOps, listenerIdentifier);
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001944 if (!receiver.linkToListenerDeathNotificationLocked(
1945 receiver.getListener().asBinder())) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001946 return null;
1947 }
Wen Jingcb3ab222014-03-27 13:42:59 +08001948 mReceivers.put(binder, receiver);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001949 }
1950 return receiver;
1951 }
1952
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001953 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00001954 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001955 @Nullable String featureId, WorkSource workSource, boolean hideFromAppOps,
1956 @NonNull String listenerIdentifier) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001957 Receiver receiver = mReceivers.get(intent);
1958 if (receiver == null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001959 receiver = new Receiver(null, intent, pid, uid, packageName, featureId, workSource,
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001960 hideFromAppOps, listenerIdentifier);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001961 mReceivers.put(intent, receiver);
1962 }
1963 return receiver;
1964 }
1965
Victoria Lease37425c32012-10-16 16:08:48 -07001966 /**
1967 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
1968 * and consistency requirements.
1969 *
1970 * @param request the LocationRequest from which to create a sanitized version
Victoria Lease37425c32012-10-16 16:08:48 -07001971 * @return a version of request that meets the given resolution and consistency requirements
1972 * @hide
1973 */
gomo48f1a642017-11-10 20:35:46 -08001974 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel,
1975 boolean callerHasLocationHardwarePermission) {
Victoria Lease37425c32012-10-16 16:08:48 -07001976 LocationRequest sanitizedRequest = new LocationRequest(request);
gomo48f1a642017-11-10 20:35:46 -08001977 if (!callerHasLocationHardwarePermission) {
1978 // allow setting low power mode only for callers with location hardware permission
1979 sanitizedRequest.setLowPowerMode(false);
1980 }
Victoria Lease37425c32012-10-16 16:08:48 -07001981 if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
1982 switch (sanitizedRequest.getQuality()) {
Victoria Lease09016ab2012-09-16 12:33:15 -07001983 case LocationRequest.ACCURACY_FINE:
Victoria Lease37425c32012-10-16 16:08:48 -07001984 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
Victoria Lease09016ab2012-09-16 12:33:15 -07001985 break;
1986 case LocationRequest.POWER_HIGH:
Victoria Lease37425c32012-10-16 16:08:48 -07001987 sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
Victoria Lease09016ab2012-09-16 12:33:15 -07001988 break;
1989 }
1990 // throttle
Victoria Lease37425c32012-10-16 16:08:48 -07001991 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1992 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001993 }
Victoria Lease37425c32012-10-16 16:08:48 -07001994 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1995 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07001996 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07001997 }
Nick Pelly4e31c4f2012-08-13 19:35:39 -07001998 // make getFastestInterval() the minimum of interval and fastest interval
Victoria Lease37425c32012-10-16 16:08:48 -07001999 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
Soonil Nagarkar397ad582019-01-23 22:47:57 -08002000 sanitizedRequest.setFastestInterval(request.getInterval());
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002001 }
Victoria Lease37425c32012-10-16 16:08:48 -07002002 return sanitizedRequest;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002003 }
2004
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002005 private void checkPackageName(String packageName) {
Nick Pellye0fd6932012-07-11 10:26:13 -07002006 if (packageName == null) {
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002007 throw new SecurityException("invalid package name: " + null);
Nick Pellye0fd6932012-07-11 10:26:13 -07002008 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002009 int uid = Binder.getCallingUid();
Nick Pellye0fd6932012-07-11 10:26:13 -07002010 String[] packages = mPackageManager.getPackagesForUid(uid);
2011 if (packages == null) {
2012 throw new SecurityException("invalid UID " + uid);
2013 }
2014 for (String pkg : packages) {
2015 if (packageName.equals(pkg)) return;
2016 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002017 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002018 }
2019
Nick Pellye0fd6932012-07-11 10:26:13 -07002020 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002021 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002022 PendingIntent intent, String packageName, String featureId,
2023 String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002024 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002025
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002026 synchronized (mLock) {
2027 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2028 checkPackageName(packageName);
2029 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2030 checkResolutionLevelIsSufficientForProviderUseLocked(allowedResolutionLevel,
2031 request.getProvider());
2032 WorkSource workSource = request.getWorkSource();
2033 if (workSource != null && !workSource.isEmpty()) {
2034 mContext.enforceCallingOrSelfPermission(
2035 Manifest.permission.UPDATE_DEVICE_STATS, null);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002036 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002037 boolean hideFromAppOps = request.getHideFromAppOps();
2038 if (hideFromAppOps) {
2039 mContext.enforceCallingOrSelfPermission(
2040 Manifest.permission.UPDATE_APP_OPS_STATS, null);
2041 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002042 if (request.isLocationSettingsIgnored()) {
2043 mContext.enforceCallingOrSelfPermission(
2044 Manifest.permission.WRITE_SECURE_SETTINGS, null);
2045 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002046 boolean callerHasLocationHardwarePermission =
2047 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
2048 == PERMISSION_GRANTED;
2049 LocationRequest sanitizedRequest = createSanitizedRequest(request,
2050 allowedResolutionLevel,
2051 callerHasLocationHardwarePermission);
2052
2053 final int pid = Binder.getCallingPid();
2054 final int uid = Binder.getCallingUid();
2055
2056 long identity = Binder.clearCallingIdentity();
2057 try {
2058
2059 // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2060 // a location.
2061 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
2062
2063 if (intent == null && listener == null) {
2064 throw new IllegalArgumentException("need either listener or intent");
2065 } else if (intent != null && listener != null) {
2066 throw new IllegalArgumentException(
2067 "cannot register both listener and intent");
2068 }
2069
Hongyi Zhang700137e2019-05-23 21:19:36 -07002070 mLocationUsageLogger.logLocationApiUsage(
2071 LocationStatsEnums.USAGE_STARTED,
2072 LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
2073 packageName, request, listener != null, intent != null,
Hongyi Zhang0e9ea752019-06-09 22:49:25 -07002074 /* geofence= */ null,
Hongyi Zhang700137e2019-05-23 21:19:36 -07002075 mActivityManager.getPackageImportance(packageName));
2076
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002077 Receiver receiver;
2078 if (intent != null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002079 receiver = getReceiverLocked(intent, pid, uid, packageName, featureId,
2080 workSource, hideFromAppOps, listenerIdentifier);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002081 } else {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002082 receiver = getReceiverLocked(listener, pid, uid, packageName, featureId,
2083 workSource, hideFromAppOps, listenerIdentifier);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002084 }
2085 requestLocationUpdatesLocked(sanitizedRequest, receiver, uid, packageName);
2086 } finally {
2087 Binder.restoreCallingIdentity(identity);
2088 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002089 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002090 }
2091
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002092 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00002093 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002094 int uid, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002095 // Figure out the provider. Either its explicitly request (legacy use cases), or
2096 // use the fused provider
2097 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2098 String name = request.getProvider();
Victoria Lease09016ab2012-09-16 12:33:15 -07002099 if (name == null) {
2100 throw new IllegalArgumentException("provider name must not be null");
2101 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -07002102
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002103 LocationProviderManager manager = getLocationProviderManager(name);
2104 if (manager == null) {
Victoria Leaseb30f3832013-10-13 12:15:40 -07002105 throw new IllegalArgumentException("provider doesn't exist: " + name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002106 }
2107
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002108 UpdateRecord record = new UpdateRecord(name, request, receiver);
gomo48f1a642017-11-10 20:35:46 -08002109 if (D) {
2110 Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
2111 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
2112 + (record.mIsForegroundUid ? "foreground" : "background")
Anil Admal08b96122019-01-30 16:55:05 -08002113 + (isThrottlingExemptLocked(receiver.mCallerIdentity)
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002114 ? " [whitelisted]" : "") + ")");
gomo48f1a642017-11-10 20:35:46 -08002115 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002116
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002117 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
2118 if (oldRecord != null) {
2119 oldRecord.disposeLocked(false);
2120 }
2121
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002122 if (!manager.isUseable() && !isSettingsExemptLocked(record)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002123 // Notify the listener that updates are currently disabled - but only if the request
2124 // does not ignore location settings
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002125 receiver.callProviderEnabledLocked(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002126 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002127
2128 applyRequirementsLocked(name);
2129
David Christie0b837452013-07-29 16:02:13 -07002130 // Update the monitoring here just in case multiple location requests were added to the
2131 // same receiver (this request may be high power and the initial might not have been).
2132 receiver.updateMonitoring(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002133 }
2134
Nick Pellye0fd6932012-07-11 10:26:13 -07002135 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002136 public void removeUpdates(ILocationListener listener, PendingIntent intent,
Soonil Nagarkar68257742019-01-09 19:42:34 +00002137 String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002138 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002139
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002140 int pid = Binder.getCallingPid();
2141 int uid = Binder.getCallingUid();
2142
2143 if (intent == null && listener == null) {
2144 throw new IllegalArgumentException("need either listener or intent");
2145 } else if (intent != null && listener != null) {
2146 throw new IllegalArgumentException("cannot register both listener and intent");
2147 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002148
Soonil Nagarkar68257742019-01-09 19:42:34 +00002149 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002150 Receiver receiver;
2151 if (intent != null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002152 receiver = getReceiverLocked(intent, pid, uid, packageName, null, null, false, "");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002153 } else {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002154 receiver = getReceiverLocked(listener, pid, uid, packageName, null, null, false,
2155 "");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002156 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002157
Soonil Nagarkar68257742019-01-09 19:42:34 +00002158 long identity = Binder.clearCallingIdentity();
2159 try {
2160 removeUpdatesLocked(receiver);
2161 } finally {
2162 Binder.restoreCallingIdentity(identity);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002163 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002164 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002165 }
2166
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002167 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00002168 private void removeUpdatesLocked(Receiver receiver) {
Dianne Hackborn7ff30112012-11-08 11:12:09 -08002169 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002170
2171 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002172 receiver.unlinkFromListenerDeathNotificationLocked(
2173 receiver.getListener().asBinder());
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08002174 receiver.clearPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002175 }
2176
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07002177 receiver.updateMonitoring(false);
2178
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002179 // Record which providers were associated with this listener
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002180 HashSet<String> providers = new HashSet<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002181 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2182 if (oldRecords != null) {
2183 // Call dispose() on the obsolete update records.
2184 for (UpdateRecord record : oldRecords.values()) {
David Christie2ff96af2014-01-30 16:09:37 -08002185 // Update statistics for historical location requests by package/provider
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002186 record.disposeLocked(false);
2187 }
2188 // Accumulate providers
2189 providers.addAll(oldRecords.keySet());
2190 }
2191
2192 // update provider
2193 for (String provider : providers) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002194 applyRequirementsLocked(provider);
2195 }
2196 }
2197
Nick Pellye0fd6932012-07-11 10:26:13 -07002198 @Override
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002199 public Location getLastLocation(LocationRequest r, String packageName, String featureId) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002200 synchronized (mLock) {
2201 LocationRequest request = r != null ? r : DEFAULT_LOCATION_REQUEST;
2202 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2203 checkPackageName(packageName);
2204 checkResolutionLevelIsSufficientForProviderUseLocked(allowedResolutionLevel,
2205 request.getProvider());
2206 // no need to sanitize this request, as only the provider name is used
Nick Pelly4035f5a2012-08-17 14:43:49 -07002207
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002208 final int pid = Binder.getCallingPid();
2209 final int uid = Binder.getCallingUid();
2210 final long identity = Binder.clearCallingIdentity();
2211 try {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07002212 if (mSettingsStore.isLocationPackageBlacklisted(UserHandle.getUserId(uid),
2213 packageName)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002214 if (D) {
2215 Log.d(TAG, "not returning last loc for blacklisted app: "
2216 + packageName);
2217 }
2218 return null;
gomo48f1a642017-11-10 20:35:46 -08002219 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002220
Soonil Nagarkar68257742019-01-09 19:42:34 +00002221 // Figure out the provider. Either its explicitly request (deprecated API's),
2222 // or use the fused provider
2223 String name = request.getProvider();
2224 if (name == null) name = LocationManager.FUSED_PROVIDER;
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002225 LocationProviderManager manager = getLocationProviderManager(name);
2226 if (manager == null) return null;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002227
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002228 // only the current user or location providers may get location this way
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08002229 if (!mUserInfoStore.isCurrentUserOrProfile(UserHandle.getUserId(uid))
2230 && !isProviderPackage(packageName)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002231 return null;
2232 }
2233
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002234 if (!manager.isUseable()) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002235 return null;
2236 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002237
2238 Location location;
2239 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2240 // Make sure that an app with coarse permissions can't get frequent location
2241 // updates by calling LocationManager.getLastKnownLocation repeatedly.
2242 location = mLastLocationCoarseInterval.get(name);
2243 } else {
2244 location = mLastLocation.get(name);
2245 }
2246 if (location == null) {
2247 return null;
2248 }
2249
2250 // Don't return stale location to apps with foreground-only location permission.
2251 String op = resolutionLevelToOpStr(allowedResolutionLevel);
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002252 long locationAgeMs = TimeUnit.NANOSECONDS.toMillis(
2253 SystemClock.elapsedRealtime() - location.getElapsedRealtimeNanos());
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07002254 if (locationAgeMs > mSettingsStore.getMaxLastLocationAgeMs()
Soonil Nagarkar68257742019-01-09 19:42:34 +00002255 && (mAppOps.unsafeCheckOp(op, uid, packageName)
2256 == AppOpsManager.MODE_FOREGROUND)) {
2257 return null;
2258 }
2259
Wei Wang16276a42019-02-04 18:23:31 -08002260 Location lastLocation = null;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002261 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2262 Location noGPSLocation = location.getExtraLocation(
2263 Location.EXTRA_NO_GPS_LOCATION);
2264 if (noGPSLocation != null) {
Wei Wang16276a42019-02-04 18:23:31 -08002265 lastLocation = new Location(mLocationFudger.getOrCreate(noGPSLocation));
Soonil Nagarkar68257742019-01-09 19:42:34 +00002266 }
2267 } else {
Wei Wang16276a42019-02-04 18:23:31 -08002268 lastLocation = new Location(location);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002269 }
Wei Wang16276a42019-02-04 18:23:31 -08002270 // Don't report location access if there is no last location to deliver.
2271 if (lastLocation != null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002272 if (!reportLocationAccessNoThrow(pid, uid, packageName, featureId,
2273 allowedResolutionLevel, null)) {
Wei Wang16276a42019-02-04 18:23:31 -08002274 if (D) {
2275 Log.d(TAG, "not returning last loc for no op app: " + packageName);
2276 }
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002277 lastLocation = null;
Wei Wang16276a42019-02-04 18:23:31 -08002278 }
2279 }
2280 return lastLocation;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002281 } finally {
2282 Binder.restoreCallingIdentity(identity);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002283 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002284 }
2285 }
2286
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002287 @Override
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002288 public boolean getCurrentLocation(LocationRequest locationRequest,
2289 ICancellationSignal remoteCancellationSignal, ILocationListener listener,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002290 String packageName, String featureId, String listenerIdentifier) {
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002291 // side effect of validating locationRequest and packageName
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002292 Location lastLocation = getLastLocation(locationRequest, packageName, featureId);
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002293 if (lastLocation != null) {
2294 long locationAgeMs = TimeUnit.NANOSECONDS.toMillis(
2295 SystemClock.elapsedRealtimeNanos() - lastLocation.getElapsedRealtimeNanos());
2296
2297 long identity = Binder.clearCallingIdentity();
2298 try {
2299 if (locationAgeMs < MAX_CURRENT_LOCATION_AGE_MS) {
2300 try {
2301 listener.onLocationChanged(lastLocation);
2302 return true;
2303 } catch (RemoteException e) {
2304 Log.w(TAG, e);
2305 return false;
2306 }
2307 }
2308
2309 // packageName already validated by getLastLocation() call above
2310 boolean foreground = LocationManagerServiceUtils.isImportanceForeground(
2311 mActivityManager.getPackageImportance(packageName));
2312 if (!foreground) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07002313 if (locationAgeMs < mSettingsStore.getBackgroundThrottleIntervalMs()) {
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002314 // not allowed to request new locations, so we can't return anything
2315 return false;
2316 }
2317 }
2318 } finally {
2319 Binder.restoreCallingIdentity(identity);
2320 }
2321 }
2322
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002323 requestLocationUpdates(locationRequest, listener, null, packageName, featureId,
2324 listenerIdentifier);
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002325 CancellationSignal cancellationSignal = CancellationSignal.fromTransport(
2326 remoteCancellationSignal);
2327 if (cancellationSignal != null) {
2328 cancellationSignal.setOnCancelListener(
2329 () -> removeUpdates(listener, null, packageName));
2330 }
2331 return true;
2332 }
2333
2334 @Override
Chad Brubakerf1133332019-03-15 14:13:59 -07002335 public LocationTime getGnssTimeMillis() {
2336 synchronized (mLock) {
2337 Location location = mLastLocation.get(LocationManager.GPS_PROVIDER);
2338 if (location == null) {
2339 return null;
2340 }
2341 long currentNanos = SystemClock.elapsedRealtimeNanos();
2342 long deltaMs = (currentNanos - location.getElapsedRealtimeNanos()) / 1000000L;
2343 return new LocationTime(location.getTime() + deltaMs, currentNanos);
2344 }
2345 }
2346
2347 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002348 public boolean injectLocation(Location location) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002349 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
2350 "Location Hardware permission not granted to inject location");
2351 mContext.enforceCallingPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
2352 "Access Fine Location permission not granted to inject Location");
2353
Soonil Nagarkar68257742019-01-09 19:42:34 +00002354 synchronized (mLock) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002355 LocationProviderManager manager = getLocationProviderManager(location.getProvider());
2356 if (manager == null || !manager.isUseable()) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002357 return false;
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002358 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002359
2360 // NOTE: If last location is already available, location is not injected. If
2361 // provider's normal source (like a GPS chipset) have already provided an output
2362 // there is no need to inject this location.
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002363 if (mLastLocation.get(manager.getName()) != null) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002364 return false;
2365 }
2366
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002367 updateLastLocationLocked(location, manager.getName());
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002368 return true;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002369 }
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002370 }
2371
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002372 @Override
2373 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002374 String packageName, String featureId, String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002375 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002376
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002377 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002378 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2379 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002380 if (intent == null) {
2381 throw new IllegalArgumentException("invalid pending intent: " + null);
Victoria Lease56e675b2012-11-05 19:25:06 -08002382 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002383 checkPackageName(packageName);
2384 synchronized (mLock) {
2385 checkResolutionLevelIsSufficientForProviderUseLocked(allowedResolutionLevel,
2386 request.getProvider());
Soonil Nagarkar8c4655e2019-02-27 13:00:56 -08002387 }
2388 // Require that caller can manage given document
2389 boolean callerHasLocationHardwarePermission =
2390 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
2391 == PERMISSION_GRANTED;
2392 LocationRequest sanitizedRequest = createSanitizedRequest(request,
2393 allowedResolutionLevel,
2394 callerHasLocationHardwarePermission);
2395
2396 if (D) {
2397 Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
2398 }
2399
2400 // geo-fence manager uses the public location API, need to clear identity
2401 int uid = Binder.getCallingUid();
2402 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
2403 // temporary measure until geofences work for secondary users
2404 Log.w(TAG, "proximity alerts are currently available only to the primary user");
2405 return;
2406 }
2407 long identity = Binder.clearCallingIdentity();
2408 try {
Hongyi Zhang700137e2019-05-23 21:19:36 -07002409 synchronized (mLock) {
2410 mLocationUsageLogger.logLocationApiUsage(
2411 LocationStatsEnums.USAGE_STARTED,
2412 LocationStatsEnums.API_REQUEST_GEOFENCE,
2413 packageName,
2414 request,
2415 /* hasListener= */ false,
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002416 true,
Hongyi Zhang0e9ea752019-06-09 22:49:25 -07002417 geofence,
Hongyi Zhang700137e2019-05-23 21:19:36 -07002418 mActivityManager.getPackageImportance(packageName));
2419 }
2420
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002421 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002422 uid, packageName, featureId, listenerIdentifier);
Soonil Nagarkar8c4655e2019-02-27 13:00:56 -08002423 } finally {
2424 Binder.restoreCallingIdentity(identity);
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002425 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002426 }
2427
2428 @Override
2429 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002430 if (intent == null) {
2431 throw new IllegalArgumentException("invalid pending intent: " + null);
2432 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002433 checkPackageName(packageName);
2434
2435 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2436
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002437 // geo-fence manager uses the public location API, need to clear identity
2438 long identity = Binder.clearCallingIdentity();
2439 try {
Hongyi Zhang700137e2019-05-23 21:19:36 -07002440 synchronized (mLock) {
2441 mLocationUsageLogger.logLocationApiUsage(
2442 LocationStatsEnums.USAGE_ENDED,
2443 LocationStatsEnums.API_REQUEST_GEOFENCE,
2444 packageName,
2445 /* LocationRequest= */ null,
2446 /* hasListener= */ false,
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002447 true,
Hongyi Zhang0e9ea752019-06-09 22:49:25 -07002448 geofence,
Hongyi Zhang700137e2019-05-23 21:19:36 -07002449 mActivityManager.getPackageImportance(packageName));
2450 }
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002451 mGeofenceManager.removeFence(geofence, intent);
2452 } finally {
2453 Binder.restoreCallingIdentity(identity);
2454 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002455 }
2456
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002457 @Override
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002458 public boolean registerGnssStatusCallback(IGnssStatusListener listener, String packageName,
2459 String featureId) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002460 return mGnssManagerService != null && mGnssManagerService.registerGnssStatusCallback(
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002461 listener, packageName, featureId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002462 }
2463
Nick Pellye0fd6932012-07-11 10:26:13 -07002464 @Override
Anil Admal98d49b72019-02-06 15:26:33 -08002465 public void unregisterGnssStatusCallback(IGnssStatusListener listener) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002466 if (mGnssManagerService != null) mGnssManagerService.unregisterGnssStatusCallback(listener);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002467 }
2468
Nick Pellye0fd6932012-07-11 10:26:13 -07002469 @Override
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002470 public boolean addGnssMeasurementsListener(IGnssMeasurementsListener listener,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002471 String packageName, String featureId, String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002472 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002473
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002474 return mGnssManagerService != null && mGnssManagerService.addGnssMeasurementsListener(
2475 listener, packageName, featureId, listenerIdentifier);
Anil Admal52686f82019-02-13 19:04:10 -08002476 }
2477
2478 @Override
2479 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002480 if (mGnssManagerService != null) {
2481 mGnssManagerService.removeGnssMeasurementsListener(
2482 listener);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002483 }
destradaaea8a8a62014-06-23 18:19:03 -07002484 }
2485
2486 @Override
gomo226b7b72018-12-12 16:49:39 -08002487 public void injectGnssMeasurementCorrections(
2488 GnssMeasurementCorrections measurementCorrections, String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002489 if (mGnssManagerService != null) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002490 mGnssManagerService.injectGnssMeasurementCorrections(measurementCorrections,
2491 packageName);
gomo226b7b72018-12-12 16:49:39 -08002492 }
2493 }
2494
2495 @Override
Anil Admal99349782019-03-19 18:58:42 -07002496 public long getGnssCapabilities(String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002497 return mGnssManagerService == null ? 0L : mGnssManagerService.getGnssCapabilities(
2498 packageName);
gomo226b7b72018-12-12 16:49:39 -08002499 }
2500
2501 @Override
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002502 public boolean addGnssNavigationMessageListener(IGnssNavigationMessageListener listener,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002503 String packageName, String featureId, String listenerIdentifier) {
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +00002504 Objects.requireNonNull(listenerIdentifier);
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002505
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002506 return mGnssManagerService != null && mGnssManagerService.addGnssNavigationMessageListener(
2507 listener, packageName, featureId, listenerIdentifier);
destradaa4b3e3932014-07-21 18:01:47 -07002508 }
2509
2510 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002511 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002512 if (mGnssManagerService != null) {
2513 mGnssManagerService.removeGnssNavigationMessageListener(
2514 listener);
2515 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002516 }
2517
2518 @Override
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002519 public boolean sendExtraCommand(String providerName, String command, Bundle extras) {
2520 if (providerName == null) {
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002521 // throw NullPointerException to remain compatible with previous implementation
2522 throw new NullPointerException();
2523 }
Soonil Nagarkar3f128402019-12-12 08:31:27 -08002524
2525 mContext.enforceCallingOrSelfPermission(
2526 Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, null);
2527
Soonil Nagarkar68257742019-01-09 19:42:34 +00002528 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002529 checkResolutionLevelIsSufficientForProviderUseLocked(getCallerAllowedResolutionLevel(),
2530 providerName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002531
Hongyi Zhang700137e2019-05-23 21:19:36 -07002532 mLocationUsageLogger.logLocationApiUsage(
2533 LocationStatsEnums.USAGE_STARTED,
2534 LocationStatsEnums.API_SEND_EXTRA_COMMAND,
2535 providerName);
2536
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002537 LocationProviderManager manager = getLocationProviderManager(providerName);
2538 if (manager != null) {
2539 manager.sendExtraCommand(Binder.getCallingUid(), Binder.getCallingPid(), command,
2540 extras);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002541 }
2542
Hongyi Zhang700137e2019-05-23 21:19:36 -07002543 mLocationUsageLogger.logLocationApiUsage(
2544 LocationStatsEnums.USAGE_ENDED,
2545 LocationStatsEnums.API_SEND_EXTRA_COMMAND,
2546 providerName);
2547
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002548 return true;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002549 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002550 }
2551
Nick Pellye0fd6932012-07-11 10:26:13 -07002552 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002553 public boolean sendNiResponse(int notifId, int userResponse) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002554 return mGnssManagerService != null && mGnssManagerService.sendNiResponse(notifId,
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002555 userResponse);
Danke Xie22d1f9f2009-08-18 18:28:45 -04002556 }
2557
Nick Pellye0fd6932012-07-11 10:26:13 -07002558 @Override
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002559 public ProviderProperties getProviderProperties(String providerName) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002560 LocationProviderManager manager = getLocationProviderManager(providerName);
2561 if (manager == null) {
2562 return null;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002563 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002564 return manager.getProperties();
Jason Monkb71218a2015-06-17 14:44:39 -04002565 }
2566
Wei Wang980b7c22018-12-06 17:53:00 -08002567 @Override
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08002568 public boolean isProviderPackage(String packageName) {
Soonil Nagarkar514dff42019-04-30 12:04:28 -07002569 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG,
2570 Manifest.permission.READ_DEVICE_CONFIG + " permission required");
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002571 for (LocationProviderManager manager : mProviderManagers) {
2572 if (manager.getPackages().contains(packageName)) {
2573 return true;
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08002574 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002575 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002576 return false;
Maggie2a9409e2018-03-21 11:47:28 -07002577 }
2578
Maggie2a9409e2018-03-21 11:47:28 -07002579 @Override
Wei Wang9f52d552019-10-02 14:49:02 -07002580 public List<String> getProviderPackages(String providerName) {
2581 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG,
2582 Manifest.permission.READ_DEVICE_CONFIG + " permission required");
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002583 LocationProviderManager manager = getLocationProviderManager(providerName);
2584 return manager == null ? Collections.emptyList() : new ArrayList<>(manager.getPackages());
Wei Wang9f52d552019-10-02 14:49:02 -07002585 }
2586
2587 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002588 public void setExtraLocationControllerPackage(String packageName) {
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002589 mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
2590 Manifest.permission.LOCATION_HARDWARE + " permission required");
Soonil Nagarkar68257742019-01-09 19:42:34 +00002591 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002592 mExtraLocationControllerPackage = packageName;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002593 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002594 }
2595
2596 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002597 public String getExtraLocationControllerPackage() {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002598 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002599 return mExtraLocationControllerPackage;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002600 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002601 }
2602
2603 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002604 public void setExtraLocationControllerPackageEnabled(boolean enabled) {
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002605 mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
2606 Manifest.permission.LOCATION_HARDWARE + " permission required");
Soonil Nagarkar68257742019-01-09 19:42:34 +00002607 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002608 mExtraLocationControllerPackageEnabled = enabled;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002609 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002610 }
2611
2612 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002613 public boolean isExtraLocationControllerPackageEnabled() {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002614 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002615 return mExtraLocationControllerPackageEnabled
2616 && (mExtraLocationControllerPackage != null);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002617 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002618 }
2619
2620 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002621 public boolean isLocationEnabledForUser(int userId) {
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002622 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002623 if (UserHandle.getCallingUserId() != userId) {
2624 mContext.enforceCallingOrSelfPermission(
2625 Manifest.permission.INTERACT_ACROSS_USERS,
2626 "Requires INTERACT_ACROSS_USERS permission");
2627 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002628
Soonil Nagarkar68257742019-01-09 19:42:34 +00002629 long identity = Binder.clearCallingIdentity();
2630 try {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07002631 return mSettingsStore.isLocationEnabled(userId);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002632 } finally {
2633 Binder.restoreCallingIdentity(identity);
2634 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002635 }
2636
Maggie2a9409e2018-03-21 11:47:28 -07002637 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002638 public boolean isProviderEnabledForUser(String providerName, int userId) {
Maggie2a9409e2018-03-21 11:47:28 -07002639 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002640 if (UserHandle.getCallingUserId() != userId) {
2641 mContext.enforceCallingOrSelfPermission(
2642 Manifest.permission.INTERACT_ACROSS_USERS,
2643 "Requires INTERACT_ACROSS_USERS permission");
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002644 }
2645
Maggie2a9409e2018-03-21 11:47:28 -07002646 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2647 // so we discourage its use
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002648 if (FUSED_PROVIDER.equals(providerName)) return false;
Maggie2a9409e2018-03-21 11:47:28 -07002649
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002650 synchronized (mLock) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002651 LocationProviderManager manager = getLocationProviderManager(providerName);
2652 return manager != null && manager.isUseable(userId);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002653 }
Maggie2a9409e2018-03-21 11:47:28 -07002654 }
2655
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002656 @GuardedBy("mLock")
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002657 private static boolean shouldBroadcastSafeLocked(
Laurent Tu75defb62012-11-01 16:21:52 -07002658 Location loc, Location lastLoc, UpdateRecord record, long now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002659 // Always broadcast the first update
2660 if (lastLoc == null) {
2661 return true;
2662 }
2663
Nick Pellyf1be6862012-05-15 10:53:42 -07002664 // Check whether sufficient time has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002665 long minTime = record.mRealRequest.getFastestInterval();
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002666 long deltaMs = TimeUnit.NANOSECONDS.toMillis(
2667 loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos());
2668 if (deltaMs < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002669 return false;
2670 }
2671
2672 // Check whether sufficient distance has been traveled
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002673 double minDistance = record.mRealRequest.getSmallestDisplacement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002674 if (minDistance > 0.0) {
2675 if (loc.distanceTo(lastLoc) <= minDistance) {
2676 return false;
2677 }
2678 }
2679
Laurent Tu75defb62012-11-01 16:21:52 -07002680 // Check whether sufficient number of udpates is left
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002681 if (record.mRealRequest.getNumUpdates() <= 0) {
Laurent Tu75defb62012-11-01 16:21:52 -07002682 return false;
2683 }
2684
2685 // Check whether the expiry date has passed
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08002686 return record.mExpirationRealtimeMs >= now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002687 }
2688
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002689 @GuardedBy("mLock")
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002690 private void handleLocationChangedLocked(Location location, LocationProviderManager manager) {
2691 if (!mProviderManagers.contains(manager)) {
2692 Log.w(TAG, "received location from unknown provider: " + manager.getName());
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002693 return;
2694 }
2695 if (!location.isComplete()) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002696 Log.w(TAG, "dropping incomplete location from " + manager.getName() + " provider: "
2697 + location);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002698 return;
2699 }
2700
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002701 // notify passive provider
2702 if (manager != mPassiveManager) {
2703 mPassiveManager.updateLocation(new Location(location));
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002704 }
2705
Soonil Nagarkar68257742019-01-09 19:42:34 +00002706 if (D) Log.d(TAG, "incoming location: " + location);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002707 long now = SystemClock.elapsedRealtime();
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002708
2709
2710 // only update last location for locations that come from useable providers
2711 if (manager.isUseable()) {
2712 updateLastLocationLocked(location, manager.getName());
Mike Lockwood4e50b782009-04-03 08:24:43 -07002713 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714
David Christie1b9b7b12013-04-15 15:31:11 -07002715 // Update last known coarse interval location if enough time has passed.
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002716 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002717 manager.getName());
David Christie1b9b7b12013-04-15 15:31:11 -07002718 if (lastLocationCoarseInterval == null) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002719 lastLocationCoarseInterval = new Location(location);
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002720
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002721 if (manager.isUseable()) {
2722 mLastLocationCoarseInterval.put(manager.getName(), lastLocationCoarseInterval);
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002723 }
David Christie1b9b7b12013-04-15 15:31:11 -07002724 }
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002725 long timeDeltaMs = TimeUnit.NANOSECONDS.toMillis(location.getElapsedRealtimeNanos()
2726 - lastLocationCoarseInterval.getElapsedRealtimeNanos());
2727 if (timeDeltaMs > LocationFudger.FASTEST_INTERVAL_MS) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002728 lastLocationCoarseInterval.set(location);
David Christie1b9b7b12013-04-15 15:31:11 -07002729 }
2730 // Don't ever return a coarse location that is more recent than the allowed update
2731 // interval (i.e. don't allow an app to keep registering and unregistering for
2732 // location updates to overcome the minimum interval).
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002733 Location noGPSLocation =
David Christie1b9b7b12013-04-15 15:31:11 -07002734 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2735
Laurent Tu60ec50a2012-10-04 17:00:10 -07002736 // Skip if there are no UpdateRecords for this provider.
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002737 ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName());
Laurent Tu60ec50a2012-10-04 17:00:10 -07002738 if (records == null || records.size() == 0) return;
2739
Victoria Lease09016ab2012-09-16 12:33:15 -07002740 // Fetch coarse location
2741 Location coarseLocation = null;
David Christie1b9b7b12013-04-15 15:31:11 -07002742 if (noGPSLocation != null) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002743 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
2744 }
2745
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002746 ArrayList<Receiver> deadReceivers = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002747 ArrayList<UpdateRecord> deadUpdateRecords = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07002748
Soonil Nagarkar94749f72018-11-08 11:46:43 -08002749 // Broadcast location to all listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002750 for (UpdateRecord r : records) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002751 Receiver receiver = r.mReceiver;
Mike Lockwood03ca2162010-04-01 08:10:09 -07002752 boolean receiverDead = false;
Nick Pelly4035f5a2012-08-17 14:43:49 -07002753
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002754 if (!manager.isUseable() && !isSettingsExemptLocked(r)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002755 continue;
2756 }
2757
Anil Admal08b96122019-01-30 16:55:05 -08002758 int receiverUserId = UserHandle.getUserId(receiver.mCallerIdentity.mUid);
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08002759 if (!mUserInfoStore.isCurrentUserOrProfile(receiverUserId)
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08002760 && !isProviderPackage(receiver.mCallerIdentity.mPackageName)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002761 if (D) {
Victoria Lease269518e2012-10-29 08:25:39 -07002762 Log.d(TAG, "skipping loc update for background user " + receiverUserId +
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08002763 " (app: " + receiver.mCallerIdentity.mPackageName + ")");
Victoria Leaseb711d572012-10-02 13:14:11 -07002764 }
2765 continue;
2766 }
2767
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07002768 if (mSettingsStore.isLocationPackageBlacklisted(receiverUserId,
2769 receiver.mCallerIdentity.mPackageName)) {
gomo48f1a642017-11-10 20:35:46 -08002770 if (D) {
2771 Log.d(TAG, "skipping loc update for blacklisted app: " +
Anil Admal08b96122019-01-30 16:55:05 -08002772 receiver.mCallerIdentity.mPackageName);
gomo48f1a642017-11-10 20:35:46 -08002773 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07002774 continue;
2775 }
2776
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002777 Location notifyLocation;
Victoria Lease37425c32012-10-16 16:08:48 -07002778 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2779 notifyLocation = coarseLocation; // use coarse location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002780 } else {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002781 notifyLocation = location; // use fine location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002782 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002783 if (notifyLocation != null) {
2784 Location lastLoc = r.mLastFixBroadcast;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002785 if ((lastLoc == null)
2786 || shouldBroadcastSafeLocked(notifyLocation, lastLoc, r, now)) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002787 if (lastLoc == null) {
2788 lastLoc = new Location(notifyLocation);
2789 r.mLastFixBroadcast = lastLoc;
2790 } else {
2791 lastLoc.set(notifyLocation);
2792 }
Wei Wang8486fc72019-03-07 18:49:21 -08002793 // Report location access before delivering location to the client. This will
2794 // note location delivery to appOps, so it should be called only when a
2795 // location is really being delivered to the client.
2796 if (!reportLocationAccessNoThrow(
2797 receiver.mCallerIdentity.mPid,
2798 receiver.mCallerIdentity.mUid,
2799 receiver.mCallerIdentity.mPackageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002800 receiver.mCallerIdentity.mFeatureId,
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002801 receiver.mAllowedResolutionLevel,
2802 "Location sent to " + receiver.mCallerIdentity.mListenerIdentifier)) {
Wei Wang8486fc72019-03-07 18:49:21 -08002803 if (D) {
2804 Log.d(TAG, "skipping loc update for no op app: "
2805 + receiver.mCallerIdentity.mPackageName);
2806 }
2807 continue;
2808 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002809 if (!receiver.callLocationChangedLocked(notifyLocation)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002810 Slog.w(TAG, "RemoteException calling onLocationChanged on "
2811 + receiver);
Victoria Lease09016ab2012-09-16 12:33:15 -07002812 receiverDead = true;
2813 }
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002814 r.mRealRequest.decrementNumUpdates();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002815 }
2816 }
2817
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002818 // track expired records
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08002819 if (r.mRealRequest.getNumUpdates() <= 0 || r.mExpirationRealtimeMs < now) {
Soonil Nagarkar39d614a2019-10-31 12:10:31 -07002820 // notify the client it can remove this listener
2821 r.mReceiver.callRemovedLocked();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002822 if (deadUpdateRecords == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002823 deadUpdateRecords = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002824 }
2825 deadUpdateRecords.add(r);
2826 }
2827 // track dead receivers
2828 if (receiverDead) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07002829 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002830 deadReceivers = new ArrayList<>();
Mike Lockwood03ca2162010-04-01 08:10:09 -07002831 }
2832 if (!deadReceivers.contains(receiver)) {
2833 deadReceivers.add(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002834 }
2835 }
2836 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002837
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002838 // remove dead records and receivers outside the loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002839 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002840 for (Receiver receiver : deadReceivers) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002841 removeUpdatesLocked(receiver);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002842 }
2843 }
2844 if (deadUpdateRecords != null) {
2845 for (UpdateRecord r : deadUpdateRecords) {
2846 r.disposeLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002847 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002848 applyRequirementsLocked(manager);
Victoria Lease8b38b292012-12-04 15:04:43 -08002849 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002850 }
2851
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002852 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00002853 private void updateLastLocationLocked(Location location, String provider) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002854 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2855 Location lastNoGPSLocation;
2856 Location lastLocation = mLastLocation.get(provider);
2857 if (lastLocation == null) {
2858 lastLocation = new Location(provider);
2859 mLastLocation.put(provider, lastLocation);
2860 } else {
2861 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2862 if (noGPSLocation == null && lastNoGPSLocation != null) {
2863 // New location has no no-GPS location: adopt last no-GPS location. This is set
2864 // directly into location because we do not want to notify COARSE clients.
2865 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
2866 }
2867 }
2868 lastLocation.set(location);
2869 }
2870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002871 // Geocoder
2872
Nick Pellye0fd6932012-07-11 10:26:13 -07002873 @Override
Mike Lockwoode15735a2010-09-20 17:48:47 -04002874 public boolean geocoderIsPresent() {
Mark Vandevoorde01ac80b2010-05-21 15:43:26 -07002875 return mGeocodeProvider != null;
2876 }
2877
Nick Pellye0fd6932012-07-11 10:26:13 -07002878 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002879 public String getFromLocation(double latitude, double longitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002880 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002881 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002882 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
2883 params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002884 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002885 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002886 }
2887
Mike Lockwooda55c3212009-04-15 11:10:11 -04002888
Nick Pellye0fd6932012-07-11 10:26:13 -07002889 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002890 public String getFromLocationName(String locationName,
Mike Lockwooda55c3212009-04-15 11:10:11 -04002891 double lowerLeftLatitude, double lowerLeftLongitude,
2892 double upperRightLatitude, double upperRightLongitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05002893 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04002894
2895 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05002896 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
2897 lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
2898 maxResults, params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002899 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04002900 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002901 }
2902
2903 // Mock Providers
2904
Nick Pellye0fd6932012-07-11 10:26:13 -07002905 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002906 public void addTestProvider(String provider, ProviderProperties properties,
2907 String packageName) {
2908 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2909 != AppOpsManager.MODE_ALLOWED) {
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002910 return;
2911 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002912
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002913 synchronized (mLock) {
2914 LocationProviderManager manager = getLocationProviderManager(provider);
2915 if (manager == null) {
2916 manager = new LocationProviderManager(provider);
2917 mProviderManagers.add(manager);
2918 }
2919
2920 manager.setMockProvider(new MockProvider(mContext, properties));
2921 }
2922 }
2923
2924 @Override
2925 public void removeTestProvider(String provider, String packageName) {
2926 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2927 != AppOpsManager.MODE_ALLOWED) {
2928 return;
Mike Lockwooda4903f22010-02-17 06:42:23 -05002929 }
2930
Soonil Nagarkar68257742019-01-09 19:42:34 +00002931 synchronized (mLock) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002932 LocationProviderManager manager = getLocationProviderManager(provider);
2933 if (manager == null) {
2934 return;
2935 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002936
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002937 manager.setMockProvider(null);
2938 if (!manager.hasProvider()) {
2939 mProviderManagers.remove(manager);
2940 mLastLocation.remove(manager.getName());
2941 mLastLocationCoarseInterval.remove(manager.getName());
Mike Lockwood7566c1d2009-08-25 10:05:18 -07002942 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002943 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09002944 }
2945
Nick Pellye0fd6932012-07-11 10:26:13 -07002946 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002947 public void setTestProviderLocation(String provider, Location location, String packageName) {
2948 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2949 != AppOpsManager.MODE_ALLOWED) {
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002950 return;
2951 }
2952
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002953 LocationProviderManager manager = getLocationProviderManager(provider);
2954 if (manager == null) {
2955 throw new IllegalArgumentException("provider doesn't exist: " + provider);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002956 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002957
2958 manager.setMockProviderLocation(location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002959 }
2960
Nick Pellye0fd6932012-07-11 10:26:13 -07002961 @Override
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002962 public void setTestProviderEnabled(String provider, boolean enabled, String packageName) {
2963 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2964 != AppOpsManager.MODE_ALLOWED) {
Svet Ganovf7e9cf42015-05-13 10:40:31 -07002965 return;
2966 }
2967
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002968 LocationProviderManager manager = getLocationProviderManager(provider);
2969 if (manager == null) {
2970 throw new IllegalArgumentException("provider doesn't exist: " + provider);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002971 }
2972
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002973 manager.setMockProviderEnabled(enabled);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002974 }
2975
2976 @Override
Kweku Adams4fb074e2019-02-01 16:03:27 -08002977 @NonNull
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002978 public List<LocationRequest> getTestProviderCurrentRequests(String provider,
2979 String packageName) {
2980 if (mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), packageName)
2981 != AppOpsManager.MODE_ALLOWED) {
Kweku Adams4fb074e2019-02-01 16:03:27 -08002982 return Collections.emptyList();
2983 }
2984
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002985 LocationProviderManager manager = getLocationProviderManager(provider);
2986 if (manager == null) {
2987 throw new IllegalArgumentException("provider doesn't exist: " + provider);
Kweku Adams4fb074e2019-02-01 16:03:27 -08002988 }
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002989
2990 return manager.getMockProviderRequests();
Kweku Adams4fb074e2019-02-01 16:03:27 -08002991 }
2992
2993 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002994 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08002995 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) {
2996 return;
2997 }
Nick Pellye0fd6932012-07-11 10:26:13 -07002998
Soonil Nagarkar1c572552019-07-10 13:31:47 -07002999 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
3000
Soonil Nagarkar68257742019-01-09 19:42:34 +00003001 synchronized (mLock) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07003002 if (mGnssManagerService != null && args.length > 0 && args[0].equals("--gnssmetrics")) {
3003 mGnssManagerService.dump(fd, pw, args);
Blake Kragten47014d22019-12-06 14:18:38 -08003004 return;
Siddharth Raybb608c82017-03-16 11:33:34 -07003005 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003006
3007 ipw.println("Location Manager State:");
3008 ipw.increaseIndent();
3009 ipw.print("Current System Time: "
WyattRileyba6072f2019-04-18 07:37:52 -07003010 + TimeUtils.logTimeOfDay(System.currentTimeMillis()));
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003011 ipw.println(", Current Elapsed Time: "
WyattRileyba6072f2019-04-18 07:37:52 -07003012 + TimeUtils.formatDuration(SystemClock.elapsedRealtime()));
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08003013
3014 ipw.println("User Info:");
3015 ipw.increaseIndent();
3016 mUserInfoStore.dump(fd, ipw, args);
3017 ipw.decreaseIndent();
3018
3019 ipw.println("Location Settings:");
3020 ipw.increaseIndent();
3021 mSettingsStore.dump(fd, ipw, args);
3022 ipw.decreaseIndent();
3023
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003024 ipw.println("Battery Saver Location Mode: "
Kweku Adams4fb074e2019-02-01 16:03:27 -08003025 + locationPowerSaveModeToString(mBatterySaverMode));
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003026
3027 ipw.println("Location Listeners:");
3028 ipw.increaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003029 for (Receiver receiver : mReceivers.values()) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003030 ipw.println(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003031 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003032 ipw.decreaseIndent();
3033
3034 ipw.println("Active Records by Provider:");
3035 ipw.increaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003036 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003037 ipw.println(entry.getKey() + ":");
3038 ipw.increaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003039 for (UpdateRecord record : entry.getValue()) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003040 ipw.println(record);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003041 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003042 ipw.decreaseIndent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003043 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003044 ipw.decreaseIndent();
Anil Admal98d49b72019-02-06 15:26:33 -08003045
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003046 ipw.println("Historical Records by Provider:");
3047 ipw.increaseIndent();
David Christie2ff96af2014-01-30 16:09:37 -08003048 for (Map.Entry<PackageProviderKey, PackageStatistics> entry
3049 : mRequestStatistics.statistics.entrySet()) {
3050 PackageProviderKey key = entry.getKey();
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003051 ipw.println(key.packageName + ": " + key.providerName + ": " + entry.getValue());
David Christie2ff96af2014-01-30 16:09:37 -08003052 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003053 ipw.decreaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003054
WyattRileyfa1ef8d32019-12-30 17:19:55 -08003055 mRequestStatistics.history.dump(ipw);
3056
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003057 ipw.println("Last Known Locations:");
3058 ipw.increaseIndent();
3059 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
3060 ipw.println(entry.getKey() + ": " + entry.getValue());
David Christie1b9b7b12013-04-15 15:31:11 -07003061 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003062 ipw.decreaseIndent();
3063
3064 ipw.println("Last Known Coarse Locations:");
3065 ipw.increaseIndent();
3066 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
3067 ipw.println(entry.getKey() + ": " + entry.getValue());
3068 }
3069 ipw.decreaseIndent();
David Christie1b9b7b12013-04-15 15:31:11 -07003070
Tyler Trephan2f3ee9a2019-03-21 10:54:22 -07003071 if (mGeofenceManager != null) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003072 ipw.println("Geofences:");
3073 ipw.increaseIndent();
3074 mGeofenceManager.dump(ipw);
3075 ipw.decreaseIndent();
Tyler Trephan2f3ee9a2019-03-21 10:54:22 -07003076 }
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07003077
Wei Wang114922a2019-01-30 18:19:35 -08003078 if (mExtraLocationControllerPackage != null) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003079 ipw.println("Location Controller Extra Package: " + mExtraLocationControllerPackage
3080 + (mExtraLocationControllerPackageEnabled ? " [enabled]" : "[disabled]"));
Wei Wang980b7c22018-12-06 17:53:00 -08003081 }
3082
Tyler Trephan2f3ee9a2019-03-21 10:54:22 -07003083 if (mLocationFudger != null) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003084 ipw.println("Location Fudger:");
3085 ipw.increaseIndent();
3086 mLocationFudger.dump(fd, ipw, args);
3087 ipw.decreaseIndent();
Tyler Trephan2f3ee9a2019-03-21 10:54:22 -07003088 }
Anil Admal98d49b72019-02-06 15:26:33 -08003089
Soonil Nagarkar9ec01852020-01-10 13:42:38 -08003090 ipw.println("Location Providers:");
3091 ipw.increaseIndent();
3092 for (LocationProviderManager manager : mProviderManagers) {
3093 manager.dump(fd, ipw, args);
3094 }
3095 ipw.decreaseIndent();
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08003096
Soonil Nagarkar8df02f42020-01-08 13:23:26 -08003097 if (mGnssManagerService != null) {
3098 ipw.println("GNSS:");
3099 ipw.increaseIndent();
3100 mGnssManagerService.dump(fd, ipw, args);
3101 ipw.decreaseIndent();
3102 }
Anil Admal98d49b72019-02-06 15:26:33 -08003103 }
3104 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003105}