blob: 54dfc98e888d7c6541b586bc9dbe2cf968f130ee [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
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -080026import static com.android.internal.util.Preconditions.checkNotNull;
Soonil Nagarkar1575a042018-10-24 17:54:54 -070027import static com.android.internal.util.Preconditions.checkState;
28
Wei Wang980b7c22018-12-06 17:53:00 -080029import android.Manifest;
Wyatt Rileycf879db2017-01-12 13:57:38 -080030import android.annotation.NonNull;
Wyatt Riley49097c02018-03-15 09:14:43 -070031import android.annotation.Nullable;
Maggieaa080f92018-01-04 15:35:11 -080032import android.app.ActivityManager;
33import android.app.AppOpsManager;
34import android.app.PendingIntent;
35import android.content.BroadcastReceiver;
Maggieaa080f92018-01-04 15:35:11 -080036import android.content.Context;
37import android.content.Intent;
38import android.content.IntentFilter;
39import android.content.pm.ApplicationInfo;
40import android.content.pm.PackageInfo;
41import android.content.pm.PackageManager;
42import android.content.pm.PackageManager.NameNotFoundException;
Maggieaa080f92018-01-04 15:35:11 -080043import android.content.pm.ResolveInfo;
44import android.content.pm.Signature;
45import android.content.res.Resources;
Brian Duddiecfa5b5b2019-01-22 18:01:40 +000046import android.hardware.location.ActivityRecognitionHardware;
Maggieaa080f92018-01-04 15:35:11 -080047import android.location.Address;
48import android.location.Criteria;
49import android.location.GeocoderParams;
50import android.location.Geofence;
gomo226b7b72018-12-12 16:49:39 -080051import android.location.GnssMeasurementCorrections;
Maggieaa080f92018-01-04 15:35:11 -080052import android.location.IBatchedLocationCallback;
53import android.location.IGnssMeasurementsListener;
54import android.location.IGnssNavigationMessageListener;
55import android.location.IGnssStatusListener;
Maggieaa080f92018-01-04 15:35:11 -080056import android.location.ILocationListener;
57import android.location.ILocationManager;
Maggieaa080f92018-01-04 15:35:11 -080058import android.location.Location;
59import android.location.LocationManager;
Maggieaa080f92018-01-04 15:35:11 -080060import android.location.LocationRequest;
Chad Brubakerf1133332019-03-15 14:13:59 -070061import android.location.LocationTime;
Maggieaa080f92018-01-04 15:35:11 -080062import android.os.Binder;
63import android.os.Bundle;
Soonil Nagarkar905e7222019-10-01 12:03:29 -070064import android.os.CancellationSignal;
Maggieaa080f92018-01-04 15:35:11 -080065import android.os.Handler;
66import android.os.IBinder;
Soonil Nagarkar905e7222019-10-01 12:03:29 -070067import android.os.ICancellationSignal;
Maggieaa080f92018-01-04 15:35:11 -080068import android.os.PowerManager;
Kweku Adams4fb074e2019-02-01 16:03:27 -080069import android.os.PowerManager.ServiceType;
70import android.os.PowerManagerInternal;
Maggieaa080f92018-01-04 15:35:11 -080071import android.os.Process;
72import android.os.RemoteException;
73import android.os.SystemClock;
74import android.os.UserHandle;
75import android.os.UserManager;
76import android.os.WorkSource;
Narayan Kamath32684dd2018-01-08 17:32:51 +000077import android.os.WorkSource.WorkChain;
Maggieaa080f92018-01-04 15:35:11 -080078import android.provider.Settings;
Hongyi Zhang700137e2019-05-23 21:19:36 -070079import android.stats.location.LocationStatsEnums;
Maggieaa080f92018-01-04 15:35:11 -080080import android.text.TextUtils;
Maggieaa080f92018-01-04 15:35:11 -080081import android.util.EventLog;
82import android.util.Log;
83import android.util.Slog;
Soonil Nagarkar06e37f62019-12-04 16:05:08 -080084import android.util.SparseArray;
WyattRileyba6072f2019-04-18 07:37:52 -070085import android.util.TimeUtils;
Yu-Han Yanga4d250e2018-10-02 21:29:20 -070086
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -080087import com.android.internal.annotations.GuardedBy;
destradaaea8a8a62014-06-23 18:19:03 -070088import com.android.internal.content.PackageMonitor;
89import com.android.internal.location.ProviderProperties;
90import com.android.internal.location.ProviderRequest;
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -070091import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060092import com.android.internal.util.DumpUtils;
Soonil Nagarkar1c572552019-07-10 13:31:47 -070093import com.android.internal.util.IndentingPrintWriter;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -080094import com.android.internal.util.Preconditions;
Soonil Nagarkar1575a042018-10-24 17:54:54 -070095import com.android.server.location.AbstractLocationProvider;
Brian Duddiecfa5b5b2019-01-22 18:01:40 +000096import com.android.server.location.ActivityRecognitionProxy;
Anil Admal08b96122019-01-30 16:55:05 -080097import com.android.server.location.CallerIdentity;
destradaaea8a8a62014-06-23 18:19:03 -070098import com.android.server.location.GeocoderProxy;
99import com.android.server.location.GeofenceManager;
100import com.android.server.location.GeofenceProxy;
destradaaea8a8a62014-06-23 18:19:03 -0700101import com.android.server.location.LocationFudger;
destradaaea8a8a62014-06-23 18:19:03 -0700102import com.android.server.location.LocationProviderProxy;
103import com.android.server.location.LocationRequestStatistics;
104import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
105import com.android.server.location.LocationRequestStatistics.PackageStatistics;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700106import com.android.server.location.LocationSettingsStore;
destradaaea8a8a62014-06-23 18:19:03 -0700107import com.android.server.location.MockProvider;
108import com.android.server.location.PassiveProvider;
Todd Kennedy583378d2019-07-12 06:50:30 -0700109import com.android.server.pm.permission.PermissionManagerServiceInternal;
Yu-Han Yanga4d250e2018-10-02 21:29:20 -0700110
Soonil Nagarkarae6ce772019-05-01 13:16:17 -0700111import java.io.ByteArrayOutputStream;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400112import java.io.FileDescriptor;
Soonil Nagarkarae6ce772019-05-01 13:16:17 -0700113import java.io.PrintStream;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400114import java.io.PrintWriter;
115import java.util.ArrayList;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700116import java.util.Arrays;
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -0800117import java.util.Collections;
Mike Lockwood43e33f22010-03-26 10:41:48 -0400118import java.util.HashMap;
119import java.util.HashSet;
120import java.util.List;
121import java.util.Map;
Soonil Nagarkar681d7112017-02-23 17:14:16 -0800122import java.util.Map.Entry;
Soonil Nagarkar905e7222019-10-01 12:03:29 -0700123import java.util.concurrent.TimeUnit;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124
125/**
126 * The service class that manages LocationProviders and issues location
127 * updates and alerts.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128 */
Victoria Lease5cd731a2012-12-19 15:04:21 -0800129public class LocationManagerService extends ILocationManager.Stub {
Soonil Nagarkar141417a2019-10-28 11:12:48 -0700130
131 /**
132 * Controls lifecycle of LocationManagerService.
133 */
134 public static class Lifecycle extends SystemService {
135
136 private LocationManagerService mService;
137
138 public Lifecycle(Context context) {
139 super(context);
140 mService = new LocationManagerService(context);
141 }
142
143 @Override
144 public void onStart() {
145 publishBinderService(Context.LOCATION_SERVICE, mService);
146 }
147
148 @Override
149 public void onBootPhase(int phase) {
Soonil Nagarkar37096062019-11-25 13:24:48 -0800150 if (phase == PHASE_SYSTEM_SERVICES_READY) {
151 // the location service must be functioning after this boot phase
152 mService.onSystemReady();
153 } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
154 // some providers rely on third party code, so we wait to initialize
155 // providers until third party code is allowed to run
156 mService.onSystemThirdPartyAppsCanStart();
Soonil Nagarkar141417a2019-10-28 11:12:48 -0700157 }
158 }
159 }
160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 private static final String TAG = "LocationManagerService";
JP Abgrallf79811e72013-02-01 18:45:05 -0800162 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700163
Olivier Gaillard7a222662017-11-20 16:07:24 +0000164 private static final String WAKELOCK_KEY = "*location*";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165
Victoria Lease37425c32012-10-16 16:08:48 -0700166 // Location resolution level: no location data whatsoever
167 private static final int RESOLUTION_LEVEL_NONE = 0;
168 // Location resolution level: coarse location data only
169 private static final int RESOLUTION_LEVEL_COARSE = 1;
170 // Location resolution level: fine location data
171 private static final int RESOLUTION_LEVEL_FINE = 2;
172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173 private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700174 android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700175
176 private static final String NETWORK_LOCATION_SERVICE_ACTION =
Stan Chesnutt39062dd2013-07-22 14:33:30 -0700177 "com.android.location.service.v3.NetworkLocationProvider";
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700178 private static final String FUSED_LOCATION_SERVICE_ACTION =
179 "com.android.location.service.FusedLocationProvider";
180
David Christie0b837452013-07-29 16:02:13 -0700181 // The maximum interval a location request can have and still be considered "high power".
182 private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
183
Soonil Nagarkar905e7222019-10-01 12:03:29 -0700184 // maximum age of a location before it is no longer considered "current"
185 private static final long MAX_CURRENT_LOCATION_AGE_MS = 10 * 1000;
186
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700187 private static final int FOREGROUND_IMPORTANCE_CUTOFF
gomo48f1a642017-11-10 20:35:46 -0800188 = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
Soonil Nagarkarebda0282017-04-10 14:55:37 -0700189
Nick Pellyf1be6862012-05-15 10:53:42 -0700190 // Location Providers may sometimes deliver location updates
191 // slightly faster that requested - provide grace period so
192 // we don't unnecessarily filter events that are otherwise on
193 // time
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700194 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
Nick Pellyf1be6862012-05-15 10:53:42 -0700195
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700196 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
197
Soonil Nagarkar68257742019-01-09 19:42:34 +0000198 private final Object mLock = new Object();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800199 private final Context mContext;
200 private final Handler mHandler;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700201
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;
Amith Yamasanib27528d2014-06-05 15:02:10 -0700206 private UserManager mUserManager;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800207
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700208 private LocationSettingsStore mSettingsStore;
209
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800210 private GeofenceManager mGeofenceManager;
211 private LocationFudger mLocationFudger;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700212 private GeocoderProxy mGeocodeProvider;
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700213 @Nullable
214 private GnssManagerService mGnssManagerService;
215 private PassiveProvider mPassiveProvider; // track passive provider for special cases
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800216 @GuardedBy("mLock")
Wei Wang114922a2019-01-30 18:19:35 -0800217 private String mExtraLocationControllerPackage;
218 private boolean mExtraLocationControllerPackageEnabled;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700219
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800220 // list of currently active providers
221 @GuardedBy("mLock")
222 private final ArrayList<LocationProvider> mProviders = new ArrayList<>();
Soonil Nagarkar68257742019-01-09 19:42:34 +0000223
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800224 // list of non-mock providers, so that when mock providers replace real providers, they can be
225 // later re-replaced
226 @GuardedBy("mLock")
227 private final ArrayList<LocationProvider> mRealProviders = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800229 @GuardedBy("mLock")
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800230 private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700231 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800232 new HashMap<>();
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700233
David Christie2ff96af2014-01-30 16:09:37 -0800234 private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics();
235
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700236 // mapping from provider name to last known location
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800237 @GuardedBy("mLock")
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800238 private final HashMap<String, Location> mLastLocation = new HashMap<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239
David Christie1b9b7b12013-04-15 15:31:11 -0700240 // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
241 // locations stored here are not fudged for coarse permissions.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800242 @GuardedBy("mLock")
David Christie1b9b7b12013-04-15 15:31:11 -0700243 private final HashMap<String, Location> mLastLocationCoarseInterval =
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800244 new HashMap<>();
David Christie1b9b7b12013-04-15 15:31:11 -0700245
Victoria Lease38389b62012-09-30 11:44:22 -0700246 // current active user on the device - other users are denied location data
Xiaohui Chena4490622015-09-22 15:29:31 -0700247 private int mCurrentUserId = UserHandle.USER_SYSTEM;
gomo48f1a642017-11-10 20:35:46 -0800248 private int[] mCurrentUserProfiles = new int[]{UserHandle.USER_SYSTEM};
Victoria Lease38389b62012-09-30 11:44:22 -0700249
Kweku Adams4fb074e2019-02-01 16:03:27 -0800250 @GuardedBy("mLock")
251 @PowerManager.LocationPowerSaveMode
252 private int mBatterySaverMode;
253
Hongyi Zhang700137e2019-05-23 21:19:36 -0700254 @GuardedBy("mLock")
255 private final LocationUsageLogger mLocationUsageLogger;
256
Soonil Nagarkar141417a2019-10-28 11:12:48 -0700257 private LocationManagerService(Context context) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700258 mContext = context;
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -0800259 mHandler = FgThread.getHandler();
Hongyi Zhang700137e2019-05-23 21:19:36 -0700260 mLocationUsageLogger = new LocationUsageLogger();
The Android Open Source Project4df24232009-03-05 14:34:35 -0800261
Svet Ganovadc1cf42015-06-15 16:36:24 -0700262 // Let the package manager query which are the default location
263 // providers as they get certain permissions granted by default.
Todd Kennedy583378d2019-07-12 06:50:30 -0700264 PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
265 PermissionManagerServiceInternal.class);
266 permissionManagerInternal.setLocationPackagesProvider(
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700267 userId -> mContext.getResources().getStringArray(
268 com.android.internal.R.array.config_locationProviderPackageNames));
Todd Kennedy583378d2019-07-12 06:50:30 -0700269 permissionManagerInternal.setLocationExtraPackagesProvider(
Wei Wangffb94e62019-01-14 00:05:45 -0800270 userId -> mContext.getResources().getStringArray(
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700271 com.android.internal.R.array.config_locationExtraPackageNames));
Svet Ganovadc1cf42015-06-15 16:36:24 -0700272
Soonil Nagarkar37096062019-11-25 13:24:48 -0800273 // most startup is deferred until systemReady()
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700274 }
275
Soonil Nagarkar37096062019-11-25 13:24:48 -0800276 private void onSystemReady() {
Soonil Nagarkar68257742019-01-09 19:42:34 +0000277 synchronized (mLock) {
Soonil Nagarkar37096062019-11-25 13:24:48 -0800278 mPackageManager = mContext.getPackageManager();
279 mAppOps = mContext.getSystemService(AppOpsManager.class);
280 mPowerManager = mContext.getSystemService(PowerManager.class);
281 mActivityManager = mContext.getSystemService(ActivityManager.class);
282 mUserManager = mContext.getSystemService(UserManager.class);
283
284 mSettingsStore = new LocationSettingsStore(mContext, mHandler);
285 mLocationFudger = new LocationFudger(mContext, mHandler);
286 mGeofenceManager = new GeofenceManager(mContext, mSettingsStore);
287
288 PowerManagerInternal localPowerManager =
289 LocalServices.getService(PowerManagerInternal.class);
290
291 // add listeners
292 mAppOps.startWatchingMode(
293 AppOpsManager.OP_COARSE_LOCATION,
294 null,
295 AppOpsManager.WATCH_FOREGROUND_CHANGES,
296 new AppOpsManager.OnOpChangedInternalListener() {
297 public void onOpChanged(int op, String packageName) {
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800298 // onOpChanged invoked on ui thread, move to our thread to reduce risk
299 // of blocking ui thread
Soonil Nagarkar37096062019-11-25 13:24:48 -0800300 mHandler.post(() -> {
301 synchronized (mLock) {
302 onAppOpChangedLocked();
303 }
304 });
305 }
306 });
307 mPackageManager.addOnPermissionsChangeListener(
308 uid -> {
309 // listener invoked on ui thread, move to our thread to reduce risk of
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800310 // blocking ui thread
Soonil Nagarkar37096062019-11-25 13:24:48 -0800311 mHandler.post(() -> {
312 synchronized (mLock) {
313 onPermissionsChangedLocked();
314 }
315 });
316 });
317 mActivityManager.addOnUidImportanceListener(
318 (uid, importance) -> {
319 // listener invoked on ui thread, move to our thread to reduce risk of
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800320 // blocking ui thread
Soonil Nagarkar37096062019-11-25 13:24:48 -0800321 mHandler.post(() -> {
322 synchronized (mLock) {
323 onUidImportanceChangedLocked(uid, importance);
324 }
325 });
326 },
327 FOREGROUND_IMPORTANCE_CUTOFF);
328
329 localPowerManager.registerLowPowerModeObserver(ServiceType.LOCATION,
330 state -> {
331 // listener invoked on ui thread, move to our thread to reduce risk of
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800332 // blocking ui thread
Soonil Nagarkar37096062019-11-25 13:24:48 -0800333 mHandler.post(() -> {
334 synchronized (mLock) {
335 onBatterySaverModeChangedLocked(state.locationMode);
336 }
337 });
338 });
339 mBatterySaverMode = mPowerManager.getLocationPowerSaveMode();
340
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800341 mSettingsStore.addOnLocationEnabledChangedListener((userId) -> {
Soonil Nagarkar37096062019-11-25 13:24:48 -0800342 synchronized (mLock) {
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800343 onLocationModeChangedLocked(userId);
Soonil Nagarkar37096062019-11-25 13:24:48 -0800344 }
345 });
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800346 mSettingsStore.addOnLocationProvidersAllowedChangedListener((userId) -> {
Soonil Nagarkar37096062019-11-25 13:24:48 -0800347 synchronized (mLock) {
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800348 onProviderAllowedChangedLocked(userId);
Soonil Nagarkar37096062019-11-25 13:24:48 -0800349 }
350 });
351 mSettingsStore.addOnBackgroundThrottleIntervalChangedListener(() -> {
352 synchronized (mLock) {
353 onBackgroundThrottleIntervalChangedLocked();
354 }
355 });
356 mSettingsStore.addOnBackgroundThrottlePackageWhitelistChangedListener(() -> {
357 synchronized (mLock) {
358 onBackgroundThrottleWhitelistChangedLocked();
359 }
360 });
361 mSettingsStore.addOnIgnoreSettingsPackageWhitelistChangedListener(() -> {
362 synchronized (mLock) {
363 onIgnoreSettingsWhitelistChangedLocked();
364 }
365 });
366
367 new PackageMonitor() {
368 @Override
369 public void onPackageDisappeared(String packageName, int reason) {
370 synchronized (mLock) {
371 LocationManagerService.this.onPackageDisappearedLocked(packageName);
372 }
373 }
374 }.register(mContext, mHandler.getLooper(), true);
375
376 IntentFilter intentFilter = new IntentFilter();
377 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
378 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
379 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
380 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
381 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
382
383 mContext.registerReceiverAsUser(new BroadcastReceiver() {
384 @Override
385 public void onReceive(Context context, Intent intent) {
386 final String action = intent.getAction();
387 if (action == null) {
388 return;
389 }
390 synchronized (mLock) {
391 switch (action) {
392 case Intent.ACTION_USER_SWITCHED:
393 onUserChangedLocked(
394 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
395 break;
396 case Intent.ACTION_MANAGED_PROFILE_ADDED:
397 case Intent.ACTION_MANAGED_PROFILE_REMOVED:
398 onUserProfilesChangedLocked();
399 break;
400 case Intent.ACTION_SCREEN_ON:
401 case Intent.ACTION_SCREEN_OFF:
402 onScreenStateChangedLocked();
403 break;
404 }
405 }
406 }
407 }, UserHandle.ALL, intentFilter, null, mHandler);
408
409 // switching the user from null to system here performs the bulk of the initialization
410 // work. the user being changed will cause a reload of all user specific settings, which
411 // causes initialization, and propagates changes until a steady state is reached
412 mCurrentUserId = UserHandle.USER_NULL;
413 onUserChangedLocked(ActivityManager.getCurrentUser());
Victoria Lease5cd731a2012-12-19 15:04:21 -0800414 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800415 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700416
Soonil Nagarkar37096062019-11-25 13:24:48 -0800417 private void onSystemThirdPartyAppsCanStart() {
418 synchronized (mLock) {
419 // prepare providers
420 initializeProvidersLocked();
421 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700422 }
423
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800424 @GuardedBy("mLock")
425 private void onAppOpChangedLocked() {
426 for (Receiver receiver : mReceivers.values()) {
427 receiver.updateMonitoring(true);
428 }
429 for (LocationProvider p : mProviders) {
430 applyRequirementsLocked(p);
431 }
432 }
433
434 @GuardedBy("mLock")
435 private void onPermissionsChangedLocked() {
436 for (LocationProvider p : mProviders) {
437 applyRequirementsLocked(p);
438 }
439 }
440
441 @GuardedBy("mLock")
Kweku Adams4fb074e2019-02-01 16:03:27 -0800442 private void onBatterySaverModeChangedLocked(int newLocationMode) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700443 if (mBatterySaverMode == newLocationMode) {
444 return;
445 }
446
Kweku Adams4fb074e2019-02-01 16:03:27 -0800447 if (D) {
448 Slog.d(TAG,
449 "Battery Saver location mode changed from "
450 + locationPowerSaveModeToString(mBatterySaverMode) + " to "
451 + locationPowerSaveModeToString(newLocationMode));
452 }
453
Kweku Adams4fb074e2019-02-01 16:03:27 -0800454 mBatterySaverMode = newLocationMode;
Soonil Nagarkarb8466b72019-10-25 14:10:30 -0700455
Kweku Adams4fb074e2019-02-01 16:03:27 -0800456 for (LocationProvider p : mProviders) {
457 applyRequirementsLocked(p);
458 }
459 }
460
461 @GuardedBy("mLock")
462 private void onScreenStateChangedLocked() {
463 if (mBatterySaverMode == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF) {
464 for (LocationProvider p : mProviders) {
465 applyRequirementsLocked(p);
466 }
467 }
468 }
469
470 @GuardedBy("mLock")
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800471 private void onLocationModeChangedLocked(int userId) {
472 if (D) {
473 Log.d(TAG, "[u" + userId + "] location enabled = " + isLocationEnabledForUser(userId));
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800474 }
475
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800476 Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION);
477 intent.putExtra(LocationManager.EXTRA_LOCATION_ENABLED, isLocationEnabled());
478 mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800479
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800480 for (LocationProvider p : mProviders) {
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800481 p.onLocationModeChangedLocked(userId);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800482 }
483 }
484
485 @GuardedBy("mLock")
Soonil Nagarkar6bf751f2019-11-27 13:41:28 -0800486 private void onProviderAllowedChangedLocked(int userId) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800487 for (LocationProvider p : mProviders) {
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800488 p.onAllowedChangedLocked(userId);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800489 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800490 }
491
492 @GuardedBy("mLock")
493 private void onPackageDisappearedLocked(String packageName) {
494 ArrayList<Receiver> deadReceivers = null;
495
496 for (Receiver receiver : mReceivers.values()) {
Anil Admal08b96122019-01-30 16:55:05 -0800497 if (receiver.mCallerIdentity.mPackageName.equals(packageName)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800498 if (deadReceivers == null) {
499 deadReceivers = new ArrayList<>();
500 }
501 deadReceivers.add(receiver);
502 }
503 }
504
505 // perform removal outside of mReceivers loop
506 if (deadReceivers != null) {
507 for (Receiver receiver : deadReceivers) {
508 removeUpdatesLocked(receiver);
509 }
510 }
511 }
512
513 @GuardedBy("mLock")
514 private void onUidImportanceChangedLocked(int uid, int importance) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700515 boolean foreground = LocationManagerServiceUtils.isImportanceForeground(importance);
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700516 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800517 for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
518 String provider = entry.getKey();
519 for (UpdateRecord record : entry.getValue()) {
Anil Admal08b96122019-01-30 16:55:05 -0800520 if (record.mReceiver.mCallerIdentity.mUid == uid
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800521 && record.mIsForegroundUid != foreground) {
gomo48f1a642017-11-10 20:35:46 -0800522 if (D) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800523 Log.d(TAG, "request from uid " + uid + " is now "
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700524 + LocationManagerServiceUtils.foregroundAsString(
525 foreground));
gomo48f1a642017-11-10 20:35:46 -0800526 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800527 record.updateForeground(foreground);
528
Anil Admal08b96122019-01-30 16:55:05 -0800529 if (!isThrottlingExemptLocked(record.mReceiver.mCallerIdentity)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800530 affectedProviders.add(provider);
Soonil Nagarkare056b0d2017-06-21 13:08:16 -0700531 }
532 }
533 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800534 }
535 for (String provider : affectedProviders) {
536 applyRequirementsLocked(provider);
537 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -0800538 }
539
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800540 @GuardedBy("mLock")
541 private void onBackgroundThrottleIntervalChangedLocked() {
542 for (LocationProvider provider : mProviders) {
543 applyRequirementsLocked(provider);
Soonil Nagarkar68257742019-01-09 19:42:34 +0000544 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -0800545 }
546
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800547 @GuardedBy("mLock")
548 private void onBackgroundThrottleWhitelistChangedLocked() {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800549 for (LocationProvider p : mProviders) {
550 applyRequirementsLocked(p);
Soonil Nagarkar68257742019-01-09 19:42:34 +0000551 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -0800552 }
553
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800554 @GuardedBy("lock")
555 private void onIgnoreSettingsWhitelistChangedLocked() {
Soonil Nagarkar397ad582019-01-23 22:47:57 -0800556 for (LocationProvider p : mProviders) {
557 applyRequirementsLocked(p);
558 }
559 }
560
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800561 @GuardedBy("mLock")
562 private void onUserProfilesChangedLocked() {
563 mCurrentUserProfiles = mUserManager.getProfileIdsWithDisabled(mCurrentUserId);
564 }
565
566 @GuardedBy("mLock")
567 private boolean isCurrentProfileLocked(int userId) {
568 return ArrayUtils.contains(mCurrentUserProfiles, userId);
569 }
570
571 @GuardedBy("mLock")
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700572 private void ensureFallbackFusedProviderPresentLocked(String[] pkgs) {
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500573 PackageManager pm = mContext.getPackageManager();
574 String systemPackageName = mContext.getPackageName();
575 ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
576
577 List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
578 new Intent(FUSED_LOCATION_SERVICE_ACTION),
579 PackageManager.GET_META_DATA, mCurrentUserId);
580 for (ResolveInfo rInfo : rInfos) {
581 String packageName = rInfo.serviceInfo.packageName;
582
583 // Check that the signature is in the list of supported sigs. If it's not in
584 // this list the standard provider binding logic won't bind to it.
585 try {
586 PackageInfo pInfo;
587 pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
588 if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
589 Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
590 ", but has wrong signature, ignoring");
591 continue;
592 }
593 } catch (NameNotFoundException e) {
594 Log.e(TAG, "missing package: " + packageName);
595 continue;
596 }
597
598 // Get the version info
599 if (rInfo.serviceInfo.metaData == null) {
600 Log.w(TAG, "Found fused provider without metadata: " + packageName);
601 continue;
602 }
603
604 int version = rInfo.serviceInfo.metaData.getInt(
605 ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
606 if (version == 0) {
607 // This should be the fallback fused location provider.
608
609 // Make sure it's in the system partition.
610 if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
611 if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
612 continue;
613 }
614
615 // Check that the fallback is signed the same as the OS
616 // as a proxy for coreApp="true"
617 if (pm.checkSignatures(systemPackageName, packageName)
618 != PackageManager.SIGNATURE_MATCH) {
gomo48f1a642017-11-10 20:35:46 -0800619 if (D) {
620 Log.d(TAG, "Fallback candidate not signed the same as system: "
621 + packageName);
622 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500623 continue;
624 }
625
626 // Found a valid fallback.
627 if (D) Log.d(TAG, "Found fallback provider: " + packageName);
628 return;
629 } else {
630 if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
631 }
632 }
633
634 throw new IllegalStateException("Unable to find a fused location provider that is in the "
635 + "system partition with version 0 and signed with the platform certificate. "
636 + "Such a package is needed to provide a default fused location provider in the "
637 + "event that no other fused location provider has been installed or is currently "
638 + "available. For example, coreOnly boot mode when decrypting the data "
639 + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
640 }
641
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800642 @GuardedBy("mLock")
643 private void initializeProvidersLocked() {
Victoria Lease5c24fd02012-10-01 11:00:50 -0700644 // create a passive location provider, which is always enabled
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800645 LocationProvider passiveProviderManager = new LocationProvider(PASSIVE_PROVIDER);
Soonil Nagarkar68257742019-01-09 19:42:34 +0000646 addProviderLocked(passiveProviderManager);
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -0800647 mPassiveProvider = new PassiveProvider(mContext, passiveProviderManager);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800648 passiveProviderManager.attachLocked(mPassiveProvider);
Victoria Lease5c24fd02012-10-01 11:00:50 -0700649
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700650 if (GnssManagerService.isGnssSupported()) {
651 // Create a gps location provider manager
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800652 LocationProvider gnssProviderManager = new LocationProvider(GPS_PROVIDER, true);
653 mRealProviders.add(gnssProviderManager);
654 addProviderLocked(gnssProviderManager);
655
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700656 mGnssManagerService = new GnssManagerService(this, mContext, gnssProviderManager,
657 mLocationUsageLogger);
658 gnssProviderManager.attachLocked(mGnssManagerService.getGnssLocationProvider());
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700659 }
660
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700661 /*
662 Load package name(s) containing location provider support.
663 These packages can contain services implementing location providers:
664 Geocoder Provider, Network Location Provider, and
665 Fused Location Provider. They will each be searched for
666 service components implementing these providers.
667 The location framework also has support for installation
668 of new location providers at run-time. The new package does not
669 have to be explicitly listed here, however it must have a signature
670 that matches the signature of at least one package on this list.
671 */
672 Resources resources = mContext.getResources();
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500673 String[] pkgs = resources.getStringArray(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700674 com.android.internal.R.array.config_locationProviderPackageNames);
gomo48f1a642017-11-10 20:35:46 -0800675 if (D) {
676 Log.d(TAG, "certificates for location providers pulled from: " +
677 Arrays.toString(pkgs));
678 }
Jeff Hamiltonfbadb692012-10-05 14:21:58 -0500679
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700680 ensureFallbackFusedProviderPresentLocked(pkgs);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700681
682 // bind to network provider
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800683 LocationProvider networkProviderManager = new LocationProvider(NETWORK_PROVIDER, true);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700684 LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
685 mContext,
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700686 networkProviderManager,
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700687 NETWORK_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700688 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
689 com.android.internal.R.string.config_networkLocationProviderPackageName,
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700690 com.android.internal.R.array.config_locationProviderPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700691 if (networkProvider != null) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800692 mRealProviders.add(networkProviderManager);
Soonil Nagarkar68257742019-01-09 19:42:34 +0000693 addProviderLocked(networkProviderManager);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800694 networkProviderManager.attachLocked(networkProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700695 } else {
gomo48f1a642017-11-10 20:35:46 -0800696 Slog.w(TAG, "no network location provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700697 }
698
699 // bind to fused provider
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800700 LocationProvider fusedProviderManager = new LocationProvider(FUSED_PROVIDER);
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700701 LocationProviderProxy fusedProvider = LocationProviderProxy.createAndBind(
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700702 mContext,
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700703 fusedProviderManager,
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700704 FUSED_LOCATION_SERVICE_ACTION,
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700705 com.android.internal.R.bool.config_enableFusedLocationOverlay,
706 com.android.internal.R.string.config_fusedLocationProviderPackageName,
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700707 com.android.internal.R.array.config_locationProviderPackageNames);
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700708 if (fusedProvider != null) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800709 mRealProviders.add(fusedProviderManager);
Soonil Nagarkar68257742019-01-09 19:42:34 +0000710 addProviderLocked(fusedProviderManager);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800711 fusedProviderManager.attachLocked(fusedProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700712 } else {
713 Slog.e(TAG, "no fused location provider found",
714 new IllegalStateException("Location service needs a fused location provider"));
715 }
716
717 // bind to geocoder provider
Zhentao Sunc5fc9982013-04-17 17:47:53 -0700718 mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
719 com.android.internal.R.bool.config_enableGeocoderOverlay,
720 com.android.internal.R.string.config_geocoderProviderPackageName,
Soonil Nagarkare731ca82018-11-02 13:55:51 -0700721 com.android.internal.R.array.config_locationProviderPackageNames);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700722 if (mGeocodeProvider == null) {
gomo48f1a642017-11-10 20:35:46 -0800723 Slog.e(TAG, "no geocoder provider found");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700724 }
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700725
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700726 if (mGnssManagerService != null) {
727 // bind to geofence provider
728 GeofenceProxy provider = GeofenceProxy.createAndBind(
729 mContext, com.android.internal.R.bool.config_enableGeofenceOverlay,
730 com.android.internal.R.string.config_geofenceProviderPackageName,
731 com.android.internal.R.array.config_locationProviderPackageNames,
732 mGnssManagerService.getGpsGeofenceProxy(),
733 null);
734 if (provider == null) {
735 Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
736 }
destradaa0682809a2013-08-12 18:50:30 -0700737 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900738
Brian Duddiecfa5b5b2019-01-22 18:01:40 +0000739 // bind to hardware activity recognition
740 boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
741 ActivityRecognitionHardware activityRecognitionHardware = null;
742 if (activityRecognitionHardwareIsSupported) {
743 activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
744 } else {
745 Slog.d(TAG, "Hardware Activity-Recognition not supported.");
746 }
747 ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
748 mContext,
749 activityRecognitionHardwareIsSupported,
750 activityRecognitionHardware,
751 com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
752 com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
753 com.android.internal.R.array.config_locationProviderPackageNames);
754 if (proxy == null) {
755 Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
756 }
757
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900758 String[] testProviderStrings = resources.getStringArray(
759 com.android.internal.R.array.config_testLocationProviders);
760 for (String testProviderString : testProviderStrings) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -0800761 String[] fragments = testProviderString.split(",");
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900762 String name = fragments[0].trim();
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900763 ProviderProperties properties = new ProviderProperties(
764 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
765 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
766 Boolean.parseBoolean(fragments[3]) /* requiresCell */,
767 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
768 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
769 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
770 Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
771 Integer.parseInt(fragments[8]) /* powerRequirement */,
772 Integer.parseInt(fragments[9]) /* accuracy */);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800773 LocationProvider testProviderManager = new LocationProvider(name);
774 addProviderLocked(testProviderManager);
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700775 testProviderManager.attachLocked(
776 new MockProvider(mContext, testProviderManager, properties));
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +0900777 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700778 }
Mike Lockwood9637d472009-04-02 21:41:57 -0700779
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800780 @GuardedBy("mLock")
781 private void onUserChangedLocked(int userId) {
Jianzheng Zhoud5c69462013-10-10 14:02:09 +0800782 if (mCurrentUserId == userId) {
783 return;
784 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800785
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800786 if (D) {
787 Log.d(TAG, "foreground user is changing to " + userId);
788 }
789
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800790 int oldUserId = userId;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800791 mCurrentUserId = userId;
792 onUserProfilesChangedLocked();
793
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800794 // let providers know the current user has changed
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800795 for (LocationProvider p : mProviders) {
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800796 p.onCurrentUserChangedLocked(oldUserId);
797 p.onCurrentUserChangedLocked(mCurrentUserId);
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800798 }
Victoria Lease38389b62012-09-30 11:44:22 -0700799 }
800
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700801 /**
802 * Location provider manager, manages a LocationProvider.
803 */
804 class LocationProvider implements AbstractLocationProvider.LocationProviderManager {
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700805
806 private final String mName;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700807
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800808 // whether this provider should respect LOCATION_PROVIDERS_ALLOWED (ie gps and network)
809 private final boolean mIsManagedBySettings;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700810
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800811 // remember to clear binder identity before invoking any provider operation
812 @GuardedBy("mLock")
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700813 @Nullable
814 protected AbstractLocationProvider mProvider;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700815
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800816 @GuardedBy("mLock")
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800817 private SparseArray<Boolean> mUseable; // combined state for each user id
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800818 @GuardedBy("mLock")
819 private boolean mAllowed; // state of LOCATION_PROVIDERS_ALLOWED
820 @GuardedBy("mLock")
821 private boolean mEnabled; // state of provider
822
823 @GuardedBy("mLock")
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700824 @Nullable
825 private ProviderProperties mProperties;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700826
827 private LocationProvider(String name) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800828 this(name, false);
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700829 }
830
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800831 private LocationProvider(String name, boolean isManagedBySettings) {
832 mName = name;
833 mIsManagedBySettings = isManagedBySettings;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700834
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800835 mProvider = null;
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800836 mUseable = new SparseArray<>(1);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800837 mAllowed = !mIsManagedBySettings;
838 mEnabled = false;
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700839 mProperties = null;
Soonil Nagarkar42da1b12019-01-22 11:29:27 -0800840
841 if (mIsManagedBySettings) {
842 // since we assume providers are disabled by default
843 Settings.Secure.putStringForUser(
844 mContext.getContentResolver(),
845 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
846 "-" + mName,
847 mCurrentUserId);
848 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700849 }
850
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800851 @GuardedBy("mLock")
852 public void attachLocked(AbstractLocationProvider provider) {
853 checkNotNull(provider);
854 checkState(mProvider == null);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800855
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -0800856 if (D) {
857 Log.d(TAG, mName + " provider attached");
858 }
859
860 mProvider = provider;
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800861
862 // it would be more correct to call this for all users, but we know this can only
863 // affect the current user since providers are disabled for non-current users
864 onUseableChangedLocked(false, mCurrentUserId);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800865 }
866
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700867 public String getName() {
868 return mName;
869 }
870
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800871 @GuardedBy("mLock")
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -0800872 public List<String> getPackagesLocked() {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800873 if (mProvider == null) {
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -0800874 return Collections.emptyList();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800875 } else {
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -0800876 // safe to not clear binder context since this doesn't call into the real provider
877 return mProvider.getProviderPackages();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800878 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700879 }
880
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800881 public boolean isMock() {
882 return false;
883 }
884
885 @GuardedBy("mLock")
886 public boolean isPassiveLocked() {
887 return mProvider == mPassiveProvider;
888 }
889
890 @GuardedBy("mLock")
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700891 @Nullable
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800892 public ProviderProperties getPropertiesLocked() {
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700893 return mProperties;
894 }
895
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700896 public void setRequest(ProviderRequest request, WorkSource workSource) {
897 // move calls going to providers onto a different thread to avoid deadlock
898 mHandler.post(() -> {
899 synchronized (mLock) {
900 if (mProvider != null) {
901 mProvider.onSetRequest(request, workSource);
902 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800903 }
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700904 });
905 }
906
907 public void sendExtraCommand(String command, Bundle extras) {
908 int uid = Binder.getCallingUid();
909 int pid = Binder.getCallingPid();
910
911 // move calls going to providers onto a different thread to avoid deadlock
912 mHandler.post(() -> {
913 synchronized (mLock) {
914 if (mProvider != null) {
915 mProvider.onSendExtraCommand(uid, pid, command, extras);
916 }
917 }
918 });
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700919 }
920
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800921 @GuardedBy("mLock")
Soonil Nagarkar1c572552019-07-10 13:31:47 -0700922 public void dumpLocked(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
923 pw.print(mName + " provider");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800924 if (isMock()) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -0800925 pw.print(" [mock]");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800926 }
Soonil Nagarkarb46c1672019-02-06 12:49:10 -0800927 pw.println(":");
928
Soonil Nagarkar1c572552019-07-10 13:31:47 -0700929 pw.increaseIndent();
930
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800931 pw.println("useable=" + isUseableLocked(mCurrentUserId));
932 if (!isUseableLocked(mCurrentUserId)) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -0700933 pw.println("attached=" + (mProvider != null));
Soonil Nagarkarb46c1672019-02-06 12:49:10 -0800934 if (mIsManagedBySettings) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -0700935 pw.println("allowed=" + mAllowed);
Soonil Nagarkarb46c1672019-02-06 12:49:10 -0800936 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -0700937 pw.println("enabled=" + mEnabled);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800938 }
Soonil Nagarkarb46c1672019-02-06 12:49:10 -0800939
Soonil Nagarkar1c572552019-07-10 13:31:47 -0700940 pw.println("properties=" + mProperties);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800941
942 if (mProvider != null) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -0700943 // in order to be consistent with other provider APIs, this should be run on the
944 // location thread... but this likely isn't worth it just for dumping info.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800945 long identity = Binder.clearCallingIdentity();
946 try {
947 mProvider.dump(fd, pw, args);
948 } finally {
949 Binder.restoreCallingIdentity(identity);
950 }
951 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -0700952
953 pw.decreaseIndent();
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700954 }
955
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700956 @Override
957 public void onReportLocation(Location location) {
Soonil Nagarkar7fc24c62019-10-18 17:32:38 -0700958 // likelihood of a 0,0 bug is far greater than this being a valid location
959 if (!isMock() && location.getLatitude() == 0 && location.getLongitude() == 0) {
960 Slog.w(TAG, "blocking 0,0 location from " + mName + " provider");
961 return;
962 }
963
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700964 synchronized (mLock) {
965 handleLocationChangedLocked(location, this);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800966 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700967 }
968
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700969 @Override
970 public void onReportLocation(List<Location> locations) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700971 if (mGnssManagerService == null) {
972 return;
973 }
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700974 synchronized (mLock) {
975 LocationProvider gpsProvider = getLocationProviderLocked(GPS_PROVIDER);
976 if (gpsProvider == null || !gpsProvider.isUseableLocked()) {
977 Slog.w(TAG, "reportLocationBatch() called without user permission");
978 return;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800979 }
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700980
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -0700981 mGnssManagerService.onReportLocation(locations);
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700982 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700983 }
984
Soonil Nagarkar1575a042018-10-24 17:54:54 -0700985 @Override
986 public void onSetEnabled(boolean enabled) {
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700987 synchronized (mLock) {
988 if (enabled == mEnabled) {
989 return;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -0800990 }
Soonil Nagarkard334f7b2019-07-08 16:16:19 -0700991
992 if (D) {
993 Log.d(TAG, mName + " provider enabled is now " + mEnabled);
994 }
995
996 mEnabled = enabled;
Soonil Nagarkar06e37f62019-12-04 16:05:08 -0800997
998 // it would be more correct to call this for all users, but we know this can only
999 // affect the current user since providers are disabled for non-current users
1000 onUseableChangedLocked(false, mCurrentUserId);
Soonil Nagarkard334f7b2019-07-08 16:16:19 -07001001 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001002 }
1003
1004 @Override
1005 public void onSetProperties(ProviderProperties properties) {
Soonil Nagarkar66c0bac2019-01-15 13:36:44 -08001006 synchronized (mLock) {
1007 mProperties = properties;
1008 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001009 }
1010
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001011 @GuardedBy("mLock")
Soonil Nagarkar06e37f62019-12-04 16:05:08 -08001012 public void onLocationModeChangedLocked(int userId) {
1013 if (!isCurrentProfileLocked(userId)) {
1014 return;
1015 }
1016
1017 onUseableChangedLocked(false, userId);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001018 }
1019
1020 @GuardedBy("mLock")
Soonil Nagarkar06e37f62019-12-04 16:05:08 -08001021 public void onAllowedChangedLocked(int userId) {
1022 if (!isCurrentProfileLocked(userId)) {
1023 return;
1024 }
1025
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001026 if (mIsManagedBySettings) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07001027 boolean allowed = mSettingsStore.getLocationProvidersAllowed(
1028 mCurrentUserId).contains(mName);
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001029
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001030 if (allowed == mAllowed) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00001031 return;
1032 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001033
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001034 if (D) {
1035 Log.d(TAG, mName + " provider allowed is now " + mAllowed);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001036 }
1037
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001038 mAllowed = allowed;
Soonil Nagarkar06e37f62019-12-04 16:05:08 -08001039 onUseableChangedLocked(true, userId);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001040 }
1041 }
1042
1043 @GuardedBy("mLock")
Soonil Nagarkar06e37f62019-12-04 16:05:08 -08001044 public void onCurrentUserChangedLocked(int userId) {
1045 onUseableChangedLocked(false, userId);
1046 }
1047
1048 @GuardedBy("mLock")
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001049 public boolean isUseableLocked() {
Soonil Nagarkar06e37f62019-12-04 16:05:08 -08001050 return isUseableLocked(mCurrentUserId);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001051 }
1052
1053 @GuardedBy("mLock")
Soonil Nagarkar06e37f62019-12-04 16:05:08 -08001054 public boolean isUseableLocked(int userId) {
1055 return mUseable.get(userId, Boolean.FALSE);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001056 }
1057
1058 @GuardedBy("mLock")
Soonil Nagarkar06e37f62019-12-04 16:05:08 -08001059 public void onUseableChangedLocked(boolean isAllowedChanged, int userId) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001060 // if any property that contributes to "useability" here changes state, it MUST result
1061 // in a direct or indrect call to onUseableChangedLocked. this allows the provider to
1062 // guarantee that it will always eventually reach the correct state.
Soonil Nagarkar06e37f62019-12-04 16:05:08 -08001063 boolean useableIgnoringAllowed = mProvider != null && mProviders.contains(this)
1064 && isCurrentProfileLocked(userId) && isLocationEnabledForUser(userId)
1065 && mEnabled;
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001066 boolean useable = useableIgnoringAllowed && mAllowed;
1067
Soonil Nagarkar06e37f62019-12-04 16:05:08 -08001068 // update deprecated provider allowed settings for backwards compatibility
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001069 if (mIsManagedBySettings) {
1070 // a "-" change derived from the allowed setting should not be overwritten, but a
1071 // "+" change should be corrected if necessary
1072 if (useableIgnoringAllowed && !isAllowedChanged) {
1073 Settings.Secure.putStringForUser(
1074 mContext.getContentResolver(),
1075 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
1076 "+" + mName,
Soonil Nagarkar06e37f62019-12-04 16:05:08 -08001077 userId);
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001078 } else if (!useableIgnoringAllowed) {
1079 Settings.Secure.putStringForUser(
1080 mContext.getContentResolver(),
1081 Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
1082 "-" + mName,
Soonil Nagarkar06e37f62019-12-04 16:05:08 -08001083 userId);
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001084 }
Soonil Nagarkar3126c902019-03-04 18:29:49 -08001085
Soonil Nagarkar3126c902019-03-04 18:29:49 -08001086 Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION);
1087 intent.putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName);
Soonil Nagarkar06e37f62019-12-04 16:05:08 -08001088 intent.putExtra(LocationManager.EXTRA_PROVIDER_ENABLED, useable);
1089 mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001090 }
1091
Soonil Nagarkar06e37f62019-12-04 16:05:08 -08001092 if (useable == isUseableLocked(userId)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001093 return;
1094 }
Soonil Nagarkar06e37f62019-12-04 16:05:08 -08001095 mUseable.put(userId, useable);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001096
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001097 if (D) {
Soonil Nagarkar06e37f62019-12-04 16:05:08 -08001098 Log.d(TAG, "[u" + userId + "] " + mName + " provider useable = " + useable);
Soonil Nagarkar4ee3ac22019-02-08 19:19:24 -08001099 }
1100
Soonil Nagarkar06e37f62019-12-04 16:05:08 -08001101 if (!useable) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001102 // If any provider has been disabled, clear all last locations for all
1103 // providers. This is to be on the safe side in case a provider has location
1104 // derived from this disabled provider.
1105 mLastLocation.clear();
1106 mLastLocationCoarseInterval.clear();
1107 }
1108
1109 updateProviderUseableLocked(this);
1110 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001111 }
1112
1113 private class MockLocationProvider extends LocationProvider {
1114
Kweku Adams4fb074e2019-02-01 16:03:27 -08001115 private ProviderRequest mCurrentRequest;
1116
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001117 private MockLocationProvider(String name) {
1118 super(name);
1119 }
1120
1121 @Override
1122 public void attachLocked(AbstractLocationProvider provider) {
1123 checkState(provider instanceof MockProvider);
1124 super.attachLocked(provider);
1125 }
1126
1127 public boolean isMock() {
1128 return true;
1129 }
1130
1131 @GuardedBy("mLock")
1132 public void setEnabledLocked(boolean enabled) {
1133 if (mProvider != null) {
1134 long identity = Binder.clearCallingIdentity();
1135 try {
1136 ((MockProvider) mProvider).setEnabled(enabled);
1137 } finally {
1138 Binder.restoreCallingIdentity(identity);
Soonil Nagarkar68257742019-01-09 19:42:34 +00001139 }
1140 }
1141 }
1142
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001143 @GuardedBy("mLock")
1144 public void setLocationLocked(Location location) {
1145 if (mProvider != null) {
1146 long identity = Binder.clearCallingIdentity();
1147 try {
1148 ((MockProvider) mProvider).setLocation(location);
1149 } finally {
1150 Binder.restoreCallingIdentity(identity);
1151 }
1152 }
1153 }
1154
Kweku Adams4fb074e2019-02-01 16:03:27 -08001155 @Override
Soonil Nagarkard334f7b2019-07-08 16:16:19 -07001156 public void setRequest(ProviderRequest request, WorkSource workSource) {
1157 super.setRequest(request, workSource);
Kweku Adams4fb074e2019-02-01 16:03:27 -08001158 mCurrentRequest = request;
1159 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001160 }
1161
Victoria Lease38389b62012-09-30 11:44:22 -07001162 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163 * A wrapper class holding either an ILocationListener or a PendingIntent to receive
1164 * location updates.
1165 */
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001166 private final class Receiver extends LocationManagerServiceUtils.LinkedListenerBase implements
1167 PendingIntent.OnFinished {
Yu-Han Yang24189822018-07-11 15:24:11 -07001168 private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001169 private final int mAllowedResolutionLevel; // resolution level allowed to receiver
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001170
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001171 private final ILocationListener mListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172 final PendingIntent mPendingIntent;
David Christie82edc9b2013-07-19 11:31:42 -07001173 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001174 private final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
1175 private final Object mKey;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001176
gomo48f1a642017-11-10 20:35:46 -08001177 final HashMap<String, UpdateRecord> mUpdateRecords = new HashMap<>();
Nick Pellyf1be6862012-05-15 10:53:42 -07001178
David Christie0b837452013-07-29 16:02:13 -07001179 // True if app ops has started monitoring this receiver for locations.
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001180 private boolean mOpMonitoring;
David Christie0b837452013-07-29 16:02:13 -07001181 // True if app ops has started monitoring this receiver for high power (gps) locations.
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001182 private boolean mOpHighPowerMonitoring;
1183 private int mPendingBroadcasts;
Victoria Lease0aa28602013-05-29 15:28:26 -07001184 PowerManager.WakeLock mWakeLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001185
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001186 private Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001187 String packageName, @Nullable String featureId, WorkSource workSource,
1188 boolean hideFromAppOps, @NonNull String listenerIdentifier) {
1189 super(new CallerIdentity(uid, pid, packageName, featureId, listenerIdentifier),
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001190 "LocationListener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001191 mListener = listener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001192 mPendingIntent = intent;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001193 if (listener != null) {
1194 mKey = listener.asBinder();
1195 } else {
1196 mKey = intent;
1197 }
Victoria Lease37425c32012-10-16 16:08:48 -07001198 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
Narayan Kamath32684dd2018-01-08 17:32:51 +00001199 if (workSource != null && workSource.isEmpty()) {
David Christie82edc9b2013-07-19 11:31:42 -07001200 workSource = null;
1201 }
1202 mWorkSource = workSource;
David Christie40e57822013-07-30 11:36:48 -07001203 mHideFromAppOps = hideFromAppOps;
Victoria Lease0aa28602013-05-29 15:28:26 -07001204
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001205 updateMonitoring(true);
1206
Victoria Lease0aa28602013-05-29 15:28:26 -07001207 // construct/configure wakelock
1208 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
David Christie82edc9b2013-07-19 11:31:42 -07001209 if (workSource == null) {
Anil Admal08b96122019-01-30 16:55:05 -08001210 workSource = new WorkSource(mCallerIdentity.mUid, mCallerIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001211 }
1212 mWakeLock.setWorkSource(workSource);
Yu-Han Yang24189822018-07-11 15:24:11 -07001213
1214 // For a non-reference counted wakelock, each acquire will reset the timeout, and we
1215 // only need to release it once.
1216 mWakeLock.setReferenceCounted(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001217 }
1218
1219 @Override
1220 public boolean equals(Object otherObj) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001221 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001222 }
1223
1224 @Override
1225 public int hashCode() {
1226 return mKey.hashCode();
1227 }
Mike Lockwood3681f262009-05-12 10:52:03 -04001228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001229 @Override
1230 public String toString() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001231 StringBuilder s = new StringBuilder();
1232 s.append("Reciever[");
1233 s.append(Integer.toHexString(System.identityHashCode(this)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001234 if (mListener != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001235 s.append(" listener");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001236 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001237 s.append(" intent");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001238 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001239 for (String p : mUpdateRecords.keySet()) {
1240 s.append(" ").append(mUpdateRecords.get(p).toString());
1241 }
Wei Wangdd070f22018-06-21 11:29:40 -07001242 s.append(" monitoring location: ").append(mOpMonitoring);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001243 s.append("]");
1244 return s.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001245 }
1246
David Christie15b31912013-08-13 15:54:32 -07001247 /**
1248 * Update AppOp monitoring for this receiver.
1249 *
1250 * @param allow If true receiver is currently active, if false it's been removed.
1251 */
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001252 public void updateMonitoring(boolean allow) {
David Christie40e57822013-07-30 11:36:48 -07001253 if (mHideFromAppOps) {
1254 return;
1255 }
1256
David Christie15b31912013-08-13 15:54:32 -07001257 boolean requestingLocation = false;
1258 boolean requestingHighPowerLocation = false;
1259 if (allow) {
1260 // See if receiver has any enabled update records. Also note if any update records
1261 // are high power (has a high power provider with an interval under a threshold).
1262 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001263 LocationProvider provider = getLocationProviderLocked(updateRecord.mProvider);
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001264 if (provider == null) {
1265 continue;
1266 }
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001267 if (!provider.isUseableLocked() && !isSettingsExemptLocked(updateRecord)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001268 continue;
1269 }
1270
1271 requestingLocation = true;
1272 ProviderProperties properties = provider.getPropertiesLocked();
1273 if (properties != null
1274 && properties.mPowerRequirement == Criteria.POWER_HIGH
1275 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
1276 requestingHighPowerLocation = true;
1277 break;
David Christie15b31912013-08-13 15:54:32 -07001278 }
1279 }
1280 }
1281
David Christie0b837452013-07-29 16:02:13 -07001282 // First update monitoring of any location request (including high power).
David Christie15b31912013-08-13 15:54:32 -07001283 mOpMonitoring = updateMonitoring(
1284 requestingLocation,
1285 mOpMonitoring,
David Christie0b837452013-07-29 16:02:13 -07001286 AppOpsManager.OP_MONITOR_LOCATION);
1287
1288 // Now update monitoring of high power requests only.
David Christiec750c1f2013-08-08 12:56:57 -07001289 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
David Christie15b31912013-08-13 15:54:32 -07001290 mOpHighPowerMonitoring = updateMonitoring(
1291 requestingHighPowerLocation,
1292 mOpHighPowerMonitoring,
David Christie0b837452013-07-29 16:02:13 -07001293 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
David Christiec750c1f2013-08-08 12:56:57 -07001294 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
David Christie15b31912013-08-13 15:54:32 -07001295 // Send an intent to notify that a high power request has been added/removed.
David Christiec750c1f2013-08-08 12:56:57 -07001296 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
1297 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
1298 }
David Christie0b837452013-07-29 16:02:13 -07001299 }
1300
1301 /**
1302 * Update AppOps monitoring for a single location request and op type.
1303 *
gomo48f1a642017-11-10 20:35:46 -08001304 * @param allowMonitoring True if monitoring is allowed for this request/op.
David Christie0b837452013-07-29 16:02:13 -07001305 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
gomo48f1a642017-11-10 20:35:46 -08001306 * @param op AppOps code for the op to update.
David Christie0b837452013-07-29 16:02:13 -07001307 * @return True if monitoring is on for this request/op after updating.
1308 */
1309 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
1310 int op) {
1311 if (!currentlyMonitoring) {
1312 if (allowMonitoring) {
Anil Admal08b96122019-01-30 16:55:05 -08001313 return mAppOps.startOpNoThrow(op, mCallerIdentity.mUid,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001314 mCallerIdentity.mPackageName, false, mCallerIdentity.mFeatureId, null)
1315 == AppOpsManager.MODE_ALLOWED;
David Christie0b837452013-07-29 16:02:13 -07001316 }
1317 } else {
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001318 if (!allowMonitoring
Wei Wang16276a42019-02-04 18:23:31 -08001319 || mAppOps.checkOpNoThrow(op, mCallerIdentity.mUid,
Anil Admal08b96122019-01-30 16:55:05 -08001320 mCallerIdentity.mPackageName) != AppOpsManager.MODE_ALLOWED) {
1321 mAppOps.finishOp(op, mCallerIdentity.mUid, mCallerIdentity.mPackageName);
David Christie0b837452013-07-29 16:02:13 -07001322 return false;
1323 }
1324 }
1325
1326 return currentlyMonitoring;
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07001327 }
1328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 public boolean isListener() {
1330 return mListener != null;
1331 }
1332
1333 public boolean isPendingIntent() {
1334 return mPendingIntent != null;
1335 }
1336
1337 public ILocationListener getListener() {
1338 if (mListener != null) {
1339 return mListener;
1340 }
1341 throw new IllegalStateException("Request for non-existent listener");
1342 }
1343
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001344 public boolean callLocationChangedLocked(Location location) {
1345 if (mListener != null) {
1346 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001347 mListener.onLocationChanged(new Location(location));
1348 // call this after broadcasting so we do not increment
1349 // if we throw an exception.
1350 incrementPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351 } catch (RemoteException e) {
1352 return false;
1353 }
1354 } else {
1355 Intent locationChanged = new Intent();
gomo48f1a642017-11-10 20:35:46 -08001356 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED,
1357 new Location(location));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001359 mPendingIntent.send(mContext, 0, locationChanged, this, mHandler,
1360 getResolutionPermission(mAllowedResolutionLevel),
1361 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
1362 // call this after broadcasting so we do not increment
1363 // if we throw an exception.
1364 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001365 } catch (PendingIntent.CanceledException e) {
1366 return false;
1367 }
1368 }
1369 return true;
1370 }
1371
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001372 private boolean callProviderEnabledLocked(String provider, boolean enabled) {
David Christie15b31912013-08-13 15:54:32 -07001373 // First update AppOp monitoring.
1374 // An app may get/lose location access as providers are enabled/disabled.
1375 updateMonitoring(true);
1376
Mike Lockwood48f17512009-04-23 09:12:08 -07001377 if (mListener != null) {
1378 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001379 if (enabled) {
1380 mListener.onProviderEnabled(provider);
1381 } else {
1382 mListener.onProviderDisabled(provider);
Mike Lockwood48f17512009-04-23 09:12:08 -07001383 }
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001384 // call this after broadcasting so we do not increment
1385 // if we throw an exception.
1386 incrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001387 } catch (RemoteException e) {
1388 return false;
1389 }
1390 } else {
1391 Intent providerIntent = new Intent();
1392 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1393 try {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001394 mPendingIntent.send(mContext, 0, providerIntent, this, mHandler,
1395 getResolutionPermission(mAllowedResolutionLevel),
1396 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
1397 // call this after broadcasting so we do not increment
1398 // if we throw an exception.
1399 incrementPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001400 } catch (PendingIntent.CanceledException e) {
1401 return false;
1402 }
1403 }
1404 return true;
1405 }
1406
Soonil Nagarkar39d614a2019-10-31 12:10:31 -07001407 public void callRemovedLocked() {
1408 if (mListener != null) {
1409 try {
1410 mListener.onRemoved();
1411 } catch (RemoteException e) {
1412 // doesn't matter
1413 }
1414 }
1415 }
1416
Nick Pellyf1be6862012-05-15 10:53:42 -07001417 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001418 public void binderDied() {
Anil Admal98d49b72019-02-06 15:26:33 -08001419 if (D) Log.d(TAG, "Remote " + mListenerName + " died.");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001420
Soonil Nagarkar68257742019-01-09 19:42:34 +00001421 synchronized (mLock) {
1422 removeUpdatesLocked(this);
Soonil Nagarkar68257742019-01-09 19:42:34 +00001423 clearPendingBroadcastsLocked();
1424 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001425 }
1426
Nick Pellye0fd6932012-07-11 10:26:13 -07001427 @Override
Mike Lockwood48f17512009-04-23 09:12:08 -07001428 public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1429 int resultCode, String resultData, Bundle resultExtras) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001430 synchronized (mLock) {
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001431 decrementPendingBroadcastsLocked();
Mike Lockwood48f17512009-04-23 09:12:08 -07001432 }
1433 }
1434
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001435 // this must be called while synchronized by caller in a synchronized block
1436 // containing the sending of the broadcaset
1437 private void incrementPendingBroadcastsLocked() {
Yu-Han Yang24189822018-07-11 15:24:11 -07001438 mPendingBroadcasts++;
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001439 // so wakelock calls will succeed
1440 long identity = Binder.clearCallingIdentity();
1441 try {
1442 mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
1443 } finally {
1444 Binder.restoreCallingIdentity(identity);
1445 }
Mike Lockwood0528b9b2009-05-07 10:12:54 -04001446 }
1447
1448 private void decrementPendingBroadcastsLocked() {
1449 if (--mPendingBroadcasts == 0) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001450 // so wakelock calls will succeed
1451 long identity = Binder.clearCallingIdentity();
1452 try {
1453 if (mWakeLock.isHeld()) {
1454 mWakeLock.release();
1455 }
1456 } finally {
1457 Binder.restoreCallingIdentity(identity);
Victoria Lease0aa28602013-05-29 15:28:26 -07001458 }
1459 }
1460 }
1461
1462 public void clearPendingBroadcastsLocked() {
1463 if (mPendingBroadcasts > 0) {
1464 mPendingBroadcasts = 0;
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001465 // so wakelock calls will succeed
1466 long identity = Binder.clearCallingIdentity();
1467 try {
1468 if (mWakeLock.isHeld()) {
1469 mWakeLock.release();
1470 }
1471 } finally {
1472 Binder.restoreCallingIdentity(identity);
Victoria Lease0aa28602013-05-29 15:28:26 -07001473 }
Mike Lockwood48f17512009-04-23 09:12:08 -07001474 }
1475 }
1476 }
1477
Nick Pellye0fd6932012-07-11 10:26:13 -07001478 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001479 public void locationCallbackFinished(ILocationListener listener) {
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001480 //Do not use getReceiverLocked here as that will add the ILocationListener to
Joshua Bartel080b61b2009-10-05 12:44:46 -04001481 //the receiver list if it is not found. If it is not found then the
1482 //LocationListener was removed when it had a pending broadcast and should
1483 //not be added back.
Soonil Nagarkar68257742019-01-09 19:42:34 +00001484 synchronized (mLock) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001485 Receiver receiver = mReceivers.get(listener.asBinder());
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001486 if (receiver != null) {
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001487 receiver.decrementPendingBroadcastsLocked();
Dianne Hackbornf5fdca92013-06-05 14:53:33 -07001488 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00001489 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 }
1491
Lifu Tang82f893d2016-01-21 18:15:33 -08001492 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001493 public int getGnssYearOfHardware() {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001494 return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001495 }
1496
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001497 @Override
Wyatt Riley49097c02018-03-15 09:14:43 -07001498 @Nullable
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001499 public String getGnssHardwareModelName() {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001500 return mGnssManagerService == null ? "" : mGnssManagerService.getGnssHardwareModelName();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001501 }
1502
Wyatt Rileycf879db2017-01-12 13:57:38 -08001503 @Override
1504 public int getGnssBatchSize(String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001505 return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssBatchSize(packageName);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001506 }
1507
Wyatt Rileycf879db2017-01-12 13:57:38 -08001508 @Override
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001509 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001510 String featureId, String listenerIdentifier) {
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001511 Preconditions.checkNotNull(listenerIdentifier);
1512
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001513 return mGnssManagerService == null ? false : mGnssManagerService.addGnssBatchingCallback(
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001514 callback, packageName, featureId, listenerIdentifier);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001515 }
1516
Wyatt Rileycf879db2017-01-12 13:57:38 -08001517 @Override
1518 public void removeGnssBatchingCallback() {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001519 if (mGnssManagerService != null) mGnssManagerService.removeGnssBatchingCallback();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001520 }
1521
Wyatt Rileycf879db2017-01-12 13:57:38 -08001522 @Override
1523 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001524 return mGnssManagerService == null ? false : mGnssManagerService.startGnssBatch(periodNanos,
1525 wakeOnFifoFull, packageName);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001526 }
1527
Wyatt Rileycf879db2017-01-12 13:57:38 -08001528 @Override
1529 public void flushGnssBatch(String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001530 if (mGnssManagerService != null) mGnssManagerService.flushGnssBatch(packageName);
Wyatt Rileycf879db2017-01-12 13:57:38 -08001531 }
1532
Wyatt Rileycf879db2017-01-12 13:57:38 -08001533 @Override
1534 public boolean stopGnssBatch() {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001535 return mGnssManagerService == null ? false : mGnssManagerService.stopGnssBatch();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001536 }
1537
1538 @GuardedBy("mLock")
1539 private void addProviderLocked(LocationProvider provider) {
1540 Preconditions.checkState(getLocationProviderLocked(provider.getName()) == null);
1541
1542 mProviders.add(provider);
1543
Soonil Nagarkar06e37f62019-12-04 16:05:08 -08001544 // allowed state may change while provider was inactive
1545 provider.onAllowedChangedLocked(mCurrentUserId);
1546
1547 // it would be more correct to call this for all users, but we know this can only
1548 // affect the current user since providers are disabled for non-current users
1549 provider.onUseableChangedLocked(false, mCurrentUserId);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001550 }
1551
1552 @GuardedBy("mLock")
1553 private void removeProviderLocked(LocationProvider provider) {
1554 if (mProviders.remove(provider)) {
Soonil Nagarkar06e37f62019-12-04 16:05:08 -08001555 // it would be more correct to call this for all users, but we know this can only
1556 // affect the current user since providers are disabled for non-current users
1557 provider.onUseableChangedLocked(false, mCurrentUserId);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001558 }
1559 }
1560
1561 @GuardedBy("mLock")
1562 @Nullable
1563 private LocationProvider getLocationProviderLocked(String providerName) {
1564 for (LocationProvider provider : mProviders) {
1565 if (providerName.equals(provider.getName())) {
1566 return provider;
Soonil Nagarkar68257742019-01-09 19:42:34 +00001567 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001568 }
1569
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001570 return null;
Maggie2a9409e2018-03-21 11:47:28 -07001571 }
1572
Victoria Lease37425c32012-10-16 16:08:48 -07001573 private String getResolutionPermission(int resolutionLevel) {
1574 switch (resolutionLevel) {
1575 case RESOLUTION_LEVEL_FINE:
1576 return android.Manifest.permission.ACCESS_FINE_LOCATION;
1577 case RESOLUTION_LEVEL_COARSE:
1578 return android.Manifest.permission.ACCESS_COARSE_LOCATION;
1579 default:
1580 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001581 }
Victoria Leaseda479c52012-10-15 15:24:16 -07001582 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001583
Victoria Lease37425c32012-10-16 16:08:48 -07001584 private int getAllowedResolutionLevel(int pid, int uid) {
1585 if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001586 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001587 return RESOLUTION_LEVEL_FINE;
1588 } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
Maggieaa080f92018-01-04 15:35:11 -08001589 pid, uid) == PERMISSION_GRANTED) {
Victoria Lease37425c32012-10-16 16:08:48 -07001590 return RESOLUTION_LEVEL_COARSE;
1591 } else {
1592 return RESOLUTION_LEVEL_NONE;
Victoria Leaseda479c52012-10-15 15:24:16 -07001593 }
Victoria Lease4fab68b2012-09-13 13:20:59 -07001594 }
1595
Victoria Lease37425c32012-10-16 16:08:48 -07001596 private int getCallerAllowedResolutionLevel() {
1597 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
1598 }
1599
Victoria Lease37425c32012-10-16 16:08:48 -07001600 private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
1601 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Victoria Lease4fab68b2012-09-13 13:20:59 -07001602 throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
1603 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001604 }
1605
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001606 @GuardedBy("mLock")
1607 private int getMinimumResolutionLevelForProviderUseLocked(String provider) {
1608 if (GPS_PROVIDER.equals(provider) || PASSIVE_PROVIDER.equals(provider)) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001609 // gps and passive providers require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001610 return RESOLUTION_LEVEL_FINE;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001611 } else if (NETWORK_PROVIDER.equals(provider) || FUSED_PROVIDER.equals(provider)) {
Victoria Lease8dbb6342012-09-21 16:55:53 -07001612 // network and fused providers are ok with COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001613 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001614 } else {
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001615 for (LocationProvider lp : mProviders) {
1616 if (!lp.getName().equals(provider)) {
1617 continue;
1618 }
1619
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001620 ProviderProperties properties = lp.getPropertiesLocked();
Laurent Tu941221c2012-10-04 14:21:52 -07001621 if (properties != null) {
1622 if (properties.mRequiresSatellite) {
1623 // provider requiring satellites require FINE permission
Victoria Lease37425c32012-10-16 16:08:48 -07001624 return RESOLUTION_LEVEL_FINE;
Laurent Tu941221c2012-10-04 14:21:52 -07001625 } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
1626 // provider requiring network and or cell require COARSE or FINE
Victoria Lease37425c32012-10-16 16:08:48 -07001627 return RESOLUTION_LEVEL_COARSE;
Laurent Tu941221c2012-10-04 14:21:52 -07001628 }
1629 }
1630 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001631 }
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001632
Victoria Lease37425c32012-10-16 16:08:48 -07001633 return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
Victoria Leaseda479c52012-10-15 15:24:16 -07001634 }
1635
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001636 @GuardedBy("mLock")
1637 private void checkResolutionLevelIsSufficientForProviderUseLocked(int allowedResolutionLevel,
Victoria Lease37425c32012-10-16 16:08:48 -07001638 String providerName) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001639 int requiredResolutionLevel = getMinimumResolutionLevelForProviderUseLocked(providerName);
Victoria Lease37425c32012-10-16 16:08:48 -07001640 if (allowedResolutionLevel < requiredResolutionLevel) {
1641 switch (requiredResolutionLevel) {
1642 case RESOLUTION_LEVEL_FINE:
1643 throw new SecurityException("\"" + providerName + "\" location provider " +
1644 "requires ACCESS_FINE_LOCATION permission.");
1645 case RESOLUTION_LEVEL_COARSE:
1646 throw new SecurityException("\"" + providerName + "\" location provider " +
1647 "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
1648 default:
1649 throw new SecurityException("Insufficient permission for \"" + providerName +
1650 "\" location provider.");
Victoria Leaseda479c52012-10-15 15:24:16 -07001651 }
1652 }
Victoria Lease8dbb6342012-09-21 16:55:53 -07001653 }
1654
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001655 public static int resolutionLevelToOp(int allowedResolutionLevel) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001656 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
1657 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001658 return AppOpsManager.OP_COARSE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001659 } else {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001660 return AppOpsManager.OP_FINE_LOCATION;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001661 }
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001662 }
1663 return -1;
1664 }
1665
Wei Wangb86334f2018-07-03 16:33:24 -07001666 private static String resolutionLevelToOpStr(int allowedResolutionLevel) {
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001667 switch (allowedResolutionLevel) {
Wei Wangb86334f2018-07-03 16:33:24 -07001668 case RESOLUTION_LEVEL_COARSE:
1669 return AppOpsManager.OPSTR_COARSE_LOCATION;
1670 case RESOLUTION_LEVEL_FINE:
1671 return AppOpsManager.OPSTR_FINE_LOCATION;
1672 case RESOLUTION_LEVEL_NONE:
1673 // The client is not allowed to get any location, so both FINE and COARSE ops will
1674 // be denied. Pick the most restrictive one to be safe.
1675 return AppOpsManager.OPSTR_FINE_LOCATION;
1676 default:
1677 // Use the most restrictive ops if not sure.
1678 return AppOpsManager.OPSTR_FINE_LOCATION;
1679 }
1680 }
1681
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001682 private boolean reportLocationAccessNoThrow(int pid, int uid, String packageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001683 @Nullable String featureId, int allowedResolutionLevel, @Nullable String message) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001684 int op = resolutionLevelToOp(allowedResolutionLevel);
1685 if (op >= 0) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07001686 if (mAppOps.noteOpNoThrow(op, uid, packageName, featureId, message)
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07001687 != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001688 return false;
1689 }
1690 }
David Christieb870dbf2015-06-22 12:42:53 -07001691
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001692 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001693 }
1694
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001695 private boolean checkLocationAccess(int pid, int uid, String packageName,
1696 int allowedResolutionLevel) {
Dianne Hackborn5e45ee62013-01-24 19:13:44 -08001697 int op = resolutionLevelToOp(allowedResolutionLevel);
1698 if (op >= 0) {
Wei Wang16276a42019-02-04 18:23:31 -08001699 if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
Dianne Hackborn35654b62013-01-14 17:38:02 -08001700 return false;
1701 }
1702 }
David Christieb870dbf2015-06-22 12:42:53 -07001703
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001704 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
Dianne Hackborn35654b62013-01-14 17:38:02 -08001705 }
1706
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001707 /**
Maggie91e630c2018-01-24 17:31:46 -08001708 * Returns all providers by name, including passive and the ones that are not permitted to
1709 * be accessed by the calling activity or are currently disabled, but excluding fused.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001710 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001711 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001712 public List<String> getAllProviders() {
Soonil Nagarkar68257742019-01-09 19:42:34 +00001713 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001714 ArrayList<String> providers = new ArrayList<>(mProviders.size());
Soonil Nagarkar68257742019-01-09 19:42:34 +00001715 for (LocationProvider provider : mProviders) {
1716 String name = provider.getName();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001717 if (FUSED_PROVIDER.equals(name)) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00001718 continue;
1719 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001720 providers.add(name);
Maggie91e630c2018-01-24 17:31:46 -08001721 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001722 return providers;
Maggie91e630c2018-01-24 17:31:46 -08001723 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001724 }
1725
Mike Lockwood03ca2162010-04-01 08:10:09 -07001726 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001727 * Return all providers by name, that match criteria and are optionally
1728 * enabled.
1729 * Can return passive provider, but never returns fused provider.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001730 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001731 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001732 public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
Victoria Lease37425c32012-10-16 16:08:48 -07001733 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001734 synchronized (mLock) {
1735 ArrayList<String> providers = new ArrayList<>(mProviders.size());
1736 for (LocationProvider provider : mProviders) {
1737 String name = provider.getName();
1738 if (FUSED_PROVIDER.equals(name)) {
1739 continue;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001740 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001741 if (allowedResolutionLevel < getMinimumResolutionLevelForProviderUseLocked(name)) {
1742 continue;
1743 }
1744 if (enabledOnly && !provider.isUseableLocked()) {
1745 continue;
1746 }
1747 if (criteria != null
1748 && !android.location.LocationProvider.propertiesMeetCriteria(
1749 name, provider.getPropertiesLocked(), criteria)) {
1750 continue;
1751 }
1752 providers.add(name);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001753 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001754 return providers;
Soonil Nagarkar68257742019-01-09 19:42:34 +00001755 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001756 }
1757
1758 /**
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001759 * Return the name of the best provider given a Criteria object.
1760 * This method has been deprecated from the public API,
Victoria Lease8dbb6342012-09-21 16:55:53 -07001761 * and the whole LocationProvider (including #meetsCriteria)
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001762 * has been deprecated as well. So this method now uses
1763 * some simplified logic.
Mike Lockwood03ca2162010-04-01 08:10:09 -07001764 */
Nick Pellye0fd6932012-07-11 10:26:13 -07001765 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001766 public String getBestProvider(Criteria criteria, boolean enabledOnly) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001767 List<String> providers = getProviders(criteria, enabledOnly);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001768 if (providers.isEmpty()) {
1769 providers = getProviders(null, enabledOnly);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08001770 }
1771
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001772 if (!providers.isEmpty()) {
1773 if (providers.contains(GPS_PROVIDER)) {
1774 return GPS_PROVIDER;
1775 } else if (providers.contains(NETWORK_PROVIDER)) {
1776 return NETWORK_PROVIDER;
1777 } else {
1778 return providers.get(0);
1779 }
1780 }
1781
Mike Lockwood03ca2162010-04-01 08:10:09 -07001782 return null;
1783 }
1784
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001785 @GuardedBy("mLock")
1786 private void updateProviderUseableLocked(LocationProvider provider) {
1787 boolean useable = provider.isUseableLocked();
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001789 ArrayList<Receiver> deadReceivers = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07001790
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001791 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 if (records != null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001793 for (UpdateRecord record : records) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001794 if (!isCurrentProfileLocked(
Anil Admal08b96122019-01-30 16:55:05 -08001795 UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001796 continue;
1797 }
1798
Kweku Adams5e0052b2019-02-22 15:17:52 -08001799 // requests that ignore location settings will never provide notifications
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001800 if (isSettingsExemptLocked(record)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001801 continue;
1802 }
1803
1804 // Sends a notification message to the receiver
1805 if (!record.mReceiver.callProviderEnabledLocked(provider.getName(), useable)) {
1806 if (deadReceivers == null) {
1807 deadReceivers = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001808 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001809 deadReceivers.add(record.mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001810 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 }
1812 }
1813
1814 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001815 for (int i = deadReceivers.size() - 1; i >= 0; i--) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00001816 removeUpdatesLocked(deadReceivers.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001817 }
1818 }
Nick Pellye0fd6932012-07-11 10:26:13 -07001819
Soonil Nagarkar68257742019-01-09 19:42:34 +00001820 applyRequirementsLocked(provider);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001821 }
1822
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001823 @GuardedBy("mLock")
1824 private void applyRequirementsLocked(String providerName) {
1825 LocationProvider provider = getLocationProviderLocked(providerName);
1826 if (provider != null) {
1827 applyRequirementsLocked(provider);
1828 }
1829 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001830
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001831 @GuardedBy("mLock")
1832 private void applyRequirementsLocked(LocationProvider provider) {
1833 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider.getName());
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001834 WorkSource worksource = new WorkSource();
1835 ProviderRequest providerRequest = new ProviderRequest();
1836
Soonil Nagarkar04cff6c2019-03-19 11:29:52 -07001837 // if provider is not active, it should not respond to requests
1838
1839 if (mProviders.contains(provider) && records != null && !records.isEmpty()) {
Kweku Adams5e0052b2019-02-22 15:17:52 -08001840 long backgroundThrottleInterval;
1841
1842 long identity = Binder.clearCallingIdentity();
1843 try {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07001844 backgroundThrottleInterval = mSettingsStore.getBackgroundThrottleIntervalMs();
Kweku Adams5e0052b2019-02-22 15:17:52 -08001845 } finally {
1846 Binder.restoreCallingIdentity(identity);
1847 }
1848
1849 final boolean isForegroundOnlyMode =
Kweku Adams4fb074e2019-02-01 16:03:27 -08001850 mBatterySaverMode == PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
1851 final boolean shouldThrottleRequests =
1852 mBatterySaverMode
1853 == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF
1854 && !mPowerManager.isInteractive();
Soonil Nagarkar1575a042018-10-24 17:54:54 -07001855 // initialize the low power mode to true and set to false if any of the records requires
1856 providerRequest.lowPowerMode = true;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001857 for (UpdateRecord record : records) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001858 if (!isCurrentProfileLocked(
Anil Admal08b96122019-01-30 16:55:05 -08001859 UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001860 continue;
1861 }
1862 if (!checkLocationAccess(
Anil Admal08b96122019-01-30 16:55:05 -08001863 record.mReceiver.mCallerIdentity.mPid,
1864 record.mReceiver.mCallerIdentity.mUid,
1865 record.mReceiver.mCallerIdentity.mPackageName,
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001866 record.mReceiver.mAllowedResolutionLevel)) {
1867 continue;
1868 }
Kweku Adams4fb074e2019-02-01 16:03:27 -08001869 final boolean isBatterySaverDisablingLocation = shouldThrottleRequests
1870 || (isForegroundOnlyMode && !record.mIsForegroundUid);
Kweku Adams5e0052b2019-02-22 15:17:52 -08001871 if (!provider.isUseableLocked() || isBatterySaverDisablingLocation) {
Soonil Nagarkar35c3b912019-01-31 10:31:24 -08001872 if (isSettingsExemptLocked(record)) {
Soonil Nagarkar509580f2019-02-06 15:57:26 -08001873 providerRequest.locationSettingsIgnored = true;
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001874 providerRequest.lowPowerMode = false;
Soonil Nagarkar35c3b912019-01-31 10:31:24 -08001875 } else {
1876 continue;
1877 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001878 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001879
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001880 LocationRequest locationRequest = record.mRealRequest;
1881 long interval = locationRequest.getInterval();
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001882
Soonil Nagarkar509580f2019-02-06 15:57:26 -08001883
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001884 // if we're forcing location, don't apply any throttling
Soonil Nagarkar509580f2019-02-06 15:57:26 -08001885 if (!providerRequest.locationSettingsIgnored && !isThrottlingExemptLocked(
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001886 record.mReceiver.mCallerIdentity)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001887 if (!record.mIsForegroundUid) {
1888 interval = Math.max(interval, backgroundThrottleInterval);
Victoria Leaseb711d572012-10-02 13:14:11 -07001889 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08001890 if (interval != locationRequest.getInterval()) {
1891 locationRequest = new LocationRequest(locationRequest);
1892 locationRequest.setInterval(interval);
1893 }
1894 }
1895
1896 record.mRequest = locationRequest;
1897 providerRequest.locationRequests.add(locationRequest);
1898 if (!locationRequest.isLowPowerMode()) {
1899 providerRequest.lowPowerMode = false;
1900 }
1901 if (interval < providerRequest.interval) {
1902 providerRequest.reportLocation = true;
1903 providerRequest.interval = interval;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001904 }
1905 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001906
1907 if (providerRequest.reportLocation) {
1908 // calculate who to blame for power
1909 // This is somewhat arbitrary. We pick a threshold interval
1910 // that is slightly higher that the minimum interval, and
1911 // spread the blame across all applications with a request
1912 // under that threshold.
1913 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
1914 for (UpdateRecord record : records) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001915 if (isCurrentProfileLocked(
Anil Admal08b96122019-01-30 16:55:05 -08001916 UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
Victoria Leaseb711d572012-10-02 13:14:11 -07001917 LocationRequest locationRequest = record.mRequest;
Svet Ganove998c732016-06-10 00:12:38 -07001918
1919 // Don't assign battery blame for update records whose
1920 // client has no permission to receive location data.
1921 if (!providerRequest.locationRequests.contains(locationRequest)) {
1922 continue;
1923 }
1924
Victoria Leaseb711d572012-10-02 13:14:11 -07001925 if (locationRequest.getInterval() <= thresholdInterval) {
David Christiee55c9682013-08-22 10:10:34 -07001926 if (record.mReceiver.mWorkSource != null
Narayan Kamath32684dd2018-01-08 17:32:51 +00001927 && isValidWorkSource(record.mReceiver.mWorkSource)) {
David Christie82edc9b2013-07-19 11:31:42 -07001928 worksource.add(record.mReceiver.mWorkSource);
1929 } else {
Narayan Kamath32684dd2018-01-08 17:32:51 +00001930 // Assign blame to caller if there's no WorkSource associated with
1931 // the request or if it's invalid.
David Christie82edc9b2013-07-19 11:31:42 -07001932 worksource.add(
Anil Admal08b96122019-01-30 16:55:05 -08001933 record.mReceiver.mCallerIdentity.mUid,
1934 record.mReceiver.mCallerIdentity.mPackageName);
David Christie82edc9b2013-07-19 11:31:42 -07001935 }
Victoria Leaseb711d572012-10-02 13:14:11 -07001936 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001937 }
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07001938 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001939 }
1940 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001941
Soonil Nagarkard334f7b2019-07-08 16:16:19 -07001942 provider.setRequest(providerRequest, worksource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001943 }
1944
Narayan Kamath32684dd2018-01-08 17:32:51 +00001945 /**
1946 * Whether a given {@code WorkSource} associated with a Location request is valid.
1947 */
1948 private static boolean isValidWorkSource(WorkSource workSource) {
1949 if (workSource.size() > 0) {
1950 // If the WorkSource has one or more non-chained UIDs, make sure they're accompanied
1951 // by tags.
Suprabh Shuklaf7cffa72019-11-08 17:03:03 -08001952 return workSource.getPackageName(0) != null;
Narayan Kamath32684dd2018-01-08 17:32:51 +00001953 } else {
1954 // For now, make sure callers have supplied an attribution tag for use with
1955 // AppOpsManager. This might be relaxed in the future.
Suprabh Shuklaf7cffa72019-11-08 17:03:03 -08001956 final List<WorkChain> workChains = workSource.getWorkChains();
Narayan Kamath32684dd2018-01-08 17:32:51 +00001957 return workChains != null && !workChains.isEmpty() &&
1958 workChains.get(0).getAttributionTag() != null;
1959 }
1960 }
1961
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001962 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00001963 public String[] getBackgroundThrottlingWhitelist() {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07001964 return mSettingsStore.getBackgroundThrottlePackageWhitelist().toArray(new String[0]);
Soonil Nagarkar681d7112017-02-23 17:14:16 -08001965 }
1966
Soonil Nagarkar5140e4f2019-02-14 17:21:33 -08001967 @Override
1968 public String[] getIgnoreSettingsWhitelist() {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07001969 return mSettingsStore.getIgnoreSettingsPackageWhitelist().toArray(new String[0]);
Soonil Nagarkar5140e4f2019-02-14 17:21:33 -08001970 }
1971
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08001972 @GuardedBy("mLock")
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07001973 public boolean isThrottlingExemptLocked(CallerIdentity callerIdentity) {
Anil Admal08b96122019-01-30 16:55:05 -08001974 if (callerIdentity.mUid == Process.SYSTEM_UID) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001975 return true;
1976 }
1977
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07001978 if (mSettingsStore.getBackgroundThrottlePackageWhitelist().contains(
1979 callerIdentity.mPackageName)) {
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001980 return true;
1981 }
1982
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001983 return isProviderPackage(callerIdentity.mPackageName);
Soonil Nagarkar2f1f7e82017-01-24 12:52:10 -08001984
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08001985 }
1986
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001987 @GuardedBy("mLock")
1988 private boolean isSettingsExemptLocked(UpdateRecord record) {
1989 if (!record.mRealRequest.isLocationSettingsIgnored()) {
1990 return false;
1991 }
1992
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07001993 if (mSettingsStore.getIgnoreSettingsPackageWhitelist().contains(
Anil Admal08b96122019-01-30 16:55:05 -08001994 record.mReceiver.mCallerIdentity.mPackageName)) {
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001995 return true;
1996 }
1997
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08001998 return isProviderPackage(record.mReceiver.mCallerIdentity.mPackageName);
Soonil Nagarkar397ad582019-01-23 22:47:57 -08001999
Soonil Nagarkar397ad582019-01-23 22:47:57 -08002000 }
2001
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002002 private class UpdateRecord {
2003 final String mProvider;
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002004 private final LocationRequest mRealRequest; // original request from client
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002005 LocationRequest mRequest; // possibly throttled version of the request
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002006 private final Receiver mReceiver;
2007 private boolean mIsForegroundUid;
2008 private Location mLastFixBroadcast;
Soonil Nagarkarae6ce772019-05-01 13:16:17 -07002009 private Throwable mStackTrace; // for debugging only
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08002010 private long mExpirationRealtimeMs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002011
2012 /**
2013 * Note: must be constructed with lock held.
2014 */
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002015 private UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08002016 mExpirationRealtimeMs = request.getExpirationRealtimeMs(SystemClock.elapsedRealtime());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002017 mProvider = provider;
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002018 mRealRequest = request;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002019 mRequest = request;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002020 mReceiver = receiver;
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002021 mIsForegroundUid =
2022 LocationManagerServiceUtils.isImportanceForeground(
2023 mActivityManager.getPackageImportance(
2024 mReceiver.mCallerIdentity.mPackageName));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002025
Soonil Nagarkarae6ce772019-05-01 13:16:17 -07002026 if (D && receiver.mCallerIdentity.mPid == Process.myPid()) {
2027 mStackTrace = new Throwable();
2028 }
2029
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002030 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
2031 if (records == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002032 records = new ArrayList<>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002033 mRecordsByProvider.put(provider, records);
2034 }
2035 if (!records.contains(this)) {
2036 records.add(this);
2037 }
David Christie2ff96af2014-01-30 16:09:37 -08002038
2039 // Update statistics for historical location requests by package/provider
2040 mRequestStatistics.startRequesting(
Anil Admal08b96122019-01-30 16:55:05 -08002041 mReceiver.mCallerIdentity.mPackageName, provider, request.getInterval(),
Wyatt Rileyf7075e02018-04-12 17:54:26 -07002042 mIsForegroundUid);
2043 }
2044
2045 /**
2046 * Method to be called when record changes foreground/background
2047 */
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002048 private void updateForeground(boolean isForeground) {
Wyatt Rileyf7075e02018-04-12 17:54:26 -07002049 mIsForegroundUid = isForeground;
2050 mRequestStatistics.updateForeground(
Anil Admal08b96122019-01-30 16:55:05 -08002051 mReceiver.mCallerIdentity.mPackageName, mProvider, isForeground);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002052 }
2053
2054 /**
David Christie2ff96af2014-01-30 16:09:37 -08002055 * Method to be called when a record will no longer be used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002056 */
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002057 private void disposeLocked(boolean removeReceiver) {
Hongyi Zhang700137e2019-05-23 21:19:36 -07002058 String packageName = mReceiver.mCallerIdentity.mPackageName;
2059 mRequestStatistics.stopRequesting(packageName, mProvider);
2060
2061 mLocationUsageLogger.logLocationApiUsage(
2062 LocationStatsEnums.USAGE_ENDED,
2063 LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
2064 packageName,
2065 mRealRequest,
2066 mReceiver.isListener(),
2067 mReceiver.isPendingIntent(),
Hongyi Zhang0e9ea752019-06-09 22:49:25 -07002068 /* geofence= */ null,
Hongyi Zhang700137e2019-05-23 21:19:36 -07002069 mActivityManager.getPackageImportance(packageName));
David Christie2ff96af2014-01-30 16:09:37 -08002070
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002071 // remove from mRecordsByProvider
2072 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
2073 if (globalRecords != null) {
2074 globalRecords.remove(this);
2075 }
2076
2077 if (!removeReceiver) return; // the caller will handle the rest
2078
2079 // remove from Receiver#mUpdateRecords
2080 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002081 receiverRecords.remove(this.mProvider);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002082
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002083 // and also remove the Receiver if it has no more update records
2084 if (receiverRecords.size() == 0) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002085 removeUpdatesLocked(mReceiver);
Mike Lockwood3a76fd62009-09-01 07:26:56 -04002086 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002087 }
2088
2089 @Override
2090 public String toString() {
Soonil Nagarkarae6ce772019-05-01 13:16:17 -07002091 StringBuilder b = new StringBuilder("UpdateRecord[");
2092 b.append(mProvider).append(" ");
2093 b.append(mReceiver.mCallerIdentity.mPackageName);
2094 b.append("(").append(mReceiver.mCallerIdentity.mUid);
2095 if (mIsForegroundUid) {
2096 b.append(" foreground");
2097 } else {
2098 b.append(" background");
2099 }
2100 b.append(") ");
2101 b.append(mRealRequest).append(" ").append(mReceiver.mWorkSource);
2102
2103 if (mStackTrace != null) {
2104 ByteArrayOutputStream tmp = new ByteArrayOutputStream();
2105 mStackTrace.printStackTrace(new PrintStream(tmp));
2106 b.append("\n\n").append(tmp.toString()).append("\n");
2107 }
2108
2109 b.append("]");
2110 return b.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002111 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002112 }
2113
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002114 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00002115 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002116 String packageName, @Nullable String featureId, WorkSource workSource,
2117 boolean hideFromAppOps, @NonNull String listenerIdentifier) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002118 IBinder binder = listener.asBinder();
2119 Receiver receiver = mReceivers.get(binder);
2120 if (receiver == null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002121 receiver = new Receiver(listener, null, pid, uid, packageName, featureId, workSource,
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002122 hideFromAppOps, listenerIdentifier);
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002123 if (!receiver.linkToListenerDeathNotificationLocked(
2124 receiver.getListener().asBinder())) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002125 return null;
2126 }
Wen Jingcb3ab222014-03-27 13:42:59 +08002127 mReceivers.put(binder, receiver);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002128 }
2129 return receiver;
2130 }
2131
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002132 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00002133 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002134 @Nullable String featureId, WorkSource workSource, boolean hideFromAppOps,
2135 @NonNull String listenerIdentifier) {
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002136 Receiver receiver = mReceivers.get(intent);
2137 if (receiver == null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002138 receiver = new Receiver(null, intent, pid, uid, packageName, featureId, workSource,
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002139 hideFromAppOps, listenerIdentifier);
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002140 mReceivers.put(intent, receiver);
2141 }
2142 return receiver;
2143 }
2144
Victoria Lease37425c32012-10-16 16:08:48 -07002145 /**
2146 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
2147 * and consistency requirements.
2148 *
2149 * @param request the LocationRequest from which to create a sanitized version
Victoria Lease37425c32012-10-16 16:08:48 -07002150 * @return a version of request that meets the given resolution and consistency requirements
2151 * @hide
2152 */
gomo48f1a642017-11-10 20:35:46 -08002153 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel,
2154 boolean callerHasLocationHardwarePermission) {
Victoria Lease37425c32012-10-16 16:08:48 -07002155 LocationRequest sanitizedRequest = new LocationRequest(request);
gomo48f1a642017-11-10 20:35:46 -08002156 if (!callerHasLocationHardwarePermission) {
2157 // allow setting low power mode only for callers with location hardware permission
2158 sanitizedRequest.setLowPowerMode(false);
2159 }
Victoria Lease37425c32012-10-16 16:08:48 -07002160 if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
2161 switch (sanitizedRequest.getQuality()) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002162 case LocationRequest.ACCURACY_FINE:
Victoria Lease37425c32012-10-16 16:08:48 -07002163 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
Victoria Lease09016ab2012-09-16 12:33:15 -07002164 break;
2165 case LocationRequest.POWER_HIGH:
Victoria Lease37425c32012-10-16 16:08:48 -07002166 sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
Victoria Lease09016ab2012-09-16 12:33:15 -07002167 break;
2168 }
2169 // throttle
Victoria Lease37425c32012-10-16 16:08:48 -07002170 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
2171 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07002172 }
Victoria Lease37425c32012-10-16 16:08:48 -07002173 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
2174 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
Victoria Lease09016ab2012-09-16 12:33:15 -07002175 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07002176 }
Nick Pelly4e31c4f2012-08-13 19:35:39 -07002177 // make getFastestInterval() the minimum of interval and fastest interval
Victoria Lease37425c32012-10-16 16:08:48 -07002178 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
Soonil Nagarkar397ad582019-01-23 22:47:57 -08002179 sanitizedRequest.setFastestInterval(request.getInterval());
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002180 }
Victoria Lease37425c32012-10-16 16:08:48 -07002181 return sanitizedRequest;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04002182 }
2183
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002184 private void checkPackageName(String packageName) {
Nick Pellye0fd6932012-07-11 10:26:13 -07002185 if (packageName == null) {
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002186 throw new SecurityException("invalid package name: " + null);
Nick Pellye0fd6932012-07-11 10:26:13 -07002187 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002188 int uid = Binder.getCallingUid();
Nick Pellye0fd6932012-07-11 10:26:13 -07002189 String[] packages = mPackageManager.getPackagesForUid(uid);
2190 if (packages == null) {
2191 throw new SecurityException("invalid UID " + uid);
2192 }
2193 for (String pkg : packages) {
2194 if (packageName.equals(pkg)) return;
2195 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002196 throw new SecurityException("invalid package name: " + packageName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002197 }
2198
Nick Pellye0fd6932012-07-11 10:26:13 -07002199 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002200 public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002201 PendingIntent intent, String packageName, String featureId,
2202 String listenerIdentifier) {
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002203 Preconditions.checkNotNull(listenerIdentifier);
2204
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002205 synchronized (mLock) {
2206 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2207 checkPackageName(packageName);
2208 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2209 checkResolutionLevelIsSufficientForProviderUseLocked(allowedResolutionLevel,
2210 request.getProvider());
2211 WorkSource workSource = request.getWorkSource();
2212 if (workSource != null && !workSource.isEmpty()) {
2213 mContext.enforceCallingOrSelfPermission(
2214 Manifest.permission.UPDATE_DEVICE_STATS, null);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002215 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002216 boolean hideFromAppOps = request.getHideFromAppOps();
2217 if (hideFromAppOps) {
2218 mContext.enforceCallingOrSelfPermission(
2219 Manifest.permission.UPDATE_APP_OPS_STATS, null);
2220 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002221 if (request.isLocationSettingsIgnored()) {
2222 mContext.enforceCallingOrSelfPermission(
2223 Manifest.permission.WRITE_SECURE_SETTINGS, null);
2224 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002225 boolean callerHasLocationHardwarePermission =
2226 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
2227 == PERMISSION_GRANTED;
2228 LocationRequest sanitizedRequest = createSanitizedRequest(request,
2229 allowedResolutionLevel,
2230 callerHasLocationHardwarePermission);
2231
2232 final int pid = Binder.getCallingPid();
2233 final int uid = Binder.getCallingUid();
2234
2235 long identity = Binder.clearCallingIdentity();
2236 try {
2237
2238 // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2239 // a location.
2240 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
2241
2242 if (intent == null && listener == null) {
2243 throw new IllegalArgumentException("need either listener or intent");
2244 } else if (intent != null && listener != null) {
2245 throw new IllegalArgumentException(
2246 "cannot register both listener and intent");
2247 }
2248
Hongyi Zhang700137e2019-05-23 21:19:36 -07002249 mLocationUsageLogger.logLocationApiUsage(
2250 LocationStatsEnums.USAGE_STARTED,
2251 LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
2252 packageName, request, listener != null, intent != null,
Hongyi Zhang0e9ea752019-06-09 22:49:25 -07002253 /* geofence= */ null,
Hongyi Zhang700137e2019-05-23 21:19:36 -07002254 mActivityManager.getPackageImportance(packageName));
2255
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002256 Receiver receiver;
2257 if (intent != null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002258 receiver = getReceiverLocked(intent, pid, uid, packageName, featureId,
2259 workSource, hideFromAppOps, listenerIdentifier);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002260 } else {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002261 receiver = getReceiverLocked(listener, pid, uid, packageName, featureId,
2262 workSource, hideFromAppOps, listenerIdentifier);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002263 }
2264 requestLocationUpdatesLocked(sanitizedRequest, receiver, uid, packageName);
2265 } finally {
2266 Binder.restoreCallingIdentity(identity);
2267 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002268 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269 }
2270
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002271 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00002272 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002273 int uid, String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002274 // Figure out the provider. Either its explicitly request (legacy use cases), or
2275 // use the fused provider
2276 if (request == null) request = DEFAULT_LOCATION_REQUEST;
2277 String name = request.getProvider();
Victoria Lease09016ab2012-09-16 12:33:15 -07002278 if (name == null) {
2279 throw new IllegalArgumentException("provider name must not be null");
2280 }
Zhentao Sunc5fc9982013-04-17 17:47:53 -07002281
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002282 LocationProvider provider = getLocationProviderLocked(name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002283 if (provider == null) {
Victoria Leaseb30f3832013-10-13 12:15:40 -07002284 throw new IllegalArgumentException("provider doesn't exist: " + name);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002285 }
2286
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002287 UpdateRecord record = new UpdateRecord(name, request, receiver);
gomo48f1a642017-11-10 20:35:46 -08002288 if (D) {
2289 Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
2290 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
2291 + (record.mIsForegroundUid ? "foreground" : "background")
Anil Admal08b96122019-01-30 16:55:05 -08002292 + (isThrottlingExemptLocked(receiver.mCallerIdentity)
Soonil Nagarkar681d7112017-02-23 17:14:16 -08002293 ? " [whitelisted]" : "") + ")");
gomo48f1a642017-11-10 20:35:46 -08002294 }
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002295
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002296 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
2297 if (oldRecord != null) {
2298 oldRecord.disposeLocked(false);
2299 }
2300
Soonil Nagarkar397ad582019-01-23 22:47:57 -08002301 if (!provider.isUseableLocked() && !isSettingsExemptLocked(record)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002302 // Notify the listener that updates are currently disabled - but only if the request
2303 // does not ignore location settings
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002304 receiver.callProviderEnabledLocked(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002305 }
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002306
2307 applyRequirementsLocked(name);
2308
David Christie0b837452013-07-29 16:02:13 -07002309 // Update the monitoring here just in case multiple location requests were added to the
2310 // same receiver (this request may be high power and the initial might not have been).
2311 receiver.updateMonitoring(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002312 }
2313
Nick Pellye0fd6932012-07-11 10:26:13 -07002314 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002315 public void removeUpdates(ILocationListener listener, PendingIntent intent,
Soonil Nagarkar68257742019-01-09 19:42:34 +00002316 String packageName) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002317 checkPackageName(packageName);
Victoria Lease37425c32012-10-16 16:08:48 -07002318
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002319 int pid = Binder.getCallingPid();
2320 int uid = Binder.getCallingUid();
2321
2322 if (intent == null && listener == null) {
2323 throw new IllegalArgumentException("need either listener or intent");
2324 } else if (intent != null && listener != null) {
2325 throw new IllegalArgumentException("cannot register both listener and intent");
2326 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002327
Soonil Nagarkar68257742019-01-09 19:42:34 +00002328 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002329 Receiver receiver;
2330 if (intent != null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002331 receiver = getReceiverLocked(intent, pid, uid, packageName, null, null, false, "");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002332 } else {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002333 receiver = getReceiverLocked(listener, pid, uid, packageName, null, null, false,
2334 "");
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002335 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002336
Soonil Nagarkar68257742019-01-09 19:42:34 +00002337 long identity = Binder.clearCallingIdentity();
2338 try {
2339 removeUpdatesLocked(receiver);
2340 } finally {
2341 Binder.restoreCallingIdentity(identity);
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002342 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002343 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002344 }
2345
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002346 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00002347 private void removeUpdatesLocked(Receiver receiver) {
Dianne Hackborn7ff30112012-11-08 11:12:09 -08002348 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002349
2350 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002351 receiver.unlinkFromListenerDeathNotificationLocked(
2352 receiver.getListener().asBinder());
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08002353 receiver.clearPendingBroadcastsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 }
2355
Dianne Hackborn1304f4a2013-07-09 18:17:27 -07002356 receiver.updateMonitoring(false);
2357
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002358 // Record which providers were associated with this listener
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002359 HashSet<String> providers = new HashSet<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002360 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2361 if (oldRecords != null) {
2362 // Call dispose() on the obsolete update records.
2363 for (UpdateRecord record : oldRecords.values()) {
David Christie2ff96af2014-01-30 16:09:37 -08002364 // Update statistics for historical location requests by package/provider
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002365 record.disposeLocked(false);
2366 }
2367 // Accumulate providers
2368 providers.addAll(oldRecords.keySet());
2369 }
2370
2371 // update provider
2372 for (String provider : providers) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002373 applyRequirementsLocked(provider);
2374 }
2375 }
2376
Nick Pellye0fd6932012-07-11 10:26:13 -07002377 @Override
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002378 public Location getLastLocation(LocationRequest r, String packageName, String featureId) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002379 synchronized (mLock) {
2380 LocationRequest request = r != null ? r : DEFAULT_LOCATION_REQUEST;
2381 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2382 checkPackageName(packageName);
2383 checkResolutionLevelIsSufficientForProviderUseLocked(allowedResolutionLevel,
2384 request.getProvider());
2385 // no need to sanitize this request, as only the provider name is used
Nick Pelly4035f5a2012-08-17 14:43:49 -07002386
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002387 final int pid = Binder.getCallingPid();
2388 final int uid = Binder.getCallingUid();
2389 final long identity = Binder.clearCallingIdentity();
2390 try {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07002391 if (mSettingsStore.isLocationPackageBlacklisted(UserHandle.getUserId(uid),
2392 packageName)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002393 if (D) {
2394 Log.d(TAG, "not returning last loc for blacklisted app: "
2395 + packageName);
2396 }
2397 return null;
gomo48f1a642017-11-10 20:35:46 -08002398 }
Victoria Leaseb711d572012-10-02 13:14:11 -07002399
Soonil Nagarkar68257742019-01-09 19:42:34 +00002400 // Figure out the provider. Either its explicitly request (deprecated API's),
2401 // or use the fused provider
2402 String name = request.getProvider();
2403 if (name == null) name = LocationManager.FUSED_PROVIDER;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002404 LocationProvider provider = getLocationProviderLocked(name);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002405 if (provider == null) return null;
2406
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002407 // only the current user or location providers may get location this way
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08002408 if (!isCurrentProfileLocked(UserHandle.getUserId(uid)) && !isProviderPackage(
2409 packageName)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002410 return null;
2411 }
2412
2413 if (!provider.isUseableLocked()) {
2414 return null;
2415 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002416
2417 Location location;
2418 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2419 // Make sure that an app with coarse permissions can't get frequent location
2420 // updates by calling LocationManager.getLastKnownLocation repeatedly.
2421 location = mLastLocationCoarseInterval.get(name);
2422 } else {
2423 location = mLastLocation.get(name);
2424 }
2425 if (location == null) {
2426 return null;
2427 }
2428
2429 // Don't return stale location to apps with foreground-only location permission.
2430 String op = resolutionLevelToOpStr(allowedResolutionLevel);
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002431 long locationAgeMs = TimeUnit.NANOSECONDS.toMillis(
2432 SystemClock.elapsedRealtime() - location.getElapsedRealtimeNanos());
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07002433 if (locationAgeMs > mSettingsStore.getMaxLastLocationAgeMs()
Soonil Nagarkar68257742019-01-09 19:42:34 +00002434 && (mAppOps.unsafeCheckOp(op, uid, packageName)
2435 == AppOpsManager.MODE_FOREGROUND)) {
2436 return null;
2437 }
2438
Wei Wang16276a42019-02-04 18:23:31 -08002439 Location lastLocation = null;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002440 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2441 Location noGPSLocation = location.getExtraLocation(
2442 Location.EXTRA_NO_GPS_LOCATION);
2443 if (noGPSLocation != null) {
Wei Wang16276a42019-02-04 18:23:31 -08002444 lastLocation = new Location(mLocationFudger.getOrCreate(noGPSLocation));
Soonil Nagarkar68257742019-01-09 19:42:34 +00002445 }
2446 } else {
Wei Wang16276a42019-02-04 18:23:31 -08002447 lastLocation = new Location(location);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002448 }
Wei Wang16276a42019-02-04 18:23:31 -08002449 // Don't report location access if there is no last location to deliver.
2450 if (lastLocation != null) {
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002451 if (!reportLocationAccessNoThrow(pid, uid, packageName, featureId,
2452 allowedResolutionLevel, null)) {
Wei Wang16276a42019-02-04 18:23:31 -08002453 if (D) {
2454 Log.d(TAG, "not returning last loc for no op app: " + packageName);
2455 }
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002456 lastLocation = null;
Wei Wang16276a42019-02-04 18:23:31 -08002457 }
2458 }
2459 return lastLocation;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002460 } finally {
2461 Binder.restoreCallingIdentity(identity);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002462 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002463 }
2464 }
2465
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002466 @Override
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002467 public boolean getCurrentLocation(LocationRequest locationRequest,
2468 ICancellationSignal remoteCancellationSignal, ILocationListener listener,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002469 String packageName, String featureId, String listenerIdentifier) {
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002470 // side effect of validating locationRequest and packageName
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002471 Location lastLocation = getLastLocation(locationRequest, packageName, featureId);
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002472 if (lastLocation != null) {
2473 long locationAgeMs = TimeUnit.NANOSECONDS.toMillis(
2474 SystemClock.elapsedRealtimeNanos() - lastLocation.getElapsedRealtimeNanos());
2475
2476 long identity = Binder.clearCallingIdentity();
2477 try {
2478 if (locationAgeMs < MAX_CURRENT_LOCATION_AGE_MS) {
2479 try {
2480 listener.onLocationChanged(lastLocation);
2481 return true;
2482 } catch (RemoteException e) {
2483 Log.w(TAG, e);
2484 return false;
2485 }
2486 }
2487
2488 // packageName already validated by getLastLocation() call above
2489 boolean foreground = LocationManagerServiceUtils.isImportanceForeground(
2490 mActivityManager.getPackageImportance(packageName));
2491 if (!foreground) {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07002492 if (locationAgeMs < mSettingsStore.getBackgroundThrottleIntervalMs()) {
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002493 // not allowed to request new locations, so we can't return anything
2494 return false;
2495 }
2496 }
2497 } finally {
2498 Binder.restoreCallingIdentity(identity);
2499 }
2500 }
2501
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002502 requestLocationUpdates(locationRequest, listener, null, packageName, featureId,
2503 listenerIdentifier);
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002504 CancellationSignal cancellationSignal = CancellationSignal.fromTransport(
2505 remoteCancellationSignal);
2506 if (cancellationSignal != null) {
2507 cancellationSignal.setOnCancelListener(
2508 () -> removeUpdates(listener, null, packageName));
2509 }
2510 return true;
2511 }
2512
2513 @Override
Chad Brubakerf1133332019-03-15 14:13:59 -07002514 public LocationTime getGnssTimeMillis() {
2515 synchronized (mLock) {
2516 Location location = mLastLocation.get(LocationManager.GPS_PROVIDER);
2517 if (location == null) {
2518 return null;
2519 }
2520 long currentNanos = SystemClock.elapsedRealtimeNanos();
2521 long deltaMs = (currentNanos - location.getElapsedRealtimeNanos()) / 1000000L;
2522 return new LocationTime(location.getTime() + deltaMs, currentNanos);
2523 }
2524 }
2525
2526 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002527 public boolean injectLocation(Location location) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002528 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
2529 "Location Hardware permission not granted to inject location");
2530 mContext.enforceCallingPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
2531 "Access Fine Location permission not granted to inject Location");
2532
Soonil Nagarkar68257742019-01-09 19:42:34 +00002533 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002534 LocationProvider provider = getLocationProviderLocked(location.getProvider());
2535 if (provider == null || !provider.isUseableLocked()) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002536 return false;
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002537 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002538
2539 // NOTE: If last location is already available, location is not injected. If
2540 // provider's normal source (like a GPS chipset) have already provided an output
2541 // there is no need to inject this location.
2542 if (mLastLocation.get(provider.getName()) != null) {
2543 return false;
2544 }
2545
2546 updateLastLocationLocked(location, provider.getName());
2547 return true;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002548 }
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002549 }
2550
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002551 @Override
2552 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002553 String packageName, String featureId, String listenerIdentifier) {
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002554 Preconditions.checkNotNull(listenerIdentifier);
2555
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002556 if (request == null) request = DEFAULT_LOCATION_REQUEST;
Victoria Lease37425c32012-10-16 16:08:48 -07002557 int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2558 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002559 if (intent == null) {
2560 throw new IllegalArgumentException("invalid pending intent: " + null);
Victoria Lease56e675b2012-11-05 19:25:06 -08002561 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002562 checkPackageName(packageName);
2563 synchronized (mLock) {
2564 checkResolutionLevelIsSufficientForProviderUseLocked(allowedResolutionLevel,
2565 request.getProvider());
Soonil Nagarkar8c4655e2019-02-27 13:00:56 -08002566 }
2567 // Require that caller can manage given document
2568 boolean callerHasLocationHardwarePermission =
2569 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
2570 == PERMISSION_GRANTED;
2571 LocationRequest sanitizedRequest = createSanitizedRequest(request,
2572 allowedResolutionLevel,
2573 callerHasLocationHardwarePermission);
2574
2575 if (D) {
2576 Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
2577 }
2578
2579 // geo-fence manager uses the public location API, need to clear identity
2580 int uid = Binder.getCallingUid();
2581 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
2582 // temporary measure until geofences work for secondary users
2583 Log.w(TAG, "proximity alerts are currently available only to the primary user");
2584 return;
2585 }
2586 long identity = Binder.clearCallingIdentity();
2587 try {
Hongyi Zhang700137e2019-05-23 21:19:36 -07002588 synchronized (mLock) {
2589 mLocationUsageLogger.logLocationApiUsage(
2590 LocationStatsEnums.USAGE_STARTED,
2591 LocationStatsEnums.API_REQUEST_GEOFENCE,
2592 packageName,
2593 request,
2594 /* hasListener= */ false,
2595 intent != null,
Hongyi Zhang0e9ea752019-06-09 22:49:25 -07002596 geofence,
Hongyi Zhang700137e2019-05-23 21:19:36 -07002597 mActivityManager.getPackageImportance(packageName));
2598 }
2599
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002600 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002601 uid, packageName, featureId, listenerIdentifier);
Soonil Nagarkar8c4655e2019-02-27 13:00:56 -08002602 } finally {
2603 Binder.restoreCallingIdentity(identity);
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002604 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002605 }
2606
2607 @Override
2608 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002609 if (intent == null) {
2610 throw new IllegalArgumentException("invalid pending intent: " + null);
2611 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002612 checkPackageName(packageName);
2613
2614 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2615
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002616 // geo-fence manager uses the public location API, need to clear identity
2617 long identity = Binder.clearCallingIdentity();
2618 try {
Hongyi Zhang700137e2019-05-23 21:19:36 -07002619 synchronized (mLock) {
2620 mLocationUsageLogger.logLocationApiUsage(
2621 LocationStatsEnums.USAGE_ENDED,
2622 LocationStatsEnums.API_REQUEST_GEOFENCE,
2623 packageName,
2624 /* LocationRequest= */ null,
2625 /* hasListener= */ false,
2626 intent != null,
Hongyi Zhang0e9ea752019-06-09 22:49:25 -07002627 geofence,
Hongyi Zhang700137e2019-05-23 21:19:36 -07002628 mActivityManager.getPackageImportance(packageName));
2629 }
Nick Pelly2b7a0d02012-08-17 15:09:44 -07002630 mGeofenceManager.removeFence(geofence, intent);
2631 } finally {
2632 Binder.restoreCallingIdentity(identity);
2633 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002634 }
2635
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002636 @Override
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002637 public boolean registerGnssStatusCallback(IGnssStatusListener listener, String packageName,
2638 String featureId) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002639 return mGnssManagerService == null ? false : mGnssManagerService.registerGnssStatusCallback(
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002640 listener, packageName, featureId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002641 }
2642
Nick Pellye0fd6932012-07-11 10:26:13 -07002643 @Override
Anil Admal98d49b72019-02-06 15:26:33 -08002644 public void unregisterGnssStatusCallback(IGnssStatusListener listener) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002645 if (mGnssManagerService != null) mGnssManagerService.unregisterGnssStatusCallback(listener);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002646 }
2647
Nick Pellye0fd6932012-07-11 10:26:13 -07002648 @Override
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002649 public boolean addGnssMeasurementsListener(IGnssMeasurementsListener listener,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002650 String packageName, String featureId, String listenerIdentifier) {
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002651 Preconditions.checkNotNull(listenerIdentifier);
2652
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002653 return mGnssManagerService == null ? false
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002654 : mGnssManagerService.addGnssMeasurementsListener(listener, packageName, featureId,
2655 listenerIdentifier);
Anil Admal52686f82019-02-13 19:04:10 -08002656 }
2657
2658 @Override
2659 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002660 if (mGnssManagerService != null) {
2661 mGnssManagerService.removeGnssMeasurementsListener(
2662 listener);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002663 }
destradaaea8a8a62014-06-23 18:19:03 -07002664 }
2665
2666 @Override
gomo226b7b72018-12-12 16:49:39 -08002667 public void injectGnssMeasurementCorrections(
2668 GnssMeasurementCorrections measurementCorrections, String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002669 if (mGnssManagerService != null) {
2670 mGnssManagerService.injectGnssMeasurementCorrections(
2671 measurementCorrections, packageName);
gomo226b7b72018-12-12 16:49:39 -08002672 }
2673 }
2674
2675 @Override
Anil Admal99349782019-03-19 18:58:42 -07002676 public long getGnssCapabilities(String packageName) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002677 return mGnssManagerService == null ? 0L : mGnssManagerService.getGnssCapabilities(
2678 packageName);
gomo226b7b72018-12-12 16:49:39 -08002679 }
2680
2681 @Override
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002682 public boolean addGnssNavigationMessageListener(IGnssNavigationMessageListener listener,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002683 String packageName, String featureId, String listenerIdentifier) {
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002684 Preconditions.checkNotNull(listenerIdentifier);
2685
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002686 return mGnssManagerService == null ? false
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002687 : mGnssManagerService.addGnssNavigationMessageListener(listener, packageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002688 featureId, listenerIdentifier);
destradaa4b3e3932014-07-21 18:01:47 -07002689 }
2690
2691 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002692 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002693 if (mGnssManagerService != null) {
2694 mGnssManagerService.removeGnssNavigationMessageListener(
2695 listener);
2696 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002697 }
2698
2699 @Override
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002700 public boolean sendExtraCommand(String providerName, String command, Bundle extras) {
2701 if (providerName == null) {
Mike Lockwoodc6cc8362009-08-17 13:16:08 -04002702 // throw NullPointerException to remain compatible with previous implementation
2703 throw new NullPointerException();
2704 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00002705 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002706 checkResolutionLevelIsSufficientForProviderUseLocked(getCallerAllowedResolutionLevel(),
2707 providerName);
Nick Pellye0fd6932012-07-11 10:26:13 -07002708
Hongyi Zhang700137e2019-05-23 21:19:36 -07002709 mLocationUsageLogger.logLocationApiUsage(
2710 LocationStatsEnums.USAGE_STARTED,
2711 LocationStatsEnums.API_SEND_EXTRA_COMMAND,
2712 providerName);
2713
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002714 // and check for ACCESS_LOCATION_EXTRA_COMMANDS
2715 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
2716 != PERMISSION_GRANTED)) {
2717 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
2718 }
2719
2720 LocationProvider provider = getLocationProviderLocked(providerName);
2721 if (provider != null) {
Soonil Nagarkard334f7b2019-07-08 16:16:19 -07002722 provider.sendExtraCommand(command, extras);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002723 }
2724
Hongyi Zhang700137e2019-05-23 21:19:36 -07002725 mLocationUsageLogger.logLocationApiUsage(
2726 LocationStatsEnums.USAGE_ENDED,
2727 LocationStatsEnums.API_SEND_EXTRA_COMMAND,
2728 providerName);
2729
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002730 return true;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002731 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002732 }
2733
Nick Pellye0fd6932012-07-11 10:26:13 -07002734 @Override
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002735 public boolean sendNiResponse(int notifId, int userResponse) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07002736 return mGnssManagerService == null ? false : mGnssManagerService.sendNiResponse(notifId,
2737 userResponse);
Danke Xie22d1f9f2009-08-18 18:28:45 -04002738 }
2739
Nick Pellye0fd6932012-07-11 10:26:13 -07002740 @Override
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002741 public ProviderProperties getProviderProperties(String providerName) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002742 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002743 LocationProvider provider = getLocationProviderLocked(providerName);
2744 if (provider == null) {
2745 return null;
2746 }
2747 return provider.getPropertiesLocked();
2748 }
Jason Monkb71218a2015-06-17 14:44:39 -04002749 }
2750
Wei Wang980b7c22018-12-06 17:53:00 -08002751 @Override
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08002752 public boolean isProviderPackage(String packageName) {
Soonil Nagarkar514dff42019-04-30 12:04:28 -07002753 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG,
2754 Manifest.permission.READ_DEVICE_CONFIG + " permission required");
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08002755 synchronized (mLock) {
2756 for (LocationProvider provider : mProviders) {
2757 if (provider.getPackagesLocked().contains(packageName)) {
2758 return true;
2759 }
2760 }
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08002761 return false;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002762 }
Maggie2a9409e2018-03-21 11:47:28 -07002763 }
2764
Maggie2a9409e2018-03-21 11:47:28 -07002765 @Override
Wei Wang9f52d552019-10-02 14:49:02 -07002766 public List<String> getProviderPackages(String providerName) {
2767 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG,
2768 Manifest.permission.READ_DEVICE_CONFIG + " permission required");
2769 synchronized (mLock) {
2770 LocationProvider provider = getLocationProviderLocked(providerName);
2771 return provider == null ? Collections.emptyList() : provider.getPackagesLocked();
2772 }
2773 }
2774
2775 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002776 public void setExtraLocationControllerPackage(String packageName) {
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002777 mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
2778 Manifest.permission.LOCATION_HARDWARE + " permission required");
Soonil Nagarkar68257742019-01-09 19:42:34 +00002779 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002780 mExtraLocationControllerPackage = packageName;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002781 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002782 }
2783
2784 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002785 public String getExtraLocationControllerPackage() {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002786 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002787 return mExtraLocationControllerPackage;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002788 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002789 }
2790
2791 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002792 public void setExtraLocationControllerPackageEnabled(boolean enabled) {
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002793 mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
2794 Manifest.permission.LOCATION_HARDWARE + " permission required");
Soonil Nagarkar68257742019-01-09 19:42:34 +00002795 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002796 mExtraLocationControllerPackageEnabled = enabled;
Soonil Nagarkar68257742019-01-09 19:42:34 +00002797 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002798 }
2799
2800 @Override
Wei Wang114922a2019-01-30 18:19:35 -08002801 public boolean isExtraLocationControllerPackageEnabled() {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002802 synchronized (mLock) {
Wei Wang114922a2019-01-30 18:19:35 -08002803 return mExtraLocationControllerPackageEnabled
2804 && (mExtraLocationControllerPackage != null);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002805 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002806 }
2807
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002808 private boolean isLocationEnabled() {
2809 return isLocationEnabledForUser(mCurrentUserId);
2810 }
2811
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002812 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002813 public boolean isLocationEnabledForUser(int userId) {
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002814 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002815 if (UserHandle.getCallingUserId() != userId) {
2816 mContext.enforceCallingOrSelfPermission(
2817 Manifest.permission.INTERACT_ACROSS_USERS,
2818 "Requires INTERACT_ACROSS_USERS permission");
2819 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002820
Soonil Nagarkar68257742019-01-09 19:42:34 +00002821 long identity = Binder.clearCallingIdentity();
2822 try {
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07002823 return mSettingsStore.isLocationEnabled(userId);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002824 } finally {
2825 Binder.restoreCallingIdentity(identity);
2826 }
Soonil Nagarkarb2fcddd2019-01-03 15:20:06 -08002827 }
2828
Maggie2a9409e2018-03-21 11:47:28 -07002829 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00002830 public boolean isProviderEnabledForUser(String providerName, int userId) {
Maggie2a9409e2018-03-21 11:47:28 -07002831 // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002832 if (UserHandle.getCallingUserId() != userId) {
2833 mContext.enforceCallingOrSelfPermission(
2834 Manifest.permission.INTERACT_ACROSS_USERS,
2835 "Requires INTERACT_ACROSS_USERS permission");
Soonil Nagarkar1575a042018-10-24 17:54:54 -07002836 }
2837
Maggie2a9409e2018-03-21 11:47:28 -07002838 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2839 // so we discourage its use
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002840 if (FUSED_PROVIDER.equals(providerName)) return false;
Maggie2a9409e2018-03-21 11:47:28 -07002841
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002842 synchronized (mLock) {
2843 LocationProvider provider = getLocationProviderLocked(providerName);
Soonil Nagarkar06e37f62019-12-04 16:05:08 -08002844 return provider != null && provider.isUseableLocked(userId);
Soonil Nagarkar68257742019-01-09 19:42:34 +00002845 }
Maggie2a9409e2018-03-21 11:47:28 -07002846 }
2847
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002848 @GuardedBy("mLock")
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002849 private static boolean shouldBroadcastSafeLocked(
Laurent Tu75defb62012-11-01 16:21:52 -07002850 Location loc, Location lastLoc, UpdateRecord record, long now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002851 // Always broadcast the first update
2852 if (lastLoc == null) {
2853 return true;
2854 }
2855
Nick Pellyf1be6862012-05-15 10:53:42 -07002856 // Check whether sufficient time has passed
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002857 long minTime = record.mRealRequest.getFastestInterval();
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002858 long deltaMs = TimeUnit.NANOSECONDS.toMillis(
2859 loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos());
2860 if (deltaMs < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002861 return false;
2862 }
2863
2864 // Check whether sufficient distance has been traveled
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002865 double minDistance = record.mRealRequest.getSmallestDisplacement();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002866 if (minDistance > 0.0) {
2867 if (loc.distanceTo(lastLoc) <= minDistance) {
2868 return false;
2869 }
2870 }
2871
Laurent Tu75defb62012-11-01 16:21:52 -07002872 // Check whether sufficient number of udpates is left
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07002873 if (record.mRealRequest.getNumUpdates() <= 0) {
Laurent Tu75defb62012-11-01 16:21:52 -07002874 return false;
2875 }
2876
2877 // Check whether the expiry date has passed
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08002878 return record.mExpirationRealtimeMs >= now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002879 }
2880
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002881 @GuardedBy("mLock")
2882 private void handleLocationChangedLocked(Location location, LocationProvider provider) {
2883 if (!mProviders.contains(provider)) {
2884 return;
2885 }
2886 if (!location.isComplete()) {
2887 Log.w(TAG, "Dropping incomplete location: " + location);
2888 return;
2889 }
2890
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002891 // only notify passive provider and update last location for locations that come from
2892 // useable providers
2893 if (provider.isUseableLocked()) {
2894 if (!provider.isPassiveLocked()) {
2895 mPassiveProvider.updateLocation(location);
2896 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002897 }
2898
Soonil Nagarkar68257742019-01-09 19:42:34 +00002899 if (D) Log.d(TAG, "incoming location: " + location);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002900 long now = SystemClock.elapsedRealtime();
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002901 if (provider.isUseableLocked()) {
2902 updateLastLocationLocked(location, provider.getName());
Mike Lockwood4e50b782009-04-03 08:24:43 -07002903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002904
David Christie1b9b7b12013-04-15 15:31:11 -07002905 // Update last known coarse interval location if enough time has passed.
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002906 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(
2907 provider.getName());
David Christie1b9b7b12013-04-15 15:31:11 -07002908 if (lastLocationCoarseInterval == null) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002909 lastLocationCoarseInterval = new Location(location);
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002910
2911 if (provider.isUseableLocked()) {
2912 mLastLocationCoarseInterval.put(provider.getName(), lastLocationCoarseInterval);
2913 }
David Christie1b9b7b12013-04-15 15:31:11 -07002914 }
Soonil Nagarkar905e7222019-10-01 12:03:29 -07002915 long timeDeltaMs = TimeUnit.NANOSECONDS.toMillis(location.getElapsedRealtimeNanos()
2916 - lastLocationCoarseInterval.getElapsedRealtimeNanos());
2917 if (timeDeltaMs > LocationFudger.FASTEST_INTERVAL_MS) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00002918 lastLocationCoarseInterval.set(location);
David Christie1b9b7b12013-04-15 15:31:11 -07002919 }
2920 // Don't ever return a coarse location that is more recent than the allowed update
2921 // interval (i.e. don't allow an app to keep registering and unregistering for
2922 // location updates to overcome the minimum interval).
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08002923 Location noGPSLocation =
David Christie1b9b7b12013-04-15 15:31:11 -07002924 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2925
Laurent Tu60ec50a2012-10-04 17:00:10 -07002926 // Skip if there are no UpdateRecords for this provider.
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002927 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider.getName());
Laurent Tu60ec50a2012-10-04 17:00:10 -07002928 if (records == null || records.size() == 0) return;
2929
Victoria Lease09016ab2012-09-16 12:33:15 -07002930 // Fetch coarse location
2931 Location coarseLocation = null;
David Christie1b9b7b12013-04-15 15:31:11 -07002932 if (noGPSLocation != null) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002933 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
2934 }
2935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002936 ArrayList<Receiver> deadReceivers = null;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002937 ArrayList<UpdateRecord> deadUpdateRecords = null;
Nick Pellye0fd6932012-07-11 10:26:13 -07002938
Soonil Nagarkar94749f72018-11-08 11:46:43 -08002939 // Broadcast location to all listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002940 for (UpdateRecord r : records) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002941 Receiver receiver = r.mReceiver;
Mike Lockwood03ca2162010-04-01 08:10:09 -07002942 boolean receiverDead = false;
Nick Pelly4035f5a2012-08-17 14:43:49 -07002943
Soonil Nagarkar397ad582019-01-23 22:47:57 -08002944 if (!provider.isUseableLocked() && !isSettingsExemptLocked(r)) {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002945 continue;
2946 }
2947
Anil Admal08b96122019-01-30 16:55:05 -08002948 int receiverUserId = UserHandle.getUserId(receiver.mCallerIdentity.mUid);
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002949 if (!isCurrentProfileLocked(receiverUserId)
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08002950 && !isProviderPackage(receiver.mCallerIdentity.mPackageName)) {
Victoria Leaseb711d572012-10-02 13:14:11 -07002951 if (D) {
Victoria Lease269518e2012-10-29 08:25:39 -07002952 Log.d(TAG, "skipping loc update for background user " + receiverUserId +
Victoria Leaseb711d572012-10-02 13:14:11 -07002953 " (current user: " + mCurrentUserId + ", app: " +
Anil Admal08b96122019-01-30 16:55:05 -08002954 receiver.mCallerIdentity.mPackageName + ")");
Victoria Leaseb711d572012-10-02 13:14:11 -07002955 }
2956 continue;
2957 }
2958
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07002959 if (mSettingsStore.isLocationPackageBlacklisted(receiverUserId,
2960 receiver.mCallerIdentity.mPackageName)) {
gomo48f1a642017-11-10 20:35:46 -08002961 if (D) {
2962 Log.d(TAG, "skipping loc update for blacklisted app: " +
Anil Admal08b96122019-01-30 16:55:05 -08002963 receiver.mCallerIdentity.mPackageName);
gomo48f1a642017-11-10 20:35:46 -08002964 }
Nick Pelly4035f5a2012-08-17 14:43:49 -07002965 continue;
2966 }
2967
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08002968 Location notifyLocation;
Victoria Lease37425c32012-10-16 16:08:48 -07002969 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2970 notifyLocation = coarseLocation; // use coarse location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002971 } else {
Soonil Nagarkarbe93e9c2019-01-08 13:05:03 -08002972 notifyLocation = location; // use fine location
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002973 }
Victoria Lease09016ab2012-09-16 12:33:15 -07002974 if (notifyLocation != null) {
2975 Location lastLoc = r.mLastFixBroadcast;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08002976 if ((lastLoc == null)
2977 || shouldBroadcastSafeLocked(notifyLocation, lastLoc, r, now)) {
Victoria Lease09016ab2012-09-16 12:33:15 -07002978 if (lastLoc == null) {
2979 lastLoc = new Location(notifyLocation);
2980 r.mLastFixBroadcast = lastLoc;
2981 } else {
2982 lastLoc.set(notifyLocation);
2983 }
Wei Wang8486fc72019-03-07 18:49:21 -08002984 // Report location access before delivering location to the client. This will
2985 // note location delivery to appOps, so it should be called only when a
2986 // location is really being delivered to the client.
2987 if (!reportLocationAccessNoThrow(
2988 receiver.mCallerIdentity.mPid,
2989 receiver.mCallerIdentity.mUid,
2990 receiver.mCallerIdentity.mPackageName,
Philip P. Moltmann6c7377c2019-09-27 17:06:25 -07002991 receiver.mCallerIdentity.mFeatureId,
Philip P. Moltmannbc8b48a2019-09-27 17:06:25 -07002992 receiver.mAllowedResolutionLevel,
2993 "Location sent to " + receiver.mCallerIdentity.mListenerIdentifier)) {
Wei Wang8486fc72019-03-07 18:49:21 -08002994 if (D) {
2995 Log.d(TAG, "skipping loc update for no op app: "
2996 + receiver.mCallerIdentity.mPackageName);
2997 }
2998 continue;
2999 }
Victoria Lease09016ab2012-09-16 12:33:15 -07003000 if (!receiver.callLocationChangedLocked(notifyLocation)) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003001 Slog.w(TAG, "RemoteException calling onLocationChanged on "
3002 + receiver);
Victoria Lease09016ab2012-09-16 12:33:15 -07003003 receiverDead = true;
3004 }
Soonil Nagarkard4def0c2017-05-23 15:54:55 -07003005 r.mRealRequest.decrementNumUpdates();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003006 }
3007 }
3008
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003009 // track expired records
Soonil Nagarkar95768ce2019-11-05 15:22:44 -08003010 if (r.mRealRequest.getNumUpdates() <= 0 || r.mExpirationRealtimeMs < now) {
Soonil Nagarkar39d614a2019-10-31 12:10:31 -07003011 // notify the client it can remove this listener
3012 r.mReceiver.callRemovedLocked();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003013 if (deadUpdateRecords == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003014 deadUpdateRecords = new ArrayList<>();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003015 }
3016 deadUpdateRecords.add(r);
3017 }
3018 // track dead receivers
3019 if (receiverDead) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07003020 if (deadReceivers == null) {
Soonil Nagarkar7decfb62017-01-18 12:18:49 -08003021 deadReceivers = new ArrayList<>();
Mike Lockwood03ca2162010-04-01 08:10:09 -07003022 }
3023 if (!deadReceivers.contains(receiver)) {
3024 deadReceivers.add(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003025 }
3026 }
3027 }
Nick Pellye0fd6932012-07-11 10:26:13 -07003028
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003029 // remove dead records and receivers outside the loop
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003030 if (deadReceivers != null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003031 for (Receiver receiver : deadReceivers) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00003032 removeUpdatesLocked(receiver);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003033 }
3034 }
3035 if (deadUpdateRecords != null) {
3036 for (UpdateRecord r : deadUpdateRecords) {
3037 r.disposeLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003038 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00003039 applyRequirementsLocked(provider);
Victoria Lease8b38b292012-12-04 15:04:43 -08003040 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003041 }
3042
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003043 @GuardedBy("mLock")
Soonil Nagarkar68257742019-01-09 19:42:34 +00003044 private void updateLastLocationLocked(Location location, String provider) {
Ram Periathiruvadi8671fea2017-12-08 18:35:10 -08003045 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
3046 Location lastNoGPSLocation;
3047 Location lastLocation = mLastLocation.get(provider);
3048 if (lastLocation == null) {
3049 lastLocation = new Location(provider);
3050 mLastLocation.put(provider, lastLocation);
3051 } else {
3052 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
3053 if (noGPSLocation == null && lastNoGPSLocation != null) {
3054 // New location has no no-GPS location: adopt last no-GPS location. This is set
3055 // directly into location because we do not want to notify COARSE clients.
3056 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
3057 }
3058 }
3059 lastLocation.set(location);
3060 }
3061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003062 // Geocoder
3063
Nick Pellye0fd6932012-07-11 10:26:13 -07003064 @Override
Mike Lockwoode15735a2010-09-20 17:48:47 -04003065 public boolean geocoderIsPresent() {
Mark Vandevoorde01ac80b2010-05-21 15:43:26 -07003066 return mGeocodeProvider != null;
3067 }
3068
Nick Pellye0fd6932012-07-11 10:26:13 -07003069 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003070 public String getFromLocation(double latitude, double longitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05003071 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04003072 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05003073 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
3074 params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003075 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04003076 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003077 }
3078
Mike Lockwooda55c3212009-04-15 11:10:11 -04003079
Nick Pellye0fd6932012-07-11 10:26:13 -07003080 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003081 public String getFromLocationName(String locationName,
Mike Lockwooda55c3212009-04-15 11:10:11 -04003082 double lowerLeftLatitude, double lowerLeftLongitude,
3083 double upperRightLatitude, double upperRightLongitude, int maxResults,
Mike Lockwood34901402010-01-04 12:14:21 -05003084 GeocoderParams params, List<Address> addrs) {
Mike Lockwooda55c3212009-04-15 11:10:11 -04003085
3086 if (mGeocodeProvider != null) {
Mike Lockwood628fd6d2010-01-25 22:46:13 -05003087 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
3088 lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
3089 maxResults, params, addrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003090 }
Mike Lockwooda55c3212009-04-15 11:10:11 -04003091 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003092 }
3093
3094 // Mock Providers
3095
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003096 private boolean canCallerAccessMockLocation(String opPackageName) {
Wei Wang16276a42019-02-04 18:23:31 -08003097 return mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(),
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003098 opPackageName) == AppOpsManager.MODE_ALLOWED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003099 }
3100
Nick Pellye0fd6932012-07-11 10:26:13 -07003101 @Override
Soonil Nagarkar68257742019-01-09 19:42:34 +00003102 public void addTestProvider(String name, ProviderProperties properties, String opPackageName) {
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003103 if (!canCallerAccessMockLocation(opPackageName)) {
3104 return;
3105 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003106
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003107 if (PASSIVE_PROVIDER.equals(name)) {
Mike Lockwooda4903f22010-02-17 06:42:23 -05003108 throw new IllegalArgumentException("Cannot mock the passive location provider");
3109 }
3110
Soonil Nagarkar68257742019-01-09 19:42:34 +00003111 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003112 long identity = Binder.clearCallingIdentity();
3113 try {
3114 LocationProvider oldProvider = getLocationProviderLocked(name);
3115 if (oldProvider != null) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003116 removeProviderLocked(oldProvider);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003117 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003118
3119 MockLocationProvider mockProviderManager = new MockLocationProvider(name);
3120 addProviderLocked(mockProviderManager);
Soonil Nagarkar0d77ea62019-01-31 14:36:56 -08003121 mockProviderManager.attachLocked(
3122 new MockProvider(mContext, mockProviderManager, properties));
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003123 } finally {
3124 Binder.restoreCallingIdentity(identity);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003125 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00003126 }
Ji-Hwan Lee26bdb8f2014-04-21 20:48:19 +09003127 }
3128
Nick Pellye0fd6932012-07-11 10:26:13 -07003129 @Override
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003130 public void removeTestProvider(String name, String opPackageName) {
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003131 if (!canCallerAccessMockLocation(opPackageName)) {
3132 return;
3133 }
3134
Soonil Nagarkar68257742019-01-09 19:42:34 +00003135 synchronized (mLock) {
Soonil Nagarkar68257742019-01-09 19:42:34 +00003136 long identity = Binder.clearCallingIdentity();
3137 try {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003138 LocationProvider testProvider = getLocationProviderLocked(name);
3139 if (testProvider == null || !testProvider.isMock()) {
Soonil Nagarkar0000e8a2019-10-08 14:32:07 -07003140 return;
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003141 }
3142
3143 removeProviderLocked(testProvider);
Soonil Nagarkar1575a042018-10-24 17:54:54 -07003144
Soonil Nagarkar68257742019-01-09 19:42:34 +00003145 // reinstate real provider if available
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003146 LocationProvider realProvider = null;
3147 for (LocationProvider provider : mRealProviders) {
3148 if (name.equals(provider.getName())) {
3149 realProvider = provider;
3150 break;
3151 }
3152 }
3153
Soonil Nagarkar68257742019-01-09 19:42:34 +00003154 if (realProvider != null) {
3155 addProviderLocked(realProvider);
3156 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00003157 } finally {
3158 Binder.restoreCallingIdentity(identity);
Mike Lockwood7566c1d2009-08-25 10:05:18 -07003159 }
Soonil Nagarkar68257742019-01-09 19:42:34 +00003160 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003161 }
3162
Nick Pellye0fd6932012-07-11 10:26:13 -07003163 @Override
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003164 public void setTestProviderLocation(String providerName, Location location,
Soonil Nagarkar68257742019-01-09 19:42:34 +00003165 String opPackageName) {
Svet Ganovf7e9cf42015-05-13 10:40:31 -07003166 if (!canCallerAccessMockLocation(opPackageName)) {
3167 return;
3168 }
3169
Soonil Nagarkar68257742019-01-09 19:42:34 +00003170 synchronized (mLock) {
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003171 LocationProvider testProvider = getLocationProviderLocked(providerName);
3172 if (testProvider == null || !testProvider.isMock()) {
3173 throw new IllegalArgumentException("Provider \"" + providerName + "\" unknown");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003174 }
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003175
3176 String locationProvider = location.getProvider();
3177 if (!TextUtils.isEmpty(locationProvider) && !providerName.equals(locationProvider)) {
3178 // The location has an explicit provider that is different from the mock
3179 // provider name. The caller may be trying to fool us via b/33091107.
3180 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
3181 providerName + "!=" + location.getProvider());
3182 }
3183
3184 ((MockLocationProvider) testProvider).setLocationLocked(location);
Soonil Nagarkar68257742019-01-09 19:42:34 +00003185 }
3186 }
3187
Soonil Nagarkar90da1ab2019-01-04 16:26:59 -08003188 @Override
3189 public void setTestProviderEnabled(String providerName, boolean enabled, String opPackageName) {
3190 if (!canCallerAccessMockLocation(opPackageName)) {
3191 return;
3192 }
3193
3194 synchronized (mLock) {
3195 LocationProvider testProvider = getLocationProviderLocked(providerName);
3196 if (testProvider == null || !testProvider.isMock()) {
3197 throw new IllegalArgumentException("Provider \"" + providerName + "\" unknown");
3198 }
3199
3200 ((MockLocationProvider) testProvider).setEnabledLocked(enabled);
3201 }
3202 }
3203
3204 @Override
Kweku Adams4fb074e2019-02-01 16:03:27 -08003205 @NonNull
3206 public List<LocationRequest> getTestProviderCurrentRequests(String providerName,
3207 String opPackageName) {
3208 if (!canCallerAccessMockLocation(opPackageName)) {
3209 return Collections.emptyList();
3210 }
3211
3212 synchronized (mLock) {
3213 LocationProvider testProvider = getLocationProviderLocked(providerName);
3214 if (testProvider == null || !testProvider.isMock()) {
3215 throw new IllegalArgumentException("Provider \"" + providerName + "\" unknown");
3216 }
3217
3218 MockLocationProvider provider = (MockLocationProvider) testProvider;
3219 if (provider.mCurrentRequest == null) {
3220 return Collections.emptyList();
3221 }
3222 List<LocationRequest> requests = new ArrayList<>();
3223 for (LocationRequest request : provider.mCurrentRequest.locationRequests) {
3224 requests.add(new LocationRequest(request));
3225 }
3226 return requests;
3227 }
3228 }
3229
3230 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003231 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003232 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Nick Pellye0fd6932012-07-11 10:26:13 -07003233
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003234 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
3235
Soonil Nagarkar68257742019-01-09 19:42:34 +00003236 synchronized (mLock) {
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07003237 if (mGnssManagerService != null && args.length > 0 && args[0].equals("--gnssmetrics")) {
3238 mGnssManagerService.dump(fd, pw, args);
Blake Kragten47014d22019-12-06 14:18:38 -08003239 return;
Siddharth Raybb608c82017-03-16 11:33:34 -07003240 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003241
3242 ipw.println("Location Manager State:");
3243 ipw.increaseIndent();
3244 ipw.print("Current System Time: "
WyattRileyba6072f2019-04-18 07:37:52 -07003245 + TimeUtils.logTimeOfDay(System.currentTimeMillis()));
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003246 ipw.println(", Current Elapsed Time: "
WyattRileyba6072f2019-04-18 07:37:52 -07003247 + TimeUtils.formatDuration(SystemClock.elapsedRealtime()));
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003248 ipw.println("Current user: " + mCurrentUserId + " " + Arrays.toString(
Soonil Nagarkarb46c1672019-02-06 12:49:10 -08003249 mCurrentUserProfiles));
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003250 ipw.println("Location Mode: " + isLocationEnabled());
3251 ipw.println("Battery Saver Location Mode: "
Kweku Adams4fb074e2019-02-01 16:03:27 -08003252 + locationPowerSaveModeToString(mBatterySaverMode));
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003253
3254 ipw.println("Location Listeners:");
3255 ipw.increaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003256 for (Receiver receiver : mReceivers.values()) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003257 ipw.println(receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003258 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003259 ipw.decreaseIndent();
3260
3261 ipw.println("Active Records by Provider:");
3262 ipw.increaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003263 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003264 ipw.println(entry.getKey() + ":");
3265 ipw.increaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003266 for (UpdateRecord record : entry.getValue()) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003267 ipw.println(record);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003268 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003269 ipw.decreaseIndent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003270 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003271 ipw.decreaseIndent();
Anil Admal98d49b72019-02-06 15:26:33 -08003272
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003273 ipw.println("Historical Records by Provider:");
3274 ipw.increaseIndent();
David Christie2ff96af2014-01-30 16:09:37 -08003275 for (Map.Entry<PackageProviderKey, PackageStatistics> entry
3276 : mRequestStatistics.statistics.entrySet()) {
3277 PackageProviderKey key = entry.getKey();
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003278 ipw.println(key.packageName + ": " + key.providerName + ": " + entry.getValue());
David Christie2ff96af2014-01-30 16:09:37 -08003279 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003280 ipw.decreaseIndent();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07003281
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003282 ipw.println("Last Known Locations:");
3283 ipw.increaseIndent();
3284 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
3285 ipw.println(entry.getKey() + ": " + entry.getValue());
David Christie1b9b7b12013-04-15 15:31:11 -07003286 }
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003287 ipw.decreaseIndent();
3288
3289 ipw.println("Last Known Coarse Locations:");
3290 ipw.increaseIndent();
3291 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
3292 ipw.println(entry.getKey() + ": " + entry.getValue());
3293 }
3294 ipw.decreaseIndent();
David Christie1b9b7b12013-04-15 15:31:11 -07003295
Tyler Trephan2f3ee9a2019-03-21 10:54:22 -07003296 if (mGeofenceManager != null) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003297 ipw.println("Geofences:");
3298 ipw.increaseIndent();
3299 mGeofenceManager.dump(ipw);
3300 ipw.decreaseIndent();
Tyler Trephan2f3ee9a2019-03-21 10:54:22 -07003301 }
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07003302
Wei Wang114922a2019-01-30 18:19:35 -08003303 if (mExtraLocationControllerPackage != null) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003304 ipw.println("Location Controller Extra Package: " + mExtraLocationControllerPackage
3305 + (mExtraLocationControllerPackageEnabled ? " [enabled]" : "[disabled]"));
Wei Wang980b7c22018-12-06 17:53:00 -08003306 }
3307
Tyler Trephan2f3ee9a2019-03-21 10:54:22 -07003308 if (mLocationFudger != null) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003309 ipw.println("Location Fudger:");
3310 ipw.increaseIndent();
3311 mLocationFudger.dump(fd, ipw, args);
3312 ipw.decreaseIndent();
Tyler Trephan2f3ee9a2019-03-21 10:54:22 -07003313 }
Nick Pelly74fa7ea2012-08-13 19:36:38 -07003314
Soonil Nagarkar1249eaf2019-11-21 12:40:49 -08003315 ipw.println("Location Settings:");
3316 ipw.increaseIndent();
3317 mSettingsStore.dump(fd, ipw, args);
3318 ipw.decreaseIndent();
Soonil Nagarkarb8466b72019-10-25 14:10:30 -07003319
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003320 ipw.println("Location Providers:");
3321 ipw.increaseIndent();
Soonil Nagarkar1575a042018-10-24 17:54:54 -07003322 for (LocationProvider provider : mProviders) {
Soonil Nagarkar1c572552019-07-10 13:31:47 -07003323 provider.dumpLocked(fd, ipw, args);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06003324 }
Soonil Nagarkar1249eaf2019-11-21 12:40:49 -08003325 ipw.decreaseIndent();
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07003326 }
Anil Admal98d49b72019-02-06 15:26:33 -08003327
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07003328 if (mGnssManagerService != null) {
Soonil Nagarkar1249eaf2019-11-21 12:40:49 -08003329 ipw.println("GNSS:");
3330 ipw.increaseIndent();
3331 mGnssManagerService.dump(fd, ipw, args);
Sasha Kuznetsova8ace3c2019-09-13 14:14:40 -07003332 ipw.decreaseIndent();
Anil Admal98d49b72019-02-06 15:26:33 -08003333 }
3334 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003335}