AI 144415: am: CL 144372 Cleanup Settings support for enabling and disabling location providers:

LocationManagerService now listens for changes to settings,
  making LocationManager.updateProviders() unnecessary.
  Removed LocationManager.updateProviders()
  Added Settings.Secure.setLocationProviderEnabled(), which is a thread-safe way
  of enabling or disabling a single location provider.
  This is safer than reading, modifying and writing the LOCATION_PROVIDERS_ALLOWED directly.
  BUG=1729031
  Original author: lockwood

Automated import of CL 144415
This commit is contained in:
Mike Lockwood
2009-04-02 23:41:33 -07:00
committed by The Android Open Source Project
parent 75e3034a35
commit bd2a7126e5
5 changed files with 138 additions and 22 deletions

View File

@@ -2113,6 +2113,46 @@ public final class Settings {
* @hide
*/
public static final String TTY_MODE_ENABLED = "tty_mode_enabled";
/**
* Helper method for determining if a location provider is enabled.
* @param cr the content resolver to use
* @param provider the location provider to query
* @return true if the provider is enabled
*
* @hide
*/
public static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) {
String allowedProviders = Settings.Secure.getString(cr, LOCATION_PROVIDERS_ALLOWED);
if (allowedProviders != null) {
return (allowedProviders.equals(provider) ||
allowedProviders.contains("," + provider + ",") ||
allowedProviders.startsWith(provider + ",") ||
allowedProviders.endsWith("," + provider));
}
return false;
}
/**
* Thread-safe method for enabling or disabling a single location provider.
* @param cr the content resolver to use
* @param provider the location provider to enable or disable
* @param enabled true if the provider should be enabled
*
* @hide
*/
public static final void setLocationProviderEnabled(ContentResolver cr,
String provider, boolean enabled) {
// 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.
if (enabled) {
provider = "+" + provider;
} else {
provider = "-" + provider;
}
putString(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider);
}
}
/**

View File

@@ -33,8 +33,6 @@ interface ILocationManager
List getAllProviders();
List getProviders(boolean enabledOnly);
void updateProviders();
void requestLocationUpdates(String provider, long minTime, float minDistance,
in ILocationListener listener);
void requestLocationUpdatesPI(String provider, long minTime, float minDistance,

View File

@@ -312,20 +312,6 @@ public class LocationManager {
return goodProviders;
}
/**
* Propagates the enabled/disabled state of the providers from the system
* settings to the providers themselves.
*
* {@hide}
*/
public void updateProviders() {
try {
mService.updateProviders();
} catch (RemoteException ex) {
Log.e(TAG, "updateProviders: RemoteException", ex);
}
}
/**
* Returns the next looser power requirement, in the sequence:
*

View File

@@ -244,6 +244,72 @@ public class SettingsProvider extends ContentProvider {
return values.length;
}
/*
* Used to parse changes to the value of Settings.Secure.LOCATION_PROVIDERS_ALLOWED.
* This setting contains a list of the currently enabled location providers.
* But helper functions in android.providers.Settings can enable or disable
* a single provider by using a "+" or "-" prefix before the provider name.
*/
private boolean parseProviderList(Uri url, ContentValues initialValues) {
String value = initialValues.getAsString(Settings.Secure.VALUE);
String newProviders = null;
if (value != null && value.length() > 1) {
char prefix = value.charAt(0);
if (prefix == '+' || prefix == '-') {
// skip prefix
value = value.substring(1);
// read list of enabled providers into "providers"
String providers = "";
String[] columns = {Settings.Secure.VALUE};
String where = Settings.Secure.NAME + "=\'" + Settings.Secure.LOCATION_PROVIDERS_ALLOWED + "\'";
Cursor cursor = query(url, columns, where, null, null);
if (cursor != null && cursor.getCount() == 1) {
try {
cursor.moveToFirst();
providers = cursor.getString(0);
} finally {
cursor.close();
}
}
int index = providers.indexOf(value);
int end = index + value.length();
// check for commas to avoid matching on partial string
if (index > 0 && providers.charAt(index - 1) != ',') index = -1;
if (end < providers.length() && providers.charAt(end) != ',') index = -1;
if (prefix == '+' && index < 0) {
// append the provider to the list if not present
if (providers.length() == 0) {
newProviders = value;
} else {
newProviders = providers + ',' + value;
}
} else if (prefix == '-' && index >= 0) {
// remove the provider from the list if present
// remove leading and trailing commas
if (index > 0) index--;
if (end < providers.length()) end++;
newProviders = providers.substring(0, index);
if (end < providers.length()) {
newProviders += providers.substring(end);
}
} else {
// nothing changed, so no need to update the database
return false;
}
if (newProviders != null) {
initialValues.put(Settings.Secure.VALUE, newProviders);
}
}
}
return true;
}
@Override
public Uri insert(Uri url, ContentValues initialValues) {
SqlArguments args = new SqlArguments(url);
@@ -252,6 +318,13 @@ public class SettingsProvider extends ContentProvider {
}
checkWritePermissions(args);
// Special case LOCATION_PROVIDERS_ALLOWED.
// Support enabling/disabling a single provider (using "+" or "-" prefix)
String name = initialValues.getAsString(Settings.Secure.NAME);
if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) {
if (!parseProviderList(url, initialValues)) return null;
}
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
final long rowId = db.insert(args.table, null, initialValues);
if (rowId <= 0) return null;

View File

@@ -28,17 +28,21 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;
import java.util.regex.Pattern;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentQueryMap;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.location.Address;
import android.location.IGpsStatusListener;
import android.location.ILocationListener;
@@ -222,6 +226,9 @@ public class LocationManagerService extends ILocationManager.Stub
private int mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
private boolean mWifiEnabled = false;
// for Settings change notification
private ContentQueryMap mSettings;
/**
* A wrapper class holding either an ILocationListener or a PendingIntent to receive
* location updates.
@@ -345,6 +352,14 @@ public class LocationManagerService extends ILocationManager.Stub
}
}
private final class SettingsObserver implements Observer {
public void update(Observable o, Object arg) {
synchronized (mLocationListeners) {
updateProvidersLocked();
}
}
}
private Location readLastKnownLocationLocked(String provider) {
Location location = null;
String s = null;
@@ -593,6 +608,16 @@ public class LocationManagerService extends ILocationManager.Stub
intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
context.registerReceiver(powerStateReceiver, intentFilter);
// listen for settings changes
ContentResolver resolver = mContext.getContentResolver();
Cursor settingsCursor = resolver.query(Settings.Secure.CONTENT_URI, null,
"(" + Settings.System.NAME + "=?)",
new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
null);
mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mLocationHandler);
SettingsObserver settingsObserver = new SettingsObserver();
mSettings.addObserver(settingsObserver);
// Get the wifi manager
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
@@ -773,12 +798,6 @@ public class LocationManagerService extends ILocationManager.Stub
return out;
}
public void updateProviders() {
synchronized (mLocationListeners) {
updateProvidersLocked();
}
}
private void updateProvidersLocked() {
for (LocationProviderImpl p : LocationProviderImpl.getProviders()) {
boolean isEnabled = p.isEnabled();