• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 
17 package com.android.server.location;
18 
19 import static android.Manifest.permission.ACCESS_FINE_LOCATION;
20 import static android.app.compat.CompatChanges.isChangeEnabled;
21 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
22 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
23 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
24 import static android.location.LocationManager.BLOCK_PENDING_INTENT_SYSTEM_API_USAGE;
25 import static android.location.LocationManager.FUSED_PROVIDER;
26 import static android.location.LocationManager.GPS_PROVIDER;
27 import static android.location.LocationManager.NETWORK_PROVIDER;
28 import static android.location.LocationRequest.LOW_POWER_EXCEPTIONS;
29 import static android.location.provider.LocationProviderBase.ACTION_FUSED_PROVIDER;
30 import static android.location.provider.LocationProviderBase.ACTION_NETWORK_PROVIDER;
31 
32 import static com.android.server.location.LocationPermissions.PERMISSION_COARSE;
33 import static com.android.server.location.LocationPermissions.PERMISSION_FINE;
34 import static com.android.server.location.eventlog.LocationEventLog.EVENT_LOG;
35 
36 import static java.util.concurrent.TimeUnit.NANOSECONDS;
37 
38 import android.Manifest;
39 import android.Manifest.permission;
40 import android.annotation.NonNull;
41 import android.annotation.Nullable;
42 import android.app.ActivityManager;
43 import android.app.AppOpsManager;
44 import android.app.PendingIntent;
45 import android.app.compat.CompatChanges;
46 import android.content.Context;
47 import android.content.Intent;
48 import android.content.pm.PackageManager;
49 import android.location.Criteria;
50 import android.location.GeocoderParams;
51 import android.location.Geofence;
52 import android.location.GnssAntennaInfo;
53 import android.location.GnssCapabilities;
54 import android.location.GnssMeasurementCorrections;
55 import android.location.GnssMeasurementRequest;
56 import android.location.IGeocodeListener;
57 import android.location.IGnssAntennaInfoListener;
58 import android.location.IGnssMeasurementsListener;
59 import android.location.IGnssNavigationMessageListener;
60 import android.location.IGnssNmeaListener;
61 import android.location.IGnssStatusListener;
62 import android.location.ILocationCallback;
63 import android.location.ILocationListener;
64 import android.location.ILocationManager;
65 import android.location.LastLocationRequest;
66 import android.location.Location;
67 import android.location.LocationManager;
68 import android.location.LocationManagerInternal;
69 import android.location.LocationManagerInternal.LocationPackageTagsListener;
70 import android.location.LocationProvider;
71 import android.location.LocationRequest;
72 import android.location.LocationTime;
73 import android.location.provider.IProviderRequestListener;
74 import android.location.provider.ProviderProperties;
75 import android.location.util.identity.CallerIdentity;
76 import android.os.Binder;
77 import android.os.Build;
78 import android.os.Bundle;
79 import android.os.ICancellationSignal;
80 import android.os.PackageTagsList;
81 import android.os.ParcelFileDescriptor;
82 import android.os.Process;
83 import android.os.RemoteException;
84 import android.os.UserHandle;
85 import android.os.WorkSource;
86 import android.os.WorkSource.WorkChain;
87 import android.provider.Settings;
88 import android.stats.location.LocationStatsEnums;
89 import android.util.ArrayMap;
90 import android.util.ArraySet;
91 import android.util.IndentingPrintWriter;
92 import android.util.Log;
93 
94 import com.android.internal.annotations.GuardedBy;
95 import com.android.internal.util.ArrayUtils;
96 import com.android.internal.util.DumpUtils;
97 import com.android.internal.util.Preconditions;
98 import com.android.server.FgThread;
99 import com.android.server.LocalServices;
100 import com.android.server.SystemService;
101 import com.android.server.location.eventlog.LocationEventLog;
102 import com.android.server.location.geofence.GeofenceManager;
103 import com.android.server.location.geofence.GeofenceProxy;
104 import com.android.server.location.gnss.GnssConfiguration;
105 import com.android.server.location.gnss.GnssManagerService;
106 import com.android.server.location.gnss.hal.GnssNative;
107 import com.android.server.location.injector.AlarmHelper;
108 import com.android.server.location.injector.AppForegroundHelper;
109 import com.android.server.location.injector.AppOpsHelper;
110 import com.android.server.location.injector.DeviceIdleHelper;
111 import com.android.server.location.injector.DeviceStationaryHelper;
112 import com.android.server.location.injector.EmergencyHelper;
113 import com.android.server.location.injector.Injector;
114 import com.android.server.location.injector.LocationAttributionHelper;
115 import com.android.server.location.injector.LocationPermissionsHelper;
116 import com.android.server.location.injector.LocationPowerSaveModeHelper;
117 import com.android.server.location.injector.LocationUsageLogger;
118 import com.android.server.location.injector.ScreenInteractiveHelper;
119 import com.android.server.location.injector.SettingsHelper;
120 import com.android.server.location.injector.SystemAlarmHelper;
121 import com.android.server.location.injector.SystemAppForegroundHelper;
122 import com.android.server.location.injector.SystemAppOpsHelper;
123 import com.android.server.location.injector.SystemDeviceIdleHelper;
124 import com.android.server.location.injector.SystemDeviceStationaryHelper;
125 import com.android.server.location.injector.SystemEmergencyHelper;
126 import com.android.server.location.injector.SystemLocationPermissionsHelper;
127 import com.android.server.location.injector.SystemLocationPowerSaveModeHelper;
128 import com.android.server.location.injector.SystemScreenInteractiveHelper;
129 import com.android.server.location.injector.SystemSettingsHelper;
130 import com.android.server.location.injector.SystemUserInfoHelper;
131 import com.android.server.location.injector.UserInfoHelper;
132 import com.android.server.location.provider.AbstractLocationProvider;
133 import com.android.server.location.provider.LocationProviderManager;
134 import com.android.server.location.provider.MockLocationProvider;
135 import com.android.server.location.provider.PassiveLocationProvider;
136 import com.android.server.location.provider.PassiveLocationProviderManager;
137 import com.android.server.location.provider.StationaryThrottlingLocationProvider;
138 import com.android.server.location.provider.proxy.ProxyLocationProvider;
139 import com.android.server.location.settings.LocationSettings;
140 import com.android.server.location.settings.LocationUserSettings;
141 import com.android.server.pm.permission.LegacyPermissionManagerInternal;
142 
143 import java.io.FileDescriptor;
144 import java.io.PrintWriter;
145 import java.util.ArrayList;
146 import java.util.Collections;
147 import java.util.List;
148 import java.util.Objects;
149 import java.util.concurrent.CopyOnWriteArrayList;
150 
151 /**
152  * The service class that manages LocationProviders and issues location
153  * updates and alerts.
154  */
155 public class LocationManagerService extends ILocationManager.Stub implements
156         LocationProviderManager.StateChangedListener {
157 
158     /**
159      * Controls lifecycle of LocationManagerService.
160      */
161     public static class Lifecycle extends SystemService {
162 
163         private final LifecycleUserInfoHelper mUserInfoHelper;
164         private final SystemInjector mSystemInjector;
165         private final LocationManagerService mService;
166 
Lifecycle(Context context)167         public Lifecycle(Context context) {
168             super(context);
169             mUserInfoHelper = new LifecycleUserInfoHelper(context);
170             mSystemInjector = new SystemInjector(context, mUserInfoHelper);
171             mService = new LocationManagerService(context, mSystemInjector);
172         }
173 
174         @Override
onStart()175         public void onStart() {
176             publishBinderService(Context.LOCATION_SERVICE, mService);
177 
178             // client caching behavior is only enabled after seeing the first invalidate
179             LocationManager.invalidateLocalLocationEnabledCaches();
180             // disable caching for our own process
181             LocationManager.disableLocalLocationEnabledCaches();
182         }
183 
184         @Override
onBootPhase(int phase)185         public void onBootPhase(int phase) {
186             if (phase == PHASE_SYSTEM_SERVICES_READY) {
187                 // the location service must be functioning after this boot phase
188                 mSystemInjector.onSystemReady();
189                 mService.onSystemReady();
190             } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
191                 // some providers rely on third party code, so we wait to initialize
192                 // providers until third party code is allowed to run
193                 mService.onSystemThirdPartyAppsCanStart();
194             }
195         }
196 
197         @Override
onUserStarting(TargetUser user)198         public void onUserStarting(TargetUser user) {
199             mUserInfoHelper.onUserStarted(user.getUserIdentifier());
200         }
201 
202         @Override
onUserSwitching(TargetUser from, TargetUser to)203         public void onUserSwitching(TargetUser from, TargetUser to) {
204             mUserInfoHelper.onCurrentUserChanged(from.getUserIdentifier(),
205                     to.getUserIdentifier());
206         }
207 
208         @Override
onUserStopped(TargetUser user)209         public void onUserStopped(TargetUser user) {
210             mUserInfoHelper.onUserStopped(user.getUserIdentifier());
211         }
212 
213         private static class LifecycleUserInfoHelper extends SystemUserInfoHelper {
214 
LifecycleUserInfoHelper(Context context)215             LifecycleUserInfoHelper(Context context) {
216                 super(context);
217             }
218 
onUserStarted(int userId)219             void onUserStarted(int userId) {
220                 dispatchOnUserStarted(userId);
221             }
222 
onUserStopped(int userId)223             void onUserStopped(int userId) {
224                 dispatchOnUserStopped(userId);
225             }
226 
onCurrentUserChanged(int fromUserId, int toUserId)227             void onCurrentUserChanged(int fromUserId, int toUserId) {
228                 dispatchOnCurrentUserChanged(fromUserId, toUserId);
229             }
230         }
231     }
232 
233     public static final String TAG = "LocationManagerService";
234     public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
235 
236     private static final String ATTRIBUTION_TAG = "LocationService";
237 
238     final Object mLock = new Object();
239 
240     private final Context mContext;
241     private final Injector mInjector;
242     private final LocalService mLocalService;
243 
244     private final GeofenceManager mGeofenceManager;
245     private volatile @Nullable GnssManagerService mGnssManagerService = null;
246     private GeocoderProxy mGeocodeProvider;
247 
248     private final Object mDeprecatedGnssBatchingLock = new Object();
249     @GuardedBy("mDeprecatedGnssBatchingLock")
250     private @Nullable ILocationListener mDeprecatedGnssBatchingListener;
251 
252     @GuardedBy("mLock")
253     private String mExtraLocationControllerPackage;
254     @GuardedBy("mLock")
255     private boolean mExtraLocationControllerPackageEnabled;
256 
257     // location provider managers
258 
259     private final PassiveLocationProviderManager mPassiveManager;
260 
261     // @GuardedBy("mProviderManagers")
262     // hold lock for writes, no lock necessary for simple reads
263     final CopyOnWriteArrayList<LocationProviderManager> mProviderManagers =
264             new CopyOnWriteArrayList<>();
265 
266     @GuardedBy("mLock")
267     @Nullable LocationPackageTagsListener mLocationTagsChangedListener;
268 
LocationManagerService(Context context, Injector injector)269     LocationManagerService(Context context, Injector injector) {
270         mContext = context.createAttributionContext(ATTRIBUTION_TAG);
271         mInjector = injector;
272         mLocalService = new LocalService();
273         LocalServices.addService(LocationManagerInternal.class, mLocalService);
274 
275         mGeofenceManager = new GeofenceManager(mContext, injector);
276 
277         mInjector.getLocationSettings().registerLocationUserSettingsListener(
278                 this::onLocationUserSettingsChanged);
279         mInjector.getSettingsHelper().addOnLocationEnabledChangedListener(
280                 this::onLocationModeChanged);
281         mInjector.getSettingsHelper().addIgnoreSettingsAllowlistChangedListener(
282                 () -> refreshAppOpsRestrictions(UserHandle.USER_ALL));
283         mInjector.getUserInfoHelper().addListener((userId, change) -> {
284             if (change == UserInfoHelper.UserListener.USER_STARTED) {
285                 refreshAppOpsRestrictions(userId);
286             }
287         });
288 
289         // set up passive provider first since it will be required for all other location providers,
290         // which are loaded later once the system is ready.
291         mPassiveManager = new PassiveLocationProviderManager(mContext, injector);
292         addLocationProviderManager(mPassiveManager, new PassiveLocationProvider(mContext));
293 
294         // TODO: load the gps provider here as well, which will require refactoring
295 
296         // Let the package manager query which are the default location
297         // providers as they get certain permissions granted by default.
298         LegacyPermissionManagerInternal permissionManagerInternal = LocalServices.getService(
299                 LegacyPermissionManagerInternal.class);
300         permissionManagerInternal.setLocationPackagesProvider(
301                 userId -> mContext.getResources().getStringArray(
302                         com.android.internal.R.array.config_locationProviderPackageNames));
303         permissionManagerInternal.setLocationExtraPackagesProvider(
304                 userId -> mContext.getResources().getStringArray(
305                         com.android.internal.R.array.config_locationExtraPackageNames));
306     }
307 
308     @Nullable
getLocationProviderManager(String providerName)309     LocationProviderManager getLocationProviderManager(String providerName) {
310         if (providerName == null) {
311             return null;
312         }
313 
314         for (LocationProviderManager manager : mProviderManagers) {
315             if (providerName.equals(manager.getName())) {
316                 return manager;
317             }
318         }
319 
320         return null;
321     }
322 
getOrAddLocationProviderManager(String providerName)323     private LocationProviderManager getOrAddLocationProviderManager(String providerName) {
324         synchronized (mProviderManagers) {
325             for (LocationProviderManager manager : mProviderManagers) {
326                 if (providerName.equals(manager.getName())) {
327                     return manager;
328                 }
329             }
330 
331             LocationProviderManager manager = new LocationProviderManager(mContext, mInjector,
332                     providerName, mPassiveManager);
333             addLocationProviderManager(manager, null);
334             return manager;
335         }
336     }
337 
addLocationProviderManager(LocationProviderManager manager, @Nullable AbstractLocationProvider realProvider)338     private void addLocationProviderManager(LocationProviderManager manager,
339             @Nullable AbstractLocationProvider realProvider) {
340         synchronized (mProviderManagers) {
341             Preconditions.checkState(getLocationProviderManager(manager.getName()) == null);
342 
343             manager.startManager(this);
344 
345             if (realProvider != null) {
346                 // custom logic wrapping all non-passive providers
347                 if (manager != mPassiveManager) {
348                     boolean enableStationaryThrottling = Settings.Global.getInt(
349                             mContext.getContentResolver(),
350                             Settings.Global.LOCATION_ENABLE_STATIONARY_THROTTLE, 1) != 0;
351                     if (enableStationaryThrottling) {
352                         realProvider = new StationaryThrottlingLocationProvider(manager.getName(),
353                                 mInjector, realProvider);
354                     }
355                 }
356                 manager.setRealProvider(realProvider);
357             }
358             mProviderManagers.add(manager);
359         }
360     }
361 
removeLocationProviderManager(LocationProviderManager manager)362     private void removeLocationProviderManager(LocationProviderManager manager) {
363         synchronized (mProviderManagers) {
364             boolean removed = mProviderManagers.remove(manager);
365             Preconditions.checkArgument(removed);
366             manager.setMockProvider(null);
367             manager.setRealProvider(null);
368             manager.stopManager();
369         }
370     }
371 
onSystemReady()372     void onSystemReady() {
373         if (Build.IS_DEBUGGABLE) {
374             // on debug builds, watch for location noteOps while location is off. there are some
375             // scenarios (emergency location) where this is expected, but generally this should
376             // rarely occur, and may indicate bugs. dump occurrences to logs for further evaluation
377             AppOpsManager appOps = Objects.requireNonNull(
378                     mContext.getSystemService(AppOpsManager.class));
379             appOps.startWatchingNoted(
380                     new int[]{AppOpsManager.OP_FINE_LOCATION, AppOpsManager.OP_COARSE_LOCATION},
381                     (code, uid, packageName, attributionTag, flags, result) -> {
382                         if (!isLocationEnabledForUser(UserHandle.getUserId(uid))) {
383                             Log.w(TAG, "location noteOp with location off - "
384                                     + CallerIdentity.forTest(uid, 0, packageName, attributionTag));
385                         }
386                     });
387         }
388     }
389 
onSystemThirdPartyAppsCanStart()390     void onSystemThirdPartyAppsCanStart() {
391         // network provider should always be initialized before the gps provider since the gps
392         // provider has unfortunate hard dependencies on the network provider
393         ProxyLocationProvider networkProvider = ProxyLocationProvider.create(
394                 mContext,
395                 NETWORK_PROVIDER,
396                 ACTION_NETWORK_PROVIDER,
397                 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
398                 com.android.internal.R.string.config_networkLocationProviderPackageName);
399         if (networkProvider != null) {
400             LocationProviderManager networkManager = new LocationProviderManager(mContext,
401                     mInjector, NETWORK_PROVIDER, mPassiveManager);
402             addLocationProviderManager(networkManager, networkProvider);
403         } else {
404             Log.w(TAG, "no network location provider found");
405         }
406 
407         // ensure that a fused provider exists which will work in direct boot
408         Preconditions.checkState(!mContext.getPackageManager().queryIntentServicesAsUser(
409                 new Intent(ACTION_FUSED_PROVIDER),
410                 MATCH_DIRECT_BOOT_AWARE | MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM).isEmpty(),
411                 "Unable to find a direct boot aware fused location provider");
412 
413         ProxyLocationProvider fusedProvider = ProxyLocationProvider.create(
414                 mContext,
415                 FUSED_PROVIDER,
416                 ACTION_FUSED_PROVIDER,
417                 com.android.internal.R.bool.config_enableFusedLocationOverlay,
418                 com.android.internal.R.string.config_fusedLocationProviderPackageName);
419         if (fusedProvider != null) {
420             LocationProviderManager fusedManager = new LocationProviderManager(mContext, mInjector,
421                     FUSED_PROVIDER, mPassiveManager);
422             addLocationProviderManager(fusedManager, fusedProvider);
423         } else {
424             Log.wtf(TAG, "no fused location provider found");
425         }
426 
427         // initialize gnss last because it has no awareness of boot phases and blindly assumes that
428         // all other location providers are loaded at initialization
429         if (GnssNative.isSupported()) {
430             GnssConfiguration gnssConfiguration = new GnssConfiguration(mContext);
431             GnssNative gnssNative = GnssNative.create(mInjector, gnssConfiguration);
432             mGnssManagerService = new GnssManagerService(mContext, mInjector, gnssNative);
433             mGnssManagerService.onSystemReady();
434 
435             LocationProviderManager gnssManager = new LocationProviderManager(mContext, mInjector,
436                     GPS_PROVIDER, mPassiveManager);
437             addLocationProviderManager(gnssManager, mGnssManagerService.getGnssLocationProvider());
438         }
439 
440         // bind to geocoder provider
441         mGeocodeProvider = GeocoderProxy.createAndRegister(mContext);
442         if (mGeocodeProvider == null) {
443             Log.e(TAG, "no geocoder provider found");
444         }
445 
446         // bind to hardware activity recognition
447         HardwareActivityRecognitionProxy hardwareActivityRecognitionProxy =
448                 HardwareActivityRecognitionProxy.createAndRegister(mContext);
449         if (hardwareActivityRecognitionProxy == null) {
450             Log.e(TAG, "unable to bind ActivityRecognitionProxy");
451         }
452 
453         // bind to gnss geofence proxy
454         if (mGnssManagerService != null) {
455             GeofenceProxy provider = GeofenceProxy.createAndBind(mContext,
456                     mGnssManagerService.getGnssGeofenceProxy());
457             if (provider == null) {
458                 Log.e(TAG, "unable to bind to GeofenceProxy");
459             }
460         }
461 
462         // create any predefined test providers
463         String[] testProviderStrings = mContext.getResources().getStringArray(
464                 com.android.internal.R.array.config_testLocationProviders);
465         for (String testProviderString : testProviderStrings) {
466             String[] fragments = testProviderString.split(",");
467             String name = fragments[0].trim();
468             ProviderProperties properties = new ProviderProperties.Builder()
469                     .setHasNetworkRequirement(Boolean.parseBoolean(fragments[1]))
470                     .setHasSatelliteRequirement(Boolean.parseBoolean(fragments[2]))
471                     .setHasCellRequirement(Boolean.parseBoolean(fragments[3]))
472                     .setHasMonetaryCost(Boolean.parseBoolean(fragments[4]))
473                     .setHasAltitudeSupport(Boolean.parseBoolean(fragments[5]))
474                     .setHasSpeedSupport(Boolean.parseBoolean(fragments[6]))
475                     .setHasBearingSupport(Boolean.parseBoolean(fragments[7]))
476                     .setPowerUsage(Integer.parseInt(fragments[8]))
477                     .setAccuracy(Integer.parseInt(fragments[9]))
478                     .build();
479             final LocationProviderManager manager = getOrAddLocationProviderManager(name);
480             manager.setMockProvider(new MockLocationProvider(properties,
481                     CallerIdentity.fromContext(mContext), Collections.emptySet()));
482         }
483     }
484 
onLocationUserSettingsChanged(int userId, LocationUserSettings oldSettings, LocationUserSettings newSettings)485     private void onLocationUserSettingsChanged(int userId, LocationUserSettings oldSettings,
486             LocationUserSettings newSettings) {
487         if (oldSettings.isAdasGnssLocationEnabled() != newSettings.isAdasGnssLocationEnabled()) {
488             boolean enabled = newSettings.isAdasGnssLocationEnabled();
489 
490             if (D) {
491                 Log.d(TAG, "[u" + userId + "] adas gnss location enabled = " + enabled);
492             }
493 
494             EVENT_LOG.logAdasLocationEnabled(userId, enabled);
495 
496             Intent intent = new Intent(LocationManager.ACTION_ADAS_GNSS_ENABLED_CHANGED)
497                     .putExtra(LocationManager.EXTRA_ADAS_GNSS_ENABLED, enabled)
498                     .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
499                     .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
500             mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
501         }
502     }
503 
onLocationModeChanged(int userId)504     private void onLocationModeChanged(int userId) {
505         boolean enabled = mInjector.getSettingsHelper().isLocationEnabled(userId);
506         LocationManager.invalidateLocalLocationEnabledCaches();
507 
508         if (D) {
509             Log.d(TAG, "[u" + userId + "] location enabled = " + enabled);
510         }
511 
512         EVENT_LOG.logLocationEnabled(userId, enabled);
513 
514         Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION)
515                 .putExtra(LocationManager.EXTRA_LOCATION_ENABLED, enabled)
516                 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
517                 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
518         mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
519 
520         refreshAppOpsRestrictions(userId);
521     }
522 
523     @Override
getGnssYearOfHardware()524     public int getGnssYearOfHardware() {
525         return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssYearOfHardware();
526     }
527 
528     @Override
529     @Nullable
getGnssHardwareModelName()530     public String getGnssHardwareModelName() {
531         return mGnssManagerService == null ? "" : mGnssManagerService.getGnssHardwareModelName();
532     }
533 
534     @Override
getGnssBatchSize()535     public int getGnssBatchSize() {
536         return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssBatchSize();
537     }
538 
539     @Override
startGnssBatch(long periodNanos, ILocationListener listener, String packageName, @Nullable String attributionTag, String listenerId)540     public void startGnssBatch(long periodNanos, ILocationListener listener, String packageName,
541             @Nullable String attributionTag, String listenerId) {
542         mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
543 
544         if (mGnssManagerService == null) {
545             return;
546         }
547 
548         long intervalMs = NANOSECONDS.toMillis(periodNanos);
549 
550         synchronized (mDeprecatedGnssBatchingLock) {
551             stopGnssBatch();
552 
553             registerLocationListener(
554                     GPS_PROVIDER,
555                     new LocationRequest.Builder(intervalMs)
556                             .setMaxUpdateDelayMillis(
557                                     intervalMs * mGnssManagerService.getGnssBatchSize())
558                             .setHiddenFromAppOps(true)
559                             .build(),
560                     listener,
561                     packageName,
562                     attributionTag,
563                     listenerId);
564             mDeprecatedGnssBatchingListener = listener;
565         }
566     }
567 
568     @Override
flushGnssBatch()569     public void flushGnssBatch() {
570         mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
571 
572         if (mGnssManagerService == null) {
573             return;
574         }
575 
576         synchronized (mDeprecatedGnssBatchingLock) {
577             if (mDeprecatedGnssBatchingListener != null) {
578                 requestListenerFlush(GPS_PROVIDER, mDeprecatedGnssBatchingListener, 0);
579             }
580         }
581     }
582 
583     @Override
stopGnssBatch()584     public void stopGnssBatch() {
585         mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
586 
587         if (mGnssManagerService == null) {
588             return;
589         }
590 
591         synchronized (mDeprecatedGnssBatchingLock) {
592             if (mDeprecatedGnssBatchingListener != null) {
593                 ILocationListener listener = mDeprecatedGnssBatchingListener;
594                 mDeprecatedGnssBatchingListener = null;
595                 unregisterLocationListener(listener);
596             }
597         }
598     }
599 
600     @Override
hasProvider(String provider)601     public boolean hasProvider(String provider) {
602         return getLocationProviderManager(provider) != null;
603     }
604 
605     @Override
getAllProviders()606     public List<String> getAllProviders() {
607         ArrayList<String> providers = new ArrayList<>(mProviderManagers.size());
608         for (LocationProviderManager manager : mProviderManagers) {
609             providers.add(manager.getName());
610         }
611         return providers;
612     }
613 
614     @Override
getProviders(Criteria criteria, boolean enabledOnly)615     public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
616         if (!LocationPermissions.checkCallingOrSelfLocationPermission(mContext,
617                 PERMISSION_COARSE)) {
618             return Collections.emptyList();
619         }
620 
621         synchronized (mLock) {
622             ArrayList<String> providers = new ArrayList<>(mProviderManagers.size());
623             for (LocationProviderManager manager : mProviderManagers) {
624                 String name = manager.getName();
625                 if (enabledOnly && !manager.isEnabled(UserHandle.getCallingUserId())) {
626                     continue;
627                 }
628                 if (criteria != null && !LocationProvider.propertiesMeetCriteria(name,
629                         manager.getProperties(), criteria)) {
630                     continue;
631                 }
632                 providers.add(name);
633             }
634             return providers;
635         }
636     }
637 
638     @Override
getBestProvider(Criteria criteria, boolean enabledOnly)639     public String getBestProvider(Criteria criteria, boolean enabledOnly) {
640         List<String> providers;
641         synchronized (mLock) {
642             providers = getProviders(criteria, enabledOnly);
643             if (providers.isEmpty()) {
644                 providers = getProviders(null, enabledOnly);
645             }
646         }
647 
648         if (!providers.isEmpty()) {
649             if (providers.contains(FUSED_PROVIDER)) {
650                 return FUSED_PROVIDER;
651             } else if (providers.contains(GPS_PROVIDER)) {
652                 return GPS_PROVIDER;
653             } else if (providers.contains(NETWORK_PROVIDER)) {
654                 return NETWORK_PROVIDER;
655             } else {
656                 return providers.get(0);
657             }
658         }
659 
660         return null;
661     }
662 
663     @Override
getBackgroundThrottlingWhitelist()664     public String[] getBackgroundThrottlingWhitelist() {
665         return mInjector.getSettingsHelper().getBackgroundThrottlePackageWhitelist().toArray(
666                 new String[0]);
667     }
668 
669     @Override
getIgnoreSettingsAllowlist()670     public PackageTagsList getIgnoreSettingsAllowlist() {
671         return mInjector.getSettingsHelper().getIgnoreSettingsAllowlist();
672     }
673 
674     @Nullable
675     @Override
getCurrentLocation(String provider, LocationRequest request, ILocationCallback consumer, String packageName, @Nullable String attributionTag, String listenerId)676     public ICancellationSignal getCurrentLocation(String provider, LocationRequest request,
677             ILocationCallback consumer, String packageName, @Nullable String attributionTag,
678             String listenerId) {
679         CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
680                 listenerId);
681         int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(),
682                 identity.getPid());
683         LocationPermissions.enforceLocationPermission(identity.getUid(), permissionLevel,
684                 PERMISSION_COARSE);
685 
686         // clients in the system process must have an attribution tag set
687         Preconditions.checkState(identity.getPid() != Process.myPid() || attributionTag != null);
688 
689         request = validateLocationRequest(provider, request, identity);
690 
691         LocationProviderManager manager = getLocationProviderManager(provider);
692         Preconditions.checkArgument(manager != null,
693                 "provider \"" + provider + "\" does not exist");
694 
695         return manager.getCurrentLocation(request, identity, permissionLevel, consumer);
696     }
697 
698     @Override
registerLocationListener(String provider, LocationRequest request, ILocationListener listener, String packageName, @Nullable String attributionTag, String listenerId)699     public void registerLocationListener(String provider, LocationRequest request,
700             ILocationListener listener, String packageName, @Nullable String attributionTag,
701             String listenerId) {
702         CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
703                 listenerId);
704         int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(),
705                 identity.getPid());
706         LocationPermissions.enforceLocationPermission(identity.getUid(), permissionLevel,
707                 PERMISSION_COARSE);
708 
709         // clients in the system process should have an attribution tag set
710         if (identity.getPid() == Process.myPid() && attributionTag == null) {
711             Log.w(TAG, "system location request with no attribution tag",
712                     new IllegalArgumentException());
713         }
714 
715         request = validateLocationRequest(provider, request, identity);
716 
717         LocationProviderManager manager = getLocationProviderManager(provider);
718         Preconditions.checkArgument(manager != null,
719                 "provider \"" + provider + "\" does not exist");
720 
721         manager.registerLocationRequest(request, identity, permissionLevel, listener);
722     }
723 
724     @Override
registerLocationPendingIntent(String provider, LocationRequest request, PendingIntent pendingIntent, String packageName, @Nullable String attributionTag)725     public void registerLocationPendingIntent(String provider, LocationRequest request,
726             PendingIntent pendingIntent, String packageName, @Nullable String attributionTag) {
727         CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
728                 AppOpsManager.toReceiverId(pendingIntent));
729         int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(),
730                 identity.getPid());
731         LocationPermissions.enforceLocationPermission(identity.getUid(), permissionLevel,
732                 PERMISSION_COARSE);
733 
734         // clients in the system process must have an attribution tag set
735         Preconditions.checkArgument(identity.getPid() != Process.myPid() || attributionTag != null);
736 
737         // pending intents requests may not use system apis because we do not keep track if clients
738         // lose the relevant permissions, and thus should not get the benefit of those apis. its
739         // simplest to ensure these apis are simply never set for pending intent requests. the same
740         // does not apply for listener requests since those will have the process (including the
741         // listener) killed on permission removal
742         if (isChangeEnabled(BLOCK_PENDING_INTENT_SYSTEM_API_USAGE, identity.getUid())) {
743             boolean usesSystemApi = request.isLowPower()
744                     || request.isHiddenFromAppOps()
745                     || request.isLocationSettingsIgnored()
746                     || !request.getWorkSource().isEmpty();
747             if (usesSystemApi) {
748                 throw new SecurityException(
749                         "PendingIntent location requests may not use system APIs: " + request);
750             }
751         }
752 
753         request = validateLocationRequest(provider, request, identity);
754 
755         LocationProviderManager manager = getLocationProviderManager(provider);
756         Preconditions.checkArgument(manager != null,
757                 "provider \"" + provider + "\" does not exist");
758 
759         manager.registerLocationRequest(request, identity, permissionLevel, pendingIntent);
760     }
761 
validateLocationRequest(String provider, LocationRequest request, CallerIdentity identity)762     private LocationRequest validateLocationRequest(String provider, LocationRequest request,
763             CallerIdentity identity) {
764         // validate unsanitized request
765         if (!request.getWorkSource().isEmpty()) {
766             mContext.enforceCallingOrSelfPermission(
767                     permission.UPDATE_DEVICE_STATS,
768                     "setting a work source requires " + permission.UPDATE_DEVICE_STATS);
769         }
770 
771         // sanitize request
772         LocationRequest.Builder sanitized = new LocationRequest.Builder(request);
773 
774         if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
775                 && GPS_PROVIDER.equals(provider)
776                 && ArrayUtils.contains(mContext.getResources().getStringArray(
777                 com.android.internal.R.array.config_locationDriverAssistancePackageNames),
778                 identity.getPackageName())) {
779             sanitized.setAdasGnssBypass(true);
780         }
781 
782         if (!CompatChanges.isChangeEnabled(LOW_POWER_EXCEPTIONS, Binder.getCallingUid())) {
783             if (mContext.checkCallingPermission(permission.LOCATION_HARDWARE)
784                     != PERMISSION_GRANTED) {
785                 sanitized.setLowPower(false);
786             }
787         }
788 
789         WorkSource workSource = new WorkSource(request.getWorkSource());
790         if (workSource.size() > 0 && workSource.getPackageName(0) == null) {
791             Log.w(TAG, "received (and ignoring) illegal worksource with no package name");
792             workSource.clear();
793         } else {
794             List<WorkChain> workChains = workSource.getWorkChains();
795             if (workChains != null && !workChains.isEmpty()
796                     && workChains.get(0).getAttributionTag() == null) {
797                 Log.w(TAG,
798                         "received (and ignoring) illegal worksource with no attribution tag");
799                 workSource.clear();
800             }
801         }
802 
803         if (workSource.isEmpty()) {
804             identity.addToWorkSource(workSource);
805         }
806         sanitized.setWorkSource(workSource);
807 
808         request = sanitized.build();
809 
810         // validate sanitized request
811         boolean isLocationProvider = mLocalService.isProvider(null, identity);
812 
813         if (request.isLowPower() && CompatChanges.isChangeEnabled(LOW_POWER_EXCEPTIONS,
814                 identity.getUid())) {
815             mContext.enforceCallingOrSelfPermission(
816                     permission.LOCATION_HARDWARE,
817                     "low power request requires " + permission.LOCATION_HARDWARE);
818         }
819         if (request.isHiddenFromAppOps()) {
820             mContext.enforceCallingOrSelfPermission(
821                     permission.UPDATE_APP_OPS_STATS,
822                     "hiding from app ops requires " + permission.UPDATE_APP_OPS_STATS);
823         }
824         if (request.isAdasGnssBypass()) {
825             if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
826                 throw new IllegalArgumentException(
827                         "adas gnss bypass requests are only allowed on automotive devices");
828             }
829             if (!GPS_PROVIDER.equals(provider)) {
830                 throw new IllegalArgumentException(
831                         "adas gnss bypass requests are only allowed on the \"gps\" provider");
832             }
833             if (!ArrayUtils.contains(mContext.getResources().getStringArray(
834                     com.android.internal.R.array.config_locationDriverAssistancePackageNames),
835                     identity.getPackageName())) {
836                 throw new SecurityException(
837                         "only verified adas packages may use adas gnss bypass requests");
838             }
839             if (!isLocationProvider) {
840                 mContext.enforceCallingOrSelfPermission(
841                         permission.WRITE_SECURE_SETTINGS,
842                         "adas gnss bypass requires " + permission.WRITE_SECURE_SETTINGS);
843             }
844         }
845         if (request.isLocationSettingsIgnored()) {
846             if (!isLocationProvider) {
847                 mContext.enforceCallingOrSelfPermission(
848                         permission.WRITE_SECURE_SETTINGS,
849                         "ignoring location settings requires " + permission.WRITE_SECURE_SETTINGS);
850             }
851         }
852 
853         return request;
854     }
855 
856     @Override
requestListenerFlush(String provider, ILocationListener listener, int requestCode)857     public void requestListenerFlush(String provider, ILocationListener listener, int requestCode) {
858         LocationProviderManager manager = getLocationProviderManager(provider);
859         Preconditions.checkArgument(manager != null,
860                 "provider \"" + provider + "\" does not exist");
861 
862         manager.flush(Objects.requireNonNull(listener), requestCode);
863     }
864 
865     @Override
requestPendingIntentFlush(String provider, PendingIntent pendingIntent, int requestCode)866     public void requestPendingIntentFlush(String provider, PendingIntent pendingIntent,
867             int requestCode) {
868         LocationProviderManager manager = getLocationProviderManager(provider);
869         Preconditions.checkArgument(manager != null,
870                 "provider \"" + provider + "\" does not exist");
871 
872         manager.flush(Objects.requireNonNull(pendingIntent), requestCode);
873     }
874 
875     @Override
unregisterLocationListener(ILocationListener listener)876     public void unregisterLocationListener(ILocationListener listener) {
877         for (LocationProviderManager manager : mProviderManagers) {
878             manager.unregisterLocationRequest(listener);
879         }
880     }
881 
882     @Override
unregisterLocationPendingIntent(PendingIntent pendingIntent)883     public void unregisterLocationPendingIntent(PendingIntent pendingIntent) {
884         for (LocationProviderManager manager : mProviderManagers) {
885             manager.unregisterLocationRequest(pendingIntent);
886         }
887     }
888 
889     @Override
getLastLocation(String provider, LastLocationRequest request, String packageName, @Nullable String attributionTag)890     public Location getLastLocation(String provider, LastLocationRequest request,
891             String packageName, @Nullable String attributionTag) {
892         CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag);
893         int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(),
894                 identity.getPid());
895         LocationPermissions.enforceLocationPermission(identity.getUid(), permissionLevel,
896                 PERMISSION_COARSE);
897 
898         // clients in the system process must have an attribution tag set
899         Preconditions.checkArgument(identity.getPid() != Process.myPid() || attributionTag != null);
900 
901         request = validateLastLocationRequest(provider, request, identity);
902 
903         LocationProviderManager manager = getLocationProviderManager(provider);
904         if (manager == null) {
905             return null;
906         }
907 
908         return manager.getLastLocation(request, identity, permissionLevel);
909     }
910 
validateLastLocationRequest(String provider, LastLocationRequest request, CallerIdentity identity)911     private LastLocationRequest validateLastLocationRequest(String provider,
912             LastLocationRequest request,
913             CallerIdentity identity) {
914         // sanitize request
915         LastLocationRequest.Builder sanitized = new LastLocationRequest.Builder(request);
916 
917         if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
918                 && GPS_PROVIDER.equals(provider)
919                 && ArrayUtils.contains(mContext.getResources().getStringArray(
920                 com.android.internal.R.array.config_locationDriverAssistancePackageNames),
921                 identity.getPackageName())) {
922             sanitized.setAdasGnssBypass(true);
923         }
924 
925         request = sanitized.build();
926 
927         // validate request
928         boolean isLocationProvider = mLocalService.isProvider(null, identity);
929 
930         if (request.isHiddenFromAppOps()) {
931             mContext.enforceCallingOrSelfPermission(
932                     permission.UPDATE_APP_OPS_STATS,
933                     "hiding from app ops requires " + permission.UPDATE_APP_OPS_STATS);
934         }
935 
936         if (request.isAdasGnssBypass()) {
937             if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
938                 throw new IllegalArgumentException(
939                         "adas gnss bypass requests are only allowed on automotive devices");
940             }
941             if (!GPS_PROVIDER.equals(provider)) {
942                 throw new IllegalArgumentException(
943                         "adas gnss bypass requests are only allowed on the \"gps\" provider");
944             }
945             if (!ArrayUtils.contains(mContext.getResources().getStringArray(
946                     com.android.internal.R.array.config_locationDriverAssistancePackageNames),
947                     identity.getPackageName())) {
948                 throw new SecurityException(
949                         "only verified adas packages may use adas gnss bypass requests");
950             }
951             if (!isLocationProvider) {
952                 mContext.enforceCallingOrSelfPermission(
953                         permission.WRITE_SECURE_SETTINGS,
954                         "adas gnss bypass requires " + permission.WRITE_SECURE_SETTINGS);
955             }
956         }
957         if (request.isLocationSettingsIgnored()) {
958             if (!isLocationProvider) {
959                 mContext.enforceCallingOrSelfPermission(
960                         permission.WRITE_SECURE_SETTINGS,
961                         "ignoring location settings requires " + permission.WRITE_SECURE_SETTINGS);
962             }
963         }
964 
965         return request;
966     }
967 
968     @Override
getGnssTimeMillis()969     public LocationTime getGnssTimeMillis() {
970         return mLocalService.getGnssTimeMillis();
971     }
972 
973     @Override
injectLocation(Location location)974     public void injectLocation(Location location) {
975         mContext.enforceCallingPermission(permission.LOCATION_HARDWARE, null);
976         mContext.enforceCallingPermission(ACCESS_FINE_LOCATION, null);
977 
978         Preconditions.checkArgument(location.isComplete());
979 
980         int userId = UserHandle.getCallingUserId();
981         LocationProviderManager manager = getLocationProviderManager(location.getProvider());
982         if (manager != null && manager.isEnabled(userId)) {
983             manager.injectLastLocation(Objects.requireNonNull(location), userId);
984         }
985     }
986 
987     @Override
requestGeofence(Geofence geofence, PendingIntent intent, String packageName, String attributionTag)988     public void requestGeofence(Geofence geofence, PendingIntent intent, String packageName,
989             String attributionTag) {
990         mGeofenceManager.addGeofence(geofence, intent, packageName, attributionTag);
991     }
992 
993     @Override
removeGeofence(PendingIntent pendingIntent)994     public void removeGeofence(PendingIntent pendingIntent) {
995         mGeofenceManager.removeGeofence(pendingIntent);
996     }
997 
998     @Override
registerGnssStatusCallback(IGnssStatusListener listener, String packageName, @Nullable String attributionTag, String listenerId)999     public void registerGnssStatusCallback(IGnssStatusListener listener, String packageName,
1000             @Nullable String attributionTag, String listenerId) {
1001         if (mGnssManagerService != null) {
1002             mGnssManagerService.registerGnssStatusCallback(listener, packageName, attributionTag,
1003                     listenerId);
1004         }
1005     }
1006 
1007     @Override
unregisterGnssStatusCallback(IGnssStatusListener listener)1008     public void unregisterGnssStatusCallback(IGnssStatusListener listener) {
1009         if (mGnssManagerService != null) {
1010             mGnssManagerService.unregisterGnssStatusCallback(listener);
1011         }
1012     }
1013 
1014     @Override
registerGnssNmeaCallback(IGnssNmeaListener listener, String packageName, @Nullable String attributionTag, String listenerId)1015     public void registerGnssNmeaCallback(IGnssNmeaListener listener, String packageName,
1016             @Nullable String attributionTag, String listenerId) {
1017         if (mGnssManagerService != null) {
1018             mGnssManagerService.registerGnssNmeaCallback(listener, packageName, attributionTag,
1019                     listenerId);
1020         }
1021     }
1022 
1023     @Override
unregisterGnssNmeaCallback(IGnssNmeaListener listener)1024     public void unregisterGnssNmeaCallback(IGnssNmeaListener listener) {
1025         if (mGnssManagerService != null) {
1026             mGnssManagerService.unregisterGnssNmeaCallback(listener);
1027         }
1028     }
1029 
1030     @Override
addGnssMeasurementsListener(GnssMeasurementRequest request, IGnssMeasurementsListener listener, String packageName, @Nullable String attributionTag, String listenerId)1031     public void addGnssMeasurementsListener(GnssMeasurementRequest request,
1032             IGnssMeasurementsListener listener, String packageName, @Nullable String attributionTag,
1033             String listenerId) {
1034         if (mGnssManagerService != null) {
1035             mGnssManagerService.addGnssMeasurementsListener(request, listener, packageName,
1036                     attributionTag, listenerId);
1037         }
1038     }
1039 
1040     @Override
removeGnssMeasurementsListener(IGnssMeasurementsListener listener)1041     public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
1042         if (mGnssManagerService != null) {
1043             mGnssManagerService.removeGnssMeasurementsListener(
1044                     listener);
1045         }
1046     }
1047 
1048     @Override
addGnssAntennaInfoListener(IGnssAntennaInfoListener listener, String packageName, @Nullable String attributionTag, String listenerId)1049     public void addGnssAntennaInfoListener(IGnssAntennaInfoListener listener, String packageName,
1050             @Nullable String attributionTag, String listenerId) {
1051         if (mGnssManagerService != null) {
1052             mGnssManagerService.addGnssAntennaInfoListener(listener, packageName, attributionTag,
1053                     listenerId);
1054         }
1055     }
1056 
1057     @Override
removeGnssAntennaInfoListener(IGnssAntennaInfoListener listener)1058     public void removeGnssAntennaInfoListener(IGnssAntennaInfoListener listener) {
1059         if (mGnssManagerService != null) {
1060             mGnssManagerService.removeGnssAntennaInfoListener(listener);
1061         }
1062     }
1063 
1064     @Override
addProviderRequestListener(IProviderRequestListener listener)1065     public void addProviderRequestListener(IProviderRequestListener listener) {
1066         for (LocationProviderManager manager : mProviderManagers) {
1067             manager.addProviderRequestListener(listener);
1068         }
1069     }
1070 
1071     @Override
removeProviderRequestListener(IProviderRequestListener listener)1072     public void removeProviderRequestListener(IProviderRequestListener listener) {
1073         for (LocationProviderManager manager : mProviderManagers) {
1074             manager.removeProviderRequestListener(listener);
1075         }
1076     }
1077 
1078     @Override
injectGnssMeasurementCorrections(GnssMeasurementCorrections corrections)1079     public void injectGnssMeasurementCorrections(GnssMeasurementCorrections corrections) {
1080         if (mGnssManagerService != null) {
1081             mGnssManagerService.injectGnssMeasurementCorrections(corrections);
1082         }
1083     }
1084 
1085     @Override
getGnssCapabilities()1086     public GnssCapabilities getGnssCapabilities() {
1087         return mGnssManagerService == null ? new GnssCapabilities.Builder().build()
1088                 : mGnssManagerService.getGnssCapabilities();
1089     }
1090 
1091     @Override
getGnssAntennaInfos()1092     public List<GnssAntennaInfo> getGnssAntennaInfos() {
1093         return mGnssManagerService == null ? null : mGnssManagerService.getGnssAntennaInfos();
1094     }
1095 
1096     @Override
addGnssNavigationMessageListener(IGnssNavigationMessageListener listener, String packageName, @Nullable String attributionTag, String listenerId)1097     public void addGnssNavigationMessageListener(IGnssNavigationMessageListener listener,
1098             String packageName, @Nullable String attributionTag, String listenerId) {
1099         if (mGnssManagerService != null) {
1100             mGnssManagerService.addGnssNavigationMessageListener(listener, packageName,
1101                     attributionTag, listenerId);
1102         }
1103     }
1104 
1105     @Override
removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener)1106     public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
1107         if (mGnssManagerService != null) {
1108             mGnssManagerService.removeGnssNavigationMessageListener(
1109                     listener);
1110         }
1111     }
1112 
1113     @Override
sendExtraCommand(String provider, String command, Bundle extras)1114     public void sendExtraCommand(String provider, String command, Bundle extras) {
1115         LocationPermissions.enforceCallingOrSelfLocationPermission(mContext, PERMISSION_COARSE);
1116         mContext.enforceCallingOrSelfPermission(
1117                 permission.ACCESS_LOCATION_EXTRA_COMMANDS, null);
1118 
1119         LocationProviderManager manager = getLocationProviderManager(
1120                 Objects.requireNonNull(provider));
1121         if (manager != null) {
1122             manager.sendExtraCommand(Binder.getCallingUid(), Binder.getCallingPid(),
1123                     Objects.requireNonNull(command), extras);
1124         }
1125 
1126         mInjector.getLocationUsageLogger().logLocationApiUsage(
1127                 LocationStatsEnums.USAGE_STARTED,
1128                 LocationStatsEnums.API_SEND_EXTRA_COMMAND,
1129                 provider);
1130         mInjector.getLocationUsageLogger().logLocationApiUsage(
1131                 LocationStatsEnums.USAGE_ENDED,
1132                 LocationStatsEnums.API_SEND_EXTRA_COMMAND,
1133                 provider);
1134     }
1135 
1136     @Override
getProviderProperties(String provider)1137     public ProviderProperties getProviderProperties(String provider) {
1138         LocationProviderManager manager = getLocationProviderManager(provider);
1139         Preconditions.checkArgument(manager != null,
1140                 "provider \"" + provider + "\" does not exist");
1141         return manager.getProperties();
1142     }
1143 
1144     @Override
isProviderPackage(@ullable String provider, String packageName, @Nullable String attributionTag)1145     public boolean isProviderPackage(@Nullable String provider, String packageName,
1146             @Nullable String attributionTag) {
1147         mContext.enforceCallingOrSelfPermission(permission.READ_DEVICE_CONFIG, null);
1148 
1149         for (LocationProviderManager manager : mProviderManagers) {
1150             if (provider != null && !provider.equals(manager.getName())) {
1151                 continue;
1152             }
1153             CallerIdentity identity = manager.getIdentity();
1154             if (identity == null) {
1155                 continue;
1156             }
1157             if (identity.getPackageName().equals(packageName) && (attributionTag == null
1158                     || Objects.equals(identity.getAttributionTag(), attributionTag))) {
1159                 return true;
1160             }
1161         }
1162 
1163         return false;
1164     }
1165 
1166     @Override
getProviderPackages(String provider)1167     public List<String> getProviderPackages(String provider) {
1168         mContext.enforceCallingOrSelfPermission(permission.READ_DEVICE_CONFIG, null);
1169 
1170         LocationProviderManager manager = getLocationProviderManager(provider);
1171         if (manager == null) {
1172             return Collections.emptyList();
1173         }
1174 
1175         CallerIdentity identity = manager.getIdentity();
1176         if (identity == null) {
1177             return Collections.emptyList();
1178         }
1179 
1180         return Collections.singletonList(identity.getPackageName());
1181     }
1182 
1183     @Override
setExtraLocationControllerPackage(String packageName)1184     public void setExtraLocationControllerPackage(String packageName) {
1185         mContext.enforceCallingPermission(permission.LOCATION_HARDWARE,
1186                 permission.LOCATION_HARDWARE + " permission required");
1187         synchronized (mLock) {
1188             mExtraLocationControllerPackage = packageName;
1189         }
1190     }
1191 
1192     @Override
getExtraLocationControllerPackage()1193     public String getExtraLocationControllerPackage() {
1194         synchronized (mLock) {
1195             return mExtraLocationControllerPackage;
1196         }
1197     }
1198 
1199     @Override
setExtraLocationControllerPackageEnabled(boolean enabled)1200     public void setExtraLocationControllerPackageEnabled(boolean enabled) {
1201         mContext.enforceCallingPermission(permission.LOCATION_HARDWARE,
1202                 permission.LOCATION_HARDWARE + " permission required");
1203         synchronized (mLock) {
1204             mExtraLocationControllerPackageEnabled = enabled;
1205         }
1206     }
1207 
1208     @Override
isExtraLocationControllerPackageEnabled()1209     public boolean isExtraLocationControllerPackageEnabled() {
1210         synchronized (mLock) {
1211             return mExtraLocationControllerPackageEnabled
1212                     && (mExtraLocationControllerPackage != null);
1213         }
1214     }
1215 
1216     @Override
setLocationEnabledForUser(boolean enabled, int userId)1217     public void setLocationEnabledForUser(boolean enabled, int userId) {
1218         userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
1219                 userId, false, false, "setLocationEnabledForUser", null);
1220 
1221         mContext.enforceCallingOrSelfPermission(permission.WRITE_SECURE_SETTINGS, null);
1222 
1223         LocationManager.invalidateLocalLocationEnabledCaches();
1224         mInjector.getSettingsHelper().setLocationEnabled(enabled, userId);
1225     }
1226 
1227     @Override
isLocationEnabledForUser(int userId)1228     public boolean isLocationEnabledForUser(int userId) {
1229         userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
1230                 userId, false, false, "isLocationEnabledForUser", null);
1231         return mInjector.getSettingsHelper().isLocationEnabled(userId);
1232     }
1233 
1234     @Override
setAdasGnssLocationEnabledForUser(boolean enabled, int userId)1235     public void setAdasGnssLocationEnabledForUser(boolean enabled, int userId) {
1236         userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
1237                 userId, false, false, "setAdasGnssLocationEnabledForUser", null);
1238 
1239         mContext.enforceCallingOrSelfPermission(permission.WRITE_SECURE_SETTINGS, null);
1240 
1241         mInjector.getLocationSettings().updateUserSettings(userId,
1242                 settings -> settings.withAdasGnssLocationEnabled(enabled));
1243     }
1244 
1245     @Override
isAdasGnssLocationEnabledForUser(int userId)1246     public boolean isAdasGnssLocationEnabledForUser(int userId) {
1247         userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
1248                 userId, false, false, "isAdasGnssLocationEnabledForUser", null);
1249         return mInjector.getLocationSettings().getUserSettings(userId).isAdasGnssLocationEnabled();
1250     }
1251 
1252     @Override
isProviderEnabledForUser(String provider, int userId)1253     public boolean isProviderEnabledForUser(String provider, int userId) {
1254         return mLocalService.isProviderEnabledForUser(provider, userId);
1255     }
1256 
1257     @Override
geocoderIsPresent()1258     public boolean geocoderIsPresent() {
1259         return mGeocodeProvider != null;
1260     }
1261 
1262     @Override
getFromLocation(double latitude, double longitude, int maxResults, GeocoderParams params, IGeocodeListener listener)1263     public void getFromLocation(double latitude, double longitude, int maxResults,
1264             GeocoderParams params, IGeocodeListener listener) {
1265         // validate identity
1266         CallerIdentity identity = CallerIdentity.fromBinder(mContext, params.getClientPackage(),
1267                 params.getClientAttributionTag());
1268         Preconditions.checkArgument(identity.getUid() == params.getClientUid());
1269 
1270         if (mGeocodeProvider != null) {
1271             mGeocodeProvider.getFromLocation(latitude, longitude, maxResults, params, listener);
1272         } else {
1273             try {
1274                 listener.onResults(null, Collections.emptyList());
1275             } catch (RemoteException e) {
1276                 // ignore
1277             }
1278         }
1279     }
1280 
1281     @Override
getFromLocationName(String locationName, double lowerLeftLatitude, double lowerLeftLongitude, double upperRightLatitude, double upperRightLongitude, int maxResults, GeocoderParams params, IGeocodeListener listener)1282     public void getFromLocationName(String locationName,
1283             double lowerLeftLatitude, double lowerLeftLongitude,
1284             double upperRightLatitude, double upperRightLongitude, int maxResults,
1285             GeocoderParams params, IGeocodeListener listener) {
1286         // validate identity
1287         CallerIdentity identity = CallerIdentity.fromBinder(mContext, params.getClientPackage(),
1288                 params.getClientAttributionTag());
1289         Preconditions.checkArgument(identity.getUid() == params.getClientUid());
1290 
1291         if (mGeocodeProvider != null) {
1292             mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
1293                     lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
1294                     maxResults, params, listener);
1295         } else {
1296             try {
1297                 listener.onResults(null, Collections.emptyList());
1298             } catch (RemoteException e) {
1299                 // ignore
1300             }
1301         }
1302     }
1303 
1304     @Override
addTestProvider(String provider, ProviderProperties properties, List<String> extraAttributionTags, String packageName, String attributionTag)1305     public void addTestProvider(String provider, ProviderProperties properties,
1306             List<String> extraAttributionTags, String packageName, String attributionTag) {
1307         // unsafe is ok because app ops will verify the package name
1308         CallerIdentity identity = CallerIdentity.fromBinderUnsafe(packageName, attributionTag);
1309         if (!mInjector.getAppOpsHelper().noteOp(AppOpsManager.OP_MOCK_LOCATION, identity)) {
1310             return;
1311         }
1312 
1313         final LocationProviderManager manager = getOrAddLocationProviderManager(provider);
1314         manager.setMockProvider(new MockLocationProvider(properties, identity,
1315                 new ArraySet<>(extraAttributionTags)));
1316     }
1317 
1318     @Override
removeTestProvider(String provider, String packageName, String attributionTag)1319     public void removeTestProvider(String provider, String packageName, String attributionTag) {
1320         // unsafe is ok because app ops will verify the package name
1321         CallerIdentity identity = CallerIdentity.fromBinderUnsafe(packageName, attributionTag);
1322         if (!mInjector.getAppOpsHelper().noteOp(AppOpsManager.OP_MOCK_LOCATION, identity)) {
1323             return;
1324         }
1325 
1326         synchronized (mLock) {
1327             LocationProviderManager manager = getLocationProviderManager(provider);
1328             if (manager == null) {
1329                 return;
1330             }
1331 
1332             manager.setMockProvider(null);
1333             if (!manager.hasProvider()) {
1334                 removeLocationProviderManager(manager);
1335             }
1336         }
1337     }
1338 
1339     @Override
setTestProviderLocation(String provider, Location location, String packageName, String attributionTag)1340     public void setTestProviderLocation(String provider, Location location, String packageName,
1341             String attributionTag) {
1342         // unsafe is ok because app ops will verify the package name
1343         CallerIdentity identity = CallerIdentity.fromBinderUnsafe(packageName,
1344                 attributionTag);
1345         if (!mInjector.getAppOpsHelper().noteOp(AppOpsManager.OP_MOCK_LOCATION, identity)) {
1346             return;
1347         }
1348 
1349         Preconditions.checkArgument(location.isComplete(),
1350                 "incomplete location object, missing timestamp or accuracy?");
1351 
1352         LocationProviderManager manager = getLocationProviderManager(provider);
1353         if (manager == null) {
1354             throw new IllegalArgumentException("provider doesn't exist: " + provider);
1355         }
1356 
1357         manager.setMockProviderLocation(location);
1358     }
1359 
1360     @Override
setTestProviderEnabled(String provider, boolean enabled, String packageName, String attributionTag)1361     public void setTestProviderEnabled(String provider, boolean enabled, String packageName,
1362             String attributionTag) {
1363         // unsafe is ok because app ops will verify the package name
1364         CallerIdentity identity = CallerIdentity.fromBinderUnsafe(packageName,
1365                 attributionTag);
1366         if (!mInjector.getAppOpsHelper().noteOp(AppOpsManager.OP_MOCK_LOCATION, identity)) {
1367             return;
1368         }
1369 
1370         LocationProviderManager manager = getLocationProviderManager(provider);
1371         if (manager == null) {
1372             throw new IllegalArgumentException("provider doesn't exist: " + provider);
1373         }
1374 
1375         manager.setMockProviderAllowed(enabled);
1376     }
1377 
1378     @Override
handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out, ParcelFileDescriptor err, String[] args)1379     public int handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out,
1380             ParcelFileDescriptor err, String[] args) {
1381         return new LocationShellCommand(mContext, this).exec(
1382                 this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(),
1383                 args);
1384     }
1385 
1386     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)1387     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1388         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) {
1389             return;
1390         }
1391 
1392         IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
1393 
1394         if (args.length > 0) {
1395             LocationProviderManager manager = getLocationProviderManager(args[0]);
1396             if (manager != null) {
1397                 ipw.println("Provider:");
1398                 ipw.increaseIndent();
1399                 manager.dump(fd, ipw, args);
1400                 ipw.decreaseIndent();
1401 
1402                 ipw.println("Event Log:");
1403                 ipw.increaseIndent();
1404                 EVENT_LOG.iterate(manager.getName(), ipw::println);
1405                 ipw.decreaseIndent();
1406                 return;
1407             }
1408 
1409             if ("--gnssmetrics".equals(args[0])) {
1410                 if (mGnssManagerService != null) {
1411                     mGnssManagerService.dump(fd, ipw, args);
1412                 }
1413                 return;
1414             }
1415         }
1416 
1417         ipw.println("Location Manager State:");
1418         ipw.increaseIndent();
1419 
1420         ipw.println("User Info:");
1421         ipw.increaseIndent();
1422         mInjector.getUserInfoHelper().dump(fd, ipw, args);
1423         ipw.decreaseIndent();
1424 
1425         ipw.println("Location Settings:");
1426         ipw.increaseIndent();
1427         mInjector.getSettingsHelper().dump(fd, ipw, args);
1428         ipw.decreaseIndent();
1429 
1430         synchronized (mLock) {
1431             if (mExtraLocationControllerPackage != null) {
1432                 ipw.println(
1433                         "Location Controller Extra Package: " + mExtraLocationControllerPackage
1434                                 + (mExtraLocationControllerPackageEnabled ? " [enabled]"
1435                                 : " [disabled]"));
1436             }
1437         }
1438 
1439         ipw.println("Location Providers:");
1440         ipw.increaseIndent();
1441         for (LocationProviderManager manager : mProviderManagers) {
1442             manager.dump(fd, ipw, args);
1443         }
1444         ipw.decreaseIndent();
1445 
1446         ipw.println("Historical Aggregate Location Provider Data:");
1447         ipw.increaseIndent();
1448         ArrayMap<String, ArrayMap<CallerIdentity, LocationEventLog.AggregateStats>> aggregateStats =
1449                 EVENT_LOG.copyAggregateStats();
1450         for (int i = 0; i < aggregateStats.size(); i++) {
1451             ipw.print(aggregateStats.keyAt(i));
1452             ipw.println(":");
1453             ipw.increaseIndent();
1454             ArrayMap<CallerIdentity, LocationEventLog.AggregateStats> providerStats =
1455                     aggregateStats.valueAt(i);
1456             for (int j = 0; j < providerStats.size(); j++) {
1457                 ipw.print(providerStats.keyAt(j));
1458                 ipw.print(": ");
1459                 providerStats.valueAt(j).updateTotals();
1460                 ipw.println(providerStats.valueAt(j));
1461             }
1462             ipw.decreaseIndent();
1463         }
1464         ipw.decreaseIndent();
1465 
1466         if (mGnssManagerService != null) {
1467             ipw.println("GNSS Manager:");
1468             ipw.increaseIndent();
1469             mGnssManagerService.dump(fd, ipw, args);
1470             ipw.decreaseIndent();
1471         }
1472 
1473         ipw.println("Geofence Manager:");
1474         ipw.increaseIndent();
1475         mGeofenceManager.dump(fd, ipw, args);
1476         ipw.decreaseIndent();
1477 
1478         ipw.println("Event Log:");
1479         ipw.increaseIndent();
1480         EVENT_LOG.iterate(ipw::println);
1481         ipw.decreaseIndent();
1482     }
1483 
1484     @Override
onStateChanged(String provider, AbstractLocationProvider.State oldState, AbstractLocationProvider.State newState)1485     public void onStateChanged(String provider, AbstractLocationProvider.State oldState,
1486             AbstractLocationProvider.State newState) {
1487         if (!Objects.equals(oldState.identity, newState.identity)) {
1488             refreshAppOpsRestrictions(UserHandle.USER_ALL);
1489         }
1490 
1491         if (!oldState.extraAttributionTags.equals(newState.extraAttributionTags)
1492                 || !Objects.equals(oldState.identity, newState.identity)) {
1493             // since we're potentially affecting the tag lists for two different uids, acquire the
1494             // lock to ensure providers cannot change while we're looping over the providers
1495             // multiple times, which could lead to inconsistent results.
1496             synchronized (mLock) {
1497                 LocationPackageTagsListener listener = mLocationTagsChangedListener;
1498                 if (listener != null) {
1499                     int oldUid = oldState.identity != null ? oldState.identity.getUid() : -1;
1500                     int newUid = newState.identity != null ? newState.identity.getUid() : -1;
1501                     if (oldUid != -1) {
1502                         PackageTagsList tags = calculateAppOpsLocationSourceTags(oldUid);
1503                         FgThread.getHandler().post(
1504                                 () -> listener.onLocationPackageTagsChanged(oldUid, tags));
1505                     }
1506                     // if the new app id is the same as the old app id, no need to invoke the
1507                     // listener twice, it's already been taken care of
1508                     if (newUid != -1 && newUid != oldUid) {
1509                         PackageTagsList tags = calculateAppOpsLocationSourceTags(newUid);
1510                         FgThread.getHandler().post(
1511                                 () -> listener.onLocationPackageTagsChanged(newUid, tags));
1512                     }
1513                 }
1514             }
1515         }
1516     }
1517 
refreshAppOpsRestrictions(int userId)1518     private void refreshAppOpsRestrictions(int userId) {
1519         if (userId == UserHandle.USER_ALL) {
1520             final int[] runningUserIds = mInjector.getUserInfoHelper().getRunningUserIds();
1521             for (int i = 0; i < runningUserIds.length; i++) {
1522                 refreshAppOpsRestrictions(runningUserIds[i]);
1523             }
1524             return;
1525         }
1526 
1527         Preconditions.checkArgument(userId >= 0);
1528 
1529         boolean enabled = mInjector.getSettingsHelper().isLocationEnabled(userId);
1530 
1531         PackageTagsList allowedPackages = null;
1532         if (!enabled) {
1533             PackageTagsList.Builder builder = new PackageTagsList.Builder();
1534             for (LocationProviderManager manager : mProviderManagers) {
1535                 CallerIdentity identity = manager.getIdentity();
1536                 if (identity != null) {
1537                     builder.add(identity.getPackageName(), identity.getAttributionTag());
1538                 }
1539             }
1540             builder.add(mInjector.getSettingsHelper().getIgnoreSettingsAllowlist());
1541             allowedPackages = builder.build();
1542         }
1543 
1544         AppOpsManager appOpsManager = Objects.requireNonNull(
1545                 mContext.getSystemService(AppOpsManager.class));
1546         appOpsManager.setUserRestrictionForUser(
1547                 AppOpsManager.OP_COARSE_LOCATION,
1548                 !enabled,
1549                 LocationManagerService.this,
1550                 allowedPackages,
1551                 userId);
1552         appOpsManager.setUserRestrictionForUser(
1553                 AppOpsManager.OP_FINE_LOCATION,
1554                 !enabled,
1555                 LocationManagerService.this,
1556                 allowedPackages,
1557                 userId);
1558     }
1559 
calculateAppOpsLocationSourceTags(int uid)1560     PackageTagsList calculateAppOpsLocationSourceTags(int uid) {
1561         PackageTagsList.Builder builder = new PackageTagsList.Builder();
1562         for (LocationProviderManager manager : mProviderManagers) {
1563             AbstractLocationProvider.State managerState = manager.getState();
1564             if (managerState.identity == null) {
1565                 continue;
1566             }
1567             if (managerState.identity.getUid() != uid) {
1568                 continue;
1569             }
1570 
1571             builder.add(managerState.identity.getPackageName(), managerState.extraAttributionTags);
1572             if (managerState.extraAttributionTags.isEmpty()
1573                     || managerState.identity.getAttributionTag() != null) {
1574                 builder.add(managerState.identity.getPackageName(),
1575                         managerState.identity.getAttributionTag());
1576             } else {
1577                 Log.e(TAG, manager.getName() + " provider has specified a null attribution tag and "
1578                         + "a non-empty set of extra attribution tags - dropping the null "
1579                         + "attribution tag");
1580             }
1581         }
1582         return builder.build();
1583     }
1584 
1585     private class LocalService extends LocationManagerInternal {
1586 
LocalService()1587         LocalService() {}
1588 
1589         @Override
isProviderEnabledForUser(@onNull String provider, int userId)1590         public boolean isProviderEnabledForUser(@NonNull String provider, int userId) {
1591             userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1592                     Binder.getCallingUid(), userId, false, false, "isProviderEnabledForUser", null);
1593 
1594             LocationProviderManager manager = getLocationProviderManager(provider);
1595             if (manager == null) {
1596                 return false;
1597             }
1598 
1599             return manager.isEnabled(userId);
1600         }
1601 
1602         @Override
addProviderEnabledListener(String provider, ProviderEnabledListener listener)1603         public void addProviderEnabledListener(String provider, ProviderEnabledListener listener) {
1604             LocationProviderManager manager = Objects.requireNonNull(
1605                     getLocationProviderManager(provider));
1606             manager.addEnabledListener(listener);
1607         }
1608 
1609         @Override
removeProviderEnabledListener(String provider, ProviderEnabledListener listener)1610         public void removeProviderEnabledListener(String provider,
1611                 ProviderEnabledListener listener) {
1612             LocationProviderManager manager = Objects.requireNonNull(
1613                     getLocationProviderManager(provider));
1614             manager.removeEnabledListener(listener);
1615         }
1616 
1617         @Override
isProvider(@ullable String provider, CallerIdentity identity)1618         public boolean isProvider(@Nullable String provider, CallerIdentity identity) {
1619             for (LocationProviderManager manager : mProviderManagers) {
1620                 if (provider != null && !provider.equals(manager.getName())) {
1621                     continue;
1622                 }
1623                 if (identity.equals(manager.getIdentity())) {
1624                     return true;
1625                 }
1626             }
1627 
1628             return false;
1629         }
1630 
1631         @Override
sendNiResponse(int notifId, int userResponse)1632         public void sendNiResponse(int notifId, int userResponse) {
1633             if (mGnssManagerService != null) {
1634                 mGnssManagerService.sendNiResponse(notifId, userResponse);
1635             }
1636         }
1637 
1638         @Override
getGnssTimeMillis()1639         public @Nullable LocationTime getGnssTimeMillis() {
1640             LocationProviderManager gpsManager = getLocationProviderManager(GPS_PROVIDER);
1641             if (gpsManager == null) {
1642                 return null;
1643             }
1644 
1645             Location location = gpsManager.getLastLocationUnsafe(UserHandle.USER_ALL,
1646                     PERMISSION_FINE, false, Long.MAX_VALUE);
1647             if (location == null) {
1648                 return null;
1649             }
1650 
1651             return new LocationTime(location.getTime(), location.getElapsedRealtimeNanos());
1652         }
1653 
1654         @Override
setLocationPackageTagsListener( @ullable LocationPackageTagsListener listener)1655         public void setLocationPackageTagsListener(
1656                 @Nullable LocationPackageTagsListener listener) {
1657             synchronized (mLock) {
1658                 mLocationTagsChangedListener = listener;
1659 
1660                 // calculate initial tag list and send to listener
1661                 if (listener != null) {
1662                     ArraySet<Integer> uids = new ArraySet<>(mProviderManagers.size());
1663                     for (LocationProviderManager manager : mProviderManagers) {
1664                         CallerIdentity identity = manager.getIdentity();
1665                         if (identity != null) {
1666                             uids.add(identity.getUid());
1667                         }
1668                     }
1669 
1670                     for (int uid : uids) {
1671                         PackageTagsList tags = calculateAppOpsLocationSourceTags(uid);
1672                         if (!tags.isEmpty()) {
1673                             FgThread.getHandler().post(
1674                                     () -> listener.onLocationPackageTagsChanged(uid, tags));
1675                         }
1676                     }
1677                 }
1678             }
1679         }
1680     }
1681 
1682     private static final class SystemInjector implements Injector {
1683 
1684         private final Context mContext;
1685 
1686         private final UserInfoHelper mUserInfoHelper;
1687         private final LocationSettings mLocationSettings;
1688         private final AlarmHelper mAlarmHelper;
1689         private final SystemAppOpsHelper mAppOpsHelper;
1690         private final SystemLocationPermissionsHelper mLocationPermissionsHelper;
1691         private final SystemSettingsHelper mSettingsHelper;
1692         private final SystemAppForegroundHelper mAppForegroundHelper;
1693         private final SystemLocationPowerSaveModeHelper mLocationPowerSaveModeHelper;
1694         private final SystemScreenInteractiveHelper mScreenInteractiveHelper;
1695         private final SystemDeviceStationaryHelper mDeviceStationaryHelper;
1696         private final SystemDeviceIdleHelper mDeviceIdleHelper;
1697         private final LocationAttributionHelper mLocationAttributionHelper;
1698         private final LocationUsageLogger mLocationUsageLogger;
1699 
1700         // lazily instantiated since they may not always be used
1701 
1702         @GuardedBy("this")
1703         private @Nullable SystemEmergencyHelper mEmergencyCallHelper;
1704 
1705         @GuardedBy("this")
1706         private boolean mSystemReady;
1707 
SystemInjector(Context context, UserInfoHelper userInfoHelper)1708         SystemInjector(Context context, UserInfoHelper userInfoHelper) {
1709             mContext = context;
1710 
1711             mUserInfoHelper = userInfoHelper;
1712             mLocationSettings = new LocationSettings(context);
1713             mAlarmHelper = new SystemAlarmHelper(context);
1714             mAppOpsHelper = new SystemAppOpsHelper(context);
1715             mLocationPermissionsHelper = new SystemLocationPermissionsHelper(context,
1716                     mAppOpsHelper);
1717             mSettingsHelper = new SystemSettingsHelper(context);
1718             mAppForegroundHelper = new SystemAppForegroundHelper(context);
1719             mLocationPowerSaveModeHelper = new SystemLocationPowerSaveModeHelper(context);
1720             mScreenInteractiveHelper = new SystemScreenInteractiveHelper(context);
1721             mDeviceStationaryHelper = new SystemDeviceStationaryHelper();
1722             mDeviceIdleHelper = new SystemDeviceIdleHelper(context);
1723             mLocationAttributionHelper = new LocationAttributionHelper(mAppOpsHelper);
1724             mLocationUsageLogger = new LocationUsageLogger();
1725         }
1726 
onSystemReady()1727         synchronized void onSystemReady() {
1728             mAppOpsHelper.onSystemReady();
1729             mLocationPermissionsHelper.onSystemReady();
1730             mSettingsHelper.onSystemReady();
1731             mAppForegroundHelper.onSystemReady();
1732             mLocationPowerSaveModeHelper.onSystemReady();
1733             mScreenInteractiveHelper.onSystemReady();
1734             mDeviceStationaryHelper.onSystemReady();
1735             mDeviceIdleHelper.onSystemReady();
1736 
1737             if (mEmergencyCallHelper != null) {
1738                 mEmergencyCallHelper.onSystemReady();
1739             }
1740 
1741             mSystemReady = true;
1742         }
1743 
1744         @Override
getUserInfoHelper()1745         public UserInfoHelper getUserInfoHelper() {
1746             return mUserInfoHelper;
1747         }
1748 
1749         @Override
getLocationSettings()1750         public LocationSettings getLocationSettings() {
1751             return mLocationSettings;
1752         }
1753 
1754         @Override
getAlarmHelper()1755         public AlarmHelper getAlarmHelper() {
1756             return mAlarmHelper;
1757         }
1758 
1759         @Override
getAppOpsHelper()1760         public AppOpsHelper getAppOpsHelper() {
1761             return mAppOpsHelper;
1762         }
1763 
1764         @Override
getLocationPermissionsHelper()1765         public LocationPermissionsHelper getLocationPermissionsHelper() {
1766             return mLocationPermissionsHelper;
1767         }
1768 
1769         @Override
getSettingsHelper()1770         public SettingsHelper getSettingsHelper() {
1771             return mSettingsHelper;
1772         }
1773 
1774         @Override
getAppForegroundHelper()1775         public AppForegroundHelper getAppForegroundHelper() {
1776             return mAppForegroundHelper;
1777         }
1778 
1779         @Override
getLocationPowerSaveModeHelper()1780         public LocationPowerSaveModeHelper getLocationPowerSaveModeHelper() {
1781             return mLocationPowerSaveModeHelper;
1782         }
1783 
1784         @Override
getScreenInteractiveHelper()1785         public ScreenInteractiveHelper getScreenInteractiveHelper() {
1786             return mScreenInteractiveHelper;
1787         }
1788 
1789         @Override
getDeviceStationaryHelper()1790         public DeviceStationaryHelper getDeviceStationaryHelper() {
1791             return mDeviceStationaryHelper;
1792         }
1793 
1794         @Override
getDeviceIdleHelper()1795         public DeviceIdleHelper getDeviceIdleHelper() {
1796             return mDeviceIdleHelper;
1797         }
1798 
1799         @Override
getLocationAttributionHelper()1800         public LocationAttributionHelper getLocationAttributionHelper() {
1801             return mLocationAttributionHelper;
1802         }
1803 
1804         @Override
getEmergencyHelper()1805         public synchronized EmergencyHelper getEmergencyHelper() {
1806             if (mEmergencyCallHelper == null) {
1807                 mEmergencyCallHelper = new SystemEmergencyHelper(mContext);
1808                 if (mSystemReady) {
1809                     mEmergencyCallHelper.onSystemReady();
1810                 }
1811             }
1812 
1813             return mEmergencyCallHelper;
1814         }
1815 
1816         @Override
getLocationUsageLogger()1817         public LocationUsageLogger getLocationUsageLogger() {
1818             return mLocationUsageLogger;
1819         }
1820     }
1821 }
1822