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