Merge "Fix bug #16356067 adb shell am start -a android.settings.DEVICE_INFO_SETTINGS is crashing again" into lmp-dev
diff --git a/res/drawable-hdpi/wifi_assistant_card.png b/res/drawable-hdpi/wifi_assistant_card.png
new file mode 100644
index 0000000..5a7e6d1
--- /dev/null
+++ b/res/drawable-hdpi/wifi_assistant_card.png
Binary files differ
diff --git a/res/drawable-hdpi/wifi_assistant_card_tablet.png b/res/drawable-hdpi/wifi_assistant_card_tablet.png
new file mode 100644
index 0000000..d309533
--- /dev/null
+++ b/res/drawable-hdpi/wifi_assistant_card_tablet.png
Binary files differ
diff --git a/res/drawable-mdpi/wifi_assistant_card.png b/res/drawable-mdpi/wifi_assistant_card.png
new file mode 100644
index 0000000..bb2114c
--- /dev/null
+++ b/res/drawable-mdpi/wifi_assistant_card.png
Binary files differ
diff --git a/res/drawable-mdpi/wifi_assistant_card_tablet.png b/res/drawable-mdpi/wifi_assistant_card_tablet.png
new file mode 100644
index 0000000..0ca411c
--- /dev/null
+++ b/res/drawable-mdpi/wifi_assistant_card_tablet.png
Binary files differ
diff --git a/res/drawable-xhdpi/wifi_assistant_card.png b/res/drawable-xhdpi/wifi_assistant_card.png
new file mode 100644
index 0000000..1f8a5b9
--- /dev/null
+++ b/res/drawable-xhdpi/wifi_assistant_card.png
Binary files differ
diff --git a/res/drawable-xhdpi/wifi_assistant_card_tablet.png b/res/drawable-xhdpi/wifi_assistant_card_tablet.png
new file mode 100644
index 0000000..570a663
--- /dev/null
+++ b/res/drawable-xhdpi/wifi_assistant_card_tablet.png
Binary files differ
diff --git a/res/drawable-xxhdpi/wifi_assistant_card.png b/res/drawable-xxhdpi/wifi_assistant_card.png
new file mode 100644
index 0000000..65211cd
--- /dev/null
+++ b/res/drawable-xxhdpi/wifi_assistant_card.png
Binary files differ
diff --git a/res/drawable-xxhdpi/wifi_assistant_card_tablet.png b/res/drawable-xxhdpi/wifi_assistant_card_tablet.png
new file mode 100644
index 0000000..2941b14
--- /dev/null
+++ b/res/drawable-xxhdpi/wifi_assistant_card_tablet.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/wifi_assistant_card.png b/res/drawable-xxxhdpi/wifi_assistant_card.png
new file mode 100644
index 0000000..e79330b
--- /dev/null
+++ b/res/drawable-xxxhdpi/wifi_assistant_card.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/wifi_assistant_card_tablet.png b/res/drawable-xxxhdpi/wifi_assistant_card_tablet.png
new file mode 100644
index 0000000..54120fb
--- /dev/null
+++ b/res/drawable-xxxhdpi/wifi_assistant_card_tablet.png
Binary files differ
diff --git a/res/layout/crypt_keeper_password_entry.xml b/res/layout/crypt_keeper_password_entry.xml
index b26f542..ecbfefd 100644
--- a/res/layout/crypt_keeper_password_entry.xml
+++ b/res/layout/crypt_keeper_password_entry.xml
@@ -33,17 +33,16 @@
     >
         <include layout="@layout/crypt_keeper_password_field" />
     </LinearLayout>
-
     <!-- Emergency call button.
-         Text and icon are set by CryptKeeper.updateEmergencyCallButtonState() -->
+         Text is set by CryptKeeper.updateEmergencyCallButtonState() -->
     <Button android:id="@+id/emergencyCallButton"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center"
         android:layout_marginTop="16dip"
-        style="@*android:style/Widget.Button.Transparent"
+        style="?android:attr/borderlessButtonStyle"
         android:textSize="14sp"
         android:drawablePadding="6dip"
-    />
+        />
 
 </LinearLayout>
diff --git a/res/layout/crypt_keeper_password_field.xml b/res/layout/crypt_keeper_password_field.xml
index 97afe6a..9a2a24d 100644
--- a/res/layout/crypt_keeper_password_field.xml
+++ b/res/layout/crypt_keeper_password_field.xml
@@ -28,6 +28,7 @@
         android:inputType="textPassword"
         android:imeOptions="flagForceAscii|actionDone"
         android:textAppearance="?android:attr/textAppearanceMedium"
+        android:gravity="center_horizontal"
      />
 
    <ImageView android:id="@+id/switch_ime_button"
diff --git a/res/layout/crypt_keeper_pattern_entry.xml b/res/layout/crypt_keeper_pattern_entry.xml
index a59d36f..2538809 100644
--- a/res/layout/crypt_keeper_pattern_entry.xml
+++ b/res/layout/crypt_keeper_pattern_entry.xml
@@ -41,8 +41,7 @@
         android:layout_height="wrap_content"
         android:layout_gravity="center"
         android:layout_marginTop="16dip"
-        style="@*android:style/Widget.Button.Transparent"
-        android:textSize="14sp"
+        style="?android:attr/borderlessButtonStyle"
         android:drawablePadding="6dip"
     />
 
diff --git a/res/layout/crypt_keeper_pin_entry.xml b/res/layout/crypt_keeper_pin_entry.xml
index dfc5fb5..0f1f1e7 100644
--- a/res/layout/crypt_keeper_pin_entry.xml
+++ b/res/layout/crypt_keeper_pin_entry.xml
@@ -41,8 +41,7 @@
         android:layout_height="wrap_content"
         android:layout_gravity="center"
         android:layout_marginTop="16dip"
-        style="@*android:style/Widget.Button.Transparent"
-        android:textSize="14sp"
+        style="?android:attr/borderlessButtonStyle"
         android:drawablePadding="6dip"
     />
 
diff --git a/res/layout/crypt_keeper_pin_field.xml b/res/layout/crypt_keeper_pin_field.xml
index 270b26b..dd9d233 100644
--- a/res/layout/crypt_keeper_pin_field.xml
+++ b/res/layout/crypt_keeper_pin_field.xml
@@ -28,6 +28,7 @@
         android:inputType="numberPassword"
         android:imeOptions="flagForceAscii|actionDone"
         android:textAppearance="?android:attr/textAppearanceMedium"
+        android:gravity="center_horizontal"
      />
 
    <ImageView android:id="@+id/switch_ime_button"
diff --git a/res/layout/wifi_assistant_card.xml b/res/layout/wifi_assistant_card.xml
new file mode 100644
index 0000000..a1917ba
--- /dev/null
+++ b/res/layout/wifi_assistant_card.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/wifi_assistant_card"
+    android:background="@android:color/transparent"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:gravity="center_vertical"
+    android:orientation="vertical"
+    android:padding="@dimen/wifi_assistant_padding">
+
+    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content">
+
+        <ImageView
+            android:id="@+id/cardBackground"
+            android:background="@color/setup_add_wifi_network_text_color"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:src="@drawable/wifi_assistant_card" />
+
+        <TextView
+            android:id="@+id/backgroundText"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="@dimen/wifi_assistant_text_padding"
+            android:gravity="start"
+            android:text="@string/wifi_assistant_intro_setup"
+            style="@style/WifiAssistantText" />
+
+    </RelativeLayout>
+
+    <TextView
+        android:id="@+id/wifi_assistant_text"
+        android:background="@android:color/transparent"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_marginBottom="@dimen/wifi_assistant_padding_top_bottom"
+        android:layout_marginTop="@dimen/wifi_assistant_padding_top_bottom"
+        android:layout_marginLeft="@dimen/wifi_assistant_padding_start_end"
+        android:layout_marginRight="@dimen/wifi_assistant_padding_start_end"
+        android:gravity="start"
+        android:text="@string/wifi_assistant_title_message"
+        android:textAppearance="?android:attr/textAppearanceMedium" />
+
+    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:background="@android:color/transparent"
+        android:layout_height="wrap_content"
+        android:layout_width="fill_parent"
+        android:gravity="end"
+        android:orientation="horizontal">
+
+        <Button
+            android:id="@+id/no_thanks_button"
+            android:background="@android:color/white"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:text="@string/wifi_assistant_no_thanks"
+            android:paddingLeft="@dimen/wifi_assistant_text_padding"
+            android:paddingRight="@dimen/wifi_assistant_text_padding" />
+
+        <Button
+            android:id="@+id/setup"
+            android:background="@android:color/white"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:paddingLeft="@dimen/wifi_assistant_text_padding"
+            android:paddingRight="@dimen/wifi_assistant_text_padding"
+            android:text="@string/wifi_assistant_setup"
+            style="@style/WifiAssistantButton" />
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/res/values-h480dp/dimens.xml b/res/values-h480dp/dimens.xml
index 6610b4f..d5e3e27 100644
--- a/res/values-h480dp/dimens.xml
+++ b/res/values-h480dp/dimens.xml
@@ -16,4 +16,10 @@
 
 <resources>
     <dimen name="battery_history_chart_height">160dp</dimen>
+
+    <!-- Dimensions for Wifi Assistant Card -->
+    <dimen name="wifi_assistant_padding_top_bottom">16dp</dimen>
+    <dimen name="wifi_assistant_padding_start_end">16dp</dimen>
+    <dimen name="wifi_assistant_padding">25dp</dimen>
+    <dimen name="wifi_assistant_text_padding">16dp</dimen>
 </resources>
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index d35d973..8d560ea 100755
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -70,4 +70,9 @@
     <dimen name="search_result_item_image_margin_start">24dp</dimen>
     <dimen name="search_result_item_image_margin_end">32dp</dimen>
 
+    <!-- Dimensions for Wifi Assistant Card -->
+    <dimen name="wifi_assistant_padding_top_bottom">24dp</dimen>
+    <dimen name="wifi_assistant_padding_start_end">24dp</dimen>
+    <dimen name="wifi_assistant_padding">25dp</dimen>
+    <dimen name="wifi_assistant_text_padding">24dp</dimen>
 </resources>
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
index b1d084f..981c936 100644
--- a/res/values-sw720dp/dimens.xml
+++ b/res/values-sw720dp/dimens.xml
@@ -50,4 +50,9 @@
     <dimen name="switchbar_subsettings_margin_start">80dp</dimen>
     <dimen name="switchbar_subsettings_margin_end">80dp</dimen>
 
+    <!-- Dimensions for Wifi Assistant Card -->
+    <dimen name="wifi_assistant_padding_top_bottom">24dp</dimen>
+    <dimen name="wifi_assistant_padding_start_end">24dp</dimen>
+    <dimen name="wifi_assistant_padding">25dp</dimen>
+    <dimen name="wifi_assistant_text_padding">24dp</dimen>
 </resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 0b3ea39..b523801 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -40,6 +40,7 @@
     <color name="setup_divider_color_dark">#33ffffff</color>
     <color name="setup_divider_color_light">#33000000</color>
     <color name="setup_add_wifi_network_text_color">#ff009587</color>
+    <color name="setup_add_wifi_network_background_color">#ff009587</color>
 
     <color name="circle_avatar_frame_color">#ffffffff</color>
     <color name="circle_avatar_frame_shadow_color">#80000000</color>
@@ -50,6 +51,10 @@
     <color name="lock_pattern_view_success_color">@color/theme_accent</color>
     <color name="lock_pattern_view_error_color">#fff4511e</color>
 
+    <color name="unlock_pattern_view_regular_color">@android:color/white</color>
+    <color name="unlock_pattern_view_success_color">@color/theme_accent</color>
+    <color name="unlock_pattern_view_error_color">#fff4511e</color>
+
     <!-- Palette colors referenced by top-level themes. -->
     <color name="theme_primary">#ff263238</color>
     <color name="theme_primary_dark">#ff21272b</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 32a2fff..ae654e4 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -165,4 +165,10 @@
     <dimen name="search_suggestion_item_image_margin_start">32dp</dimen>
     <dimen name="search_suggestion_item_image_margin_end">16dp</dimen>
 
+    <!-- Dimensions for Wifi Assistant Card -->
+    <dimen name="wifi_assistant_padding_top_bottom">16dp</dimen>
+    <dimen name="wifi_assistant_padding_start_end">16dp</dimen>
+    <dimen name="wifi_assistant_padding">25dp</dimen>
+    <dimen name="wifi_assistant_text_padding">16dp</dimen>
+
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 04e0b9a..4f71c97 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -646,11 +646,15 @@
     <!-- Main Settings screen settings summary text for the "Wireless controls" setting -->
     <string name="radio_controls_summary">Manage Wi\u2011Fi, Bluetooth, airplane mode, cellular networks, &amp; VPNs</string>
 
-    <!-- check box cellular data title [CHAR LIMIT=30]-->
+    <!-- check box cellular data title [CHAR LIMIT=30] -->
     <string name="cellular_data_title">Cellular data</string>
-    <!-- check box cellular data summary [CHAR LIMIT=40]-->
+    <!-- check box Calls title [CHAR LIMIT=30] -->
+    <string name="calls_title">Calls</string>
+    <!-- check box SMS Messges title [CHAR LIMIT=30] -->
+    <string name="sms_messages_title">SMS Messages</string>
+    <!-- check box cellular data summary [CHAR LIMIT=40] -->
     <string name="cellular_data_summary">Allow data usage over cellular network</string>
-    <!-- check box to allow data usage when roaming [CHAR LIMIT=30]-->
+    <!-- check box to allow data usage when roaming [CHAR LIMIT=30] -->
     <string name="allow_data_usage_title">Allow data usage when roaming</string>
     <!-- mobile network settings screen, setting check box title -->
     <string name="roaming">Data roaming</string>
@@ -1164,6 +1168,8 @@
     <string name="bluetooth_preference_paired_dialog_internet_option">Internet connection</string>
     <!-- Bluetooth settings: Checkbox label for enable/disable keyboard connection.  [CHAR LIMIT=40] -->
     <string name="bluetooth_preference_paired_dialog_keyboard_option">Keyboard</string>
+    <!-- Bluetooth settings: Checkbox label for enable/disable contacts connection.  [CHAR LIMIT=40] -->
+    <string name="bluetooth_preference_paired_dialog_contacts_option">Contacts and call history</string>
     <!-- Bluetooth settings: pairing dialog title.  [CHAR LIMIT=40] -->
     <string name="bluetooth_pairing_dialog_title">Pair with this device?</string>
     <!-- Bluetooth settings: share phone book title.  [CHAR LIMIT=40] -->
@@ -1171,7 +1177,7 @@
     <!-- Bluetooth settings: Message informing user that a bluetooth wants to access contant and call history.  [CHAR LIMIT=100] -->
     <string name="bluetooth_pairing_dialog_contants_request"><xliff:g id="device_name">%1$s</xliff:g> wants to access your contacts and call history.</string>
     <!-- Bluetooth settings: paring permission message.  [CHAR LIMIT=100] -->
-    <string name="bluetooth_pairing_dialog_paring_request"><xliff:g id="device_name">%1$s</xliff:g> wants to pair with Bluetooth.</string>
+    <string name="bluetooth_pairing_dialog_paring_request"><xliff:g id="device_name">%1$s</xliff:g> wants to pair with Bluetooth. When connected, it will have access to your contacts and call history.</string>
     <!-- Bluetooth settings: The sub heading for devices which have already been paired with this device. [CHAR LIMIT=40] -->
     <string name="bluetooth_preference_paired_devices">Paired devices</string>
     <!-- Bluetooth settings: The sub heading for messaging accesses. [CHAR LIMIT=50] -->
@@ -1288,6 +1294,8 @@
     <!-- Bluetooth settings.  Dock Setting Dialog - Remember setting and don't ask user again -->
     <string name="bluetooth_dock_settings_remember">Remember settings</string>
 
+    <!-- Wifi Assistant title string.  [CHAR LIMIT=20] -->
+    <string name="wifi_assistant_intro_setup">Introducing\nWi\u2011Fi Assistant</string>
     <!-- Wifi Assistant title string.  [CHAR LIMIT=40] -->
     <string name="wifi_assistant_title">Wi\u2011Fi Assistant</string>
     <!-- Wifi Assistant No, thanks string.  Text to say no to wifi assistant. [CHAR LIMIT=20] -->
@@ -1450,7 +1458,7 @@
     <!-- Checkbox title for option to Automatically manage Wi\u2011Fi  [CHAR LIMIT=40] -->
     <string name="wifi_automatically_manage_title">Automatically manage Wi\u2011Fi</string>
     <!-- Checkbox summary for option to Automatically manage Wi\u2011Fi  [CHAR LIMIT=100] -->
-    <string name="wifi_automatically_manage_summary">Let a Wi\u2011Fi assistant manager your Wi\u2011Fi connection</string>
+    <string name="wifi_automatically_manage_summary">Let a Wi\u2011Fi assistant manage your Wi\u2011Fi connection</string>
     <!-- Checkbox title for option for Wi\u2011Fi Assistant  [CHAR LIMIT=40] -->
     <string name="wifi_assistant_setting_title">Wi\u2011Fi assistant</string>
     <!-- Checkbox summary for option for Wi\u2011Fi Assistant  [CHAR LIMIT=40] -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index cea615e..32a205d 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -221,7 +221,7 @@
         <item name="android:windowIsFloating">true</item>
     </style>
 
-    <style name="CryptKeeperBlankTheme" parent="@android:style/Theme.Material.Light.NoActionBar">
+    <style name="CryptKeeperBlankTheme" parent="@android:style/Theme.Material.NoActionBar">
         <item name="android:background">#ff000000</item>
     </style>
 
@@ -262,6 +262,16 @@
         <item name="android:textSize">18sp</item>
     </style>
 
+    <style name="WifiAssistantText">
+        <item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
+        <item name="android:textColor">@android:color/white</item>
+    </style>
+
+    <style name="WifiAssistantButton">
+        <item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
+        <item name="android:textColor">@color/setup_add_wifi_network_text_color</item>
+    </style>
+
     <!-- Scrollbar style OUTSIDE_OVERLAY -->
     <integer name="preference_scrollbar_style">33554432</integer>
 
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 92bb3b2..4d8862a 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -145,11 +145,11 @@
         <item name="dashboardBackgroundColor">@color/dashboard_background_color</item>
     </style>
 
-    <style name="Theme.CryptKeeper" parent="@android:style/Theme.Material.Light.NoActionBar">
+    <style name="Theme.CryptKeeper" parent="@android:style/Theme.Material.NoActionBar">
         <!-- LockPatternView colors -->
-        <item name="@*android:regularColor">@color/lock_pattern_view_regular_color</item>
-        <item name="@*android:successColor">@color/lock_pattern_view_success_color</item>
-        <item name="@*android:errorColor">@color/lock_pattern_view_error_color</item>
+        <item name="@*android:regularColor">@color/unlock_pattern_view_regular_color</item>
+        <item name="@*android:successColor">@color/unlock_pattern_view_success_color</item>
+        <item name="@*android:errorColor">@color/unlock_pattern_view_error_color</item>
     </style>
 
     <style name="Theme.SubSettingsDialogWhenLarge" parent="Theme.DialogWhenLarge">
diff --git a/src/com/android/settings/CryptKeeper.java b/src/com/android/settings/CryptKeeper.java
index 7f159ab..0ddeb50 100644
--- a/src/com/android/settings/CryptKeeper.java
+++ b/src/com/android/settings/CryptKeeper.java
@@ -148,22 +148,6 @@
         }
     }
 
-    /**
-     * Activity used to fade the screen to black after the password is entered.
-     */
-    public static class FadeToBlack extends Activity {
-        @Override
-        public void onCreate(Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-            setContentView(R.layout.crypt_keeper_blank);
-        }
-        /** Ignore all back events. */
-        @Override
-        public void onBackPressed() {
-            return;
-        }
-    }
-
     private class DecryptTask extends AsyncTask<String, Void, Integer> {
         @Override
         protected Integer doInBackground(String... params) {
@@ -179,13 +163,8 @@
         @Override
         protected void onPostExecute(Integer failedAttempts) {
             if (failedAttempts == 0) {
-                // The password was entered successfully. Start the Blank activity
-                // so this activity animates to black before the devices starts. Note
-                // It has 1 second to complete the animation or it will be frozen
-                // until the boot animation comes back up.
-                Intent intent = new Intent(CryptKeeper.this, FadeToBlack.class);
-                finish();
-                startActivity(intent);
+                // The password was entered successfully. Simply do nothing
+                // and wait for the service restart to switch to surfacefligner
             } else if (failedAttempts == MAX_FAILED_ATTEMPTS) {
                 // Factory reset the device.
                 sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR"));
@@ -862,14 +841,10 @@
 
         int textId;
         if (getPhoneManager().isInAPhoneCall()) {
-            // Show "return to call" text and show phone icon
+            // Show "return to call"
             textId = R.string.cryptkeeper_return_to_call;
-            final int phoneCallIcon = R.drawable.stat_sys_phone_call;
-            emergencyCall.setCompoundDrawablesWithIntrinsicBounds(phoneCallIcon, 0, 0, 0);
         } else {
             textId = R.string.cryptkeeper_emergency_call;
-            final int emergencyIcon = R.drawable.ic_emergency;
-            emergencyCall.setCompoundDrawablesWithIntrinsicBounds(emergencyIcon, 0, 0, 0);
         }
         emergencyCall.setText(textId);
     }
diff --git a/src/com/android/settings/accounts/AccountSyncSettings.java b/src/com/android/settings/accounts/AccountSyncSettings.java
index 77b1124..458adca 100644
--- a/src/com/android/settings/accounts/AccountSyncSettings.java
+++ b/src/com/android/settings/accounts/AccountSyncSettings.java
@@ -17,7 +17,6 @@
 package com.android.settings.accounts;
 
 import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
@@ -59,7 +58,6 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
-import java.util.HashMap;
 import java.util.List;
 
 public class AccountSyncSettings extends AccountPreferenceBase {
@@ -76,9 +74,6 @@
     private ImageView mProviderIcon;
     private TextView mErrorInfoView;
     private Account mAccount;
-    // List of all accounts, updated when accounts are added/removed
-    // We need to re-scan the accounts on sync events, in case sync state changes.
-    private Account[] mAccounts;
     private ArrayList<SyncStateCheckBoxPreference> mCheckBoxes =
                 new ArrayList<SyncStateCheckBoxPreference>();
     private ArrayList<SyncAdapterType> mInvisibleAdapters = Lists.newArrayList();
@@ -185,11 +180,16 @@
             return;
         }
         mAccount = (Account) arguments.getParcelable(ACCOUNT_KEY);
-        if (mAccount != null) {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "Got account: " + mAccount);
-            mUserId.setText(mAccount.name);
-            mProviderId.setText(mAccount.type);
+        if (!accountExists(mAccount)) {
+            Log.e(TAG, "Account provided does not exist: " + mAccount);
+            finish();
+            return;
         }
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+          Log.v(TAG, "Got account: " + mAccount);
+        }
+        mUserId.setText(mAccount.name);
+        mProviderId.setText(mAccount.type);
     }
 
     @Override
@@ -336,10 +336,7 @@
         // plus whatever the system needs to sync, e.g., invisible sync adapters
         if (mAccount != null) {
             for (SyncAdapterType syncAdapter : mInvisibleAdapters) {
-                // invisible sync adapters' account type should be same as current account type
-                if (syncAdapter.accountType.equals(mAccount.type)) {
-                    requestOrCancelSync(mAccount, syncAdapter.authority, startSync);
-                }
+                  requestOrCancelSync(mAccount, syncAdapter.authority, startSync);
             }
         }
     }
@@ -378,7 +375,7 @@
         boolean syncIsFailing = false;
 
         // Refresh the sync status checkboxes - some syncs may have become active.
-        updateAccountCheckboxes(mAccounts);
+        updateAccountCheckboxes();
 
         for (int i = 0, count = getPreferenceScreen().getPreferenceCount(); i < count; i++) {
             Preference pref = getPreferenceScreen().getPreference(i);
@@ -446,29 +443,42 @@
     @Override
     public void onAccountsUpdate(final UserHandle userHandle) {
         super.onAccountsUpdate(userHandle);
-        mAccounts = AccountManager.get(getActivity()).getAccountsAsUser(
-                mUserHandle.getIdentifier());
-        updateAccountCheckboxes(mAccounts);
+        if (!accountExists(mAccount)) {
+            // The account was deleted
+            finish();
+            return;
+        }
+        updateAccountCheckboxes();
         onSyncStateUpdated();
     }
 
-    private void updateAccountCheckboxes(Account[] accounts) {
+    private boolean accountExists(Account account) {
+        if (account == null) return false;
+
+        Account[] accounts = AccountManager.get(getActivity()).getAccountsByTypeAsUser(
+                account.type, mUserHandle);
+        final int count = accounts.length;
+        for (int i = 0; i < count; i++) {
+            if (accounts[i].equals(account)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void updateAccountCheckboxes() {
         mInvisibleAdapters.clear();
 
-       SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypesAsUser(
+        SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypesAsUser(
                 mUserHandle.getIdentifier());
-        HashMap<String, ArrayList<String>> accountTypeToAuthorities =
-            Maps.newHashMap();
+        ArrayList<String> authorities = new ArrayList<String>();
         for (int i = 0, n = syncAdapters.length; i < n; i++) {
             final SyncAdapterType sa = syncAdapters[i];
+            // Only keep track of sync adapters for this account
+            if (!sa.accountType.equals(mAccount.type)) continue;
             if (sa.isUserVisible()) {
-                ArrayList<String> authorities = accountTypeToAuthorities.get(sa.accountType);
-                if (authorities == null) {
-                    authorities = new ArrayList<String>();
-                    accountTypeToAuthorities.put(sa.accountType, authorities);
-                }
                 if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.d(TAG, "onAccountUpdated: added authority " + sa.authority
+                    Log.d(TAG, "updateAccountCheckboxes: added authority " + sa.authority
                             + " to accountType " + sa.accountType);
                 }
                 authorities.add(sa.authority);
@@ -484,25 +494,19 @@
         }
         mCheckBoxes.clear();
 
-        for (int i = 0, n = accounts.length; i < n; i++) {
-            final Account account = accounts[i];
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Log.d(TAG, "looking for sync adapters that match account " + mAccount);
+        }
+        for (int j = 0, m = authorities.size(); j < m; j++) {
+            final String authority = authorities.get(j);
+            // We could check services here....
+            int syncState = ContentResolver.getIsSyncableAsUser(mAccount, authority,
+                    mUserHandle.getIdentifier());
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.d(TAG, "looking for sync adapters that match account " + account);
+                Log.d(TAG, "  found authority " + authority + " " + syncState);
             }
-            final ArrayList<String> authorities = accountTypeToAuthorities.get(account.type);
-            if (authorities != null && (mAccount == null || mAccount.equals(account))) {
-                for (int j = 0, m = authorities.size(); j < m; j++) {
-                    final String authority = authorities.get(j);
-                    // We could check services here....
-                    int syncState = ContentResolver.getIsSyncableAsUser(account, authority,
-                            mUserHandle.getIdentifier());
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.d(TAG, "  found authority " + authority + " " + syncState);
-                    }
-                    if (syncState > 0) {
-                        addSyncStateCheckBox(account, authority);
-                    }
-                }
+            if (syncState > 0) {
+                addSyncStateCheckBox(mAccount, authority);
             }
         }
 
diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java
index 474a857..c0a13c1 100644
--- a/src/com/android/settings/location/LocationSettings.java
+++ b/src/com/android/settings/location/LocationSettings.java
@@ -54,17 +54,13 @@
 
     private SwitchBar mSwitchBar;
     private Switch mSwitch;
-    private boolean mValidListener;
+    private boolean mValidListener = false;
     private Preference mLocationMode;
     private PreferenceCategory mCategoryRecentLocationRequests;
     /** Receives UPDATE_INTENT  */
     private BroadcastReceiver mReceiver;
     private SettingsInjector injector;
 
-    public LocationSettings() {
-        mValidListener = false;
-    }
-
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
@@ -79,21 +75,17 @@
     @Override
     public void onDestroyView() {
         super.onDestroyView();
-
         mSwitchBar.hide();
     }
 
     @Override
-    public void onStop() {
-        super.onStop();
-    }
-
-    @Override
     public void onResume() {
         super.onResume();
         createPreferenceHierarchy();
-        mSwitchBar.addOnSwitchChangeListener(this);
-        mValidListener = true;
+        if (!mValidListener) {
+            mSwitchBar.addOnSwitchChangeListener(this);
+            mValidListener = true;
+        }
     }
 
     @Override
@@ -102,10 +94,15 @@
             getActivity().unregisterReceiver(mReceiver);
         } catch (RuntimeException e) {
             // Ignore exceptions caused by race condition
+            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                Log.v(TAG, "Swallowing " + e);
+            }
+        }
+        if (mValidListener) {
+            mSwitchBar.removeOnSwitchChangeListener(this);
+            mValidListener = false;
         }
         super.onPause();
-        mSwitchBar.removeOnSwitchChangeListener(this);
-        mValidListener = false;
     }
 
     private void addPreferencesSorted(List<Preference> prefs, PreferenceGroup container) {
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 1237715..0721248 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -25,7 +25,6 @@
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 import com.android.settings.search.SearchIndexableRaw;
-import com.android.settings.wifi.p2p.WifiP2pSettings;
 
 import android.app.Activity;
 import android.app.Dialog;
@@ -37,10 +36,12 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.content.SharedPreferences;
 import android.location.LocationManager;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkScoreManager;
 import android.net.wifi.ScanResult;
 import android.net.wifi.SupplicantState;
 import android.net.wifi.WifiConfiguration;
@@ -59,7 +60,9 @@
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.View.OnClickListener;
 import android.widget.AdapterView.AdapterContextMenuInfo;
+import android.widget.Button;
 import android.widget.TextView;
 import android.widget.Toast;
 
@@ -82,6 +85,7 @@
         implements DialogInterface.OnClickListener, Indexable  {
 
     private static final String TAG = "WifiSettings";
+
     /* package */ static final int MENU_ID_WPS_PBC = Menu.FIRST;
     private static final int MENU_ID_WPS_PIN = Menu.FIRST + 1;
     private static final int MENU_ID_SAVED_NETWORK = Menu.FIRST + 2;
@@ -93,6 +97,13 @@
     private static final int MENU_ID_MODIFY = Menu.FIRST + 8;
     private static final int MENU_ID_WRITE_NFC = Menu.FIRST + 9;
 
+    private static final String KEY_ASSISTANT_DISMISS_TIME = "wifi_assistant_dismiss_time";
+    private static final String KEY_ASSISTANT_START_TIME = "wifi_assistant_start_time";
+
+    private static final long MILI_SECONDS_30_DAYS = 30L * 24L * 60L * 60L * 1000L;
+    private static final long MILI_SECONDS_90_DAYS = MILI_SECONDS_30_DAYS * 3L;
+    private static final long MILI_SECONDS_180_DAYS = MILI_SECONDS_90_DAYS * 2L;
+
     public static final int WIFI_DIALOG_ID = 1;
     /* package */ static final int WPS_PBC_DIALOG_ID = 2;
     private static final int WPS_PIN_DIALOG_ID = 3;
@@ -142,6 +153,7 @@
     private boolean mDlgEdit;
     private AccessPoint mDlgAccessPoint;
     private Bundle mAccessPointSavedState;
+    private Preference mWifiAssistant;
 
     /** verbose logging flag. this flag is set thru developer debugging options
      * and used so as to assist with in-the-field WiFi connectivity debugging  */
@@ -149,6 +161,105 @@
 
     /* End of "used in Wifi Setup context" */
 
+    /** Holds the Wifi Assistant Card. */
+    private static class WifiAssistantPreference extends Preference {
+        final WifiSettings mWifiSettings;
+
+        public WifiAssistantPreference(WifiSettings wifiSettings) {
+            super(wifiSettings.getActivity());
+            mWifiSettings = wifiSettings;
+            setLayoutResource(R.layout.wifi_assistant_card);
+        }
+
+        @Override
+        public void onBindView(View view) {
+            super.onBindView(view);
+            final Preference pref = this;
+            Button setup = (Button)view.findViewById(R.id.setup);
+            Button noThanks = (Button)view.findViewById(R.id.no_thanks_button);
+
+            if (setup != null && noThanks != null) {
+                setup.setOnClickListener(new OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        Intent intent = new Intent(NetworkScoreManager.ACTION_CHANGE_ACTIVE);
+                        intent.putExtra(NetworkScoreManager.EXTRA_PACKAGE_NAME, "wifi-assistant");
+                        mWifiSettings.startActivity(intent);
+                        mWifiSettings.setWifiAssistantTimeout();
+                        mWifiSettings.getPreferenceScreen().removePreference(pref);
+                    }
+                });
+
+                noThanks.setOnClickListener(new OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        mWifiSettings.setWifiAssistantTimeout();
+                        mWifiSettings.getPreferenceScreen().removePreference(pref);
+                    }
+                });
+            }
+        }
+    }
+
+    /** A restricted multimap for use in constructAccessPoints */
+    private static class Multimap<K,V> {
+        private final HashMap<K,List<V>> store = new HashMap<K,List<V>>();
+        /** retrieve a non-null list of values with key K */
+        List<V> getAll(K key) {
+            List<V> values = store.get(key);
+            return values != null ? values : Collections.<V>emptyList();
+        }
+
+        void put(K key, V val) {
+            List<V> curVals = store.get(key);
+            if (curVals == null) {
+                curVals = new ArrayList<V>(3);
+                store.put(key, curVals);
+            }
+            curVals.add(val);
+        }
+    }
+
+    private static class Scanner extends Handler {
+        private int mRetry = 0;
+        private WifiSettings mWifiSettings = null;
+
+        Scanner(WifiSettings wifiSettings) {
+            mWifiSettings = wifiSettings;
+        }
+
+        void resume() {
+            if (!hasMessages(0)) {
+                sendEmptyMessage(0);
+            }
+        }
+
+        void forceScan() {
+            removeMessages(0);
+            sendEmptyMessage(0);
+        }
+
+        void pause() {
+            mRetry = 0;
+            removeMessages(0);
+        }
+
+        @Override
+        public void handleMessage(Message message) {
+            if (mWifiSettings.mWifiManager.startScan()) {
+                mRetry = 0;
+            } else if (++mRetry >= 3) {
+                mRetry = 0;
+                Activity activity = mWifiSettings.getActivity();
+                if (activity != null) {
+                    Toast.makeText(activity, R.string.wifi_fail_to_scan, Toast.LENGTH_LONG).show();
+                }
+                return;
+            }
+            sendEmptyMessageDelayed(0, WIFI_RESCAN_INTERVAL_MS);
+        }
+    }
+
     public WifiSettings() {
         super(DISALLOW_CONFIG_WIFI);
         mFilter = new IntentFilter();
@@ -168,7 +279,7 @@
             }
         };
 
-        mScanner = new Scanner();
+        mScanner = new Scanner(this);
     }
 
     @Override
@@ -248,6 +359,8 @@
 
         addPreferencesFromResource(R.xml.wifi_settings);
 
+        mWifiAssistant = new WifiAssistantPreference(this);
+
         mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
         getListView().setEmptyView(mEmptyView);
         registerForContextMenu(getListView());
@@ -322,7 +435,7 @@
                 .setIcon(ta.getDrawable(0))
                 .setEnabled(wifiIsEnabled)
                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
-        if (savedNetworksExist){
+        if (savedNetworksExist) {
             menu.add(Menu.NONE, MENU_ID_SAVED_NETWORK, 0, R.string.wifi_saved_access_points_label)
                     .setIcon(ta.getDrawable(0))
                     .setEnabled(wifiIsEnabled)
@@ -483,7 +596,7 @@
             if (mSelectedAccessPoint.security == AccessPoint.SECURITY_NONE &&
                     mSelectedAccessPoint.networkId == INVALID_NETWORK_ID) {
                 mSelectedAccessPoint.generateOpenNetworkConfig();
-                if (!savedNetworksExist){
+                if (!savedNetworksExist) {
                     savedNetworksExist = true;
                     getActivity().invalidateOptionsMenu();
                 }
@@ -566,9 +679,14 @@
                 final Collection<AccessPoint> accessPoints =
                         constructAccessPoints(getActivity(), mWifiManager, mLastInfo, mLastState);
                 getPreferenceScreen().removeAll();
-                if(accessPoints.size() == 0) {
+                if (accessPoints.size() == 0) {
                     addMessagePreference(R.string.wifi_empty_list_wifi_on);
                 }
+
+                if (showWifiAssistantCard()) {
+                    getPreferenceScreen().addPreference(mWifiAssistant);
+                }
+
                 for (AccessPoint accessPoint : accessPoints) {
                     getPreferenceScreen().addPreference(accessPoint);
                 }
@@ -588,6 +706,34 @@
         }
     }
 
+    private boolean showWifiAssistantCard() {
+        SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
+        long lastTimeoutEndTime = sharedPreferences.getLong(KEY_ASSISTANT_START_TIME, 0);
+        long dismissTime = sharedPreferences.getLong(KEY_ASSISTANT_DISMISS_TIME, 0);
+
+        return ((System.currentTimeMillis() - lastTimeoutEndTime) > dismissTime);
+    }
+
+    private void setWifiAssistantTimeout() {
+        SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
+        SharedPreferences.Editor editor = sharedPreferences.edit();
+        long dismissTime = sharedPreferences.getLong(KEY_ASSISTANT_DISMISS_TIME, 0);
+
+        if (dismissTime == 0) {
+            dismissTime = MILI_SECONDS_30_DAYS;
+        } else if (dismissTime == MILI_SECONDS_30_DAYS) {
+            dismissTime = MILI_SECONDS_90_DAYS;
+        } else if (dismissTime == MILI_SECONDS_90_DAYS) {
+            dismissTime = MILI_SECONDS_180_DAYS;
+        } else if (dismissTime == MILI_SECONDS_180_DAYS) {
+            dismissTime = java.lang.Long.MAX_VALUE;
+        }
+
+        editor.putLong(KEY_ASSISTANT_DISMISS_TIME, dismissTime);
+        editor.putLong(KEY_ASSISTANT_START_TIME, System.currentTimeMillis());
+        editor.apply();
+    }
+
     private void setOffMessage() {
         if (mEmptyView != null) {
             mEmptyView.setCompoundDrawablesWithIntrinsicBounds(0,
@@ -663,25 +809,6 @@
         return accessPoints;
     }
 
-    /** A restricted multimap for use in constructAccessPoints */
-    private static class Multimap<K,V> {
-        private final HashMap<K,List<V>> store = new HashMap<K,List<V>>();
-        /** retrieve a non-null list of values with key K */
-        List<V> getAll(K key) {
-            List<V> values = store.get(key);
-            return values != null ? values : Collections.<V>emptyList();
-        }
-
-        void put(K key, V val) {
-            List<V> curVals = store.get(key);
-            if (curVals == null) {
-                curVals = new ArrayList<V>(3);
-                store.put(key, curVals);
-            }
-            curVals.add(val);
-        }
-    }
-
     private void handleEvent(Context context, Intent intent) {
         String action = intent.getAction();
         if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
@@ -773,41 +900,6 @@
         mScanner.pause();
     }
 
-    private class Scanner extends Handler {
-        private int mRetry = 0;
-
-        void resume() {
-            if (!hasMessages(0)) {
-                sendEmptyMessage(0);
-            }
-        }
-
-        void forceScan() {
-            removeMessages(0);
-            sendEmptyMessage(0);
-        }
-
-        void pause() {
-            mRetry = 0;
-            removeMessages(0);
-        }
-
-        @Override
-        public void handleMessage(Message message) {
-            if (mWifiManager.startScan()) {
-                mRetry = 0;
-            } else if (++mRetry >= 3) {
-                mRetry = 0;
-                Activity activity = getActivity();
-                if (activity != null) {
-                    Toast.makeText(activity, R.string.wifi_fail_to_scan, Toast.LENGTH_LONG).show();
-                }
-                return;
-            }
-            sendEmptyMessageDelayed(0, WIFI_RESCAN_INTERVAL_MS);
-        }
-    }
-
     /**
      * Renames/replaces "Next" button when appropriate. "Next" button usually exists in
      * Wifi setup screens, not in usual wifi settings screen.
diff --git a/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java b/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
index 888396d..ea884e1 100644
--- a/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
+++ b/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
@@ -95,7 +95,7 @@
         final View title = view.findViewById(R.id.title);
         if (title == null) {
             final View header = inflater.inflate(R.layout.setup_wizard_header, list, false);
-            list.addHeaderView(header);
+            list.addHeaderView(header, null, false);
         }
 
         final View other = inflater.inflate(R.layout.setup_wifi_add_network, list, false);