Merge "Add user selectable Default Browser feature"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 98516ed..2484831 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -709,6 +709,26 @@
                 android:value="true" />
         </activity>
 
+        <activity android:name="Settings$ZenModeScheduleRuleSettingsActivity"
+                android:exported="true"
+                android:taskAffinity="">
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.ZEN_MODE_SCHEDULE_RULE_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="com.android.settings.SHORTCUT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.notification.ZenModeScheduleRuleSettings" />
+            <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
+                android:resource="@id/notification_settings" />
+            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+                android:value="true" />
+        </activity>
+
         <activity android:name="Settings$HomeSettingsActivity"
                 android:label="@string/home_settings"
                 android:taskAffinity="">
diff --git a/res/drawable/ic_delete.xml b/res/drawable/ic_delete.xml
new file mode 100644
index 0000000..d4f79e3
--- /dev/null
+++ b/res/drawable/ic_delete.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2015 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:tint="?android:attr/colorControlNormal"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M12.0,38.0c0.0,2.21 1.79,4.0 4.0,4.0l16.0,0.0c2.21,0.0 4.0,-1.79 4.0,-4.0L36.0,14.0L12.0,14.0l0.0,24.0zM38.0,8.0l-7.0,0.0l-2.0,-2.0L19.0,6.0l-2.0,2.0l-7.0,0.0l0.0,4.0l28.0,0.0L38.0,8.0z"/>
+</vector>
diff --git a/res/layout/switch_bar.xml b/res/layout/switch_bar.xml
index 4d33518..7136624 100644
--- a/res/layout/switch_bar.xml
+++ b/res/layout/switch_bar.xml
@@ -24,6 +24,8 @@
               android:layout_width="0dp"
               android:layout_weight="1"
               android:layout_gravity="center_vertical"
+              android:maxLines="2"
+              android:ellipsize="end"
               android:textAppearance="@style/TextAppearance.Switch"
               android:textColor="?android:attr/textColorPrimary"
               android:textAlignment="viewStart" />
diff --git a/res/layout/zen_rule_name.xml b/res/layout/zen_rule_name.xml
new file mode 100755
index 0000000..62f51ea
--- /dev/null
+++ b/res/layout/zen_rule_name.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content" >
+
+    <EditText
+        android:id="@+id/rule_name"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:layout_marginLeft="22dp"
+        android:layout_marginRight="22dp" >
+
+        <requestFocus />
+
+    </EditText>
+
+</FrameLayout>
diff --git a/res/layout/zen_downtime_day.xml b/res/layout/zen_schedule_rule_day.xml
similarity index 92%
rename from res/layout/zen_downtime_day.xml
rename to res/layout/zen_schedule_rule_day.xml
index 8d2fa73..1d300d2 100755
--- a/res/layout/zen_downtime_day.xml
+++ b/res/layout/zen_schedule_rule_day.xml
@@ -20,4 +20,4 @@
     android:minHeight="?android:attr/listPreferredItemHeightSmall"
     android:textAppearance="?android:attr/textAppearanceMedium"
     android:gravity="center_vertical"
-    android:paddingStart="@dimen/zen_downtime_checkbox_padding" />
+    android:paddingStart="@dimen/zen_schedule_rule_checkbox_padding" />
diff --git a/res/menu/zen_mode_automation.xml b/res/menu/zen_mode_automation.xml
new file mode 100644
index 0000000..02ec41f
--- /dev/null
+++ b/res/menu/zen_mode_automation.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/add"
+        android:title="@string/zen_mode_time_add_rule"
+        android:icon="@drawable/ic_menu_add_white"
+        android:visible="true"
+        android:showAsAction="collapseActionView|ifRoom" />
+</menu>
diff --git a/res/menu/zen_mode_rule.xml b/res/menu/zen_mode_rule.xml
new file mode 100644
index 0000000..eea30a8
--- /dev/null
+++ b/res/menu/zen_mode_rule.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/delete"
+        android:title="@string/zen_mode_delete_rule"
+        android:icon="@drawable/ic_delete"
+        android:visible="true"
+        android:showAsAction="collapseActionView|ifRoom" />
+</menu>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 22c351c..4f1eb97 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1210,20 +1210,6 @@
         <item>3</item>
     </string-array>
 
-    <!-- Setting display values for zen mode -->
-    <string-array name="entries_zen_mode">
-        <item>Off</item>
-        <item>Limited interruptions</item>
-        <item>Zero interruptions</item>
-    </string-array>
-
-    <!-- Setting values for zen mode, must match the Settings.Global.ZEN_MODE_ constants -->
-    <string-array name="entryvalues_zen_mode" translatable="false">
-        <item>0</item>
-        <item>1</item>
-        <item>2</item>
-    </string-array>
-
     <!-- Battery saver mode: allowable trigger threshold levels. -->
     <integer-array name="battery_saver_trigger_values" translatable="false" >
         <item>0</item>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 580ae22..1fd22e0 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -90,8 +90,8 @@
     <dimen name="notification_app_icon_size">64dp</dimen>
     <dimen name="notification_app_icon_badge_size">20dp</dimen>
     <dimen name="notification_app_icon_badge_margin">4dp</dimen>
-    <dimen name="zen_downtime_checkbox_padding">7dp</dimen>
-    <dimen name="zen_downtime_margin">17dp</dimen>
+    <dimen name="zen_schedule_rule_checkbox_padding">7dp</dimen>
+    <dimen name="zen_schedule_day_margin">17dp</dimen>
 
     <!-- Default text size for caption preview samples. Uses dp rather than sp because captions are not scaled. -->
     <dimen name="caption_preview_text_size">48dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0adf5be..50ba70c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -587,23 +587,11 @@
     <!-- Button label for generic cancel action [CHAR LIMIT=20] -->
     <string name="cancel">Cancel</string>
 
-    <!-- Button label for generic cancel action in all caps [CHAR LIMIT=20] -->
-    <string name="cancel_all_caps">CANCEL</string>
-
-    <!-- Button label for generic continue action in all caps [CHAR LIMIT=20] -->
-    <string name="continue_all_caps">CONTINUE</string>
-
     <!-- Button label for generic OK action [CHAR LIMIT=20] -->
     <string name="okay">OK</string>
 
-    <!-- Button label for generic YES action [CHAR LIMIT=20] -->
-    <string name="yes_all_caps">YES</string>
-
-    <!-- Button label for generic NO action [CHAR LIMIT=20] -->
-    <string name="no_all_caps">NO</string>
-
-    <!-- Button label for generic FORGET action [CHAR LIMIT=20] -->
-    <string name="forget">FORGET</string>
+    <!-- Button label for generic forget action [CHAR LIMIT=20] -->
+    <string name="forget">Forget</string>
 
     <!-- Title of the Settings activity shown within the application itself. -->
     <string name="settings_label">Settings</string>
@@ -1249,9 +1237,11 @@
     <!-- Message to describe "BLE scan always available feature" when Bluetooth is off. The
       place-holders "LINK_BEGIN" and "LINK_END" must NOT be translated. They mark a link to bring
       the user to "scanning settings" screen. -->
-    <string name="ble_scan_notify_text">To improve location accuracy, Google services will scan for
-        Bluetooth devices, even when Bluetooth is off. You can change this in LINK_BEGINscanning
-        settingsLINK_END.</string>
+    <string name="ble_scan_notify_text">To improve location accuracy, apps and
+        services will scan for Bluetooth devices, even when Bluetooth is off.
+        You can change this in
+        <xliff:g id="link_begin">LINK_BEGIN</xliff:g>scanning
+        settings<xliff:g id="link_end">LINK_END</xliff:g>.</string>
 
 
     <!-- Bluetooth settings.  The title of the screen to pick which profiles to connect to on the device.  For example, headphones may have both A2DP and headset, this allows the user to choose which one he wants to connect to. -->
@@ -1425,9 +1415,11 @@
     <!-- Message to describe "Wi-Fi scan always available feature" when Wi-Fi is off. The
       place-holders "LINK_BEGIN" and "LINK_END" must NOT be translated. They mark a link to bring
       the user to "scanning settings" screen. -->
-    <string name="wifi_scan_notify_text">To improve location accuracy, Google services will scan for
-        Wi\u2011Fi networks, even when Wi\u2011Fi is off. You can change this in LINK_BEGINscanning
-        settingsLINK_END.</string>
+    <string name="wifi_scan_notify_text">To improve location accuracy, apps and
+        services will scan for Wi\u2011Fi networks, even when Wi\u2011Fi is off.
+        You can change this in
+        <xliff:g id="link_begin">LINK_BEGIN</xliff:g>scanning
+        settings<xliff:g id="link_end">LINK_END</xliff:g>.</string>
     <!-- Wifi scan always mode checkbox text -->
     <string name="wifi_scan_notify_remember_choice">Don\'t show again</string>
     <!-- Setting title for setting the wifi sleep policy. Do we keep Wi-Fi active when the screen turns off? -->
@@ -2620,16 +2612,18 @@
     <string name="location_menu_scanning">Scanning</string>
     <!-- [CHAR LIMIT=30] Wireless background scanning settings screen, screen title -->
     <string name="location_scanning_screen_title">Scanning</string>
-    <!-- [CHAR LIMIT=130] Preference title for Wi-Fi always scanning [DO NOT TRANSLATE] -->
-    <string name="location_scanning_wifi_always_scanning_title">Wi\u2011Fi scanning always available</string>
-    <!-- Preference description text for Wi-Fi always scanning [DO NOT TRANSLATE] -->
-    <string name="location_scanning_wifi_always_scanning_description">The clear history button in
-        your browser has saved more lives than Superman</string>
-    <!-- [CHAR LIMIT=130] Description text for Bluetooth always scanning [DO NOT TRANSLATE] -->
-    <string name="location_scanning_bluetooth_always_scanning_title">Bluetooth scanning always available</string>
-    <!-- Description text for Bluetooth always scanning [DO NOT TRANSLATE] -->
-    <string name="location_scanning_bluetooth_always_scanning_description">If you want to catch a
-        squirrel just climb a tree and act like a nut</string>
+    <!-- [CHAR LIMIT=130] Preference title for Wi-Fi always scanning -->
+    <string name="location_scanning_wifi_always_scanning_title">Wi\u2011Fi scanning</string>
+    <!-- Preference description text for Wi-Fi always scanning -->
+    <string name="location_scanning_wifi_always_scanning_description">Improve
+        location by allowing apps and services to scan for Wi\u2011Fi networks
+        even when Wi\u2011Fi is off</string>
+    <!-- [CHAR LIMIT=130] Description text for Bluetooth always scanning -->
+    <string name="location_scanning_bluetooth_always_scanning_title">Bluetooth scanning</string>
+    <!-- Description text for Bluetooth always scanning -->
+    <string name="location_scanning_bluetooth_always_scanning_description">
+        Improve location by allowing system services to scan for Bluetooth
+        devices, even when Bluetooth is off</string>
 
     <!-- [CHAR LIMIT=30] Security & location settings screen, setting check box label for Google location service (cell ID, wifi, etc.) -->
     <string name="location_network_based">Wi\u2011Fi &amp; cellular network location</string>
@@ -5700,7 +5694,7 @@
     <string name="notification_volume_option_title">Notification volume</string>
 
     <!-- Sound & notification > Sound section: Title for the Interruptions option and associated settings page. [CHAR LIMIT=30] -->
-    <string name="zen_mode_settings_title">Block interruptions</string>
+    <string name="zen_mode_settings_title">@*android:string/zen_mode_feature_name</string>
 
     <!-- Sound & notification > Sound section: Title for the Priority interruptions option and associated settings page. [CHAR LIMIT=30] -->
     <string name="zen_mode_priority_settings_title">Priority only allows</string>
@@ -5708,20 +5702,17 @@
     <!-- Sound & notification > Sound section: Title for the zen mode automation option and associated settings page. [CHAR LIMIT=30] -->
     <string name="zen_mode_automation_settings_title">Automatic rules</string>
 
-    <!-- Sound & notification > Sound section: Title for the zen mode option. [CHAR LIMIT=60] -->
-    <string name="zen_mode_option_title">When calls and notifications arrive</string>
-
-    <!-- Sound & notification > Sound section: Zen mode option: Off [CHAR LIMIT=60] -->
-    <string name="zen_mode_option_off">Always interrupt</string>
-
     <!-- Sound & notification > Sound section: Zen mode option: Important interruptions [CHAR LIMIT=60] -->
-    <string name="zen_mode_option_important_interruptions">Allow only priority interruptions</string>
+    <string name="zen_mode_option_important_interruptions">Priority only</string>
 
     <!-- Sound & notification > Sound section: Zen mode option: Alarms only [CHAR LIMIT=60] -->
-    <string name="zen_mode_option_alarms">Allow only alarms</string>
+    <string name="zen_mode_option_alarms">Alarms only</string>
 
     <!-- Sound & notification > Sound section: Zen mode option: No interruptions [CHAR LIMIT=60] -->
-    <string name="zen_mode_option_no_interruptions">Don\'t interrupt</string>
+    <string name="zen_mode_option_no_interruptions">No interruptions</string>
+
+    <!-- Sound & notification > Sound section: Zen mode combined summary + condition line [CHAR LIMIT=60] -->
+    <string name="zen_mode_summary_combination"><xliff:g id="mode" example="Priority only">%1$s</xliff:g>: <xliff:g id="exit condition" example="Until you turn this off">%2$s</xliff:g></string>
 
     <!-- Sound & notification > Sound section: Title for the option defining the phone ringtone. [CHAR LIMIT=30] -->
     <string name="ringtone_title">Phone ringtone</string>
@@ -5826,32 +5817,6 @@
         to dismiss these notifications or touch action buttons within them.
     </string>
 
-    <!-- Title of preference to manage condition providers -->
-    <string name="manage_condition_providers">Condition providers</string>
-
-    <!-- Summary of preference to manage condition providers, when none are enabled -->
-    <string name="manage_condition_providers_summary_zero">No apps provide conditions</string>
-
-    <!-- Summary of preference to manage condition providers, when one or more are enabled -->
-    <plurals name="manage_condition_providers_summary_nonzero">
-        <item quantity="one">%d app provides conditions</item>
-        <item quantity="other">%d apps provide conditions</item>
-    </plurals>
-
-    <!-- String to show in the list of condition providers, when none is installed -->
-    <string name="no_condition_providers">No condition providers are installed.</string>
-
-    <!-- Title for a warning message about security implications of enabling a condition
-          provider, displayed as a dialog message. [CHAR LIMIT=NONE] -->
-    <string name="condition_provider_security_warning_title">Enable
-         <xliff:g id="service" example="ConditionProvider">%1$s</xliff:g>?</string>
-    <!-- Summary for a warning message about security implications of enabling a condition
-          provider, displayed as a dialog message. [CHAR LIMIT=NONE] -->
-    <string name="condition_provider_security_warning_summary">
-        <xliff:g id="condition_provider_name">%1$s</xliff:g> will be able to
-        add exit conditions to Do not disturb mode.
-    </string>
-
     <!-- [CHAR LIMIT=NONE] Text when loading app list in notification settings -->
     <string name="loading_notification_apps">Loading apps...</string>
 
@@ -5891,38 +5856,44 @@
     <!-- [CHAR LIMIT=20] Notification settings: App notifications dialog dismiss button caption -->
     <string name="app_notifications_dialog_done">Done</string>
 
-    <!-- [CHAR LIMIT=30] Zen mode settings: Exit condition selection dialog, default option -->
-    <string name="zen_mode_default_option">Until you turn this off</string>
+    <!-- [CHAR LIMIT=40] Zen mode settings: Rule name option and edit dialog title -->
+    <string name="zen_mode_rule_name">Rule name</string>
 
-    <!-- [CHAR LIMIT=60] Zen mode settings: Downtime category text -->
-    <string name="zen_mode_downtime_category">Downtime</string>
+    <!-- [CHAR LIMIT=40] Zen mode settings: Add rule menu option name -->
+    <string name="zen_mode_time_add_rule">Add rule</string>
 
-    <!-- [CHAR LIMIT=40] Zen mode settings: Downtime days option title -->
-    <string name="zen_mode_downtime_days">Days</string>
+    <!-- [CHAR LIMIT=40] Zen mode settings: Delete rule menu option name -->
+    <string name="zen_mode_delete_rule">Delete rule</string>
+
+    <!-- [CHAR LIMIT=40] Zen mode settings: Delete rule dialog confirmation message -->
+    <string name="zen_mode_delete_rule_confirmation">Delete \"<xliff:g id="rule" example="Weekends">%1$s</xliff:g>\" rule?</string>
+
+    <!-- [CHAR LIMIT=40] Zen mode settings: Delete rule dialog button caption -->
+    <string name="zen_mode_delete_rule_button">Delete</string>
+
+    <!-- [CHAR LIMIT=40] Zen mode settings: Text to display if rule isn't found  -->
+    <string name="zen_mode_rule_not_found_text">Rule not found.</string>
+
+    <!-- [CHAR LIMIT=40] Zen mode settings: Rule summary template (when enabled)  -->
+    <string name="zen_mode_rule_summary_template"><xliff:g id="days" example="Sun - Thu">%1$s</xliff:g> / <xliff:g id="timerange" example="10:00 PM to 7:30 AM">%2$s</xliff:g> / <xliff:g id="mode" example="Alarms only">%3$s</xliff:g></string>
+
+    <!-- [CHAR LIMIT=40] Zen mode settings: Timebased rule days option title -->
+    <string name="zen_mode_schedule_rule_days">Days</string>
 
     <!-- [CHAR LIMIT=40] Zen mode settings: Downtime days option value, no days set -->
-    <string name="zen_mode_downtime_days_none">None</string>
+    <string name="zen_mode_schedule_rule_days_none">None</string>
 
-    <!-- [CHAR LIMIT=60] Zen mode settings: Downtime mode option title -->
-    <string name="zen_mode_downtime_mode_title">Interruptions allowed</string>
-
-    <!-- [CHAR LIMIT=40] Zen mode settings: Downtime mode option value, priority only -->
-    <string name="zen_mode_downtime_mode_priority">Priority only</string>
-
-    <!-- [CHAR LIMIT=40] Zen mode settings: Downtime mode option value, none -->
-    <string name="zen_mode_downtime_mode_none">None</string>
-
-    <!-- [CHAR LIMIT=40] Zen mode settings: Automation category text -->
-    <string name="zen_mode_automation_category">Automation</string>
-
-    <!-- [CHAR LIMIT=40] Zen mode settings: Entry conditions option: title -->
-    <string name="zen_mode_entry_conditions_title">Automatically turn on</string>
+    <!-- [CHAR LIMIT=40] Zen mode settings: Downtime days option value, all days set -->
+    <string name="zen_mode_schedule_rule_days_all">Every day</string>
 
     <!-- [CHAR LIMIT=40] General divider text when concatenating multiple items in a text summary -->
     <string name="summary_divider_text">,\u0020</string>
 
-    <!-- [CHAR LIMIT=40] Zen mode settings: Entry conditions option: value when blank -->
-    <string name="zen_mode_entry_conditions_summary_none">Never</string>
+    <!-- [CHAR LIMIT=40] General template for a symbolic start - end range in a text summary -->
+    <string name="summary_range_symbol_combination"><xliff:g id="start" example="Sun">%1$s</xliff:g> - <xliff:g id="end" example="Thu">%2$s</xliff:g></string>
+
+    <!-- [CHAR LIMIT=40] General template for a verbal start to end range in a text summary -->
+    <string name="summary_range_verbal_combination"><xliff:g id="start" example="Sun">%1$s</xliff:g> to <xliff:g id="end" example="Thu">%2$s</xliff:g></string>
 
     <!-- [CHAR LIMIT=20] Zen mode settings: Calls option -->
     <string name="zen_mode_calls">Calls</string>
@@ -5951,6 +5922,15 @@
     <!-- [CHAR LIMIT=50] Zen mode settings: Events option -->
     <string name="zen_mode_events">Events</string>
 
+    <!-- [CHAR LIMIT=50] Zen mode settings: Selected callers summary -->
+    <string name="zen_mode_selected_callers">Selected callers</string>
+
+    <!-- [CHAR LIMIT=50] Zen mode settings: Repeat callers option -->
+    <string name="zen_mode_repeat_callers">Repeat callers</string>
+
+    <!-- [CHAR LIMIT=200] Zen mode settings: Repeat callers option summary -->
+    <string name="zen_mode_repeat_callers_summary">If the same person calls a second time within a <xliff:g id="minutes">%d</xliff:g> minute period, allow it</string>
+
     <!-- [CHAR LIMIT=20] Zen mode settings: When option -->
     <string name="zen_mode_when">Automatically turn on</string>
 
@@ -5969,14 +5949,8 @@
     <!-- [CHAR LIMIT=20] Zen mode settings: End time option -->
     <string name="zen_mode_end_time">End time</string>
 
-    <!-- [CHAR LIMIT=60] Zen mode settings: End time option: Summary text value format when downtime mode = priority and end time = next day -->
-    <string name="zen_mode_end_time_priority_next_day_summary_format"><xliff:g id="formatted_time">%s</xliff:g> next day</string>
-
-    <!-- [CHAR LIMIT=60] Zen mode settings: End time option: Summary text value format when downtime mode = none and end time = same day -->
-    <string name="zen_mode_end_time_none_same_day_summary_format"><xliff:g id="formatted_time">%s</xliff:g> or any alarm before</string>
-
-    <!-- [CHAR LIMIT=60] Zen mode settings: End time option: Summary text value format when downtime mode = none and end time = next day -->
-    <string name="zen_mode_end_time_none_next_day_summary_format"><xliff:g id="formatted_time">%s</xliff:g> next day or any alarm before</string>
+    <!-- [CHAR LIMIT=60] Zen mode settings: End time option: Summary text value format when end time = next day -->
+    <string name="zen_mode_end_time_next_day_summary_format"><xliff:g id="formatted_time">%s</xliff:g> next day</string>
 
     <!-- [CHAR LIMIT=20] Notifications settings: Apps section header -->
     <string name="notification_settings_apps_title">App notifications</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 8d0b885..78a3572 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -350,4 +350,8 @@
         <item name="android:textColor">@color/fingerprint_message_color</item>
     </style>
 
+    <style name="TextAppearance.Small.SwitchBar">
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
+        <item name="android:textStyle">normal</item>
+    </style>
 </resources>
diff --git a/res/xml/zen_mode_automation_settings.xml b/res/xml/zen_mode_automation_settings.xml
index 3098630..7cfffd4 100644
--- a/res/xml/zen_mode_automation_settings.xml
+++ b/res/xml/zen_mode_automation_settings.xml
@@ -19,43 +19,5 @@
     android:key="zen_mode_settings"
     android:title="@string/zen_mode_automation_settings_title" >
 
-    <!-- Downtime -->
-    <PreferenceCategory
-        android:key="downtime"
-        android:title="@string/zen_mode_downtime_category" >
-
-        <!-- Days -->
-        <Preference
-            android:key="days"
-            android:title="@string/zen_mode_downtime_days"
-            android:persistent="false" />
-
-        <!-- Start time/End time added and removed here! :-) -->
-
-        <!-- Interruptions allowed -->
-        <com.android.settings.DropDownPreference
-                android:key="downtime_mode"
-                android:title="@string/zen_mode_downtime_mode_title"
-                android:order="100"
-                android:persistent="false" />
-
-    </PreferenceCategory>
-
-    <PreferenceCategory
-        android:key="automation"
-        android:title="@string/zen_mode_automation_category" >
-
-        <Preference
-            android:key="entry"
-            android:title="@string/zen_mode_entry_conditions_title"
-            android:persistent="false" />
-
-        <Preference
-                android:key="manage_condition_providers"
-                android:title="@string/manage_condition_providers"
-                android:persistent="false"
-                android:fragment="com.android.settings.notification.ConditionProviderSettings" />
-
-    </PreferenceCategory>
-
+    <!-- Rules added at runtime -->
 </PreferenceScreen>
diff --git a/res/xml/zen_mode_priority_settings.xml b/res/xml/zen_mode_priority_settings.xml
index e8bab66..5b1dbf8 100644
--- a/res/xml/zen_mode_priority_settings.xml
+++ b/res/xml/zen_mode_priority_settings.xml
@@ -16,7 +16,7 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-    android:key="zen_mode_settings"
+    android:key="zen_mode_priority_settings"
     android:title="@string/zen_mode_priority_settings_title" >
 
     <!-- Alarms -->
@@ -67,4 +67,12 @@
             android:title="@string/zen_mode_from"
             android:persistent="false" />
 
+    <!-- Repeat callers -->
+    <SwitchPreference
+        android:key="repeat_callers"
+        android:title="@string/zen_mode_repeat_callers"
+        android:persistent="false"
+        android:switchTextOff=""
+        android:switchTextOn="" />
+
 </PreferenceScreen>
diff --git a/res/xml/zen_mode_schedule_rule_settings.xml b/res/xml/zen_mode_schedule_rule_settings.xml
new file mode 100644
index 0000000..d808b10
--- /dev/null
+++ b/res/xml/zen_mode_schedule_rule_settings.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2015 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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    android:key="zen_mode_schedule_rule_settings" >
+
+    <!-- Rule name -->
+    <Preference
+        android:key="rule_name"
+        android:title="@string/zen_mode_rule_name"
+        android:persistent="false" />
+
+    <!-- Days -->
+    <Preference
+        android:key="days"
+        android:title="@string/zen_mode_schedule_rule_days"
+        android:persistent="false" />
+
+    <!-- Start time/End time added and removed here! :-) -->
+
+    <!-- Zen mode -->
+    <com.android.settings.DropDownPreference
+            android:key="zen_mode"
+            android:title="@string/zen_mode_settings_title"
+            android:order="100"
+            android:persistent="false" />
+
+</PreferenceScreen>
diff --git a/res/xml/zen_mode_settings.xml b/res/xml/zen_mode_settings.xml
index 1194d1b..267727f 100644
--- a/res/xml/zen_mode_settings.xml
+++ b/res/xml/zen_mode_settings.xml
@@ -19,12 +19,6 @@
     android:key="zen_mode_settings"
     android:title="@string/zen_mode_settings_title" >
 
-    <!-- When calls and notifications arrive -->
-    <com.android.settings.DropDownPreference
-            android:key="zen_mode"
-            android:title="@string/zen_mode_option_title"
-            android:persistent="false" />
-
     <!-- Priority only allows -->
     <PreferenceScreen
             android:key="priority_settings"
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index e0091e1..5fafc92 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -24,6 +24,7 @@
 import android.app.backup.IBackupManager;
 import android.bluetooth.BluetoothAdapter;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -751,6 +752,9 @@
     }
 
     private void updateBugreportOptions() {
+        final ComponentName bugreportStorageProviderComponentName =
+                new ComponentName("com.android.shell",
+                        "com.android.shell.BugreportStorageProvider");
         if ("user".equals(Build.TYPE)) {
             final ContentResolver resolver = getActivity().getContentResolver();
             final boolean adbEnabled = Settings.Global.getInt(
@@ -758,14 +762,23 @@
             if (adbEnabled) {
                 mBugreport.setEnabled(true);
                 mBugreportInPower.setEnabled(true);
+                getPackageManager().setComponentEnabledSetting(
+                        bugreportStorageProviderComponentName,
+                        PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
             } else {
                 mBugreport.setEnabled(false);
                 mBugreportInPower.setEnabled(false);
                 mBugreportInPower.setChecked(false);
                 Settings.Secure.putInt(resolver, Settings.Secure.BUGREPORT_IN_POWER_MENU, 0);
+                getPackageManager().setComponentEnabledSetting(
+                        bugreportStorageProviderComponentName,
+                        PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0);
             }
         } else {
             mBugreportInPower.setEnabled(true);
+            getPackageManager().setComponentEnabledSetting(
+                    bugreportStorageProviderComponentName,
+                    PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
         }
     }
 
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 70455a4..b58159e 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -96,6 +96,7 @@
     public static class ZenModeSettingsActivity extends SettingsActivity { /* empty */ }
     public static class ZenModePrioritySettingsActivity extends SettingsActivity { /* empty */ }
     public static class ZenModeAutomationSettingsActivity extends SettingsActivity { /* empty */ }
+    public static class ZenModeScheduleRuleSettingsActivity extends SettingsActivity { /* empty */ }
     public static class NotificationSettingsActivity extends SettingsActivity { /* empty */ }
     public static class NotificationAppListActivity extends SettingsActivity { /* empty */ }
     public static class AppNotificationSettingsActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 4794608..24209b0 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -100,6 +100,7 @@
 import com.android.settings.notification.NotificationStation;
 import com.android.settings.notification.OtherSoundSettings;
 import com.android.settings.notification.ZenModeSettings;
+import com.android.settings.notification.ZenModeScheduleRuleSettings;
 import com.android.settings.print.PrintJobSettingsFragment;
 import com.android.settings.print.PrintSettingsFragment;
 import com.android.settings.search.DynamicIndexableContentMonitor;
@@ -332,7 +333,8 @@
             AppNotificationSettings.class.getName(),
             OtherSoundSettings.class.getName(),
             ApnSettings.class.getName(),
-            WifiCallingSettings.class.getName()
+            WifiCallingSettings.class.getName(),
+            ZenModeScheduleRuleSettings.class.getName(),
     };
 
 
@@ -934,17 +936,31 @@
      */
     public void startPreferencePanelAsUser(String fragmentClass, Bundle args, int titleRes,
             CharSequence titleText, UserHandle userHandle) {
-        String title = null;
-        if (titleRes < 0) {
-            if (titleText != null) {
-                title = titleText.toString();
-            } else {
-                // There not much we can do in that case
-                title = "";
+        // This is a workaround.
+        //
+        // Calling startWithFragmentAsUser() without specifying FLAG_ACTIVITY_NEW_TASK to the intent
+        // starting the fragment could cause a native stack corruption. See b/17523189. However,
+        // adding that flag and start the preference panel with the same UserHandler will make it
+        // impossible to use back button to return to the previous screen. See b/20042570.
+        //
+        // We work around this issue by adding FLAG_ACTIVITY_NEW_TASK to the intent, while doing
+        // another check here to call startPreferencePanel() instead of startWithFragmentAsUser()
+        // when we're calling it as the same user.
+        if (userHandle.getIdentifier() == UserHandle.myUserId()) {
+            startPreferencePanel(fragmentClass, args, titleRes, titleText, null, 0);
+        } else {
+            String title = null;
+            if (titleRes < 0) {
+                if (titleText != null) {
+                    title = titleText.toString();
+                } else {
+                    // There not much we can do in that case
+                    title = "";
+                }
             }
+            Utils.startWithFragmentAsUser(this, fragmentClass, args,
+                    titleRes, title, mIsShortcut, userHandle);
         }
-        Utils.startWithFragmentAsUser(this, fragmentClass, args,
-                titleRes, title, mIsShortcut, userHandle);
     }
 
     /**
diff --git a/src/com/android/settings/SetupChooseLockGeneric.java b/src/com/android/settings/SetupChooseLockGeneric.java
index a631caf..a69ae38 100644
--- a/src/com/android/settings/SetupChooseLockGeneric.java
+++ b/src/com/android/settings/SetupChooseLockGeneric.java
@@ -52,7 +52,7 @@
 
     @Override
     protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
-        resid = SetupWizardUtils.getTheme(getIntent(), resid);
+        resid = SetupWizardUtils.getTheme(getIntent());
         super.onApplyThemeResource(theme, resid, first);
     }
 
diff --git a/src/com/android/settings/SetupChooseLockPassword.java b/src/com/android/settings/SetupChooseLockPassword.java
index b9f408e..75a4b76 100644
--- a/src/com/android/settings/SetupChooseLockPassword.java
+++ b/src/com/android/settings/SetupChooseLockPassword.java
@@ -63,7 +63,7 @@
 
     @Override
     protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
-        resid = SetupWizardUtils.getTheme(getIntent(), resid);
+        resid = SetupWizardUtils.getTheme(getIntent());
         super.onApplyThemeResource(theme, resid, first);
     }
 
diff --git a/src/com/android/settings/SetupChooseLockPattern.java b/src/com/android/settings/SetupChooseLockPattern.java
index 903a207..ed5b61a 100644
--- a/src/com/android/settings/SetupChooseLockPattern.java
+++ b/src/com/android/settings/SetupChooseLockPattern.java
@@ -61,7 +61,7 @@
 
     @Override
     protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
-        resid = SetupWizardUtils.getTheme(getIntent(), resid);
+        resid = SetupWizardUtils.getTheme(getIntent());
         super.onApplyThemeResource(theme, resid, first);
     }
 
diff --git a/src/com/android/settings/SetupEncryptionInterstitial.java b/src/com/android/settings/SetupEncryptionInterstitial.java
index 41782da..09c3bfc 100644
--- a/src/com/android/settings/SetupEncryptionInterstitial.java
+++ b/src/com/android/settings/SetupEncryptionInterstitial.java
@@ -62,7 +62,7 @@
 
     @Override
     protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
-        resid = SetupWizardUtils.getTheme(getIntent(), resid);
+        resid = SetupWizardUtils.getTheme(getIntent());
         super.onApplyThemeResource(theme, resid, first);
     }
 
diff --git a/src/com/android/settings/SetupRedactionInterstitial.java b/src/com/android/settings/SetupRedactionInterstitial.java
index badfe8d..410804e 100644
--- a/src/com/android/settings/SetupRedactionInterstitial.java
+++ b/src/com/android/settings/SetupRedactionInterstitial.java
@@ -60,7 +60,7 @@
 
     @Override
     protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
-        resid = SetupWizardUtils.getTheme(getIntent(), resid);
+        resid = SetupWizardUtils.getTheme(getIntent());
         super.onApplyThemeResource(theme, resid, first);
     }
 
diff --git a/src/com/android/settings/SetupWizardUtils.java b/src/com/android/settings/SetupWizardUtils.java
index c35bb15..e83482a 100644
--- a/src/com/android/settings/SetupWizardUtils.java
+++ b/src/com/android/settings/SetupWizardUtils.java
@@ -38,6 +38,8 @@
     public static final String THEME_HOLO_LIGHT = "holo_light";
     public static final String THEME_MATERIAL = "material";
     public static final String THEME_MATERIAL_LIGHT = "material_light";
+    public static final String THEME_MATERIAL_BLUE = "material_blue";
+    public static final String THEME_MATERIAL_BLUE_LIGHT = "material_blue_light";
 
     public static final String EXTRA_USE_IMMERSIVE_MODE = "useImmersiveMode";
 
@@ -68,17 +70,14 @@
         activity.startActivityForResult(nextIntent, NEXT_REQUEST);
     }
 
-    public static int getTheme(Intent intent, int defaultResId) {
+    public static int getTheme(Intent intent) {
         final String themeName = intent.getStringExtra(EXTRA_THEME);
-        int resid = defaultResId;
-        if (THEME_HOLO_LIGHT.equalsIgnoreCase(themeName) ||
-                THEME_MATERIAL_LIGHT.equalsIgnoreCase(themeName)) {
-            resid = R.style.SetupWizardTheme_Light;
-        } else if (THEME_HOLO.equalsIgnoreCase(themeName) ||
-                THEME_MATERIAL.equalsIgnoreCase(themeName)) {
-            resid = R.style.SetupWizardTheme;
+        if (THEME_HOLO.equalsIgnoreCase(themeName) || THEME_MATERIAL.equalsIgnoreCase(themeName)
+                || THEME_MATERIAL_BLUE.equalsIgnoreCase(themeName)) {
+            return R.style.SetupWizardTheme;
+        } else {
+            return R.style.SetupWizardTheme_Light;
         }
-        return resid;
     }
 
     /**
diff --git a/src/com/android/settings/fuelgauge/PowerUsageDetail.java b/src/com/android/settings/fuelgauge/PowerUsageDetail.java
index 3bc1a23..1f13e8e 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageDetail.java
@@ -260,14 +260,8 @@
         args.putIntArray(PowerUsageDetail.EXTRA_DETAIL_TYPES, types);
         args.putDoubleArray(PowerUsageDetail.EXTRA_DETAIL_VALUES, values);
 
-        // This is a workaround, see b/17523189
-        if (userId == UserHandle.myUserId()) {
-            caller.startPreferencePanel(PowerUsageDetail.class.getName(), args,
-                    R.string.details_title, null, null, 0);
-        } else {
-            caller.startPreferencePanelAsUser(PowerUsageDetail.class.getName(), args,
-                    R.string.details_title, null, new UserHandle(userId));
-        }
+        caller.startPreferencePanelAsUser(PowerUsageDetail.class.getName(), args,
+                R.string.details_title, null, new UserHandle(userId));
     }
 
     public static final int ACTION_DISPLAY_SETTINGS = 1;
diff --git a/src/com/android/settings/notification/ZenModeAutomaticConditionSelection.java b/src/com/android/settings/notification/ZenModeAutomaticConditionSelection.java
deleted file mode 100644
index 0e77632..0000000
--- a/src/com/android/settings/notification/ZenModeAutomaticConditionSelection.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.settings.notification;
-
-import android.animation.LayoutTransition;
-import android.app.INotificationManager;
-import android.content.Context;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.service.notification.Condition;
-import android.service.notification.IConditionListener;
-import android.util.ArraySet;
-import android.util.Log;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
-import android.widget.LinearLayout;
-
-import com.android.settings.R;
-
-public class ZenModeAutomaticConditionSelection extends LinearLayout {
-    private static final String TAG = "ZenModeAutomaticConditionSelection";
-    private static final boolean DEBUG = true;
-
-    private final INotificationManager mNoMan;
-    private final H mHandler = new H();
-    private final Context mContext;
-    private final ArraySet<Uri> mSelectedConditions = new ArraySet<Uri>();
-
-    public ZenModeAutomaticConditionSelection(Context context) {
-        super(context);
-        mContext = context;
-        setOrientation(VERTICAL);
-        setLayoutTransition(new LayoutTransition());
-        final int p = mContext.getResources().getDimensionPixelSize(R.dimen.content_margin_left);
-        setPadding(p, p, p, 0);
-        mNoMan = INotificationManager.Stub.asInterface(
-                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
-        refreshSelectedConditions();
-    }
-
-    private void refreshSelectedConditions() {
-        try {
-            final Condition[] automatic = mNoMan.getAutomaticZenModeConditions();
-            mSelectedConditions.clear();
-            if (automatic != null) {
-                for (Condition c : automatic) {
-                    mSelectedConditions.add(c.id);
-                }
-            }
-        } catch (RemoteException e) {
-            Log.w(TAG, "Error calling getAutomaticZenModeConditions", e);
-        }
-    }
-
-    private CheckBox newCheckBox(Object tag) {
-        final CheckBox button = new CheckBox(mContext);
-        button.setTag(tag);
-        button.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
-            @Override
-            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-                 setSelectedCondition((Uri)button.getTag(), isChecked);
-            }
-        });
-        addView(button);
-        return button;
-    }
-
-    private void setSelectedCondition(Uri conditionId, boolean selected) {
-        if (DEBUG) Log.d(TAG, "setSelectedCondition conditionId=" + conditionId
-                + " selected=" + selected);
-        if (selected) {
-            mSelectedConditions.add(conditionId);
-        } else {
-            mSelectedConditions.remove(conditionId);
-        }
-        final Uri[] automatic = new Uri[mSelectedConditions.size()];
-        for (int i = 0; i < automatic.length; i++) {
-            automatic[i] = mSelectedConditions.valueAt(i);
-        }
-        try {
-            mNoMan.setAutomaticZenModeConditions(automatic);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Error calling setAutomaticZenModeConditions", e);
-        }
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        requestZenModeConditions(Condition.FLAG_RELEVANT_ALWAYS);
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        requestZenModeConditions(0 /*none*/);
-    }
-
-    protected void requestZenModeConditions(int relevance) {
-        if (DEBUG) Log.d(TAG, "requestZenModeConditions " + Condition.relevanceToString(relevance));
-        try {
-            mNoMan.requestZenModeConditions(mListener, relevance);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Error calling requestZenModeConditions", e);
-        }
-    }
-
-    protected void handleConditions(Condition[] conditions) {
-        for (final Condition c : conditions) {
-            CheckBox v = (CheckBox) findViewWithTag(c.id);
-            if (c.state != Condition.STATE_ERROR) {
-                if (v == null) {
-                    v = newCheckBox(c.id);
-                }
-            }
-            if (v != null) {
-                v.setText(c.summary);
-                v.setEnabled(c.state != Condition.STATE_ERROR);
-                v.setChecked(mSelectedConditions.contains(c.id));
-            }
-        }
-    }
-
-    private final IConditionListener mListener = new IConditionListener.Stub() {
-        @Override
-        public void onConditionsReceived(Condition[] conditions) {
-            if (conditions == null || conditions.length == 0) return;
-            mHandler.obtainMessage(H.CONDITIONS, conditions).sendToTarget();
-        }
-    };
-
-    private final class H extends Handler {
-        private static final int CONDITIONS = 1;
-
-        @Override
-        public void handleMessage(Message msg) {
-            if (msg.what == CONDITIONS) handleConditions((Condition[])msg.obj);
-        }
-    }
-}
diff --git a/src/com/android/settings/notification/ZenModeAutomationSettings.java b/src/com/android/settings/notification/ZenModeAutomationSettings.java
index 32ad3ce..c43d99e 100644
--- a/src/com/android/settings/notification/ZenModeAutomationSettings.java
+++ b/src/com/android/settings/notification/ZenModeAutomationSettings.java
@@ -16,247 +16,86 @@
 
 package com.android.settings.notification;
 
-import static com.android.settings.notification.ZenModeDowntimeDaysSelection.DAYS;
+import static android.service.notification.ZenModeConfig.ALL_DAYS;
 
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.app.FragmentManager;
-import android.app.INotificationManager;
-import android.app.TimePickerDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnDismissListener;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
+import android.content.Intent;
 import android.os.Bundle;
-import android.os.ServiceManager;
 import android.preference.Preference;
 import android.preference.Preference.OnPreferenceClickListener;
-import android.preference.PreferenceCategory;
 import android.preference.PreferenceScreen;
-import android.service.notification.Condition;
+import android.provider.Settings.Global;
 import android.service.notification.ZenModeConfig;
+import android.service.notification.ZenModeConfig.ScheduleInfo;
+import android.service.notification.ZenModeConfig.ZenRule;
 import android.text.format.DateFormat;
 import android.util.Log;
-import android.util.SparseArray;
-import android.widget.TimePicker;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.settings.DropDownPreference;
 import com.android.settings.R;
-import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settings.search.Indexable;
-import com.android.settings.search.SearchIndexableRaw;
 
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
 import java.util.Calendar;
-import java.util.List;
-import java.util.Objects;
+import java.util.TreeSet;
 
-public class ZenModeAutomationSettings extends ZenModeSettingsBase implements Indexable {
-    private static final String KEY_DOWNTIME = "downtime";
-    private static final String KEY_DAYS = "days";
-    private static final String KEY_START_TIME = "start_time";
-    private static final String KEY_END_TIME = "end_time";
-    private static final String KEY_DOWNTIME_MODE = "downtime_mode";
-
-    private static final String KEY_AUTOMATION = "automation";
-    private static final String KEY_ENTRY = "entry";
-    private static final String KEY_CONDITION_PROVIDERS = "manage_condition_providers";
-
+public class ZenModeAutomationSettings extends ZenModeSettingsBase {
     private static final SimpleDateFormat DAY_FORMAT = new SimpleDateFormat("EEE");
 
-    private PackageManager mPM;
-    private boolean mDisableListeners;
-    private boolean mDowntimeSupported;
-
-    private Preference mDays;
-    private TimePickerPreference mStart;
-    private TimePickerPreference mEnd;
-    private DropDownPreference mDowntimeMode;
-    private PreferenceCategory mAutomationCategory;
-    private Preference mEntry;
-    private Preference mConditionProviders;
+    private final Calendar mCalendar = Calendar.getInstance();
 
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        mPM = mContext.getPackageManager();
+
+        setHasOptionsMenu(true);
 
         addPreferencesFromResource(R.xml.zen_mode_automation_settings);
-        final PreferenceScreen root = getPreferenceScreen();
-
-        onCreateDowntimeSettings(root);
-
-        mAutomationCategory = (PreferenceCategory) findPreference(KEY_AUTOMATION);
-        mEntry = findPreference(KEY_ENTRY);
-        mEntry.setOnPreferenceClickListener(new OnPreferenceClickListener() {
-            @Override
-            public boolean onPreferenceClick(Preference preference) {
-                new AlertDialog.Builder(mContext)
-                    .setTitle(R.string.zen_mode_entry_conditions_title)
-                    .setView(new ZenModeAutomaticConditionSelection(mContext))
-                    .setOnDismissListener(new OnDismissListener() {
-                        @Override
-                        public void onDismiss(DialogInterface dialog) {
-                            refreshAutomationSection();
-                        }
-                    })
-                    .setPositiveButton(R.string.dlg_ok, null)
-                    .show();
-                return true;
-            }
-        });
-        mConditionProviders = findPreference(KEY_CONDITION_PROVIDERS);
     }
 
-    private void onCreateDowntimeSettings(PreferenceScreen root) {
-        mDowntimeSupported = isDowntimeSupported(mContext);
-        if (!mDowntimeSupported) {
-            removePreference(KEY_DOWNTIME);
-            return;
-        }
-        mDays = root.findPreference(KEY_DAYS);
-        mDays.setOnPreferenceClickListener(new OnPreferenceClickListener() {
-            @Override
-            public boolean onPreferenceClick(Preference preference) {
-                new AlertDialog.Builder(mContext)
-                        .setTitle(R.string.zen_mode_downtime_days)
-                        .setView(new ZenModeDowntimeDaysSelection(mContext, mConfig.sleepMode) {
-                              @Override
-                              protected void onChanged(String mode) {
-                                  if (mDisableListeners) return;
-                                  if (Objects.equals(mode, mConfig.sleepMode)) return;
-                                  if (DEBUG) Log.d(TAG, "days.onChanged sleepMode=" + mode);
-                                  final ZenModeConfig newConfig = mConfig.copy();
-                                  newConfig.sleepMode = mode;
-                                  setZenModeConfig(newConfig);
-                              }
-                        })
-                        .setOnDismissListener(new OnDismissListener() {
-                            @Override
-                            public void onDismiss(DialogInterface dialog) {
-                                updateDays();
-                            }
-                        })
-                        .setPositiveButton(R.string.done_button, null)
-                        .show();
-                return true;
-            }
-        });
-
-        final FragmentManager mgr = getFragmentManager();
-
-        mStart = new TimePickerPreference(mContext, mgr);
-        mStart.setKey(KEY_START_TIME);
-        mStart.setTitle(R.string.zen_mode_start_time);
-        mStart.setCallback(new TimePickerPreference.Callback() {
-            @Override
-            public boolean onSetTime(int hour, int minute) {
-                if (mDisableListeners) return true;
-                if (!ZenModeConfig.isValidHour(hour)) return false;
-                if (!ZenModeConfig.isValidMinute(minute)) return false;
-                if (hour == mConfig.sleepStartHour && minute == mConfig.sleepStartMinute) {
-                    return true;
-                }
-                if (DEBUG) Log.d(TAG, "onPrefChange sleepStart h=" + hour + " m=" + minute);
-                final ZenModeConfig newConfig = mConfig.copy();
-                newConfig.sleepStartHour = hour;
-                newConfig.sleepStartMinute = minute;
-                return setZenModeConfig(newConfig);
-            }
-        });
-        root.addPreference(mStart);
-        mStart.setDependency(mDays.getKey());
-
-        mEnd = new TimePickerPreference(mContext, mgr);
-        mEnd.setKey(KEY_END_TIME);
-        mEnd.setTitle(R.string.zen_mode_end_time);
-        mEnd.setCallback(new TimePickerPreference.Callback() {
-            @Override
-            public boolean onSetTime(int hour, int minute) {
-                if (mDisableListeners) return true;
-                if (!ZenModeConfig.isValidHour(hour)) return false;
-                if (!ZenModeConfig.isValidMinute(minute)) return false;
-                if (hour == mConfig.sleepEndHour && minute == mConfig.sleepEndMinute) {
-                    return true;
-                }
-                if (DEBUG) Log.d(TAG, "onPrefChange sleepEnd h=" + hour + " m=" + minute);
-                final ZenModeConfig newConfig = mConfig.copy();
-                newConfig.sleepEndHour = hour;
-                newConfig.sleepEndMinute = minute;
-                return setZenModeConfig(newConfig);
-            }
-        });
-        root.addPreference(mEnd);
-        mEnd.setDependency(mDays.getKey());
-
-        mDowntimeMode = (DropDownPreference) root.findPreference(KEY_DOWNTIME_MODE);
-        mDowntimeMode.addItem(R.string.zen_mode_downtime_mode_priority, false);
-        mDowntimeMode.addItem(R.string.zen_mode_downtime_mode_none, true);
-        mDowntimeMode.setCallback(new DropDownPreference.Callback() {
-            @Override
-            public boolean onItemSelected(int pos, Object value) {
-                if (mDisableListeners) return true;
-                final boolean sleepNone = value instanceof Boolean ? ((Boolean) value) : false;
-                if (mConfig == null || mConfig.sleepNone == sleepNone) return false;
-                final ZenModeConfig newConfig = mConfig.copy();
-                newConfig.sleepNone = sleepNone;
-                if (DEBUG) Log.d(TAG, "onPrefChange sleepNone=" + sleepNone);
-                return setZenModeConfig(newConfig);
-            }
-        });
-        mDowntimeMode.setOrder(10);  // sort at the bottom of the category
-        mDowntimeMode.setDependency(mDays.getKey());
+    private void showRule(String ruleId, String ruleName) {
+        if (DEBUG) Log.d(TAG, "showRule " + ruleId + " name=" + ruleName);
+        mContext.startActivity(new Intent(ZenModeScheduleRuleSettings.ACTION)
+                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+                .putExtra(ZenModeScheduleRuleSettings.EXTRA_RULE_ID, ruleId));
     }
 
-    private void updateDays() {
-        // Compute an ordered, delimited list of day names based on the persisted user config.
-        if (mConfig != null) {
-            final int[] days = ZenModeConfig.tryParseDays(mConfig.sleepMode);
-            if (days != null && days.length != 0) {
-                final StringBuilder sb = new StringBuilder();
-                final Calendar c = Calendar.getInstance();
-                for (int i = 0; i < DAYS.length; i++) {
-                    final int day = DAYS[i];
-                    for (int j = 0; j < days.length; j++) {
-                        if (day == days[j]) {
-                            c.set(Calendar.DAY_OF_WEEK, day);
-                            if (sb.length() > 0) {
-                                sb.append(mContext.getString(R.string.summary_divider_text));
-                            }
-                            sb.append(DAY_FORMAT.format(c.getTime()));
-                            break;
-                        }
-                    }
-                }
-                if (sb.length() > 0) {
-                    mDays.setSummary(sb);
-                    mDays.notifyDependencyChange(false);
-                    return;
-                }
-            }
-        }
-        mDays.setSummary(R.string.zen_mode_downtime_days_none);
-        mDays.notifyDependencyChange(true);
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        inflater.inflate(R.menu.zen_mode_automation, menu);
     }
 
-    private void updateEndSummary() {
-        if (!mDowntimeSupported) return;
-        final int startMin = 60 * mConfig.sleepStartHour + mConfig.sleepStartMinute;
-        final int endMin = 60 * mConfig.sleepEndHour + mConfig.sleepEndMinute;
-        final boolean nextDay = startMin >= endMin;
-        final int summaryFormat;
-        if (mConfig.sleepNone) {
-            summaryFormat = nextDay ? R.string.zen_mode_end_time_none_next_day_summary_format
-                    : R.string.zen_mode_end_time_none_same_day_summary_format;
-        } else {
-            summaryFormat = nextDay ? R.string.zen_mode_end_time_priority_next_day_summary_format
-                    : 0;
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        if (item.getItemId() == R.id.add) {
+            showAddRuleDialog();
+            return true;
         }
-        mEnd.setSummaryFormat(summaryFormat);
+        return super.onOptionsItemSelected(item);
+    }
+
+    private void showAddRuleDialog() {
+        new ZenRuleNameDialog(mContext, "", mConfig.getAutomaticRuleNames()) {
+            @Override
+            public void onOk(String ruleName) {
+                final ScheduleInfo schedule = new ScheduleInfo();
+                schedule.days = ZenModeConfig.ALL_DAYS;
+                schedule.startHour = 22;
+                schedule.endHour = 7;
+                final ZenRule rule = new ZenRule();
+                rule.name = ruleName;
+                rule.enabled = true;
+                rule.zenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+                rule.conditionId = ZenModeConfig.toScheduleConditionId(schedule);
+                final ZenModeConfig newConfig = mConfig.copy();
+                final String ruleId = newConfig.newRuleId();
+                newConfig.automaticRules.put(ruleId, rule);
+                if (setZenModeConfig(newConfig)) {
+                    showRule(ruleId, rule.name);
+                }
+            }
+        }.show();
     }
 
     @Override
@@ -265,17 +104,38 @@
     }
 
     @Override
-    protected void updateControls() {
-        mDisableListeners = true;
-        if (mDowntimeSupported) {
-            updateDays();
-            mStart.setTime(mConfig.sleepStartHour, mConfig.sleepStartMinute);
-            mEnd.setTime(mConfig.sleepEndHour, mConfig.sleepEndMinute);
-            mDowntimeMode.setSelectedValue(mConfig.sleepNone);
+    protected void onZenModeConfigChanged() {
+        updateControls();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        updateControls();
+    }
+
+    private void updateControls() {
+        final PreferenceScreen root = getPreferenceScreen();
+        root.removeAll();
+
+        if (mConfig == null) return;
+        for (int i = 0; i < mConfig.automaticRules.size(); i++) {
+            final String id = mConfig.automaticRules.keyAt(i);
+            final ZenRule rule = mConfig.automaticRules.valueAt(i);
+            if (!ZenModeConfig.isValidScheduleConditionId(rule.conditionId)) continue;
+            final Preference p = new Preference(mContext);
+            p.setTitle(rule.name);
+            p.setSummary(computeRuleSummary(rule));
+            p.setPersistent(false);
+            p.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+                @Override
+                public boolean onPreferenceClick(Preference preference) {
+                    showRule(id, rule.name);
+                    return true;
+                }
+            });
+            root.addPreference(p);
         }
-        mDisableListeners = false;
-        refreshAutomationSection();
-        updateEndSummary();
     }
 
     @Override
@@ -283,171 +143,60 @@
         return MetricsLogger.NOTIFICATION_ZEN_MODE_AUTOMATION;
     }
 
-    private void refreshAutomationSection() {
-        if (mConditionProviders != null) {
-            final int total = ConditionProviderSettings.getProviderCount(mPM);
-            if (total == 0) {
-                getPreferenceScreen().removePreference(mAutomationCategory);
-            } else {
-                final int n = ConditionProviderSettings.getEnabledProviderCount(mContext);
-                if (n == 0) {
-                    mConditionProviders.setSummary(getResources().getString(
-                            R.string.manage_condition_providers_summary_zero));
-                } else {
-                    mConditionProviders.setSummary(String.format(getResources().getQuantityString(
-                            R.plurals.manage_condition_providers_summary_nonzero,
-                            n, n)));
-                }
-                final String entrySummary = getEntryConditionSummary();
-                if (n == 0 || entrySummary == null) {
-                    mEntry.setSummary(R.string.zen_mode_entry_conditions_summary_none);
-                } else {
-                    mEntry.setSummary(entrySummary);
-                }
-            }
-        }
+    private String computeRuleSummary(ZenRule rule) {
+        if (rule == null || !rule.enabled) return getString(R.string.switch_off_text);
+        final ScheduleInfo schedule = ZenModeConfig.tryParseScheduleConditionId(rule.conditionId);
+        if (schedule == null) return getString(R.string.switch_on_text);
+        final String days = computeContiguousDayRanges(schedule.days);
+        final String start = getTime(schedule.startHour, schedule.startMinute);
+        final String end = getTime(schedule.endHour, schedule.endMinute);
+        final String time = getString(R.string.summary_range_verbal_combination, start, end);
+        final String mode = ZenModeSettings.computeZenModeCaption(getResources(), rule.zenMode);
+        return getString(R.string.zen_mode_rule_summary_template, days, time, mode);
     }
 
-    private String getEntryConditionSummary() {
-        final INotificationManager nm = INotificationManager.Stub.asInterface(
-                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
-        try {
-            final Condition[] automatic = nm.getAutomaticZenModeConditions();
-            if (automatic == null || automatic.length == 0) {
-                return null;
-            }
-            final String divider = getString(R.string.summary_divider_text);
-            final StringBuilder sb = new StringBuilder();
-            for (int i = 0; i < automatic.length; i++) {
-                if (i > 0) sb.append(divider);
-                sb.append(automatic[i].summary);
-            }
-            return sb.toString();
-        } catch (Exception e) {
-            Log.w(TAG, "Error calling getAutomaticZenModeConditions", e);
-            return null;
-        }
+    private String getTime(int hour, int minute) {
+        mCalendar.set(Calendar.HOUR_OF_DAY, hour);
+        mCalendar.set(Calendar.MINUTE, minute);
+        return DateFormat.getTimeFormat(mContext).format(mCalendar.getTime());
     }
 
-    private static SparseArray<String> allKeyTitles(Context context) {
-        final SparseArray<String> rt = new SparseArray<String>();
-        rt.put(R.string.zen_mode_downtime_category, KEY_DOWNTIME);
-        rt.put(R.string.zen_mode_downtime_days, KEY_DAYS);
-        rt.put(R.string.zen_mode_start_time, KEY_START_TIME);
-        rt.put(R.string.zen_mode_end_time, KEY_END_TIME);
-        rt.put(R.string.zen_mode_downtime_mode_title, KEY_DOWNTIME_MODE);
-        rt.put(R.string.zen_mode_automation_category, KEY_AUTOMATION);
-        rt.put(R.string.manage_condition_providers, KEY_CONDITION_PROVIDERS);
+    private String computeContiguousDayRanges(int[] days) {
+        final TreeSet<Integer> daySet = new TreeSet<>();
+        for (int i = 0; days != null && i < days.length; i++) {
+            daySet.add(days[i]);
+        }
+        if (daySet.isEmpty()) {
+            return getString(R.string.zen_mode_schedule_rule_days_none);
+        }
+        final int N = ALL_DAYS.length;
+        if (daySet.size() == N) {
+            return getString(R.string.zen_mode_schedule_rule_days_all);
+        }
+        String rt = null;
+        for (int i = 0; i < N; i++) {
+            final int startDay = ALL_DAYS[i];
+            final boolean active = daySet.contains(startDay);
+            if (!active) continue;
+            int end = 0;
+            while (daySet.contains(ALL_DAYS[(i + end + 1) % N])) {
+                end++;
+            }
+            if (!(i == 0 && daySet.contains(ALL_DAYS[N - 1]))) {
+                final String v = end == 0 ? dayString(startDay)
+                        : getString(R.string.summary_range_symbol_combination,
+                                dayString(startDay),
+                                dayString(ALL_DAYS[(i + end) % N]));
+                rt = rt == null ? v : getString(R.string.summary_divider_text, rt, v);
+            }
+            i += end;
+        }
         return rt;
     }
 
-    // Enable indexing of searchable data
-    public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
-        new BaseSearchIndexProvider() {
-
-            @Override
-            public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
-                final SparseArray<String> keyTitles = allKeyTitles(context);
-                final int N = keyTitles.size();
-                final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>(N);
-                final Resources res = context.getResources();
-                for (int i = 0; i < N; i++) {
-                    final SearchIndexableRaw data = new SearchIndexableRaw(context);
-                    data.key = keyTitles.valueAt(i);
-                    data.title = res.getString(keyTitles.keyAt(i));
-                    data.screenTitle = res.getString(R.string.zen_mode_automation_settings_title);
-                    result.add(data);
-                }
-                return result;
-            }
-
-            @Override
-            public List<String> getNonIndexableKeys(Context context) {
-                final ArrayList<String> rt = new ArrayList<String>();
-                if (!isDowntimeSupported(context)) {
-                    rt.add(KEY_DOWNTIME);
-                    rt.add(KEY_DAYS);
-                    rt.add(KEY_START_TIME);
-                    rt.add(KEY_END_TIME);
-                    rt.add(KEY_DOWNTIME_MODE);
-                }
-                return rt;
-            }
-        };
-
-    private static class TimePickerPreference extends Preference {
-        private final Context mContext;
-
-        private int mSummaryFormat;
-        private int mHourOfDay;
-        private int mMinute;
-        private Callback mCallback;
-
-        public TimePickerPreference(Context context, final FragmentManager mgr) {
-            super(context);
-            mContext = context;
-            setPersistent(false);
-            setOnPreferenceClickListener(new OnPreferenceClickListener(){
-                @Override
-                public boolean onPreferenceClick(Preference preference) {
-                    final TimePickerFragment frag = new TimePickerFragment();
-                    frag.pref = TimePickerPreference.this;
-                    frag.show(mgr, TimePickerPreference.class.getName());
-                    return true;
-                }
-            });
-        }
-
-        public void setCallback(Callback callback) {
-            mCallback = callback;
-        }
-
-        public void setSummaryFormat(int resId) {
-            mSummaryFormat = resId;
-            updateSummary();
-        }
-
-        public void setTime(int hourOfDay, int minute) {
-            if (mCallback != null && !mCallback.onSetTime(hourOfDay, minute)) return;
-            mHourOfDay = hourOfDay;
-            mMinute = minute;
-            updateSummary();
-        }
-
-        private void updateSummary() {
-            final Calendar c = Calendar.getInstance();
-            c.set(Calendar.HOUR_OF_DAY, mHourOfDay);
-            c.set(Calendar.MINUTE, mMinute);
-            String time = DateFormat.getTimeFormat(mContext).format(c.getTime());
-            if (mSummaryFormat != 0) {
-                time = mContext.getResources().getString(mSummaryFormat, time);
-            }
-            setSummary(time);
-        }
-
-        public static class TimePickerFragment extends DialogFragment implements
-                TimePickerDialog.OnTimeSetListener {
-            public TimePickerPreference pref;
-
-            @Override
-            public Dialog onCreateDialog(Bundle savedInstanceState) {
-                final boolean usePref = pref != null && pref.mHourOfDay >= 0 && pref.mMinute >= 0;
-                final Calendar c = Calendar.getInstance();
-                final int hour = usePref ? pref.mHourOfDay : c.get(Calendar.HOUR_OF_DAY);
-                final int minute = usePref ? pref.mMinute : c.get(Calendar.MINUTE);
-                return new TimePickerDialog(getActivity(), this, hour, minute,
-                        DateFormat.is24HourFormat(getActivity()));
-            }
-
-            public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
-                if (pref != null) {
-                    pref.setTime(hourOfDay, minute);
-                }
-            }
-        }
-
-        public interface Callback {
-            boolean onSetTime(int hour, int minute);
-        }
+    private String dayString(int day) {
+        mCalendar.set(Calendar.DAY_OF_WEEK, day);
+        return DAY_FORMAT.format(mCalendar.getTime());
     }
+
 }
diff --git a/src/com/android/settings/notification/ZenModeConditionSelection.java b/src/com/android/settings/notification/ZenModeConditionSelection.java
index 87f55a3..481bd88 100644
--- a/src/com/android/settings/notification/ZenModeConditionSelection.java
+++ b/src/com/android/settings/notification/ZenModeConditionSelection.java
@@ -27,7 +27,6 @@
 import android.service.notification.Condition;
 import android.service.notification.IConditionListener;
 import android.service.notification.ZenModeConfig;
-import android.text.TextUtils;
 import android.util.Log;
 import android.widget.CompoundButton;
 import android.widget.RadioButton;
@@ -46,11 +45,14 @@
     private final H mHandler = new H();
     private final Context mContext;
     private final List<Condition> mConditions;
+    private final int mZenMode;
+
     private Condition mCondition;
 
-    public ZenModeConditionSelection(Context context) {
+    public ZenModeConditionSelection(Context context, int zenMode) {
         super(context);
         mContext = context;
+        mZenMode = zenMode;
         mConditions = new ArrayList<Condition>();
         setLayoutTransition(new LayoutTransition());
         final int p = mContext.getResources().getDimensionPixelSize(R.dimen.content_margin_left);
@@ -117,7 +119,7 @@
             }
         }
         if (v != null) {
-            v.setText(!TextUtils.isEmpty(c.line1) ? c.line1 : c.summary);
+            v.setText(ZenModeSettings.computeConditionText(c));
             v.setEnabled(c.state == Condition.STATE_TRUE);
         }
         mConditions.add(c);
@@ -131,7 +133,7 @@
     public void confirmCondition() {
         if (DEBUG) Log.d(TAG, "confirmCondition " + mCondition);
         try {
-            mNoMan.setZenModeCondition(mCondition);
+            mNoMan.setZenMode(mZenMode, mCondition != null ? mCondition.id : null, TAG);
         } catch (RemoteException e) {
             // noop
         }
diff --git a/src/com/android/settings/notification/ZenModePrioritySettings.java b/src/com/android/settings/notification/ZenModePrioritySettings.java
index 062c12a..89e9ea3 100644
--- a/src/com/android/settings/notification/ZenModePrioritySettings.java
+++ b/src/com/android/settings/notification/ZenModePrioritySettings.java
@@ -35,6 +35,7 @@
     private static final String KEY_MESSAGES = "messages";
     private static final String KEY_CALLS = "calls";
     private static final String KEY_STARRED = "starred";
+    private static final String KEY_REPEAT_CALLERS = "repeat_callers";
 
     private boolean mDisableListeners;
     private SwitchPreference mReminders;
@@ -42,6 +43,7 @@
     private SwitchPreference mMessages;
     private SwitchPreference mCalls;
     private DropDownPreference mStarred;
+    private SwitchPreference mRepeatCallers;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -123,6 +125,23 @@
             }
         });
 
+        mRepeatCallers = (SwitchPreference) root.findPreference(KEY_REPEAT_CALLERS);
+        mRepeatCallers.setSummary(mContext.getString(R.string.zen_mode_repeat_callers_summary,
+                mContext.getResources().getInteger(com.android.internal.R.integer
+                        .config_zen_repeat_callers_threshold)));
+        mRepeatCallers.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+            @Override
+            public boolean onPreferenceChange(Preference preference, Object newValue) {
+                if (mDisableListeners) return true;
+                final boolean val = (Boolean) newValue;
+                if (val == mConfig.allowRepeatCallers) return true;
+                if (DEBUG) Log.d(TAG, "onPrefChange allowRepeatCallers=" + val);
+                final ZenModeConfig newConfig = mConfig.copy();
+                newConfig.allowRepeatCallers = val;
+                return setZenModeConfig(newConfig);
+            }
+        });
+
         updateControls();
     }
 
@@ -132,16 +151,23 @@
     }
 
     @Override
-    protected void updateControls() {
+    protected void onZenModeConfigChanged() {
+        updateControls();
+    }
+
+    private void updateControls() {
         mDisableListeners = true;
         if (mCalls != null) {
             mCalls.setChecked(mConfig.allowCalls);
         }
         mMessages.setChecked(mConfig.allowMessages);
         mStarred.setSelectedValue(mConfig.allowFrom);
+        mStarred.setEnabled(mConfig.allowCalls || mConfig.allowMessages);
         mReminders.setChecked(mConfig.allowReminders);
         mEvents.setChecked(mConfig.allowEvents);
-        updateStarredEnabled();
+        mRepeatCallers.setChecked(mConfig.allowRepeatCallers);
+        mRepeatCallers.setEnabled(!mConfig.allowCalls
+                || mConfig.allowFrom != ZenModeConfig.SOURCE_ANYONE);
         mDisableListeners = false;
     }
 
@@ -150,8 +176,4 @@
         return MetricsLogger.NOTIFICATION_ZEN_MODE_PRIORITY;
     }
 
-    private void updateStarredEnabled() {
-        mStarred.setEnabled(mConfig.allowCalls || mConfig.allowMessages);
-    }
-
 }
diff --git a/src/com/android/settings/notification/ZenModeDowntimeDaysSelection.java b/src/com/android/settings/notification/ZenModeScheduleDaysSelection.java
similarity index 73%
rename from src/com/android/settings/notification/ZenModeDowntimeDaysSelection.java
rename to src/com/android/settings/notification/ZenModeScheduleDaysSelection.java
index 3361ad0..6d11ffb 100644
--- a/src/com/android/settings/notification/ZenModeDowntimeDaysSelection.java
+++ b/src/com/android/settings/notification/ZenModeScheduleDaysSelection.java
@@ -17,37 +17,42 @@
 package com.android.settings.notification;
 
 import android.content.Context;
-import android.service.notification.ZenModeConfig;
 import android.util.SparseBooleanArray;
 import android.view.LayoutInflater;
 import android.widget.CheckBox;
 import android.widget.CompoundButton;
-import android.widget.ScrollView;
 import android.widget.CompoundButton.OnCheckedChangeListener;
 import android.widget.LinearLayout;
+import android.widget.ScrollView;
 
 import com.android.settings.R;
 
 import java.text.SimpleDateFormat;
+import java.util.Arrays;
 import java.util.Calendar;
 
-public class ZenModeDowntimeDaysSelection extends ScrollView {
+public class ZenModeScheduleDaysSelection extends ScrollView {
     public static final int[] DAYS = {
-        Calendar.MONDAY, Calendar.TUESDAY, Calendar.WEDNESDAY, Calendar.THURSDAY, Calendar.FRIDAY,
-        Calendar.SATURDAY, Calendar.SUNDAY
+        Calendar.SUNDAY,
+        Calendar.MONDAY,
+        Calendar.TUESDAY,
+        Calendar.WEDNESDAY,
+        Calendar.THURSDAY,
+        Calendar.FRIDAY,
+        Calendar.SATURDAY,
     };
     private static final SimpleDateFormat DAY_FORMAT = new SimpleDateFormat("EEEE");
 
     private final SparseBooleanArray mDays = new SparseBooleanArray();
     private final LinearLayout mLayout;
 
-    public ZenModeDowntimeDaysSelection(Context context, String mode) {
+    public ZenModeScheduleDaysSelection(Context context, int[] days) {
         super(context);
         mLayout = new LinearLayout(mContext);
-        final int hPad = context.getResources().getDimensionPixelSize(R.dimen.zen_downtime_margin);
+        final int hPad = context.getResources()
+                .getDimensionPixelSize(R.dimen.zen_schedule_day_margin);
         mLayout.setPadding(hPad, 0, hPad, 0);
         addView(mLayout);
-        final int[] days = ZenModeConfig.tryParseDays(mode);
         if (days != null) {
             for (int i = 0; i < days.length; i++) {
                 mDays.put(days[i], true);
@@ -58,7 +63,7 @@
         final LayoutInflater inflater = LayoutInflater.from(context);
         for (int i = 0; i < DAYS.length; i++) {
             final int day = DAYS[i];
-            final CheckBox checkBox = (CheckBox) inflater.inflate(R.layout.zen_downtime_day,
+            final CheckBox checkBox = (CheckBox) inflater.inflate(R.layout.zen_schedule_rule_day,
                     this, false);
             c.set(Calendar.DAY_OF_WEEK, day);
             checkBox.setText(DAY_FORMAT.format(c.getTime()));
@@ -67,30 +72,29 @@
                 @Override
                 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                     mDays.put(day, isChecked);
-                    onChanged(getMode());
+                    onChanged(getDays());
                 }
             });
             mLayout.addView(checkBox);
         }
     }
 
-    private String getMode() {
-        final StringBuilder sb = new StringBuilder(ZenModeConfig.SLEEP_MODE_DAYS_PREFIX);
-        boolean empty = true;
+    private int[] getDays() {
+        final SparseBooleanArray rt = new SparseBooleanArray(mDays.size());
         for (int i = 0; i < mDays.size(); i++) {
             final int day = mDays.keyAt(i);
             if (!mDays.valueAt(i)) continue;
-            if (empty) {
-                empty = false;
-            } else {
-                sb.append(',');
-            }
-            sb.append(day);
+            rt.put(day, true);
         }
-        return empty ? null : sb.toString();
+        final int[] rta = new int[rt.size()];
+        for (int i = 0; i < rta.length; i++) {
+            rta[i] = rt.keyAt(i);
+        }
+        Arrays.sort(rta);
+        return rta;
     }
 
-    protected void onChanged(String mode) {
+    protected void onChanged(int[] days) {
         // event hook for subclasses
     }
 }
diff --git a/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
new file mode 100644
index 0000000..f0f0294
--- /dev/null
+++ b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
@@ -0,0 +1,477 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import static com.android.settings.notification.ZenModeScheduleDaysSelection.DAYS;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.FragmentManager;
+import android.app.TimePickerDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.DialogInterface.OnDismissListener;
+import android.content.Intent;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceScreen;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+import android.service.notification.ZenModeConfig;
+import android.service.notification.ZenModeConfig.ScheduleInfo;
+import android.service.notification.ZenModeConfig.ZenRule;
+import android.text.format.DateFormat;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.widget.Switch;
+import android.widget.TimePicker;
+import android.widget.Toast;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.settings.DropDownPreference;
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.widget.SwitchBar;
+
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Calendar;
+
+public class ZenModeScheduleRuleSettings extends ZenModeSettingsBase
+        implements SwitchBar.OnSwitchChangeListener {
+    private static final String TAG = ZenModeSettingsBase.TAG;
+    private static final boolean DEBUG = ZenModeSettingsBase.DEBUG;
+
+    private static final String KEY_RULE_NAME = "rule_name";
+    private static final String KEY_DAYS = "days";
+    private static final String KEY_START_TIME = "start_time";
+    private static final String KEY_END_TIME = "end_time";
+    private static final String KEY_ZEN_MODE = "zen_mode";
+
+    private static final SimpleDateFormat DAY_FORMAT = new SimpleDateFormat("EEE");
+
+    public static final String ACTION = Settings.ACTION_ZEN_MODE_SCHEDULE_RULE_SETTINGS;
+    public static final String EXTRA_RULE_ID = "rule_id";
+
+    private Context mContext;
+    private boolean mDisableListeners;
+    private SwitchBar mSwitchBar;
+    private Preference mRuleName;
+    private Preference mDays;
+    private TimePickerPreference mStart;
+    private TimePickerPreference mEnd;
+    private DropDownPreference mZenMode;
+
+    private String mRuleId;
+    private ZenRule mRule;
+    private ScheduleInfo mSchedule;
+    private boolean mDeleting;
+
+    @Override
+    protected void onZenModeChanged() {
+        // noop
+    }
+
+    @Override
+    protected void onZenModeConfigChanged() {
+        if (!refreshRuleOrFinish()) {
+            updateControls();
+        }
+    }
+
+    private boolean refreshRuleOrFinish() {
+        mRule = mConfig.automaticRules.get(mRuleId);
+        if (DEBUG) Log.d(TAG, "mRule=" + mRule);
+        mSchedule = mRule != null ? ZenModeConfig.tryParseScheduleConditionId(mRule.conditionId)
+                : null;
+        if (mSchedule == null) {
+            toastAndFinish();
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        if (DEBUG) Log.d(TAG, "onCreateOptionsMenu");
+        inflater.inflate(R.menu.zen_mode_rule, menu);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        if (DEBUG) Log.d(TAG, "onOptionsItemSelected " + item.getItemId());
+        if (item.getItemId() == R.id.delete) {
+            showDeleteRuleDialog();
+            return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mContext = getActivity();
+
+        final Intent intent = getActivity().getIntent();
+        if (DEBUG) Log.d(TAG, "onCreate getIntent()=" + intent);
+        if (intent == null) {
+            Log.w(TAG, "No intent");
+            toastAndFinish();
+            return;
+        }
+
+        mRuleId = intent.getStringExtra(EXTRA_RULE_ID);
+        if (DEBUG) Log.d(TAG, "mRuleId=" + mRuleId);
+        if (refreshRuleOrFinish()) {
+            return;
+        }
+
+        addPreferencesFromResource(R.xml.zen_mode_schedule_rule_settings);
+        final PreferenceScreen root = getPreferenceScreen();
+
+        setHasOptionsMenu(true);
+
+        mRuleName = root.findPreference(KEY_RULE_NAME);
+        mRuleName.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+            @Override
+            public boolean onPreferenceClick(Preference preference) {
+                showRuleNameDialog();
+                return true;
+            }
+        });
+
+        mDays = root.findPreference(KEY_DAYS);
+        mDays.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+            @Override
+            public boolean onPreferenceClick(Preference preference) {
+                showDaysDialog();
+                return true;
+            }
+        });
+
+        final FragmentManager mgr = getFragmentManager();
+
+        mStart = new TimePickerPreference(mContext, mgr);
+        mStart.setKey(KEY_START_TIME);
+        mStart.setTitle(R.string.zen_mode_start_time);
+        mStart.setCallback(new TimePickerPreference.Callback() {
+            @Override
+            public boolean onSetTime(final int hour, final int minute) {
+                if (mDisableListeners) return true;
+                if (!ZenModeConfig.isValidHour(hour)) return false;
+                if (!ZenModeConfig.isValidMinute(minute)) return false;
+                if (hour == mSchedule.startHour && minute == mSchedule.startMinute) {
+                    return true;
+                }
+                if (DEBUG) Log.d(TAG, "onPrefChange start h=" + hour + " m=" + minute);
+                mSchedule.startHour = hour;
+                mSchedule.startMinute = minute;
+                mRule.conditionId = ZenModeConfig.toScheduleConditionId(mSchedule);
+                mRule.condition = null;
+                mRule.snoozing = false;
+                setZenModeConfig(mConfig);
+                return true;
+            }
+        });
+        root.addPreference(mStart);
+        mStart.setDependency(mDays.getKey());
+
+        mEnd = new TimePickerPreference(mContext, mgr);
+        mEnd.setKey(KEY_END_TIME);
+        mEnd.setTitle(R.string.zen_mode_end_time);
+        mEnd.setCallback(new TimePickerPreference.Callback() {
+            @Override
+            public boolean onSetTime(final int hour, final int minute) {
+                if (mDisableListeners) return true;
+                if (!ZenModeConfig.isValidHour(hour)) return false;
+                if (!ZenModeConfig.isValidMinute(minute)) return false;
+                if (hour == mSchedule.endHour && minute == mSchedule.endMinute) {
+                    return true;
+                }
+                if (DEBUG) Log.d(TAG, "onPrefChange end h=" + hour + " m=" + minute);
+                mSchedule.endHour = hour;
+                mSchedule.endMinute = minute;
+                mRule.conditionId = ZenModeConfig.toScheduleConditionId(mSchedule);
+                mRule.condition = null;
+                mRule.snoozing = false;
+                setZenModeConfig(mConfig);
+                return true;
+            }
+        });
+        root.addPreference(mEnd);
+        mEnd.setDependency(mDays.getKey());
+
+        mZenMode = (DropDownPreference) root.findPreference(KEY_ZEN_MODE);
+        mZenMode.addItem(R.string.zen_mode_option_important_interruptions, Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+        mZenMode.addItem(R.string.zen_mode_option_alarms, Global.ZEN_MODE_ALARMS);
+        mZenMode.addItem(R.string.zen_mode_option_no_interruptions, Global.ZEN_MODE_NO_INTERRUPTIONS);
+        mZenMode.setCallback(new DropDownPreference.Callback() {
+            @Override
+            public boolean onItemSelected(int pos, Object value) {
+                if (mDisableListeners) return true;
+                final int zenMode = (Integer) value;
+                if (zenMode == mRule.zenMode) return true;
+                if (DEBUG) Log.d(TAG, "onPrefChange zenMode=" + zenMode);
+                mRule.zenMode = zenMode;
+                setZenModeConfig(mConfig);
+                return true;
+            }
+        });
+        mZenMode.setOrder(10);  // sort at the bottom of the category
+        mZenMode.setDependency(mDays.getKey());
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        final SettingsActivity activity = (SettingsActivity) getActivity();
+        mSwitchBar = activity.getSwitchBar();
+        mSwitchBar.addOnSwitchChangeListener(this);
+        mSwitchBar.show();
+    }
+
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        mSwitchBar.removeOnSwitchChangeListener(this);
+        mSwitchBar.hide();
+    }
+
+    @Override
+    public void onSwitchChanged(Switch switchView, boolean isChecked) {
+        if (DEBUG) Log.d(TAG, "onSwitchChanged " + isChecked);
+        if (mDisableListeners) return;
+        final boolean enabled = isChecked;
+        if (enabled == mRule.enabled) return;
+        if (DEBUG) Log.d(TAG, "onSwitchChanged enabled=" + enabled);
+        mRule.enabled = enabled;
+        mRule.snoozing = false;
+        setZenModeConfig(mConfig);
+    }
+
+    private void updateDays() {
+        // Compute an ordered, delimited list of day names based on the persisted user config.
+        final int[] days = mSchedule.days;
+        if (days != null && days.length > 0) {
+            final StringBuilder sb = new StringBuilder();
+            final Calendar c = Calendar.getInstance();
+            for (int i = 0; i < DAYS.length; i++) {
+                final int day = DAYS[i];
+                for (int j = 0; j < days.length; j++) {
+                    if (day == days[j]) {
+                        c.set(Calendar.DAY_OF_WEEK, day);
+                        if (sb.length() > 0) {
+                            sb.append(mContext.getString(R.string.summary_divider_text));
+                        }
+                        sb.append(DAY_FORMAT.format(c.getTime()));
+                        break;
+                    }
+                }
+            }
+            if (sb.length() > 0) {
+                mDays.setSummary(sb);
+                mDays.notifyDependencyChange(false);
+                return;
+            }
+        }
+        mDays.setSummary(R.string.zen_mode_schedule_rule_days_none);
+        mDays.notifyDependencyChange(true);
+    }
+
+    private void updateEndSummary() {
+        final int startMin = 60 * mSchedule.startHour + mSchedule.startMinute;
+        final int endMin = 60 * mSchedule.endHour + mSchedule.endMinute;
+        final boolean nextDay = startMin >= endMin;
+        final int summaryFormat = nextDay ? R.string.zen_mode_end_time_next_day_summary_format : 0;
+        mEnd.setSummaryFormat(summaryFormat);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        updateControls();
+    }
+
+    private void updateRuleName() {
+        getActivity().setTitle(mRule.name);
+        mRuleName.setSummary(mRule.name);
+    }
+
+    private void updateControls() {
+        mDisableListeners = true;
+        updateRuleName();
+        updateDays();
+        mStart.setTime(mSchedule.startHour, mSchedule.startMinute);
+        mEnd.setTime(mSchedule.endHour, mSchedule.endMinute);
+        mZenMode.setSelectedValue(mRule.zenMode);
+        mDisableListeners = false;
+        updateEndSummary();
+        if (mSwitchBar != null) {
+            mSwitchBar.setChecked(mRule.enabled);
+        }
+    }
+
+    @Override
+    protected int getMetricsCategory() {
+        return MetricsLogger.NOTIFICATION_ZEN_MODE_SCHEDULE_RULE;
+    }
+
+    private void showDeleteRuleDialog() {
+        new AlertDialog.Builder(mContext)
+                .setMessage(getString(R.string.zen_mode_delete_rule_confirmation, mRule.name))
+                .setNegativeButton(R.string.cancel, null)
+                .setPositiveButton(R.string.zen_mode_delete_rule_button, new OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        mDeleting = true;
+                        mConfig.automaticRules.remove(mRuleId);
+                        setZenModeConfig(mConfig);
+                    }
+                })
+                .show();
+    }
+
+    private void showRuleNameDialog() {
+        new ZenRuleNameDialog(mContext, mRule.name, mConfig.getAutomaticRuleNames()) {
+            @Override
+            public void onOk(String ruleName) {
+                final ZenModeConfig newConfig = mConfig.copy();
+                final ZenRule rule = newConfig.automaticRules.get(mRuleId);
+                if (rule == null) return;
+                rule.name = ruleName;
+                setZenModeConfig(newConfig);
+            }
+        }.show();
+    }
+
+    private void showDaysDialog() {
+        new AlertDialog.Builder(mContext)
+                .setTitle(R.string.zen_mode_schedule_rule_days)
+                .setView(new ZenModeScheduleDaysSelection(mContext, mSchedule.days) {
+                      @Override
+                      protected void onChanged(final int[] days) {
+                          if (mDisableListeners) return;
+                          if (Arrays.equals(days, mSchedule.days)) return;
+                          if (DEBUG) Log.d(TAG, "days.onChanged days=" + Arrays.asList(days));
+                          mSchedule.days = days;
+                          mRule.conditionId = ZenModeConfig.toScheduleConditionId(mSchedule);
+                          mRule.condition = null;
+                          mRule.snoozing = false;
+                          setZenModeConfig(mConfig);
+                      }
+                })
+                .setOnDismissListener(new OnDismissListener() {
+                    @Override
+                    public void onDismiss(DialogInterface dialog) {
+                        updateDays();
+                    }
+                })
+                .setPositiveButton(R.string.done_button, null)
+                .show();
+    }
+
+    private void toastAndFinish() {
+        if (!mDeleting) {
+            Toast.makeText(mContext, R.string.zen_mode_rule_not_found_text, Toast.LENGTH_SHORT)
+                    .show();
+        }
+        getActivity().finish();
+    }
+
+    private static class TimePickerPreference extends Preference {
+        private final Context mContext;
+
+        private int mSummaryFormat;
+        private int mHourOfDay;
+        private int mMinute;
+        private Callback mCallback;
+
+        public TimePickerPreference(Context context, final FragmentManager mgr) {
+            super(context);
+            mContext = context;
+            setPersistent(false);
+            setOnPreferenceClickListener(new OnPreferenceClickListener(){
+                @Override
+                public boolean onPreferenceClick(Preference preference) {
+                    final TimePickerFragment frag = new TimePickerFragment();
+                    frag.pref = TimePickerPreference.this;
+                    frag.show(mgr, TimePickerPreference.class.getName());
+                    return true;
+                }
+            });
+        }
+
+        public void setCallback(Callback callback) {
+            mCallback = callback;
+        }
+
+        public void setSummaryFormat(int resId) {
+            mSummaryFormat = resId;
+            updateSummary();
+        }
+
+        public void setTime(int hourOfDay, int minute) {
+            if (mCallback != null && !mCallback.onSetTime(hourOfDay, minute)) return;
+            mHourOfDay = hourOfDay;
+            mMinute = minute;
+            updateSummary();
+        }
+
+        private void updateSummary() {
+            final Calendar c = Calendar.getInstance();
+            c.set(Calendar.HOUR_OF_DAY, mHourOfDay);
+            c.set(Calendar.MINUTE, mMinute);
+            String time = DateFormat.getTimeFormat(mContext).format(c.getTime());
+            if (mSummaryFormat != 0) {
+                time = mContext.getResources().getString(mSummaryFormat, time);
+            }
+            setSummary(time);
+        }
+
+        public static class TimePickerFragment extends DialogFragment implements
+                TimePickerDialog.OnTimeSetListener {
+            public TimePickerPreference pref;
+
+            @Override
+            public Dialog onCreateDialog(Bundle savedInstanceState) {
+                final boolean usePref = pref != null && pref.mHourOfDay >= 0 && pref.mMinute >= 0;
+                final Calendar c = Calendar.getInstance();
+                final int hour = usePref ? pref.mHourOfDay : c.get(Calendar.HOUR_OF_DAY);
+                final int minute = usePref ? pref.mMinute : c.get(Calendar.MINUTE);
+                return new TimePickerDialog(getActivity(), this, hour, minute,
+                        DateFormat.is24HourFormat(getActivity()));
+            }
+
+            public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
+                if (pref != null) {
+                    pref.setTime(hourOfDay, minute);
+                }
+            }
+        }
+
+        public interface Callback {
+            boolean onSetTime(int hour, int minute);
+        }
+    }
+}
diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java
index 47d1f5d..24774cb 100644
--- a/src/com/android/settings/notification/ZenModeSettings.java
+++ b/src/com/android/settings/notification/ZenModeSettings.java
@@ -21,54 +21,94 @@
 import android.content.DialogInterface;
 import android.content.res.Resources;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.preference.Preference;
 import android.preference.PreferenceScreen;
 import android.provider.Settings.Global;
+import android.service.notification.Condition;
+import android.service.notification.ZenModeConfig;
+import android.text.TextUtils;
+import android.util.Log;
 import android.util.SparseArray;
 import android.widget.ScrollView;
+import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.SettingsActivity;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 import com.android.settings.search.SearchIndexableRaw;
+import com.android.settings.widget.SwitchBar;
 
 import java.util.ArrayList;
 import java.util.List;
 
-public class ZenModeSettings extends ZenModeSettingsBase implements Indexable {
-    private static final String KEY_ZEN_MODE = "zen_mode";
+public class ZenModeSettings extends ZenModeSettingsBase
+        implements Indexable, SwitchBar.OnSwitchChangeListener {
     private static final String KEY_PRIORITY_SETTINGS = "priority_settings";
     private static final String KEY_AUTOMATION_SETTINGS = "automation_settings";
 
-    private static final SettingPrefWithCallback PREF_ZEN_MODE = new SettingPrefWithCallback(
-            SettingPref.TYPE_GLOBAL, KEY_ZEN_MODE, Global.ZEN_MODE, Global.ZEN_MODE_OFF,
-            Global.ZEN_MODE_OFF, Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, Global.ZEN_MODE_ALARMS,
-            Global.ZEN_MODE_NO_INTERRUPTIONS) {
-        protected String getCaption(Resources res, int value) {
-            switch (value) {
-                case Global.ZEN_MODE_NO_INTERRUPTIONS:
-                    return res.getString(R.string.zen_mode_option_no_interruptions);
-                case Global.ZEN_MODE_ALARMS:
-                    return res.getString(R.string.zen_mode_option_alarms);
-                case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
-                    return res.getString(R.string.zen_mode_option_important_interruptions);
-                default:
-                    return res.getString(R.string.zen_mode_option_off);
-            }
-        }
-    };
-
     private Preference mPrioritySettings;
     private AlertDialog mDialog;
+    private SwitchBar mSwitchBar;
+    private boolean mShowing;
+    private boolean mUpdatingControls;
 
-    private static SparseArray<String> allKeyTitles(Context context) {
-        final SparseArray<String> rt = new SparseArray<String>();
-        rt.put(R.string.zen_mode_option_title, KEY_ZEN_MODE);
-        rt.put(R.string.zen_mode_priority_settings_title, KEY_PRIORITY_SETTINGS);
-        rt.put(R.string.zen_mode_automation_settings_title, KEY_AUTOMATION_SETTINGS);
-        return rt;
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        addPreferencesFromResource(R.xml.zen_mode_settings);
+        final PreferenceScreen root = getPreferenceScreen();
+
+        mPrioritySettings = root.findPreference(KEY_PRIORITY_SETTINGS);
+        if (!isScheduleSupported(mContext)) {
+            removePreference(KEY_AUTOMATION_SETTINGS);
+        }
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        final SettingsActivity activity = (SettingsActivity) getActivity();
+        mSwitchBar = activity.getSwitchBar();
+        mSwitchBar.addOnSwitchChangeListener(this);
+        mSwitchBar.show();
+    }
+
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        mSwitchBar.removeOnSwitchChangeListener(this);
+        mSwitchBar.hide();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        updateControls();
+        mShowing = true;
+    }
+
+    @Override
+    public void onPause() {
+        mShowing = false;
+        super.onPause();
+    }
+
+    @Override
+    public void onSwitchChanged(Switch switchView, boolean isChecked) {
+        if (DEBUG) Log.d(TAG, "onSwitchChanged " + isChecked + " mShowing=" + mShowing
+                + " mUpdatingControls=" + mUpdatingControls);
+        if (!mShowing || mUpdatingControls) return; // not from the user
+        if (isChecked) {
+            setZenMode(Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, null);
+            showConditionSelection(Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+        } else {
+            setZenMode(Global.ZEN_MODE_OFF, null);
+        }
     }
 
     @Override
@@ -78,44 +118,52 @@
 
     @Override
     protected void onZenModeChanged() {
-        PREF_ZEN_MODE.update(mContext);
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        addPreferencesFromResource(R.xml.zen_mode_settings);
-        final PreferenceScreen root = getPreferenceScreen();
-
-        PREF_ZEN_MODE.init(this);
-        PREF_ZEN_MODE.setCallback(new SettingPrefWithCallback.Callback() {
-            @Override
-            public void onSettingSelected(int value) {
-                if (value != Global.ZEN_MODE_OFF) {
-                    showConditionSelection(value);
-                }
-            }
-        });
-
-        mPrioritySettings = root.findPreference(KEY_PRIORITY_SETTINGS);
-        if (!isDowntimeSupported(mContext)) {
-            removePreference(KEY_AUTOMATION_SETTINGS);
-        }
-
         updateControls();
     }
 
     @Override
-    protected void updateControls() {
+    protected void onZenModeConfigChanged() {
+        updateControls();
+    }
+
+    public static String computeZenModeCaption(Resources res, int zenMode) {
+        switch (zenMode) {
+            case Global.ZEN_MODE_ALARMS:
+                return res.getString(R.string.zen_mode_option_alarms);
+            case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
+                return res.getString(R.string.zen_mode_option_important_interruptions);
+            case Global.ZEN_MODE_NO_INTERRUPTIONS:
+                return res.getString(R.string.zen_mode_option_no_interruptions);
+            default:
+                return null;
+        }
+    }
+
+    private String computeZenModeSummaryLine() {
+        final String caption = computeZenModeCaption(getResources(), mZenMode);
+        if (caption == null) return null;  // zen mode off
+        final String conditionText = ZenModeConfig.getConditionLine1(mContext, mConfig,
+                UserHandle.myUserId());
+        return getString(R.string.zen_mode_summary_combination, caption, conditionText);
+    }
+
+    private void updateControls() {
+        if (mSwitchBar != null) {
+            final String summaryLine = computeZenModeSummaryLine();
+            mUpdatingControls = true;
+            mSwitchBar.setChecked(summaryLine != null);
+            mUpdatingControls = false;
+            mSwitchBar.setSummary(summaryLine);
+        }
         updatePrioritySettingsSummary();
     }
 
     private void updatePrioritySettingsSummary() {
+        final boolean callers = mConfig.allowCalls || mConfig.allowRepeatCallers;
         String s = getResources().getString(R.string.zen_mode_alarms);
         s = appendLowercase(s, mConfig.allowReminders, R.string.zen_mode_reminders);
         s = appendLowercase(s, mConfig.allowEvents, R.string.zen_mode_events);
-        s = appendLowercase(s, mConfig.allowCalls, R.string.zen_mode_calls);
+        s = appendLowercase(s, callers, R.string.zen_mode_selected_callers);
         s = appendLowercase(s, mConfig.allowMessages, R.string.zen_mode_messages);
         mPrioritySettings.setSummary(s);
     }
@@ -128,11 +176,11 @@
         return s;
     }
 
-    protected void showConditionSelection(final int newSettingsValue) {
+    protected void showConditionSelection(final int zenMode) {
         if (mDialog != null) return;
 
         final ZenModeConditionSelection zenModeConditionSelection =
-                new ZenModeConditionSelection(mContext);
+                new ZenModeConditionSelection(mContext, zenMode);
         DialogInterface.OnClickListener positiveListener = new DialogInterface.OnClickListener() {
             @Override
             public void onClick(DialogInterface dialog, int which) {
@@ -140,34 +188,47 @@
                 mDialog = null;
             }
         };
-        final int oldSettingsValue = PREF_ZEN_MODE.getValue(mContext);
         ScrollView scrollView = new ScrollView(mContext);
         scrollView.addView(zenModeConditionSelection);
         mDialog = new AlertDialog.Builder(getActivity())
-                .setTitle(PREF_ZEN_MODE.getCaption(getResources(), newSettingsValue))
+                .setTitle(computeZenModeCaption(getResources(), zenMode))
                 .setView(scrollView)
                 .setPositiveButton(R.string.okay, positiveListener)
-                .setNegativeButton(R.string.cancel_all_caps, new DialogInterface.OnClickListener() {
+                .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                     @Override
                     public void onClick(DialogInterface dialog, int which) {
-                        cancelDialog(oldSettingsValue);
+                        cancelDialog();
                     }
                 })
                 .setOnCancelListener(new DialogInterface.OnCancelListener() {
                     @Override
                     public void onCancel(DialogInterface dialog) {
-                        cancelDialog(oldSettingsValue);
+                        cancelDialog();
                     }
                 }).create();
         mDialog.show();
     }
 
-    protected void cancelDialog(int oldSettingsValue) {
-        // If not making a decision, reset drop down to current setting.
-        PREF_ZEN_MODE.setValueWithoutCallback(mContext, oldSettingsValue);
+    private void cancelDialog() {
+        if (DEBUG) Log.d(TAG, "cancelDialog");
+        // If not making a decision, reset zen to off.
+        setZenMode(Global.ZEN_MODE_OFF, null);
         mDialog = null;
     }
 
+    public static String computeConditionText(Condition c) {
+        return !TextUtils.isEmpty(c.line1) ? c.line1
+                : !TextUtils.isEmpty(c.summary) ? c.summary
+                : "";
+    }
+
+    private static SparseArray<String> allKeyTitles(Context context) {
+        final SparseArray<String> rt = new SparseArray<String>();
+        rt.put(R.string.zen_mode_priority_settings_title, KEY_PRIORITY_SETTINGS);
+        rt.put(R.string.zen_mode_automation_settings_title, KEY_AUTOMATION_SETTINGS);
+        return rt;
+    }
+
     // Enable indexing of searchable data
     public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
         new BaseSearchIndexProvider() {
@@ -191,64 +252,10 @@
             @Override
             public List<String> getNonIndexableKeys(Context context) {
                 final ArrayList<String> rt = new ArrayList<String>();
-                if (!isDowntimeSupported(context)) {
+                if (!isScheduleSupported(context)) {
                     rt.add(KEY_AUTOMATION_SETTINGS);
                 }
                 return rt;
             }
         };
-
-    private static class SettingPrefWithCallback extends SettingPref {
-
-        private Callback mCallback;
-        private int mValue;
-
-        public SettingPrefWithCallback(int type, String key, String setting, int def,
-                int... values) {
-            super(type, key, setting, def, values);
-        }
-
-        public void setCallback(Callback callback) {
-            mCallback = callback;
-        }
-
-        @Override
-        public void update(Context context) {
-            // Avoid callbacks from non-user changes.
-            mValue = getValue(context);
-            super.update(context);
-        }
-
-        @Override
-        protected boolean setSetting(Context context, int value) {
-            if (value == mValue) return true;
-            mValue = value;
-            if (mCallback != null) {
-                mCallback.onSettingSelected(value);
-            }
-            return super.setSetting(context, value);
-        }
-
-        @Override
-        public Preference init(SettingsPreferenceFragment settings) {
-            Preference ret = super.init(settings);
-            mValue = getValue(settings.getActivity());
-
-            return ret;
-        }
-
-        public boolean setValueWithoutCallback(Context context, int value) {
-            // Set the current value ahead of time, this way we won't trigger a callback.
-            mValue = value;
-            return putInt(mType, context.getContentResolver(), mSetting, value);
-        }
-
-        public int getValue(Context context) {
-            return getInt(mType, context.getContentResolver(), mSetting, mDefault);
-        }
-
-        public interface Callback {
-            void onSettingSelected(int value);
-        }
-    }
 }
diff --git a/src/com/android/settings/notification/ZenModeSettingsBase.java b/src/com/android/settings/notification/ZenModeSettingsBase.java
index ec17d86..9824dc7 100644
--- a/src/com/android/settings/notification/ZenModeSettingsBase.java
+++ b/src/com/android/settings/notification/ZenModeSettingsBase.java
@@ -16,14 +16,13 @@
 
 package com.android.settings.notification;
 
-import android.app.INotificationManager;
 import android.app.NotificationManager;
 import android.content.Context;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.ServiceManager;
+import android.provider.Settings;
 import android.provider.Settings.Global;
 import android.service.notification.ZenModeConfig;
 import android.util.Log;
@@ -41,23 +40,25 @@
 
     protected Context mContext;
     protected ZenModeConfig mConfig;
+    protected int mZenMode;
 
     abstract protected void onZenModeChanged();
-    abstract protected void updateControls();
+    abstract protected void onZenModeConfigChanged();
 
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         mContext = getActivity();
-        mConfig = getZenModeConfig();
+        updateZenMode(false /*fireChanged*/);
+        updateZenModeConfig(false /*fireChanged*/);
         if (DEBUG) Log.d(TAG, "Loaded mConfig=" + mConfig);
     }
 
     @Override
     public void onResume() {
         super.onResume();
-        mConfig = getZenModeConfig();
-        updateControls();
+        updateZenMode(true /*fireChanged*/);
+        updateZenModeConfig(true /*fireChanged*/);
         mSettingsObserver.register();
     }
 
@@ -67,45 +68,48 @@
         mSettingsObserver.unregister();
     }
 
-    protected boolean setZenModeConfig(ZenModeConfig config) {
-        final INotificationManager nm = INotificationManager.Stub.asInterface(
-                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
-        try {
-            final boolean success = nm.setZenModeConfig(config);
-            if (success) {
-                mConfig = config;
-                if (DEBUG) Log.d(TAG, "Saved mConfig=" + mConfig);
-                updateControls();
-            }
-            return success;
-        } catch (Exception e) {
-           Log.w(TAG, "Error calling NoMan", e);
-           return false;
+    private void updateZenMode(boolean fireChanged) {
+        final int zenMode = Settings.Global.getInt(getContentResolver(), Global.ZEN_MODE, mZenMode);
+        if (zenMode == mZenMode) return;
+        mZenMode = zenMode;
+        if (DEBUG) Log.d(TAG, "updateZenMode mZenMode=" + mZenMode);
+        if (fireChanged) {
+            onZenModeChanged();
         }
     }
 
-    protected static boolean isDowntimeSupported(Context context) {
-        return NotificationManager.from(context)
-                .isSystemConditionProviderEnabled(ZenModeConfig.DOWNTIME_PATH);
-    }
-
-    private void updateZenModeConfig() {
+    private void updateZenModeConfig(boolean fireChanged) {
         final ZenModeConfig config = getZenModeConfig();
         if (Objects.equals(config, mConfig)) return;
         mConfig = config;
         if (DEBUG) Log.d(TAG, "updateZenModeConfig mConfig=" + mConfig);
-        updateControls();
+        if (fireChanged) {
+            onZenModeConfigChanged();
+        }
+    }
+
+    protected boolean setZenModeConfig(ZenModeConfig config) {
+        final String reason = getClass().getSimpleName();
+        final boolean success = NotificationManager.from(mContext).setZenModeConfig(config, reason);
+        if (success) {
+            mConfig = config;
+            if (DEBUG) Log.d(TAG, "Saved mConfig=" + mConfig);
+            onZenModeConfigChanged();
+        }
+        return success;
+    }
+
+    protected void setZenMode(int zenMode, Uri conditionId) {
+        NotificationManager.from(mContext).setZenMode(zenMode, conditionId, TAG);
+    }
+
+    protected static boolean isScheduleSupported(Context context) {
+        return NotificationManager.from(context)
+                .isSystemConditionProviderEnabled(ZenModeConfig.SCHEDULE_PATH);
     }
 
     private ZenModeConfig getZenModeConfig() {
-        final INotificationManager nm = INotificationManager.Stub.asInterface(
-                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
-        try {
-            return nm.getZenModeConfig();
-        } catch (Exception e) {
-           Log.w(TAG, "Error calling NoMan", e);
-           return new ZenModeConfig();
-        }
+        return NotificationManager.from(mContext).getZenModeConfig();
     }
 
     private final class SettingsObserver extends ContentObserver {
@@ -129,10 +133,10 @@
         public void onChange(boolean selfChange, Uri uri) {
             super.onChange(selfChange, uri);
             if (ZEN_MODE_URI.equals(uri)) {
-                onZenModeChanged();
+                updateZenMode(true /*fireChanged*/);
             }
             if (ZEN_MODE_CONFIG_ETAG_URI.equals(uri)) {
-                updateZenModeConfig();
+                updateZenModeConfig(true /*fireChanged*/);
             }
         }
     }
diff --git a/src/com/android/settings/notification/ZenRuleNameDialog.java b/src/com/android/settings/notification/ZenRuleNameDialog.java
new file mode 100644
index 0000000..b0eaaec
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleNameDialog.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.util.ArraySet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.EditText;
+
+import com.android.settings.R;
+
+public abstract class ZenRuleNameDialog {
+    private final AlertDialog mDialog;
+    private final EditText mEditText;
+    private final ArraySet<String> mExistingNames;
+
+    public ZenRuleNameDialog(Context context, String ruleName, ArraySet<String> existingNames) {
+        final View v = LayoutInflater.from(context).inflate(R.layout.zen_rule_name, null, false);
+        mEditText = (EditText) v.findViewById(R.id.rule_name);
+        mEditText.setText(ruleName);
+        mEditText.setSelectAllOnFocus(true);
+        mDialog = new AlertDialog.Builder(context)
+                .setTitle(R.string.zen_mode_rule_name)
+                .setView(v)
+                .setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        onOk(trimmedText());
+                    }
+                })
+                .setNegativeButton(R.string.cancel, null)
+                .create();
+        mEditText.addTextChangedListener(new TextWatcher() {
+            @Override
+            public void onTextChanged(CharSequence s, int start, int before, int count) {
+                // noop
+            }
+
+            @Override
+            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+                // noop
+            }
+
+            @Override
+            public void afterTextChanged(Editable s) {
+                updatePositiveButton();
+            }
+        });
+        mExistingNames = new ArraySet<String>(existingNames.size());
+        for (String existingName : existingNames) {
+            mExistingNames.add(existingName.toLowerCase());
+        }
+    }
+
+    abstract public void onOk(String ruleName);
+
+    private String trimmedText() {
+        return mEditText.getText() == null ? null : mEditText.getText().toString().trim();
+    }
+
+    public void show() {
+        mDialog.show();
+        updatePositiveButton();
+    }
+
+    private void updatePositiveButton() {
+        final String name = trimmedText();
+        final boolean validName = !TextUtils.isEmpty(name)
+                && !mExistingNames.contains(name.toLowerCase());
+        mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(validName);
+    }
+
+}
\ No newline at end of file
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index 0ad9503..dae8860 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -24,11 +24,12 @@
 import com.android.settings.DeviceInfoSettings;
 import com.android.settings.DisplaySettings;
 import com.android.settings.HomeSettings;
-import com.android.settings.ScreenPinningSettings;
 import com.android.settings.PrivacySettings;
 import com.android.settings.R;
+import com.android.settings.ScreenPinningSettings;
 import com.android.settings.SecuritySettings;
 import com.android.settings.WallpaperTypeSettings;
+import com.android.settings.WifiCallingSettings;
 import com.android.settings.WirelessSettings;
 import com.android.settings.accessibility.AccessibilitySettings;
 import com.android.settings.applications.AdvancedAppSettings;
@@ -43,7 +44,6 @@
 import com.android.settings.net.DataUsageMeteredSettings;
 import com.android.settings.notification.NotificationSettings;
 import com.android.settings.notification.OtherSoundSettings;
-import com.android.settings.notification.ZenModeAutomationSettings;
 import com.android.settings.notification.ZenModePrioritySettings;
 import com.android.settings.notification.ZenModeSettings;
 import com.android.settings.print.PrintSettingsFragment;
@@ -53,7 +53,6 @@
 import com.android.settings.wifi.AdvancedWifiSettings;
 import com.android.settings.wifi.SavedAccessPointsWifiSettings;
 import com.android.settings.wifi.WifiSettings;
-import com.android.settings.WifiCallingSettings;
 
 import java.util.Collection;
 import java.util.HashMap;
@@ -171,13 +170,6 @@
                         ZenModePrioritySettings.class.getName(),
                         R.drawable.ic_settings_notifications));
 
-        sResMap.put(ZenModeAutomationSettings.class.getName(),
-                new SearchIndexableResource(
-                        Ranking.getRankForClassName(ZenModeAutomationSettings.class.getName()),
-                        NO_DATA_RES_ID,
-                        ZenModeAutomationSettings.class.getName(),
-                        R.drawable.ic_settings_notifications));
-
         sResMap.put(Memory.class.getName(),
                 new SearchIndexableResource(
                         Ranking.getRankForClassName(Memory.class.getName()),
diff --git a/src/com/android/settings/widget/SwitchBar.java b/src/com/android/settings/widget/SwitchBar.java
index 606ceaa..094b95f 100644
--- a/src/com/android/settings/widget/SwitchBar.java
+++ b/src/com/android/settings/widget/SwitchBar.java
@@ -20,15 +20,18 @@
 import android.content.res.TypedArray;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.SpannableStringBuilder;
+import android.text.TextUtils;
+import android.text.style.TextAppearanceSpan;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.CompoundButton;
 import android.widget.LinearLayout;
-
 import android.widget.Switch;
 import android.widget.TextView;
+
 import com.android.settings.R;
 
 import java.util.ArrayList;
@@ -46,8 +49,12 @@
         void onSwitchChanged(Switch switchView, boolean isChecked);
     }
 
+    private final TextAppearanceSpan mSummarySpan;
+
     private ToggleSwitch mSwitch;
     private TextView mTextView;
+    private String mLabel;
+    private String mSummary;
 
     private ArrayList<OnSwitchChangeListener> mSwitchChangeListeners =
             new ArrayList<OnSwitchChangeListener>();
@@ -78,7 +85,9 @@
         a.recycle();
 
         mTextView = (TextView) findViewById(R.id.switch_text);
-        mTextView.setText(R.string.switch_off_text);
+        mLabel = getResources().getString(R.string.switch_off_text);
+        mSummarySpan = new TextAppearanceSpan(mContext, R.style.TextAppearance_Small_SwitchBar);
+        updateText();
         ViewGroup.MarginLayoutParams lp = (MarginLayoutParams) mTextView.getLayoutParams();
         lp.setMarginStart(switchBarMarginStart);
 
@@ -103,7 +112,26 @@
     }
 
     public void setTextViewLabel(boolean isChecked) {
-        mTextView.setText(isChecked ? R.string.switch_on_text : R.string.switch_off_text);
+        mLabel = getResources()
+                .getString(isChecked ? R.string.switch_on_text : R.string.switch_off_text);
+        updateText();
+    }
+
+    public void setSummary(String summary) {
+        mSummary = summary;
+        updateText();
+    }
+
+    private void updateText() {
+        if (TextUtils.isEmpty(mSummary)) {
+            mTextView.setText(mLabel);
+            return;
+        }
+        final SpannableStringBuilder ssb = new SpannableStringBuilder(mLabel).append('\n');
+        final int start = ssb.length();
+        ssb.append(mSummary);
+        ssb.setSpan(mSummarySpan, start, ssb.length(), 0);
+        mTextView.setText(ssb);
     }
 
     public void setChecked(boolean checked) {
diff --git a/src/com/android/settings/wifi/WifiSetupActivity.java b/src/com/android/settings/wifi/WifiSetupActivity.java
index a60945f..155fd93 100644
--- a/src/com/android/settings/wifi/WifiSetupActivity.java
+++ b/src/com/android/settings/wifi/WifiSetupActivity.java
@@ -180,7 +180,7 @@
 
     @Override
     protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
-        resid = SetupWizardUtils.getTheme(getIntent(), resid);
+        resid = SetupWizardUtils.getTheme(getIntent());
         super.onApplyThemeResource(theme, resid, first);
     }