Merge "Disable Wifi when a user press cancel in XL setup"
diff --git a/res/layout/manage_applications.xml b/res/layout/manage_applications.xml
index 2d6678a..95d4847 100755
--- a/res/layout/manage_applications.xml
+++ b/res/layout/manage_applications.xml
@@ -60,7 +60,7 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_weight="0"
-                android:layout_marginTop="-23dp"
+                android:layout_marginTop="-20dp"
                 android:textAppearance="?android:attr/textAppearanceSmallInverse"
                 android:textColor="#ccc"
                 android:shadowColor="#000"
diff --git a/res/layout/running_processes_view.xml b/res/layout/running_processes_view.xml
index 2e62c48..3558e92 100644
--- a/res/layout/running_processes_view.xml
+++ b/res/layout/running_processes_view.xml
@@ -60,7 +60,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_weight="0"
-            android:layout_marginTop="-23dp"
+            android:layout_marginTop="-20dp"
             android:textAppearance="?android:attr/textAppearanceSmallInverse"
             android:textColor="#ccc"
             android:shadowColor="#000"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e00d3c2..1d763ee 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1406,12 +1406,14 @@
     <string name="sd_insert_summary" product="nosdcard">Insert USB storage for mounting</string>
     <!-- SD card & phone storage settings item summary that is displayed when no SD card is inserted -->
     <string name="sd_insert_summary" product="default">Insert an SD card for mounting</string>
-    <!-- SD card & phone storage settings item title that will result in the phone mounting the SD card. [CHAR LIMIT=25] -->
-    <string name="sd_mount" product="nosdcard">Mount shared storage</string>
+
+    <!-- Storage setting item that will mount USB storage if it unmounted. A user should never see this. [CHAR LIMIT=25] -->
+    <string name="sd_mount" product="nosdcard">Mount USB storage</string>
     <!-- SD card & phone storage settings item title that will result in the phone mounting the SD card. -->
     <string name="sd_mount" product="default">Mount SD card</string>
-    <!-- SD card & phone storage settings item title that will result in the phone mounting the SD card. [CHAR LIMIT=30] -->
-    <string name="sd_mount_summary" product="nosdcard">Mount the internal USB storage</string>
+
+    <!-- Subtext for Mount USB storage in Storage settings. User should never see this. -->
+    <string name="sd_mount_summary" product="nosdcard">Mount the USB storage</string>
     <!-- SD card & phone storage settings item title that will result in the phone mounting the SD card. -->
     <string name="sd_mount_summary" product="default">Mount the SD card</string>
     <!-- SD card & phone storage settings item title that will result in the phone formatting the USB storage.   [CHAR LIMIT=25] -->
@@ -1678,6 +1680,12 @@
     <string name="assisted_gps_enabled">Use server to assist GPS (uncheck to reduce network usage)</string>
     <!-- Security & location settings screen, setting summary when Assisted GPS check box is clear -->
     <string name="assisted_gps_disabled">Use server to assist GPS (uncheck to improve GPS performance)</string>
+    <!-- [CHAR_LIMIT=100] Security & location settings screen, setting check box label if the user wants to use their location for Google Search & other Google services -->
+    <string name="use_location_title">Use location for Google search</string>
+    <!-- [CHAR_LIMIT=100] Security & location settings screen, setting summary when Use My Location for Google services is clear -->
+    <string name="use_location_summary_disabled">Use location for Google search and other Google services</string>
+    <!-- [CHAR_LIMIT=100] Security & location settings screen, setting summary when Use My Location for Google services is checked -->
+    <string name="use_location_summary_enabled">Location used to improve Google search results and other Google services</string>
 
     <!-- About --> <skip />
     <!-- Main settings screen, setting title for the user to go into the About phone screen -->
diff --git a/src/com/android/settings/GoogleLocationSettingHelper.java b/src/com/android/settings/GoogleLocationSettingHelper.java
new file mode 100644
index 0000000..0d4861e
--- /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 dacc19f..dd51295 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -36,10 +36,11 @@
 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 @@
     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 @@
     private CheckBoxPreference mNetwork;
     private CheckBoxPreference mGps;
     private CheckBoxPreference mAssistedGps;
+    private CheckBoxPreference mUseLocation;
 
     DevicePolicyManager mDPM;
 
@@ -158,6 +162,22 @@
         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 @@
         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 @@
             } 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;
     }
diff --git a/src/com/android/settings/applications/ApplicationsState.java b/src/com/android/settings/applications/ApplicationsState.java
index c08ae5a..814bbbf 100644
--- a/src/com/android/settings/applications/ApplicationsState.java
+++ b/src/com/android/settings/applications/ApplicationsState.java
@@ -585,7 +585,7 @@
 
     private long getTotalSize(PackageStats ps) {
         if (ps != null) {
-            return ps.cacheSize+ps.codeSize+ps.dataSize;
+            return ps.codeSize+ps.dataSize;
         }
         return SIZE_INVALID;
     }
diff --git a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
index 7805e14..c0fa105 100644
--- a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
+++ b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
@@ -300,7 +300,7 @@
         LocalBluetoothProfileManager profileManager =
             LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile);
         CachedBluetoothDeviceManager cachedDeviceManager = mLocalManager.getCachedDeviceManager();
-        Set<BluetoothDevice> devices = profileManager.getConnectedDevices();
+        List<BluetoothDevice> devices = profileManager.getConnectedDevices();
         if (devices == null) return;
         for (BluetoothDevice btDevice : devices) {
             CachedBluetoothDevice cachedDevice = cachedDeviceManager.findDevice(btDevice);
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothManager.java b/src/com/android/settings/bluetooth/LocalBluetoothManager.java
index d503325..613ee25 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothManager.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothManager.java
@@ -196,10 +196,9 @@
 
                 // If we are playing music, don't scan unless forced.
                 if (mBluetoothA2dp != null) {
-                    Set<BluetoothDevice> sinks = mBluetoothA2dp.getConnectedDevices();
+                    List<BluetoothDevice> sinks = mBluetoothA2dp.getConnectedDevices();
                     if (sinks.size() > 0) {
-                        BluetoothDevice sink = sinks.toArray(new BluetoothDevice[sinks.size()])[0];
-                        if (mBluetoothA2dp.isA2dpPlaying(sink)) return;
+                        if (mBluetoothA2dp.isA2dpPlaying(sinks.get(0))) return;
                     }
                 }
             }
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java
index 7e11887..1480b16 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java
@@ -197,7 +197,7 @@
         mLocalManager = localManager;
     }
 
-    public abstract Set<BluetoothDevice> getConnectedDevices();
+    public abstract List<BluetoothDevice> getConnectedDevices();
 
     public abstract boolean connect(BluetoothDevice device);
 
@@ -261,7 +261,7 @@
         }
 
         @Override
-        public Set<BluetoothDevice> getConnectedDevices() {
+        public List<BluetoothDevice> getConnectedDevices() {
             return mService.getDevicesMatchingConnectionStates(
                   new int[] {BluetoothProfile.STATE_CONNECTED,
                              BluetoothProfile.STATE_CONNECTING,
@@ -270,7 +270,7 @@
 
         @Override
         public boolean connect(BluetoothDevice device) {
-            Set<BluetoothDevice> sinks = getConnectedDevices();
+            List<BluetoothDevice> sinks = getConnectedDevices();
             if (sinks != null) {
                 for (BluetoothDevice sink : sinks) {
                     mService.disconnect(sink);
@@ -378,14 +378,11 @@
                      * We just bound to the service, so refresh the UI of the
                      * headset device.
                      */
-                    Set<BluetoothDevice> deviceSet = mService.getConnectedDevices();
-                    if (deviceSet.size() == 0) return;
-
-                    BluetoothDevice[] devices =
-                        deviceSet.toArray(new BluetoothDevice[deviceSet.size()]);
+                    List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+                    if (deviceList.size() == 0) return;
 
                     mLocalManager.getCachedDeviceManager()
-                            .onProfileStateChanged(devices[0], Profile.HEADSET,
+                            .onProfileStateChanged(deviceList.get(0), Profile.HEADSET,
                                                    BluetoothProfile.STATE_CONNECTED);
                 }
             });
@@ -415,7 +412,7 @@
         }
 
         @Override
-        public Set<BluetoothDevice> getConnectedDevices() {
+        public List<BluetoothDevice> getConnectedDevices() {
             return mService.getConnectedDevices();
         }
 
@@ -426,9 +423,8 @@
 
         @Override
         public boolean disconnect(BluetoothDevice device) {
-            Set<BluetoothDevice> deviceSet = getConnectedDevices();
-            BluetoothDevice[] devices = deviceSet.toArray(new BluetoothDevice[deviceSet.size()]);
-            if (devices.length != 0 && devices[0].equals(device)) {
+            List<BluetoothDevice> deviceList = getConnectedDevices();
+            if (deviceList.size() != 0 && deviceList.get(0).equals(device)) {
                 // Downgrade prority as user is disconnecting the headset.
                 if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
                     mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
@@ -441,10 +437,9 @@
 
         @Override
         public int getConnectionStatus(BluetoothDevice device) {
-            Set<BluetoothDevice> deviceSet = getConnectedDevices();
-            BluetoothDevice[] devices = deviceSet.toArray(new BluetoothDevice[deviceSet.size()]);
+            List<BluetoothDevice> deviceList = getConnectedDevices();
 
-            return devices.length > 0 && devices[0].equals(device)
+            return deviceList.size() > 0 && deviceList.get(0).equals(device)
                     ? convertState(mService.getConnectionState(device))
                     : SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED;
         }
@@ -506,7 +501,7 @@
         }
 
         @Override
-        public Set<BluetoothDevice> getConnectedDevices() {
+        public List<BluetoothDevice> getConnectedDevices() {
             return null;
         }
 
@@ -605,7 +600,7 @@
         }
 
         @Override
-        public Set<BluetoothDevice> getConnectedDevices() {
+        public List<BluetoothDevice> getConnectedDevices() {
             return mService.getConnectedInputDevices();
         }
 
@@ -703,7 +698,7 @@
         }
 
         @Override
-        public Set<BluetoothDevice> getConnectedDevices() {
+        public List<BluetoothDevice> getConnectedDevices() {
             return mService.getConnectedDevices();
         }