/*
 * 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(ActivityManager.getCurrentUser());

        // 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));
        }
    }
}
