Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9637d474 authored by Mike Lockwood's avatar Mike Lockwood Committed by The Android Open Source Project
Browse files

AI 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

Automated import of CL 144372
parent f80f5d02
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -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);
        }
    }
    
    /**
+0 −2
Original line number Diff line number Diff line
@@ -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,
+0 −14
Original line number Diff line number Diff line
@@ -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:
     *
+73 −0
Original line number Diff line number Diff line
@@ -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;
+25 −6
Original line number Diff line number Diff line
@@ -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();