Merge "Add on/off actionbar switch for NFC Tap To Share."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 22b2226..9712a63 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1180,12 +1180,6 @@
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
-            <intent-filter>
-                <!-- actions from NetworkPolicyManager notifications -->
-                <action android:name="android.intent.action.DATA_USAGE_WARNING" />
-                <action android:name="android.intent.action.DATA_USAGE_LIMIT" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
                 android:value="com.android.settings.DataUsageSummary" />
             <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
diff --git a/res/layout/data_usage_chart.xml b/res/layout/data_usage_chart.xml
index a942bb3..3409d64 100644
--- a/res/layout/data_usage_chart.xml
+++ b/res/layout/data_usage_chart.xml
@@ -51,20 +51,6 @@
         settings:fillColorSecondary="#0000" />
 
     <com.android.settings.widget.ChartSweepView
-        android:id="@+id/sweep_left"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        settings:sweepDrawable="@drawable/data_sweep_left"
-        settings:followAxis="horizontal" />
-
-    <com.android.settings.widget.ChartSweepView
-        android:id="@+id/sweep_right"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        settings:sweepDrawable="@drawable/data_sweep_right"
-        settings:followAxis="horizontal" />
-
-    <com.android.settings.widget.ChartSweepView
         android:id="@+id/sweep_warning"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
@@ -84,4 +70,18 @@
         settings:labelTemplate="@string/data_usage_sweep_limit"
         settings:labelColor="#c01a2c" />
 
+    <com.android.settings.widget.ChartSweepView
+        android:id="@+id/sweep_left"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        settings:sweepDrawable="@drawable/data_sweep_left"
+        settings:followAxis="horizontal" />
+
+    <com.android.settings.widget.ChartSweepView
+        android:id="@+id/sweep_right"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        settings:sweepDrawable="@drawable/data_sweep_right"
+        settings:followAxis="horizontal" />
+
 </com.android.settings.widget.DataUsageChartView>
diff --git a/res/layout/data_usage_cycles.xml b/res/layout/data_usage_cycles.xml
new file mode 100644
index 0000000..225fb4b
--- /dev/null
+++ b/res/layout/data_usage_cycles.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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/cycles"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:paddingLeft="16dip"
+    android:paddingRight="16dip">
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:text="@string/data_usage_cycle" />
+
+    <Spinner
+        android:id="@+id/cycles_spinner"
+        android:layout_width="0dip"
+        android:layout_height="wrap_content"
+        android:layout_weight="1" />
+
+</LinearLayout>
diff --git a/res/layout/data_usage_header.xml b/res/layout/data_usage_header.xml
index 547d85d..52f56c1 100644
--- a/res/layout/data_usage_header.xml
+++ b/res/layout/data_usage_header.xml
@@ -32,28 +32,19 @@
             android:divider="?android:attr/listDivider" />
     </FrameLayout>
 
-    <LinearLayout
+    <include layout="@layout/data_usage_cycles" />
+    <include layout="@layout/data_usage_chart" />
+
+    <TextView
+        android:id="@+id/usage_summary"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:orientation="horizontal"
         android:paddingLeft="16dip"
-        android:paddingRight="16dip">
+        android:paddingRight="16dip"
+        android:paddingTop="8dip"
+        android:paddingBottom="8dip"
+        android:textAppearance="?android:attr/textAppearanceSmall" />
 
-        <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center_vertical"
-            android:text="@string/data_usage_cycle" />
-
-        <Spinner
-            android:id="@+id/cycles"
-            android:layout_width="0dip"
-            android:layout_height="wrap_content"
-            android:layout_weight="1" />
-
-    </LinearLayout>
-
-    <include layout="@layout/data_usage_chart" />
     <include layout="@layout/data_usage_detail" />
 
 </LinearLayout>
diff --git a/res/layout/data_usage_item.xml b/res/layout/data_usage_item.xml
index d709753..36f8b4d 100644
--- a/res/layout/data_usage_item.xml
+++ b/res/layout/data_usage_item.xml
@@ -17,20 +17,22 @@
 <GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:padding="8dip"
+    android:paddingLeft="16dip"
+    android:paddingRight="16dip"
+    android:paddingTop="8dip"
+    android:paddingBottom="8dip"
     android:columnCount="2">
 
-    <!-- TODO: consider using canShrink -->
     <TextView
         android:id="@android:id/title"
+        android:layout_width="0dip"
+        android:layout_gravity="fill_horizontal"
         android:singleLine="true"
         android:ellipsize="marquee"
-        android:layout_columnFlexibility="canStretch"
         android:textAppearance="?android:attr/textAppearanceMedium" />
 
     <TextView
         android:id="@android:id/summary"
-        android:layout_gravity="right"
         android:layout_marginLeft="8dip"
         android:textAppearance="?android:attr/textAppearanceSmall" />
 
diff --git a/res/layout/vpn_dialog.xml b/res/layout/vpn_dialog.xml
index ffbfd4d..b4779e6 100644
--- a/res/layout/vpn_dialog.xml
+++ b/res/layout/vpn_dialog.xml
@@ -15,7 +15,7 @@
 -->
 
 <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="wrap_content"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content">
     <LinearLayout android:layout_width="match_parent"
             android:layout_height="wrap_content"
@@ -96,15 +96,27 @@
                         android:prompt="@string/vpn_ipsec_ca_cert" />
             </LinearLayout>
 
+            <CheckBox style="@style/vpn_value" android:id="@+id/show_options"
+                    android:singleLine="false"
+                    android:text="@string/vpn_show_options"/>
+        </LinearLayout>
+
+        <LinearLayout android:id="@+id/options"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical"
+                android:visibility="gone">
             <TextView style="@style/vpn_label" android:text="@string/vpn_search_domains"/>
             <EditText style="@style/vpn_value" android:id="@+id/search_domains"
                     android:hint="@string/vpn_not_used"/>
 
-            <!-- Not sure if we have time to make it. -->
-            <TextView style="@style/vpn_label" android:text="@string/vpn_routes"
-                    android:visibility="gone"/>
+            <TextView style="@style/vpn_label" android:text="@string/vpn_dns_servers"/>
+            <EditText style="@style/vpn_value" android:id="@+id/dns_servers"
+                    android:hint="@string/vpn_not_used"/>
+
+            <TextView style="@style/vpn_label" android:text="@string/vpn_routes"/>
             <EditText style="@style/vpn_value" android:id="@+id/routes"
-                    android:visibility="gone"/>
+                    android:hint="@string/vpn_not_used"/>
         </LinearLayout>
 
         <LinearLayout android:id="@+id/login"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 99a46a9..4423d60 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1544,6 +1544,8 @@
     <string name="screen_timeout_summary">Screen turns off automatically after <xliff:g id="timeout_description">%1$s</xliff:g></string>
     <!-- Wallpaper settings title [CHAR LIMIT=30] -->
     <string name="wallpaper_settings_title">Wallpaper</string>
+    <!-- Wallpaper settings fragment title [CHAR LIMIT=30] -->
+    <string name="wallpaper_settings_fragment_title">Select wallpaper from</string>
     <!-- Display settings screen, trigger for screen saver options -->
     <string name="dream_settings_title">Android Dreams</string>
     <!-- Display settings screen, summary for screen saver options -->
@@ -2741,6 +2743,8 @@
     <string name="power_usage_summary">What has been using the battery</string>
     <!-- Message to show when battery usage data is not available [CHAR LIMIT=30] -->
     <string name="power_usage_not_available">Battery usage data not available</string>
+    <!-- Display the battery level and status [CHAR_LIMIT=30] -->
+    <string name="power_usage_level_and_status">Battery level <xliff:g id="level">%1$s</xliff:g> - <xliff:g id="status">%2$s</xliff:g></string>
     <!-- Battery usage since unplugged -->
     <string name="battery_since_unplugged">Battery use since unplugged</string>
     <!-- Battery usage since user reset the stats -->
@@ -3452,17 +3456,6 @@
     <!-- Body of dialog shown before user limits 4G data usage. [CHAR LIMIT=NONE] -->
     <string name="data_usage_limit_dialog_4g">Your 4G data connection will be disabled when the specified limit is reached.\n\nTo avoid overage charges, consider using a reduced limit, as device and carrier accounting methods may vary.</string>
 
-    <!-- Title of dialog shown when 2G-3G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
-    <string name="data_usage_disabled_dialog_3g_title">2G-3G data disabled</string>
-    <!-- Title of dialog shown when 4G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
-    <string name="data_usage_disabled_dialog_4g_title">4G data disabled</string>
-    <!-- Title of dialog shown when mobile data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
-    <string name="data_usage_disabled_dialog_mobile_title">Mobile data disabled</string>
-    <!-- Body of dialog shown when data usage has exceeded limit and has been disabled. [CHAR LIMIT=NONE] -->
-    <string name="data_usage_disabled_dialog">The specified data usage limit has been reached.\n\nAdditional data use may incur carrier charges.</string>
-    <!-- Dialog button indicating that data connection should be re-enabled. [CHAR LIMIT=28] -->
-    <string name="data_usage_disabled_dialog_enable">Re-enable data</string>
-
     <!-- Title of dialog shown before user restricts background data usage. [CHAR LIMIT=48] -->
     <string name="data_usage_restrict_background_title">Restricting background data</string>
     <!-- Body of dialog shown before user restricts background data usage. [CHAR LIMIT=NONE] -->
@@ -3477,6 +3470,8 @@
     <string name="data_usage_uninstalled_apps">Removed apps</string>
     <!-- Combination of total network bytes sent and received by an application. [CHAR LIMIT=NONE] -->
     <string name="data_usage_received_sent"><xliff:g id="received" example="128KB">%1$s</xliff:g> received, <xliff:g id="sent" example="1.3GB">%2$s</xliff:g> sent</string>
+    <!-- Label displaying total network data transferred during a specific time period. [CHAR LIMIT=64] -->
+    <string name="data_usage_total_during_range">Data usage: <xliff:g id="total" example="128KB">%1$s</xliff:g> between <xliff:g id="range" example="Jul 1 - Jul 31">%2$s</xliff:g></string>
 
     <!-- Button at the bottom of the CryptKeeper screen to make an emergency call. -->
     <string name="cryptkeeper_emergency_call">Emergency call</string>
@@ -3501,18 +3496,21 @@
     <string name="vpn_ipsec_user_cert">IPSec user certificate</string>
     <!-- Selection label for the IPSec CA certificate of a VPN network. [CHAR LIMIT=40] -->
     <string name="vpn_ipsec_ca_cert">IPSec CA certificate</string>
+    <!-- Checkbox label to show advanced options of a VPN network. [CHAR LIMIT=40] -->
+    <string name="vpn_show_options">Show advanced options</string>
     <!-- Input label for the DNS search domains of a VPN network. [CHAR LIMIT=40] -->
     <string name="vpn_search_domains">DNS search domains</string>
+    <!-- Input label for the DNS servers of a VPN network. [CHAR LIMIT=40] -->
+    <string name="vpn_dns_servers">DNS servers (e.g. 8.8.8.8)</string>
     <!-- Input label for the forwarding routes of a VPN network. [CHAR LIMIT=40] -->
-    <string name="vpn_routes">Forwarding routes</string>
+    <string name="vpn_routes">Forwarding routes (e.g. 10.0.0.0/8)</string>
     <!-- Input label for the username of a VPN network. [CHAR LIMIT=40] -->
     <string name="vpn_username">Username</string>
     <!-- Input label for the password of a VPN network. [CHAR LIMIT=40] -->
     <string name="vpn_password">Password</string>
     <!-- Checkbox label to save the username and the password for a VPN network. [CHAR LIMIT=40] -->
     <string name="vpn_save_login">Save account information</string>
-
-    <!-- Hint for not filling an optional field in a VPN configuration. [CHAR LIMIT=40] -->
+    <!-- Hint for not using an optional feature of a VPN network. [CHAR LIMIT=40] -->
     <string name="vpn_not_used">(not used)</string>
     <!-- Option to not use a CA certificate to verify the VPN server. [CHAR LIMIT=40] -->
     <string name="vpn_no_ca_cert">(do not verify server)</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index ffa7912..32e0a48 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -143,15 +143,14 @@
     <style name="vpn_label">
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">wrap_content</item>
-        <item name="android:textSize">16sp</item>
+        <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
     </style>
 
     <style name="vpn_value">
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">wrap_content</item>
-        <item name="android:textSize">18sp</item>
+        <item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
         <item name="android:singleLine">true</item>
-        <item name="android:paddingBottom">1mm</item>
     </style>
 
     <style name="InputMethodPreferenceStyle">
diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml
index b49b140..5fcae5c 100644
--- a/res/xml/power_usage_summary.xml
+++ b/res/xml/power_usage_summary.xml
@@ -17,4 +17,9 @@
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
         android:title="@string/battery_since_unplugged"
         android:key="app_list">
+    <Preference
+        style="?android:attr/preferenceInformationStyle"
+        android:key="battery_status"
+        android:persistent="false"
+    />
 </PreferenceScreen>
diff --git a/res/xml/wallpaper_settings.xml b/res/xml/wallpaper_settings.xml
index 63346f7..bb9e809 100644
--- a/res/xml/wallpaper_settings.xml
+++ b/res/xml/wallpaper_settings.xml
@@ -15,6 +15,6 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-        android:title="@string/wallpaper_settings_title">
+        android:title="@string/wallpaper_settings_fragment_title">
 
 </PreferenceScreen>
diff --git a/src/com/android/settings/AccessibilityTutorialActivity.java b/src/com/android/settings/AccessibilityTutorialActivity.java
index 21d0028..9ea9917 100644
--- a/src/com/android/settings/AccessibilityTutorialActivity.java
+++ b/src/com/android/settings/AccessibilityTutorialActivity.java
@@ -17,6 +17,7 @@
 package com.android.settings;
 
 import android.app.Activity;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -25,6 +26,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
+import android.provider.Settings;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -52,9 +54,6 @@
  * available in Touch Exploration.
  */
 public class AccessibilityTutorialActivity extends Activity {
-    /** Intent action for launching this activity. */
-    public static final String ACTION = "com.android.settings.touchtutorial.LAUNCH_TUTORIAL";
-
     /** Instance state saving constant for the active module. */
     private static final String KEY_ACTIVE_MODULE = "active_module";
 
@@ -66,6 +65,9 @@
 
     private AccessibilityManager mAccessibilityManager;
 
+    /** Should touch exploration be disabled when this activity is paused? */
+    private boolean mDisableOnPause;
+
     private final AnimationListener mInAnimationListener = new AnimationListener() {
         @Override
         public void onAnimationEnd(Animation animation) {
@@ -115,6 +117,30 @@
     }
 
     @Override
+    protected void onResume() {
+        super.onResume();
+
+        final ContentResolver cr = getContentResolver();
+
+        if (Settings.Secure.getInt(cr, Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0) == 0) {
+            Settings.Secure.putInt(cr, Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1);
+            mDisableOnPause = true;
+        } else {
+            mDisableOnPause = false;
+        }
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+
+        if (mDisableOnPause) {
+            final ContentResolver cr = getContentResolver();
+            Settings.Secure.putInt(cr, Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0);
+        }
+    }
+
+    @Override
     protected void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
 
diff --git a/src/com/android/settings/BatteryInfo.java b/src/com/android/settings/BatteryInfo.java
index 3e037cf..d8046cf 100644
--- a/src/com/android/settings/BatteryInfo.java
+++ b/src/com/android/settings/BatteryInfo.java
@@ -90,26 +90,7 @@
                         + getString(R.string.battery_info_temperature_units));
                 mTechnology.setText("" + intent.getStringExtra("technology"));
                 
-                int status = intent.getIntExtra("status", BatteryManager.BATTERY_STATUS_UNKNOWN);
-                String statusString;
-                if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
-                    statusString = getString(R.string.battery_info_status_charging);
-                    if (plugType > 0) {
-                        statusString = statusString + " " + getString(
-                                (plugType == BatteryManager.BATTERY_PLUGGED_AC)
-                                        ? R.string.battery_info_status_charging_ac
-                                        : R.string.battery_info_status_charging_usb);
-                    }
-                } else if (status == BatteryManager.BATTERY_STATUS_DISCHARGING) {
-                    statusString = getString(R.string.battery_info_status_discharging);
-                } else if (status == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
-                    statusString = getString(R.string.battery_info_status_not_charging);
-                } else if (status == BatteryManager.BATTERY_STATUS_FULL) {
-                    statusString = getString(R.string.battery_info_status_full);
-                } else {
-                    statusString = getString(R.string.battery_info_status_unknown);
-                }
-                mStatus.setText(statusString);
+                mStatus.setText(Utils.getBatteryStatus(getResources(), intent));
 
                 switch (plugType) {
                     case 0:
diff --git a/src/com/android/settings/DataUsageSummary.java b/src/com/android/settings/DataUsageSummary.java
index 1f433fb..d87080f 100644
--- a/src/com/android/settings/DataUsageSummary.java
+++ b/src/com/android/settings/DataUsageSummary.java
@@ -20,7 +20,6 @@
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_WIMAX;
 import static android.net.NetworkPolicy.LIMIT_DISABLED;
-import static android.net.NetworkPolicyManager.ACTION_DATA_USAGE_LIMIT;
 import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
 import static android.net.NetworkPolicyManager.POLICY_NONE;
 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
@@ -129,6 +128,7 @@
     private static final boolean LOGD = true;
 
     // TODO: remove this testing code
+    private static final boolean TEST_ANIM = false;
     private static final boolean TEST_RADIOS = false;
     private static final String TEST_RADIOS_PROP = "test.radios";
 
@@ -141,7 +141,6 @@
     private static final String TAG_CONFIRM_ROAMING = "confirmRoaming";
     private static final String TAG_CONFIRM_LIMIT = "confirmLimit";
     private static final String TAG_CYCLE_EDITOR = "cycleEditor";
-    private static final String TAG_POLICY_LIMIT = "policyLimit";
     private static final String TAG_CONFIRM_RESTRICT = "confirmRestrict";
     private static final String TAG_CONFIRM_APP_RESTRICT = "confirmAppRestrict";
     private static final String TAG_APP_DETAILS = "appDetails";
@@ -177,10 +176,12 @@
     private CheckBox mDisableAtLimit;
     private View mDisableAtLimitView;
 
+    private View mCycleView;
     private Spinner mCycleSpinner;
     private CycleAdapter mCycleAdapter;
 
     private DataUsageChartView mChart;
+    private TextView mUsageSummary;
 
     private View mAppDetail;
     private TextView mAppTitle;
@@ -274,7 +275,8 @@
         }
 
         // bind cycle dropdown
-        mCycleSpinner = (Spinner) mHeader.findViewById(R.id.cycles);
+        mCycleView = mHeader.findViewById(R.id.cycles);
+        mCycleSpinner = (Spinner) mCycleView.findViewById(R.id.cycles_spinner);
         mCycleAdapter = new CycleAdapter(context);
         mCycleSpinner.setAdapter(mCycleAdapter);
         mCycleSpinner.setOnItemSelectedListener(mCycleListener);
@@ -284,12 +286,12 @@
 
         {
             // bind app detail controls
-            mAppDetail = view.findViewById(R.id.app_detail);
-            mAppTitle = (TextView) view.findViewById(R.id.app_title);
-            mAppSubtitle = (TextView) view.findViewById(R.id.app_subtitle);
-            mAppSwitches = (LinearLayout) view.findViewById(R.id.app_switches);
+            mAppDetail = mHeader.findViewById(R.id.app_detail);
+            mAppTitle = (TextView) mAppDetail.findViewById(R.id.app_title);
+            mAppSubtitle = (TextView) mAppDetail.findViewById(R.id.app_subtitle);
+            mAppSwitches = (LinearLayout) mAppDetail.findViewById(R.id.app_switches);
 
-            mAppSettings = (Button) view.findViewById(R.id.app_settings);
+            mAppSettings = (Button) mAppDetail.findViewById(R.id.app_settings);
             mAppSettings.setOnClickListener(mAppSettingsListener);
 
             mAppRestrict = new CheckBox(inflater.getContext());
@@ -302,8 +304,10 @@
             mAppSwitches.addView(mAppRestrictView);
         }
 
+        mUsageSummary = (TextView) mHeader.findViewById(R.id.usage_summary);
+
         // only assign layout transitions once first layout is finished
-        mHeader.getViewTreeObserver().addOnGlobalLayoutListener(mFirstLayoutListener);
+        mListView.getViewTreeObserver().addOnGlobalLayoutListener(mFirstLayoutListener);
 
         mAdapter = new DataUsageAdapter();
         mListView.setOnItemClickListener(mListListener);
@@ -324,12 +328,6 @@
         // selected network, and binds chart, cycles and detail list.
         updateTabs();
 
-        // template and tab has been selected; show dialog if limit passed
-        final String action = intent.getAction();
-        if (ACTION_DATA_USAGE_LIMIT.equals(action)) {
-            PolicyLimitFragment.show(this);
-        }
-
         // kick off background task to update stats
         new AsyncTask<Void, Void, Void>() {
             @Override
@@ -451,19 +449,28 @@
     private OnGlobalLayoutListener mFirstLayoutListener = new OnGlobalLayoutListener() {
         /** {@inheritDoc} */
         public void onGlobalLayout() {
-            mHeader.getViewTreeObserver().removeGlobalOnLayoutListener(mFirstLayoutListener);
+            mListView.getViewTreeObserver().removeGlobalOnLayoutListener(mFirstLayoutListener);
 
-            mTabsContainer.setLayoutTransition(new LayoutTransition());
-            mHeader.setLayoutTransition(new LayoutTransition());
-            mNetworkSwitchesContainer.setLayoutTransition(new LayoutTransition());
+            mTabsContainer.setLayoutTransition(buildLayoutTransition());
+            mHeader.setLayoutTransition(buildLayoutTransition());
+            mNetworkSwitchesContainer.setLayoutTransition(buildLayoutTransition());
 
-            final LayoutTransition chartTransition = new LayoutTransition();
+            final LayoutTransition chartTransition = buildLayoutTransition();
             chartTransition.setStartDelay(LayoutTransition.APPEARING, 0);
             chartTransition.setStartDelay(LayoutTransition.DISAPPEARING, 0);
             mChart.setLayoutTransition(chartTransition);
         }
     };
 
+    private static LayoutTransition buildLayoutTransition() {
+        final LayoutTransition transition = new LayoutTransition();
+        if (TEST_ANIM) {
+            transition.setDuration(1500);
+        }
+        transition.setAnimateParentHierarchy(false);
+        return transition;
+    }
+
     /**
      * Rebuild all tabs based on {@link NetworkPolicyEditor} and
      * {@link #mShowWifi}, hiding the tabs entirely when applicable. Selects
@@ -676,7 +683,7 @@
         updateDetailData();
 
         final Context context = getActivity();
-        if (NetworkPolicyManager.isUidValidForPolicy(context, mUid)) {
+        if (NetworkPolicyManager.isUidValidForPolicy(context, mUid) && !getRestrictBackground()) {
             mAppRestrictView.setVisibility(View.VISIBLE);
             mAppRestrict.setChecked(getAppRestrictBackground());
 
@@ -718,13 +725,22 @@
     }
 
     private boolean getRestrictBackground() {
-        return !mConnService.getBackgroundDataSetting();
+        try {
+            return mPolicyService.getRestrictBackground();
+        } catch (RemoteException e) {
+            Log.w(TAG, "problem talking with policy service: " + e);
+            return false;
+        }
     }
 
     private void setRestrictBackground(boolean restrictBackground) {
         if (LOGD) Log.d(TAG, "setRestrictBackground()");
-        mConnService.setBackgroundDataSetting(!restrictBackground);
-        mMenuRestrictBackground.setChecked(restrictBackground);
+        try {
+            mPolicyService.setRestrictBackground(restrictBackground);
+            mMenuRestrictBackground.setChecked(restrictBackground);
+        } catch (RemoteException e) {
+            Log.w(TAG, "problem talking with policy service: " + e);
+        }
     }
 
     private boolean getAppRestrictBackground() {
@@ -740,7 +756,7 @@
     }
 
     private void setAppRestrictBackground(boolean restrictBackground) {
-        if (LOGD) Log.d(TAG, "setRestrictBackground()");
+        if (LOGD) Log.d(TAG, "setAppRestrictBackground()");
         try {
             mPolicyService.setUidPolicy(
                     mUid, restrictBackground ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE);
@@ -917,7 +933,7 @@
 
                 // update chart to show selected cycle, and update detail data
                 // to match updated sweep bounds.
-                mChart.setVisibleRange(cycle.start, cycle.end, mHistory.getEnd());
+                mChart.setVisibleRange(cycle.start, cycle.end);
 
                 updateDetailData();
             }
@@ -940,28 +956,40 @@
 
         final long start = mChart.getInspectStart();
         final long end = mChart.getInspectEnd();
+        final long now = System.currentTimeMillis();
+
+        final Context context = getActivity();
+        final NetworkStatsHistory.Entry entry;
 
         if (isAppDetailMode()) {
             if (mDetailHistory != null) {
-                final Context context = mChart.getContext();
-                final long now = System.currentTimeMillis();
-                final NetworkStatsHistory.Entry entry = mDetailHistory.getValues(
-                        start, end, now, null);
+                entry = mDetailHistory.getValues(start, end, now, null);
 
                 mAppSubtitle.setText(
                         getString(R.string.data_usage_received_sent,
                                 Formatter.formatFileSize(context, entry.rxBytes),
                                 Formatter.formatFileSize(context, entry.txBytes)));
+            } else {
+                entry = null;
             }
 
             getLoaderManager().destroyLoader(LOADER_SUMMARY);
 
         } else {
+            entry = mHistory.getValues(start, end, now, null);
+
             // kick off loader for detailed stats
             getLoaderManager().restartLoader(LOADER_SUMMARY,
                     SummaryForAllUidLoader.buildArgs(mTemplate, start, end), mSummaryForAllUid);
 
         }
+
+        final long totalBytes = entry != null ? entry.rxBytes + entry.txBytes : 0;
+        final String totalPhrase = Formatter.formatFileSize(context, totalBytes);
+        final String rangePhrase = formatDateRangeUtc(context, start, end);
+
+        mUsageSummary.setText(
+                getString(R.string.data_usage_total_during_range, totalPhrase, rangePhrase));
     }
 
     private final LoaderCallbacks<NetworkStats> mSummaryForAllUid = new LoaderCallbacks<
@@ -1030,10 +1058,6 @@
         public long start;
         public long end;
 
-        private static final StringBuilder sBuilder = new StringBuilder(50);
-        private static final java.util.Formatter sFormatter = new java.util.Formatter(
-                sBuilder, Locale.getDefault());
-
         CycleItem(CharSequence label) {
             this.label = label;
         }
@@ -1044,21 +1068,30 @@
             this.end = end;
         }
 
-        private static String formatDateRangeUtc(Context context, long start, long end) {
-            synchronized (sBuilder) {
-                sBuilder.setLength(0);
-                return DateUtils.formatDateRange(context, sFormatter, start, end,
-                        DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH,
-                        Time.TIMEZONE_UTC).toString();
-            }
-        }
-
         @Override
         public String toString() {
             return label.toString();
         }
     }
 
+    private static final StringBuilder sBuilder = new StringBuilder(50);
+    private static final java.util.Formatter sFormatter = new java.util.Formatter(
+            sBuilder, Locale.getDefault());
+
+    private static String formatDateRangeUtc(Context context, long start, long end) {
+        synchronized (sBuilder) {
+            int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH;
+            if (Time.getJulianDay(start, 0) == Time.getJulianDay(end, 0)) {
+                // when times are on same day, include time detail
+                flags |= DateUtils.FORMAT_SHOW_TIME;
+            }
+
+            sBuilder.setLength(0);
+            return DateUtils.formatDateRange(
+                    context, sFormatter, start, end, flags, Time.TIMEZONE_UTC).toString();
+        }
+    }
+
     /**
      * Special-case data usage cycle that triggers dialog to change
      * {@link NetworkPolicy#cycleDay}.
@@ -1338,58 +1371,6 @@
     }
 
     /**
-     * Dialog explaining that {@link NetworkPolicy#limitBytes} has been passed,
-     * and giving the user an option to bypass.
-     */
-    public static class PolicyLimitFragment extends DialogFragment {
-        private static final String EXTRA_TITLE_ID = "titleId";
-
-        public static void show(DataUsageSummary parent) {
-            final Bundle args = new Bundle();
-
-            final String currentTab = parent.mCurrentTab;
-            if (TAB_3G.equals(currentTab)) {
-                args.putInt(EXTRA_TITLE_ID, R.string.data_usage_disabled_dialog_3g_title);
-            } else if (TAB_4G.equals(currentTab)) {
-                args.putInt(EXTRA_TITLE_ID, R.string.data_usage_disabled_dialog_4g_title);
-            } else if (TAB_MOBILE.equals(currentTab)) {
-                args.putInt(EXTRA_TITLE_ID, R.string.data_usage_disabled_dialog_mobile_title);
-            }
-
-            final PolicyLimitFragment dialog = new PolicyLimitFragment();
-            dialog.setArguments(args);
-            dialog.setTargetFragment(parent, 0);
-            dialog.show(parent.getFragmentManager(), TAG_POLICY_LIMIT);
-        }
-
-        @Override
-        public Dialog onCreateDialog(Bundle savedInstanceState) {
-            final Context context = getActivity();
-
-            final int titleId = getArguments().getInt(EXTRA_TITLE_ID);
-
-            final AlertDialog.Builder builder = new AlertDialog.Builder(context);
-            builder.setTitle(titleId);
-            builder.setMessage(R.string.data_usage_disabled_dialog);
-
-            builder.setPositiveButton(android.R.string.ok, null);
-            builder.setNegativeButton(R.string.data_usage_disabled_dialog_enable,
-                    new DialogInterface.OnClickListener() {
-                        public void onClick(DialogInterface dialog, int which) {
-                            final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
-                            if (target != null) {
-                                // TODO: consider "allow 100mb more data", or
-                                // only bypass limit for current cycle.
-                                target.setPolicyLimitBytes(LIMIT_DISABLED);
-                            }
-                        }
-                    });
-
-            return builder.create();
-        }
-    }
-
-    /**
      * Dialog to request user confirmation before setting
      * {@link Settings.Secure#DATA_ROAMING}.
      */
@@ -1426,7 +1407,7 @@
 
     /**
      * Dialog to request user confirmation before setting
-     * {@link ConnectivityManager#setBackgroundDataSetting(boolean)}.
+     * {@link INetworkPolicyManager#setRestrictBackground(boolean)}.
      */
     public static class ConfirmRestrictFragment extends DialogFragment {
         public static void show(DataUsageSummary parent) {
@@ -1497,8 +1478,10 @@
      * {@link NetworkPolicyManager#EXTRA_NETWORK_TEMPLATE} extra.
      */
     private static String computeTabFromIntent(Intent intent) {
-        final int networkTemplate = intent.getIntExtra(EXTRA_NETWORK_TEMPLATE, MATCH_MOBILE_ALL);
-        switch (networkTemplate) {
+        final NetworkTemplate template = intent.getParcelableExtra(EXTRA_NETWORK_TEMPLATE);
+        if (template == null) return null;
+
+        switch (template.getMatchRule()) {
             case MATCH_MOBILE_3G_LOWER:
                 return TAB_3G;
             case MATCH_MOBILE_4G:
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index c630ee2..ae7e24e 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -28,7 +28,9 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Bundle;
+import android.preference.Preference;
 import android.preference.PreferenceActivity;
+import android.preference.PreferenceFragment;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -535,6 +537,17 @@
     }
 
     @Override
+    public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
+        // Override the fragment title for Wallpaper settings
+        CharSequence title = pref.getTitle();
+        if (pref.getFragment().equals(WallpaperTypeSettings.class.getName())) {
+            title = getString(R.string.wallpaper_settings_fragment_title);
+        }
+        startPreferencePanel(pref.getFragment(), pref.getExtras(), 0, title, null, 0);
+        return true;
+    }
+
+    @Override
     public void setListAdapter(ListAdapter adapter) {
         if (mHeaders == null) {
             mHeaders = new ArrayList<Header>();
diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java
index 9991725..f5bee3a 100644
--- a/src/com/android/settings/TetherSettings.java
+++ b/src/com/android/settings/TetherSettings.java
@@ -516,16 +516,13 @@
             mWifiConfig = mDialog.getConfig();
             if (mWifiConfig != null) {
                 /**
-                 * if soft AP is running, bring up with new config
-                 * else update the configuration alone
+                 * if soft AP is stopped, bring up
+                 * else restart with new config
+                 * TODO: update config on a running access point when framework support is added
                  */
                 if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) {
+                    mWifiManager.setWifiApEnabled(null, false);
                     mWifiManager.setWifiApEnabled(mWifiConfig, true);
-                    /**
-                     * There is no tether notification on changing AP
-                     * configuration. Update status with new config.
-                     */
-                    mWifiApEnabler.updateConfigSummary(mWifiConfig);
                 } else {
                     mWifiManager.setWifiApConfiguration(mWifiConfig);
                 }
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 422ae90..b725d56 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -27,6 +27,7 @@
 import android.graphics.drawable.Drawable;
 import android.net.ConnectivityManager;
 import android.net.LinkProperties;
+import android.os.BatteryManager;
 import android.os.Bundle;
 import android.os.SystemProperties;
 import android.preference.Preference;
@@ -330,4 +331,38 @@
             return new Locale(brokenDownLocale[0], brokenDownLocale[1], brokenDownLocale[2]);
         }
     }
+
+    public static String getBatteryPercentage(Intent batteryChangedIntent) {
+        int level = batteryChangedIntent.getIntExtra("level", 0);
+        int scale = batteryChangedIntent.getIntExtra("scale", 100);
+        return String.valueOf(level * 100 / scale) + "%";
+    }
+
+    public static String getBatteryStatus(Resources res, Intent batteryChangedIntent) {
+        final Intent intent = batteryChangedIntent;
+
+        int plugType = intent.getIntExtra("plugged", 0);
+        int status = intent.getIntExtra("status", BatteryManager.BATTERY_STATUS_UNKNOWN);
+        String statusString;
+        if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
+            statusString = res.getString(R.string.battery_info_status_charging);
+            if (plugType > 0) {
+                statusString = statusString
+                        + " "
+                        + res.getString((plugType == BatteryManager.BATTERY_PLUGGED_AC)
+                                ? R.string.battery_info_status_charging_ac
+                                : R.string.battery_info_status_charging_usb);
+            }
+        } else if (status == BatteryManager.BATTERY_STATUS_DISCHARGING) {
+            statusString = res.getString(R.string.battery_info_status_discharging);
+        } else if (status == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
+            statusString = res.getString(R.string.battery_info_status_not_charging);
+        } else if (status == BatteryManager.BATTERY_STATUS_FULL) {
+            statusString = res.getString(R.string.battery_info_status_full);
+        } else {
+            statusString = res.getString(R.string.battery_info_status_unknown);
+        }
+
+        return statusString;
+    }
 }
diff --git a/src/com/android/settings/WallpaperTypeSettings.java b/src/com/android/settings/WallpaperTypeSettings.java
index fa0b4e4..fa5f0ac 100644
--- a/src/com/android/settings/WallpaperTypeSettings.java
+++ b/src/com/android/settings/WallpaperTypeSettings.java
@@ -16,13 +16,14 @@
 
 package com.android.settings;
 
+import android.app.Activity;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.preference.Preference;
+import android.preference.PreferenceScreen;
 
 import java.util.List;
 
@@ -32,7 +33,6 @@
         super.onCreate(savedInstanceState);
 
         addPreferencesFromResource(R.xml.wallpaper_settings);
-
         populateWallpaperTypes();
     }
 
@@ -43,6 +43,8 @@
         List<ResolveInfo> rList = pm.queryIntentActivities(intent,
                 PackageManager.MATCH_DEFAULT_ONLY);
 
+        final PreferenceScreen parent = getPreferenceScreen();
+        parent.setOrderingAsAdded(false);
         // Add Preference items for each of the matching activities
         for (ResolveInfo info : rList) {
             Preference pref = new Preference(getActivity());
@@ -53,7 +55,7 @@
             CharSequence label = info.loadLabel(pm);
             if (label == null) label = info.activityInfo.packageName;
             pref.setTitle(label);
-            getPreferenceScreen().addPreference(pref);
+            parent.addPreference(pref);
         }
     }
 }
diff --git a/src/com/android/settings/deviceinfo/Status.java b/src/com/android/settings/deviceinfo/Status.java
index 456bc98..987fab8 100644
--- a/src/com/android/settings/deviceinfo/Status.java
+++ b/src/com/android/settings/deviceinfo/Status.java
@@ -157,33 +157,8 @@
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
             if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
-
-                int level = intent.getIntExtra("level", 0);
-                int scale = intent.getIntExtra("scale", 100);
-
-                mBatteryLevel.setSummary(String.valueOf(level * 100 / scale) + "%");
-
-                int plugType = intent.getIntExtra("plugged", 0);
-                int status = intent.getIntExtra("status", BatteryManager.BATTERY_STATUS_UNKNOWN);
-                String statusString;
-                if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
-                    statusString = getString(R.string.battery_info_status_charging);
-                    if (plugType > 0) {
-                        statusString = statusString + " " + getString(
-                                (plugType == BatteryManager.BATTERY_PLUGGED_AC)
-                                        ? R.string.battery_info_status_charging_ac
-                                        : R.string.battery_info_status_charging_usb);
-                    }
-                } else if (status == BatteryManager.BATTERY_STATUS_DISCHARGING) {
-                    statusString = getString(R.string.battery_info_status_discharging);
-                } else if (status == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
-                    statusString = getString(R.string.battery_info_status_not_charging);
-                } else if (status == BatteryManager.BATTERY_STATUS_FULL) {
-                    statusString = getString(R.string.battery_info_status_full);
-                } else {
-                    statusString = getString(R.string.battery_info_status_unknown);
-                }
-                mBatteryStatus.setSummary(statusString);
+                mBatteryLevel.setSummary(Utils.getBatteryPercentage(intent));
+                mBatteryStatus.setSummary(Utils.getBatteryStatus(getResources(), intent));
             }
         }
     };
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index d46853d..f28ba93 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -16,10 +16,14 @@
 
 package com.android.settings.fuelgauge;
 
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.hardware.SensorManager;
 import android.os.BatteryStats;
 import android.os.BatteryStats.Uid;
+import android.os.BatteryManager;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
@@ -64,6 +68,9 @@
 
     private static final String TAG = "PowerUsageSummary";
 
+    private static final String KEY_APP_LIST = "app_list";
+    private static final String KEY_BATTERY_STATUS = "battery_status";
+
     private static final int MENU_STATS_TYPE = Menu.FIRST;
     private static final int MENU_STATS_REFRESH = Menu.FIRST + 1;
 
@@ -76,6 +83,7 @@
     private final List<BatterySipper> mBluetoothSippers = new ArrayList<BatterySipper>();
 
     private PreferenceGroup mAppListGroup;
+    private Preference mBatteryStatusPref;
 
     private int mStatsType = BatteryStats.STATS_SINCE_CHARGED;
 
@@ -96,7 +104,23 @@
     private ArrayList<BatterySipper> mRequestQueue = new ArrayList<BatterySipper>();
     private Thread mRequestThread;
     private boolean mAbort;
-    
+
+    private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
+                String batteryLevel = com.android.settings.Utils.getBatteryPercentage(intent);
+                String batteryStatus = com.android.settings.Utils.getBatteryStatus(getResources(),
+                        intent);
+                String batterySummary = context.getResources().getString(
+                        R.string.power_usage_level_and_status, batteryLevel, batteryStatus);
+                mBatteryStatusPref.setTitle(batterySummary);
+            }
+        }
+    };
+
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
@@ -108,7 +132,8 @@
         addPreferencesFromResource(R.xml.power_usage_summary);
         mBatteryInfo = IBatteryStats.Stub.asInterface(
                 ServiceManager.getService("batteryinfo"));
-        mAppListGroup = (PreferenceGroup) findPreference("app_list");
+        mAppListGroup = (PreferenceGroup) findPreference(KEY_APP_LIST);
+        mBatteryStatusPref = mAppListGroup.findPreference(KEY_BATTERY_STATUS);
         mPowerProfile = new PowerProfile(getActivity());
         setHasOptionsMenu(true);
     }
@@ -117,6 +142,8 @@
     public void onResume() {
         super.onResume();
         mAbort = false;
+        getActivity().registerReceiver(mBatteryInfoReceiver,
+                new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
         refreshStats();
     }
 
@@ -126,6 +153,7 @@
             mAbort = true;
         }
         mHandler.removeMessages(MSG_UPDATE_NAME_ICON);
+        getActivity().unregisterReceiver(mBatteryInfoReceiver);
         super.onPause();
     }
 
@@ -335,6 +363,8 @@
         mBluetoothSippers.clear();
         mAppListGroup.setOrderingAsAdded(false);
 
+        mBatteryStatusPref.setOrder(-2);
+        mAppListGroup.addPreference(mBatteryStatusPref);
         BatteryHistoryPreference hist = new BatteryHistoryPreference(getActivity(), mStats);
         hist.setOrder(-1);
         mAppListGroup.addPreference(hist);
diff --git a/src/com/android/settings/net/NetworkPolicyEditor.java b/src/com/android/settings/net/NetworkPolicyEditor.java
index 1e64ec2..81cf78e 100644
--- a/src/com/android/settings/net/NetworkPolicyEditor.java
+++ b/src/com/android/settings/net/NetworkPolicyEditor.java
@@ -17,6 +17,7 @@
 package com.android.settings.net;
 
 import static android.net.NetworkPolicy.LIMIT_DISABLED;
+import static android.net.NetworkPolicy.SNOOZE_NEVER;
 import static android.net.NetworkPolicy.WARNING_DISABLED;
 import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
 import static android.net.NetworkTemplate.MATCH_MOBILE_4G;
@@ -100,17 +101,23 @@
     }
 
     public void setPolicyCycleDay(NetworkTemplate template, int cycleDay) {
-        getPolicy(template).cycleDay = cycleDay;
+        final NetworkPolicy policy = getPolicy(template);
+        policy.cycleDay = cycleDay;
+        policy.lastSnooze = SNOOZE_NEVER;
         writeAsync();
     }
 
     public void setPolicyWarningBytes(NetworkTemplate template, long warningBytes) {
-        getPolicy(template).warningBytes = warningBytes;
+        final NetworkPolicy policy = getPolicy(template);
+        policy.warningBytes = warningBytes;
+        policy.lastSnooze = SNOOZE_NEVER;
         writeAsync();
     }
 
     public void setPolicyLimitBytes(NetworkTemplate template, long limitBytes) {
-        getPolicy(template).limitBytes = limitBytes;
+        final NetworkPolicy policy = getPolicy(template);
+        policy.limitBytes = limitBytes;
+        policy.lastSnooze = SNOOZE_NEVER;
         writeAsync();
     }
 
@@ -155,17 +162,19 @@
             mPolicies.remove(policy4g);
             mPolicies.add(
                     new NetworkPolicy(templateAll, restrictive.cycleDay, restrictive.warningBytes,
-                            restrictive.limitBytes));
+                            restrictive.limitBytes, SNOOZE_NEVER));
             writeAsync();
 
         } else if (!beforeSplit && split) {
             // duplicate existing policy into two rules
             final NetworkPolicy policyAll = getPolicy(templateAll);
             mPolicies.remove(policyAll);
-            mPolicies.add(new NetworkPolicy(
-                    template3g, policyAll.cycleDay, policyAll.warningBytes, policyAll.limitBytes));
-            mPolicies.add(new NetworkPolicy(
-                    template4g, policyAll.cycleDay, policyAll.warningBytes, policyAll.limitBytes));
+            mPolicies.add(
+                    new NetworkPolicy(template3g, policyAll.cycleDay, policyAll.warningBytes,
+                            policyAll.limitBytes, SNOOZE_NEVER));
+            mPolicies.add(
+                    new NetworkPolicy(template4g, policyAll.cycleDay, policyAll.warningBytes,
+                            policyAll.limitBytes, SNOOZE_NEVER));
             writeAsync();
 
         }
diff --git a/src/com/android/settings/vpn2/VpnDialog.java b/src/com/android/settings/vpn2/VpnDialog.java
index d644700..c1a4531 100644
--- a/src/com/android/settings/vpn2/VpnDialog.java
+++ b/src/com/android/settings/vpn2/VpnDialog.java
@@ -27,15 +27,18 @@
 import android.text.Editable;
 import android.text.TextWatcher;
 import android.view.View;
+import android.view.WindowManager;
 import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemSelectedListener;
 import android.widget.ArrayAdapter;
 import android.widget.Button;
 import android.widget.CheckBox;
 import android.widget.Spinner;
 import android.widget.TextView;
 
-class VpnDialog extends AlertDialog implements TextWatcher, OnItemSelectedListener {
+import java.net.InetAddress;
+
+class VpnDialog extends AlertDialog implements TextWatcher,
+        View.OnClickListener, AdapterView.OnItemSelectedListener {
     private final KeyStore mKeyStore = KeyStore.getInstance();
     private final DialogInterface.OnClickListener mListener;
     private final VpnProfile mProfile;
@@ -50,6 +53,7 @@
     private TextView mUsername;
     private TextView mPassword;
     private TextView mSearchDomains;
+    private TextView mDnsServers;
     private TextView mRoutes;
     private CheckBox mMppe;
     private TextView mL2tpSecret;
@@ -82,6 +86,7 @@
         mUsername = (TextView) mView.findViewById(R.id.username);
         mPassword = (TextView) mView.findViewById(R.id.password);
         mSearchDomains = (TextView) mView.findViewById(R.id.search_domains);
+        mDnsServers = (TextView) mView.findViewById(R.id.dns_servers);
         mRoutes = (TextView) mView.findViewById(R.id.routes);
         mMppe = (CheckBox) mView.findViewById(R.id.mppe);
         mL2tpSecret = (TextView) mView.findViewById(R.id.l2tp_secret);
@@ -98,6 +103,7 @@
         mUsername.setText(mProfile.username);
         mPassword.setText(mProfile.password);
         mSearchDomains.setText(mProfile.searchDomains);
+        mDnsServers.setText(mProfile.dnsServers);
         mRoutes.setText(mProfile.routes);
         mMppe.setChecked(mProfile.mppe);
         mL2tpSecret.setText(mProfile.l2tpSecret);
@@ -115,6 +121,8 @@
         mServer.addTextChangedListener(this);
         mUsername.addTextChangedListener(this);
         mPassword.addTextChangedListener(this);
+        mDnsServers.addTextChangedListener(this);
+        mRoutes.addTextChangedListener(this);
         mIpsecSecret.addTextChangedListener(this);
         mIpsecUserCert.setOnItemSelectedListener(this);
 
@@ -131,6 +139,15 @@
             // Show type-specific fields.
             changeType(mProfile.type);
 
+            // Show advanced options directly if any of them is set.
+            View showOptions = mView.findViewById(R.id.show_options);
+            if (mProfile.searchDomains.isEmpty() && mProfile.dnsServers.isEmpty() &&
+                    mProfile.routes.isEmpty()) {
+                showOptions.setOnClickListener(this);
+            } else {
+                onClick(showOptions);
+            }
+
             // Create a button to save the profile.
             setButton(DialogInterface.BUTTON_POSITIVE,
                     context.getString(R.string.vpn_save), mListener);
@@ -155,6 +172,10 @@
         // Disable the action button if necessary.
         getButton(DialogInterface.BUTTON_POSITIVE)
                 .setEnabled(mEditing ? valid : validate(false));
+
+        // Workaround to resize the dialog for the input method.
+        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE |
+                WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
     }
 
     @Override
@@ -171,6 +192,12 @@
     }
 
     @Override
+    public void onClick(View showOptions) {
+        showOptions.setVisibility(View.GONE);
+        mView.findViewById(R.id.options).setVisibility(View.VISIBLE);
+    }
+
+    @Override
     public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
         if (parent == mType) {
             changeType(position);
@@ -221,7 +248,9 @@
         if (!editing) {
             return mUsername.getText().length() != 0 && mPassword.getText().length() != 0;
         }
-        if (mName.getText().length() == 0 || mServer.getText().length() == 0) {
+        if (mName.getText().length() == 0 || mServer.getText().length() == 0 ||
+                !validateAddresses(mDnsServers.getText().toString(), false) ||
+                !validateAddresses(mRoutes.getText().toString(), true)) {
             return false;
         }
         switch (mType.getSelectedItemPosition()) {
@@ -239,6 +268,33 @@
         return false;
     }
 
+    private boolean validateAddresses(String addresses, boolean cidr) {
+        try {
+            for (String address : addresses.split(" ")) {
+                if (address.isEmpty()) {
+                    continue;
+                }
+                // Legacy VPN currently only supports IPv4.
+                int prefixLength = 32;
+                if (cidr) {
+                    String[] parts = address.split("/", 2);
+                    address = parts[0];
+                    prefixLength = Integer.parseInt(parts[1]);
+                }
+                byte[] bytes = InetAddress.parseNumericAddress(address).getAddress();
+                int integer = (bytes[3] & 0xFF) | (bytes[2] & 0xFF) << 8 |
+                        (bytes[1] & 0xFF) << 16 | (bytes[0] & 0xFF) << 24;
+                if (bytes.length != 4 || prefixLength < 0 || prefixLength > 32 ||
+                        (prefixLength < 32 && (integer << prefixLength) != 0)) {
+                    return false;
+                }
+            }
+        } catch (Exception e) {
+            return false;
+        }
+        return true;
+    }
+
     private void loadCertificates(Spinner spinner, String prefix, int firstId, String selected) {
         Context context = getContext();
         String first = (firstId == 0) ? "" : context.getString(firstId);
@@ -279,6 +335,7 @@
         profile.username = mUsername.getText().toString();
         profile.password = mPassword.getText().toString();
         profile.searchDomains = mSearchDomains.getText().toString().trim();
+        profile.dnsServers = mDnsServers.getText().toString().trim();
         profile.routes = mRoutes.getText().toString().trim();
 
         // Then, save type-specific fields.
diff --git a/src/com/android/settings/vpn2/VpnSettings.java b/src/com/android/settings/vpn2/VpnSettings.java
index 4dbb6bd..2ab99e8 100644
--- a/src/com/android/settings/vpn2/VpnSettings.java
+++ b/src/com/android/settings/vpn2/VpnSettings.java
@@ -108,7 +108,7 @@
                 Credentials.getInstance().unlock(getActivity());
             } else {
                 // We already tried, but it is still not working!
-                getActivity().getFragmentManager().popBackStack();
+                finishFragment();
             }
             mUnlocking = !mUnlocking;
             return;
@@ -429,8 +429,11 @@
         config.interfaze = interfaze;
         config.session = profile.name;
         config.routes = profile.routes;
+        if (!profile.dnsServers.isEmpty()) {
+            config.dnsServers = Arrays.asList(profile.dnsServers.split(" +"));
+        }
         if (!profile.searchDomains.isEmpty()) {
-            config.searchDomains = Arrays.asList(profile.searchDomains.split(" "));
+            config.searchDomains = Arrays.asList(profile.searchDomains.split(" +"));
         }
 
         mService.startLegacyVpn(config, racoon, mtpd);
diff --git a/src/com/android/settings/widget/ChartSweepView.java b/src/com/android/settings/widget/ChartSweepView.java
index 4e37657..99c35bd 100644
--- a/src/com/android/settings/widget/ChartSweepView.java
+++ b/src/com/android/settings/widget/ChartSweepView.java
@@ -61,8 +61,11 @@
     private ChartAxis mAxis;
     private long mValue;
 
-    private ChartSweepView mClampAfter;
-    private ChartSweepView mClampBefore;
+    private long mValidAfter;
+    private long mValidBefore;
+    private ChartSweepView mValidAfterDynamic;
+    private ChartSweepView mValidBeforeDynamic;
+    private long mValidBufferArea;
 
     public static final int HORIZONTAL = 0;
     public static final int VERTICAL = 1;
@@ -259,12 +262,25 @@
         }
     }
 
-    public void setClampAfter(ChartSweepView clampAfter) {
-        mClampAfter = clampAfter;
+    /**
+     * Set valid range this sweep can move within, in {@link #mAxis} values. The
+     * most restrictive combination of all valid ranges is used.
+     */
+    public void setValidRange(long validAfter, long validBefore) {
+        mValidAfter = validAfter;
+        mValidBefore = validBefore;
     }
 
-    public void setClampBefore(ChartSweepView clampBefore) {
-        mClampBefore = clampBefore;
+    /**
+     * Set valid range this sweep can move within, defined by the given
+     * {@link ChartSweepView}. The most restrictive combination of all valid
+     * ranges is used.
+     */
+    public void setValidRangeDynamic(
+            ChartSweepView validAfter, ChartSweepView validBefore, long bufferArea) {
+        mValidAfterDynamic = validAfter;
+        mValidBeforeDynamic = validBefore;
+        mValidBufferArea = bufferArea;
     }
 
     @Override
@@ -285,6 +301,12 @@
 
                 if (accept) {
                     mTracking = event.copy();
+
+                    // starting drag should activate entire chart
+                    if (!parent.isActivated()) {
+                        parent.setActivated(true);
+                    }
+
                     return true;
                 } else {
                     return false;
@@ -336,31 +358,52 @@
         }
     }
 
+    @Override
+    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
+        // ignored to keep LayoutTransition from animating us
+    }
+
+    @Override
+    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
+        // ignored to keep LayoutTransition from animating us
+    }
+
+    private long getValidAfterValue() {
+        final ChartSweepView dynamic = mValidAfterDynamic;
+        final boolean dynamicEnabled = dynamic != null && dynamic.isEnabled();
+        return Math.max(mValidAfter,
+                dynamicEnabled ? dynamic.getValue() + mValidBufferArea : Long.MIN_VALUE);
+    }
+
+    private long getValidBeforeValue() {
+        final ChartSweepView dynamic = mValidBeforeDynamic;
+        final boolean dynamicEnabled = dynamic != null && dynamic.isEnabled();
+        return Math.min(mValidBefore,
+                dynamicEnabled ? dynamic.getValue() - mValidBufferArea : Long.MAX_VALUE);
+    }
+
     /**
      * Compute {@link Rect} in {@link #getParent()} coordinates that we should
-     * be clamped inside of, usually from {@link #setClampAfter(ChartSweepView)}
+     * be clamped inside of, usually from {@link #setValidRange(long, long)}
      * style rules.
      */
     private Rect computeClampRect(Rect parentContent) {
         final Rect clampRect = new Rect(parentContent);
 
-        final ChartSweepView after = mClampAfter;
-        final ChartSweepView before = mClampBefore;
+        float validAfterPoint = mAxis.convertToPoint(getValidAfterValue());
+        float validBeforePoint = mAxis.convertToPoint(getValidBeforeValue());
+        if (validAfterPoint > validBeforePoint) {
+            float swap = validBeforePoint;
+            validBeforePoint = validAfterPoint;
+            validAfterPoint = swap;
+        }
 
         if (mFollowAxis == VERTICAL) {
-            if (after != null) {
-                clampRect.top += after.getPoint();
-            }
-            if (before != null) {
-                clampRect.bottom -= clampRect.height() - before.getPoint();
-            }
+            clampRect.bottom = clampRect.top + (int) validBeforePoint;
+            clampRect.top += validAfterPoint;
         } else {
-            if (after != null) {
-                clampRect.left += after.getPoint();
-            }
-            if (before != null) {
-                clampRect.right -= clampRect.width() - before.getPoint();
-            }
+            clampRect.right = clampRect.left + (int) validBeforePoint;
+            clampRect.left += validAfterPoint;
         }
         return clampRect;
     }
diff --git a/src/com/android/settings/widget/DataUsageChartView.java b/src/com/android/settings/widget/DataUsageChartView.java
index affede0..839171e 100644
--- a/src/com/android/settings/widget/DataUsageChartView.java
+++ b/src/com/android/settings/widget/DataUsageChartView.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.widget;
 
+import static android.text.format.DateUtils.HOUR_IN_MILLIS;
+
 import android.content.Context;
 import android.content.res.Resources;
 import android.net.NetworkPolicy;
@@ -47,6 +49,8 @@
     private ChartNetworkSeriesView mSeries;
     private ChartNetworkSeriesView mDetailSeries;
 
+    private NetworkStatsHistory mHistory;
+
     private ChartSweepView mSweepLeft;
     private ChartSweepView mSweepRight;
     private ChartSweepView mSweepWarning;
@@ -88,10 +92,14 @@
         mSweepWarning = (ChartSweepView) findViewById(R.id.sweep_warning);
 
         // prevent sweeps from crossing each other
-        mSweepLeft.setClampBefore(mSweepRight);
-        mSweepRight.setClampAfter(mSweepLeft);
-        mSweepLimit.setClampBefore(mSweepWarning);
-        mSweepWarning.setClampAfter(mSweepLimit);
+        mSweepLeft.setValidRangeDynamic(null, mSweepRight, HOUR_IN_MILLIS);
+        mSweepRight.setValidRangeDynamic(mSweepLeft, null, HOUR_IN_MILLIS);
+
+        // TODO: assign these ranges as user changes data axis
+        mSweepWarning.setValidRange(0L, 5 * GB_IN_BYTES);
+        mSweepWarning.setValidRangeDynamic(null, mSweepLimit, MB_IN_BYTES);
+        mSweepLimit.setValidRange(0L, 5 * GB_IN_BYTES);
+        mSweepLimit.setValidRangeDynamic(mSweepWarning, null, MB_IN_BYTES);
 
         mSweepLeft.addOnSweepListener(mSweepListener);
         mSweepRight.addOnSweepListener(mSweepListener);
@@ -116,6 +124,7 @@
 
     public void bindNetworkStats(NetworkStatsHistory stats) {
         mSeries.bindNetworkStats(stats);
+        mHistory = stats;
         updatePrimaryRange();
         requestLayout();
     }
@@ -197,15 +206,6 @@
         }
     }
 
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent ev) {
-        if (!isActivated()) {
-            return true;
-        } else {
-            return super.onInterceptTouchEvent(ev);
-        }
-    }
-
     public long getInspectStart() {
         return mSweepLeft.getValue();
     }
@@ -222,18 +222,33 @@
         return mSweepLimit.getValue();
     }
 
+    private long getStatsStart() {
+        return mHistory != null ? mHistory.getStart() : Long.MIN_VALUE;
+    }
+
+    private long getStatsEnd() {
+        return mHistory != null ? mHistory.getEnd() : Long.MAX_VALUE;
+    }
+
     /**
      * Set the exact time range that should be displayed, updating how
      * {@link ChartNetworkSeriesView} paints. Moves inspection ranges to be the
      * last "week" of available data, without triggering listener events.
      */
-    public void setVisibleRange(long start, long end, long dataBoundary) {
-        mHoriz.setBounds(start, end);
+    public void setVisibleRange(long visibleStart, long visibleEnd) {
+        mHoriz.setBounds(visibleStart, visibleEnd);
+
+        final long validStart = Math.max(visibleStart, getStatsStart());
+        final long validEnd = Math.min(visibleEnd, getStatsEnd());
+
+        // prevent time sweeps from leaving valid data
+        mSweepLeft.setValidRange(validStart, validEnd);
+        mSweepRight.setValidRange(validStart, validEnd);
 
         // default sweeps to last week of data
-        final long halfRange = (end + start) / 2;
-        final long sweepMax = Math.min(end, dataBoundary);
-        final long sweepMin = Math.max(start, (sweepMax - DateUtils.WEEK_IN_MILLIS));
+        final long halfRange = (visibleEnd + visibleStart) / 2;
+        final long sweepMax = validEnd;
+        final long sweepMin = Math.max(visibleStart, (sweepMax - DateUtils.WEEK_IN_MILLIS));
 
         mSweepLeft.setValue(sweepMin);
         mSweepRight.setValue(sweepMax);
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index 897280f..876fd99 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -112,8 +112,8 @@
     private TextView mProxyPortView;
     private TextView mProxyExclusionListView;
 
-    private IpAssignment mIpAssignment;
-    private ProxySettings mProxySettings;
+    private IpAssignment mIpAssignment = IpAssignment.UNASSIGNED;
+    private ProxySettings mProxySettings = ProxySettings.UNASSIGNED;
     private LinkProperties mLinkProperties = new LinkProperties();
 
     // True when this instance is used in SetupWizard XL context.