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.provider;
18 
19 import static android.app.AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION;
20 import static android.app.AppOpsManager.OP_MONITOR_LOCATION;
21 import static android.app.compat.CompatChanges.isChangeEnabled;
22 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
23 import static android.location.LocationManager.DELIVER_HISTORICAL_LOCATIONS;
24 import static android.location.LocationManager.GPS_PROVIDER;
25 import static android.location.LocationManager.KEY_FLUSH_COMPLETE;
26 import static android.location.LocationManager.KEY_LOCATIONS;
27 import static android.location.LocationManager.KEY_LOCATION_CHANGED;
28 import static android.location.LocationManager.KEY_PROVIDER_ENABLED;
29 import static android.location.LocationManager.PASSIVE_PROVIDER;
30 import static android.os.IPowerManager.LOCATION_MODE_NO_CHANGE;
31 import static android.os.PowerExemptionManager.REASON_LOCATION_PROVIDER;
32 import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
33 import static android.os.PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF;
34 import static android.os.PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
35 import static android.os.PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF;
36 import static android.os.PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF;
37 import static android.os.UserHandle.USER_CURRENT;
38 
39 import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
40 import static com.android.server.location.LocationManagerService.D;
41 import static com.android.server.location.LocationManagerService.TAG;
42 import static com.android.server.location.LocationPermissions.PERMISSION_COARSE;
43 import static com.android.server.location.LocationPermissions.PERMISSION_FINE;
44 import static com.android.server.location.LocationPermissions.PERMISSION_NONE;
45 import static com.android.server.location.eventlog.LocationEventLog.EVENT_LOG;
46 
47 import static java.lang.Math.max;
48 import static java.lang.Math.min;
49 
50 import android.annotation.IntDef;
51 import android.annotation.Nullable;
52 import android.annotation.SuppressLint;
53 import android.app.AlarmManager.OnAlarmListener;
54 import android.app.BroadcastOptions;
55 import android.app.PendingIntent;
56 import android.content.Context;
57 import android.content.Intent;
58 import android.location.ILocationCallback;
59 import android.location.ILocationListener;
60 import android.location.LastLocationRequest;
61 import android.location.Location;
62 import android.location.LocationManager;
63 import android.location.LocationManagerInternal;
64 import android.location.LocationManagerInternal.ProviderEnabledListener;
65 import android.location.LocationRequest;
66 import android.location.LocationResult;
67 import android.location.provider.IProviderRequestListener;
68 import android.location.provider.ProviderProperties;
69 import android.location.provider.ProviderRequest;
70 import android.location.util.identity.CallerIdentity;
71 import android.os.Binder;
72 import android.os.Bundle;
73 import android.os.CancellationSignal;
74 import android.os.IBinder;
75 import android.os.ICancellationSignal;
76 import android.os.IRemoteCallback;
77 import android.os.PowerManager;
78 import android.os.PowerManager.LocationPowerSaveMode;
79 import android.os.Process;
80 import android.os.RemoteException;
81 import android.os.SystemClock;
82 import android.os.UserHandle;
83 import android.os.WorkSource;
84 import android.stats.location.LocationStatsEnums;
85 import android.text.TextUtils;
86 import android.util.ArraySet;
87 import android.util.EventLog;
88 import android.util.IndentingPrintWriter;
89 import android.util.Log;
90 import android.util.SparseArray;
91 import android.util.SparseBooleanArray;
92 import android.util.TimeUtils;
93 
94 import com.android.internal.annotations.GuardedBy;
95 import com.android.internal.util.Preconditions;
96 import com.android.server.FgThread;
97 import com.android.server.LocalServices;
98 import com.android.server.location.LocationPermissions;
99 import com.android.server.location.LocationPermissions.PermissionLevel;
100 import com.android.server.location.fudger.LocationFudger;
101 import com.android.server.location.injector.AlarmHelper;
102 import com.android.server.location.injector.AppForegroundHelper;
103 import com.android.server.location.injector.AppForegroundHelper.AppForegroundListener;
104 import com.android.server.location.injector.AppOpsHelper;
105 import com.android.server.location.injector.Injector;
106 import com.android.server.location.injector.LocationPermissionsHelper;
107 import com.android.server.location.injector.LocationPermissionsHelper.LocationPermissionsListener;
108 import com.android.server.location.injector.LocationPowerSaveModeHelper;
109 import com.android.server.location.injector.LocationPowerSaveModeHelper.LocationPowerSaveModeChangedListener;
110 import com.android.server.location.injector.LocationUsageLogger;
111 import com.android.server.location.injector.PackageResetHelper;
112 import com.android.server.location.injector.ScreenInteractiveHelper;
113 import com.android.server.location.injector.ScreenInteractiveHelper.ScreenInteractiveChangedListener;
114 import com.android.server.location.injector.SettingsHelper;
115 import com.android.server.location.injector.SettingsHelper.GlobalSettingChangedListener;
116 import com.android.server.location.injector.SettingsHelper.UserSettingChangedListener;
117 import com.android.server.location.injector.UserInfoHelper;
118 import com.android.server.location.injector.UserInfoHelper.UserListener;
119 import com.android.server.location.listeners.ListenerMultiplexer;
120 import com.android.server.location.listeners.RemovableListenerRegistration;
121 import com.android.server.location.settings.LocationSettings;
122 import com.android.server.location.settings.LocationUserSettings;
123 
124 import java.io.FileDescriptor;
125 import java.lang.annotation.Retention;
126 import java.lang.annotation.RetentionPolicy;
127 import java.util.ArrayList;
128 import java.util.Collection;
129 import java.util.Collections;
130 import java.util.NoSuchElementException;
131 import java.util.Objects;
132 import java.util.concurrent.CopyOnWriteArrayList;
133 import java.util.concurrent.Executor;
134 import java.util.function.Predicate;
135 
136 /**
137  * Manages all aspects of a single location provider.
138  */
139 public class LocationProviderManager extends
140         ListenerMultiplexer<Object, LocationProviderManager.LocationTransport,
141                 LocationProviderManager.Registration, ProviderRequest> implements
142         AbstractLocationProvider.Listener {
143 
144     private static final String WAKELOCK_TAG = "*location*";
145     private static final long WAKELOCK_TIMEOUT_MS = 30 * 1000;
146 
147     // duration PI location clients are put on the allowlist to start a fg service
148     private static final long TEMPORARY_APP_ALLOWLIST_DURATION_MS = 10 * 1000;
149 
150     // fastest interval at which clients may receive coarse locations
151     private static final long MIN_COARSE_INTERVAL_MS = 10 * 60 * 1000;
152 
153     // max interval to be considered "high power" request
154     private static final long MAX_HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
155 
156     // max age of a location before it is no longer considered "current"
157     private static final long MAX_CURRENT_LOCATION_AGE_MS = 30 * 1000;
158 
159     // max timeout allowed for getting the current location
160     private static final long MAX_GET_CURRENT_LOCATION_TIMEOUT_MS = 30 * 1000;
161 
162     // max jitter allowed for min update interval as a percentage of the interval
163     private static final float FASTEST_INTERVAL_JITTER_PERCENTAGE = .10f;
164 
165     // max absolute jitter allowed for min update interval evaluation
166     private static final int MAX_FASTEST_INTERVAL_JITTER_MS = 30 * 1000;
167 
168     // minimum amount of request delay in order to respect the delay, below this value the request
169     // will just be scheduled immediately
170     private static final long MIN_REQUEST_DELAY_MS = 30 * 1000;
171 
172     @Retention(RetentionPolicy.SOURCE)
173     @IntDef({STATE_STARTED, STATE_STOPPING, STATE_STOPPED})
174     private @interface State {}
175 
176     private static final int STATE_STARTED = 0;
177     private static final int STATE_STOPPING = 1;
178     private static final int STATE_STOPPED = 2;
179 
180     public interface StateChangedListener {
onStateChanged(String provider, AbstractLocationProvider.State oldState, AbstractLocationProvider.State newState)181         void onStateChanged(String provider, AbstractLocationProvider.State oldState,
182                 AbstractLocationProvider.State newState);
183     }
184 
185     protected interface LocationTransport {
186 
deliverOnLocationChanged(LocationResult locationResult, @Nullable IRemoteCallback onCompleteCallback)187         void deliverOnLocationChanged(LocationResult locationResult,
188                 @Nullable IRemoteCallback onCompleteCallback) throws Exception;
deliverOnFlushComplete(int requestCode)189         void deliverOnFlushComplete(int requestCode) throws Exception;
190     }
191 
192     protected interface ProviderTransport {
193 
deliverOnProviderEnabledChanged(String provider, boolean enabled)194         void deliverOnProviderEnabledChanged(String provider, boolean enabled) throws Exception;
195     }
196 
197     protected static final class LocationListenerTransport implements LocationTransport,
198             ProviderTransport {
199 
200         private final ILocationListener mListener;
201 
LocationListenerTransport(ILocationListener listener)202         LocationListenerTransport(ILocationListener listener) {
203             mListener = Objects.requireNonNull(listener);
204         }
205 
206         @Override
deliverOnLocationChanged(LocationResult locationResult, @Nullable IRemoteCallback onCompleteCallback)207         public void deliverOnLocationChanged(LocationResult locationResult,
208                 @Nullable IRemoteCallback onCompleteCallback) throws RemoteException {
209             try {
210                 mListener.onLocationChanged(locationResult.asList(), onCompleteCallback);
211             } catch (RuntimeException e) {
212                 // the only way a runtime exception can be thrown here is if the client is in the
213                 // system server process (so that the binder call is executed directly, rather than
214                 // asynchronously in another process), and the client is using a direct executor (so
215                 // any client exceptions bubble directly back to us). we move any exception onto
216                 // another thread so that it can't cause further problems
217                 RuntimeException wrapper = new RuntimeException(e);
218                 FgThread.getExecutor().execute(() -> {
219                     throw wrapper;
220                 });
221             }
222         }
223 
224         @Override
deliverOnFlushComplete(int requestCode)225         public void deliverOnFlushComplete(int requestCode) throws RemoteException {
226             try {
227                 mListener.onFlushComplete(requestCode);
228             } catch (RuntimeException e) {
229                 // the only way a runtime exception can be thrown here is if the client is in the
230                 // system server process (so that the binder call is executed directly, rather than
231                 // asynchronously in another process), and the client is using a direct executor (so
232                 // any client exceptions bubble directly back to us). we move any exception onto
233                 // another thread so that it can't cause further problems
234                 RuntimeException wrapper = new RuntimeException(e);
235                 FgThread.getExecutor().execute(() -> {
236                     throw wrapper;
237                 });
238             }
239         }
240 
241         @Override
deliverOnProviderEnabledChanged(String provider, boolean enabled)242         public void deliverOnProviderEnabledChanged(String provider, boolean enabled)
243                 throws RemoteException {
244             try {
245                 mListener.onProviderEnabledChanged(provider, enabled);
246             } catch (RuntimeException e) {
247                 // the only way a runtime exception can be thrown here is if the client is in the
248                 // system server process (so that the binder call is executed directly, rather than
249                 // asynchronously in another process), and the client is using a direct executor (so
250                 // any client exceptions bubble directly back to us). we move any exception onto
251                 // another thread so that it can't cause further problems
252                 RuntimeException wrapper = new RuntimeException(e);
253                 FgThread.getExecutor().execute(() -> {
254                     throw wrapper;
255                 });
256             }
257         }
258     }
259 
260     protected static final class LocationPendingIntentTransport implements LocationTransport,
261             ProviderTransport {
262 
263         private final Context mContext;
264         private final PendingIntent mPendingIntent;
265 
LocationPendingIntentTransport(Context context, PendingIntent pendingIntent)266         public LocationPendingIntentTransport(Context context, PendingIntent pendingIntent) {
267             mContext = context;
268             mPendingIntent = pendingIntent;
269         }
270 
271         @Override
deliverOnLocationChanged(LocationResult locationResult, @Nullable IRemoteCallback onCompleteCallback)272         public void deliverOnLocationChanged(LocationResult locationResult,
273                 @Nullable IRemoteCallback onCompleteCallback)
274                 throws PendingIntent.CanceledException {
275             BroadcastOptions options = BroadcastOptions.makeBasic();
276             options.setDontSendToRestrictedApps(true);
277             // allows apps to start a fg service in response to a location PI
278             options.setTemporaryAppAllowlist(TEMPORARY_APP_ALLOWLIST_DURATION_MS,
279                     TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
280                     REASON_LOCATION_PROVIDER,
281                     "");
282 
283             Intent intent = new Intent().putExtra(KEY_LOCATION_CHANGED,
284                     locationResult.getLastLocation());
285             if (locationResult.size() > 1) {
286                 intent.putExtra(KEY_LOCATIONS, locationResult.asList().toArray(new Location[0]));
287             }
288 
289             Runnable callback = null;
290             if (onCompleteCallback != null) {
291                 callback = () -> {
292                     try {
293                         onCompleteCallback.sendResult(null);
294                     } catch (RemoteException e) {
295                         throw e.rethrowFromSystemServer();
296                     }
297                 };
298             }
299 
300             PendingIntentSender.send(mPendingIntent, mContext, intent, callback,
301                     options.toBundle());
302         }
303 
304         @Override
deliverOnFlushComplete(int requestCode)305         public void deliverOnFlushComplete(int requestCode) throws PendingIntent.CanceledException {
306             BroadcastOptions options = BroadcastOptions.makeBasic();
307             options.setDontSendToRestrictedApps(true);
308             options.setPendingIntentBackgroundActivityLaunchAllowed(false);
309 
310             mPendingIntent.send(mContext, 0, new Intent().putExtra(KEY_FLUSH_COMPLETE, requestCode),
311                     null, null, null, options.toBundle());
312         }
313 
314         @Override
deliverOnProviderEnabledChanged(String provider, boolean enabled)315         public void deliverOnProviderEnabledChanged(String provider, boolean enabled)
316                 throws PendingIntent.CanceledException {
317             BroadcastOptions options = BroadcastOptions.makeBasic();
318             options.setDontSendToRestrictedApps(true);
319 
320             mPendingIntent.send(mContext, 0, new Intent().putExtra(KEY_PROVIDER_ENABLED, enabled),
321                     null, null, null, options.toBundle());
322         }
323     }
324 
325     protected static final class GetCurrentLocationTransport implements LocationTransport {
326 
327         private final ILocationCallback mCallback;
328 
GetCurrentLocationTransport(ILocationCallback callback)329         GetCurrentLocationTransport(ILocationCallback callback) {
330             mCallback = Objects.requireNonNull(callback);
331         }
332 
333         @Override
deliverOnLocationChanged(@ullable LocationResult locationResult, @Nullable IRemoteCallback onCompleteCallback)334         public void deliverOnLocationChanged(@Nullable LocationResult locationResult,
335                 @Nullable IRemoteCallback onCompleteCallback)
336                 throws RemoteException {
337             // ILocationCallback doesn't currently support completion callbacks
338             Preconditions.checkState(onCompleteCallback == null);
339 
340             try {
341                 if (locationResult != null) {
342                     mCallback.onLocation(locationResult.getLastLocation());
343                 } else {
344                     mCallback.onLocation(null);
345                 }
346             } catch (RuntimeException e) {
347                 // the only way a runtime exception can be thrown here is if the client is in the
348                 // system server process (so that the binder call is executed directly, rather than
349                 // asynchronously in another process), and the client is using a direct executor (so
350                 // any client exceptions bubble directly back to us). we move any exception onto
351                 // another thread so that it can't cause further problems
352                 RuntimeException wrapper = new RuntimeException(e);
353                 FgThread.getExecutor().execute(() -> {
354                     throw wrapper;
355                 });
356             }
357         }
358 
359         @Override
deliverOnFlushComplete(int requestCode)360         public void deliverOnFlushComplete(int requestCode) {}
361     }
362 
363     protected abstract class Registration extends RemovableListenerRegistration<Object,
364                 LocationTransport> {
365 
366         private final LocationRequest mBaseRequest;
367         private final CallerIdentity mIdentity;
368         private final @PermissionLevel int mPermissionLevel;
369 
370         // we cache these values because checking/calculating on the fly is more expensive
371         @GuardedBy("mMultiplexerLock")
372         private boolean mPermitted;
373         @GuardedBy("mMultiplexerLock")
374         private boolean mForeground;
375         @GuardedBy("mMultiplexerLock")
376         private LocationRequest mProviderLocationRequest;
377         @GuardedBy("mMultiplexerLock")
378         private boolean mIsUsingHighPower;
379 
380         @Nullable private Location mLastLocation = null;
381 
Registration(LocationRequest request, CallerIdentity identity, Executor executor, LocationTransport transport, @PermissionLevel int permissionLevel)382         protected Registration(LocationRequest request, CallerIdentity identity, Executor executor,
383                 LocationTransport transport, @PermissionLevel int permissionLevel) {
384             super(executor, transport);
385 
386             Preconditions.checkArgument(identity.getListenerId() != null);
387             Preconditions.checkArgument(permissionLevel > PERMISSION_NONE);
388             Preconditions.checkArgument(!request.getWorkSource().isEmpty());
389 
390             mBaseRequest = Objects.requireNonNull(request);
391             mIdentity = Objects.requireNonNull(identity);
392             mPermissionLevel = permissionLevel;
393             mProviderLocationRequest = request;
394         }
395 
getIdentity()396         public final CallerIdentity getIdentity() {
397             return mIdentity;
398         }
399 
getRequest()400         public final LocationRequest getRequest() {
401             synchronized (mMultiplexerLock) {
402                 return mProviderLocationRequest;
403             }
404         }
405 
406         @GuardedBy("mMultiplexerLock")
407         @Override
onRegister()408         protected void onRegister() {
409             super.onRegister();
410 
411             if (D) {
412                 Log.d(TAG, mName + " provider added registration from " + getIdentity() + " -> "
413                         + getRequest());
414             }
415 
416             EVENT_LOG.logProviderClientRegistered(mName, getIdentity(), mBaseRequest);
417 
418             // initialization order is important as there are ordering dependencies
419             mPermitted = mLocationPermissionsHelper.hasLocationPermissions(mPermissionLevel,
420                     getIdentity());
421             mForeground = mAppForegroundHelper.isAppForeground(getIdentity().getUid());
422             mProviderLocationRequest = calculateProviderLocationRequest();
423             mIsUsingHighPower = isUsingHighPower();
424 
425             if (mForeground) {
426                 EVENT_LOG.logProviderClientForeground(mName, getIdentity());
427             }
428         }
429 
430         @GuardedBy("mMultiplexerLock")
431         @Override
onUnregister()432         protected void onUnregister() {
433             EVENT_LOG.logProviderClientUnregistered(mName, getIdentity());
434 
435             if (D) {
436                 Log.d(TAG, mName + " provider removed registration from " + getIdentity());
437             }
438 
439             super.onUnregister();
440         }
441 
442         @GuardedBy("mMultiplexerLock")
443         @Override
onActive()444         protected void onActive() {
445             EVENT_LOG.logProviderClientActive(mName, getIdentity());
446 
447             if (!getRequest().isHiddenFromAppOps()) {
448                 mAppOpsHelper.startOpNoThrow(OP_MONITOR_LOCATION, getIdentity());
449             }
450             onHighPowerUsageChanged();
451         }
452 
453         @GuardedBy("mMultiplexerLock")
454         @Override
onInactive()455         protected void onInactive() {
456             onHighPowerUsageChanged();
457             if (!getRequest().isHiddenFromAppOps()) {
458                 mAppOpsHelper.finishOp(OP_MONITOR_LOCATION, getIdentity());
459             }
460 
461             EVENT_LOG.logProviderClientInactive(mName, getIdentity());
462         }
463 
464         @GuardedBy("mMultiplexerLock")
setLastDeliveredLocation(@ullable Location location)465         final void setLastDeliveredLocation(@Nullable Location location) {
466             mLastLocation = location;
467         }
468 
getLastDeliveredLocation()469         public final Location getLastDeliveredLocation() {
470             synchronized (mMultiplexerLock) {
471                 return mLastLocation;
472             }
473         }
474 
getPermissionLevel()475         public @PermissionLevel int getPermissionLevel() {
476             synchronized (mMultiplexerLock) {
477                 return mPermissionLevel;
478             }
479         }
480 
isForeground()481         public final boolean isForeground() {
482             synchronized (mMultiplexerLock) {
483                 return mForeground;
484             }
485         }
486 
isPermitted()487         public final boolean isPermitted() {
488             synchronized (mMultiplexerLock) {
489                 return mPermitted;
490             }
491         }
492 
flush(int requestCode)493         public final void flush(int requestCode) {
494             // when the flush callback is invoked, we are guaranteed that locations have been
495             // queued on our executor, so by running the listener callback on the same executor it
496             // should be guaranteed that those locations will be delivered before the flush callback
497             mProvider.getController().flush(() -> executeOperation(
498                     listener -> listener.deliverOnFlushComplete(requestCode)));
499         }
500 
501         @Override
getOwner()502         protected final LocationProviderManager getOwner() {
503             return LocationProviderManager.this;
504         }
505 
onProviderPropertiesChanged()506         final boolean onProviderPropertiesChanged() {
507             synchronized (mMultiplexerLock) {
508                 onHighPowerUsageChanged();
509                 return false;
510             }
511         }
512 
513         @GuardedBy("mMultiplexerLock")
onHighPowerUsageChanged()514         private void onHighPowerUsageChanged() {
515             boolean isUsingHighPower = isUsingHighPower();
516             if (isUsingHighPower != mIsUsingHighPower) {
517                 mIsUsingHighPower = isUsingHighPower;
518 
519                 if (!getRequest().isHiddenFromAppOps()) {
520                     if (mIsUsingHighPower) {
521                         mAppOpsHelper.startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, getIdentity());
522                     } else {
523                         mAppOpsHelper.finishOp(OP_MONITOR_HIGH_POWER_LOCATION, getIdentity());
524                     }
525                 }
526             }
527         }
528 
isUsingHighPower()529         private boolean isUsingHighPower() {
530             ProviderProperties properties = getProperties();
531             if (properties == null) {
532                 return false;
533             }
534 
535             return isActive()
536                     && getRequest().getIntervalMillis() < MAX_HIGH_POWER_INTERVAL_MS
537                     && properties.getPowerUsage() == ProviderProperties.POWER_USAGE_HIGH;
538         }
539 
onLocationPermissionsChanged(@ullable String packageName)540         final boolean onLocationPermissionsChanged(@Nullable String packageName) {
541             synchronized (mMultiplexerLock) {
542                 if (packageName == null || getIdentity().getPackageName().equals(packageName)) {
543                     return onLocationPermissionsChanged();
544                 }
545 
546                 return false;
547             }
548         }
549 
onLocationPermissionsChanged(int uid)550         final boolean onLocationPermissionsChanged(int uid) {
551             synchronized (mMultiplexerLock) {
552                 if (getIdentity().getUid() == uid) {
553                     return onLocationPermissionsChanged();
554                 }
555 
556                 return false;
557             }
558         }
559 
560         @GuardedBy("mMultiplexerLock")
onLocationPermissionsChanged()561         private boolean onLocationPermissionsChanged() {
562             boolean permitted = mLocationPermissionsHelper.hasLocationPermissions(mPermissionLevel,
563                     getIdentity());
564             if (permitted != mPermitted) {
565                 if (D) {
566                     Log.v(TAG, mName + " provider package " + getIdentity().getPackageName()
567                             + " permitted = " + permitted);
568                 }
569 
570                 mPermitted = permitted;
571 
572                 if (mPermitted) {
573                     EVENT_LOG.logProviderClientPermitted(mName, getIdentity());
574                 } else {
575                     EVENT_LOG.logProviderClientUnpermitted(mName, getIdentity());
576                 }
577 
578                 return true;
579             }
580 
581             return false;
582         }
583 
onAdasGnssLocationEnabledChanged(int userId)584         final boolean onAdasGnssLocationEnabledChanged(int userId) {
585             synchronized (mMultiplexerLock) {
586                 if (getIdentity().getUserId() == userId) {
587                     return onProviderLocationRequestChanged();
588                 }
589 
590                 return false;
591             }
592         }
593 
onForegroundChanged(int uid, boolean foreground)594         final boolean onForegroundChanged(int uid, boolean foreground) {
595             synchronized (mMultiplexerLock) {
596                 if (getIdentity().getUid() == uid && foreground != mForeground) {
597                     if (D) {
598                         Log.v(TAG, mName + " provider uid " + uid + " foreground = " + foreground);
599                     }
600 
601                     mForeground = foreground;
602 
603                     if (mForeground) {
604                         EVENT_LOG.logProviderClientForeground(mName, getIdentity());
605                     } else {
606                         EVENT_LOG.logProviderClientBackground(mName, getIdentity());
607                     }
608 
609                     // note that onProviderLocationRequestChanged() is always called
610                     return onProviderLocationRequestChanged()
611                             || mLocationPowerSaveModeHelper.getLocationPowerSaveMode()
612                             == LOCATION_MODE_FOREGROUND_ONLY;
613                 }
614 
615                 return false;
616             }
617         }
618 
onProviderLocationRequestChanged()619         final boolean onProviderLocationRequestChanged() {
620             synchronized (mMultiplexerLock) {
621                 LocationRequest newRequest = calculateProviderLocationRequest();
622                 if (mProviderLocationRequest.equals(newRequest)) {
623                     return false;
624                 }
625 
626                 LocationRequest oldRequest = mProviderLocationRequest;
627                 mProviderLocationRequest = newRequest;
628                 onHighPowerUsageChanged();
629                 updateService();
630 
631                 // if bypass state has changed then the active state may have changed
632                 return oldRequest.isBypass() != newRequest.isBypass();
633             }
634         }
635 
636         @GuardedBy("mMultiplexerLock")
calculateProviderLocationRequest()637         private LocationRequest calculateProviderLocationRequest() {
638             LocationRequest.Builder builder = new LocationRequest.Builder(mBaseRequest);
639 
640             if (mPermissionLevel < PERMISSION_FINE) {
641                 builder.setQuality(LocationRequest.QUALITY_LOW_POWER);
642                 if (mBaseRequest.getIntervalMillis() < MIN_COARSE_INTERVAL_MS) {
643                     builder.setIntervalMillis(MIN_COARSE_INTERVAL_MS);
644                 }
645                 if (mBaseRequest.getMinUpdateIntervalMillis() < MIN_COARSE_INTERVAL_MS) {
646                     builder.setMinUpdateIntervalMillis(MIN_COARSE_INTERVAL_MS);
647                 }
648             }
649 
650             boolean locationSettingsIgnored = mBaseRequest.isLocationSettingsIgnored();
651             if (locationSettingsIgnored) {
652                 // if we are not currently allowed use location settings ignored, disable it
653                 if (!mSettingsHelper.getIgnoreSettingsAllowlist().contains(
654                         getIdentity().getPackageName(), getIdentity().getAttributionTag())
655                         && !mLocationManagerInternal.isProvider(null, getIdentity())) {
656                     locationSettingsIgnored = false;
657                 }
658 
659                 builder.setLocationSettingsIgnored(locationSettingsIgnored);
660             }
661 
662             boolean adasGnssBypass = mBaseRequest.isAdasGnssBypass();
663             if (adasGnssBypass) {
664                 // if we are not currently allowed use adas gnss bypass, disable it
665                 if (!GPS_PROVIDER.equals(mName)) {
666                     Log.e(TAG, "adas gnss bypass request received in non-gps provider");
667                     adasGnssBypass = false;
668                 } else if (!mUserHelper.isCurrentUserId(getIdentity().getUserId())) {
669                     adasGnssBypass = false;
670                 } else if (!mLocationSettings.getUserSettings(
671                         getIdentity().getUserId()).isAdasGnssLocationEnabled()) {
672                     adasGnssBypass = false;
673                 } else if (!mSettingsHelper.getAdasAllowlist().contains(
674                         getIdentity().getPackageName(), getIdentity().getAttributionTag())) {
675                     adasGnssBypass = false;
676                 }
677 
678                 builder.setAdasGnssBypass(adasGnssBypass);
679             }
680 
681             if (!locationSettingsIgnored && !isThrottlingExempt()) {
682                 // throttle in the background
683                 if (!mForeground) {
684                     builder.setIntervalMillis(max(mBaseRequest.getIntervalMillis(),
685                             mSettingsHelper.getBackgroundThrottleIntervalMs()));
686                 }
687             }
688 
689             return builder.build();
690         }
691 
isThrottlingExempt()692         private boolean isThrottlingExempt() {
693             if (mSettingsHelper.getBackgroundThrottlePackageWhitelist().contains(
694                     getIdentity().getPackageName())) {
695                 return true;
696             }
697 
698             return mLocationManagerInternal.isProvider(null, getIdentity());
699         }
700 
acceptLocationChange( LocationResult fineLocationResult)701         @Nullable abstract ListenerOperation<LocationTransport> acceptLocationChange(
702                 LocationResult fineLocationResult);
703 
704         @Override
toString()705         public String toString() {
706             StringBuilder builder = new StringBuilder();
707             builder.append(getIdentity());
708 
709             ArraySet<String> flags = new ArraySet<>(2);
710             if (!isForeground()) {
711                 flags.add("bg");
712             }
713             if (!isPermitted()) {
714                 flags.add("na");
715             }
716             if (!flags.isEmpty()) {
717                 builder.append(" ").append(flags);
718             }
719 
720             if (mPermissionLevel == PERMISSION_COARSE) {
721                 builder.append(" (COARSE)");
722             }
723 
724             builder.append(" ").append(getRequest());
725             return builder.toString();
726         }
727     }
728 
729     protected abstract class LocationRegistration extends Registration implements
730             OnAlarmListener, ProviderEnabledListener {
731 
732         final PowerManager.WakeLock mWakeLock;
733 
734         // b/206340085 - if we allocate a new wakelock releaser object for every delivery we
735         // increase the risk of resource starvation. if a client stops processing deliveries the
736         // system server binder allocation pool will be starved as we continue to queue up
737         // deliveries, each with a new allocation. in order to mitigate this, we use a single
738         // releaser object per registration rather than per delivery.
739         final ExternalWakeLockReleaser mWakeLockReleaser;
740 
741         private volatile ProviderTransport mProviderTransport;
742 
743         @GuardedBy("mMultiplexerLock")
744         private int mNumLocationsDelivered = 0;
745         @GuardedBy("mMultiplexerLock")
746         private long mExpirationRealtimeMs = Long.MAX_VALUE;
747 
LocationRegistration( LocationRequest request, CallerIdentity identity, Executor executor, TTransport transport, @PermissionLevel int permissionLevel)748         protected <TTransport extends LocationTransport & ProviderTransport> LocationRegistration(
749                 LocationRequest request,
750                 CallerIdentity identity,
751                 Executor executor,
752                 TTransport transport,
753                 @PermissionLevel int permissionLevel) {
754             super(request, identity, executor, transport, permissionLevel);
755             mProviderTransport = transport;
756             mWakeLock = Objects.requireNonNull(mContext.getSystemService(PowerManager.class))
757                     .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
758             mWakeLock.setReferenceCounted(true);
759             mWakeLock.setWorkSource(request.getWorkSource());
760             mWakeLockReleaser = new ExternalWakeLockReleaser(identity, mWakeLock);
761         }
762 
763         @Override
onListenerUnregister()764         protected void onListenerUnregister() {
765             mProviderTransport = null;
766         }
767 
768         // TODO: remove suppression when GuardedBy analysis can recognize lock from super class
769         @SuppressWarnings("GuardedBy")
770         @GuardedBy("mMultiplexerLock")
771         @Override
onRegister()772         protected void onRegister() {
773             super.onRegister();
774 
775             long registerTimeMs = SystemClock.elapsedRealtime();
776             mExpirationRealtimeMs = getRequest().getExpirationRealtimeMs(registerTimeMs);
777 
778             // add alarm for expiration
779             if (mExpirationRealtimeMs <= registerTimeMs) {
780                 onAlarm();
781             } else if (mExpirationRealtimeMs < Long.MAX_VALUE) {
782                 // Set WorkSource to null in order to ensure the alarm wakes up the device even when
783                 // it is idle. Do this when the cost of waking up the device is less than the power
784                 // cost of not performing the actions set off by the alarm, such as unregistering a
785                 // location request.
786                 mAlarmHelper.setDelayedAlarm(mExpirationRealtimeMs - registerTimeMs, this,
787                         null);
788             }
789 
790             // start listening for provider enabled/disabled events
791             addEnabledListener(this);
792 
793             // if the provider is currently disabled, let the client know immediately
794             int userId = getIdentity().getUserId();
795             if (!isEnabled(userId)) {
796                 onProviderEnabledChanged(mName, userId, false);
797             }
798         }
799 
800         // TODO: remove suppression when GuardedBy analysis can recognize lock from super class
801         @SuppressWarnings("GuardedBy")
802         @GuardedBy("mMultiplexerLock")
803         @Override
onUnregister()804         protected void onUnregister() {
805             // stop listening for provider enabled/disabled events
806             removeEnabledListener(this);
807 
808             // remove alarm for expiration
809             if (mExpirationRealtimeMs < Long.MAX_VALUE) {
810                 mAlarmHelper.cancel(this);
811             }
812 
813             super.onUnregister();
814         }
815 
816         // TODO: remove suppression when GuardedBy analysis can recognize lock from super class
817         @SuppressWarnings("GuardedBy")
818         @GuardedBy("mMultiplexerLock")
819         @Override
onActive()820         protected void onActive() {
821             super.onActive();
822 
823             // a new registration may not get a location immediately, the provider request may be
824             // delayed. therefore we deliver a historical location if available. since delivering an
825             // older location could be considered a breaking change for some applications, we only
826             // do so for apps targeting S+.
827             if (isChangeEnabled(DELIVER_HISTORICAL_LOCATIONS, getIdentity().getUid())) {
828                 long maxLocationAgeMs = getRequest().getIntervalMillis();
829                 Location lastDeliveredLocation = getLastDeliveredLocation();
830                 if (lastDeliveredLocation != null) {
831                     // ensure that location is fresher than the last delivered location
832                     maxLocationAgeMs = min(maxLocationAgeMs,
833                             lastDeliveredLocation.getElapsedRealtimeAgeMillis() - 1);
834                 }
835 
836                 // requests are never delayed less than MIN_REQUEST_DELAY_MS, so it only makes sense
837                 // to deliver historical locations to clients with a last location older than that
838                 if (maxLocationAgeMs > MIN_REQUEST_DELAY_MS) {
839                     Location lastLocation = getLastLocationUnsafe(
840                             getIdentity().getUserId(),
841                             getPermissionLevel(),
842                             getRequest().isBypass(),
843                             maxLocationAgeMs);
844                     if (lastLocation != null) {
845                         executeOperation(acceptLocationChange(LocationResult.wrap(lastLocation)));
846                     }
847                 }
848             }
849         }
850 
851         @Override
onAlarm()852         public void onAlarm() {
853             if (D) {
854                 Log.d(TAG, mName + " provider registration " + getIdentity()
855                         + " expired at " + TimeUtils.formatRealtime(mExpirationRealtimeMs));
856             }
857 
858             synchronized (mMultiplexerLock) {
859                 // no need to remove alarm after it's fired
860                 mExpirationRealtimeMs = Long.MAX_VALUE;
861                 remove();
862             }
863         }
864 
865         @GuardedBy("mMultiplexerLock")
866         @Override
acceptLocationChange( LocationResult fineLocationResult)867         @Nullable ListenerOperation<LocationTransport> acceptLocationChange(
868                 LocationResult fineLocationResult) {
869             // check expiration time - alarm is not guaranteed to go off at the right time,
870             // especially for short intervals
871             if (SystemClock.elapsedRealtime() >= mExpirationRealtimeMs) {
872                 if (D) {
873                     Log.d(TAG, mName + " provider registration " + getIdentity()
874                             + " expired at " + TimeUtils.formatRealtime(mExpirationRealtimeMs));
875                 }
876                 remove();
877                 return null;
878             }
879 
880             LocationResult permittedLocationResult = Objects.requireNonNull(
881                     getPermittedLocationResult(fineLocationResult, getPermissionLevel()));
882 
883             LocationResult locationResult = permittedLocationResult.filter(
884                     new Predicate<Location>() {
885                         private Location mPreviousLocation = getLastDeliveredLocation();
886 
887                         @Override
888                         public boolean test(Location location) {
889                             if (mPreviousLocation != null) {
890                                 // check fastest interval
891                                 long deltaMs = location.getElapsedRealtimeMillis()
892                                         - mPreviousLocation.getElapsedRealtimeMillis();
893                                 long maxJitterMs = min((long) (FASTEST_INTERVAL_JITTER_PERCENTAGE
894                                                 * getRequest().getIntervalMillis()),
895                                         MAX_FASTEST_INTERVAL_JITTER_MS);
896                                 if (deltaMs
897                                         < getRequest().getMinUpdateIntervalMillis() - maxJitterMs) {
898                                     if (D) {
899                                         Log.v(TAG, mName + " provider registration " + getIdentity()
900                                                 + " dropped delivery - too fast");
901                                     }
902                                     return false;
903                                 }
904 
905                                 // check smallest displacement
906                                 double smallestDisplacementM =
907                                         getRequest().getMinUpdateDistanceMeters();
908                                 if (smallestDisplacementM > 0.0 && location.distanceTo(
909                                         mPreviousLocation)
910                                         <= smallestDisplacementM) {
911                                     if (D) {
912                                         Log.v(TAG, mName + " provider registration " + getIdentity()
913                                                 + " dropped delivery - too close");
914                                     }
915                                     return false;
916                                 }
917                             }
918 
919                             mPreviousLocation = location;
920                             return true;
921                         }
922                     });
923 
924             if (locationResult == null) {
925                 return null;
926             }
927 
928             // note app ops
929             if (!mAppOpsHelper.noteOpNoThrow(LocationPermissions.asAppOp(getPermissionLevel()),
930                     getIdentity())) {
931                 if (D) {
932                     Log.w(TAG,
933                             mName + " provider registration " + getIdentity() + " noteOp denied");
934                 }
935                 return null;
936             }
937 
938             // acquire a wakelock for non-passive requests
939             boolean useWakeLock =
940                     getRequest().getIntervalMillis() != LocationRequest.PASSIVE_INTERVAL;
941 
942             // deliver location
943             return new ListenerOperation<LocationTransport>() {
944 
945                 @Override
946                 public void onPreExecute() {
947                     // update last delivered location
948                     setLastDeliveredLocation(locationResult.getLastLocation());
949 
950                     if (useWakeLock) {
951                         mWakeLock.acquire(WAKELOCK_TIMEOUT_MS);
952                     }
953                 }
954 
955                 @Override
956                 public void operate(LocationTransport listener) throws Exception {
957                     // if delivering to the same process, make a copy of the location first (since
958                     // location is mutable)
959                     LocationResult deliverLocationResult;
960                     if (getIdentity().getPid() == Process.myPid()) {
961                         deliverLocationResult = locationResult.deepCopy();
962                     } else {
963                         deliverLocationResult = locationResult;
964                     }
965 
966                     listener.deliverOnLocationChanged(deliverLocationResult,
967                             useWakeLock ? mWakeLockReleaser : null);
968                     EVENT_LOG.logProviderDeliveredLocations(mName, locationResult.size(),
969                             getIdentity());
970                 }
971 
972                 @Override
973                 public void onPostExecute(boolean success) {
974                     if (!success && useWakeLock) {
975                         mWakeLock.release();
976                     }
977 
978                     if (success) {
979                         // check num updates - if successful then this function will always be run
980                         // from the same thread, and no additional synchronization is necessary
981                         boolean remove = ++mNumLocationsDelivered >= getRequest().getMaxUpdates();
982                         if (remove) {
983                             if (D) {
984                                 Log.d(TAG, mName + " provider registration " + getIdentity()
985                                         + " finished after " + mNumLocationsDelivered + " updates");
986                             }
987 
988                             remove();
989                         }
990                     }
991                 }
992             };
993         }
994 
995         @Override
onProviderEnabledChanged(String provider, int userId, boolean enabled)996         public void onProviderEnabledChanged(String provider, int userId, boolean enabled) {
997             Preconditions.checkState(mName.equals(provider));
998 
999             if (userId != getIdentity().getUserId()) {
1000                 return;
1001             }
1002 
1003             // we choose not to hold a wakelock for provider enabled changed events
1004             executeSafely(getExecutor(), () -> mProviderTransport,
1005                     listener -> listener.deliverOnProviderEnabledChanged(mName, enabled),
1006                     this::onProviderOperationFailure);
1007         }
1008 
onProviderOperationFailure( ListenerOperation<ProviderTransport> operation, Exception exception)1009         protected abstract void onProviderOperationFailure(
1010                 ListenerOperation<ProviderTransport> operation, Exception exception);
1011     }
1012 
1013     protected final class LocationListenerRegistration extends LocationRegistration implements
1014             IBinder.DeathRecipient {
1015 
1016         LocationListenerRegistration(LocationRequest request, CallerIdentity identity,
1017                 LocationListenerTransport transport, @PermissionLevel int permissionLevel) {
1018             super(request, identity,
1019                     identity.isMyProcess() ? FgThread.getExecutor() : DIRECT_EXECUTOR, transport,
1020                     permissionLevel);
1021         }
1022 
1023         // TODO: remove suppression when GuardedBy analysis can recognize lock from super class
1024         @SuppressWarnings("GuardedBy")
1025         @GuardedBy("mMultiplexerLock")
1026         @Override
1027         protected void onRegister() {
1028             super.onRegister();
1029 
1030             try {
1031                 ((IBinder) getKey()).linkToDeath(this, 0);
1032             } catch (RemoteException e) {
1033                 remove();
1034             }
1035         }
1036 
1037         // TODO: remove suppression when GuardedBy analysis can recognize lock from super class
1038         @SuppressWarnings("GuardedBy")
1039         @GuardedBy("mMultiplexerLock")
1040         @Override
1041         protected void onUnregister() {
1042             try {
1043                 ((IBinder) getKey()).unlinkToDeath(this, 0);
1044             } catch (NoSuchElementException e) {
1045                 // the only way this exception can occur should be if another exception has been
1046                 // thrown prior to registration completing, and that exception is currently
1047                 // unwinding the call stack and causing this cleanup. since that exception should
1048                 // crash us anyways, drop this exception so we're not hiding the original exception.
1049                 Log.w(getTag(), "failed to unregister binder death listener", e);
1050             }
1051 
1052             super.onUnregister();
1053         }
1054 
1055         @Override
1056         protected void onProviderOperationFailure(ListenerOperation<ProviderTransport> operation,
1057                 Exception exception) {
1058             onTransportFailure(exception);
1059         }
1060 
1061         @Override
1062         public void onOperationFailure(ListenerOperation<LocationTransport> operation,
1063                 Exception exception) {
1064             onTransportFailure(exception);
1065         }
1066 
1067         private void onTransportFailure(Exception e) {
1068             if (e instanceof RemoteException) {
1069                 Log.w(TAG, mName + " provider registration " + getIdentity() + " removed", e);
1070                 remove();
1071             } else {
1072                 throw new AssertionError(e);
1073             }
1074         }
1075 
1076         @Override
1077         public void binderDied() {
1078             try {
1079                 if (D) {
1080                     Log.d(TAG, mName + " provider registration " + getIdentity() + " died");
1081                 }
1082 
1083                 remove();
1084             } catch (RuntimeException e) {
1085                 // the caller may swallow runtime exceptions, so we rethrow as assertion errors to
1086                 // ensure the crash is seen
1087                 throw new AssertionError(e);
1088             }
1089         }
1090     }
1091 
1092     protected final class LocationPendingIntentRegistration extends LocationRegistration implements
1093             PendingIntent.CancelListener {
1094 
1095         LocationPendingIntentRegistration(LocationRequest request,
1096                 CallerIdentity identity, LocationPendingIntentTransport transport,
1097                 @PermissionLevel int permissionLevel) {
1098             super(request, identity, DIRECT_EXECUTOR, transport, permissionLevel);
1099         }
1100 
1101         // TODO: remove suppression when GuardedBy analysis can recognize lock from super class
1102         @SuppressWarnings("GuardedBy")
1103         @GuardedBy("mMultiplexerLock")
1104         @Override
1105         protected void onRegister() {
1106             super.onRegister();
1107             if (!((PendingIntent) getKey()).addCancelListener(DIRECT_EXECUTOR, this)) {
1108                 remove();
1109             }
1110         }
1111 
1112         // TODO: remove suppression when GuardedBy analysis can recognize lock from super class
1113         @SuppressWarnings("GuardedBy")
1114         @GuardedBy("mMultiplexerLock")
1115         @Override
1116         protected void onUnregister() {
1117             ((PendingIntent) getKey()).removeCancelListener(this);
1118             super.onUnregister();
1119         }
1120 
1121         @Override
1122         protected void onProviderOperationFailure(ListenerOperation<ProviderTransport> operation,
1123                 Exception exception) {
1124             onTransportFailure(exception);
1125         }
1126 
1127         @Override
1128         public void onOperationFailure(ListenerOperation<LocationTransport> operation,
1129                 Exception exception) {
1130             onTransportFailure(exception);
1131         }
1132 
1133         private void onTransportFailure(Exception e) {
1134             if (e instanceof PendingIntent.CanceledException) {
1135                 Log.w(TAG, mName + " provider registration " + getIdentity() + " removed", e);
1136                 remove();
1137             } else {
1138                 throw new AssertionError(e);
1139             }
1140         }
1141 
1142         @Override
1143         public void onCanceled(PendingIntent intent) {
1144             if (D) {
1145                 Log.d(TAG, mName + " provider registration " + getIdentity() + " canceled");
1146             }
1147 
1148             remove();
1149         }
1150     }
1151 
1152     protected final class GetCurrentLocationListenerRegistration extends Registration implements
1153             IBinder.DeathRecipient, OnAlarmListener {
1154 
1155         @GuardedBy("mMultiplexerLock")
1156         private long mExpirationRealtimeMs = Long.MAX_VALUE;
1157 
1158         GetCurrentLocationListenerRegistration(LocationRequest request,
1159                 CallerIdentity identity, LocationTransport transport, int permissionLevel) {
1160             super(request,
1161                     identity,
1162                     identity.isMyProcess() ? FgThread.getExecutor() : DIRECT_EXECUTOR,
1163                     transport,
1164                     permissionLevel);
1165         }
1166 
1167         // TODO: remove suppression when GuardedBy analysis can recognize lock from super class
1168         @SuppressWarnings("GuardedBy")
1169         @GuardedBy("mMultiplexerLock")
1170         @Override
1171         protected void onRegister() {
1172             super.onRegister();
1173 
1174             try {
1175                 ((IBinder) getKey()).linkToDeath(this, 0);
1176             } catch (RemoteException e) {
1177                 remove();
1178             }
1179 
1180             long registerTimeMs = SystemClock.elapsedRealtime();
1181             mExpirationRealtimeMs = getRequest().getExpirationRealtimeMs(registerTimeMs);
1182 
1183             // add alarm for expiration
1184             if (mExpirationRealtimeMs <= registerTimeMs) {
1185                 onAlarm();
1186             } else if (mExpirationRealtimeMs < Long.MAX_VALUE) {
1187                 // Set WorkSource to null in order to ensure the alarm wakes up the device even when
1188                 // it is idle. Do this when the cost of waking up the device is less than the power
1189                 // cost of not performing the actions set off by the alarm, such as unregistering a
1190                 // location request.
1191                 mAlarmHelper.setDelayedAlarm(mExpirationRealtimeMs - registerTimeMs, this,
1192                         null);
1193             }
1194         }
1195 
1196         // TODO: remove suppression when GuardedBy analysis can recognize lock from super class
1197         @SuppressWarnings("GuardedBy")
1198         @GuardedBy("mMultiplexerLock")
1199         @Override
1200         protected void onUnregister() {
1201             // remove alarm for expiration
1202             if (mExpirationRealtimeMs < Long.MAX_VALUE) {
1203                 mAlarmHelper.cancel(this);
1204             }
1205 
1206             try {
1207                 ((IBinder) getKey()).unlinkToDeath(this, 0);
1208             } catch (NoSuchElementException e) {
1209                 // the only way this exception can occur should be if another exception has been
1210                 // thrown prior to registration completing, and that exception is currently
1211                 // unwinding the call stack and causing this cleanup. since that exception should
1212                 // crash us anyways, drop this exception so we're not hiding the original exception.
1213                 Log.w(getTag(), "failed to unregister binder death listener", e);
1214             }
1215 
1216             super.onUnregister();
1217         }
1218 
1219         // TODO: remove suppression when GuardedBy analysis can recognize lock from super class
1220         @SuppressWarnings("GuardedBy")
1221         @GuardedBy("mMultiplexerLock")
1222         @Override
1223         protected void onActive() {
1224             super.onActive();
1225 
1226             Location lastLocation = getLastLocationUnsafe(
1227                     getIdentity().getUserId(),
1228                     getPermissionLevel(),
1229                     getRequest().isBypass(),
1230                     MAX_CURRENT_LOCATION_AGE_MS);
1231             if (lastLocation != null) {
1232                 executeOperation(acceptLocationChange(LocationResult.wrap(lastLocation)));
1233             }
1234         }
1235 
1236         // TODO: remove suppression when GuardedBy analysis can recognize lock from super class
1237         @SuppressWarnings("GuardedBy")
1238         @GuardedBy("mMultiplexerLock")
1239         @Override
1240         protected void onInactive() {
1241             // if we go inactive for any reason, fail immediately
1242             executeOperation(acceptLocationChange(null));
1243             super.onInactive();
1244         }
1245 
1246         @GuardedBy("mMultiplexerLock")
1247         void deliverNull() {
1248             executeOperation(acceptLocationChange(null));
1249         }
1250 
1251         @Override
1252         public void onAlarm() {
1253             if (D) {
1254                 Log.d(TAG, mName + " provider registration " + getIdentity()
1255                         + " expired at " + TimeUtils.formatRealtime(mExpirationRealtimeMs));
1256             }
1257 
1258             synchronized (mMultiplexerLock) {
1259                 // no need to remove alarm after it's fired
1260                 mExpirationRealtimeMs = Long.MAX_VALUE;
1261                 executeOperation(acceptLocationChange(null));
1262             }
1263         }
1264 
1265         @GuardedBy("mMultiplexerLock")
1266         @Override
1267         @Nullable ListenerOperation<LocationTransport> acceptLocationChange(
1268                 @Nullable LocationResult fineLocationResult) {
1269             // check expiration time - alarm is not guaranteed to go off at the right time,
1270             // especially for short intervals
1271             if (SystemClock.elapsedRealtime() >= mExpirationRealtimeMs) {
1272                 if (D) {
1273                     Log.d(TAG, mName + " provider registration " + getIdentity()
1274                             + " expired at " + TimeUtils.formatRealtime(mExpirationRealtimeMs));
1275                 }
1276                 fineLocationResult = null;
1277             }
1278 
1279             // lastly - note app ops
1280             if (fineLocationResult != null && !mAppOpsHelper.noteOpNoThrow(
1281                     LocationPermissions.asAppOp(getPermissionLevel()), getIdentity())) {
1282                 if (D) {
1283                     Log.w(TAG, "noteOp denied for " + getIdentity());
1284                 }
1285                 fineLocationResult = null;
1286             }
1287 
1288             if (fineLocationResult != null) {
1289                 fineLocationResult = fineLocationResult.asLastLocationResult();
1290             }
1291 
1292             LocationResult locationResult = getPermittedLocationResult(fineLocationResult,
1293                     getPermissionLevel());
1294 
1295             // deliver location
1296             return new ListenerOperation<LocationTransport>() {
1297                 @Override
1298                 public void operate(LocationTransport listener) throws Exception {
1299                     // if delivering to the same process, make a copy of the location first (since
1300                     // location is mutable)
1301                     LocationResult deliverLocationResult;
1302                     if (getIdentity().getPid() == Process.myPid() && locationResult != null) {
1303                         deliverLocationResult = locationResult.deepCopy();
1304                     } else {
1305                         deliverLocationResult = locationResult;
1306                     }
1307 
1308                     // we currently don't hold a wakelock for getCurrentLocation deliveries
1309                     listener.deliverOnLocationChanged(deliverLocationResult, null);
1310                     EVENT_LOG.logProviderDeliveredLocations(mName,
1311                             locationResult != null ? locationResult.size() : 0, getIdentity());
1312                 }
1313 
1314                 @Override
1315                 public void onPostExecute(boolean success) {
1316                     // on failure we're automatically removed anyways, no need to attempt removal
1317                     // again
1318                     if (success) {
1319                         remove();
1320                     }
1321                 }
1322             };
1323         }
1324 
1325         @Override
1326         public void onOperationFailure(ListenerOperation<LocationTransport> operation,
1327                 Exception e) {
1328             if (e instanceof RemoteException) {
1329                 Log.w(TAG, mName + " provider registration " + getIdentity() + " removed", e);
1330                 remove();
1331             } else {
1332                 throw new AssertionError(e);
1333             }
1334         }
1335 
1336         @Override
1337         public void binderDied() {
1338             try {
1339                 if (D) {
1340                     Log.d(TAG, mName + " provider registration " + getIdentity() + " died");
1341                 }
1342 
1343                 remove();
1344             } catch (RuntimeException e) {
1345                 // the caller may swallow runtime exceptions, so we rethrow as assertion errors to
1346                 // ensure the crash is seen
1347                 throw new AssertionError(e);
1348             }
1349         }
1350     }
1351 
1352     protected final String mName;
1353     @Nullable private final PassiveLocationProviderManager mPassiveManager;
1354 
1355     protected final Context mContext;
1356 
1357     @GuardedBy("mMultiplexerLock")
1358     private @State int mState;
1359 
1360     // maps of user id to value
1361     @GuardedBy("mMultiplexerLock")
1362     private final SparseBooleanArray mEnabled; // null or not present means unknown
1363     @GuardedBy("mMultiplexerLock")
1364     private final SparseArray<LastLocation> mLastLocations;
1365 
1366     @GuardedBy("mMultiplexerLock")
1367     private final ArrayList<ProviderEnabledListener> mEnabledListeners;
1368 
1369     // Extra permissions required to use this provider (on top of the usual location permissions).
1370     // Not guarded because it's read only.
1371     private final Collection<String> mRequiredPermissions;
1372 
1373     private final CopyOnWriteArrayList<IProviderRequestListener> mProviderRequestListeners;
1374 
1375     protected final LocationManagerInternal mLocationManagerInternal;
1376     protected final LocationSettings mLocationSettings;
1377     protected final SettingsHelper mSettingsHelper;
1378     protected final UserInfoHelper mUserHelper;
1379     protected final AlarmHelper mAlarmHelper;
1380     protected final AppOpsHelper mAppOpsHelper;
1381     protected final LocationPermissionsHelper mLocationPermissionsHelper;
1382     protected final AppForegroundHelper mAppForegroundHelper;
1383     protected final LocationPowerSaveModeHelper mLocationPowerSaveModeHelper;
1384     protected final ScreenInteractiveHelper mScreenInteractiveHelper;
1385     protected final LocationUsageLogger mLocationUsageLogger;
1386     protected final LocationFudger mLocationFudger;
1387     private final PackageResetHelper mPackageResetHelper;
1388 
1389     private final UserListener mUserChangedListener = this::onUserChanged;
1390     private final LocationSettings.LocationUserSettingsListener mLocationUserSettingsListener =
1391             this::onLocationUserSettingsChanged;
1392     private final UserSettingChangedListener mLocationEnabledChangedListener =
1393             this::onLocationEnabledChanged;
1394     private final GlobalSettingChangedListener mBackgroundThrottlePackageWhitelistChangedListener =
1395             this::onBackgroundThrottlePackageWhitelistChanged;
1396     private final UserSettingChangedListener mLocationPackageBlacklistChangedListener =
1397             this::onLocationPackageBlacklistChanged;
1398     private final LocationPermissionsListener mLocationPermissionsListener =
1399             new LocationPermissionsListener() {
1400                 @Override
1401                 public void onLocationPermissionsChanged(@Nullable String packageName) {
1402                     LocationProviderManager.this.onLocationPermissionsChanged(packageName);
1403                 }
1404 
1405                 @Override
1406                 public void onLocationPermissionsChanged(int uid) {
1407                     LocationProviderManager.this.onLocationPermissionsChanged(uid);
1408                 }
1409             };
1410     private final AppForegroundListener mAppForegroundChangedListener =
1411             this::onAppForegroundChanged;
1412     private final GlobalSettingChangedListener mBackgroundThrottleIntervalChangedListener =
1413             this::onBackgroundThrottleIntervalChanged;
1414     private final GlobalSettingChangedListener mAdasPackageAllowlistChangedListener =
1415             this::onAdasAllowlistChanged;
1416     private final GlobalSettingChangedListener mIgnoreSettingsPackageWhitelistChangedListener =
1417             this::onIgnoreSettingsWhitelistChanged;
1418     private final LocationPowerSaveModeChangedListener mLocationPowerSaveModeChangedListener =
1419             this::onLocationPowerSaveModeChanged;
1420     private final ScreenInteractiveChangedListener mScreenInteractiveChangedListener =
1421             this::onScreenInteractiveChanged;
1422     private final PackageResetHelper.Responder mPackageResetResponder =
1423             new PackageResetHelper.Responder() {
1424                 @Override
1425                 public void onPackageReset(String packageName) {
1426                     LocationProviderManager.this.onPackageReset(packageName);
1427                 }
1428 
1429                 @Override
1430                 public boolean isResetableForPackage(String packageName) {
1431                     return LocationProviderManager.this.isResetableForPackage(packageName);
1432                 }
1433             };
1434 
1435     // acquiring mMultiplexerLock makes operations on mProvider atomic, but is otherwise unnecessary
1436     protected final MockableLocationProvider mProvider;
1437 
1438     @GuardedBy("mMultiplexerLock")
1439     @Nullable private OnAlarmListener mDelayedRegister;
1440 
1441     @GuardedBy("mMultiplexerLock")
1442     @Nullable private StateChangedListener mStateChangedListener;
1443 
1444     public LocationProviderManager(Context context, Injector injector,
1445             String name, @Nullable PassiveLocationProviderManager passiveManager) {
1446         this(context, injector, name, passiveManager, Collections.emptyList());
1447     }
1448 
1449     /**
1450      * Creates a manager for a location provider (the two have a 1:1 correspondence).
1451      *
1452      * @param context Context in which the manager is running.
1453      * @param injector Injector to retrieve system components (useful to override in testing)
1454      * @param name Name of this provider (used in LocationManager APIs by client apps).
1455      * @param passiveManager The "passive" manager (special case provider that returns locations
1456      *     from all other providers).
1457      * @param requiredPermissions Required permissions for accessing this provider. All of the given
1458      *     permissions are required to access the provider. If a caller doesn't hold the correct
1459      *     permission, the provider will be invisible to it.
1460      */
1461     public LocationProviderManager(
1462             Context context,
1463             Injector injector,
1464             String name,
1465             @Nullable PassiveLocationProviderManager passiveManager,
1466             Collection<String> requiredPermissions) {
1467         mContext = context;
1468         mName = Objects.requireNonNull(name);
1469         mPassiveManager = passiveManager;
1470         mState = STATE_STOPPED;
1471         mEnabled = new SparseBooleanArray(2);
1472         mLastLocations = new SparseArray<>(2);
1473         mRequiredPermissions = requiredPermissions;
1474 
1475         mEnabledListeners = new ArrayList<>();
1476         mProviderRequestListeners = new CopyOnWriteArrayList<>();
1477 
1478         mLocationManagerInternal = Objects.requireNonNull(
1479                 LocalServices.getService(LocationManagerInternal.class));
1480         mLocationSettings = injector.getLocationSettings();
1481         mSettingsHelper = injector.getSettingsHelper();
1482         mUserHelper = injector.getUserInfoHelper();
1483         mAlarmHelper = injector.getAlarmHelper();
1484         mAppOpsHelper = injector.getAppOpsHelper();
1485         mLocationPermissionsHelper = injector.getLocationPermissionsHelper();
1486         mAppForegroundHelper = injector.getAppForegroundHelper();
1487         mLocationPowerSaveModeHelper = injector.getLocationPowerSaveModeHelper();
1488         mScreenInteractiveHelper = injector.getScreenInteractiveHelper();
1489         mLocationUsageLogger = injector.getLocationUsageLogger();
1490         mLocationFudger = new LocationFudger(mSettingsHelper.getCoarseLocationAccuracyM());
1491         mPackageResetHelper = injector.getPackageResetHelper();
1492 
1493         mProvider = new MockableLocationProvider(mMultiplexerLock);
1494 
1495         // set listener last, since this lets our reference escape
1496         mProvider.getController().setListener(this);
1497     }
1498 
1499     public void startManager(@Nullable StateChangedListener listener) {
1500         synchronized (mMultiplexerLock) {
1501             Preconditions.checkState(mState == STATE_STOPPED);
1502             mState = STATE_STARTED;
1503             mStateChangedListener = listener;
1504 
1505             mUserHelper.addListener(mUserChangedListener);
1506             mLocationSettings.registerLocationUserSettingsListener(mLocationUserSettingsListener);
1507             mSettingsHelper.addOnLocationEnabledChangedListener(mLocationEnabledChangedListener);
1508 
1509             final long identity = Binder.clearCallingIdentity();
1510             try {
1511                 mProvider.getController().start();
1512                 onUserStarted(UserHandle.USER_ALL);
1513             } finally {
1514                 Binder.restoreCallingIdentity(identity);
1515             }
1516         }
1517     }
1518 
1519     public void stopManager() {
1520         synchronized (mMultiplexerLock) {
1521             Preconditions.checkState(mState == STATE_STARTED);
1522             mState = STATE_STOPPING;
1523 
1524             final long identity = Binder.clearCallingIdentity();
1525             try {
1526                 onEnabledChanged(UserHandle.USER_ALL);
1527                 removeRegistrationIf(key -> true);
1528                 mProvider.getController().stop();
1529             } finally {
1530                 Binder.restoreCallingIdentity(identity);
1531             }
1532 
1533             mUserHelper.removeListener(mUserChangedListener);
1534             mLocationSettings.unregisterLocationUserSettingsListener(mLocationUserSettingsListener);
1535             mSettingsHelper.removeOnLocationEnabledChangedListener(mLocationEnabledChangedListener);
1536 
1537             // if external entities are registering listeners it's their responsibility to
1538             // unregister them before stopManager() is called
1539             Preconditions.checkState(mEnabledListeners.isEmpty());
1540             mProviderRequestListeners.clear();
1541 
1542             mEnabled.clear();
1543             mLastLocations.clear();
1544             mStateChangedListener = null;
1545             mState = STATE_STOPPED;
1546         }
1547     }
1548 
1549     public String getName() {
1550         return mName;
1551     }
1552 
1553     public AbstractLocationProvider.State getState() {
1554         return mProvider.getState();
1555     }
1556 
1557     @Nullable public CallerIdentity getProviderIdentity() {
1558         return mProvider.getState().identity;
1559     }
1560 
1561     @Nullable public ProviderProperties getProperties() {
1562         return mProvider.getState().properties;
1563     }
1564 
1565     public boolean hasProvider() {
1566         return mProvider.getProvider() != null;
1567     }
1568 
1569     public boolean isEnabled(int userId) {
1570         if (userId == UserHandle.USER_NULL) {
1571             return false;
1572         } else if (userId == USER_CURRENT) {
1573             return isEnabled(mUserHelper.getCurrentUserId());
1574         }
1575 
1576         Preconditions.checkArgument(userId >= 0);
1577 
1578         synchronized (mMultiplexerLock) {
1579             int index = mEnabled.indexOfKey(userId);
1580             if (index < 0) {
1581                 // this generally shouldn't occur, but might be possible due to race conditions
1582                 // on when we are notified of new users
1583                 Log.w(TAG, mName + " provider saw user " + userId + " unexpectedly");
1584                 onEnabledChanged(userId);
1585                 index = mEnabled.indexOfKey(userId);
1586             }
1587 
1588             return mEnabled.valueAt(index);
1589         }
1590     }
1591 
1592     /**
1593      * Returns true if this provider is visible to the current caller (whether called from a binder
1594      * thread or not). If a provider isn't visible, then all APIs return the same data they would if
1595      * the provider didn't exist (i.e. the caller can't see or use the provider).
1596      *
1597      * <p>This method doesn't require any permissions, but uses permissions to determine which
1598      * subset of providers are visible.
1599      */
1600     @SuppressLint("AndroidFrameworkRequiresPermission")
1601     public boolean isVisibleToCaller() {
1602         for (String permission : mRequiredPermissions) {
1603             if (mContext.checkCallingOrSelfPermission(permission) != PERMISSION_GRANTED) {
1604                 return false;
1605             }
1606         }
1607         return true;
1608     }
1609 
1610     public void addEnabledListener(ProviderEnabledListener listener) {
1611         synchronized (mMultiplexerLock) {
1612             Preconditions.checkState(mState != STATE_STOPPED);
1613             mEnabledListeners.add(listener);
1614         }
1615     }
1616 
1617     public void removeEnabledListener(ProviderEnabledListener listener) {
1618         synchronized (mMultiplexerLock) {
1619             Preconditions.checkState(mState != STATE_STOPPED);
1620             mEnabledListeners.remove(listener);
1621         }
1622     }
1623 
1624     /** Add a {@link IProviderRequestListener}. */
1625     public void addProviderRequestListener(IProviderRequestListener listener) {
1626         mProviderRequestListeners.add(listener);
1627     }
1628 
1629     /** Remove a {@link IProviderRequestListener}. */
1630     public void removeProviderRequestListener(IProviderRequestListener listener) {
1631         mProviderRequestListeners.remove(listener);
1632     }
1633 
1634     public void setRealProvider(@Nullable AbstractLocationProvider provider) {
1635         synchronized (mMultiplexerLock) {
1636             Preconditions.checkState(mState != STATE_STOPPED);
1637 
1638             final long identity = Binder.clearCallingIdentity();
1639             try {
1640                 mProvider.setRealProvider(provider);
1641             } finally {
1642                 Binder.restoreCallingIdentity(identity);
1643             }
1644         }
1645     }
1646 
1647     public void setMockProvider(@Nullable MockLocationProvider provider) {
1648         synchronized (mMultiplexerLock) {
1649             Preconditions.checkState(mState != STATE_STOPPED);
1650 
1651             EVENT_LOG.logProviderMocked(mName, provider != null);
1652 
1653             final long identity = Binder.clearCallingIdentity();
1654             try {
1655                 mProvider.setMockProvider(provider);
1656             } finally {
1657                 Binder.restoreCallingIdentity(identity);
1658             }
1659 
1660             // when removing a mock provider, also clear any mock last locations and reset the
1661             // location fudger. the mock provider could have been used to infer the current
1662             // location fudger offsets.
1663             if (provider == null) {
1664                 final int lastLocationSize = mLastLocations.size();
1665                 for (int i = 0; i < lastLocationSize; i++) {
1666                     mLastLocations.valueAt(i).clearMock();
1667                 }
1668 
1669                 mLocationFudger.resetOffsets();
1670             }
1671         }
1672     }
1673 
1674     public void setMockProviderAllowed(boolean enabled) {
1675         synchronized (mMultiplexerLock) {
1676             if (!mProvider.isMock()) {
1677                 throw new IllegalArgumentException(mName + " provider is not a test provider");
1678             }
1679 
1680             final long identity = Binder.clearCallingIdentity();
1681             try {
1682                 mProvider.setMockProviderAllowed(enabled);
1683             } finally {
1684                 Binder.restoreCallingIdentity(identity);
1685             }
1686         }
1687     }
1688 
1689     public void setMockProviderLocation(Location location) {
1690         synchronized (mMultiplexerLock) {
1691             if (!mProvider.isMock()) {
1692                 throw new IllegalArgumentException(mName + " provider is not a test provider");
1693             }
1694 
1695             String locationProvider = location.getProvider();
1696             if (!TextUtils.isEmpty(locationProvider) && !mName.equals(locationProvider)) {
1697                 // The location has an explicit provider that is different from the mock
1698                 // provider name. The caller may be trying to fool us via b/33091107.
1699                 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
1700                         mName + "!=" + locationProvider);
1701             }
1702 
1703             final long identity = Binder.clearCallingIdentity();
1704             try {
1705                 mProvider.setMockProviderLocation(location);
1706             } finally {
1707                 Binder.restoreCallingIdentity(identity);
1708             }
1709         }
1710     }
1711 
1712     @Nullable public Location getLastLocation(LastLocationRequest request,
1713             CallerIdentity identity, @PermissionLevel int permissionLevel) {
1714         request = calculateLastLocationRequest(request, identity);
1715 
1716         if (!isActive(request.isBypass(), identity)) {
1717             return null;
1718         }
1719 
1720         // lastly - note app ops
1721         if (!mAppOpsHelper.noteOpNoThrow(LocationPermissions.asAppOp(permissionLevel),
1722                 identity)) {
1723             return null;
1724         }
1725 
1726         Location location = getPermittedLocation(
1727                 getLastLocationUnsafe(
1728                         identity.getUserId(),
1729                         permissionLevel,
1730                         request.isBypass(),
1731                         Long.MAX_VALUE),
1732                 permissionLevel);
1733 
1734         if (location != null && identity.getPid() == Process.myPid()) {
1735             // if delivering to the same process, make a copy of the location first (since
1736             // location is mutable)
1737             location = new Location(location);
1738         }
1739 
1740         return location;
1741     }
1742 
1743     private LastLocationRequest calculateLastLocationRequest(LastLocationRequest baseRequest,
1744             CallerIdentity identity) {
1745         LastLocationRequest.Builder builder = new LastLocationRequest.Builder(baseRequest);
1746 
1747         boolean locationSettingsIgnored = baseRequest.isLocationSettingsIgnored();
1748         if (locationSettingsIgnored) {
1749             // if we are not currently allowed use location settings ignored, disable it
1750             if (!mSettingsHelper.getIgnoreSettingsAllowlist().contains(
1751                     identity.getPackageName(), identity.getAttributionTag())
1752                     && !mLocationManagerInternal.isProvider(null, identity)) {
1753                 locationSettingsIgnored = false;
1754             }
1755 
1756             builder.setLocationSettingsIgnored(locationSettingsIgnored);
1757         }
1758 
1759         boolean adasGnssBypass = baseRequest.isAdasGnssBypass();
1760         if (adasGnssBypass) {
1761             // if we are not currently allowed use adas gnss bypass, disable it
1762             if (!GPS_PROVIDER.equals(mName)) {
1763                 Log.e(TAG, "adas gnss bypass request received in non-gps provider");
1764                 adasGnssBypass = false;
1765             } else if (!mUserHelper.isCurrentUserId(identity.getUserId())) {
1766                 adasGnssBypass = false;
1767             } else if (!mLocationSettings.getUserSettings(
1768                     identity.getUserId()).isAdasGnssLocationEnabled()) {
1769                 adasGnssBypass = false;
1770             } else if (!mSettingsHelper.getAdasAllowlist().contains(
1771                     identity.getPackageName(), identity.getAttributionTag())) {
1772                 adasGnssBypass = false;
1773             }
1774 
1775             builder.setAdasGnssBypass(adasGnssBypass);
1776         }
1777 
1778         return builder.build();
1779     }
1780 
1781     /**
1782      * This function does not perform any permissions or safety checks, by calling it you are
1783      * committing to performing all applicable checks yourself. This always returns a "fine"
1784      * location, even if the permissionLevel is coarse. You are responsible for coarsening the
1785      * location if necessary.
1786      */
1787     @Nullable public Location getLastLocationUnsafe(int userId,
1788             @PermissionLevel int permissionLevel, boolean isBypass,
1789             long maximumAgeMs) {
1790         if (userId == UserHandle.USER_ALL) {
1791             // find the most recent location across all users
1792             Location lastLocation = null;
1793             final int[] runningUserIds = mUserHelper.getRunningUserIds();
1794             for (int i = 0; i < runningUserIds.length; i++) {
1795                 Location next = getLastLocationUnsafe(runningUserIds[i], permissionLevel,
1796                         isBypass, maximumAgeMs);
1797                 if (lastLocation == null || (next != null && next.getElapsedRealtimeNanos()
1798                         > lastLocation.getElapsedRealtimeNanos())) {
1799                     lastLocation = next;
1800                 }
1801             }
1802             return lastLocation;
1803         } else if (userId == USER_CURRENT) {
1804             return getLastLocationUnsafe(mUserHelper.getCurrentUserId(), permissionLevel,
1805                     isBypass, maximumAgeMs);
1806         }
1807 
1808         Preconditions.checkArgument(userId >= 0);
1809 
1810         Location location;
1811         synchronized (mMultiplexerLock) {
1812             Preconditions.checkState(mState != STATE_STOPPED);
1813             LastLocation lastLocation = mLastLocations.get(userId);
1814             if (lastLocation == null) {
1815                 location = null;
1816             } else {
1817                 location = lastLocation.get(permissionLevel, isBypass);
1818             }
1819         }
1820 
1821         if (location == null) {
1822             return null;
1823         }
1824 
1825         if (location.getElapsedRealtimeAgeMillis() > maximumAgeMs) {
1826             return null;
1827         }
1828 
1829         return location;
1830     }
1831 
1832     public void injectLastLocation(Location location, int userId) {
1833         synchronized (mMultiplexerLock) {
1834             Preconditions.checkState(mState != STATE_STOPPED);
1835             if (getLastLocationUnsafe(userId, PERMISSION_FINE, false, Long.MAX_VALUE) == null) {
1836                 setLastLocation(location, userId);
1837             }
1838         }
1839     }
1840 
1841     private void setLastLocation(Location location, int userId) {
1842         if (userId == UserHandle.USER_ALL) {
1843             final int[] runningUserIds = mUserHelper.getRunningUserIds();
1844             for (int i = 0; i < runningUserIds.length; i++) {
1845                 setLastLocation(location, runningUserIds[i]);
1846             }
1847             return;
1848         } else if (userId == USER_CURRENT) {
1849             setLastLocation(location, mUserHelper.getCurrentUserId());
1850             return;
1851         }
1852 
1853         Preconditions.checkArgument(userId >= 0);
1854 
1855         synchronized (mMultiplexerLock) {
1856             LastLocation lastLocation = mLastLocations.get(userId);
1857             if (lastLocation == null) {
1858                 lastLocation = new LastLocation();
1859                 mLastLocations.put(userId, lastLocation);
1860             }
1861 
1862             if (isEnabled(userId)) {
1863                 lastLocation.set(location);
1864             }
1865             lastLocation.setBypass(location);
1866         }
1867     }
1868 
1869     @Nullable public ICancellationSignal getCurrentLocation(LocationRequest request,
1870             CallerIdentity identity, int permissionLevel, ILocationCallback callback) {
1871         if (request.getDurationMillis() > MAX_GET_CURRENT_LOCATION_TIMEOUT_MS) {
1872             request = new LocationRequest.Builder(request)
1873                     .setDurationMillis(MAX_GET_CURRENT_LOCATION_TIMEOUT_MS)
1874                     .build();
1875         }
1876 
1877         GetCurrentLocationListenerRegistration registration =
1878                 new GetCurrentLocationListenerRegistration(
1879                         request,
1880                         identity,
1881                         new GetCurrentLocationTransport(callback),
1882                         permissionLevel);
1883 
1884         synchronized (mMultiplexerLock) {
1885             Preconditions.checkState(mState != STATE_STOPPED);
1886             final long ident = Binder.clearCallingIdentity();
1887             try {
1888                 putRegistration(callback.asBinder(), registration);
1889                 if (!registration.isActive()) {
1890                     // if the registration never activated, fail it immediately
1891                     registration.deliverNull();
1892                 }
1893             } finally {
1894                 Binder.restoreCallingIdentity(ident);
1895             }
1896         }
1897 
1898         ICancellationSignal cancelTransport = CancellationSignal.createTransport();
1899         CancellationSignal.fromTransport(cancelTransport)
1900                 .setOnCancelListener(
1901                         () -> {
1902                             final long ident = Binder.clearCallingIdentity();
1903                             try {
1904                                 removeRegistration(callback.asBinder(), registration);
1905                             } catch (RuntimeException e) {
1906                                 // since this is within a oneway binder transaction there is nowhere
1907                                 // for exceptions to go - move onto another thread to crash system
1908                                 // server so we find out about it
1909                                 FgThread.getExecutor().execute(() -> {
1910                                     throw new AssertionError(e);
1911                                 });
1912                                 throw e;
1913                             } finally {
1914                                 Binder.restoreCallingIdentity(ident);
1915                             }
1916 
1917                         });
1918         return cancelTransport;
1919     }
1920 
1921     public void sendExtraCommand(int uid, int pid, String command, Bundle extras) {
1922         final long identity = Binder.clearCallingIdentity();
1923         try {
1924             mProvider.getController().sendExtraCommand(uid, pid, command, extras);
1925         } finally {
1926             Binder.restoreCallingIdentity(identity);
1927         }
1928     }
1929 
1930     public void registerLocationRequest(LocationRequest request, CallerIdentity identity,
1931             @PermissionLevel int permissionLevel, ILocationListener listener) {
1932         LocationListenerRegistration registration = new LocationListenerRegistration(
1933                 request,
1934                 identity,
1935                 new LocationListenerTransport(listener),
1936                 permissionLevel);
1937 
1938         synchronized (mMultiplexerLock) {
1939             Preconditions.checkState(mState != STATE_STOPPED);
1940             final long ident = Binder.clearCallingIdentity();
1941             try {
1942                 putRegistration(listener.asBinder(), registration);
1943             } finally {
1944                 Binder.restoreCallingIdentity(ident);
1945             }
1946         }
1947     }
1948 
1949     public void registerLocationRequest(LocationRequest request, CallerIdentity callerIdentity,
1950             @PermissionLevel int permissionLevel, PendingIntent pendingIntent) {
1951         LocationPendingIntentRegistration registration = new LocationPendingIntentRegistration(
1952                 request,
1953                 callerIdentity,
1954                 new LocationPendingIntentTransport(mContext, pendingIntent),
1955                 permissionLevel);
1956 
1957         synchronized (mMultiplexerLock) {
1958             Preconditions.checkState(mState != STATE_STOPPED);
1959             final long identity = Binder.clearCallingIdentity();
1960             try {
1961                 putRegistration(pendingIntent, registration);
1962             } finally {
1963                 Binder.restoreCallingIdentity(identity);
1964             }
1965         }
1966     }
1967 
1968     public void flush(ILocationListener listener, int requestCode) {
1969         final long identity = Binder.clearCallingIdentity();
1970         try {
1971             boolean flushed = updateRegistration(listener.asBinder(), registration -> {
1972                 registration.flush(requestCode);
1973                 return false;
1974             });
1975             if (!flushed) {
1976                 throw new IllegalArgumentException("unregistered listener cannot be flushed");
1977             }
1978         } finally {
1979             Binder.restoreCallingIdentity(identity);
1980         }
1981     }
1982 
1983     public void flush(PendingIntent pendingIntent, int requestCode) {
1984         final long identity = Binder.clearCallingIdentity();
1985         try {
1986             boolean flushed = updateRegistration(pendingIntent, registration -> {
1987                 registration.flush(requestCode);
1988                 return false;
1989             });
1990             if (!flushed) {
1991                 throw new IllegalArgumentException(
1992                         "unregistered pending intent cannot be flushed");
1993             }
1994         } finally {
1995             Binder.restoreCallingIdentity(identity);
1996         }
1997     }
1998 
1999     public void unregisterLocationRequest(ILocationListener listener) {
2000         synchronized (mMultiplexerLock) {
2001             Preconditions.checkState(mState != STATE_STOPPED);
2002             final long identity = Binder.clearCallingIdentity();
2003             try {
2004                 removeRegistration(listener.asBinder());
2005             } finally {
2006                 Binder.restoreCallingIdentity(identity);
2007             }
2008         }
2009     }
2010 
2011     public void unregisterLocationRequest(PendingIntent pendingIntent) {
2012         synchronized (mMultiplexerLock) {
2013             Preconditions.checkState(mState != STATE_STOPPED);
2014             final long identity = Binder.clearCallingIdentity();
2015             try {
2016                 removeRegistration(pendingIntent);
2017             } finally {
2018                 Binder.restoreCallingIdentity(identity);
2019             }
2020         }
2021     }
2022 
2023     @GuardedBy("mMultiplexerLock")
2024     @Override
2025     protected void onRegister() {
2026         mSettingsHelper.addOnBackgroundThrottleIntervalChangedListener(
2027                 mBackgroundThrottleIntervalChangedListener);
2028         mSettingsHelper.addOnBackgroundThrottlePackageWhitelistChangedListener(
2029                 mBackgroundThrottlePackageWhitelistChangedListener);
2030         mSettingsHelper.addOnLocationPackageBlacklistChangedListener(
2031                 mLocationPackageBlacklistChangedListener);
2032         mSettingsHelper.addAdasAllowlistChangedListener(
2033                 mAdasPackageAllowlistChangedListener);
2034         mSettingsHelper.addIgnoreSettingsAllowlistChangedListener(
2035                 mIgnoreSettingsPackageWhitelistChangedListener);
2036         mLocationPermissionsHelper.addListener(mLocationPermissionsListener);
2037         mAppForegroundHelper.addListener(mAppForegroundChangedListener);
2038         mLocationPowerSaveModeHelper.addListener(mLocationPowerSaveModeChangedListener);
2039         mScreenInteractiveHelper.addListener(mScreenInteractiveChangedListener);
2040         mPackageResetHelper.register(mPackageResetResponder);
2041     }
2042 
2043     @GuardedBy("mMultiplexerLock")
2044     @Override
2045     protected void onUnregister() {
2046         mSettingsHelper.removeOnBackgroundThrottleIntervalChangedListener(
2047                 mBackgroundThrottleIntervalChangedListener);
2048         mSettingsHelper.removeOnBackgroundThrottlePackageWhitelistChangedListener(
2049                 mBackgroundThrottlePackageWhitelistChangedListener);
2050         mSettingsHelper.removeOnLocationPackageBlacklistChangedListener(
2051                 mLocationPackageBlacklistChangedListener);
2052         mSettingsHelper.removeAdasAllowlistChangedListener(mAdasPackageAllowlistChangedListener);
2053         mSettingsHelper.removeIgnoreSettingsAllowlistChangedListener(
2054                 mIgnoreSettingsPackageWhitelistChangedListener);
2055         mLocationPermissionsHelper.removeListener(mLocationPermissionsListener);
2056         mAppForegroundHelper.removeListener(mAppForegroundChangedListener);
2057         mLocationPowerSaveModeHelper.removeListener(mLocationPowerSaveModeChangedListener);
2058         mScreenInteractiveHelper.removeListener(mScreenInteractiveChangedListener);
2059         mPackageResetHelper.unregister(mPackageResetResponder);
2060     }
2061 
2062     @GuardedBy("mMultiplexerLock")
2063     @Override
2064     protected void onRegistrationAdded(Object key, Registration registration) {
2065         mLocationUsageLogger.logLocationApiUsage(
2066                 LocationStatsEnums.USAGE_STARTED,
2067                 LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
2068                 registration.getIdentity().getPackageName(),
2069                 registration.getIdentity().getAttributionTag(),
2070                 mName,
2071                 registration.getRequest(),
2072                 key instanceof PendingIntent,
2073                 /* geofence= */ key instanceof IBinder,
2074                 null, registration.isForeground());
2075     }
2076 
2077     // TODO: remove suppression when GuardedBy analysis can recognize lock from super class
2078     @SuppressWarnings("GuardedBy")
2079     @GuardedBy("mMultiplexerLock")
2080     @Override
2081     protected void onRegistrationReplaced(Object oldKey, Registration oldRegistration,
2082             Object newKey, Registration newRegistration) {
2083         // by saving the last delivered location state we are able to potentially delay the
2084         // resulting provider request longer and save additional power
2085         newRegistration.setLastDeliveredLocation(oldRegistration.getLastDeliveredLocation());
2086         super.onRegistrationReplaced(oldKey, oldRegistration, newKey, newRegistration);
2087     }
2088 
2089     @GuardedBy("mMultiplexerLock")
2090     @Override
2091     protected void onRegistrationRemoved(Object key, Registration registration) {
2092         mLocationUsageLogger.logLocationApiUsage(
2093                 LocationStatsEnums.USAGE_ENDED,
2094                 LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
2095                 registration.getIdentity().getPackageName(),
2096                 registration.getIdentity().getAttributionTag(),
2097                 mName,
2098                 registration.getRequest(),
2099                 key instanceof PendingIntent,
2100                 /* geofence= */ key instanceof IBinder,
2101                 null, registration.isForeground());
2102     }
2103 
2104     @GuardedBy("mMultiplexerLock")
2105     @Override
2106     protected boolean registerWithService(ProviderRequest request,
2107             Collection<Registration> registrations) {
2108         if (!request.isActive()) {
2109             // the default request is already an empty request, no need to register this
2110             return true;
2111         }
2112 
2113         return reregisterWithService(ProviderRequest.EMPTY_REQUEST, request, registrations);
2114     }
2115 
2116     @GuardedBy("mMultiplexerLock")
2117     @Override
2118     protected boolean reregisterWithService(ProviderRequest oldRequest,
2119             ProviderRequest newRequest, Collection<Registration> registrations) {
2120         // calculate how long the new request should be delayed before sending it off to the
2121         // provider, under the assumption that once we send the request off, the provider will
2122         // immediately attempt to deliver a new location satisfying that request.
2123         long delayMs;
2124         if (!oldRequest.isBypass() && newRequest.isBypass()) {
2125             delayMs = 0;
2126         } else if (newRequest.getIntervalMillis() > oldRequest.getIntervalMillis()) {
2127             // if the interval has increased, tell the provider immediately, so it can save power
2128             // (even though technically this could burn extra power in the short term by producing
2129             // an extra location - the provider itself is free to detect an increasing interval and
2130             // delay its own location)
2131             delayMs = 0;
2132         } else {
2133             delayMs = calculateRequestDelayMillis(newRequest.getIntervalMillis(), registrations);
2134         }
2135 
2136         // the delay should never exceed the new interval
2137         Preconditions.checkState(delayMs >= 0 && delayMs <= newRequest.getIntervalMillis());
2138 
2139         if (delayMs < MIN_REQUEST_DELAY_MS) {
2140             setProviderRequest(newRequest);
2141         } else {
2142             if (D) {
2143                 Log.d(TAG, mName + " provider delaying request update " + newRequest + " by "
2144                         + TimeUtils.formatDuration(delayMs));
2145             }
2146 
2147             if (mDelayedRegister != null) {
2148                 mAlarmHelper.cancel(mDelayedRegister);
2149                 mDelayedRegister = null;
2150             }
2151 
2152             mDelayedRegister = new OnAlarmListener() {
2153                 @Override
2154                 public void onAlarm() {
2155                     synchronized (mMultiplexerLock) {
2156                         if (mDelayedRegister == this) {
2157                             mDelayedRegister = null;
2158                             setProviderRequest(newRequest);
2159                         }
2160                     }
2161                 }
2162             };
2163             // Set WorkSource to null in order to ensure the alarm wakes up the device even when it
2164             // is idle. Do this when the cost of waking up the device is less than the power cost of
2165             // not performing the actions set off by the alarm, such as unregistering a location
2166             // request.
2167             mAlarmHelper.setDelayedAlarm(delayMs, mDelayedRegister, null);
2168         }
2169 
2170         return true;
2171     }
2172 
2173     @GuardedBy("mMultiplexerLock")
2174     @Override
2175     protected void unregisterWithService() {
2176         setProviderRequest(ProviderRequest.EMPTY_REQUEST);
2177     }
2178 
2179     @GuardedBy("mMultiplexerLock")
2180     void setProviderRequest(ProviderRequest request) {
2181         if (mDelayedRegister != null) {
2182             mAlarmHelper.cancel(mDelayedRegister);
2183             mDelayedRegister = null;
2184         }
2185 
2186         EVENT_LOG.logProviderUpdateRequest(mName, request);
2187         if (D) {
2188             Log.d(TAG, mName + " provider request changed to " + request);
2189         }
2190         mProvider.getController().setRequest(request);
2191 
2192         FgThread.getHandler().post(() -> {
2193             for (IProviderRequestListener listener : mProviderRequestListeners) {
2194                 try {
2195                     listener.onProviderRequestChanged(mName, request);
2196                 } catch (RemoteException e) {
2197                     mProviderRequestListeners.remove(listener);
2198                 }
2199             }
2200         });
2201     }
2202 
2203     @GuardedBy("mMultiplexerLock")
2204     @Override
2205     protected boolean isActive(Registration registration) {
2206         if (!registration.isPermitted()) {
2207             return false;
2208         }
2209 
2210         boolean isBypass = registration.getRequest().isBypass();
2211         if (!isActive(isBypass, registration.getIdentity())) {
2212             return false;
2213         }
2214 
2215         if (!isBypass) {
2216             switch (mLocationPowerSaveModeHelper.getLocationPowerSaveMode()) {
2217                 case LOCATION_MODE_FOREGROUND_ONLY:
2218                     if (!registration.isForeground()) {
2219                         return false;
2220                     }
2221                     break;
2222                 case LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF:
2223                     if (!GPS_PROVIDER.equals(mName)) {
2224                         break;
2225                     }
2226                     // fall through
2227                 case LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF:
2228                     // fall through
2229                 case LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF:
2230                     if (!mScreenInteractiveHelper.isInteractive()) {
2231                         return false;
2232                     }
2233                     break;
2234                 case LOCATION_MODE_NO_CHANGE:
2235                     // fall through
2236                 default:
2237                     break;
2238             }
2239         }
2240 
2241         return true;
2242     }
2243 
2244     private boolean isActive(boolean isBypass, CallerIdentity identity) {
2245         if (identity.isSystemServer()) {
2246             if (!isBypass) {
2247                 if (!isEnabled(mUserHelper.getCurrentUserId())) {
2248                     return false;
2249                 }
2250             }
2251         } else {
2252             if (!isBypass) {
2253                 if (!isEnabled(identity.getUserId())) {
2254                     return false;
2255                 }
2256                 if (!mUserHelper.isVisibleUserId(identity.getUserId())) {
2257                     return false;
2258                 }
2259             }
2260             if (mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
2261                     identity.getPackageName())) {
2262                 return false;
2263             }
2264         }
2265 
2266         return true;
2267     }
2268 
2269     @GuardedBy("mMultiplexerLock")
2270     @Override
2271     protected ProviderRequest mergeRegistrations(Collection<Registration> registrations) {
2272         long intervalMs = ProviderRequest.INTERVAL_DISABLED;
2273         int quality = LocationRequest.QUALITY_LOW_POWER;
2274         long maxUpdateDelayMs = Long.MAX_VALUE;
2275         boolean adasGnssBypass = false;
2276         boolean locationSettingsIgnored = false;
2277         boolean lowPower = true;
2278 
2279         for (Registration registration : registrations) {
2280             LocationRequest request = registration.getRequest();
2281 
2282             // passive requests do not contribute to the provider request, and passive requests
2283             // must handle the batching parameters of non-passive requests
2284             if (request.getIntervalMillis() == LocationRequest.PASSIVE_INTERVAL) {
2285                 continue;
2286             }
2287 
2288             intervalMs = min(request.getIntervalMillis(), intervalMs);
2289             quality = min(request.getQuality(), quality);
2290             maxUpdateDelayMs = min(request.getMaxUpdateDelayMillis(), maxUpdateDelayMs);
2291             adasGnssBypass |= request.isAdasGnssBypass();
2292             locationSettingsIgnored |= request.isLocationSettingsIgnored();
2293             lowPower &= request.isLowPower();
2294         }
2295 
2296         if (intervalMs == ProviderRequest.INTERVAL_DISABLED) {
2297             return ProviderRequest.EMPTY_REQUEST;
2298         }
2299 
2300         if (maxUpdateDelayMs / 2 < intervalMs) {
2301             // reduces churn if only the batching parameter has changed
2302             maxUpdateDelayMs = 0;
2303         }
2304 
2305         // calculate who to blame for power in a somewhat arbitrary fashion. we pick a threshold
2306         // interval slightly higher that the minimum interval, and spread the blame across all
2307         // contributing registrations under that threshold (since worksource does not allow us to
2308         // represent differing power blame ratios).
2309         long thresholdIntervalMs;
2310         try {
2311             thresholdIntervalMs = Math.multiplyExact(Math.addExact(intervalMs, 1000) / 2, 3);
2312         } catch (ArithmeticException e) {
2313             // check for and handle overflow by setting to one below the passive interval so passive
2314             // requests are automatically skipped
2315             thresholdIntervalMs = LocationRequest.PASSIVE_INTERVAL - 1;
2316         }
2317 
2318         WorkSource workSource = new WorkSource();
2319         for (Registration registration : registrations) {
2320             if (registration.getRequest().getIntervalMillis() <= thresholdIntervalMs) {
2321                 workSource.add(registration.getRequest().getWorkSource());
2322             }
2323         }
2324 
2325         return new ProviderRequest.Builder()
2326                 .setIntervalMillis(intervalMs)
2327                 .setQuality(quality)
2328                 .setMaxUpdateDelayMillis(maxUpdateDelayMs)
2329                 .setAdasGnssBypass(adasGnssBypass)
2330                 .setLocationSettingsIgnored(locationSettingsIgnored)
2331                 .setLowPower(lowPower)
2332                 .setWorkSource(workSource)
2333                 .build();
2334     }
2335 
2336     @GuardedBy("mMultiplexerLock")
2337     protected long calculateRequestDelayMillis(long newIntervalMs,
2338             Collection<Registration> registrations) {
2339         // calculate the minimum delay across all registrations, ensuring that it is not more than
2340         // the requested interval
2341         long delayMs = newIntervalMs;
2342         for (Registration registration : registrations) {
2343             if (delayMs == 0) {
2344                 break;
2345             }
2346 
2347             LocationRequest locationRequest = registration.getRequest();
2348             Location last = registration.getLastDeliveredLocation();
2349 
2350             if (last == null && !locationRequest.isLocationSettingsIgnored()) {
2351                 // if this request has never gotten any location and it's not ignoring location
2352                 // settings, then we pretend that this request has gotten the last applicable cached
2353                 // location for our calculations instead. this prevents spammy add/remove behavior
2354                 last = getLastLocationUnsafe(
2355                         registration.getIdentity().getUserId(),
2356                         registration.getPermissionLevel(),
2357                         false,
2358                         locationRequest.getIntervalMillis());
2359             }
2360 
2361             long registrationDelayMs;
2362             if (last == null) {
2363                 // if this request has never gotten any location then there's no delay
2364                 registrationDelayMs = 0;
2365             } else {
2366                 // otherwise the delay is the amount of time until the next location is expected
2367                 registrationDelayMs = max(0,
2368                         locationRequest.getIntervalMillis() - last.getElapsedRealtimeAgeMillis());
2369             }
2370 
2371             delayMs = min(delayMs, registrationDelayMs);
2372         }
2373 
2374         return delayMs;
2375     }
2376 
2377     private void onUserChanged(int userId, int change) {
2378         synchronized (mMultiplexerLock) {
2379             if (mState == STATE_STOPPED) {
2380                 return;
2381             }
2382 
2383             switch (change) {
2384                 case UserListener.CURRENT_USER_CHANGED:
2385                     // current user changes affect whether system server location requests are
2386                     // allowed to access location, and visibility changes affect whether any given
2387                     // user may access location.
2388                 case UserListener.USER_VISIBILITY_CHANGED:
2389                     updateRegistrations(
2390                             registration -> registration.getIdentity().getUserId() == userId);
2391                     break;
2392                 case UserListener.USER_STARTED:
2393                     onUserStarted(userId);
2394                     break;
2395                 case UserListener.USER_STOPPED:
2396                     onUserStopped(userId);
2397                     break;
2398             }
2399         }
2400     }
2401 
2402     private void onLocationUserSettingsChanged(int userId, LocationUserSettings oldSettings,
2403             LocationUserSettings newSettings) {
2404         if (oldSettings.isAdasGnssLocationEnabled() != newSettings.isAdasGnssLocationEnabled()) {
2405             updateRegistrations(
2406                     registration -> registration.onAdasGnssLocationEnabledChanged(userId));
2407         }
2408     }
2409 
2410     private void onLocationEnabledChanged(int userId) {
2411         synchronized (mMultiplexerLock) {
2412             if (mState == STATE_STOPPED) {
2413                 return;
2414             }
2415 
2416             onEnabledChanged(userId);
2417         }
2418     }
2419 
2420     private void onScreenInteractiveChanged(boolean screenInteractive) {
2421         switch (mLocationPowerSaveModeHelper.getLocationPowerSaveMode()) {
2422             case LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF:
2423                 if (!GPS_PROVIDER.equals(mName)) {
2424                     break;
2425                 }
2426                 // fall through
2427             case LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF:
2428                 // fall through
2429             case LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF:
2430                 updateRegistrations(registration -> true);
2431                 break;
2432             default:
2433                 break;
2434         }
2435     }
2436 
2437     private void onBackgroundThrottlePackageWhitelistChanged() {
2438         updateRegistrations(Registration::onProviderLocationRequestChanged);
2439     }
2440 
2441     private void onBackgroundThrottleIntervalChanged() {
2442         updateRegistrations(Registration::onProviderLocationRequestChanged);
2443     }
2444 
2445     private void onLocationPowerSaveModeChanged(@LocationPowerSaveMode int locationPowerSaveMode) {
2446         // this is rare, just assume everything has changed to keep it simple
2447         updateRegistrations(registration -> true);
2448     }
2449 
2450     private void onAppForegroundChanged(int uid, boolean foreground) {
2451         updateRegistrations(registration -> registration.onForegroundChanged(uid, foreground));
2452     }
2453 
2454     private void onAdasAllowlistChanged() {
2455         updateRegistrations(Registration::onProviderLocationRequestChanged);
2456     }
2457 
2458     private void onIgnoreSettingsWhitelistChanged() {
2459         updateRegistrations(Registration::onProviderLocationRequestChanged);
2460     }
2461 
2462     private void onLocationPackageBlacklistChanged(int userId) {
2463         updateRegistrations(registration -> registration.getIdentity().getUserId() == userId);
2464     }
2465 
2466     private void onLocationPermissionsChanged(@Nullable String packageName) {
2467         updateRegistrations(
2468                 registration -> registration.onLocationPermissionsChanged(packageName));
2469     }
2470 
2471     private void onLocationPermissionsChanged(int uid) {
2472         updateRegistrations(registration -> registration.onLocationPermissionsChanged(uid));
2473     }
2474 
2475     private void onPackageReset(String packageName) {
2476         updateRegistrations(
2477                 registration -> {
2478                     if (registration.getIdentity().getPackageName().equals(
2479                             packageName)) {
2480                         registration.remove();
2481                     }
2482 
2483                     return false;
2484                 });
2485     }
2486 
2487     private boolean isResetableForPackage(String packageName) {
2488         // invoked to find out if the given package has any state that can be "force quit"
2489         return findRegistration(
2490                 registration -> registration.getIdentity().getPackageName().equals(packageName));
2491     }
2492 
2493     @GuardedBy("mMultiplexerLock")
2494     @Override
2495     public void onStateChanged(
2496             AbstractLocationProvider.State oldState, AbstractLocationProvider.State newState) {
2497         if (oldState.allowed != newState.allowed) {
2498             onEnabledChanged(UserHandle.USER_ALL);
2499         }
2500 
2501         if (!Objects.equals(oldState.properties, newState.properties)) {
2502             updateRegistrations(Registration::onProviderPropertiesChanged);
2503         }
2504 
2505         if (mStateChangedListener != null) {
2506             StateChangedListener listener = mStateChangedListener;
2507             FgThread.getExecutor().execute(
2508                     () -> listener.onStateChanged(mName, oldState, newState));
2509         }
2510     }
2511 
2512     @GuardedBy("mMultiplexerLock")
2513     @Override
2514     public void onReportLocation(LocationResult locationResult) {
2515         LocationResult filtered;
2516         if (mPassiveManager != null) {
2517             filtered = locationResult.filter(location -> {
2518                 if (!location.isMock()) {
2519                     if (location.getLatitude() == 0 && location.getLongitude() == 0) {
2520                         Log.e(TAG, "blocking 0,0 location from " + mName + " provider");
2521                         return false;
2522                     }
2523                 }
2524 
2525                 if (!location.isComplete()) {
2526                     Log.e(TAG, "blocking incomplete location from " + mName + " provider");
2527                     return false;
2528                 }
2529 
2530                 return true;
2531             });
2532 
2533             if (filtered == null) {
2534                 return;
2535             }
2536 
2537             // don't log location received for passive provider because it's spammy
2538             EVENT_LOG.logProviderReceivedLocations(mName, filtered.size());
2539         } else {
2540             // passive provider should get already filtered results as input
2541             filtered = locationResult;
2542         }
2543 
2544         // check for non-monotonic locations if we're not the passive manager. the passive manager
2545         // is much more likely to see non-monotonic locations since it gets locations from all
2546         // providers, so this error log is not very useful there.
2547         if (mPassiveManager != null) {
2548             Location last = getLastLocationUnsafe(USER_CURRENT, PERMISSION_FINE, true,
2549                     Long.MAX_VALUE);
2550             if (last != null && locationResult.get(0).getElapsedRealtimeNanos()
2551                     < last.getElapsedRealtimeNanos()) {
2552                 Log.e(TAG, "non-monotonic location received from " + mName + " provider");
2553             }
2554         }
2555 
2556         // update last location
2557         setLastLocation(filtered.getLastLocation(), UserHandle.USER_ALL);
2558 
2559         // attempt listener delivery
2560         deliverToListeners(registration -> {
2561             return registration.acceptLocationChange(filtered);
2562         });
2563 
2564         // notify passive provider
2565         if (mPassiveManager != null) {
2566             mPassiveManager.updateLocation(filtered);
2567         }
2568     }
2569 
2570     @GuardedBy("mMultiplexerLock")
2571     private void onUserStarted(int userId) {
2572         if (userId == UserHandle.USER_NULL) {
2573             return;
2574         }
2575 
2576         if (userId == UserHandle.USER_ALL) {
2577             // clear the user's prior enabled state to prevent broadcast of enabled state change
2578             mEnabled.clear();
2579             onEnabledChanged(UserHandle.USER_ALL);
2580         } else {
2581             Preconditions.checkArgument(userId >= 0);
2582 
2583             // clear the user's prior enabled state to prevent broadcast of enabled state change
2584             mEnabled.delete(userId);
2585             onEnabledChanged(userId);
2586         }
2587     }
2588 
2589     @GuardedBy("mMultiplexerLock")
2590     private void onUserStopped(int userId) {
2591         if (userId == UserHandle.USER_NULL) {
2592             return;
2593         }
2594 
2595         if (userId == UserHandle.USER_ALL) {
2596             mEnabled.clear();
2597             mLastLocations.clear();
2598         } else {
2599             Preconditions.checkArgument(userId >= 0);
2600             mEnabled.delete(userId);
2601             mLastLocations.remove(userId);
2602         }
2603     }
2604 
2605     @GuardedBy("mMultiplexerLock")
2606     private void onEnabledChanged(int userId) {
2607         if (userId == UserHandle.USER_NULL) {
2608             // used during initialization - ignore since many lower level operations (checking
2609             // settings for instance) do not support the null user
2610             return;
2611         } else if (userId == UserHandle.USER_ALL) {
2612             final int[] runningUserIds = mUserHelper.getRunningUserIds();
2613             for (int i = 0; i < runningUserIds.length; i++) {
2614                 onEnabledChanged(runningUserIds[i]);
2615             }
2616             return;
2617         }
2618 
2619         Preconditions.checkArgument(userId >= 0);
2620 
2621         boolean enabled = mState == STATE_STARTED
2622                 && mProvider.getState().allowed
2623                 && mSettingsHelper.isLocationEnabled(userId);
2624 
2625         int index = mEnabled.indexOfKey(userId);
2626         Boolean wasEnabled = index < 0 ? null : mEnabled.valueAt(index);
2627         if (wasEnabled != null && wasEnabled == enabled) {
2628             return;
2629         }
2630 
2631         mEnabled.put(userId, enabled);
2632 
2633         // don't log unknown -> false transitions for brevity
2634         if (wasEnabled != null || enabled) {
2635             if (D) {
2636                 Log.d(TAG, "[u" + userId + "] " + mName + " provider enabled = " + enabled);
2637             }
2638             EVENT_LOG.logProviderEnabled(mName, userId, enabled);
2639         }
2640 
2641         // clear last locations if we become disabled
2642         if (!enabled) {
2643             LastLocation lastLocation = mLastLocations.get(userId);
2644             if (lastLocation != null) {
2645                 lastLocation.clearLocations();
2646             }
2647         }
2648 
2649         // do not send change notifications if we just saw this user for the first time
2650         if (wasEnabled != null) {
2651             // passive provider never get public updates for legacy reasons
2652             if (!PASSIVE_PROVIDER.equals(mName)) {
2653                 Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION)
2654                         .putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName)
2655                         .putExtra(LocationManager.EXTRA_PROVIDER_ENABLED, enabled)
2656                         .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
2657                         .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
2658                 mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
2659             }
2660 
2661             // send updates to internal listeners - since we expect listener changes to be more
2662             // frequent than enabled changes, we use copy-on-read instead of copy-on-write
2663             if (!mEnabledListeners.isEmpty()) {
2664                 ProviderEnabledListener[] listeners = mEnabledListeners.toArray(
2665                         new ProviderEnabledListener[0]);
2666                 FgThread.getHandler().post(() -> {
2667                     for (int i = 0; i < listeners.length; i++) {
2668                         listeners[i].onProviderEnabledChanged(mName, userId, enabled);
2669                     }
2670                 });
2671             }
2672         }
2673 
2674         // update active state of affected registrations
2675         updateRegistrations(registration -> registration.getIdentity().getUserId() == userId);
2676     }
2677 
2678     @Nullable Location getPermittedLocation(@Nullable Location fineLocation,
2679             @PermissionLevel int permissionLevel) {
2680         switch (permissionLevel) {
2681             case PERMISSION_FINE:
2682                 return fineLocation;
2683             case PERMISSION_COARSE:
2684                 return fineLocation != null ? mLocationFudger.createCoarse(fineLocation) : null;
2685             default:
2686                 // shouldn't be possible to have a client added without location permissions
2687                 throw new AssertionError();
2688         }
2689     }
2690 
2691     @Nullable LocationResult getPermittedLocationResult(
2692             @Nullable LocationResult fineLocationResult, @PermissionLevel int permissionLevel) {
2693         switch (permissionLevel) {
2694             case PERMISSION_FINE:
2695                 return fineLocationResult;
2696             case PERMISSION_COARSE:
2697                 return fineLocationResult != null ? mLocationFudger.createCoarse(fineLocationResult)
2698                         : null;
2699             default:
2700                 // shouldn't be possible to have a client added without location permissions
2701                 throw new AssertionError();
2702         }
2703     }
2704 
2705     public void dump(FileDescriptor fd, IndentingPrintWriter ipw, String[] args) {
2706         synchronized (mMultiplexerLock) {
2707             ipw.print(mName);
2708             ipw.print(" provider");
2709             if (mProvider.isMock()) {
2710                 ipw.print(" [mock]");
2711             }
2712             ipw.println(":");
2713             ipw.increaseIndent();
2714 
2715             super.dump(fd, ipw, args);
2716 
2717             int[] userIds = mUserHelper.getRunningUserIds();
2718             for (int userId : userIds) {
2719                 if (userIds.length != 1) {
2720                     ipw.print("user ");
2721                     ipw.print(userId);
2722                     ipw.println(":");
2723                     ipw.increaseIndent();
2724                 }
2725                 ipw.print("last location=");
2726                 ipw.println(getLastLocationUnsafe(userId, PERMISSION_FINE, false, Long.MAX_VALUE));
2727                 ipw.print("enabled=");
2728                 ipw.println(isEnabled(userId));
2729                 if (userIds.length != 1) {
2730                     ipw.decreaseIndent();
2731                 }
2732             }
2733         }
2734 
2735         mProvider.dump(fd, ipw, args);
2736 
2737         ipw.decreaseIndent();
2738     }
2739 
2740     @Override
2741     protected String getServiceState() {
2742         return mProvider.getCurrentRequest().toString();
2743     }
2744 
2745     private static class LastLocation {
2746 
2747         @Nullable private Location mFineLocation;
2748         @Nullable private Location mCoarseLocation;
2749         @Nullable private Location mFineBypassLocation;
2750         @Nullable private Location mCoarseBypassLocation;
2751 
2752         LastLocation() {}
2753 
2754         public void clearMock() {
2755             if (mFineLocation != null && mFineLocation.isMock()) {
2756                 mFineLocation = null;
2757             }
2758             if (mCoarseLocation != null && mCoarseLocation.isMock()) {
2759                 mCoarseLocation = null;
2760             }
2761             if (mFineBypassLocation != null && mFineBypassLocation.isMock()) {
2762                 mFineBypassLocation = null;
2763             }
2764             if (mCoarseBypassLocation != null && mCoarseBypassLocation.isMock()) {
2765                 mCoarseBypassLocation = null;
2766             }
2767         }
2768 
2769         public void clearLocations() {
2770             mFineLocation = null;
2771             mCoarseLocation = null;
2772         }
2773 
2774         @Nullable public Location get(@PermissionLevel int permissionLevel,
2775                 boolean isBypass) {
2776             switch (permissionLevel) {
2777                 case PERMISSION_FINE:
2778                     if (isBypass) {
2779                         return mFineBypassLocation;
2780                     } else {
2781                         return mFineLocation;
2782                     }
2783                 case PERMISSION_COARSE:
2784                     if (isBypass) {
2785                         return mCoarseBypassLocation;
2786                     } else {
2787                         return mCoarseLocation;
2788                     }
2789                 default:
2790                     // shouldn't be possible to have a client added without location permissions
2791                     throw new AssertionError();
2792             }
2793         }
2794 
2795         public void set(Location location) {
2796             mFineLocation = calculateNextFine(mFineLocation, location);
2797             mCoarseLocation = calculateNextCoarse(mCoarseLocation, location);
2798         }
2799 
2800         public void setBypass(Location location) {
2801             mFineBypassLocation = calculateNextFine(mFineBypassLocation, location);
2802             mCoarseBypassLocation = calculateNextCoarse(mCoarseBypassLocation, location);
2803         }
2804 
2805         private Location calculateNextFine(@Nullable Location oldFine, Location newFine) {
2806             if (oldFine == null) {
2807                 return newFine;
2808             }
2809 
2810             // update last fine interval only if more recent
2811             if (newFine.getElapsedRealtimeNanos() > oldFine.getElapsedRealtimeNanos()) {
2812                 return newFine;
2813             } else {
2814                 return oldFine;
2815             }
2816         }
2817 
2818         private Location calculateNextCoarse(@Nullable Location oldCoarse, Location newCoarse) {
2819             if (oldCoarse == null) {
2820                 return newCoarse;
2821             }
2822 
2823             // update last coarse interval only if enough time has passed
2824             if (newCoarse.getElapsedRealtimeMillis() - MIN_COARSE_INTERVAL_MS
2825                     > oldCoarse.getElapsedRealtimeMillis()) {
2826                 return newCoarse;
2827             } else {
2828                 return oldCoarse;
2829             }
2830         }
2831     }
2832 
2833     private static class PendingIntentSender {
2834 
2835         // send() SHOULD only run the OnFinished callback if it completes successfully. however,
2836         // b/201299281 (which could not be fixed in the S timeframe) means that it's possible
2837         // for send() to throw an exception AND run the completion callback which breaks the
2838         // guarantee we rely on. we take matters into our own hands to ensure that the OnFinished
2839         // callback can only be run if send() completes successfully. this means the OnFinished
2840         // callback may be run inline, so there is no longer any guarantee about what thread the
2841         // callback will be run on.
2842         public static void send(PendingIntent pendingIntent, Context context, Intent intent,
2843                 @Nullable final Runnable callback, Bundle options)
2844                 throws PendingIntent.CanceledException {
2845             GatedCallback gatedCallback;
2846             PendingIntent.OnFinished onFinished;
2847             if (callback != null) {
2848                 gatedCallback = new GatedCallback(callback);
2849                 onFinished = (pI, i, rC, rD, rE) -> gatedCallback.run();
2850             } else {
2851                 gatedCallback = null;
2852                 onFinished = null;
2853             }
2854 
2855             pendingIntent.send(
2856                     context,
2857                     0,
2858                     intent,
2859                     onFinished,
2860                     null,
2861                     null,
2862                     options);
2863             if (gatedCallback != null) {
2864                 gatedCallback.allow();
2865             }
2866         }
2867 
2868         private static class GatedCallback implements Runnable {
2869 
2870             @GuardedBy("this")
2871             @Nullable private Runnable mCallback;
2872 
2873             @GuardedBy("this")
2874             private boolean mGate;
2875             @GuardedBy("this")
2876             private boolean mRun;
2877 
2878             private GatedCallback(@Nullable Runnable callback) {
2879                 mCallback = callback;
2880             }
2881 
2882             public void allow() {
2883                 Runnable callback = null;
2884                 synchronized (this) {
2885                     mGate = true;
2886                     if (mRun && mCallback != null) {
2887                         callback = mCallback;
2888                         mCallback = null;
2889                     }
2890                 }
2891 
2892                 if (callback != null) {
2893                     callback.run();
2894                 }
2895             }
2896 
2897             @Override
2898             public void run() {
2899                 Runnable callback = null;
2900                 synchronized (this) {
2901                     mRun = true;
2902                     if (mGate && mCallback != null) {
2903                         callback = mCallback;
2904                         mCallback = null;
2905                     }
2906                 }
2907 
2908                 if (callback != null) {
2909                     callback.run();
2910                 }
2911             }
2912         }
2913     }
2914 
2915     private static class ExternalWakeLockReleaser extends IRemoteCallback.Stub {
2916 
2917         private final CallerIdentity mIdentity;
2918         private final PowerManager.WakeLock mWakeLock;
2919 
2920         ExternalWakeLockReleaser(CallerIdentity identity, PowerManager.WakeLock wakeLock) {
2921             mIdentity = identity;
2922             mWakeLock = Objects.requireNonNull(wakeLock);
2923         }
2924 
2925         @Override
2926         public void sendResult(Bundle data) {
2927             final long identity = Binder.clearCallingIdentity();
2928             try {
2929                 mWakeLock.release();
2930             } catch (RuntimeException e) {
2931                 // wakelock throws a RuntimeException instead of some more specific exception, so
2932                 // attempt to capture only actual RuntimeExceptions
2933                 if (e.getClass() == RuntimeException.class) {
2934                     Log.e(TAG, "wakelock over-released by " + mIdentity, e);
2935                 } else {
2936                     // since this is within a oneway binder transaction there is nowhere for
2937                     // exceptions to go - move onto another thread to crash system server so we find
2938                     // out about it
2939                     FgThread.getExecutor().execute(() -> {
2940                         throw new AssertionError(e);
2941                     });
2942                     throw e;
2943                 }
2944             } finally {
2945                 Binder.restoreCallingIdentity(identity);
2946             }
2947         }
2948     }
2949 }
2950