diff --git a/res/values/strings.xml b/res/values/strings.xml
index d4acfd61dd0..1d763eede4e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1680,6 +1680,12 @@
Use server to assist GPS (uncheck to reduce network usage)
Use server to assist GPS (uncheck to improve GPS performance)
+
+ Use location for Google search
+
+ Use location for Google search and other Google services
+
+ Location used to improve Google search results and other Google services
diff --git a/src/com/android/settings/GoogleLocationSettingHelper.java b/src/com/android/settings/GoogleLocationSettingHelper.java
new file mode 100644
index 00000000000..0d4861e36e5
--- /dev/null
+++ b/src/com/android/settings/GoogleLocationSettingHelper.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2010 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.settings;
+
+import android.content.ActivityNotFoundException;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.database.Cursor;
+import android.net.Uri;
+import android.util.Log;
+
+/**
+ * Helper class to read and write the 'Use My Location' setting used by Google Apps (e.g. GoogleQSB,
+ * VoiceSearch).
+ *
+ * This class duplicates a small amount of functionality from GSF (Google Services Framework) to
+ * allow the open source Settings app to interface to the 'Use My Location' setting owned by GSF.
+ */
+public class GoogleLocationSettingHelper {
+
+ private static final String TAG = "GoogleLocationSettingHelper";
+
+ /**
+ * User has disagreed to use location for Google services.
+ */
+ public static final int USE_LOCATION_FOR_SERVICES_OFF = 0;
+
+ /**
+ * User has agreed to use location for Google services.
+ */
+ public static final int USE_LOCATION_FOR_SERVICES_ON = 1;
+
+ /**
+ * The user has neither agreed nor disagreed to use location for Google services yet.
+ */
+ public static final int USE_LOCATION_FOR_SERVICES_NOT_SET = 2;
+
+ private static final String GOOGLE_SETTINGS_AUTHORITY = "com.google.settings";
+ private static final Uri GOOGLE_SETTINGS_CONTENT_URI =
+ Uri.parse("content://" + GOOGLE_SETTINGS_AUTHORITY + "/partner");
+ private static final String NAME = "name";
+ private static final String VALUE = "value";
+ private static final String USE_LOCATION_FOR_SERVICES = "use_location_for_services";
+
+ private static final String ACTION_SET_USE_LOCATION_FOR_SERVICES =
+ "com.google.android.gsf.action.SET_USE_LOCATION_FOR_SERVICES";
+ public static final String EXTRA_DISABLE_USE_LOCATION_FOR_SERVICES = "disable";
+
+ /**
+ * Determine if the 'Use My Location' setting is applicable on this device, i.e. if the
+ * activity used to enabled/disable it is present.
+ */
+ public static boolean isAvailable(Context context) {
+ ResolveInfo ri = context.getPackageManager().resolveActivity(getSetUseLocationIntent(),
+ PackageManager.MATCH_DEFAULT_ONLY);
+ return ri != null;
+ }
+
+ private static Intent getSetUseLocationIntent() {
+ Intent i = new Intent(ACTION_SET_USE_LOCATION_FOR_SERVICES);
+ return i;
+ }
+
+ /**
+ * Get the current value for the 'Use value for location' setting.
+ * @return One of {@link #USE_LOCATION_FOR_SERVICES_NOT_SET},
+ * {@link #USE_LOCATION_FOR_SERVICES_OFF} or {@link #USE_LOCATION_FOR_SERVICES_ON}.
+ */
+ public static int getUseLocationForServices(Context context) {
+ ContentResolver resolver = context.getContentResolver();
+ Cursor c = null;
+ String stringValue = null;
+ try {
+ c = resolver.query(GOOGLE_SETTINGS_CONTENT_URI, new String[] { VALUE }, NAME + "=?",
+ new String[] { USE_LOCATION_FOR_SERVICES }, null);
+ if (c != null && c.moveToNext()) {
+ stringValue = c.getString(0);
+ }
+ } catch (RuntimeException e) {
+ Log.w(TAG, "Failed to get 'Use My Location' setting", e);
+ } finally {
+ if (c != null) {
+ c.close();
+ }
+ }
+ if (stringValue == null) {
+ return USE_LOCATION_FOR_SERVICES_NOT_SET;
+ }
+ int value;
+ try {
+ value = Integer.parseInt(stringValue);
+ } catch (NumberFormatException nfe) {
+ value = USE_LOCATION_FOR_SERVICES_NOT_SET;
+ }
+ return value;
+ }
+
+ /**
+ * Change the value of the 'Use My Location' setting. This launches a GSF activity which has
+ * the permissions to actually make the change, prompting the user if necessary.
+ */
+ public static void setUseLocationForServices(Context context, boolean use) {
+ Intent i = getSetUseLocationIntent();
+ i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ i.putExtra(EXTRA_DISABLE_USE_LOCATION_FOR_SERVICES, !use);
+ try {
+ context.startActivity(i);
+ } catch (ActivityNotFoundException e) {
+ }
+ }
+
+}
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index dacc19f4337..dd512952c0a 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -36,10 +36,11 @@ import android.os.SystemProperties;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceCategory;
+import android.preference.PreferenceGroup;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
-import android.preference.Preference.OnPreferenceChangeListener;
import android.provider.Settings;
import android.security.Credentials;
import android.security.KeyStore;
@@ -78,15 +79,17 @@ public class SecuritySettings extends SettingsPreferenceFragment
private CheckBoxPreference mShowPassword;
// Location Settings
+ private static final String LOCATION_CATEGORY = "location_category";
private static final String LOCATION_NETWORK = "location_network";
private static final String LOCATION_GPS = "location_gps";
private static final String ASSISTED_GPS = "assisted_gps";
+ private static final String USE_LOCATION = "location_use_for_services";
private static final String LOCK_AFTER_TIMEOUT_KEY = "lock_after_timeout";
private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123;
private static final int FALLBACK_LOCK_AFTER_TIMEOUT_VALUE = 5000; // compatible with pre-Froyo
// Credential storage
- private CredentialStorage mCredentialStorage = new CredentialStorage();
+ private final CredentialStorage mCredentialStorage = new CredentialStorage();
// Encrypted file system
private CheckBoxPreference mEncryptedFSEnabled;
@@ -94,6 +97,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
private CheckBoxPreference mNetwork;
private CheckBoxPreference mGps;
private CheckBoxPreference mAssistedGps;
+ private CheckBoxPreference mUseLocation;
DevicePolicyManager mDPM;
@@ -158,6 +162,22 @@ public class SecuritySettings extends SettingsPreferenceFragment
mNetwork = (CheckBoxPreference) getPreferenceScreen().findPreference(LOCATION_NETWORK);
mGps = (CheckBoxPreference) getPreferenceScreen().findPreference(LOCATION_GPS);
mAssistedGps = (CheckBoxPreference) getPreferenceScreen().findPreference(ASSISTED_GPS);
+ if (GoogleLocationSettingHelper.isAvailable(getActivity())) {
+ // GSF present, Add setting for 'Use My Location'
+ PreferenceGroup locationCat = (PreferenceGroup) root.findPreference(LOCATION_CATEGORY);
+ CheckBoxPreference useLocation = new CheckBoxPreference(getActivity());
+ useLocation.setKey(USE_LOCATION);
+ useLocation.setTitle(R.string.use_location_title);
+ useLocation.setSummaryOn(R.string.use_location_summary_enabled);
+ useLocation.setSummaryOff(R.string.use_location_summary_disabled);
+ useLocation.setChecked(
+ GoogleLocationSettingHelper.getUseLocationForServices(getActivity())
+ == GoogleLocationSettingHelper.USE_LOCATION_FOR_SERVICES_ON);
+ useLocation.setPersistent(false);
+ useLocation.setOnPreferenceChangeListener(this);
+ locationCat.addPreference(useLocation);
+ mUseLocation = useLocation;
+ }
PreferenceManager pm = getPreferenceManager();
@@ -398,7 +418,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
private static final int DLG_RESET = DLG_PASSWORD + 1;
private static final int DLG_ENABLE_EFS = DLG_RESET + 1;
- private KeyStore mKeyStore = KeyStore.getInstance();
+ private final KeyStore mKeyStore = KeyStore.getInstance();
private int mState;
private boolean mSubmit = false;
private boolean mExternal = false;
@@ -748,6 +768,14 @@ public class SecuritySettings extends SettingsPreferenceFragment
} catch (NumberFormatException e) {
Log.e("SecuritySettings", "could not persist lockAfter timeout setting", e);
}
+ } else if (preference == mUseLocation) {
+ boolean newValue = value == null ? false : (Boolean) value;
+ GoogleLocationSettingHelper.setUseLocationForServices(getActivity(), newValue);
+ // We don't want to change the value immediately here, since the user may click
+ // disagree in the dialog that pops up. When the activity we just launched exits, this
+ // activity will be restated and the new value re-read, so the checkbox will get its
+ // new value then.
+ return false;
}
return true;
}