Refactor how location providers are managed
Put enabled/disabled state under location provider control, and use it
to represent whether a location provider may be used, not whether the
user has enabled or disabled a location provider.
Bug: 118885128
Test: manually
Change-Id: I1209c49c13ca8995b223f383ad332322fffc7a96
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index cc7bf33..db445c1 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -17,8 +17,11 @@
package com.android.server;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.location.LocationProvider.AVAILABLE;
import static android.provider.Settings.Global.LOCATION_DISABLE_STATUS_CALLBACKS;
+import static com.android.internal.util.Preconditions.checkState;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -54,7 +57,6 @@
import android.location.INetInitiatedListener;
import android.location.Location;
import android.location.LocationManager;
-import android.location.LocationProvider;
import android.location.LocationRequest;
import android.os.Binder;
import android.os.Bundle;
@@ -84,6 +86,7 @@
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
+import com.android.server.location.AbstractLocationProvider;
import com.android.server.location.ActivityRecognitionProxy;
import com.android.server.location.GeocoderProxy;
import com.android.server.location.GeofenceManager;
@@ -94,7 +97,6 @@
import com.android.server.location.GnssNavigationMessageProvider;
import com.android.server.location.LocationBlacklist;
import com.android.server.location.LocationFudger;
-import com.android.server.location.LocationProviderInterface;
import com.android.server.location.LocationProviderProxy;
import com.android.server.location.LocationRequestStatistics;
import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
@@ -131,8 +133,6 @@
// Location resolution level: fine location data
private static final int RESOLUTION_LEVEL_FINE = 2;
- private static final String ACCESS_MOCK_LOCATION =
- android.Manifest.permission.ACCESS_MOCK_LOCATION;
private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
private static final String INSTALL_LOCATION_PROVIDER =
@@ -192,12 +192,6 @@
private IGpsGeofenceHardware mGpsGeofenceProxy;
// --- fields below are protected by mLock ---
- // Set of providers that are explicitly enabled
- // Only used by passive, fused & test. Network & GPS are controlled separately, and not listed.
- private final Set<String> mEnabledProviders = new HashSet<>();
-
- // Set of providers that are explicitly disabled
- private final Set<String> mDisabledProviders = new HashSet<>();
// Mock (test) providers
private final HashMap<String, MockProvider> mMockProviders =
@@ -207,15 +201,15 @@
private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
// currently installed providers (with mocks replacing real providers)
- private final ArrayList<LocationProviderInterface> mProviders =
+ private final ArrayList<LocationProvider> mProviders =
new ArrayList<>();
// real providers, saved here when mocked out
- private final HashMap<String, LocationProviderInterface> mRealProviders =
+ private final HashMap<String, LocationProvider> mRealProviders =
new HashMap<>();
// mapping from provider name to provider
- private final HashMap<String, LocationProviderInterface> mProvidersByName =
+ private final HashMap<String, LocationProvider> mProvidersByName =
new HashMap<>();
// mapping from provider name to all its UpdateRecords
@@ -270,13 +264,8 @@
PackageManagerInternal packageManagerInternal = LocalServices.getService(
PackageManagerInternal.class);
packageManagerInternal.setLocationPackagesProvider(
- new PackageManagerInternal.PackagesProvider() {
- @Override
- public String[] getPackages(int userId) {
- return mContext.getResources().getStringArray(
- com.android.internal.R.array.config_locationProviderPackageNames);
- }
- });
+ userId -> mContext.getResources().getStringArray(
+ com.android.internal.R.array.config_locationProviderPackageNames));
if (D) Log.d(TAG, "Constructed");
@@ -321,30 +310,17 @@
mAppOps.startWatchingMode(AppOpsManager.OP_COARSE_LOCATION, null,
AppOpsManager.WATCH_FOREGROUND_CHANGES, callback);
- PackageManager.OnPermissionsChangedListener permissionListener
- = new PackageManager.OnPermissionsChangedListener() {
- @Override
- public void onPermissionsChanged(final int uid) {
- synchronized (mLock) {
- applyAllProviderRequirementsLocked();
- }
+ PackageManager.OnPermissionsChangedListener permissionListener = uid -> {
+ synchronized (mLock) {
+ applyAllProviderRequirementsLocked();
}
};
mPackageManager.addOnPermissionsChangeListener(permissionListener);
// listen for background/foreground changes
- ActivityManager.OnUidImportanceListener uidImportanceListener
- = new ActivityManager.OnUidImportanceListener() {
- @Override
- public void onUidImportance(final int uid, final int importance) {
- mLocationHandler.post(new Runnable() {
- @Override
- public void run() {
- onUidImportanceChanged(uid, importance);
- }
- });
- }
- };
+ ActivityManager.OnUidImportanceListener uidImportanceListener =
+ (uid, importance) -> mLocationHandler.post(
+ () -> onUidImportanceChanged(uid, importance));
mActivityManager.addOnUidImportanceListener(uidImportanceListener,
FOREGROUND_IMPORTANCE_CUTOFF);
@@ -356,7 +332,10 @@
// prepare providers
loadProvidersLocked();
- updateProvidersLocked();
+ updateProvidersSettingsLocked();
+ for (LocationProvider provider : mProviders) {
+ applyRequirementsLocked(provider.getName());
+ }
}
// listen for settings changes
@@ -366,7 +345,7 @@
@Override
public void onChange(boolean selfChange) {
synchronized (mLock) {
- updateProvidersLocked();
+ updateProvidersSettingsLocked();
}
}
}, UserHandle.USER_ALL);
@@ -377,7 +356,9 @@
@Override
public void onChange(boolean selfChange) {
synchronized (mLock) {
- updateProvidersLocked();
+ for (LocationProvider provider : mProviders) {
+ applyRequirementsLocked(provider.getName());
+ }
}
}
}, UserHandle.USER_ALL);
@@ -402,7 +383,9 @@
public void onChange(boolean selfChange) {
synchronized (mLock) {
updateBackgroundThrottlingWhitelistLocked();
- updateProvidersLocked();
+ for (LocationProvider provider : mProviders) {
+ applyRequirementsLocked(provider.getName());
+ }
}
}
}, UserHandle.USER_ALL);
@@ -414,7 +397,6 @@
intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
- intentFilter.addAction(Intent.ACTION_SHUTDOWN);
mContext.registerReceiverAsUser(new BroadcastReceiver() {
@Override
@@ -425,12 +407,6 @@
} else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)
|| Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
updateUserProfiles(mCurrentUserId);
- } else if (Intent.ACTION_SHUTDOWN.equals(action)) {
- // shutdown only if UserId indicates whole system, not just one user
- if (D) Log.d(TAG, "Shutdown received with UserId: " + getSendingUserId());
- if (getSendingUserId() == UserHandle.USER_ALL) {
- shutdownComponents();
- }
}
}
}, UserHandle.ALL, intentFilter, null, mLocationHandler);
@@ -502,30 +478,13 @@
}
/**
- * Provides a way for components held by the {@link LocationManagerService} to clean-up
- * gracefully on system's shutdown.
- *
- * NOTES:
- * 1) Only provides a chance to clean-up on an opt-in basis. This guarantees back-compat
- * support for components that do not wish to handle such event.
- */
- private void shutdownComponents() {
- if (D) Log.d(TAG, "Shutting down components...");
-
- LocationProviderInterface gpsProvider = mProvidersByName.get(LocationManager.GPS_PROVIDER);
- if (gpsProvider != null && gpsProvider.isEnabled()) {
- gpsProvider.disable();
- }
- }
-
- /**
* Makes a list of userids that are related to the current user. This is
* relevant when using managed profiles. Otherwise the list only contains
* the current user.
*
* @param currentUserId the current user, who might have an alter-ego.
*/
- void updateUserProfiles(int currentUserId) {
+ private void updateUserProfiles(int currentUserId) {
int[] profileIds = mUserManager.getProfileIdsWithDisabled(currentUserId);
synchronized (mLock) {
mCurrentUserProfiles = profileIds;
@@ -614,22 +573,28 @@
private void loadProvidersLocked() {
// create a passive location provider, which is always enabled
- PassiveProvider passiveProvider = new PassiveProvider(this);
- addProviderLocked(passiveProvider);
- mEnabledProviders.add(passiveProvider.getName());
+ LocationProvider passiveProviderManager = new LocationProvider(
+ LocationManager.PASSIVE_PROVIDER);
+ PassiveProvider passiveProvider = new PassiveProvider(passiveProviderManager);
+
+ addProviderLocked(passiveProviderManager);
mPassiveProvider = passiveProvider;
if (GnssLocationProvider.isSupported()) {
// Create a gps location provider
- GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this,
+ LocationProvider gnssProviderManager = new LocationProvider(
+ LocationManager.GPS_PROVIDER);
+ GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext,
+ gnssProviderManager,
mLocationHandler.getLooper());
+
mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider();
mGnssMetricsProvider = gnssProvider.getGnssMetricsProvider();
mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
- addProviderLocked(gnssProvider);
- mRealProviders.put(LocationManager.GPS_PROVIDER, gnssProvider);
+ addProviderLocked(gnssProviderManager);
+ mRealProviders.put(LocationManager.GPS_PROVIDER, gnssProviderManager);
mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider();
mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy();
@@ -657,34 +622,38 @@
ensureFallbackFusedProviderPresentLocked(pkgs);
// bind to network provider
+
+ LocationProvider networkProviderManager = new LocationProvider(
+ LocationManager.NETWORK_PROVIDER);
LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
mContext,
- LocationManager.NETWORK_PROVIDER,
+ 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.put(LocationManager.NETWORK_PROVIDER, networkProvider);
+ mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProviderManager);
mProxyProviders.add(networkProvider);
- addProviderLocked(networkProvider);
+ addProviderLocked(networkProviderManager);
} else {
Slog.w(TAG, "no network location provider found");
}
// bind to fused provider
- LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind(
+ LocationProvider fusedProviderManager = new LocationProvider(
+ LocationManager.FUSED_PROVIDER);
+ LocationProviderProxy fusedProvider = LocationProviderProxy.createAndBind(
mContext,
- LocationManager.FUSED_PROVIDER,
+ 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 (fusedLocationProvider != null) {
- addProviderLocked(fusedLocationProvider);
- mProxyProviders.add(fusedLocationProvider);
- mEnabledProviders.add(fusedLocationProvider.getName());
- mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
+ if (fusedProvider != null) {
+ addProviderLocked(fusedProviderManager);
+ mProxyProviders.add(fusedProvider);
+ mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedProviderManager);
} else {
Slog.e(TAG, "no fused location provider found",
new IllegalStateException("Location service needs a fused location provider"));
@@ -765,12 +734,9 @@
synchronized (mLock) {
mLastLocation.clear();
mLastLocationCoarseInterval.clear();
- for (LocationProviderInterface p : mProviders) {
- updateProviderListenersLocked(p.getName(), false);
- }
- mCurrentUserId = userId;
updateUserProfiles(userId);
- updateProvidersLocked();
+ updateProvidersSettingsLocked();
+ mCurrentUserId = userId;
}
}
@@ -786,6 +752,165 @@
}
}
+ private class LocationProvider implements AbstractLocationProvider.LocationProviderManager {
+
+ private final String mName;
+ private AbstractLocationProvider mProvider;
+
+ // whether the provider is enabled in location settings
+ private boolean mSettingsEnabled;
+
+ // whether the provider considers itself enabled
+ private volatile boolean mEnabled;
+
+ @Nullable
+ private volatile ProviderProperties mProperties;
+
+ private LocationProvider(String name) {
+ mName = name;
+ // TODO: initialize settings enabled?
+ }
+
+ @Override
+ public void onAttachProvider(AbstractLocationProvider provider, boolean initiallyEnabled) {
+ checkState(mProvider == null);
+
+ // the provider is not yet fully constructed at this point, so we may not do anything
+ // except save a reference for later use here. do not call any provider methods.
+ mProvider = provider;
+ mEnabled = initiallyEnabled;
+ mProperties = null;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public boolean isEnabled() {
+ return mSettingsEnabled && mEnabled;
+ }
+
+ @Nullable
+ public ProviderProperties getProperties() {
+ return mProperties;
+ }
+
+ public void setRequest(ProviderRequest request, WorkSource workSource) {
+ mProvider.setRequest(request, workSource);
+ }
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println(mName + " provider:");
+ pw.println(" setting=" + mSettingsEnabled);
+ pw.println(" enabled=" + mEnabled);
+ pw.println(" properties=" + mProperties);
+ mProvider.dump(fd, pw, args);
+ }
+
+ public long getStatusUpdateTime() {
+ return mProvider.getStatusUpdateTime();
+ }
+
+ public int getStatus(Bundle extras) {
+ return mProvider.getStatus(extras);
+ }
+
+ public void sendExtraCommand(String command, Bundle extras) {
+ mProvider.sendExtraCommand(command, extras);
+ }
+
+ // called from any thread
+ @Override
+ public void onReportLocation(Location location) {
+ runOnHandler(() -> LocationManagerService.this.reportLocation(location,
+ mProvider == mPassiveProvider));
+ }
+
+ // called from any thread
+ @Override
+ public void onReportLocation(List<Location> locations) {
+ runOnHandler(() -> LocationManagerService.this.reportLocationBatch(locations));
+ }
+
+ // called from any thread
+ @Override
+ public void onSetEnabled(boolean enabled) {
+ runOnHandler(() -> {
+ if (enabled == mEnabled) {
+ return;
+ }
+
+ mEnabled = enabled;
+
+ if (!mSettingsEnabled) {
+ // this provider was disabled in settings anyways, so a change to it's own
+ // enabled status won't have any affect.
+ return;
+ }
+
+ // traditionally clients can listen for changes to the LOCATION_PROVIDERS_ALLOWED
+ // setting to detect when providers are enabled or disabled (even though they aren't
+ // supposed to). to continue to support this we must force a change to this setting.
+ // we use the fused provider because this is forced to be always enabled in settings
+ // anyways, and so won't have any visible effect beyond triggering content observers
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+ "+" + LocationManager.FUSED_PROVIDER, mCurrentUserId);
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+ "-" + LocationManager.FUSED_PROVIDER, mCurrentUserId);
+
+ synchronized (mLock) {
+ if (!enabled) {
+ // 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();
+ }
+
+ updateProviderListenersLocked(mName);
+ }
+
+ mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
+ UserHandle.ALL);
+ });
+ }
+
+ @Override
+ public void onSetProperties(ProviderProperties properties) {
+ runOnHandler(() -> mProperties = properties);
+ }
+
+ private void setSettingsEnabled(boolean enabled) {
+ synchronized (mLock) {
+ if (mSettingsEnabled == enabled) {
+ return;
+ }
+
+ mSettingsEnabled = enabled;
+ if (!mSettingsEnabled) {
+ // 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();
+ updateProviderListenersLocked(mName);
+ } else if (mEnabled) {
+ updateProviderListenersLocked(mName);
+ }
+ }
+ }
+
+ private void runOnHandler(Runnable runnable) {
+ if (Looper.myLooper() == mLocationHandler.getLooper()) {
+ runnable.run();
+ } else {
+ mLocationHandler.post(runnable);
+ }
+ }
+ }
+
/**
* A wrapper class holding either an ILocationListener or a PendingIntent to receive
* location updates.
@@ -793,24 +918,24 @@
private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
final Identity mIdentity;
- final int mAllowedResolutionLevel; // resolution level allowed to receiver
+ private final int mAllowedResolutionLevel; // resolution level allowed to receiver
- final ILocationListener mListener;
+ private final ILocationListener mListener;
final PendingIntent mPendingIntent;
final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
- final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
- final Object mKey;
+ 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.
- boolean mOpMonitoring;
+ private boolean mOpMonitoring;
// True if app ops has started monitoring this receiver for high power (gps) locations.
- boolean mOpHighPowerMonitoring;
- int mPendingBroadcasts;
+ private boolean mOpHighPowerMonitoring;
+ private int mPendingBroadcasts;
PowerManager.WakeLock mWakeLock;
- Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
+ private Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
String packageName, WorkSource workSource, boolean hideFromAppOps) {
mListener = listener;
mPendingIntent = intent;
@@ -885,9 +1010,10 @@
// 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()) {
- if (isAllowedByCurrentUserSettingsLocked(updateRecord.mProvider)) {
+ if (isAllowedByUserSettingsLockedForUser(updateRecord.mProvider,
+ mCurrentUserId)) {
requestingLocation = true;
- LocationProviderInterface locationProvider
+ LocationManagerService.LocationProvider locationProvider
= mProvidersByName.get(updateRecord.mProvider);
ProviderProperties properties = locationProvider != null
? locationProvider.getProperties() : null;
@@ -1034,7 +1160,7 @@
return true;
}
- public boolean callProviderEnabledLocked(String provider, boolean enabled) {
+ 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);
@@ -1236,7 +1362,7 @@
private class LinkedCallback implements IBinder.DeathRecipient {
private final IBatchedLocationCallback mCallback;
- public LinkedCallback(@NonNull IBatchedLocationCallback callback) {
+ private LinkedCallback(@NonNull IBatchedLocationCallback callback) {
mCallback = callback;
}
@@ -1337,7 +1463,7 @@
checkCallerIsProvider();
// Currently used only for GNSS locations - update permissions check if changed
- if (isAllowedByCurrentUserSettingsLocked(LocationManager.GPS_PROVIDER)) {
+ if (isAllowedByUserSettingsLockedForUser(LocationManager.GPS_PROVIDER, mCurrentUserId)) {
if (mGnssBatchingCallback == null) {
Slog.e(TAG, "reportLocationBatch() called without active Callback");
return;
@@ -1352,29 +1478,17 @@
}
}
- private void addProviderLocked(LocationProviderInterface provider) {
+ private void addProviderLocked(LocationProvider provider) {
mProviders.add(provider);
mProvidersByName.put(provider.getName(), provider);
}
- private void removeProviderLocked(LocationProviderInterface provider) {
- provider.disable();
+ private void removeProviderLocked(LocationProvider provider) {
mProviders.remove(provider);
mProvidersByName.remove(provider.getName());
}
/**
- * Returns "true" if access to the specified location provider is allowed by the current
- * user's settings. Access to all location providers is forbidden to non-location-provider
- * processes belonging to background users.
- *
- * @param provider the name of the location provider
- */
- private boolean isAllowedByCurrentUserSettingsLocked(String provider) {
- return isAllowedByUserSettingsLockedForUser(provider, mCurrentUserId);
- }
-
- /**
* Returns "true" if access to the specified location provider is allowed by the specified
* user's settings. Access to all location providers is forbidden to non-location-provider
* processes belonging to background users.
@@ -1383,13 +1497,28 @@
* @param userId the user id to query
*/
private boolean isAllowedByUserSettingsLockedForUser(String provider, int userId) {
- if (mEnabledProviders.contains(provider)) {
- return true;
+ if (LocationManager.PASSIVE_PROVIDER.equals(provider)) {
+ return isLocationEnabledForUser(userId);
}
- if (mDisabledProviders.contains(provider)) {
- return false;
+ if (LocationManager.FUSED_PROVIDER.equals(provider)) {
+ return isLocationEnabledForUser(userId);
}
- return isLocationProviderEnabledForUser(provider, userId);
+ synchronized (mLock) {
+ if (mMockProviders.containsKey(provider)) {
+ return isLocationEnabledForUser(userId);
+ }
+ }
+
+ long identity = Binder.clearCallingIdentity();
+ try {
+ // Use system settings
+ ContentResolver cr = mContext.getContentResolver();
+ String allowedProviders = Settings.Secure.getStringForUser(
+ cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userId);
+ return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
@@ -1481,9 +1610,11 @@
// network and fused providers are ok with COARSE or FINE
return RESOLUTION_LEVEL_COARSE;
} else {
- // mock providers
- LocationProviderInterface lp = mMockProviders.get(provider);
- if (lp != null) {
+ for (LocationProvider lp : mProviders) {
+ if (!lp.getName().equals(provider)) {
+ continue;
+ }
+
ProviderProperties properties = lp.getProperties();
if (properties != null) {
if (properties.mRequiresSatellite) {
@@ -1496,6 +1627,7 @@
}
}
}
+
return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
}
@@ -1550,7 +1682,7 @@
}
private static String resolutionLevelToOpStr(int allowedResolutionLevel) {
- switch(allowedResolutionLevel) {
+ switch (allowedResolutionLevel) {
case RESOLUTION_LEVEL_COARSE:
return AppOpsManager.OPSTR_COARSE_LOCATION;
case RESOLUTION_LEVEL_FINE:
@@ -1565,7 +1697,7 @@
}
}
- boolean reportLocationAccessNoThrow(
+ private boolean reportLocationAccessNoThrow(
int pid, int uid, String packageName, int allowedResolutionLevel) {
int op = resolutionLevelToOp(allowedResolutionLevel);
if (op >= 0) {
@@ -1577,7 +1709,8 @@
return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
}
- boolean checkLocationAccess(int pid, int uid, String packageName, int allowedResolutionLevel) {
+ private boolean checkLocationAccess(int pid, int uid, String packageName,
+ int allowedResolutionLevel) {
int op = resolutionLevelToOp(allowedResolutionLevel);
if (op >= 0) {
if (mAppOps.noteOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
@@ -1597,7 +1730,7 @@
ArrayList<String> out;
synchronized (mLock) {
out = new ArrayList<>(mProviders.size());
- for (LocationProviderInterface provider : mProviders) {
+ for (LocationProvider provider : mProviders) {
String name = provider.getName();
if (LocationManager.FUSED_PROVIDER.equals(name)) {
continue;
@@ -1623,7 +1756,7 @@
try {
synchronized (mLock) {
out = new ArrayList<>(mProviders.size());
- for (LocationProviderInterface provider : mProviders) {
+ for (LocationProvider provider : mProviders) {
String name = provider.getName();
if (LocationManager.FUSED_PROVIDER.equals(name)) {
continue;
@@ -1633,7 +1766,8 @@
&& !isAllowedByUserSettingsLocked(name, uid, mCurrentUserId)) {
continue;
}
- if (criteria != null && !LocationProvider.propertiesMeetCriteria(
+ if (criteria != null
+ && !android.location.LocationProvider.propertiesMeetCriteria(
name, provider.getProperties(), criteria)) {
continue;
}
@@ -1658,7 +1792,7 @@
*/
@Override
public String getBestProvider(Criteria criteria, boolean enabledOnly) {
- String result = null;
+ String result;
List<String> providers = getProviders(criteria, enabledOnly);
if (!providers.isEmpty()) {
@@ -1673,7 +1807,7 @@
return result;
}
- if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
+ if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + null);
return null;
}
@@ -1689,51 +1823,32 @@
@Override
public boolean providerMeetsCriteria(String provider, Criteria criteria) {
- LocationProviderInterface p = mProvidersByName.get(provider);
+ LocationProvider p = mProvidersByName.get(provider);
if (p == null) {
throw new IllegalArgumentException("provider=" + provider);
}
- boolean result = LocationProvider.propertiesMeetCriteria(
+ boolean result = android.location.LocationProvider.propertiesMeetCriteria(
p.getName(), p.getProperties(), criteria);
if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result);
return result;
}
- private void updateProvidersLocked() {
- boolean changesMade = false;
- for (int i = mProviders.size() - 1; i >= 0; i--) {
- LocationProviderInterface p = mProviders.get(i);
- boolean isEnabled = p.isEnabled();
- String name = p.getName();
- boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
- if (isEnabled && !shouldBeEnabled) {
- updateProviderListenersLocked(name, false);
- // 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();
- changesMade = true;
- } else if (!isEnabled && shouldBeEnabled) {
- updateProviderListenersLocked(name, true);
- changesMade = true;
- }
+ private void updateProvidersSettingsLocked() {
+ for (LocationProvider p : mProviders) {
+ p.setSettingsEnabled(isAllowedByUserSettingsLockedForUser(p.getName(), mCurrentUserId));
}
- if (changesMade) {
- mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
- UserHandle.ALL);
- mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
- UserHandle.ALL);
- }
+
+ mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
+ UserHandle.ALL);
}
- private void updateProviderListenersLocked(String provider, boolean enabled) {
- int listeners = 0;
-
- LocationProviderInterface p = mProvidersByName.get(provider);
+ private void updateProviderListenersLocked(String provider) {
+ LocationProvider p = mProvidersByName.get(provider);
if (p == null) return;
+ boolean enabled = p.isEnabled();
+
ArrayList<Receiver> deadReceivers = null;
ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
@@ -1747,7 +1862,6 @@
}
deadReceivers.add(record.mReceiver);
}
- listeners++;
}
}
}
@@ -1758,16 +1872,11 @@
}
}
- if (enabled) {
- p.enable();
- applyRequirementsLocked(provider);
- } else {
- p.disable();
- }
+ applyRequirementsLocked(provider);
}
private void applyRequirementsLocked(String provider) {
- LocationProviderInterface p = mProvidersByName.get(provider);
+ LocationProvider p = mProvidersByName.get(provider);
if (p == null) return;
ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
@@ -1779,10 +1888,10 @@
resolver,
Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
- // initialize the low power mode to true and set to false if any of the records requires
- providerRequest.lowPowerMode = true;
- if (records != null) {
+ if (p.isEnabled() && records != null && !records.isEmpty()) {
+ // 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 (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
if (checkLocationAccess(
@@ -1875,7 +1984,7 @@
public String[] getBackgroundThrottlingWhitelist() {
synchronized (mLock) {
return mBackgroundThrottlePackageWhitelist.toArray(
- new String[mBackgroundThrottlePackageWhitelist.size()]);
+ new String[0]);
}
}
@@ -1922,17 +2031,17 @@
private class UpdateRecord {
final String mProvider;
- final LocationRequest mRealRequest; // original request from client
+ private final LocationRequest mRealRequest; // original request from client
LocationRequest mRequest; // possibly throttled version of the request
- final Receiver mReceiver;
- boolean mIsForegroundUid;
- Location mLastFixBroadcast;
- long mLastStatusBroadcast;
+ private final Receiver mReceiver;
+ private boolean mIsForegroundUid;
+ private Location mLastFixBroadcast;
+ private long mLastStatusBroadcast;
/**
* Note: must be constructed with lock held.
*/
- UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
+ private UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
mProvider = provider;
mRealRequest = request;
mRequest = request;
@@ -1958,7 +2067,7 @@
/**
* Method to be called when record changes foreground/background
*/
- void updateForeground(boolean isForeground){
+ private void updateForeground(boolean isForeground) {
mIsForegroundUid = isForeground;
mRequestStatistics.updateForeground(
mReceiver.mIdentity.mPackageName, mProvider, isForeground);
@@ -1967,7 +2076,7 @@
/**
* Method to be called when a record will no longer be used.
*/
- void disposeLocked(boolean removeReceiver) {
+ private void disposeLocked(boolean removeReceiver) {
mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider);
// remove from mRecordsByProvider
@@ -1980,13 +2089,11 @@
// remove from Receiver#mUpdateRecords
HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
- if (receiverRecords != null) {
- receiverRecords.remove(this.mProvider);
+ receiverRecords.remove(this.mProvider);
- // and also remove the Receiver if it has no more update records
- if (receiverRecords.size() == 0) {
- removeUpdatesLocked(mReceiver);
- }
+ // and also remove the Receiver if it has no more update records
+ if (receiverRecords.size() == 0) {
+ removeUpdatesLocked(mReceiver);
}
}
@@ -2070,7 +2177,7 @@
private void checkPackageName(String packageName) {
if (packageName == null) {
- throw new SecurityException("invalid package name: " + packageName);
+ throw new SecurityException("invalid package name: " + null);
}
int uid = Binder.getCallingUid();
String[] packages = mPackageManager.getPackagesForUid(uid);
@@ -2085,7 +2192,7 @@
private void checkPendingIntent(PendingIntent intent) {
if (intent == null) {
- throw new IllegalArgumentException("invalid pending intent: " + intent);
+ throw new IllegalArgumentException("invalid pending intent: " + null);
}
}
@@ -2137,7 +2244,7 @@
synchronized (mLock) {
Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
packageName, workSource, hideFromAppOps);
- requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
+ requestLocationUpdatesLocked(sanitizedRequest, recevier, uid, packageName);
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -2145,7 +2252,7 @@
}
private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
- int pid, int uid, String packageName) {
+ 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;
@@ -2154,7 +2261,7 @@
throw new IllegalArgumentException("provider name must not be null");
}
- LocationProviderInterface provider = mProvidersByName.get(name);
+ LocationProvider provider = mProvidersByName.get(name);
if (provider == null) {
throw new IllegalArgumentException("provider doesn't exist: " + name);
}
@@ -2173,8 +2280,7 @@
oldRecord.disposeLocked(false);
}
- boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid, mCurrentUserId);
- if (isProviderEnabled) {
+ if (provider.isEnabled()) {
applyRequirementsLocked(name);
} else {
// Notify the listener that updates are currently disabled
@@ -2194,10 +2300,8 @@
final int uid = Binder.getCallingUid();
synchronized (mLock) {
- WorkSource workSource = null;
- boolean hideFromAppOps = false;
Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid,
- packageName, workSource, hideFromAppOps);
+ packageName, null, false);
// providers may use public location API's, need to clear identity
long identity = Binder.clearCallingIdentity();
@@ -2236,22 +2340,12 @@
// update provider
for (String provider : providers) {
- // If provider is already disabled, don't need to do anything
- if (!isAllowedByCurrentUserSettingsLocked(provider)) {
- continue;
- }
-
applyRequirementsLocked(provider);
}
}
private void applyAllProviderRequirementsLocked() {
- for (LocationProviderInterface p : mProviders) {
- // If provider is already disabled, don't need to do anything
- if (!isAllowedByCurrentUserSettingsLocked(p.getName())) {
- continue;
- }
-
+ for (LocationProvider p : mProviders) {
applyRequirementsLocked(p.getName());
}
}
@@ -2291,7 +2385,7 @@
// or use the fused provider
String name = request.getProvider();
if (name == null) name = LocationManager.FUSED_PROVIDER;
- LocationProviderInterface provider = mProvidersByName.get(name);
+ LocationProvider provider = mProvidersByName.get(name);
if (provider == null) return null;
if (!isAllowedByUserSettingsLocked(name, uid, mCurrentUserId)) return null;
@@ -2314,7 +2408,7 @@
location.getElapsedRealtimeNanos() / NANOS_PER_MILLI;
if ((locationAgeMs > mLastLocationMaxAgeMs)
&& (mAppOps.unsafeCheckOp(op, uid, packageName)
- == AppOpsManager.MODE_FOREGROUND)) {
+ == AppOpsManager.MODE_FOREGROUND)) {
return null;
}
@@ -2358,7 +2452,7 @@
}
return false;
}
- LocationProviderInterface p = null;
+ LocationProvider p = null;
String provider = location.getProvider();
if (provider != null) {
p = mProvidersByName.get(provider);
@@ -2370,7 +2464,7 @@
return false;
}
synchronized (mLock) {
- if (!isAllowedByCurrentUserSettingsLocked(provider)) {
+ if (!isAllowedByUserSettingsLockedForUser(provider, mCurrentUserId)) {
if (D) {
Log.d(TAG, "Location disabled in Settings for current user:" + mCurrentUserId);
}
@@ -2499,11 +2593,13 @@
@Override
public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
- if (mGnssMeasurementsProvider != null) {
- synchronized (mLock) {
- mGnssMeasurementsListeners.remove(listener.asBinder());
- mGnssMeasurementsProvider.removeListener(listener);
- }
+ if (mGnssMeasurementsProvider == null) {
+ return;
+ }
+
+ synchronized (mLock) {
+ mGnssMeasurementsListeners.remove(listener.asBinder());
+ mGnssMeasurementsProvider.removeListener(listener);
}
}
@@ -2560,10 +2656,11 @@
}
synchronized (mLock) {
- LocationProviderInterface p = mProvidersByName.get(provider);
+ LocationProvider p = mProvidersByName.get(provider);
if (p == null) return false;
- return p.sendExtraCommand(command, extras);
+ p.sendExtraCommand(command, extras);
+ return true;
}
}
@@ -2588,14 +2685,10 @@
*/
@Override
public ProviderProperties getProviderProperties(String provider) {
- if (mProvidersByName.get(provider) == null) {
- return null;
- }
-
checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
provider);
- LocationProviderInterface p;
+ LocationProvider p;
synchronized (mLock) {
p = mProvidersByName.get(provider);
}
@@ -2611,25 +2704,25 @@
*/
@Override
public String getNetworkProviderPackage() {
- LocationProviderInterface p;
+ LocationProvider p;
synchronized (mLock) {
- if (mProvidersByName.get(LocationManager.NETWORK_PROVIDER) == null) {
- return null;
- }
p = mProvidersByName.get(LocationManager.NETWORK_PROVIDER);
}
- if (p instanceof LocationProviderProxy) {
- return ((LocationProviderProxy) p).getConnectedPackageName();
+ if (p == null) {
+ return null;
+ }
+ if (p.mProvider instanceof LocationProviderProxy) {
+ return ((LocationProviderProxy) p.mProvider).getConnectedPackageName();
}
return null;
}
/**
- * Returns the current location enabled/disabled status for a user
+ * Returns the current location enabled/disabled status for a user
*
- * @param userId the id of the user
- * @return true if location is enabled
+ * @param userId the id of the user
+ * @return true if location is enabled
*/
@Override
public boolean isLocationEnabledForUser(int userId) {
@@ -2647,7 +2740,7 @@
return false;
}
final List<String> providerList = Arrays.asList(allowedProviders.split(","));
- for(String provider : mRealProviders.keySet()) {
+ for (String provider : mRealProviders.keySet()) {
if (provider.equals(LocationManager.PASSIVE_PROVIDER)
|| provider.equals(LocationManager.FUSED_PROVIDER)) {
continue;
@@ -2664,16 +2757,16 @@
}
/**
- * Enable or disable location for a user
+ * Enable or disable location for a user
*
- * @param enabled true to enable location, false to disable location
- * @param userId the id of the user
+ * @param enabled true to enable location, false to disable location
+ * @param userId the id of the user
*/
@Override
public void setLocationEnabledForUser(boolean enabled, int userId) {
mContext.enforceCallingPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS,
- "Requires WRITE_SECURE_SETTINGS permission");
+ android.Manifest.permission.WRITE_SECURE_SETTINGS,
+ "Requires WRITE_SECURE_SETTINGS permission");
// Check INTERACT_ACROSS_USERS permission if userId is not current user id.
checkInteractAcrossUsersPermission(userId);
@@ -2688,7 +2781,7 @@
allProvidersSet.addAll(allRealProviders);
// When disabling location, disable gps and network provider that could have been
// enabled by location mode api.
- if (enabled == false) {
+ if (!enabled) {
allProvidersSet.add(LocationManager.GPS_PROVIDER);
allProvidersSet.add(LocationManager.NETWORK_PROVIDER);
}
@@ -2723,26 +2816,34 @@
}
/**
- * Returns the current enabled/disabled status of a location provider and user
+ * Returns the current enabled/disabled status of a location provider and user
*
- * @param provider name of the provider
- * @param userId the id of the user
- * @return true if the provider exists and is enabled
+ * @param providerName name of the provider
+ * @param userId the id of the user
+ * @return true if the provider exists and is enabled
*/
@Override
- public boolean isProviderEnabledForUser(String provider, int userId) {
+ public boolean isProviderEnabledForUser(String providerName, int userId) {
// Check INTERACT_ACROSS_USERS permission if userId is not current user id.
checkInteractAcrossUsersPermission(userId);
+ if (!isLocationEnabledForUser(userId)) {
+ return false;
+ }
+
// Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
// so we discourage its use
- if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
+ if (LocationManager.FUSED_PROVIDER.equals(providerName)) return false;
- int uid = Binder.getCallingUid();
- synchronized (mLock) {
- LocationProviderInterface p = mProvidersByName.get(provider);
- return p != null
- && isAllowedByUserSettingsLocked(provider, uid, userId);
+ long identity = Binder.clearCallingIdentity();
+ try {
+ LocationProvider provider;
+ synchronized (mLock) {
+ provider = mProvidersByName.get(providerName);
+ }
+ return provider != null && provider.isEnabled();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
}
@@ -2750,66 +2851,13 @@
* Enable or disable a single location provider.
*
* @param provider name of the provider
- * @param enabled true to enable the provider. False to disable the provider
- * @param userId the id of the user to set
+ * @param enabled true to enable the provider. False to disable the provider
+ * @param userId the id of the user to set
* @return true if the value was set, false on errors
*/
@Override
public boolean setProviderEnabledForUser(String provider, boolean enabled, int userId) {
- mContext.enforceCallingPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS,
- "Requires WRITE_SECURE_SETTINGS permission");
-
- // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
- checkInteractAcrossUsersPermission(userId);
-
- // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
- // so we discourage its use
- if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
-
- long identity = Binder.clearCallingIdentity();
- try {
- synchronized (mLock) {
- // No such provider exists
- if (!mProvidersByName.containsKey(provider)) return false;
-
- // If it is a test provider, do not write to Settings.Secure
- if (mMockProviders.containsKey(provider)) {
- setTestProviderEnabled(provider, enabled);
- return true;
- }
-
- // to ensure thread safety, we write the provider name with a '+' or '-'
- // and let the SettingsProvider handle it rather than reading and modifying
- // the list of enabled providers.
- String providerChange = (enabled ? "+" : "-") + provider;
- return Settings.Secure.putStringForUser(
- mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
- providerChange, userId);
- }
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- /**
- * Read location provider status from Settings.Secure
- *
- * @param provider the location provider to query
- * @param userId the user id to query
- * @return true if the provider is enabled
- */
- private boolean isLocationProviderEnabledForUser(String provider, int userId) {
- long identity = Binder.clearCallingIdentity();
- try {
- // Use system settings
- ContentResolver cr = mContext.getContentResolver();
- String allowedProviders = Settings.Secure.getStringForUser(
- cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userId);
- return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
+ return false;
}
/**
@@ -2941,7 +2989,7 @@
long now = SystemClock.elapsedRealtime();
String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
// Skip if the provider is unknown.
- LocationProviderInterface p = mProvidersByName.get(provider);
+ LocationProvider p = mProvidersByName.get(provider);
if (p == null) return;
updateLastLocationLocked(location, provider);
// mLastLocation should have been updated from the updateLastLocationLocked call above.
@@ -3053,7 +3101,7 @@
LOCATION_DISABLE_STATUS_CALLBACKS, 1) == 0) {
long prevStatusUpdateTime = r.mLastStatusBroadcast;
if ((newStatusUpdateTime > prevStatusUpdateTime)
- && (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
+ && (prevStatusUpdateTime != 0 || status != AVAILABLE)) {
r.mLastStatusBroadcast = newStatusUpdateTime;
if (!receiver.callStatusChangedLocked(provider, status, extras)) {
@@ -3098,8 +3146,8 @@
/**
* Updates last location with the given location
*
- * @param location new location to update
- * @param provider Location provider to update for
+ * @param location new location to update
+ * @param provider Location provider to update for
*/
private void updateLastLocationLocked(Location location, String provider) {
Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
@@ -3154,13 +3202,11 @@
}
synchronized (mLock) {
- if (isAllowedByCurrentUserSettingsLocked(provider)) {
- if (!passive) {
- // notify passive provider of the new location
- mPassiveProvider.updateLocation(myLocation);
- }
- handleLocationChangedLocked(myLocation, passive);
+ if (!passive) {
+ // notify passive provider of the new location
+ mPassiveProvider.updateLocation(myLocation);
}
+ handleLocationChangedLocked(myLocation, passive);
}
}
@@ -3245,13 +3291,12 @@
if (LocationManager.GPS_PROVIDER.equals(name)
|| LocationManager.NETWORK_PROVIDER.equals(name)
|| LocationManager.FUSED_PROVIDER.equals(name)) {
- LocationProviderInterface p = mProvidersByName.get(name);
+ LocationProvider p = mProvidersByName.get(name);
if (p != null) {
removeProviderLocked(p);
}
}
addTestProviderLocked(name, properties);
- updateProvidersLocked();
}
Binder.restoreCallingIdentity(identity);
}
@@ -3260,9 +3305,12 @@
if (mProvidersByName.get(name) != null) {
throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
}
- MockProvider provider = new MockProvider(name, this, properties);
+
+ LocationProvider provider = new LocationProvider(name);
+ MockProvider mockProvider = new MockProvider(provider, properties);
+
addProviderLocked(provider);
- mMockProviders.put(name, provider);
+ mMockProviders.put(name, mockProvider);
mLastLocation.put(name, null);
mLastLocationCoarseInterval.put(name, null);
}
@@ -3274,28 +3322,25 @@
}
synchronized (mLock) {
-
- // These methods can't be called after removing the test provider, so first make sure
- // we don't leave anything dangling.
- clearTestProviderEnabled(provider, opPackageName);
- clearTestProviderLocation(provider, opPackageName);
-
MockProvider mockProvider = mMockProviders.remove(provider);
if (mockProvider == null) {
throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
}
- long identity = Binder.clearCallingIdentity();
- removeProviderLocked(mProvidersByName.get(provider));
- // reinstate real provider if available
- LocationProviderInterface realProvider = mRealProviders.get(provider);
- if (realProvider != null) {
- addProviderLocked(realProvider);
+ long identity = Binder.clearCallingIdentity();
+ try {
+ removeProviderLocked(mProvidersByName.get(provider));
+
+ // reinstate real provider if available
+ LocationProvider realProvider = mRealProviders.get(provider);
+ if (realProvider != null) {
+ addProviderLocked(realProvider);
+ }
+ mLastLocation.put(provider, null);
+ mLastLocationCoarseInterval.put(provider, null);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
- mLastLocation.put(provider, null);
- mLastLocationCoarseInterval.put(provider, null);
- updateProvidersLocked();
- Binder.restoreCallingIdentity(identity);
}
}
@@ -3325,23 +3370,11 @@
// clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
long identity = Binder.clearCallingIdentity();
- mockProvider.setLocation(mock);
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public void clearTestProviderLocation(String provider, String opPackageName) {
- if (!canCallerAccessMockLocation(opPackageName)) {
- return;
- }
-
- synchronized (mLock) {
- MockProvider mockProvider = mMockProviders.get(provider);
- if (mockProvider == null) {
- throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
+ try {
+ mockProvider.setLocation(mock);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
- mockProvider.clearLocation();
}
}
@@ -3350,36 +3383,6 @@
if (!canCallerAccessMockLocation(opPackageName)) {
return;
}
- setTestProviderEnabled(provider, enabled);
- }
-
- /** Enable or disable a test location provider. */
- private void setTestProviderEnabled(String provider, boolean enabled) {
- synchronized (mLock) {
- MockProvider mockProvider = mMockProviders.get(provider);
- if (mockProvider == null) {
- throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
- }
- long identity = Binder.clearCallingIdentity();
- if (enabled) {
- mockProvider.enable();
- mEnabledProviders.add(provider);
- mDisabledProviders.remove(provider);
- } else {
- mockProvider.disable();
- mEnabledProviders.remove(provider);
- mDisabledProviders.add(provider);
- }
- updateProvidersLocked();
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public void clearTestProviderEnabled(String provider, String opPackageName) {
- if (!canCallerAccessMockLocation(opPackageName)) {
- return;
- }
synchronized (mLock) {
MockProvider mockProvider = mMockProviders.get(provider);
@@ -3387,10 +3390,11 @@
throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
}
long identity = Binder.clearCallingIdentity();
- mEnabledProviders.remove(provider);
- mDisabledProviders.remove(provider);
- updateProvidersLocked();
- Binder.restoreCallingIdentity(identity);
+ try {
+ mockProvider.setEnabled(enabled);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
}
@@ -3450,10 +3454,11 @@
+ identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
}
pw.println(" Overlay Provider Packages:");
- for (LocationProviderInterface provider : mProviders) {
- if (provider instanceof LocationProviderProxy) {
+ for (LocationProvider provider : mProviders) {
+ if (provider.mProvider instanceof LocationProviderProxy) {
pw.println(" " + provider.getName() + ": "
- + ((LocationProviderProxy) provider).getConnectedPackageName());
+ + ((LocationProviderProxy) provider.mProvider)
+ .getConnectedPackageName());
}
}
pw.println(" Historical Records by Provider:");
@@ -3479,25 +3484,12 @@
mGeofenceManager.dump(pw);
- if (mEnabledProviders.size() > 0) {
- pw.println(" Enabled Providers:");
- for (String i : mEnabledProviders) {
- pw.println(" " + i);
- }
-
- }
- if (mDisabledProviders.size() > 0) {
- pw.println(" Disabled Providers:");
- for (String i : mDisabledProviders) {
- pw.println(" " + i);
- }
- }
pw.append(" ");
mBlacklist.dump(pw);
if (mMockProviders.size() > 0) {
pw.println(" Mock Providers:");
for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
- i.getValue().dump(pw, " ");
+ i.getValue().dump(fd, pw, args);
}
}
@@ -3514,13 +3506,7 @@
if (args.length > 0 && "short".equals(args[0])) {
return;
}
- for (LocationProviderInterface provider : mProviders) {
- pw.print(provider.getName() + " Internal State");
- if (provider instanceof LocationProviderProxy) {
- LocationProviderProxy proxy = (LocationProviderProxy) provider;
- pw.print(" (" + proxy.getConnectedPackageName() + ")");
- }
- pw.println(":");
+ for (LocationProvider provider : mProviders) {
provider.dump(fd, pw, args);
}
if (mGnssBatchingInProgress) {