/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server;

import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.location.LocationManager.FUSED_PROVIDER;
import static android.location.LocationManager.GPS_PROVIDER;
import static android.location.LocationManager.NETWORK_PROVIDER;
import static android.location.LocationManager.PASSIVE_PROVIDER;
import static android.location.LocationProvider.AVAILABLE;
import static android.os.PowerManager.locationPowerSaveModeToString;
import static android.provider.Settings.Global.LOCATION_DISABLE_STATUS_CALLBACKS;

import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.Preconditions.checkState;

import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.location.ActivityRecognitionHardware;
import android.location.Address;
import android.location.Criteria;
import android.location.GeocoderParams;
import android.location.Geofence;
import android.location.GnssCapabilities;
import android.location.GnssMeasurementCorrections;
import android.location.IBatchedLocationCallback;
import android.location.IGnssMeasurementsListener;
import android.location.IGnssNavigationMessageListener;
import android.location.IGnssStatusListener;
import android.location.IGpsGeofenceHardware;
import android.location.ILocationListener;
import android.location.ILocationManager;
import android.location.INetInitiatedListener;
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationRequest;
import android.location.LocationTime;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.IInterface;
import android.os.PowerManager;
import android.os.PowerManager.ServiceType;
import android.os.PowerManagerInternal;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.WorkSource;
import android.os.WorkSource.WorkChain;
import android.provider.Settings;
import android.stats.location.LocationStatsEnums;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
import android.util.TimeUtils;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
import com.android.server.location.AbstractLocationProvider;
import com.android.server.location.ActivityRecognitionProxy;
import com.android.server.location.CallerIdentity;
import com.android.server.location.GeocoderProxy;
import com.android.server.location.GeofenceManager;
import com.android.server.location.GeofenceProxy;
import com.android.server.location.GnssBatchingProvider;
import com.android.server.location.GnssCapabilitiesProvider;
import com.android.server.location.GnssLocationProvider;
import com.android.server.location.GnssMeasurementCorrectionsProvider;
import com.android.server.location.GnssMeasurementsProvider;
import com.android.server.location.GnssNavigationMessageProvider;
import com.android.server.location.GnssStatusListenerHelper;
import com.android.server.location.LocationBlacklist;
import com.android.server.location.LocationFudger;
import com.android.server.location.LocationProviderProxy;
import com.android.server.location.LocationRequestStatistics;
import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
import com.android.server.location.LocationRequestStatistics.PackageStatistics;
import com.android.server.location.MockProvider;
import com.android.server.location.PassiveProvider;
import com.android.server.location.RemoteListenerHelper;

import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * The service class that manages LocationProviders and issues location
 * updates and alerts.
 */
public class LocationManagerService extends ILocationManager.Stub {
    private static final String TAG = "LocationManagerService";
    public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);

    private static final String WAKELOCK_KEY = "*location*";

    // Location resolution level: no location data whatsoever
    private static final int RESOLUTION_LEVEL_NONE = 0;
    // Location resolution level: coarse location data only
    private static final int RESOLUTION_LEVEL_COARSE = 1;
    // Location resolution level: fine location data
    private static final int RESOLUTION_LEVEL_FINE = 2;

    private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
            android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;

    private static final String NETWORK_LOCATION_SERVICE_ACTION =
            "com.android.location.service.v3.NetworkLocationProvider";
    private static final String FUSED_LOCATION_SERVICE_ACTION =
            "com.android.location.service.FusedLocationProvider";

    private static final long NANOS_PER_MILLI = 1000000L;

    // The maximum interval a location request can have and still be considered "high power".
    private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;

    private static final int FOREGROUND_IMPORTANCE_CUTOFF
            = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;

    // default background throttling interval if not overriden in settings
    private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;

    // Default value for maximum age of last location returned to applications with foreground-only
    // location permissions.
    private static final long DEFAULT_LAST_LOCATION_MAX_AGE_MS = 20 * 60 * 1000;

    // Location Providers may sometimes deliver location updates
    // slightly faster that requested - provide grace period so
    // we don't unnecessarily filter events that are otherwise on
    // time
    private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;

    private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();

    private final Object mLock = new Object();
    private final Context mContext;
    private final Handler mHandler;

    private AppOpsManager mAppOps;
    private PackageManager mPackageManager;
    private PowerManager mPowerManager;
    private ActivityManager mActivityManager;
    private UserManager mUserManager;

    private GeofenceManager mGeofenceManager;
    private LocationFudger mLocationFudger;
    private GeocoderProxy mGeocodeProvider;
    private GnssStatusListenerHelper mGnssStatusProvider;
    private INetInitiatedListener mNetInitiatedListener;
    private PassiveProvider mPassiveProvider;  // track passive provider for special cases
    private LocationBlacklist mBlacklist;
    private GnssMeasurementsProvider mGnssMeasurementsProvider;
    private GnssMeasurementCorrectionsProvider mGnssMeasurementCorrectionsProvider;
    private GnssNavigationMessageProvider mGnssNavigationMessageProvider;
    @GuardedBy("mLock")
    private String mExtraLocationControllerPackage;
    private boolean mExtraLocationControllerPackageEnabled;
    private IGpsGeofenceHardware mGpsGeofenceProxy;

    // list of currently active providers
    @GuardedBy("mLock")
    private final ArrayList<LocationProvider> mProviders = new ArrayList<>();

    // list of non-mock providers, so that when mock providers replace real providers, they can be
    // later re-replaced
    @GuardedBy("mLock")
    private final ArrayList<LocationProvider> mRealProviders = new ArrayList<>();

    @GuardedBy("mLock")
    private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
    private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
            new HashMap<>();

    private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics();

    // mapping from provider name to last known location
    @GuardedBy("mLock")
    private final HashMap<String, Location> mLastLocation = new HashMap<>();

    // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
    // locations stored here are not fudged for coarse permissions.
    @GuardedBy("mLock")
    private final HashMap<String, Location> mLastLocationCoarseInterval =
            new HashMap<>();

    private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();

    private final ArraySet<String> mIgnoreSettingsPackageWhitelist = new ArraySet<>();

    @GuardedBy("mLock")
    private final ArrayMap<IBinder, LinkedListener<IGnssMeasurementsListener>>
            mGnssMeasurementsListeners = new ArrayMap<>();
    @GuardedBy("mLock")
    private final ArrayMap<IBinder, LinkedListener<IGnssNavigationMessageListener>>
            mGnssNavigationMessageListeners = new ArrayMap<>();
    @GuardedBy("mLock")
    private final ArrayMap<IBinder, LinkedListener<IGnssStatusListener>>
            mGnssStatusListeners = new ArrayMap<>();

    // current active user on the device - other users are denied location data
    private int mCurrentUserId = UserHandle.USER_SYSTEM;
    private int[] mCurrentUserProfiles = new int[]{UserHandle.USER_SYSTEM};

    private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;
    private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;
    private GnssCapabilitiesProvider mGnssCapabilitiesProvider;

    private GnssBatchingProvider mGnssBatchingProvider;
    @GuardedBy("mLock")
    private IBatchedLocationCallback mGnssBatchingCallback;
    @GuardedBy("mLock")
    private LinkedListener<IBatchedLocationCallback> mGnssBatchingDeathCallback;
    @GuardedBy("mLock")
    private boolean mGnssBatchingInProgress = false;

    @GuardedBy("mLock")
    @PowerManager.LocationPowerSaveMode
    private int mBatterySaverMode;

    @GuardedBy("mLock")
    private final LocationUsageLogger mLocationUsageLogger;

    public LocationManagerService(Context context) {
        super();
        mContext = context;
        mHandler = FgThread.getHandler();
        mLocationUsageLogger = new LocationUsageLogger();

        // Let the package manager query which are the default location
        // providers as they get certain permissions granted by default.
        PackageManagerInternal packageManagerInternal = LocalServices.getService(
                PackageManagerInternal.class);
        packageManagerInternal.setLocationPackagesProvider(
                userId -> mContext.getResources().getStringArray(
                        com.android.internal.R.array.config_locationProviderPackageNames));
        packageManagerInternal.setLocationExtraPackagesProvider(
                userId -> mContext.getResources().getStringArray(
                      com.android.internal.R.array.config_locationExtraPackageNames));

        // most startup is deferred until systemRunning()
    }

    public void systemRunning() {
        synchronized (mLock) {
            initializeLocked();
        }
    }

    @GuardedBy("mLock")
    private void initializeLocked() {
        mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
        mPackageManager = mContext.getPackageManager();
        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);

        mLocationFudger = new LocationFudger(mContext, mHandler);
        mBlacklist = new LocationBlacklist(mContext, mHandler);
        mBlacklist.init();
        mGeofenceManager = new GeofenceManager(mContext, mBlacklist);

        // prepare providers
        initializeProvidersLocked();

        // add listeners
        mAppOps.startWatchingMode(
                AppOpsManager.OP_COARSE_LOCATION,
                null,
                AppOpsManager.WATCH_FOREGROUND_CHANGES,
                new AppOpsManager.OnOpChangedInternalListener() {
                    public void onOpChanged(int op, String packageName) {
                        // onOpChanged invoked on ui thread, move to our thread to reduce risk of
                        // blocking ui thread
                        mHandler.post(() -> {
                            synchronized (mLock) {
                                onAppOpChangedLocked();
                            }
                        });
                    }
                });
        mPackageManager.addOnPermissionsChangeListener(
                uid -> {
                    // listener invoked on ui thread, move to our thread to reduce risk of blocking
                    // ui thread
                    mHandler.post(() -> {
                        synchronized (mLock) {
                            onPermissionsChangedLocked();
                        }
                    });
                });

        mActivityManager.addOnUidImportanceListener(
                (uid, importance) -> {
                    // listener invoked on ui thread, move to our thread to reduce risk of blocking
                    // ui thread
                    mHandler.post(() -> {
                        synchronized (mLock) {
                            onUidImportanceChangedLocked(uid, importance);
                        }
                    });
                },
                FOREGROUND_IMPORTANCE_CUTOFF);
        mContext.getContentResolver().registerContentObserver(
                Settings.Secure.getUriFor(Settings.Secure.LOCATION_MODE), true,
                new ContentObserver(mHandler) {
                    @Override
                    public void onChange(boolean selfChange) {
                        synchronized (mLock) {
                            onLocationModeChangedLocked(true);
                        }
                    }
                }, UserHandle.USER_ALL);
        mContext.getContentResolver().registerContentObserver(
                Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
                new ContentObserver(mHandler) {
                    @Override
                    public void onChange(boolean selfChange) {
                        synchronized (mLock) {
                            onProviderAllowedChangedLocked();
                        }
                    }
                }, UserHandle.USER_ALL);
        mContext.getContentResolver().registerContentObserver(
                Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS),
                true,
                new ContentObserver(mHandler) {
                    @Override
                    public void onChange(boolean selfChange) {
                        synchronized (mLock) {
                            onBackgroundThrottleIntervalChangedLocked();
                        }
                    }
                }, UserHandle.USER_ALL);
        mContext.getContentResolver().registerContentObserver(
                Settings.Global.getUriFor(
                        Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
                true,
                new ContentObserver(mHandler) {
                    @Override
                    public void onChange(boolean selfChange) {
                        synchronized (mLock) {
                            onBackgroundThrottleWhitelistChangedLocked();
                        }
                    }
                }, UserHandle.USER_ALL);
        mContext.getContentResolver().registerContentObserver(
                Settings.Global.getUriFor(
                        Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST),
                true,
                new ContentObserver(mHandler) {
                    @Override
                    public void onChange(boolean selfChange) {
                        synchronized (mLock) {
                            onIgnoreSettingsWhitelistChangedLocked();
                        }
                    }
                }, UserHandle.USER_ALL);
        PowerManagerInternal localPowerManager =
                LocalServices.getService(PowerManagerInternal.class);
        localPowerManager.registerLowPowerModeObserver(ServiceType.LOCATION,
                state -> {
                    // listener invoked on ui thread, move to our thread to reduce risk of blocking
                    // ui thread
                    mHandler.post(() -> {
                        synchronized (mLock) {
                            onBatterySaverModeChangedLocked(state.locationMode);
                        }
                    });
                });

        new PackageMonitor() {
            @Override
            public void onPackageDisappeared(String packageName, int reason) {
                synchronized (mLock) {
                    LocationManagerService.this.onPackageDisappearedLocked(packageName);
                }
            }
        }.register(mContext, mHandler.getLooper(), true);

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
        intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
        intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
        intentFilter.addAction(Intent.ACTION_SCREEN_ON);

        mContext.registerReceiverAsUser(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                final String action = intent.getAction();
                if (action == null) {
                    return;
                }
                synchronized (mLock) {
                    switch (action) {
                        case Intent.ACTION_USER_SWITCHED:
                            onUserChangedLocked(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
                            break;
                        case Intent.ACTION_MANAGED_PROFILE_ADDED:
                        case Intent.ACTION_MANAGED_PROFILE_REMOVED:
                            onUserProfilesChangedLocked();
                            break;
                        case Intent.ACTION_SCREEN_ON:
                        case Intent.ACTION_SCREEN_OFF:
                            onScreenStateChangedLocked();
                            break;
                    }
                }
            }
        }, UserHandle.ALL, intentFilter, null, mHandler);

        // switching the user from null to system here performs the bulk of the initialization work.
        // the user being changed will cause a reload of all user specific settings, which causes
        // provider initialization, and propagates changes until a steady state is reached
        mCurrentUserId = UserHandle.USER_NULL;
        onUserChangedLocked(UserHandle.USER_SYSTEM);

        // initialize in-memory settings values
        onBackgroundThrottleWhitelistChangedLocked();
        onIgnoreSettingsWhitelistChangedLocked();
        onBatterySaverModeChangedLocked(mPowerManager.getLocationPowerSaveMode());
    }

    @GuardedBy("mLock")
    private void onAppOpChangedLocked() {
        for (Receiver receiver : mReceivers.values()) {
            receiver.updateMonitoring(true);
        }
        for (LocationProvider p : mProviders) {
            applyRequirementsLocked(p);
        }
    }

    @GuardedBy("mLock")
    private void onPermissionsChangedLocked() {
        for (LocationProvider p : mProviders) {
            applyRequirementsLocked(p);
        }
    }

    @GuardedBy("mLock")
    private void onBatterySaverModeChangedLocked(int newLocationMode) {
        if (D) {
            Slog.d(TAG,
                    "Battery Saver location mode changed from "
                            + locationPowerSaveModeToString(mBatterySaverMode) + " to "
                            + locationPowerSaveModeToString(newLocationMode));
        }

        if (mBatterySaverMode == newLocationMode) {
            return;
        }

        mBatterySaverMode = newLocationMode;
        for (LocationProvider p : mProviders) {
            applyRequirementsLocked(p);
        }
    }

    @GuardedBy("mLock")
    private void onScreenStateChangedLocked() {
        if (mBatterySaverMode == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF) {
            for (LocationProvider p : mProviders) {
                applyRequirementsLocked(p);
            }
        }
    }

    @GuardedBy("mLock")
    private void onLocationModeChangedLocked(boolean broadcast) {
        if (D) {
            Log.d(TAG, "location enabled is now " + isLocationEnabled());
        }

        for (LocationProvider p : mProviders) {
            p.onLocationModeChangedLocked();
        }

        if (broadcast) {
            // needs to be sent to everyone because we don't know which user may have changed
            // LOCATION_MODE state.
            mContext.sendBroadcastAsUser(
                    new Intent(LocationManager.MODE_CHANGED_ACTION),
                    UserHandle.ALL);
        }
    }

    @GuardedBy("mLock")
    private void onProviderAllowedChangedLocked() {
        for (LocationProvider p : mProviders) {
            p.onAllowedChangedLocked();
        }
    }

    @GuardedBy("mLock")
    private void onPackageDisappearedLocked(String packageName) {
        ArrayList<Receiver> deadReceivers = null;

        for (Receiver receiver : mReceivers.values()) {
            if (receiver.mCallerIdentity.mPackageName.equals(packageName)) {
                if (deadReceivers == null) {
                    deadReceivers = new ArrayList<>();
                }
                deadReceivers.add(receiver);
            }
        }

        // perform removal outside of mReceivers loop
        if (deadReceivers != null) {
            for (Receiver receiver : deadReceivers) {
                removeUpdatesLocked(receiver);
            }
        }
    }

    @GuardedBy("mLock")
    private void onUidImportanceChangedLocked(int uid, int importance) {
        boolean foreground = isImportanceForeground(importance);
        HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
        for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
            String provider = entry.getKey();
            for (UpdateRecord record : entry.getValue()) {
                if (record.mReceiver.mCallerIdentity.mUid == uid
                        && record.mIsForegroundUid != foreground) {
                    if (D) {
                        Log.d(TAG, "request from uid " + uid + " is now "
                                + foregroundAsString(foreground));
                    }
                    record.updateForeground(foreground);

                    if (!isThrottlingExemptLocked(record.mReceiver.mCallerIdentity)) {
                        affectedProviders.add(provider);
                    }
                }
            }
        }
        for (String provider : affectedProviders) {
            applyRequirementsLocked(provider);
        }

        updateGnssDataProviderOnUidImportanceChangedLocked(mGnssMeasurementsListeners,
                mGnssMeasurementsProvider, IGnssMeasurementsListener.Stub::asInterface,
                uid, foreground);

        updateGnssDataProviderOnUidImportanceChangedLocked(mGnssNavigationMessageListeners,
                mGnssNavigationMessageProvider, IGnssNavigationMessageListener.Stub::asInterface,
                uid, foreground);

        updateGnssDataProviderOnUidImportanceChangedLocked(mGnssStatusListeners,
                mGnssStatusProvider, IGnssStatusListener.Stub::asInterface, uid, foreground);
    }

    @GuardedBy("mLock")
    private <TListener extends IInterface> void updateGnssDataProviderOnUidImportanceChangedLocked(
            ArrayMap<IBinder, ? extends LinkedListenerBase> gnssDataListeners,
            RemoteListenerHelper<TListener> gnssDataProvider,
            Function<IBinder, TListener> mapBinderToListener, int uid, boolean foreground) {
        for (Entry<IBinder, ? extends LinkedListenerBase> entry : gnssDataListeners.entrySet()) {
            LinkedListenerBase linkedListener = entry.getValue();
            CallerIdentity callerIdentity = linkedListener.mCallerIdentity;
            if (callerIdentity.mUid != uid) {
                continue;
            }

            if (D) {
                Log.d(TAG, linkedListener.mListenerName + " from uid "
                        + uid + " is now " + foregroundAsString(foreground));
            }

            TListener listener = mapBinderToListener.apply(entry.getKey());
            if (foreground || isThrottlingExemptLocked(callerIdentity)) {
                gnssDataProvider.addListener(listener, callerIdentity);
            } else {
                gnssDataProvider.removeListener(listener);
            }
        }
    }

    private static String foregroundAsString(boolean foreground) {
        return foreground ? "foreground" : "background";
    }

    private static boolean isImportanceForeground(int importance) {
        return importance <= FOREGROUND_IMPORTANCE_CUTOFF;
    }

    @GuardedBy("mLock")
    private void onBackgroundThrottleIntervalChangedLocked() {
        for (LocationProvider provider : mProviders) {
            applyRequirementsLocked(provider);
        }
    }

    @GuardedBy("mLock")
    private void onBackgroundThrottleWhitelistChangedLocked() {
        mBackgroundThrottlePackageWhitelist.clear();
        mBackgroundThrottlePackageWhitelist.addAll(
                SystemConfig.getInstance().getAllowUnthrottledLocation());

        String setting = Settings.Global.getString(
                mContext.getContentResolver(),
                Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
        if (!TextUtils.isEmpty(setting)) {
            mBackgroundThrottlePackageWhitelist.addAll(Arrays.asList(setting.split(",")));
        }

        for (LocationProvider p : mProviders) {
            applyRequirementsLocked(p);
        }
    }

    @GuardedBy("lock")
    private void onIgnoreSettingsWhitelistChangedLocked() {
        mIgnoreSettingsPackageWhitelist.clear();
        mIgnoreSettingsPackageWhitelist.addAll(
                SystemConfig.getInstance().getAllowIgnoreLocationSettings());

        String setting = Settings.Global.getString(
                mContext.getContentResolver(),
                Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST);
        if (!TextUtils.isEmpty(setting)) {
            mIgnoreSettingsPackageWhitelist.addAll(Arrays.asList(setting.split(",")));
        }

        for (LocationProvider p : mProviders) {
            applyRequirementsLocked(p);
        }
    }

    @GuardedBy("mLock")
    private void onUserProfilesChangedLocked() {
        mCurrentUserProfiles = mUserManager.getProfileIdsWithDisabled(mCurrentUserId);
    }

    @GuardedBy("mLock")
    private boolean isCurrentProfileLocked(int userId) {
        return ArrayUtils.contains(mCurrentUserProfiles, userId);
    }

    @GuardedBy("mLock")
    private void ensureFallbackFusedProviderPresentLocked(String[] pkgs) {
        PackageManager pm = mContext.getPackageManager();
        String systemPackageName = mContext.getPackageName();
        ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);

        List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
                new Intent(FUSED_LOCATION_SERVICE_ACTION),
                PackageManager.GET_META_DATA, mCurrentUserId);
        for (ResolveInfo rInfo : rInfos) {
            String packageName = rInfo.serviceInfo.packageName;

            // Check that the signature is in the list of supported sigs. If it's not in
            // this list the standard provider binding logic won't bind to it.
            try {
                PackageInfo pInfo;
                pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
                if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
                    Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
                            ", but has wrong signature, ignoring");
                    continue;
                }
            } catch (NameNotFoundException e) {
                Log.e(TAG, "missing package: " + packageName);
                continue;
            }

            // Get the version info
            if (rInfo.serviceInfo.metaData == null) {
                Log.w(TAG, "Found fused provider without metadata: " + packageName);
                continue;
            }

            int version = rInfo.serviceInfo.metaData.getInt(
                    ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
            if (version == 0) {
                // This should be the fallback fused location provider.

                // Make sure it's in the system partition.
                if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                    if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
                    continue;
                }

                // Check that the fallback is signed the same as the OS
                // as a proxy for coreApp="true"
                if (pm.checkSignatures(systemPackageName, packageName)
                        != PackageManager.SIGNATURE_MATCH) {
                    if (D) {
                        Log.d(TAG, "Fallback candidate not signed the same as system: "
                                + packageName);
                    }
                    continue;
                }

                // Found a valid fallback.
                if (D) Log.d(TAG, "Found fallback provider: " + packageName);
                return;
            } else {
                if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
            }
        }

        throw new IllegalStateException("Unable to find a fused location provider that is in the "
                + "system partition with version 0 and signed with the platform certificate. "
                + "Such a package is needed to provide a default fused location provider in the "
                + "event that no other fused location provider has been installed or is currently "
                + "available. For example, coreOnly boot mode when decrypting the data "
                + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
    }

    @GuardedBy("mLock")
    private void initializeProvidersLocked() {
        // create a passive location provider, which is always enabled
        LocationProvider passiveProviderManager = new LocationProvider(PASSIVE_PROVIDER);
        addProviderLocked(passiveProviderManager);
        mPassiveProvider = new PassiveProvider(mContext, passiveProviderManager);
        passiveProviderManager.attachLocked(mPassiveProvider);

        if (GnssLocationProvider.isSupported()) {
            // Create a gps location provider
            LocationProvider gnssProviderManager = new LocationProvider(GPS_PROVIDER, true);
            mRealProviders.add(gnssProviderManager);
            addProviderLocked(gnssProviderManager);

            GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext,
                    gnssProviderManager,
                    mHandler.getLooper());
            gnssProviderManager.attachLocked(gnssProvider);

            mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
            mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider();
            mGnssMetricsProvider = gnssProvider.getGnssMetricsProvider();
            mGnssCapabilitiesProvider = gnssProvider.getGnssCapabilitiesProvider();
            mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
            mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
            mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
            mGnssMeasurementCorrectionsProvider =
                    gnssProvider.getGnssMeasurementCorrectionsProvider();
            mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider();
            mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy();
        }

        /*
        Load package name(s) containing location provider support.
        These packages can contain services implementing location providers:
        Geocoder Provider, Network Location Provider, and
        Fused Location Provider. They will each be searched for
        service components implementing these providers.
        The location framework also has support for installation
        of new location providers at run-time. The new package does not
        have to be explicitly listed here, however it must have a signature
        that matches the signature of at least one package on this list.
        */
        Resources resources = mContext.getResources();
        String[] pkgs = resources.getStringArray(
                com.android.internal.R.array.config_locationProviderPackageNames);
        if (D) {
            Log.d(TAG, "certificates for location providers pulled from: " +
                    Arrays.toString(pkgs));
        }

        ensureFallbackFusedProviderPresentLocked(pkgs);

        // bind to network provider
        LocationProvider networkProviderManager = new LocationProvider(NETWORK_PROVIDER, true);
        LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
                mContext,
                networkProviderManager,
                NETWORK_LOCATION_SERVICE_ACTION,
                com.android.internal.R.bool.config_enableNetworkLocationOverlay,
                com.android.internal.R.string.config_networkLocationProviderPackageName,
                com.android.internal.R.array.config_locationProviderPackageNames);
        if (networkProvider != null) {
            mRealProviders.add(networkProviderManager);
            addProviderLocked(networkProviderManager);
            networkProviderManager.attachLocked(networkProvider);
        } else {
            Slog.w(TAG, "no network location provider found");
        }

        // bind to fused provider
        LocationProvider fusedProviderManager = new LocationProvider(FUSED_PROVIDER);
        LocationProviderProxy fusedProvider = LocationProviderProxy.createAndBind(
                mContext,
                fusedProviderManager,
                FUSED_LOCATION_SERVICE_ACTION,
                com.android.internal.R.bool.config_enableFusedLocationOverlay,
                com.android.internal.R.string.config_fusedLocationProviderPackageName,
                com.android.internal.R.array.config_locationProviderPackageNames);
        if (fusedProvider != null) {
            mRealProviders.add(fusedProviderManager);
            addProviderLocked(fusedProviderManager);
            fusedProviderManager.attachLocked(fusedProvider);
        } else {
            Slog.e(TAG, "no fused location provider found",
                    new IllegalStateException("Location service needs a fused location provider"));
        }

        // bind to geocoder provider
        mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
                com.android.internal.R.bool.config_enableGeocoderOverlay,
                com.android.internal.R.string.config_geocoderProviderPackageName,
                com.android.internal.R.array.config_locationProviderPackageNames);
        if (mGeocodeProvider == null) {
            Slog.e(TAG, "no geocoder provider found");
        }

        // bind to geofence provider
        GeofenceProxy provider = GeofenceProxy.createAndBind(
                mContext, com.android.internal.R.bool.config_enableGeofenceOverlay,
                com.android.internal.R.string.config_geofenceProviderPackageName,
                com.android.internal.R.array.config_locationProviderPackageNames,
                mGpsGeofenceProxy,
                null);
        if (provider == null) {
            Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
        }

        // bind to hardware activity recognition
        boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
        ActivityRecognitionHardware activityRecognitionHardware = null;
        if (activityRecognitionHardwareIsSupported) {
            activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
        } else {
            Slog.d(TAG, "Hardware Activity-Recognition not supported.");
        }
        ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
                mContext,
                activityRecognitionHardwareIsSupported,
                activityRecognitionHardware,
                com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
                com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
                com.android.internal.R.array.config_locationProviderPackageNames);
        if (proxy == null) {
            Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
        }

        String[] testProviderStrings = resources.getStringArray(
                com.android.internal.R.array.config_testLocationProviders);
        for (String testProviderString : testProviderStrings) {
            String[] fragments = testProviderString.split(",");
            String name = fragments[0].trim();
            ProviderProperties properties = new ProviderProperties(
                    Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
                    Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
                    Boolean.parseBoolean(fragments[3]) /* requiresCell */,
                    Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
                    Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
                    Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
                    Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
                    Integer.parseInt(fragments[8]) /* powerRequirement */,
                    Integer.parseInt(fragments[9]) /* accuracy */);
            LocationProvider testProviderManager = new LocationProvider(name);
            addProviderLocked(testProviderManager);
            new MockProvider(mContext, testProviderManager, properties);
        }
    }

    @GuardedBy("mLock")
    private void onUserChangedLocked(int userId) {
        if (mCurrentUserId == userId) {
            return;
        }

        if (D) {
            Log.d(TAG, "foreground user is changing to " + userId);
        }

        // let providers know the current user is on the way out before changing the user
        for (LocationProvider p : mProviders) {
            p.onUserChangingLocked();
        }

        mCurrentUserId = userId;
        onUserProfilesChangedLocked();

        mBlacklist.switchUser(userId);

        // if the user changes, per-user settings may also have changed
        onLocationModeChangedLocked(false);
        onProviderAllowedChangedLocked();

        // always force useability to be rechecked, even if no per-user settings have changed
        for (LocationProvider p : mProviders) {
            p.onUseableChangedLocked(false);
        }
    }

    private class LocationProvider implements AbstractLocationProvider.LocationProviderManager {

        private final String mName;

        // whether this provider should respect LOCATION_PROVIDERS_ALLOWED (ie gps and network)
        private final boolean mIsManagedBySettings;

        // remember to clear binder identity before invoking any provider operation
        @GuardedBy("mLock")
        @Nullable protected AbstractLocationProvider mProvider;

        @GuardedBy("mLock")
        private boolean mUseable;  // combined state
        @GuardedBy("mLock")
        private boolean mAllowed;  // state of LOCATION_PROVIDERS_ALLOWED
        @GuardedBy("mLock")
        private boolean mEnabled;  // state of provider

        @GuardedBy("mLock")
        @Nullable private ProviderProperties mProperties;

        private LocationProvider(String name) {
            this(name, false);
        }

        private LocationProvider(String name, boolean isManagedBySettings) {
            mName = name;
            mIsManagedBySettings = isManagedBySettings;

            mProvider = null;
            mUseable = false;
            mAllowed = !mIsManagedBySettings;
            mEnabled = false;
            mProperties = null;

            if (mIsManagedBySettings) {
                // since we assume providers are disabled by default
                Settings.Secure.putStringForUser(
                        mContext.getContentResolver(),
                        Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
                        "-" + mName,
                        mCurrentUserId);
            }
        }

        @GuardedBy("mLock")
        public void attachLocked(AbstractLocationProvider provider) {
            checkNotNull(provider);
            checkState(mProvider == null);

            if (D) {
                Log.d(TAG, mName + " provider attached");
            }

            mProvider = provider;
            onUseableChangedLocked(false);
        }

        public String getName() {
            return mName;
        }

        @GuardedBy("mLock")
        public List<String> getPackagesLocked() {
            if (mProvider == null) {
                return Collections.emptyList();
            } else {
                // safe to not clear binder context since this doesn't call into the real provider
                return mProvider.getProviderPackages();
            }
        }

        public boolean isMock() {
            return false;
        }

        @GuardedBy("mLock")
        public boolean isPassiveLocked() {
            return mProvider == mPassiveProvider;
        }

        @GuardedBy("mLock")
        @Nullable
        public ProviderProperties getPropertiesLocked() {
            return mProperties;
        }

        @GuardedBy("mLock")
        public void setRequestLocked(ProviderRequest request, WorkSource workSource) {
            if (mProvider != null) {
                long identity = Binder.clearCallingIdentity();
                try {
                    mProvider.setRequest(request, workSource);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
        }

        @GuardedBy("mLock")
        public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
            pw.print("  " + mName + " provider");
            if (isMock()) {
                pw.print(" [mock]");
            }
            pw.println(":");

            pw.println("    useable=" + mUseable);
            if (!mUseable) {
                pw.println("    attached=" + (mProvider != null));
                if (mIsManagedBySettings) {
                    pw.println("    allowed=" + mAllowed);
                }
                pw.println("    enabled=" + mEnabled);
            }

            pw.println("    properties=" + mProperties);

            if (mProvider != null) {
                long identity = Binder.clearCallingIdentity();
                try {
                    mProvider.dump(fd, pw, args);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
        }

        @GuardedBy("mLock")
        public long getStatusUpdateTimeLocked() {
            if (mProvider != null) {
                long identity = Binder.clearCallingIdentity();
                try {
                    return mProvider.getStatusUpdateTime();
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            } else {
                return 0;
            }
        }

        @GuardedBy("mLock")
        public int getStatusLocked(Bundle extras) {
            if (mProvider != null) {
                long identity = Binder.clearCallingIdentity();
                try {
                    return mProvider.getStatus(extras);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            } else {
                return AVAILABLE;
            }
        }

        @GuardedBy("mLock")
        public void sendExtraCommandLocked(String command, Bundle extras) {
            if (mProvider != null) {
                long identity = Binder.clearCallingIdentity();
                try {
                    mProvider.sendExtraCommand(command, extras);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
        }

        // called from any thread
        @Override
        public void onReportLocation(Location location) {
            // no security check necessary because this is coming from an internal-only interface
            // move calls coming from below LMS onto a different thread to avoid deadlock
            mHandler.post(() -> {
                synchronized (mLock) {
                    handleLocationChangedLocked(location, this);
                }
            });
        }

        // called from any thread
        @Override
        public void onReportLocation(List<Location> locations) {
            // move calls coming from below LMS onto a different thread to avoid deadlock
            mHandler.post(() -> {
                synchronized (mLock) {
                    LocationProvider gpsProvider = getLocationProviderLocked(GPS_PROVIDER);
                    if (gpsProvider == null || !gpsProvider.isUseableLocked()) {
                        Slog.w(TAG, "reportLocationBatch() called without user permission");
                        return;
                    }

                    if (mGnssBatchingCallback == null) {
                        Slog.e(TAG, "reportLocationBatch() called without active Callback");
                        return;
                    }

                    try {
                        mGnssBatchingCallback.onLocationBatch(locations);
                    } catch (RemoteException e) {
                        Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e);
                    }
                }
            });
        }

        // called from any thread
        @Override
        public void onSetEnabled(boolean enabled) {
            // move calls coming from below LMS onto a different thread to avoid deadlock
            mHandler.post(() -> {
                synchronized (mLock) {
                    if (enabled == mEnabled) {
                        return;
                    }

                    if (D) {
                        Log.d(TAG, mName + " provider enabled is now " + mEnabled);
                    }

                    mEnabled = enabled;
                    onUseableChangedLocked(false);
                }
            });
        }

        @Override
        public void onSetProperties(ProviderProperties properties) {
            // because this does not invoke any other methods which might result in calling back
            // into the location provider, it is safe to run this on the calling thread. it is also
            // currently necessary to run this on the calling thread to ensure that property changes
            // are publicly visibly immediately, ie for mock providers which are created.
            synchronized (mLock) {
                mProperties = properties;
            }
        }

        @GuardedBy("mLock")
        public void onLocationModeChangedLocked() {
            onUseableChangedLocked(false);
        }

        @GuardedBy("mLock")
        public void onAllowedChangedLocked() {
            if (mIsManagedBySettings) {
                String allowedProviders = Settings.Secure.getStringForUser(
                        mContext.getContentResolver(),
                        Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
                        mCurrentUserId);
                boolean allowed = TextUtils.delimitedStringContains(allowedProviders, ',', mName);

                if (allowed == mAllowed) {
                    return;
                }

                if (D) {
                    Log.d(TAG, mName + " provider allowed is now " + mAllowed);
                }

                mAllowed = allowed;
                onUseableChangedLocked(true);
            }
        }

        @GuardedBy("mLock")
        public boolean isUseableLocked() {
            return isUseableForUserLocked(mCurrentUserId);
        }

        @GuardedBy("mLock")
        public boolean isUseableForUserLocked(int userId) {
            return isCurrentProfileLocked(userId) && mUseable;
        }

        @GuardedBy("mLock")
        private boolean isUseableIgnoringAllowedLocked() {
            return mProvider != null && mProviders.contains(this) && isLocationEnabled()
                    && mEnabled;
        }

        @GuardedBy("mLock")
        public void onUseableChangedLocked(boolean isAllowedChanged) {
            // if any property that contributes to "useability" here changes state, it MUST result
            // in a direct or indrect call to onUseableChangedLocked. this allows the provider to
            // guarantee that it will always eventually reach the correct state.
            boolean useableIgnoringAllowed = isUseableIgnoringAllowedLocked();
            boolean useable = useableIgnoringAllowed && mAllowed;

            // update deprecated provider allowed settings for backwards compatibility, and do this
            // even if there is no change in overall useability state. this may result in trying to
            // overwrite the same value, but Settings handles deduping this.
            if (mIsManagedBySettings) {
                // a "-" change derived from the allowed setting should not be overwritten, but a
                // "+" change should be corrected if necessary
                if (useableIgnoringAllowed && !isAllowedChanged) {
                    Settings.Secure.putStringForUser(
                            mContext.getContentResolver(),
                            Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
                            "+" + mName,
                            mCurrentUserId);
                } else if (!useableIgnoringAllowed) {
                    Settings.Secure.putStringForUser(
                            mContext.getContentResolver(),
                            Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
                            "-" + mName,
                            mCurrentUserId);
                }

                // needs to be sent to all users because whether or not a provider is enabled for
                // a given user is complicated... we broadcast to everyone and let them figure it
                // out via isProviderEnabled()
                Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION);
                intent.putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName);
                mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
            }

            if (useable == mUseable) {
                return;
            }
            mUseable = useable;

            if (D) {
                Log.d(TAG, mName + " provider useable is now " + mUseable);
            }

            if (!mUseable) {
                // If any provider has been disabled, clear all last locations for all
                // providers. This is to be on the safe side in case a provider has location
                // derived from this disabled provider.
                mLastLocation.clear();
                mLastLocationCoarseInterval.clear();
            }

            updateProviderUseableLocked(this);
        }

        @GuardedBy("mLock")
        public void onUserChangingLocked() {
            // when the user is about to change, we set this provider to un-useable, and notify all
            // of the current user clients. when the user is finished changing, useability will be
            // updated back via onLocationModeChanged() and onAllowedChanged().
            mUseable = false;
            updateProviderUseableLocked(this);
        }
    }

    private class MockLocationProvider extends LocationProvider {

        private ProviderRequest mCurrentRequest;

        private MockLocationProvider(String name) {
            super(name);
        }

        @Override
        public void attachLocked(AbstractLocationProvider provider) {
            checkState(provider instanceof MockProvider);
            super.attachLocked(provider);
        }

        public boolean isMock() {
            return true;
        }

        @GuardedBy("mLock")
        public void setEnabledLocked(boolean enabled) {
            if (mProvider != null) {
                long identity = Binder.clearCallingIdentity();
                try {
                    ((MockProvider) mProvider).setEnabled(enabled);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
        }

        @GuardedBy("mLock")
        public void setLocationLocked(Location location) {
            if (mProvider != null) {
                long identity = Binder.clearCallingIdentity();
                try {
                    ((MockProvider) mProvider).setLocation(location);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
        }

        @Override
        @GuardedBy("mLock")
        public void setRequestLocked(ProviderRequest request, WorkSource workSource) {
            super.setRequestLocked(request, workSource);
            mCurrentRequest = request;
        }

        @GuardedBy("mLock")
        public void setStatusLocked(int status, Bundle extras, long updateTime) {
            if (mProvider != null) {
                long identity = Binder.clearCallingIdentity();
                try {
                    ((MockProvider) mProvider).setStatus(status, extras, updateTime);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
        }
    }

    /**
     * A wrapper class holding either an ILocationListener or a PendingIntent to receive
     * location updates.
     */
    private final class Receiver extends LinkedListenerBase implements PendingIntent.OnFinished {
        private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
        private final int mAllowedResolutionLevel;  // resolution level allowed to receiver

        private final ILocationListener mListener;
        final PendingIntent mPendingIntent;
        final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
        private final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
        private final Object mKey;

        final HashMap<String, UpdateRecord> mUpdateRecords = new HashMap<>();

        // True if app ops has started monitoring this receiver for locations.
        private boolean mOpMonitoring;
        // True if app ops has started monitoring this receiver for high power (gps) locations.
        private boolean mOpHighPowerMonitoring;
        private int mPendingBroadcasts;
        PowerManager.WakeLock mWakeLock;

        private Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
                String packageName, WorkSource workSource, boolean hideFromAppOps) {
            super(new CallerIdentity(uid, pid, packageName), "LocationListener");
            mListener = listener;
            mPendingIntent = intent;
            if (listener != null) {
                mKey = listener.asBinder();
            } else {
                mKey = intent;
            }
            mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
            if (workSource != null && workSource.isEmpty()) {
                workSource = null;
            }
            mWorkSource = workSource;
            mHideFromAppOps = hideFromAppOps;

            updateMonitoring(true);

            // construct/configure wakelock
            mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
            if (workSource == null) {
                workSource = new WorkSource(mCallerIdentity.mUid, mCallerIdentity.mPackageName);
            }
            mWakeLock.setWorkSource(workSource);

            // For a non-reference counted wakelock, each acquire will reset the timeout, and we
            // only need to release it once.
            mWakeLock.setReferenceCounted(false);
        }

        @Override
        public boolean equals(Object otherObj) {
            return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
        }

        @Override
        public int hashCode() {
            return mKey.hashCode();
        }

        @Override
        public String toString() {
            StringBuilder s = new StringBuilder();
            s.append("Reciever[");
            s.append(Integer.toHexString(System.identityHashCode(this)));
            if (mListener != null) {
                s.append(" listener");
            } else {
                s.append(" intent");
            }
            for (String p : mUpdateRecords.keySet()) {
                s.append(" ").append(mUpdateRecords.get(p).toString());
            }
            s.append(" monitoring location: ").append(mOpMonitoring);
            s.append("]");
            return s.toString();
        }

        /**
         * Update AppOp monitoring for this receiver.
         *
         * @param allow If true receiver is currently active, if false it's been removed.
         */
        public void updateMonitoring(boolean allow) {
            if (mHideFromAppOps) {
                return;
            }

            boolean requestingLocation = false;
            boolean requestingHighPowerLocation = false;
            if (allow) {
                // See if receiver has any enabled update records.  Also note if any update records
                // are high power (has a high power provider with an interval under a threshold).
                for (UpdateRecord updateRecord : mUpdateRecords.values()) {
                    LocationProvider provider = getLocationProviderLocked(updateRecord.mProvider);
                    if (provider == null) {
                        continue;
                    }
                    if (!provider.isUseableLocked() && !isSettingsExemptLocked(updateRecord)) {
                        continue;
                    }

                    requestingLocation = true;
                    ProviderProperties properties = provider.getPropertiesLocked();
                    if (properties != null
                            && properties.mPowerRequirement == Criteria.POWER_HIGH
                            && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
                        requestingHighPowerLocation = true;
                        break;
                    }
                }
            }

            // First update monitoring of any location request (including high power).
            mOpMonitoring = updateMonitoring(
                    requestingLocation,
                    mOpMonitoring,
                    AppOpsManager.OP_MONITOR_LOCATION);

            // Now update monitoring of high power requests only.
            boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
            mOpHighPowerMonitoring = updateMonitoring(
                    requestingHighPowerLocation,
                    mOpHighPowerMonitoring,
                    AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
            if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
                // Send an intent to notify that a high power request has been added/removed.
                Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
                mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
            }
        }

        /**
         * Update AppOps monitoring for a single location request and op type.
         *
         * @param allowMonitoring     True if monitoring is allowed for this request/op.
         * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
         * @param op                  AppOps code for the op to update.
         * @return True if monitoring is on for this request/op after updating.
         */
        private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
                int op) {
            if (!currentlyMonitoring) {
                if (allowMonitoring) {
                    return mAppOps.startOpNoThrow(op, mCallerIdentity.mUid,
                            mCallerIdentity.mPackageName) == AppOpsManager.MODE_ALLOWED;
                }
            } else {
                if (!allowMonitoring
                        || mAppOps.checkOpNoThrow(op, mCallerIdentity.mUid,
                        mCallerIdentity.mPackageName) != AppOpsManager.MODE_ALLOWED) {
                    mAppOps.finishOp(op, mCallerIdentity.mUid, mCallerIdentity.mPackageName);
                    return false;
                }
            }

            return currentlyMonitoring;
        }

        public boolean isListener() {
            return mListener != null;
        }

        public boolean isPendingIntent() {
            return mPendingIntent != null;
        }

        public ILocationListener getListener() {
            if (mListener != null) {
                return mListener;
            }
            throw new IllegalStateException("Request for non-existent listener");
        }

        public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
            if (mListener != null) {
                try {
                    mListener.onStatusChanged(provider, status, extras);
                    // call this after broadcasting so we do not increment
                    // if we throw an exception.
                    incrementPendingBroadcastsLocked();
                } catch (RemoteException e) {
                    return false;
                }
            } else {
                Intent statusChanged = new Intent();
                statusChanged.putExtras(new Bundle(extras));
                statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
                try {
                    mPendingIntent.send(mContext, 0, statusChanged, this, mHandler,
                            getResolutionPermission(mAllowedResolutionLevel),
                            PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
                    // call this after broadcasting so we do not increment
                    // if we throw an exception.
                    incrementPendingBroadcastsLocked();
                } catch (PendingIntent.CanceledException e) {
                    return false;
                }
            }
            return true;
        }

        public boolean callLocationChangedLocked(Location location) {
            if (mListener != null) {
                try {
                    mListener.onLocationChanged(new Location(location));
                    // call this after broadcasting so we do not increment
                    // if we throw an exception.
                    incrementPendingBroadcastsLocked();
                } catch (RemoteException e) {
                    return false;
                }
            } else {
                Intent locationChanged = new Intent();
                locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED,
                        new Location(location));
                try {
                    mPendingIntent.send(mContext, 0, locationChanged, this, mHandler,
                            getResolutionPermission(mAllowedResolutionLevel),
                            PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
                    // call this after broadcasting so we do not increment
                    // if we throw an exception.
                    incrementPendingBroadcastsLocked();
                } catch (PendingIntent.CanceledException e) {
                    return false;
                }
            }
            return true;
        }

        private boolean callProviderEnabledLocked(String provider, boolean enabled) {
            // First update AppOp monitoring.
            // An app may get/lose location access as providers are enabled/disabled.
            updateMonitoring(true);

            if (mListener != null) {
                try {
                    if (enabled) {
                        mListener.onProviderEnabled(provider);
                    } else {
                        mListener.onProviderDisabled(provider);
                    }
                    // call this after broadcasting so we do not increment
                    // if we throw an exception.
                    incrementPendingBroadcastsLocked();
                } catch (RemoteException e) {
                    return false;
                }
            } else {
                Intent providerIntent = new Intent();
                providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
                try {
                    mPendingIntent.send(mContext, 0, providerIntent, this, mHandler,
                            getResolutionPermission(mAllowedResolutionLevel),
                            PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
                    // call this after broadcasting so we do not increment
                    // if we throw an exception.
                    incrementPendingBroadcastsLocked();
                } catch (PendingIntent.CanceledException e) {
                    return false;
                }
            }
            return true;
        }

        @Override
        public void binderDied() {
            if (D) Log.d(TAG, "Remote " + mListenerName + " died.");

            synchronized (mLock) {
                removeUpdatesLocked(this);
                clearPendingBroadcastsLocked();
            }
        }

        @Override
        public void onSendFinished(PendingIntent pendingIntent, Intent intent,
                int resultCode, String resultData, Bundle resultExtras) {
            synchronized (mLock) {
                decrementPendingBroadcastsLocked();
            }
        }

        // this must be called while synchronized by caller in a synchronized block
        // containing the sending of the broadcaset
        private void incrementPendingBroadcastsLocked() {
            mPendingBroadcasts++;
            // so wakelock calls will succeed
            long identity = Binder.clearCallingIdentity();
            try {
                mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }

        private void decrementPendingBroadcastsLocked() {
            if (--mPendingBroadcasts == 0) {
                // so wakelock calls will succeed
                long identity = Binder.clearCallingIdentity();
                try {
                    if (mWakeLock.isHeld()) {
                        mWakeLock.release();
                    }
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
        }

        public void clearPendingBroadcastsLocked() {
            if (mPendingBroadcasts > 0) {
                mPendingBroadcasts = 0;
                // so wakelock calls will succeed
                long identity = Binder.clearCallingIdentity();
                try {
                    if (mWakeLock.isHeld()) {
                        mWakeLock.release();
                    }
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
        }
    }

    @Override
    public void locationCallbackFinished(ILocationListener listener) {
        //Do not use getReceiverLocked here as that will add the ILocationListener to
        //the receiver list if it is not found.  If it is not found then the
        //LocationListener was removed when it had a pending broadcast and should
        //not be added back.
        synchronized (mLock) {
            Receiver receiver = mReceivers.get(listener.asBinder());
            if (receiver != null) {
                receiver.decrementPendingBroadcastsLocked();
            }
        }
    }

    @Override
    public int getGnssYearOfHardware() {
        if (mGnssSystemInfoProvider != null) {
            return mGnssSystemInfoProvider.getGnssYearOfHardware();
        } else {
            return 0;
        }
    }

    @Override
    @Nullable
    public String getGnssHardwareModelName() {
        if (mGnssSystemInfoProvider != null) {
            return mGnssSystemInfoProvider.getGnssHardwareModelName();
        } else {
            return null;
        }
    }

    private boolean hasGnssPermissions(String packageName) {
        synchronized (mLock) {
            int allowedResolutionLevel = getCallerAllowedResolutionLevel();
            checkResolutionLevelIsSufficientForProviderUseLocked(
                    allowedResolutionLevel,
                    GPS_PROVIDER);

            int pid = Binder.getCallingPid();
            int uid = Binder.getCallingUid();
            long identity = Binder.clearCallingIdentity();
            try {
                return checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    @Override
    public int getGnssBatchSize(String packageName) {
        mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
                "Location Hardware permission not granted to access hardware batching");

        if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
            return mGnssBatchingProvider.getBatchSize();
        } else {
            return 0;
        }
    }

    @Override
    public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) {
        mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
                "Location Hardware permission not granted to access hardware batching");

        if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
            return false;
        }

        CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(),
                Binder.getCallingPid(), packageName);
        synchronized (mLock) {
            mGnssBatchingCallback = callback;
            mGnssBatchingDeathCallback =  new LinkedListener<>(callback,
                    "BatchedLocationCallback", callerIdentity,
                    (IBatchedLocationCallback listener) -> {
                        stopGnssBatch();
                        removeGnssBatchingCallback();
                    });
            if (!linkToListenerDeathNotificationLocked(callback.asBinder(),
                    mGnssBatchingDeathCallback)) {
                return false;
            }
            return true;
        }
    }

    @Override
    public void removeGnssBatchingCallback() {
        synchronized (mLock) {
            unlinkFromListenerDeathNotificationLocked(mGnssBatchingCallback.asBinder(),
                    mGnssBatchingDeathCallback);
            mGnssBatchingCallback = null;
            mGnssBatchingDeathCallback = null;
        }
    }

    @Override
    public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
        mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
                "Location Hardware permission not granted to access hardware batching");

        if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
            return false;
        }

        synchronized (mLock) {
            if (mGnssBatchingInProgress) {
                // Current design does not expect multiple starts to be called repeatedly
                Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch");
                // Try to clean up anyway, and continue
                stopGnssBatch();
            }

            mGnssBatchingInProgress = true;
            return mGnssBatchingProvider.start(periodNanos, wakeOnFifoFull);
        }
    }

    @Override
    public void flushGnssBatch(String packageName) {
        mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
                "Location Hardware permission not granted to access hardware batching");

        if (!hasGnssPermissions(packageName)) {
            Log.e(TAG, "flushGnssBatch called without GNSS permissions");
            return;
        }

        synchronized (mLock) {
            if (!mGnssBatchingInProgress) {
                Log.w(TAG, "flushGnssBatch called with no batch in progress");
            }

            if (mGnssBatchingProvider != null) {
                mGnssBatchingProvider.flush();
            }
        }
    }

    @Override
    public boolean stopGnssBatch() {
        mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
                "Location Hardware permission not granted to access hardware batching");

        synchronized (mLock) {
            if (mGnssBatchingProvider != null) {
                mGnssBatchingInProgress = false;
                return mGnssBatchingProvider.stop();
            } else {
                return false;
            }
        }
    }

    @GuardedBy("mLock")
    private void addProviderLocked(LocationProvider provider) {
        Preconditions.checkState(getLocationProviderLocked(provider.getName()) == null);

        mProviders.add(provider);

        provider.onAllowedChangedLocked();  // allowed state may change while provider was inactive
        provider.onUseableChangedLocked(false);
    }

    @GuardedBy("mLock")
    private void removeProviderLocked(LocationProvider provider) {
        if (mProviders.remove(provider)) {
            provider.onUseableChangedLocked(false);
        }
    }

    @GuardedBy("mLock")
    @Nullable
    private LocationProvider getLocationProviderLocked(String providerName) {
        for (LocationProvider provider : mProviders) {
            if (providerName.equals(provider.getName())) {
                return provider;
            }
        }

        return null;
    }

    private String getResolutionPermission(int resolutionLevel) {
        switch (resolutionLevel) {
            case RESOLUTION_LEVEL_FINE:
                return android.Manifest.permission.ACCESS_FINE_LOCATION;
            case RESOLUTION_LEVEL_COARSE:
                return android.Manifest.permission.ACCESS_COARSE_LOCATION;
            default:
                return null;
        }
    }

    private int getAllowedResolutionLevel(int pid, int uid) {
        if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
                pid, uid) == PERMISSION_GRANTED) {
            return RESOLUTION_LEVEL_FINE;
        } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
                pid, uid) == PERMISSION_GRANTED) {
            return RESOLUTION_LEVEL_COARSE;
        } else {
            return RESOLUTION_LEVEL_NONE;
        }
    }

    private int getCallerAllowedResolutionLevel() {
        return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
    }

    private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
        if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
            throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
        }
    }

    @GuardedBy("mLock")
    private int getMinimumResolutionLevelForProviderUseLocked(String provider) {
        if (GPS_PROVIDER.equals(provider) || PASSIVE_PROVIDER.equals(provider)) {
            // gps and passive providers require FINE permission
            return RESOLUTION_LEVEL_FINE;
        } else if (NETWORK_PROVIDER.equals(provider) || FUSED_PROVIDER.equals(provider)) {
            // network and fused providers are ok with COARSE or FINE
            return RESOLUTION_LEVEL_COARSE;
        } else {
            for (LocationProvider lp : mProviders) {
                if (!lp.getName().equals(provider)) {
                    continue;
                }

                ProviderProperties properties = lp.getPropertiesLocked();
                if (properties != null) {
                    if (properties.mRequiresSatellite) {
                        // provider requiring satellites require FINE permission
                        return RESOLUTION_LEVEL_FINE;
                    } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
                        // provider requiring network and or cell require COARSE or FINE
                        return RESOLUTION_LEVEL_COARSE;
                    }
                }
            }
        }

        return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
    }

    @GuardedBy("mLock")
    private void checkResolutionLevelIsSufficientForProviderUseLocked(int allowedResolutionLevel,
            String providerName) {
        int requiredResolutionLevel = getMinimumResolutionLevelForProviderUseLocked(providerName);
        if (allowedResolutionLevel < requiredResolutionLevel) {
            switch (requiredResolutionLevel) {
                case RESOLUTION_LEVEL_FINE:
                    throw new SecurityException("\"" + providerName + "\" location provider " +
                            "requires ACCESS_FINE_LOCATION permission.");
                case RESOLUTION_LEVEL_COARSE:
                    throw new SecurityException("\"" + providerName + "\" location provider " +
                            "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
                default:
                    throw new SecurityException("Insufficient permission for \"" + providerName +
                            "\" location provider.");
            }
        }
    }

    public static int resolutionLevelToOp(int allowedResolutionLevel) {
        if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
            if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
                return AppOpsManager.OP_COARSE_LOCATION;
            } else {
                return AppOpsManager.OP_FINE_LOCATION;
            }
        }
        return -1;
    }

    private static String resolutionLevelToOpStr(int allowedResolutionLevel) {
        switch (allowedResolutionLevel) {
            case RESOLUTION_LEVEL_COARSE:
                return AppOpsManager.OPSTR_COARSE_LOCATION;
            case RESOLUTION_LEVEL_FINE:
                return AppOpsManager.OPSTR_FINE_LOCATION;
            case RESOLUTION_LEVEL_NONE:
                // The client is not allowed to get any location, so both FINE and COARSE ops will
                // be denied. Pick the most restrictive one to be safe.
                return AppOpsManager.OPSTR_FINE_LOCATION;
            default:
                // Use the most restrictive ops if not sure.
                return AppOpsManager.OPSTR_FINE_LOCATION;
        }
    }

    private boolean reportLocationAccessNoThrow(
            int pid, int uid, String packageName, int allowedResolutionLevel) {
        int op = resolutionLevelToOp(allowedResolutionLevel);
        if (op >= 0) {
            if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
                return false;
            }
        }

        return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
    }

    private boolean checkLocationAccess(int pid, int uid, String packageName,
            int allowedResolutionLevel) {
        int op = resolutionLevelToOp(allowedResolutionLevel);
        if (op >= 0) {
            if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
                return false;
            }
        }

        return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
    }

    /**
     * Returns all providers by name, including passive and the ones that are not permitted to
     * be accessed by the calling activity or are currently disabled, but excluding fused.
     */
    @Override
    public List<String> getAllProviders() {
        synchronized (mLock) {
            ArrayList<String> providers = new ArrayList<>(mProviders.size());
            for (LocationProvider provider : mProviders) {
                String name = provider.getName();
                if (FUSED_PROVIDER.equals(name)) {
                    continue;
                }
                providers.add(name);
            }
            return providers;
        }
    }

    /**
     * Return all providers by name, that match criteria and are optionally
     * enabled.
     * Can return passive provider, but never returns fused provider.
     */
    @Override
    public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
        synchronized (mLock) {
            ArrayList<String> providers = new ArrayList<>(mProviders.size());
            for (LocationProvider provider : mProviders) {
                String name = provider.getName();
                if (FUSED_PROVIDER.equals(name)) {
                    continue;
                }
                if (allowedResolutionLevel < getMinimumResolutionLevelForProviderUseLocked(name)) {
                    continue;
                }
                if (enabledOnly && !provider.isUseableLocked()) {
                    continue;
                }
                if (criteria != null
                        && !android.location.LocationProvider.propertiesMeetCriteria(
                        name, provider.getPropertiesLocked(), criteria)) {
                    continue;
                }
                providers.add(name);
            }
            return providers;
        }
    }

    /**
     * Return the name of the best provider given a Criteria object.
     * This method has been deprecated from the public API,
     * and the whole LocationProvider (including #meetsCriteria)
     * has been deprecated as well. So this method now uses
     * some simplified logic.
     */
    @Override
    public String getBestProvider(Criteria criteria, boolean enabledOnly) {
        List<String> providers = getProviders(criteria, enabledOnly);
        if (providers.isEmpty()) {
            providers = getProviders(null, enabledOnly);
        }

        if (!providers.isEmpty()) {
            if (providers.contains(GPS_PROVIDER)) {
                return GPS_PROVIDER;
            } else if (providers.contains(NETWORK_PROVIDER)) {
                return NETWORK_PROVIDER;
            } else {
                return providers.get(0);
            }
        }

        return null;
    }

    @GuardedBy("mLock")
    private void updateProviderUseableLocked(LocationProvider provider) {
        boolean useable = provider.isUseableLocked();

        ArrayList<Receiver> deadReceivers = null;

        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider.getName());
        if (records != null) {
            for (UpdateRecord record : records) {
                if (!isCurrentProfileLocked(
                        UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
                    continue;
                }

                // requests that ignore location settings will never provide notifications
                if (isSettingsExemptLocked(record)) {
                    continue;
                }

                // Sends a notification message to the receiver
                if (!record.mReceiver.callProviderEnabledLocked(provider.getName(), useable)) {
                    if (deadReceivers == null) {
                        deadReceivers = new ArrayList<>();
                    }
                    deadReceivers.add(record.mReceiver);
                }
            }
        }

        if (deadReceivers != null) {
            for (int i = deadReceivers.size() - 1; i >= 0; i--) {
                removeUpdatesLocked(deadReceivers.get(i));
            }
        }

        applyRequirementsLocked(provider);
    }

    @GuardedBy("mLock")
    private void applyRequirementsLocked(String providerName) {
        LocationProvider provider = getLocationProviderLocked(providerName);
        if (provider != null) {
            applyRequirementsLocked(provider);
        }
    }

    @GuardedBy("mLock")
    private void applyRequirementsLocked(LocationProvider provider) {
        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider.getName());
        WorkSource worksource = new WorkSource();
        ProviderRequest providerRequest = new ProviderRequest();

        // if provider is not active, it should not respond to requests

        if (mProviders.contains(provider) && records != null && !records.isEmpty()) {
            long backgroundThrottleInterval;

            long identity = Binder.clearCallingIdentity();
            try {
                backgroundThrottleInterval = Settings.Global.getLong(
                        mContext.getContentResolver(),
                        Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
                        DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
            } finally {
                Binder.restoreCallingIdentity(identity);
            }

            final boolean isForegroundOnlyMode =
                    mBatterySaverMode == PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
            final boolean shouldThrottleRequests =
                    mBatterySaverMode
                            == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF
                            && !mPowerManager.isInteractive();
            // initialize the low power mode to true and set to false if any of the records requires
            providerRequest.lowPowerMode = true;
            for (UpdateRecord record : records) {
                if (!isCurrentProfileLocked(
                        UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
                    continue;
                }
                if (!checkLocationAccess(
                        record.mReceiver.mCallerIdentity.mPid,
                        record.mReceiver.mCallerIdentity.mUid,
                        record.mReceiver.mCallerIdentity.mPackageName,
                        record.mReceiver.mAllowedResolutionLevel)) {
                    continue;
                }
                final boolean isBatterySaverDisablingLocation = shouldThrottleRequests
                        || (isForegroundOnlyMode && !record.mIsForegroundUid);
                if (!provider.isUseableLocked() || isBatterySaverDisablingLocation) {
                    if (isSettingsExemptLocked(record)) {
                        providerRequest.locationSettingsIgnored = true;
                        providerRequest.lowPowerMode = false;
                    } else {
                        continue;
                    }
                }

                LocationRequest locationRequest = record.mRealRequest;
                long interval = locationRequest.getInterval();


                // if we're forcing location, don't apply any throttling
                if (!providerRequest.locationSettingsIgnored && !isThrottlingExemptLocked(
                        record.mReceiver.mCallerIdentity)) {
                    if (!record.mIsForegroundUid) {
                        interval = Math.max(interval, backgroundThrottleInterval);
                    }
                    if (interval != locationRequest.getInterval()) {
                        locationRequest = new LocationRequest(locationRequest);
                        locationRequest.setInterval(interval);
                    }
                }

                record.mRequest = locationRequest;
                providerRequest.locationRequests.add(locationRequest);
                if (!locationRequest.isLowPowerMode()) {
                    providerRequest.lowPowerMode = false;
                }
                if (interval < providerRequest.interval) {
                    providerRequest.reportLocation = true;
                    providerRequest.interval = interval;
                }
            }

            if (providerRequest.reportLocation) {
                // calculate who to blame for power
                // This is somewhat arbitrary. We pick a threshold interval
                // that is slightly higher that the minimum interval, and
                // spread the blame across all applications with a request
                // under that threshold.
                long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
                for (UpdateRecord record : records) {
                    if (isCurrentProfileLocked(
                            UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) {
                        LocationRequest locationRequest = record.mRequest;

                        // Don't assign battery blame for update records whose
                        // client has no permission to receive location data.
                        if (!providerRequest.locationRequests.contains(locationRequest)) {
                            continue;
                        }

                        if (locationRequest.getInterval() <= thresholdInterval) {
                            if (record.mReceiver.mWorkSource != null
                                    && isValidWorkSource(record.mReceiver.mWorkSource)) {
                                worksource.add(record.mReceiver.mWorkSource);
                            } else {
                                // Assign blame to caller if there's no WorkSource associated with
                                // the request or if it's invalid.
                                worksource.add(
                                        record.mReceiver.mCallerIdentity.mUid,
                                        record.mReceiver.mCallerIdentity.mPackageName);
                            }
                        }
                    }
                }
            }
        }

        provider.setRequestLocked(providerRequest, worksource);
    }

    /**
     * Whether a given {@code WorkSource} associated with a Location request is valid.
     */
    private static boolean isValidWorkSource(WorkSource workSource) {
        if (workSource.size() > 0) {
            // If the WorkSource has one or more non-chained UIDs, make sure they're accompanied
            // by tags.
            return workSource.getName(0) != null;
        } else {
            // For now, make sure callers have supplied an attribution tag for use with
            // AppOpsManager. This might be relaxed in the future.
            final ArrayList<WorkChain> workChains = workSource.getWorkChains();
            return workChains != null && !workChains.isEmpty() &&
                    workChains.get(0).getAttributionTag() != null;
        }
    }

    @Override
    public String[] getBackgroundThrottlingWhitelist() {
        synchronized (mLock) {
            return mBackgroundThrottlePackageWhitelist.toArray(new String[0]);
        }
    }

    @Override
    public String[] getIgnoreSettingsWhitelist() {
        synchronized (mLock) {
            return mIgnoreSettingsPackageWhitelist.toArray(new String[0]);
        }
    }

    @GuardedBy("mLock")
    private boolean isThrottlingExemptLocked(CallerIdentity callerIdentity) {
        if (callerIdentity.mUid == Process.SYSTEM_UID) {
            return true;
        }

        if (mBackgroundThrottlePackageWhitelist.contains(callerIdentity.mPackageName)) {
            return true;
        }

        return isProviderPackage(callerIdentity.mPackageName);

    }

    @GuardedBy("mLock")
    private boolean isSettingsExemptLocked(UpdateRecord record) {
        if (!record.mRealRequest.isLocationSettingsIgnored()) {
            return false;
        }

        if (mIgnoreSettingsPackageWhitelist.contains(
                record.mReceiver.mCallerIdentity.mPackageName)) {
            return true;
        }

        return isProviderPackage(record.mReceiver.mCallerIdentity.mPackageName);

    }

    private class UpdateRecord {
        final String mProvider;
        private final LocationRequest mRealRequest;  // original request from client
        LocationRequest mRequest;  // possibly throttled version of the request
        private final Receiver mReceiver;
        private boolean mIsForegroundUid;
        private Location mLastFixBroadcast;
        private long mLastStatusBroadcast;
        private Throwable mStackTrace;  // for debugging only

        /**
         * Note: must be constructed with lock held.
         */
        private UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
            mProvider = provider;
            mRealRequest = request;
            mRequest = request;
            mReceiver = receiver;
            mIsForegroundUid = isImportanceForeground(
                    mActivityManager.getPackageImportance(mReceiver.mCallerIdentity.mPackageName));

            if (D && receiver.mCallerIdentity.mPid == Process.myPid()) {
                mStackTrace = new Throwable();
            }

            ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
            if (records == null) {
                records = new ArrayList<>();
                mRecordsByProvider.put(provider, records);
            }
            if (!records.contains(this)) {
                records.add(this);
            }

            // Update statistics for historical location requests by package/provider
            mRequestStatistics.startRequesting(
                    mReceiver.mCallerIdentity.mPackageName, provider, request.getInterval(),
                    mIsForegroundUid);
        }

        /**
         * Method to be called when record changes foreground/background
         */
        private void updateForeground(boolean isForeground) {
            mIsForegroundUid = isForeground;
            mRequestStatistics.updateForeground(
                    mReceiver.mCallerIdentity.mPackageName, mProvider, isForeground);
        }

        /**
         * Method to be called when a record will no longer be used.
         */
        private void disposeLocked(boolean removeReceiver) {
            String packageName = mReceiver.mCallerIdentity.mPackageName;
            mRequestStatistics.stopRequesting(packageName, mProvider);

            mLocationUsageLogger.logLocationApiUsage(
                    LocationStatsEnums.USAGE_ENDED,
                    LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
                    packageName,
                    mRealRequest,
                    mReceiver.isListener(),
                    mReceiver.isPendingIntent(),
                    /* geofence= */ null,
                    mActivityManager.getPackageImportance(packageName));

            // remove from mRecordsByProvider
            ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
            if (globalRecords != null) {
                globalRecords.remove(this);
            }

            if (!removeReceiver) return;  // the caller will handle the rest

            // remove from Receiver#mUpdateRecords
            HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
            receiverRecords.remove(this.mProvider);

            // and also remove the Receiver if it has no more update records
            if (receiverRecords.size() == 0) {
                removeUpdatesLocked(mReceiver);
            }
        }

        @Override
        public String toString() {
            StringBuilder b = new StringBuilder("UpdateRecord[");
            b.append(mProvider).append(" ");
            b.append(mReceiver.mCallerIdentity.mPackageName);
            b.append("(").append(mReceiver.mCallerIdentity.mUid);
            if (mIsForegroundUid) {
                b.append(" foreground");
            } else {
                b.append(" background");
            }
            b.append(") ");
            b.append(mRealRequest).append(" ").append(mReceiver.mWorkSource);

            if (mStackTrace != null) {
                ByteArrayOutputStream tmp = new ByteArrayOutputStream();
                mStackTrace.printStackTrace(new PrintStream(tmp));
                b.append("\n\n").append(tmp.toString()).append("\n");
            }

            b.append("]");
            return b.toString();
        }
    }

    @GuardedBy("mLock")
    private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
            String packageName, WorkSource workSource, boolean hideFromAppOps) {
        IBinder binder = listener.asBinder();
        Receiver receiver = mReceivers.get(binder);
        if (receiver == null) {
            receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
                    hideFromAppOps);
            if (!linkToListenerDeathNotificationLocked(receiver.getListener().asBinder(),
                    receiver)) {
                return null;
            }
            mReceivers.put(binder, receiver);
        }
        return receiver;
    }

    @GuardedBy("mLock")
    private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
            WorkSource workSource, boolean hideFromAppOps) {
        Receiver receiver = mReceivers.get(intent);
        if (receiver == null) {
            receiver = new Receiver(null, intent, pid, uid, packageName, workSource,
                    hideFromAppOps);
            mReceivers.put(intent, receiver);
        }
        return receiver;
    }

    /**
     * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
     * and consistency requirements.
     *
     * @param request the LocationRequest from which to create a sanitized version
     * @return a version of request that meets the given resolution and consistency requirements
     * @hide
     */
    private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel,
            boolean callerHasLocationHardwarePermission) {
        LocationRequest sanitizedRequest = new LocationRequest(request);
        if (!callerHasLocationHardwarePermission) {
            // allow setting low power mode only for callers with location hardware permission
            sanitizedRequest.setLowPowerMode(false);
        }
        if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
            switch (sanitizedRequest.getQuality()) {
                case LocationRequest.ACCURACY_FINE:
                    sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
                    break;
                case LocationRequest.POWER_HIGH:
                    sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
                    break;
            }
            // throttle
            if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
                sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
            }
            if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
                sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
            }
        }
        // make getFastestInterval() the minimum of interval and fastest interval
        if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
            sanitizedRequest.setFastestInterval(request.getInterval());
        }
        return sanitizedRequest;
    }

    private void checkPackageName(String packageName) {
        if (packageName == null) {
            throw new SecurityException("invalid package name: " + null);
        }
        int uid = Binder.getCallingUid();
        String[] packages = mPackageManager.getPackagesForUid(uid);
        if (packages == null) {
            throw new SecurityException("invalid UID " + uid);
        }
        for (String pkg : packages) {
            if (packageName.equals(pkg)) return;
        }
        throw new SecurityException("invalid package name: " + packageName);
    }

    @Override
    public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
            PendingIntent intent, String packageName) {
        synchronized (mLock) {
            if (request == null) request = DEFAULT_LOCATION_REQUEST;
            checkPackageName(packageName);
            int allowedResolutionLevel = getCallerAllowedResolutionLevel();
            checkResolutionLevelIsSufficientForProviderUseLocked(allowedResolutionLevel,
                    request.getProvider());
            WorkSource workSource = request.getWorkSource();
            if (workSource != null && !workSource.isEmpty()) {
                mContext.enforceCallingOrSelfPermission(
                        Manifest.permission.UPDATE_DEVICE_STATS, null);
            }
            boolean hideFromAppOps = request.getHideFromAppOps();
            if (hideFromAppOps) {
                mContext.enforceCallingOrSelfPermission(
                        Manifest.permission.UPDATE_APP_OPS_STATS, null);
            }
            if (request.isLocationSettingsIgnored()) {
                mContext.enforceCallingOrSelfPermission(
                        Manifest.permission.WRITE_SECURE_SETTINGS, null);
            }
            boolean callerHasLocationHardwarePermission =
                    mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
                            == PERMISSION_GRANTED;
            LocationRequest sanitizedRequest = createSanitizedRequest(request,
                    allowedResolutionLevel,
                    callerHasLocationHardwarePermission);

            final int pid = Binder.getCallingPid();
            final int uid = Binder.getCallingUid();

            long identity = Binder.clearCallingIdentity();
            try {

                // We don't check for MODE_IGNORED here; we will do that when we go to deliver
                // a location.
                checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);

                if (intent == null && listener == null) {
                    throw new IllegalArgumentException("need either listener or intent");
                } else if (intent != null && listener != null) {
                    throw new IllegalArgumentException(
                            "cannot register both listener and intent");
                }

                mLocationUsageLogger.logLocationApiUsage(
                        LocationStatsEnums.USAGE_STARTED,
                        LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
                        packageName, request, listener != null, intent != null,
                        /* geofence= */ null,
                        mActivityManager.getPackageImportance(packageName));

                Receiver receiver;
                if (intent != null) {
                    receiver = getReceiverLocked(intent, pid, uid, packageName, workSource,
                            hideFromAppOps);
                } else {
                    receiver = getReceiverLocked(listener, pid, uid, packageName, workSource,
                            hideFromAppOps);
                }
                requestLocationUpdatesLocked(sanitizedRequest, receiver, uid, packageName);
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    @GuardedBy("mLock")
    private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
            int uid, String packageName) {
        // Figure out the provider. Either its explicitly request (legacy use cases), or
        // use the fused provider
        if (request == null) request = DEFAULT_LOCATION_REQUEST;
        String name = request.getProvider();
        if (name == null) {
            throw new IllegalArgumentException("provider name must not be null");
        }

        LocationProvider provider = getLocationProviderLocked(name);
        if (provider == null) {
            throw new IllegalArgumentException("provider doesn't exist: " + name);
        }

        UpdateRecord record = new UpdateRecord(name, request, receiver);
        if (D) {
            Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
                    + " " + name + " " + request + " from " + packageName + "(" + uid + " "
                    + (record.mIsForegroundUid ? "foreground" : "background")
                    + (isThrottlingExemptLocked(receiver.mCallerIdentity)
                    ? " [whitelisted]" : "") + ")");
        }

        UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
        if (oldRecord != null) {
            oldRecord.disposeLocked(false);
        }

        if (!provider.isUseableLocked() && !isSettingsExemptLocked(record)) {
            // Notify the listener that updates are currently disabled - but only if the request
            // does not ignore location settings
            receiver.callProviderEnabledLocked(name, false);
        }

        applyRequirementsLocked(name);

        // Update the monitoring here just in case multiple location requests were added to the
        // same receiver (this request may be high power and the initial might not have been).
        receiver.updateMonitoring(true);
    }

    @Override
    public void removeUpdates(ILocationListener listener, PendingIntent intent,
            String packageName) {
        checkPackageName(packageName);

        int pid = Binder.getCallingPid();
        int uid = Binder.getCallingUid();

        if (intent == null && listener == null) {
            throw new IllegalArgumentException("need either listener or intent");
        } else if (intent != null && listener != null) {
            throw new IllegalArgumentException("cannot register both listener and intent");
        }

        synchronized (mLock) {
            Receiver receiver;
            if (intent != null) {
                receiver = getReceiverLocked(intent, pid, uid, packageName, null, false);
            } else {
                receiver = getReceiverLocked(listener, pid, uid, packageName, null, false);
            }

            long identity = Binder.clearCallingIdentity();
            try {
                removeUpdatesLocked(receiver);
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    @GuardedBy("mLock")
    private void removeUpdatesLocked(Receiver receiver) {
        if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));

        if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
            unlinkFromListenerDeathNotificationLocked(receiver.getListener().asBinder(),
                    receiver);
            receiver.clearPendingBroadcastsLocked();
        }

        receiver.updateMonitoring(false);

        // Record which providers were associated with this listener
        HashSet<String> providers = new HashSet<>();
        HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
        if (oldRecords != null) {
            // Call dispose() on the obsolete update records.
            for (UpdateRecord record : oldRecords.values()) {
                // Update statistics for historical location requests by package/provider
                record.disposeLocked(false);
            }
            // Accumulate providers
            providers.addAll(oldRecords.keySet());
        }

        // update provider
        for (String provider : providers) {
            applyRequirementsLocked(provider);
        }
    }

    @Override
    public Location getLastLocation(LocationRequest r, String packageName) {
        synchronized (mLock) {
            LocationRequest request = r != null ? r : DEFAULT_LOCATION_REQUEST;
            int allowedResolutionLevel = getCallerAllowedResolutionLevel();
            checkPackageName(packageName);
            checkResolutionLevelIsSufficientForProviderUseLocked(allowedResolutionLevel,
                    request.getProvider());
            // no need to sanitize this request, as only the provider name is used

            final int pid = Binder.getCallingPid();
            final int uid = Binder.getCallingUid();
            final long identity = Binder.clearCallingIdentity();
            try {
                if (mBlacklist.isBlacklisted(packageName)) {
                    if (D) {
                        Log.d(TAG, "not returning last loc for blacklisted app: "
                                + packageName);
                    }
                    return null;
                }


                // Figure out the provider. Either its explicitly request (deprecated API's),
                // or use the fused provider
                String name = request.getProvider();
                if (name == null) name = LocationManager.FUSED_PROVIDER;
                LocationProvider provider = getLocationProviderLocked(name);
                if (provider == null) return null;

                // only the current user or location providers may get location this way
                if (!isCurrentProfileLocked(UserHandle.getUserId(uid)) && !isProviderPackage(
                        packageName)) {
                    return null;
                }

                if (!provider.isUseableLocked()) {
                    return null;
                }

                Location location;
                if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
                    // Make sure that an app with coarse permissions can't get frequent location
                    // updates by calling LocationManager.getLastKnownLocation repeatedly.
                    location = mLastLocationCoarseInterval.get(name);
                } else {
                    location = mLastLocation.get(name);
                }
                if (location == null) {
                    return null;
                }

                // Don't return stale location to apps with foreground-only location permission.
                String op = resolutionLevelToOpStr(allowedResolutionLevel);
                long locationAgeMs = SystemClock.elapsedRealtime()
                        - location.getElapsedRealtimeNanos() / NANOS_PER_MILLI;
                if ((locationAgeMs > Settings.Global.getLong(
                        mContext.getContentResolver(),
                        Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
                        DEFAULT_LAST_LOCATION_MAX_AGE_MS))
                        && (mAppOps.unsafeCheckOp(op, uid, packageName)
                        == AppOpsManager.MODE_FOREGROUND)) {
                    return null;
                }

                Location lastLocation = null;
                if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
                    Location noGPSLocation = location.getExtraLocation(
                            Location.EXTRA_NO_GPS_LOCATION);
                    if (noGPSLocation != null) {
                        lastLocation = new Location(mLocationFudger.getOrCreate(noGPSLocation));
                    }
                } else {
                    lastLocation = new Location(location);
                }
                // Don't report location access if there is no last location to deliver.
                if (lastLocation != null) {
                    if (!reportLocationAccessNoThrow(
                            pid, uid, packageName, allowedResolutionLevel)) {
                        if (D) {
                            Log.d(TAG, "not returning last loc for no op app: " + packageName);
                        }
                        lastLocation =  null;
                    }
                }
                return lastLocation;
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    @Override
    public LocationTime getGnssTimeMillis() {
        synchronized (mLock) {
            Location location = mLastLocation.get(LocationManager.GPS_PROVIDER);
            if (location == null) {
                return null;
            }
            long currentNanos = SystemClock.elapsedRealtimeNanos();
            long deltaMs = (currentNanos - location.getElapsedRealtimeNanos()) / 1000000L;
            return new LocationTime(location.getTime() + deltaMs, currentNanos);
        }
    }

    @Override
    public boolean injectLocation(Location location) {
        mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
                "Location Hardware permission not granted to inject location");
        mContext.enforceCallingPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
                "Access Fine Location permission not granted to inject Location");

        if (location == null) {
            if (D) {
                Log.d(TAG, "injectLocation(): called with null location");
            }
            return false;
        }

        synchronized (mLock) {
            LocationProvider provider = getLocationProviderLocked(location.getProvider());
            if (provider == null || !provider.isUseableLocked()) {
                return false;
            }

            // NOTE: If last location is already available, location is not injected.  If
            // provider's normal source (like a GPS chipset) have already provided an output
            // there is no need to inject this location.
            if (mLastLocation.get(provider.getName()) != null) {
                return false;
            }

            updateLastLocationLocked(location, provider.getName());
            return true;
        }
    }

    @Override
    public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
            String packageName) {
        if (request == null) request = DEFAULT_LOCATION_REQUEST;
        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
        checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
        if (intent == null) {
            throw new IllegalArgumentException("invalid pending intent: " + null);
        }
        checkPackageName(packageName);
        synchronized (mLock) {
            checkResolutionLevelIsSufficientForProviderUseLocked(allowedResolutionLevel,
                    request.getProvider());
        }
        // Require that caller can manage given document
        boolean callerHasLocationHardwarePermission =
                mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
                        == PERMISSION_GRANTED;
        LocationRequest sanitizedRequest = createSanitizedRequest(request,
                allowedResolutionLevel,
                callerHasLocationHardwarePermission);

        if (D) {
            Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
        }

        // geo-fence manager uses the public location API, need to clear identity
        int uid = Binder.getCallingUid();
        if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
            // temporary measure until geofences work for secondary users
            Log.w(TAG, "proximity alerts are currently available only to the primary user");
            return;
        }
        long identity = Binder.clearCallingIdentity();
        try {
            synchronized (mLock) {
                mLocationUsageLogger.logLocationApiUsage(
                        LocationStatsEnums.USAGE_STARTED,
                        LocationStatsEnums.API_REQUEST_GEOFENCE,
                        packageName,
                        request,
                        /* hasListener= */ false,
                        intent != null,
                        geofence,
                        mActivityManager.getPackageImportance(packageName));
            }

            mGeofenceManager.addFence(sanitizedRequest, geofence, intent,
                    allowedResolutionLevel,
                    uid, packageName);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
        if (intent == null) {
            throw new IllegalArgumentException("invalid pending intent: " + null);
        }
        checkPackageName(packageName);

        if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);

        // geo-fence manager uses the public location API, need to clear identity
        long identity = Binder.clearCallingIdentity();
        try {
            synchronized (mLock) {
                mLocationUsageLogger.logLocationApiUsage(
                        LocationStatsEnums.USAGE_ENDED,
                        LocationStatsEnums.API_REQUEST_GEOFENCE,
                        packageName,
                        /* LocationRequest= */ null,
                        /* hasListener= */ false,
                        intent != null,
                        geofence,
                        mActivityManager.getPackageImportance(packageName));
            }
            mGeofenceManager.removeFence(geofence, intent);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public boolean registerGnssStatusCallback(IGnssStatusListener listener, String packageName) {
        return addGnssDataListener(listener, packageName, "GnssStatusListener",
                mGnssStatusProvider, mGnssStatusListeners,
                this::unregisterGnssStatusCallback);
    }

    @Override
    public void unregisterGnssStatusCallback(IGnssStatusListener listener) {
        removeGnssDataListener(listener, mGnssStatusProvider, mGnssStatusListeners);
    }

    @Override
    public boolean addGnssMeasurementsListener(
            IGnssMeasurementsListener listener, String packageName) {
        return addGnssDataListener(listener, packageName, "GnssMeasurementsListener",
                mGnssMeasurementsProvider, mGnssMeasurementsListeners,
                this::removeGnssMeasurementsListener);
    }

    @Override
    public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
        removeGnssDataListener(listener, mGnssMeasurementsProvider, mGnssMeasurementsListeners);
    }

    private abstract static class LinkedListenerBase implements IBinder.DeathRecipient {
        protected final CallerIdentity mCallerIdentity;
        protected final String mListenerName;

        private LinkedListenerBase(@NonNull CallerIdentity callerIdentity,
                @NonNull String listenerName) {
            mCallerIdentity = callerIdentity;
            mListenerName = listenerName;
        }
    }

    private static class LinkedListener<TListener> extends LinkedListenerBase {
        private final TListener mListener;
        private final Consumer<TListener> mBinderDeathCallback;

        private LinkedListener(@NonNull TListener listener, String listenerName,
                @NonNull CallerIdentity callerIdentity,
                @NonNull Consumer<TListener> binderDeathCallback) {
            super(callerIdentity, listenerName);
            mListener = listener;
            mBinderDeathCallback = binderDeathCallback;
        }

        @Override
        public void binderDied() {
            if (D) Log.d(TAG, "Remote " + mListenerName + " died.");
            mBinderDeathCallback.accept(mListener);
        }
    }

    private <TListener extends IInterface> boolean addGnssDataListener(
            TListener listener, String packageName, String listenerName,
            RemoteListenerHelper<TListener> gnssDataProvider,
            ArrayMap<IBinder, LinkedListener<TListener>> gnssDataListeners,
            Consumer<TListener> binderDeathCallback) {
        if (!hasGnssPermissions(packageName) || gnssDataProvider == null) {
            return false;
        }

        CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(),
                Binder.getCallingPid(), packageName);
        LinkedListener<TListener> linkedListener = new LinkedListener<>(listener,
                listenerName, callerIdentity, binderDeathCallback);
        IBinder binder = listener.asBinder();
        synchronized (mLock) {
            if (!linkToListenerDeathNotificationLocked(binder, linkedListener)) {
                return false;
            }

            gnssDataListeners.put(binder, linkedListener);
            long identity = Binder.clearCallingIdentity();
            try {
                if (gnssDataProvider == mGnssMeasurementsProvider
                        || gnssDataProvider == mGnssStatusProvider) {
                    mLocationUsageLogger.logLocationApiUsage(
                            LocationStatsEnums.USAGE_STARTED,
                            gnssDataProvider == mGnssMeasurementsProvider
                                ? LocationStatsEnums.API_ADD_GNSS_MEASUREMENTS_LISTENER
                                : LocationStatsEnums.API_REGISTER_GNSS_STATUS_CALLBACK,
                            packageName,
                            /* LocationRequest= */ null,
                            /* hasListener= */ true,
                            /* hasIntent= */ false,
                            /* geofence= */ null,
                            mActivityManager.getPackageImportance(packageName));
                }
                if (isThrottlingExemptLocked(callerIdentity)
                        || isImportanceForeground(
                        mActivityManager.getPackageImportance(packageName))) {
                    gnssDataProvider.addListener(listener, callerIdentity);
                }
                return true;
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    private <TListener extends IInterface> void removeGnssDataListener(
            TListener listener, RemoteListenerHelper<TListener> gnssDataProvider,
            ArrayMap<IBinder, LinkedListener<TListener>> gnssDataListeners) {
        if (gnssDataProvider == null) {
            return;
        }

        IBinder binder = listener.asBinder();
        synchronized (mLock) {
            LinkedListener<TListener> linkedListener = gnssDataListeners.remove(binder);
            if (linkedListener == null) {
                return;
            }
            long identity = Binder.clearCallingIdentity();
            try {
                if (gnssDataProvider == mGnssMeasurementsProvider
                        || gnssDataProvider == mGnssStatusProvider) {
                    mLocationUsageLogger.logLocationApiUsage(
                            LocationStatsEnums.USAGE_ENDED,
                            gnssDataProvider == mGnssMeasurementsProvider
                                ? LocationStatsEnums.API_ADD_GNSS_MEASUREMENTS_LISTENER
                                : LocationStatsEnums.API_REGISTER_GNSS_STATUS_CALLBACK,
                            linkedListener.mCallerIdentity.mPackageName,
                            /* LocationRequest= */ null,
                            /* hasListener= */ true,
                            /* hasIntent= */ false,
                            /* geofence= */ null,
                            mActivityManager.getPackageImportance(
                                    linkedListener.mCallerIdentity.mPackageName));
                }
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
            unlinkFromListenerDeathNotificationLocked(binder, linkedListener);
            gnssDataProvider.removeListener(listener);
        }
    }

    private boolean linkToListenerDeathNotificationLocked(IBinder binder,
            LinkedListenerBase linkedListener) {
        try {
            binder.linkToDeath(linkedListener, 0 /* flags */);
            return true;
        } catch (RemoteException e) {
            // if the remote process registering the listener is already dead, just swallow the
            // exception and return
            Log.w(TAG, "Could not link " + linkedListener.mListenerName + " death callback.", e);
            return false;
        }
    }

    private boolean unlinkFromListenerDeathNotificationLocked(IBinder binder,
            LinkedListenerBase linkedListener) {
        try {
            binder.unlinkToDeath(linkedListener, 0 /* flags */);
            return true;
        } catch (NoSuchElementException e) {
            // if the death callback isn't connected (it should be...), log error,
            // swallow the exception and return
            Log.w(TAG, "Could not unlink " + linkedListener.mListenerName + " death callback.", e);
            return false;
        }
    }

    @Override
    public void injectGnssMeasurementCorrections(
            GnssMeasurementCorrections measurementCorrections, String packageName) {
        mContext.enforceCallingPermission(
                android.Manifest.permission.LOCATION_HARDWARE,
                "Location Hardware permission not granted to inject GNSS measurement corrections.");
        if (!hasGnssPermissions(packageName)) {
            Slog.e(TAG, "Can not inject GNSS corrections due to no permission.");
            return;
        }
        if (mGnssMeasurementCorrectionsProvider == null) {
            Slog.e(TAG, "Can not inject GNSS corrections. GNSS measurement corrections provider "
                    + "not available.");
            return;
        }
        mGnssMeasurementCorrectionsProvider.injectGnssMeasurementCorrections(
                measurementCorrections);
    }

    @Override
    public long getGnssCapabilities(String packageName) {
        mContext.enforceCallingPermission(
                android.Manifest.permission.LOCATION_HARDWARE,
                "Location Hardware permission not granted to obtain GNSS chipset capabilities.");
        if (!hasGnssPermissions(packageName) || mGnssCapabilitiesProvider == null) {
            return GnssCapabilities.INVALID_CAPABILITIES;
        }
        return mGnssCapabilitiesProvider.getGnssCapabilities();
    }

    @Override
    public boolean addGnssNavigationMessageListener(
            IGnssNavigationMessageListener listener, String packageName) {
        return addGnssDataListener(listener, packageName, "GnssNavigationMessageListener",
                mGnssNavigationMessageProvider, mGnssNavigationMessageListeners,
                this::removeGnssNavigationMessageListener);
    }

    @Override
    public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
        removeGnssDataListener(listener, mGnssNavigationMessageProvider,
                mGnssNavigationMessageListeners);
    }

    @Override
    public boolean sendExtraCommand(String providerName, String command, Bundle extras) {
        if (providerName == null) {
            // throw NullPointerException to remain compatible with previous implementation
            throw new NullPointerException();
        }
        synchronized (mLock) {
            checkResolutionLevelIsSufficientForProviderUseLocked(getCallerAllowedResolutionLevel(),
                    providerName);

            mLocationUsageLogger.logLocationApiUsage(
                    LocationStatsEnums.USAGE_STARTED,
                    LocationStatsEnums.API_SEND_EXTRA_COMMAND,
                    providerName);

            // and check for ACCESS_LOCATION_EXTRA_COMMANDS
            if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
                    != PERMISSION_GRANTED)) {
                throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
            }

            LocationProvider provider = getLocationProviderLocked(providerName);
            if (provider != null) {
                provider.sendExtraCommandLocked(command, extras);
            }

            mLocationUsageLogger.logLocationApiUsage(
                    LocationStatsEnums.USAGE_ENDED,
                    LocationStatsEnums.API_SEND_EXTRA_COMMAND,
                    providerName);

            return true;
        }
    }

    @Override
    public boolean sendNiResponse(int notifId, int userResponse) {
        if (Binder.getCallingUid() != Process.myUid()) {
            throw new SecurityException(
                    "calling sendNiResponse from outside of the system is not allowed");
        }
        try {
            return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
        } catch (RemoteException e) {
            Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
            return false;
        }
    }

    @Override
    public ProviderProperties getProviderProperties(String providerName) {
        synchronized (mLock) {
            checkResolutionLevelIsSufficientForProviderUseLocked(getCallerAllowedResolutionLevel(),
                    providerName);

            LocationProvider provider = getLocationProviderLocked(providerName);
            if (provider == null) {
                return null;
            }
            return provider.getPropertiesLocked();
        }
    }

    @Override
    public boolean isProviderPackage(String packageName) {
        synchronized (mLock) {
            for (LocationProvider provider : mProviders) {
                if (provider.getPackagesLocked().contains(packageName)) {
                    return true;
                }
            }

            return false;
        }
    }

    @Override
    public void setExtraLocationControllerPackage(String packageName) {
        mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
                Manifest.permission.LOCATION_HARDWARE + " permission required");
        synchronized (mLock) {
            mExtraLocationControllerPackage = packageName;
        }
    }

    @Override
    public String getExtraLocationControllerPackage() {
        synchronized (mLock) {
            return mExtraLocationControllerPackage;
        }
    }

    @Override
    public void setExtraLocationControllerPackageEnabled(boolean enabled) {
        mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
                Manifest.permission.LOCATION_HARDWARE + " permission required");
        synchronized (mLock) {
            mExtraLocationControllerPackageEnabled = enabled;
        }
    }

    @Override
    public boolean isExtraLocationControllerPackageEnabled() {
        synchronized (mLock) {
            return mExtraLocationControllerPackageEnabled
                    && (mExtraLocationControllerPackage != null);
        }
    }

    private boolean isLocationEnabled() {
        return isLocationEnabledForUser(mCurrentUserId);
    }

    @Override
    public boolean isLocationEnabledForUser(int userId) {
        // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
        if (UserHandle.getCallingUserId() != userId) {
            mContext.enforceCallingOrSelfPermission(
                    Manifest.permission.INTERACT_ACROSS_USERS,
                    "Requires INTERACT_ACROSS_USERS permission");
        }

        long identity = Binder.clearCallingIdentity();
        try {
            return Settings.Secure.getIntForUser(
                        mContext.getContentResolver(),
                        Settings.Secure.LOCATION_MODE,
                        Settings.Secure.LOCATION_MODE_OFF,
                        userId) != Settings.Secure.LOCATION_MODE_OFF;
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public boolean isProviderEnabledForUser(String providerName, int userId) {
        // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
        if (UserHandle.getCallingUserId() != userId) {
            mContext.enforceCallingOrSelfPermission(
                    Manifest.permission.INTERACT_ACROSS_USERS,
                    "Requires INTERACT_ACROSS_USERS permission");
        }

        // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
        // so we discourage its use
        if (FUSED_PROVIDER.equals(providerName)) return false;

        synchronized (mLock) {
            LocationProvider provider = getLocationProviderLocked(providerName);
            return provider != null && provider.isUseableForUserLocked(userId);
        }
    }

    @GuardedBy("mLock")
    private static boolean shouldBroadcastSafeLocked(
            Location loc, Location lastLoc, UpdateRecord record, long now) {
        // Always broadcast the first update
        if (lastLoc == null) {
            return true;
        }

        // Check whether sufficient time has passed
        long minTime = record.mRealRequest.getFastestInterval();
        long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
                / NANOS_PER_MILLI;
        if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
            return false;
        }

        // Check whether sufficient distance has been traveled
        double minDistance = record.mRealRequest.getSmallestDisplacement();
        if (minDistance > 0.0) {
            if (loc.distanceTo(lastLoc) <= minDistance) {
                return false;
            }
        }

        // Check whether sufficient number of udpates is left
        if (record.mRealRequest.getNumUpdates() <= 0) {
            return false;
        }

        // Check whether the expiry date has passed
        return record.mRealRequest.getExpireAt() >= now;
    }

    @GuardedBy("mLock")
    private void handleLocationChangedLocked(Location location, LocationProvider provider) {
        if (!mProviders.contains(provider)) {
            return;
        }
        if (!location.isComplete()) {
            Log.w(TAG, "Dropping incomplete location: " + location);
            return;
        }

        // only notify passive provider and update last location for locations that come from
        // useable providers
        if (provider.isUseableLocked()) {
            if (!provider.isPassiveLocked()) {
                mPassiveProvider.updateLocation(location);
            }
        }

        if (D) Log.d(TAG, "incoming location: " + location);
        long now = SystemClock.elapsedRealtime();
        if (provider.isUseableLocked()) {
            updateLastLocationLocked(location, provider.getName());
        }

        // Update last known coarse interval location if enough time has passed.
        Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(
                provider.getName());
        if (lastLocationCoarseInterval == null) {
            lastLocationCoarseInterval = new Location(location);

            if (provider.isUseableLocked()) {
                mLastLocationCoarseInterval.put(provider.getName(), lastLocationCoarseInterval);
            }
        }
        long timeDiffNanos = location.getElapsedRealtimeNanos()
                - lastLocationCoarseInterval.getElapsedRealtimeNanos();
        if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
            lastLocationCoarseInterval.set(location);
        }
        // Don't ever return a coarse location that is more recent than the allowed update
        // interval (i.e. don't allow an app to keep registering and unregistering for
        // location updates to overcome the minimum interval).
        Location noGPSLocation =
                lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);

        // Skip if there are no UpdateRecords for this provider.
        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider.getName());
        if (records == null || records.size() == 0) return;

        // Fetch coarse location
        Location coarseLocation = null;
        if (noGPSLocation != null) {
            coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
        }

        ArrayList<Receiver> deadReceivers = null;
        ArrayList<UpdateRecord> deadUpdateRecords = null;

        // Broadcast location to all listeners
        for (UpdateRecord r : records) {
            Receiver receiver = r.mReceiver;
            boolean receiverDead = false;

            if (!provider.isUseableLocked() && !isSettingsExemptLocked(r)) {
                continue;
            }

            int receiverUserId = UserHandle.getUserId(receiver.mCallerIdentity.mUid);
            if (!isCurrentProfileLocked(receiverUserId)
                    && !isProviderPackage(receiver.mCallerIdentity.mPackageName)) {
                if (D) {
                    Log.d(TAG, "skipping loc update for background user " + receiverUserId +
                            " (current user: " + mCurrentUserId + ", app: " +
                            receiver.mCallerIdentity.mPackageName + ")");
                }
                continue;
            }

            if (mBlacklist.isBlacklisted(receiver.mCallerIdentity.mPackageName)) {
                if (D) {
                    Log.d(TAG, "skipping loc update for blacklisted app: " +
                            receiver.mCallerIdentity.mPackageName);
                }
                continue;
            }

            Location notifyLocation;
            if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
                notifyLocation = coarseLocation;  // use coarse location
            } else {
                notifyLocation = location;  // use fine location
            }
            if (notifyLocation != null) {
                Location lastLoc = r.mLastFixBroadcast;
                if ((lastLoc == null)
                        || shouldBroadcastSafeLocked(notifyLocation, lastLoc, r, now)) {
                    if (lastLoc == null) {
                        lastLoc = new Location(notifyLocation);
                        r.mLastFixBroadcast = lastLoc;
                    } else {
                        lastLoc.set(notifyLocation);
                    }
                    // Report location access before delivering location to the client. This will
                    // note location delivery to appOps, so it should be called only when a
                    // location is really being delivered to the client.
                    if (!reportLocationAccessNoThrow(
                            receiver.mCallerIdentity.mPid,
                            receiver.mCallerIdentity.mUid,
                            receiver.mCallerIdentity.mPackageName,
                            receiver.mAllowedResolutionLevel)) {
                        if (D) {
                            Log.d(TAG, "skipping loc update for no op app: "
                                    + receiver.mCallerIdentity.mPackageName);
                        }
                        continue;
                    }
                    if (!receiver.callLocationChangedLocked(notifyLocation)) {
                        Slog.w(TAG, "RemoteException calling onLocationChanged on "
                                + receiver);
                        receiverDead = true;
                    }
                    r.mRealRequest.decrementNumUpdates();
                }
            }

            // TODO: location provider status callbacks have been disabled and deprecated, and are
            // guarded behind this setting now. should be removed completely post-Q
            if (Settings.Global.getInt(mContext.getContentResolver(),
                    LOCATION_DISABLE_STATUS_CALLBACKS, 1) == 0) {
                long newStatusUpdateTime = provider.getStatusUpdateTimeLocked();
                Bundle extras = new Bundle();
                int status = provider.getStatusLocked(extras);

                long prevStatusUpdateTime = r.mLastStatusBroadcast;
                if ((newStatusUpdateTime > prevStatusUpdateTime)
                        && (prevStatusUpdateTime != 0 || status != AVAILABLE)) {

                    r.mLastStatusBroadcast = newStatusUpdateTime;
                    if (!receiver.callStatusChangedLocked(provider.getName(), status, extras)) {
                        receiverDead = true;
                        Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
                    }
                }
            }

            // track expired records
            if (r.mRealRequest.getNumUpdates() <= 0 || r.mRealRequest.getExpireAt() < now) {
                if (deadUpdateRecords == null) {
                    deadUpdateRecords = new ArrayList<>();
                }
                deadUpdateRecords.add(r);
            }
            // track dead receivers
            if (receiverDead) {
                if (deadReceivers == null) {
                    deadReceivers = new ArrayList<>();
                }
                if (!deadReceivers.contains(receiver)) {
                    deadReceivers.add(receiver);
                }
            }
        }

        // remove dead records and receivers outside the loop
        if (deadReceivers != null) {
            for (Receiver receiver : deadReceivers) {
                removeUpdatesLocked(receiver);
            }
        }
        if (deadUpdateRecords != null) {
            for (UpdateRecord r : deadUpdateRecords) {
                r.disposeLocked(true);
            }
            applyRequirementsLocked(provider);
        }
    }

    @GuardedBy("mLock")
    private void updateLastLocationLocked(Location location, String provider) {
        Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
        Location lastNoGPSLocation;
        Location lastLocation = mLastLocation.get(provider);
        if (lastLocation == null) {
            lastLocation = new Location(provider);
            mLastLocation.put(provider, lastLocation);
        } else {
            lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
            if (noGPSLocation == null && lastNoGPSLocation != null) {
                // New location has no no-GPS location: adopt last no-GPS location. This is set
                // directly into location because we do not want to notify COARSE clients.
                location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
            }
        }
        lastLocation.set(location);
    }

    // Geocoder

    @Override
    public boolean geocoderIsPresent() {
        return mGeocodeProvider != null;
    }

    @Override
    public String getFromLocation(double latitude, double longitude, int maxResults,
            GeocoderParams params, List<Address> addrs) {
        if (mGeocodeProvider != null) {
            return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
                    params, addrs);
        }
        return null;
    }


    @Override
    public String getFromLocationName(String locationName,
            double lowerLeftLatitude, double lowerLeftLongitude,
            double upperRightLatitude, double upperRightLongitude, int maxResults,
            GeocoderParams params, List<Address> addrs) {

        if (mGeocodeProvider != null) {
            return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
                    lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
                    maxResults, params, addrs);
        }
        return null;
    }

    // Mock Providers

    private boolean canCallerAccessMockLocation(String opPackageName) {
        return mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(),
                opPackageName) == AppOpsManager.MODE_ALLOWED;
    }

    @Override
    public void addTestProvider(String name, ProviderProperties properties, String opPackageName) {
        if (!canCallerAccessMockLocation(opPackageName)) {
            return;
        }

        if (PASSIVE_PROVIDER.equals(name)) {
            throw new IllegalArgumentException("Cannot mock the passive location provider");
        }

        synchronized (mLock) {
            long identity = Binder.clearCallingIdentity();
            try {
                LocationProvider oldProvider = getLocationProviderLocked(name);
                if (oldProvider != null) {
                    if (oldProvider.isMock()) {
                        throw new IllegalArgumentException(
                                "Provider \"" + name + "\" already exists");
                    }

                    removeProviderLocked(oldProvider);
                }

                MockLocationProvider mockProviderManager = new MockLocationProvider(name);
                addProviderLocked(mockProviderManager);
                mockProviderManager.attachLocked(
                        new MockProvider(mContext, mockProviderManager, properties));
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    @Override
    public void removeTestProvider(String name, String opPackageName) {
        if (!canCallerAccessMockLocation(opPackageName)) {
            return;
        }

        synchronized (mLock) {
            long identity = Binder.clearCallingIdentity();
            try {
                LocationProvider testProvider = getLocationProviderLocked(name);
                if (testProvider == null || !testProvider.isMock()) {
                    throw new IllegalArgumentException("Provider \"" + name + "\" unknown");
                }

                removeProviderLocked(testProvider);

                // reinstate real provider if available
                LocationProvider realProvider = null;
                for (LocationProvider provider : mRealProviders) {
                    if (name.equals(provider.getName())) {
                        realProvider = provider;
                        break;
                    }
                }

                if (realProvider != null) {
                    addProviderLocked(realProvider);
                }
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    @Override
    public void setTestProviderLocation(String providerName, Location location,
            String opPackageName) {
        if (!canCallerAccessMockLocation(opPackageName)) {
            return;
        }

        synchronized (mLock) {
            LocationProvider testProvider = getLocationProviderLocked(providerName);
            if (testProvider == null || !testProvider.isMock()) {
                throw new IllegalArgumentException("Provider \"" + providerName + "\" unknown");
            }

            String locationProvider = location.getProvider();
            if (!TextUtils.isEmpty(locationProvider) && !providerName.equals(locationProvider)) {
                // The location has an explicit provider that is different from the mock
                // provider name. The caller may be trying to fool us via b/33091107.
                EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
                        providerName + "!=" + location.getProvider());
            }

            ((MockLocationProvider) testProvider).setLocationLocked(location);
        }
    }

    @Override
    public void setTestProviderEnabled(String providerName, boolean enabled, String opPackageName) {
        if (!canCallerAccessMockLocation(opPackageName)) {
            return;
        }

        synchronized (mLock) {
            LocationProvider testProvider = getLocationProviderLocked(providerName);
            if (testProvider == null || !testProvider.isMock()) {
                throw new IllegalArgumentException("Provider \"" + providerName + "\" unknown");
            }

            ((MockLocationProvider) testProvider).setEnabledLocked(enabled);
        }
    }

    @Override
    public void setTestProviderStatus(String providerName, int status, Bundle extras,
            long updateTime, String opPackageName) {
        if (!canCallerAccessMockLocation(opPackageName)) {
            return;
        }

        synchronized (mLock) {
            LocationProvider testProvider = getLocationProviderLocked(providerName);
            if (testProvider == null || !testProvider.isMock()) {
                throw new IllegalArgumentException("Provider \"" + providerName + "\" unknown");
            }

            ((MockLocationProvider) testProvider).setStatusLocked(status, extras, updateTime);
        }
    }

    @Override
    @NonNull
    public List<LocationRequest> getTestProviderCurrentRequests(String providerName,
            String opPackageName) {
        if (!canCallerAccessMockLocation(opPackageName)) {
            return Collections.emptyList();
        }

        synchronized (mLock) {
            LocationProvider testProvider = getLocationProviderLocked(providerName);
            if (testProvider == null || !testProvider.isMock()) {
                throw new IllegalArgumentException("Provider \"" + providerName + "\" unknown");
            }

            MockLocationProvider provider = (MockLocationProvider) testProvider;
            if (provider.mCurrentRequest == null) {
                return Collections.emptyList();
            }
            List<LocationRequest> requests = new ArrayList<>();
            for (LocationRequest request : provider.mCurrentRequest.locationRequests) {
                requests.add(new LocationRequest(request));
            }
            return requests;
        }
    }

    @Override
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;

        synchronized (mLock) {
            if (args.length > 0 && args[0].equals("--gnssmetrics")) {
                if (mGnssMetricsProvider != null) {
                    pw.append(mGnssMetricsProvider.getGnssMetricsAsProtoString());
                }
                return;
            }
            pw.println("Current Location Manager state:");
            pw.print("  Current System Time: "
                    + TimeUtils.logTimeOfDay(System.currentTimeMillis()));
            pw.println(", Current Elapsed Time: "
                    + TimeUtils.formatDuration(SystemClock.elapsedRealtime()));
            pw.println("  Current user: " + mCurrentUserId + " " + Arrays.toString(
                    mCurrentUserProfiles));
            pw.println("  Location mode: " + isLocationEnabled());
            pw.println("  Battery Saver Location Mode: "
                    + locationPowerSaveModeToString(mBatterySaverMode));
            pw.println("  Location Listeners:");
            for (Receiver receiver : mReceivers.values()) {
                pw.println("    " + receiver);
            }
            pw.println("  Active Records by Provider:");
            for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
                pw.println("    " + entry.getKey() + ":");
                for (UpdateRecord record : entry.getValue()) {
                    pw.println("      " + record);
                }
            }

            pw.println("  Active GnssMeasurement Listeners:");
            dumpGnssDataListenersLocked(pw, mGnssMeasurementsListeners);
            pw.println("  Active GnssNavigationMessage Listeners:");
            dumpGnssDataListenersLocked(pw, mGnssNavigationMessageListeners);
            pw.println("  Active GnssStatus Listeners:");
            dumpGnssDataListenersLocked(pw, mGnssStatusListeners);

            pw.println("  Historical Records by Provider:");
            for (Map.Entry<PackageProviderKey, PackageStatistics> entry
                    : mRequestStatistics.statistics.entrySet()) {
                PackageProviderKey key = entry.getKey();
                PackageStatistics stats = entry.getValue();
                pw.println("    " + key.packageName + ": " + key.providerName + ": " + stats);
            }
            pw.println("  Last Known Locations:");
            for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
                String provider = entry.getKey();
                Location location = entry.getValue();
                pw.println("    " + provider + ": " + location);
            }

            pw.println("  Last Known Locations Coarse Intervals:");
            for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
                String provider = entry.getKey();
                Location location = entry.getValue();
                pw.println("    " + provider + ": " + location);
            }

            if (mGeofenceManager != null) {
                mGeofenceManager.dump(pw);
            } else {
                pw.println("  Geofences: null");
            }
          
            if (mBlacklist != null) {
                pw.append("  ");
                mBlacklist.dump(pw);
            } else {
                pw.println("  mBlacklist=null");
            }

            if (mExtraLocationControllerPackage != null) {
                pw.println(" Location controller extra package: " + mExtraLocationControllerPackage
                        + " enabled: " + mExtraLocationControllerPackageEnabled);
            }

            if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
                pw.println("  Throttling Whitelisted Packages:");
                for (String packageName : mBackgroundThrottlePackageWhitelist) {
                    pw.println("    " + packageName);
                }
            }

            if (!mIgnoreSettingsPackageWhitelist.isEmpty()) {
                pw.println("  Bypass Whitelisted Packages:");
                for (String packageName : mIgnoreSettingsPackageWhitelist) {
                    pw.println("    " + packageName);
                }
            }

            if (mLocationFudger != null) {
                pw.append("  fudger: ");
                mLocationFudger.dump(fd, pw, args);
            } else {
                pw.println("  fudger: null");
            }

            if (args.length > 0 && "short".equals(args[0])) {
                return;
            }
            for (LocationProvider provider : mProviders) {
                provider.dumpLocked(fd, pw, args);
            }
            if (mGnssBatchingInProgress) {
                pw.println("  GNSS batching in progress");
            }
        }
    }

    @GuardedBy("mLock")
    private void dumpGnssDataListenersLocked(PrintWriter pw,
            ArrayMap<IBinder, ? extends LinkedListenerBase> gnssDataListeners) {
        for (LinkedListenerBase listener : gnssDataListeners.values()) {
            CallerIdentity callerIdentity = listener.mCallerIdentity;
            pw.println("    " + callerIdentity.mPid + " " + callerIdentity.mUid + " "
                    + callerIdentity.mPackageName + ": "
                    + isThrottlingExemptLocked(callerIdentity));
        }
    }
}
