Loading location/java/android/location/LocationManager.java +33 −3 Original line number Diff line number Diff line Loading @@ -42,12 +42,14 @@ import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; import com.android.internal.location.ProviderProperties; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Set; /** * This class provides access to the system location services. These Loading Loading @@ -1252,12 +1254,40 @@ public class LocationManager { @SystemApi @RequiresPermission(WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean enabled, UserHandle userHandle) { for (String provider : getAllProviders()) { final List<String> allProvidersList = getAllProviders(); // Update all providers on device plus gps and network provider when disabling location. Set<String> allProvidersSet = new ArraySet<>(allProvidersList.size() + 2); allProvidersSet.addAll(allProvidersList); // When disabling location, disable gps and network provider that could have been enabled by // location mode api. if (enabled == false) { allProvidersSet.add(GPS_PROVIDER); allProvidersSet.add(NETWORK_PROVIDER); } if (allProvidersSet.isEmpty()) { return; } // 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. final String prefix = enabled ? "+" : "-"; StringBuilder locationProvidersAllowed = new StringBuilder(); for (String provider : allProvidersSet) { checkProvider(provider); if (provider.equals(PASSIVE_PROVIDER)) { continue; } setProviderEnabledForUser(provider, enabled, userHandle); locationProvidersAllowed.append(prefix); locationProvidersAllowed.append(provider); locationProvidersAllowed.append(","); } // Remove the trailing comma locationProvidersAllowed.setLength(locationProvidersAllowed.length() - 1); Settings.Secure.putStringForUser( mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, locationProvidersAllowed.toString(), userHandle.getIdentifier()); } /** Loading packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +34 −58 Original line number Diff line number Diff line Loading @@ -1798,76 +1798,52 @@ public class SettingsProvider extends ContentProvider { if (TextUtils.isEmpty(value)) { return false; } final char prefix = value.charAt(0); if (prefix != '+' && prefix != '-') { if (forceNotify) { final int key = makeKey(SETTINGS_TYPE_SECURE, owningUserId); mSettingsRegistry.notifyForSettingsChange(key, Settings.Secure.LOCATION_PROVIDERS_ALLOWED); } return false; } // skip prefix value = value.substring(1); Setting settingValue = getSecureSetting( Setting oldSetting = getSecureSetting( Settings.Secure.LOCATION_PROVIDERS_ALLOWED, owningUserId); if (settingValue == null) { if (oldSetting == null) { return false; } String oldProviders = !settingValue.isNull() ? settingValue.getValue() : ""; int index = oldProviders.indexOf(value); int end = index + value.length(); // check for commas to avoid matching on partial string if (index > 0 && oldProviders.charAt(index - 1) != ',') { index = -1; } // check for commas to avoid matching on partial string if (end < oldProviders.length() && oldProviders.charAt(end) != ',') { index = -1; String oldProviders = oldSetting.getValue(); List<String> oldProvidersList = TextUtils.isEmpty(oldProviders) ? new ArrayList<>() : new ArrayList<>(Arrays.asList(oldProviders.split(","))); Set<String> newProvidersSet = new ArraySet<>(); newProvidersSet.addAll(oldProvidersList); String[] providerUpdates = value.split(","); boolean inputError = false; for (String provider : providerUpdates) { // do not update location_providers_allowed when input is invalid if (TextUtils.isEmpty(provider)) { inputError = true; break; } String newProviders; if (prefix == '+' && index < 0) { // append the provider to the list if not present if (oldProviders.length() == 0) { newProviders = value; } else { newProviders = oldProviders + ',' + value; final char prefix = provider.charAt(0); // do not update location_providers_allowed when input is invalid if (prefix != '+' && prefix != '-') { inputError = true; break; } } else if (prefix == '-' && index >= 0) { // remove the provider from the list if present // remove leading or trailing comma if (index > 0) { index--; } else if (end < oldProviders.length()) { end++; // skip prefix provider = provider.substring(1); if (prefix == '+') { newProvidersSet.add(provider); } else if (prefix == '-') { newProvidersSet.remove(provider); } newProviders = oldProviders.substring(0, index); if (end < oldProviders.length()) { newProviders += oldProviders.substring(end); } } else { String newProviders = TextUtils.join(",", newProvidersSet.toArray()); if (inputError == true || newProviders.equals(oldProviders)) { // nothing changed, so no need to update the database if (forceNotify) { final int key = makeKey(SETTINGS_TYPE_SECURE, owningUserId); mSettingsRegistry.notifyForSettingsChange(key, mSettingsRegistry.notifyForSettingsChange( makeKey(SETTINGS_TYPE_SECURE, owningUserId), Settings.Secure.LOCATION_PROVIDERS_ALLOWED); } return false; } return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SECURE, owningUserId, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, newProviders, tag, makeDefault, getCallingPackage(), forceNotify, CRITICAL_SECURE_SETTINGS); owningUserId, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, newProviders, tag, makeDefault, getCallingPackage(), forceNotify, CRITICAL_SECURE_SETTINGS); } private static void warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk( Loading packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java +110 −3 Original line number Diff line number Diff line Loading @@ -17,8 +17,8 @@ package com.android.providers.settings; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertSame; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertSame; import static junit.framework.Assert.fail; import android.content.ContentResolver; Loading @@ -32,9 +32,8 @@ import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.util.Log; import org.junit.Test; import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Test; /** * Tests for the SettingContentProvider. Loading Loading @@ -688,4 +687,112 @@ public class SettingsProviderTest extends BaseSettingsProviderTest { cursor.close(); } } @Test public void testUpdateLocationProvidersAllowedLocked_enableProviders() throws Exception { setSettingViaFrontEndApiAndAssertSuccessfulChange( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_MODE, String.valueOf(Settings.Secure.LOCATION_MODE_OFF), UserHandle.USER_SYSTEM); // Enable one provider updateStringViaProviderApiSetting( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+gps"); assertEquals( "Wrong location providers", "gps", queryStringViaProviderApi( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)); // Enable a list of providers, including the one that is already enabled updateStringViaProviderApiSetting( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+gps,+network,+network"); assertEquals( "Wrong location providers", "gps,network", queryStringViaProviderApi( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)); } @Test public void testUpdateLocationProvidersAllowedLocked_disableProviders() throws Exception { setSettingViaFrontEndApiAndAssertSuccessfulChange( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_MODE, String.valueOf(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY), UserHandle.USER_SYSTEM); // Disable providers that were enabled updateStringViaProviderApiSetting( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-gps,-network"); assertEquals( "Wrong location providers", "", queryStringViaProviderApi( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)); // Disable a provider that was not enabled updateStringViaProviderApiSetting( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-test"); assertEquals( "Wrong location providers", "", queryStringViaProviderApi( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)); } @Test public void testUpdateLocationProvidersAllowedLocked_enableAndDisable() throws Exception { setSettingViaFrontEndApiAndAssertSuccessfulChange( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_MODE, String.valueOf(Settings.Secure.LOCATION_MODE_OFF), UserHandle.USER_SYSTEM); updateStringViaProviderApiSetting( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+gps,+network,+test"); updateStringViaProviderApiSetting( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-test"); assertEquals( "Wrong location providers", "gps,network", queryStringViaProviderApi( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)); } @Test public void testUpdateLocationProvidersAllowedLocked_invalidInput() throws Exception { setSettingViaFrontEndApiAndAssertSuccessfulChange( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_MODE, String.valueOf(Settings.Secure.LOCATION_MODE_OFF), UserHandle.USER_SYSTEM); // update providers with a invalid string updateStringViaProviderApiSetting( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+gps, invalid-string"); // Verifies providers list does not change assertEquals( "Wrong location providers", "", queryStringViaProviderApi( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)); } } Loading
location/java/android/location/LocationManager.java +33 −3 Original line number Diff line number Diff line Loading @@ -42,12 +42,14 @@ import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; import com.android.internal.location.ProviderProperties; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Set; /** * This class provides access to the system location services. These Loading Loading @@ -1252,12 +1254,40 @@ public class LocationManager { @SystemApi @RequiresPermission(WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean enabled, UserHandle userHandle) { for (String provider : getAllProviders()) { final List<String> allProvidersList = getAllProviders(); // Update all providers on device plus gps and network provider when disabling location. Set<String> allProvidersSet = new ArraySet<>(allProvidersList.size() + 2); allProvidersSet.addAll(allProvidersList); // When disabling location, disable gps and network provider that could have been enabled by // location mode api. if (enabled == false) { allProvidersSet.add(GPS_PROVIDER); allProvidersSet.add(NETWORK_PROVIDER); } if (allProvidersSet.isEmpty()) { return; } // 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. final String prefix = enabled ? "+" : "-"; StringBuilder locationProvidersAllowed = new StringBuilder(); for (String provider : allProvidersSet) { checkProvider(provider); if (provider.equals(PASSIVE_PROVIDER)) { continue; } setProviderEnabledForUser(provider, enabled, userHandle); locationProvidersAllowed.append(prefix); locationProvidersAllowed.append(provider); locationProvidersAllowed.append(","); } // Remove the trailing comma locationProvidersAllowed.setLength(locationProvidersAllowed.length() - 1); Settings.Secure.putStringForUser( mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, locationProvidersAllowed.toString(), userHandle.getIdentifier()); } /** Loading
packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +34 −58 Original line number Diff line number Diff line Loading @@ -1798,76 +1798,52 @@ public class SettingsProvider extends ContentProvider { if (TextUtils.isEmpty(value)) { return false; } final char prefix = value.charAt(0); if (prefix != '+' && prefix != '-') { if (forceNotify) { final int key = makeKey(SETTINGS_TYPE_SECURE, owningUserId); mSettingsRegistry.notifyForSettingsChange(key, Settings.Secure.LOCATION_PROVIDERS_ALLOWED); } return false; } // skip prefix value = value.substring(1); Setting settingValue = getSecureSetting( Setting oldSetting = getSecureSetting( Settings.Secure.LOCATION_PROVIDERS_ALLOWED, owningUserId); if (settingValue == null) { if (oldSetting == null) { return false; } String oldProviders = !settingValue.isNull() ? settingValue.getValue() : ""; int index = oldProviders.indexOf(value); int end = index + value.length(); // check for commas to avoid matching on partial string if (index > 0 && oldProviders.charAt(index - 1) != ',') { index = -1; } // check for commas to avoid matching on partial string if (end < oldProviders.length() && oldProviders.charAt(end) != ',') { index = -1; String oldProviders = oldSetting.getValue(); List<String> oldProvidersList = TextUtils.isEmpty(oldProviders) ? new ArrayList<>() : new ArrayList<>(Arrays.asList(oldProviders.split(","))); Set<String> newProvidersSet = new ArraySet<>(); newProvidersSet.addAll(oldProvidersList); String[] providerUpdates = value.split(","); boolean inputError = false; for (String provider : providerUpdates) { // do not update location_providers_allowed when input is invalid if (TextUtils.isEmpty(provider)) { inputError = true; break; } String newProviders; if (prefix == '+' && index < 0) { // append the provider to the list if not present if (oldProviders.length() == 0) { newProviders = value; } else { newProviders = oldProviders + ',' + value; final char prefix = provider.charAt(0); // do not update location_providers_allowed when input is invalid if (prefix != '+' && prefix != '-') { inputError = true; break; } } else if (prefix == '-' && index >= 0) { // remove the provider from the list if present // remove leading or trailing comma if (index > 0) { index--; } else if (end < oldProviders.length()) { end++; // skip prefix provider = provider.substring(1); if (prefix == '+') { newProvidersSet.add(provider); } else if (prefix == '-') { newProvidersSet.remove(provider); } newProviders = oldProviders.substring(0, index); if (end < oldProviders.length()) { newProviders += oldProviders.substring(end); } } else { String newProviders = TextUtils.join(",", newProvidersSet.toArray()); if (inputError == true || newProviders.equals(oldProviders)) { // nothing changed, so no need to update the database if (forceNotify) { final int key = makeKey(SETTINGS_TYPE_SECURE, owningUserId); mSettingsRegistry.notifyForSettingsChange(key, mSettingsRegistry.notifyForSettingsChange( makeKey(SETTINGS_TYPE_SECURE, owningUserId), Settings.Secure.LOCATION_PROVIDERS_ALLOWED); } return false; } return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SECURE, owningUserId, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, newProviders, tag, makeDefault, getCallingPackage(), forceNotify, CRITICAL_SECURE_SETTINGS); owningUserId, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, newProviders, tag, makeDefault, getCallingPackage(), forceNotify, CRITICAL_SECURE_SETTINGS); } private static void warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk( Loading
packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java +110 −3 Original line number Diff line number Diff line Loading @@ -17,8 +17,8 @@ package com.android.providers.settings; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertSame; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertSame; import static junit.framework.Assert.fail; import android.content.ContentResolver; Loading @@ -32,9 +32,8 @@ import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.util.Log; import org.junit.Test; import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Test; /** * Tests for the SettingContentProvider. Loading Loading @@ -688,4 +687,112 @@ public class SettingsProviderTest extends BaseSettingsProviderTest { cursor.close(); } } @Test public void testUpdateLocationProvidersAllowedLocked_enableProviders() throws Exception { setSettingViaFrontEndApiAndAssertSuccessfulChange( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_MODE, String.valueOf(Settings.Secure.LOCATION_MODE_OFF), UserHandle.USER_SYSTEM); // Enable one provider updateStringViaProviderApiSetting( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+gps"); assertEquals( "Wrong location providers", "gps", queryStringViaProviderApi( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)); // Enable a list of providers, including the one that is already enabled updateStringViaProviderApiSetting( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+gps,+network,+network"); assertEquals( "Wrong location providers", "gps,network", queryStringViaProviderApi( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)); } @Test public void testUpdateLocationProvidersAllowedLocked_disableProviders() throws Exception { setSettingViaFrontEndApiAndAssertSuccessfulChange( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_MODE, String.valueOf(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY), UserHandle.USER_SYSTEM); // Disable providers that were enabled updateStringViaProviderApiSetting( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-gps,-network"); assertEquals( "Wrong location providers", "", queryStringViaProviderApi( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)); // Disable a provider that was not enabled updateStringViaProviderApiSetting( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-test"); assertEquals( "Wrong location providers", "", queryStringViaProviderApi( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)); } @Test public void testUpdateLocationProvidersAllowedLocked_enableAndDisable() throws Exception { setSettingViaFrontEndApiAndAssertSuccessfulChange( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_MODE, String.valueOf(Settings.Secure.LOCATION_MODE_OFF), UserHandle.USER_SYSTEM); updateStringViaProviderApiSetting( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+gps,+network,+test"); updateStringViaProviderApiSetting( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-test"); assertEquals( "Wrong location providers", "gps,network", queryStringViaProviderApi( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)); } @Test public void testUpdateLocationProvidersAllowedLocked_invalidInput() throws Exception { setSettingViaFrontEndApiAndAssertSuccessfulChange( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_MODE, String.valueOf(Settings.Secure.LOCATION_MODE_OFF), UserHandle.USER_SYSTEM); // update providers with a invalid string updateStringViaProviderApiSetting( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+gps, invalid-string"); // Verifies providers list does not change assertEquals( "Wrong location providers", "", queryStringViaProviderApi( SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)); } }