Split Sound & notification settings.

Bug: 25860852
Change-Id: If88daf6fd50b5abf86fb86f3590361f0118172a1
diff --git a/src/com/android/settings/InstrumentedFragment.java b/src/com/android/settings/InstrumentedFragment.java
index 5453d52..80e1131 100644
--- a/src/com/android/settings/InstrumentedFragment.java
+++ b/src/com/android/settings/InstrumentedFragment.java
@@ -29,6 +29,8 @@
     public static final int UNDECLARED = 100000;
 
     public static final int ACCESSIBILITY_TOGGLE_AUTOCLICK = UNDECLARED + 1;
+    public static final int SOUND = UNDECLARED + 2;
+    public static final int CONFIGURE_NOTIFICATION = UNDECLARED + 3;
 
     /**
      * Declare the view of this category.
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 46d24ae..4380d1e 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -105,7 +105,8 @@
     public static class ZenModeEventRuleSettingsActivity extends SettingsActivity { /* empty */ }
     public static class ZenModeExternalRuleSettingsActivity extends SettingsActivity { /* empty */ }
     public static class ZenModeVisualInterruptionSettingsActivity extends SettingsActivity { /* empty */}
-    public static class NotificationSettingsActivity extends SettingsActivity { /* empty */ }
+    public static class SoundSettingsActivity extends SettingsActivity { /* empty */ }
+    public static class ConfigureNotificationSettingsActivity extends SettingsActivity { /* empty */ }
     public static class NotificationAppListActivity extends SettingsActivity { /* empty */ }
     public static class AppNotificationSettingsActivity extends SettingsActivity { /* empty */ }
     public static class OtherSoundSettingsActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index fd4a493..809a740 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -82,8 +82,9 @@
 import com.android.settings.nfc.AndroidBeam;
 import com.android.settings.nfc.PaymentSettings;
 import com.android.settings.notification.AppNotificationSettings;
+import com.android.settings.notification.ConfigureNotificationSettings;
 import com.android.settings.notification.NotificationAccessSettings;
-import com.android.settings.notification.NotificationSettings;
+import com.android.settings.notification.SoundSettings;
 import com.android.settings.notification.NotificationStation;
 import com.android.settings.notification.OtherSoundSettings;
 import com.android.settings.notification.ZenAccessSettings;
@@ -211,7 +212,7 @@
             Settings.WirelessSettingsActivity.class.getName(),
             //device_section
             Settings.HomeSettingsActivity.class.getName(),
-            Settings.NotificationSettingsActivity.class.getName(),
+            Settings.SoundSettingsActivity.class.getName(),
             Settings.DisplaySettingsActivity.class.getName(),
             Settings.StorageSettingsActivity.class.getName(),
             Settings.ManageApplicationsActivity.class.getName(),
@@ -284,7 +285,8 @@
             PaymentSettings.class.getName(),
             KeyboardLayoutPickerFragment.class.getName(),
             ZenModeSettings.class.getName(),
-            NotificationSettings.class.getName(),
+            SoundSettings.class.getName(),
+            ConfigureNotificationSettings.class.getName(),
             ChooseLockPassword.ChooseLockPasswordFragment.class.getName(),
             ChooseLockPattern.ChooseLockPatternFragment.class.getName(),
             InstalledAppDetails.class.getName(),
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index 35ae427..a01e18d 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -67,6 +67,7 @@
 import com.android.settings.fuelgauge.HighPowerDetail;
 import com.android.settings.fuelgauge.PowerWhitelistBackend;
 import com.android.settings.notification.AppNotificationSettings;
+import com.android.settings.notification.ConfigureNotificationSettings;
 import com.android.settings.notification.NotificationBackend;
 import com.android.settings.notification.NotificationBackend.AppRow;
 import com.android.settingslib.applications.ApplicationsState;
@@ -523,7 +524,8 @@
         if (mOptionsMenu == null) {
             return;
         }
-        mOptionsMenu.findItem(R.id.advanced).setVisible(mListType == LIST_TYPE_MAIN);
+        mOptionsMenu.findItem(R.id.advanced).setVisible(
+                mListType == LIST_TYPE_MAIN || mListType == LIST_TYPE_NOTIFICATION);
 
         mOptionsMenu.findItem(R.id.sort_order_alpha).setVisible(mListType == LIST_TYPE_STORAGE
                 && mSortOrder != R.id.sort_order_alpha);
@@ -556,9 +558,15 @@
                 mResetAppsHelper.buildResetDialog();
                 return true;
             case R.id.advanced:
-                ((SettingsActivity) getActivity()).startPreferencePanel(
-                        AdvancedAppSettings.class.getName(), null, R.string.configure_apps,
-                        null, this, ADVANCED_SETTINGS);
+                if (mListType == LIST_TYPE_NOTIFICATION) {
+                    ((SettingsActivity) getActivity()).startPreferencePanel(
+                            ConfigureNotificationSettings.class.getName(), null,
+                            R.string.configure_notification_settings, null, this, ADVANCED_SETTINGS);
+                } else {
+                    ((SettingsActivity) getActivity()).startPreferencePanel(
+                            AdvancedAppSettings.class.getName(), null, R.string.configure_apps,
+                            null, this, ADVANCED_SETTINGS);
+                }
                 return true;
             default:
                 // Handle the home button
diff --git a/src/com/android/settings/notification/ConfigureNotificationSettings.java b/src/com/android/settings/notification/ConfigureNotificationSettings.java
new file mode 100644
index 0000000..4b438f0
--- /dev/null
+++ b/src/com/android/settings/notification/ConfigureNotificationSettings.java
@@ -0,0 +1,250 @@
+/**
+ * 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 com.android.internal.widget.LockPatternUtils;
+import com.android.settings.DropDownPreference;
+import com.android.settings.InstrumentedFragment;
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.Preference.OnPreferenceChangeListener;
+import android.support.v7.preference.TwoStatePreference;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+public class ConfigureNotificationSettings extends SettingsPreferenceFragment {
+    private static final String TAG = "ConfigNotiSettings";
+
+    private static final String KEY_NOTIFICATION_PULSE = "notification_pulse";
+    private static final String KEY_LOCK_SCREEN_NOTIFICATIONS = "lock_screen_notifications";
+
+    private final SettingsObserver mSettingsObserver = new SettingsObserver();
+
+    private Context mContext;
+
+    private TwoStatePreference mNotificationPulse;
+    private DropDownPreference mLockscreen;
+    private boolean mSecure;
+    private int mLockscreenSelectedValue;
+
+    @Override
+    protected int getMetricsCategory() {
+        return InstrumentedFragment.CONFIGURE_NOTIFICATION;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mContext = getActivity();
+        mSecure = new LockPatternUtils(getActivity()).isSecure(UserHandle.myUserId());
+
+        addPreferencesFromResource(R.xml.configure_notification_settings);
+
+        initPulse();
+        initLockscreenNotifications();
+
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        mSettingsObserver.register(true);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        mSettingsObserver.register(false);
+    }
+
+    // === Pulse notification light ===
+
+    private void initPulse() {
+        mNotificationPulse =
+                (TwoStatePreference) getPreferenceScreen().findPreference(KEY_NOTIFICATION_PULSE);
+        if (mNotificationPulse == null) {
+            Log.i(TAG, "Preference not found: " + KEY_NOTIFICATION_PULSE);
+            return;
+        }
+        if (!getResources()
+                .getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed)) {
+            getPreferenceScreen().removePreference(mNotificationPulse);
+        } else {
+            updatePulse();
+            mNotificationPulse.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+                @Override
+                public boolean onPreferenceChange(Preference preference, Object newValue) {
+                    final boolean val = (Boolean)newValue;
+                    return Settings.System.putInt(getContentResolver(),
+                            Settings.System.NOTIFICATION_LIGHT_PULSE,
+                            val ? 1 : 0);
+                }
+            });
+        }
+    }
+
+    private void updatePulse() {
+        if (mNotificationPulse == null) {
+            return;
+        }
+        try {
+            mNotificationPulse.setChecked(Settings.System.getInt(getContentResolver(),
+                    Settings.System.NOTIFICATION_LIGHT_PULSE) == 1);
+        } catch (Settings.SettingNotFoundException snfe) {
+            Log.e(TAG, Settings.System.NOTIFICATION_LIGHT_PULSE + " not found");
+        }
+    }
+
+    // === Lockscreen (public / private) notifications ===
+
+    private void initLockscreenNotifications() {
+        mLockscreen = (DropDownPreference) getPreferenceScreen().findPreference(
+                KEY_LOCK_SCREEN_NOTIFICATIONS);
+        if (mLockscreen == null) {
+            Log.i(TAG, "Preference not found: " + KEY_LOCK_SCREEN_NOTIFICATIONS);
+            return;
+        }
+
+        boolean isSecureNotificationsDisabled = isSecureNotificationsDisabled();
+        boolean isUnredactedNotificationsDisabled = isUnredactedNotificationsDisabled();
+        ArrayList<CharSequence> entries = new ArrayList<>();
+        ArrayList<CharSequence> values = new ArrayList<>();
+        if (!isSecureNotificationsDisabled && !isUnredactedNotificationsDisabled) {
+            entries.add(getString(R.string.lock_screen_notifications_summary_show));
+            values.add(Integer.toString(R.string.lock_screen_notifications_summary_show));
+        }
+        if (mSecure && !isSecureNotificationsDisabled) {
+            entries.add(getString(R.string.lock_screen_notifications_summary_hide));
+            values.add(Integer.toString(R.string.lock_screen_notifications_summary_hide));
+        }
+        entries.add(getString(R.string.lock_screen_notifications_summary_disable));
+        values.add(Integer.toString(R.string.lock_screen_notifications_summary_disable));
+
+        mLockscreen.setEntries(entries.toArray(new CharSequence[entries.size()]));
+        mLockscreen.setEntryValues(values.toArray(new CharSequence[values.size()]));
+        updateLockscreenNotifications();
+        if (mLockscreen.getEntries().length > 1) {
+            mLockscreen.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+                @Override
+                public boolean onPreferenceChange(Preference preference, Object newValue) {
+                    final int val = Integer.parseInt((String) newValue);
+                    if (val == mLockscreenSelectedValue) {
+                        return false;
+                    }
+                    final boolean enabled =
+                            val != R.string.lock_screen_notifications_summary_disable;
+                    final boolean show = val == R.string.lock_screen_notifications_summary_show;
+                    Settings.Secure.putInt(getContentResolver(),
+                            Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, show ? 1 : 0);
+                    Settings.Secure.putInt(getContentResolver(),
+                            Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, enabled ? 1 : 0);
+                    mLockscreenSelectedValue = val;
+                    return true;
+                }
+            });
+        } else {
+            // There is one or less option for the user, disable the drop down.
+            mLockscreen.setEnabled(false);
+        }
+    }
+
+    private boolean isSecureNotificationsDisabled() {
+        final DevicePolicyManager dpm =
+                (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
+        return dpm != null && (dpm.getKeyguardDisabledFeatures(null)
+                & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) != 0;
+    }
+
+    private boolean isUnredactedNotificationsDisabled() {
+        final DevicePolicyManager dpm =
+                (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
+        return dpm != null && (dpm.getKeyguardDisabledFeatures(null)
+                & DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) != 0;
+    }
+
+    private void updateLockscreenNotifications() {
+        if (mLockscreen == null) {
+            return;
+        }
+        final boolean enabled = getLockscreenNotificationsEnabled();
+        final boolean allowPrivate = !mSecure || getLockscreenAllowPrivateNotifications();
+        mLockscreenSelectedValue = !enabled ? R.string.lock_screen_notifications_summary_disable :
+                allowPrivate ? R.string.lock_screen_notifications_summary_show :
+                R.string.lock_screen_notifications_summary_hide;
+        mLockscreen.setValue(Integer.toString(mLockscreenSelectedValue));
+    }
+
+    private boolean getLockscreenNotificationsEnabled() {
+        return Settings.Secure.getInt(getContentResolver(),
+                Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0;
+    }
+
+    private boolean getLockscreenAllowPrivateNotifications() {
+        return Settings.Secure.getInt(getContentResolver(),
+                Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0) != 0;
+    }
+
+
+    // === Callbacks ===
+
+    private final class SettingsObserver extends ContentObserver {
+        private final Uri NOTIFICATION_LIGHT_PULSE_URI =
+                Settings.System.getUriFor(Settings.System.NOTIFICATION_LIGHT_PULSE);
+        private final Uri LOCK_SCREEN_PRIVATE_URI =
+                Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+        private final Uri LOCK_SCREEN_SHOW_URI =
+                Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS);
+
+        public SettingsObserver() {
+            super(new Handler());
+        }
+
+        public void register(boolean register) {
+            final ContentResolver cr = getContentResolver();
+            if (register) {
+                cr.registerContentObserver(NOTIFICATION_LIGHT_PULSE_URI, false, this);
+                cr.registerContentObserver(LOCK_SCREEN_PRIVATE_URI, false, this);
+                cr.registerContentObserver(LOCK_SCREEN_SHOW_URI, false, this);
+            } else {
+                cr.unregisterContentObserver(this);
+            }
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            super.onChange(selfChange, uri);
+            if (NOTIFICATION_LIGHT_PULSE_URI.equals(uri)) {
+                updatePulse();
+            }
+            if (LOCK_SCREEN_PRIVATE_URI.equals(uri) || LOCK_SCREEN_SHOW_URI.equals(uri)) {
+                updateLockscreenNotifications();
+            }
+        }
+    }
+}
diff --git a/src/com/android/settings/notification/NotificationSettings.java b/src/com/android/settings/notification/SoundSettings.java
similarity index 64%
rename from src/com/android/settings/notification/NotificationSettings.java
rename to src/com/android/settings/notification/SoundSettings.java
index 46935d0..9e27528 100644
--- a/src/com/android/settings/notification/NotificationSettings.java
+++ b/src/com/android/settings/notification/SoundSettings.java
@@ -16,8 +16,8 @@
 
 package com.android.settings.notification;
 
+import android.app.Activity;
 import android.app.NotificationManager;
-import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -37,7 +37,6 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.Vibrator;
 import android.preference.SeekBarVolumizer;
@@ -47,29 +46,27 @@
 import android.provider.Settings;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.Preference.OnPreferenceChangeListener;
-import android.support.v7.preference.PreferenceCategory;
 import android.support.v7.preference.TwoStatePreference;
 import android.util.Log;
 
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.settings.DropDownPreference;
+import com.android.settings.InstrumentedFragment;
 import com.android.settings.R;
 import com.android.settings.RingtonePreference;
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.Utils;
+import com.android.settings.dashboard.SummaryLoader;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 
+import java.text.NumberFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 
-public class NotificationSettings extends SettingsPreferenceFragment implements Indexable {
-    private static final String TAG = "NotificationSettings";
+public class SoundSettings extends SettingsPreferenceFragment implements Indexable {
+    private static final String TAG = "SoundSettings";
 
-    private static final String KEY_SOUND = "sound";
     private static final String KEY_MEDIA_VOLUME = "media_volume";
     private static final String KEY_ALARM_VOLUME = "alarm_volume";
     private static final String KEY_RING_VOLUME = "ring_volume";
@@ -78,11 +75,6 @@
     private static final String KEY_NOTIFICATION_RINGTONE = "notification_ringtone";
     private static final String KEY_VIBRATE_WHEN_RINGING = "vibrate_when_ringing";
     private static final String KEY_WIFI_DISPLAY = "wifi_display";
-    private static final String KEY_NOTIFICATION = "notification";
-    private static final String KEY_NOTIFICATION_PULSE = "notification_pulse";
-    private static final String KEY_LOCK_SCREEN_NOTIFICATIONS = "lock_screen_notifications";
-    private static final String KEY_NOTIFICATION_ACCESS = "manage_notification_access";
-    private static final String KEY_ZEN_ACCESS = "manage_zen_access";
     private static final String KEY_ZEN_MODE = "zen_mode";
 
     private static final String[] RESTRICTED_KEYS = {
@@ -90,7 +82,6 @@
         KEY_ALARM_VOLUME,
         KEY_RING_VOLUME,
         KEY_NOTIFICATION_VOLUME,
-        KEY_ZEN_ACCESS,
         KEY_ZEN_MODE,
     };
 
@@ -103,7 +94,6 @@
     private final ArrayList<VolumeSeekBarPreference> mVolumePrefs = new ArrayList<>();
 
     private Context mContext;
-    private PackageManager mPM;
     private boolean mVoiceCapable;
     private Vibrator mVibrator;
     private AudioManager mAudioManager;
@@ -112,12 +102,6 @@
     private Preference mPhoneRingtonePreference;
     private Preference mNotificationRingtonePreference;
     private TwoStatePreference mVibrateWhenRinging;
-    private TwoStatePreference mNotificationPulse;
-    private DropDownPreference mLockscreen;
-    private Preference mNotificationAccess;
-    private Preference mZenAccess;
-    private boolean mSecure;
-    private int mLockscreenSelectedValue;
     private ComponentName mSuppressor;
     private int mRingerMode = -1;
 
@@ -126,17 +110,15 @@
 
     @Override
     protected int getMetricsCategory() {
-        return MetricsLogger.NOTIFICATION;
+        return InstrumentedFragment.SOUND;
     }
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mContext = getActivity();
-        mPM = mContext.getPackageManager();
         mUserManager = UserManager.get(getContext());
         mVoiceCapable = Utils.isVoiceCapable(mContext);
-        mSecure = new LockPatternUtils(getActivity()).isSecure(UserHandle.myUserId());
 
         mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
         mVibrator = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE);
@@ -144,9 +126,8 @@
             mVibrator = null;
         }
 
-        addPreferencesFromResource(R.xml.notification_settings);
+        addPreferencesFromResource(R.xml.sound_settings);
 
-        final PreferenceCategory sound = (PreferenceCategory) findPreference(KEY_SOUND);
         initVolumePreference(KEY_MEDIA_VOLUME, AudioManager.STREAM_MUSIC,
                 com.android.internal.R.drawable.ic_audio_media_mute);
         initVolumePreference(KEY_ALARM_VOLUME, AudioManager.STREAM_ALARM,
@@ -155,25 +136,15 @@
             mRingOrNotificationPreference =
                     initVolumePreference(KEY_RING_VOLUME, AudioManager.STREAM_RING,
                             com.android.internal.R.drawable.ic_audio_ring_notif_mute);
-            sound.removePreference(sound.findPreference(KEY_NOTIFICATION_VOLUME));
+            removePreference(KEY_NOTIFICATION_VOLUME);
         } else {
             mRingOrNotificationPreference =
                     initVolumePreference(KEY_NOTIFICATION_VOLUME, AudioManager.STREAM_NOTIFICATION,
                             com.android.internal.R.drawable.ic_audio_ring_notif_mute);
-            sound.removePreference(sound.findPreference(KEY_RING_VOLUME));
+            removePreference(KEY_RING_VOLUME);
         }
-        initRingtones(sound);
-        initVibrateWhenRinging(sound);
-
-        final PreferenceCategory notification = (PreferenceCategory)
-                findPreference(KEY_NOTIFICATION);
-        initPulse(notification);
-        initLockscreenNotifications(notification);
-
-        mNotificationAccess = findPreference(KEY_NOTIFICATION_ACCESS);
-        refreshNotificationListeners();
-        mZenAccess = findPreference(KEY_ZEN_ACCESS);
-        refreshZenAccess();
+        initRingtones();
+        initVibrateWhenRinging();
         updateRingerMode();
         updateEffectsSuppressor();
     }
@@ -181,8 +152,6 @@
     @Override
     public void onResume() {
         super.onResume();
-        refreshNotificationListeners();
-        refreshZenAccess();
         lookupRingtoneNames();
         mSettingsObserver.register(true);
         mReceiver.register(true);
@@ -323,13 +292,14 @@
 
     // === Phone & notification ringtone ===
 
-    private void initRingtones(PreferenceCategory root) {
-        mPhoneRingtonePreference = root.findPreference(KEY_PHONE_RINGTONE);
+    private void initRingtones() {
+        mPhoneRingtonePreference = getPreferenceScreen().findPreference(KEY_PHONE_RINGTONE);
         if (mPhoneRingtonePreference != null && !mVoiceCapable) {
-            root.removePreference(mPhoneRingtonePreference);
+            getPreferenceScreen().removePreference(mPhoneRingtonePreference);
             mPhoneRingtonePreference = null;
         }
-        mNotificationRingtonePreference = root.findPreference(KEY_NOTIFICATION_RINGTONE);
+        mNotificationRingtonePreference =
+                getPreferenceScreen().findPreference(KEY_NOTIFICATION_RINGTONE);
     }
 
     private void lookupRingtoneNames() {
@@ -397,14 +367,15 @@
 
     // === Vibrate when ringing ===
 
-    private void initVibrateWhenRinging(PreferenceCategory root) {
-        mVibrateWhenRinging = (TwoStatePreference) root.findPreference(KEY_VIBRATE_WHEN_RINGING);
+    private void initVibrateWhenRinging() {
+        mVibrateWhenRinging =
+                (TwoStatePreference) getPreferenceScreen().findPreference(KEY_VIBRATE_WHEN_RINGING);
         if (mVibrateWhenRinging == null) {
             Log.i(TAG, "Preference not found: " + KEY_VIBRATE_WHEN_RINGING);
             return;
         }
         if (!mVoiceCapable) {
-            root.removePreference(mVibrateWhenRinging);
+            getPreferenceScreen().removePreference(mVibrateWhenRinging);
             mVibrateWhenRinging = null;
             return;
         }
@@ -427,164 +398,11 @@
                 Settings.System.VIBRATE_WHEN_RINGING, 0) != 0);
     }
 
-    // === Pulse notification light ===
-
-    private void initPulse(PreferenceCategory parent) {
-        mNotificationPulse = (TwoStatePreference) parent.findPreference(KEY_NOTIFICATION_PULSE);
-        if (mNotificationPulse == null) {
-            Log.i(TAG, "Preference not found: " + KEY_NOTIFICATION_PULSE);
-            return;
-        }
-        if (!getResources()
-                .getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed)) {
-            parent.removePreference(mNotificationPulse);
-        } else {
-            updatePulse();
-            mNotificationPulse.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
-                @Override
-                public boolean onPreferenceChange(Preference preference, Object newValue) {
-                    final boolean val = (Boolean)newValue;
-                    return Settings.System.putInt(getContentResolver(),
-                            Settings.System.NOTIFICATION_LIGHT_PULSE,
-                            val ? 1 : 0);
-                }
-            });
-        }
-    }
-
-    private void updatePulse() {
-        if (mNotificationPulse == null) {
-            return;
-        }
-        try {
-            mNotificationPulse.setChecked(Settings.System.getInt(getContentResolver(),
-                    Settings.System.NOTIFICATION_LIGHT_PULSE) == 1);
-        } catch (Settings.SettingNotFoundException snfe) {
-            Log.e(TAG, Settings.System.NOTIFICATION_LIGHT_PULSE + " not found");
-        }
-    }
-
-    // === Lockscreen (public / private) notifications ===
-
-    private void initLockscreenNotifications(PreferenceCategory parent) {
-        mLockscreen = (DropDownPreference) parent.findPreference(KEY_LOCK_SCREEN_NOTIFICATIONS);
-        if (mLockscreen == null) {
-            Log.i(TAG, "Preference not found: " + KEY_LOCK_SCREEN_NOTIFICATIONS);
-            return;
-        }
-
-        boolean isSecureNotificationsDisabled = isSecureNotificationsDisabled();
-        boolean isUnredactedNotificationsDisabled = isUnredactedNotificationsDisabled();
-        ArrayList<CharSequence> entries = new ArrayList<>();
-        ArrayList<CharSequence> values = new ArrayList<>();
-        if (!isSecureNotificationsDisabled && !isUnredactedNotificationsDisabled) {
-            entries.add(getString(R.string.lock_screen_notifications_summary_show));
-            values.add(Integer.toString(R.string.lock_screen_notifications_summary_show));
-        }
-        if (mSecure && !isSecureNotificationsDisabled) {
-            entries.add(getString(R.string.lock_screen_notifications_summary_hide));
-            values.add(Integer.toString(R.string.lock_screen_notifications_summary_hide));
-        }
-        entries.add(getString(R.string.lock_screen_notifications_summary_disable));
-        values.add(Integer.toString(R.string.lock_screen_notifications_summary_disable));
-
-        mLockscreen.setEntries(entries.toArray(new CharSequence[entries.size()]));
-        mLockscreen.setEntryValues(values.toArray(new CharSequence[values.size()]));
-        updateLockscreenNotifications();
-        if (mLockscreen.getEntries().length > 1) {
-            mLockscreen.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
-                @Override
-                public boolean onPreferenceChange(Preference preference, Object newValue) {
-                    final int val = Integer.parseInt((String) newValue);
-                    if (val == mLockscreenSelectedValue) {
-                        return false;
-                    }
-                    final boolean enabled =
-                            val != R.string.lock_screen_notifications_summary_disable;
-                    final boolean show = val == R.string.lock_screen_notifications_summary_show;
-                    Settings.Secure.putInt(getContentResolver(),
-                            Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, show ? 1 : 0);
-                    Settings.Secure.putInt(getContentResolver(),
-                            Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, enabled ? 1 : 0);
-                    mLockscreenSelectedValue = val;
-                    return true;
-                }
-            });
-        } else {
-            // There is one or less option for the user, disable the drop down.
-            mLockscreen.setEnabled(false);
-        }
-    }
-
-    private boolean isSecureNotificationsDisabled() {
-        final DevicePolicyManager dpm =
-                (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
-        return dpm != null && (dpm.getKeyguardDisabledFeatures(null)
-                & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) != 0;
-    }
-
-    private boolean isUnredactedNotificationsDisabled() {
-        final DevicePolicyManager dpm =
-                (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
-        return dpm != null && (dpm.getKeyguardDisabledFeatures(null)
-                & DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) != 0;
-    }
-
-    private void updateLockscreenNotifications() {
-        if (mLockscreen == null) {
-            return;
-        }
-        final boolean enabled = getLockscreenNotificationsEnabled();
-        final boolean allowPrivate = !mSecure || getLockscreenAllowPrivateNotifications();
-        mLockscreenSelectedValue = !enabled ? R.string.lock_screen_notifications_summary_disable :
-                allowPrivate ? R.string.lock_screen_notifications_summary_show :
-                R.string.lock_screen_notifications_summary_hide;
-        mLockscreen.setValue(Integer.toString(mLockscreenSelectedValue));
-    }
-
-    private boolean getLockscreenNotificationsEnabled() {
-        return Settings.Secure.getInt(getContentResolver(),
-                Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0;
-    }
-
-    private boolean getLockscreenAllowPrivateNotifications() {
-        return Settings.Secure.getInt(getContentResolver(),
-                Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0) != 0;
-    }
-
-    // === Notification listeners ===
-
-    private void refreshNotificationListeners() {
-        if (mNotificationAccess != null) {
-            final int n = NotificationAccessSettings.getEnabledListenersCount(mContext);
-            if (n == 0) {
-                mNotificationAccess.setSummary(getResources().getString(
-                        R.string.manage_notification_access_summary_zero));
-            } else {
-                mNotificationAccess.setSummary(String.format(getResources().getQuantityString(
-                        R.plurals.manage_notification_access_summary_nonzero,
-                        n, n)));
-            }
-        }
-    }
-
-    // === Zen access ===
-
-    private void refreshZenAccess() {
-        // noop for now
-    }
-
     // === Callbacks ===
 
     private final class SettingsObserver extends ContentObserver {
         private final Uri VIBRATE_WHEN_RINGING_URI =
                 Settings.System.getUriFor(Settings.System.VIBRATE_WHEN_RINGING);
-        private final Uri NOTIFICATION_LIGHT_PULSE_URI =
-                Settings.System.getUriFor(Settings.System.NOTIFICATION_LIGHT_PULSE);
-        private final Uri LOCK_SCREEN_PRIVATE_URI =
-                Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
-        private final Uri LOCK_SCREEN_SHOW_URI =
-                Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS);
 
         public SettingsObserver() {
             super(mHandler);
@@ -594,9 +412,6 @@
             final ContentResolver cr = getContentResolver();
             if (register) {
                 cr.registerContentObserver(VIBRATE_WHEN_RINGING_URI, false, this);
-                cr.registerContentObserver(NOTIFICATION_LIGHT_PULSE_URI, false, this);
-                cr.registerContentObserver(LOCK_SCREEN_PRIVATE_URI, false, this);
-                cr.registerContentObserver(LOCK_SCREEN_SHOW_URI, false, this);
             } else {
                 cr.unregisterContentObserver(this);
             }
@@ -608,12 +423,6 @@
             if (VIBRATE_WHEN_RINGING_URI.equals(uri)) {
                 updateVibrateWhenRinging();
             }
-            if (NOTIFICATION_LIGHT_PULSE_URI.equals(uri)) {
-                updatePulse();
-            }
-            if (LOCK_SCREEN_PRIVATE_URI.equals(uri) || LOCK_SCREEN_SHOW_URI.equals(uri)) {
-                updateLockscreenNotifications();
-            }
         }
     }
 
@@ -677,6 +486,57 @@
         }
     }
 
+    // === Summary ===
+
+    private static class SummaryProvider extends BroadcastReceiver
+            implements SummaryLoader.SummaryProvider {
+
+        private final Context mContext;
+        private final AudioManager mAudioManager;
+        private final SummaryLoader mSummaryLoader;
+        private final int maxVolume;
+
+        public SummaryProvider(Context context, SummaryLoader summaryLoader) {
+            mContext = context;
+            mSummaryLoader = summaryLoader;
+            mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+            maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_RING);
+        }
+
+        @Override
+        public void setListening(boolean listening) {
+            if (listening) {
+                IntentFilter filter = new IntentFilter();
+                filter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
+                filter.addAction(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
+                filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
+                filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
+                filter.addAction(AudioManager.STREAM_MUTE_CHANGED_ACTION);
+                filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED);
+                mContext.registerReceiver(this, filter);
+            } else {
+                mContext.unregisterReceiver(this);
+            }
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String percent =  NumberFormat.getPercentInstance().format(
+                    (double) mAudioManager.getStreamVolume(AudioManager.STREAM_RING) / maxVolume);
+            mSummaryLoader.setSummary(this,
+                    mContext.getString(R.string.sound_settings_summary, percent));
+        }
+    }
+
+    public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY
+            = new SummaryLoader.SummaryProviderFactory() {
+        @Override
+        public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,
+                SummaryLoader summaryLoader) {
+            return new SummaryProvider(activity, summaryLoader);
+        }
+    };
+
     // === Indexing ===
 
     public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
@@ -685,7 +545,7 @@
         public List<SearchIndexableResource> getXmlResourcesToIndex(
                 Context context, boolean enabled) {
             final SearchIndexableResource sir = new SearchIndexableResource(context);
-            sir.xmlResId = R.xml.notification_settings;
+            sir.xmlResId = R.xml.configure_notification_settings;
             return Arrays.asList(sir);
         }
 
diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java
index 39ec08c..3743396 100644
--- a/src/com/android/settings/notification/ZenModeSettings.java
+++ b/src/com/android/settings/notification/ZenModeSettings.java
@@ -18,26 +18,19 @@
 
 import android.app.NotificationManager;
 import android.app.NotificationManager.Policy;
-import android.content.Context;
-import android.content.res.Resources;
 import android.os.Bundle;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
-import android.util.SparseArray;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.settings.R;
-import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settings.search.Indexable;
-import com.android.settings.search.SearchIndexableRaw;
+import com.android.settings.SettingsActivity;
 
-import java.util.ArrayList;
-import java.util.List;
-
-public class ZenModeSettings extends ZenModeSettingsBase implements Indexable {
+public class ZenModeSettings extends ZenModeSettingsBase {
     private static final String KEY_PRIORITY_SETTINGS = "priority_settings";
-    private static final String KEY_AUTOMATION_SETTINGS = "automation_settings";
-    private static final String KEY_VISUAL_INTERRUPTIONS_SETTINGS = "visual_interruptions_settings";
 
     private Preference mPrioritySettings;
 
@@ -49,9 +42,6 @@
         final PreferenceScreen root = getPreferenceScreen();
 
         mPrioritySettings = root.findPreference(KEY_PRIORITY_SETTINGS);
-        if (!isScheduleSupported(mContext)) {
-            removePreference(KEY_AUTOMATION_SETTINGS);
-        }
     }
 
     @Override
@@ -79,6 +69,23 @@
         updatePrioritySettingsSummary();
     }
 
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        inflater.inflate(R.menu.zen_settings_menu, menu);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.zen_access:
+                ((SettingsActivity) getActivity()).startPreferencePanel(
+                            ZenAccessSettings.class.getCanonicalName(), null,
+                            R.string.manage_zen_access_title, null, this, 0);
+                return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
     private void updatePrioritySettingsSummary() {
         Policy policy = NotificationManager.from(mContext).getNotificationPolicy();
         String s = getResources().getString(R.string.zen_mode_alarms);
@@ -117,47 +124,8 @@
         return s;
     }
 
-    private static SparseArray<String> allKeyTitles() {
-        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);
-        rt.put(R.string.zen_mode_visual_interruptions_settings_title,
-                KEY_VISUAL_INTERRUPTIONS_SETTINGS);
-        return rt;
-    }
-
     @Override
     protected int getHelpResource() {
         return R.string.help_uri_interruptions;
     }
-
-    // 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();
-                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_settings_title);
-                    result.add(data);
-                }
-                return result;
-            }
-
-            @Override
-            public List<String> getNonIndexableKeys(Context context) {
-                final ArrayList<String> rt = new ArrayList<String>();
-                if (!isScheduleSupported(context)) {
-                    rt.add(KEY_AUTOMATION_SETTINGS);
-                }
-                return rt;
-            }
-        };
 }
diff --git a/src/com/android/settings/notification/ZenModeSettingsBase.java b/src/com/android/settings/notification/ZenModeSettingsBase.java
index 1a34062..4c8663f 100644
--- a/src/com/android/settings/notification/ZenModeSettingsBase.java
+++ b/src/com/android/settings/notification/ZenModeSettingsBase.java
@@ -122,11 +122,6 @@
         NotificationManager.from(mContext).setZenMode(zenMode, conditionId, TAG);
     }
 
-    protected static boolean isScheduleSupported(Context context) {
-        return NotificationManager.from(context)
-                .isSystemConditionProviderEnabled(ZenModeConfig.SCHEDULE_PATH);
-    }
-
     private List<AutomaticZenRule> getZenModeRules() {
         return NotificationManager.from(mContext).getAutomaticZenRules();
     }
diff --git a/src/com/android/settings/search/Ranking.java b/src/com/android/settings/search/Ranking.java
index 1f464df..4ac4fb8 100644
--- a/src/com/android/settings/search/Ranking.java
+++ b/src/com/android/settings/search/Ranking.java
@@ -42,8 +42,9 @@
 import com.android.settings.location.LocationSettings;
 import com.android.settings.location.ScanningSettings;
 import com.android.settings.net.DataUsageMeteredSettings;
-import com.android.settings.notification.NotificationSettings;
+import com.android.settings.notification.ConfigureNotificationSettings;
 import com.android.settings.notification.OtherSoundSettings;
+import com.android.settings.notification.SoundSettings;
 import com.android.settings.notification.ZenModeAutomationSettings;
 import com.android.settings.notification.ZenModePrioritySettings;
 import com.android.settings.notification.ZenModeSettings;
@@ -71,20 +72,21 @@
     public static final int RANK_DISPLAY = 7;
     public static final int RANK_WALLPAPER = 8;
     public static final int RANK_NOTIFICATIONS = 9;
-    public static final int RANK_APPS = 10;
-    public static final int RANK_STORAGE = 11;
-    public static final int RANK_POWER_USAGE = 12;
-    public static final int RANK_USERS = 13;
-    public static final int RANK_LOCATION = 14;
-    public static final int RANK_SECURITY = 15;
-    public static final int RANK_ACCOUNT = 16;
-    public static final int RANK_IME = 17;
-    public static final int RANK_PRIVACY = 18;
-    public static final int RANK_DATE_TIME = 19;
-    public static final int RANK_ACCESSIBILITY = 20;
-    public static final int RANK_PRINTING = 21;
-    public static final int RANK_DEVELOPEMENT = 22;
-    public static final int RANK_DEVICE_INFO = 23;
+    public static final int RANK_SOUND = 10;
+    public static final int RANK_APPS = 11;
+    public static final int RANK_STORAGE = 12;
+    public static final int RANK_POWER_USAGE = 13;
+    public static final int RANK_USERS = 14;
+    public static final int RANK_LOCATION = 15;
+    public static final int RANK_SECURITY = 16;
+    public static final int RANK_ACCOUNT = 17;
+    public static final int RANK_IME = 18;
+    public static final int RANK_PRIVACY = 19;
+    public static final int RANK_DATE_TIME = 20;
+    public static final int RANK_ACCESSIBILITY = 21;
+    public static final int RANK_PRINTING = 22;
+    public static final int RANK_DEVELOPEMENT = 23;
+    public static final int RANK_DEVICE_INFO = 24;
 
     public static final int RANK_UNDEFINED = -1;
     public static final int RANK_OTHERS = 1024;
@@ -124,8 +126,11 @@
         // Wallpapers
         sRankMap.put(WallpaperTypeSettings.class.getName(), RANK_WALLPAPER);
 
+        // Sound
+        sRankMap.put(SoundSettings.class.getName(), RANK_SOUND);
+
         // Notifications
-        sRankMap.put(NotificationSettings.class.getName(), RANK_NOTIFICATIONS);
+        sRankMap.put(ConfigureNotificationSettings.class.getName(), RANK_NOTIFICATIONS);
         sRankMap.put(OtherSoundSettings.class.getName(), RANK_NOTIFICATIONS);
         sRankMap.put(ZenModeSettings.class.getName(), RANK_NOTIFICATIONS);
         sRankMap.put(ZenModePrioritySettings.class.getName(), RANK_NOTIFICATIONS);
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index 7e669e0..376b2eb 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -44,8 +44,9 @@
 import com.android.settings.location.LocationSettings;
 import com.android.settings.location.ScanningSettings;
 import com.android.settings.net.DataUsageMeteredSettings;
-import com.android.settings.notification.NotificationSettings;
+import com.android.settings.notification.ConfigureNotificationSettings;
 import com.android.settings.notification.OtherSoundSettings;
+import com.android.settings.notification.SoundSettings;
 import com.android.settings.notification.ZenModePrioritySettings;
 import com.android.settings.notification.ZenModeSettings;
 import com.android.settings.notification.ZenModeVisualInterruptionSettings;
@@ -144,24 +145,31 @@
                         WallpaperTypeSettings.class.getName(),
                         R.drawable.ic_settings_display));
 
-        sResMap.put(NotificationSettings.class.getName(),
+        sResMap.put(ConfigureNotificationSettings.class.getName(),
                 new SearchIndexableResource(
-                        Ranking.getRankForClassName(NotificationSettings.class.getName()),
-                        NO_DATA_RES_ID,
-                        NotificationSettings.class.getName(),
+                        Ranking.getRankForClassName(ConfigureNotificationSettings.class.getName()),
+                        R.xml.configure_notification_settings,
+                        ConfigureNotificationSettings.class.getName(),
                         R.drawable.ic_settings_notifications));
 
+        sResMap.put(SoundSettings.class.getName(),
+                new SearchIndexableResource(
+                        Ranking.getRankForClassName(SoundSettings.class.getName()),
+                        R.xml.sound_settings,
+                        SoundSettings.class.getName(),
+                        R.drawable.ic_settings_sound));
+
         sResMap.put(OtherSoundSettings.class.getName(),
                 new SearchIndexableResource(
                         Ranking.getRankForClassName(OtherSoundSettings.class.getName()),
                         NO_DATA_RES_ID,
                         OtherSoundSettings.class.getName(),
-                        R.drawable.ic_settings_notifications));
+                        R.drawable.ic_settings_sound));
 
         sResMap.put(ZenModeSettings.class.getName(),
                 new SearchIndexableResource(
                         Ranking.getRankForClassName(ZenModeSettings.class.getName()),
-                        NO_DATA_RES_ID,
+                        R.xml.zen_mode_settings,
                         ZenModeSettings.class.getName(),
                         R.drawable.ic_settings_notifications));