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; }