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