diff options
-rw-r--r-- | AndroidManifest.xml | 47 | ||||
-rw-r--r-- | proguard.flags | 2 | ||||
-rw-r--r-- | res/layout/notification_app.xml | 32 | ||||
-rw-r--r-- | res/layout/notification_app_dialog.xml | 18 | ||||
-rw-r--r-- | res/values/strings.xml | 274 | ||||
-rw-r--r-- | res/xml/notification_display_settings.xml | 48 | ||||
-rw-r--r-- | res/xml/notification_settings.xml | 87 | ||||
-rw-r--r-- | res/xml/touch_sound_settings.xml | 54 | ||||
-rw-r--r-- | src/com/android/settings/RingerVolumePreference.java | 7 | ||||
-rw-r--r-- | src/com/android/settings/Settings.java | 3 | ||||
-rw-r--r-- | src/com/android/settings/notification/AppNotificationSettings.java | 146 | ||||
-rw-r--r-- | src/com/android/settings/notification/NotificationDisplaySettings.java | 251 | ||||
-rw-r--r-- | src/com/android/settings/notification/NotificationSettings.java | 368 | ||||
-rw-r--r-- | src/com/android/settings/notification/TouchSoundSettings.java | 208 | ||||
-rw-r--r-- | src/com/android/settings/notification/VolumeSeekBarPreference.java | 97 | ||||
-rw-r--r-- | src/com/android/settings/notification/ZenModeSettings.java | 2 | ||||
-rw-r--r-- | src/com/android/settings/search/SearchIndexableResources.java | 21 |
17 files changed, 1324 insertions, 341 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 2794d9d..07cc59b 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1722,6 +1722,53 @@ android:resource="@id/notification_settings" /> </activity> + <activity android:name="Settings$NotificationDisplaySettingsActivity" + android:label="@string/notification_display_settings" + android:exported="true" + android:taskAffinity="" + android:excludeFromRecents="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <action android:name="android.settings.ACTION_NOTIFICATION_DISPLAY_SETTINGS" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + <meta-data android:name="com.android.settings.FRAGMENT_CLASS" + android:value="com.android.settings.notification.NotificationDisplaySettings" /> + <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID" + android:resource="@id/notification_settings" /> + </activity> + + <activity android:name="Settings$TouchSoundSettingsActivity" + android:label="@string/touch_sound_settings" + android:exported="true" + android:taskAffinity="" + android:excludeFromRecents="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <action android:name="android.settings.ACTION_TOUCH_SOUND_SETTINGS" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + <meta-data android:name="com.android.settings.FRAGMENT_CLASS" + android:value="com.android.settings.notification.TouchSoundSettings" /> + <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID" + android:resource="@id/notification_settings" /> + </activity> + + <activity android:name="Settings$AppNotificationSettingsActivity" + android:label="@string/app_notifications_title" + android:exported="true" + android:taskAffinity="" + android:excludeFromRecents="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <action android:name="android.settings.ACTION_APP_NOTIFICATION_SETTINGS" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + <meta-data android:name="com.android.settings.FRAGMENT_CLASS" + android:value="com.android.settings.notification.AppNotificationSettings" /> + <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID" + android:resource="@id/notification_settings" /> + </activity> <!-- Show regulatory info (from settings item or dialing "*#07#") --> <activity android:name="RegulatoryInfoDisplayActivity" diff --git a/proguard.flags b/proguard.flags index 211a5a4..694ab29 100644 --- a/proguard.flags +++ b/proguard.flags @@ -12,8 +12,8 @@ -keep class com.android.settings.accounts.* -keep class com.android.settings.fuelgauge.* -keep class com.android.settings.users.* --keep class com.android.settings.NotificationStation -keep class com.android.settings.nfc.* +-keep class com.android.settings.notification.* # Keep click responders -keepclassmembers class com.android.settings.inputmethod.UserDictionaryAddWordActivity { diff --git a/res/layout/notification_app.xml b/res/layout/notification_app.xml index 414165a..1bb11a0 100644 --- a/res/layout/notification_app.xml +++ b/res/layout/notification_app.xml @@ -33,26 +33,6 @@ android:contentDescription="@null" android:scaleType="center" /> - <ImageView - android:id="@android:id/icon1" - android:layout_width="@dimen/notification_app_icon_badge_size" - android:layout_height="@dimen/notification_app_icon_badge_size" - android:layout_marginLeft="@dimen/notification_app_icon_badge_margin" - android:layout_marginTop="@dimen/notification_app_icon_badge_margin" - android:background="#bb8b0000" - android:contentDescription="@null" /> - - <ImageView - android:id="@android:id/icon2" - android:layout_width="@dimen/notification_app_icon_badge_size" - android:layout_height="@dimen/notification_app_icon_badge_size" - android:layout_alignBottom="@android:id/icon" - android:layout_alignEnd="@android:id/icon" - android:layout_marginBottom="@dimen/notification_app_icon_badge_margin" - android:layout_marginEnd="@dimen/notification_app_icon_badge_margin" - android:background="#bb006400" - android:contentDescription="@null" /> - <TextView android:id="@android:id/title" android:layout_width="match_parent" @@ -63,6 +43,18 @@ android:singleLine="true" android:textAlignment="viewStart" android:textAppearance="?android:attr/textAppearanceMedium" /> + + <TextView + android:id="@android:id/text1" + android:layout_width="match_parent" + android:layout_height="@dimen/notification_app_icon_size" + android:layout_toEndOf="@android:id/icon" + android:gravity="bottom" + android:ellipsize="end" + android:singleLine="true" + android:textAlignment="viewStart" + android:textColor="#888" + android:textAppearance="?android:attr/textAppearanceMedium" /> </RelativeLayout> <View diff --git a/res/layout/notification_app_dialog.xml b/res/layout/notification_app_dialog.xml index a8f7880..5b2fd1a 100644 --- a/res/layout/notification_app_dialog.xml +++ b/res/layout/notification_app_dialog.xml @@ -44,4 +44,22 @@ android:text="@string/app_notifications_dialog_show" android:textAppearance="?android:attr/textAppearanceListItem" /> + <CheckBox + android:id="@android:id/button2" + android:layout_width="match_parent" + android:layout_height="@dimen/notification_app_icon_size" + android:layout_below="@android:id/button1" + android:layout_marginStart="@dimen/content_margin_left" + android:text="@string/app_notifications_dialog_priority" + android:textAppearance="?android:attr/textAppearanceListItem" /> + + <CheckBox + android:id="@android:id/button3" + android:layout_width="match_parent" + android:layout_height="@dimen/notification_app_icon_size" + android:layout_below="@android:id/button2" + android:layout_marginStart="@dimen/content_margin_left" + android:text="@string/app_notifications_dialog_visibility" + android:textAppearance="?android:attr/textAppearanceListItem" /> + </RelativeLayout>
\ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 6b5ff84..4fb33c9 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1028,63 +1028,6 @@ <!-- Summary of preference to manage device policies --> <string name="manage_trust_agents_summary">View or deactivate trust agents</string> - <!-- Notification access settings (part of Security) --> - - <!-- Title of preference to manage notification listeners --> - <string name="manage_notification_access">Notification access</string> - - <!-- Summary of preference to manage notification listeners, when none are enabled --> - <string name="manage_notification_access_summary_zero">Apps cannot read notifications</string> - - <!-- Summary of preference to manage notification listeners, when one or more are enabled - and are therefore able to read the user's notifications --> - <plurals name="manage_notification_access_summary_nonzero"> - <item quantity="one">%d app can read notifications</item> - <item quantity="other">%d apps can read notifications</item> - </plurals> - - <!-- String to show in the list of notification listeners, when none is installed --> - <string name="no_notification_listeners">No notification listeners are installed.</string> - - <!-- Title for a warning message about security implications of enabling a notification - listener, displayed as a dialog message. [CHAR LIMIT=NONE] --> - <string name="notification_listener_security_warning_title">Enable - <xliff:g id="service" example="NotificationReader">%1$s</xliff:g>?</string> - <!-- Summary for a warning message about security implications of enabling a notification - listener, displayed as a dialog message. [CHAR LIMIT=NONE] --> - <string name="notification_listener_security_warning_summary"> - <xliff:g id="notification_listener_name">%1$s</xliff:g> will be able to - read all notifications posted by the system or any installed app, which may include personal - information such as contact names and the text of messages sent to you. It will also be able - 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> - <!-- Bluetooth settings --> <!-- Bluetooth settings check box title on Main Settings screen --> <string name="bluetooth_quick_toggle_title">Bluetooth</string> @@ -1778,8 +1721,6 @@ <string name="display_settings_title">Display</string> <!-- Sound settings screen heading --> <string name="sound_settings">Sound</string> - <!-- Sound settings screen, setting option name to pick ringtone (a list dialog comes up)--> - <string name="ringtone_title">Phone ringtone</string> <!-- Sound settings screen, setting option summary text --> <string name="ringtone_summary">""</string> <!-- Sound settings screen, volume title --> @@ -1792,8 +1733,6 @@ <string name="vibrate_in_silent_title">Vibrate when silent</string> <!-- Sound settings screen, setting option name --> <string name="notification_sound_title">Default notification sound</string> - <!-- Sound settings screen, notification light repeat pulsing title --> - <string name="notification_pulse_title">Pulse notification light</string> <!-- Display settings screen, notification popups are enabled [CHAR LIMIT=30] --> <string name="heads_up_enabled_title">Pop up if high priority</string> <!-- Sound settings screen, the title of the volume bar to adjust the incoming call volume --> @@ -1839,9 +1778,6 @@ <string name="volume_notification_mute">Mute notifications</string> <!-- Image description for alarm volume mute button. --> <string name="volume_alarm_mute">Mute alarms</string> - <!-- Sound settings screen, setting option name checkbox. About vibration setting - during incoming calls. [CHAR LIMIT=30] --> - <string name="vibrate_when_ringing_title">Vibrate when ringing</string> <!-- Dock settings title, top level --> <string name="dock_settings">Dock</string> @@ -5110,39 +5046,6 @@ <!--Search Keywords--> <string name="keywords_wifi">wifi wi-fi network connection</string> - <!-- Notifications on lockscreen --> - <!-- Label for checkbox controlling the contents of notifications shown on - the secure lockscreen [CHAR LIMIT=25] --> - <string name="lock_screen_notifications">When device is locked</string> - <!-- Summary for lock_screen_notifications: sensitive information will be - hidden or redacted from notifications shown on a secure lock screen - [CHAR LIMIT=50] --> - <string name="lock_screen_notifications_summary_hide">Hide sensitive notification content</string> - <!-- Summary for lock_screen_notifications: all information will be - shown in notifications shown on a secure lock screen - [CHAR LIMIT=50] --> - <string name="lock_screen_notifications_summary_show">Show all notification content</string> - - <!-- [CHAR LIMIT=30] Notification settings screen, setting option name --> - <string name="title_zen_mode">Do not disturb</string> - - <!-- [CHAR LIMIT=30] Zen mode settings screen, activity title --> - <string name="zen_mode_settings_title">Do not disturb</string> - - <!-- [CHAR LIMIT=20] Notifications settings header --> - <string name="notification_settings">Notifications</string> - - <!-- [CHAR LIMIT=20] Notifications settings: Tweaks section header (eng - builds only) --> - <string name="notification_settings_tweaks">Tweaks</string> - - <!-- [CHAR LIMIT=20] Notifications settings: Apps section header --> - <string name="notification_settings_apps_title">App notifications</string> - - <!-- [CHAR LIMIT=NONE] Content description for per-app notification - settings button --> - <string name="notification_app_settings_button">Notification settings</string> - <!-- NFC Wi-Fi pairing/setup strings--> <!-- Write NFC tag for Wi-Fi pairing/setup title [CHAR_LIMIT=30]--> @@ -5163,17 +5066,170 @@ <!-- Option title for the default sound, context based on screen --> <string name="default_sound">Default sound</string> - <!-- [CHAR LIMIT=NONE] Text when loading app list in notification settings --> - <string name="loading_notification_apps">Loading apps...</string> - <!-- [CHAR LIMIT=40] Notification settings: App notifications screen title --> + <!-- Sounds and Notifications --> + + <!-- Sounds & notifications: Settings header. [CHAR LIMIT=20] --> + <string name="notification_settings">Sounds & Notifications</string> + + <!-- Sounds & notifications: Title for the option managing media volume. [CHAR LIMIT=NONE] --> + <string name="media_volume_option_title">Media volume</string> + + <!-- Sounds & notifications: Title for the option managing alarm volume. [CHAR LIMIT=NONE] --> + <string name="alarm_volume_option_title">Alarm volume</string> + + <!-- Sounds & notifications: Title for the option managing ringer volume. [CHAR LIMIT=NONE] --> + <string name="ring_volume_option_title">Ring volume</string> + + <!-- Sounds & notifications: Title for the Do not disturb option and associated settings page. [CHAR LIMIT=NONE] --> + <string name="zen_mode_settings_title">Do not disturb</string> + + <!-- Sounds & notifications: Title for the ringer mode option. [CHAR LIMIT=NONE] --> + <string name="ringer_mode_title">When calls and notifications arrive</string> + + <!-- Sounds & notifications: Value for the ringer mode option when audible. [CHAR LIMIT=NONE] --> + <string name="ringer_mode_audible">Ring</string> + + <!-- Sounds & notifications: Value for the ringer mode option when vibrate. [CHAR LIMIT=NONE] --> + <string name="ringer_mode_vibrate">Vibrate instead of ringing</string> + + <!-- Sounds & notifications: Value for the ringer mode option when silent. [CHAR LIMIT=NONE] --> + <string name="ringer_mode_silent">Don\'t ring or vibrate</string> + + <!-- Sounds & notifications: Title for the option defining the phone ringtone. [CHAR LIMIT=NONE] --> + <string name="ringtone_title">Phone ringtone</string> + + <!-- Sounds & notifications: Title for the option defining the default notification ringtone. [CHAR LIMIT=NONE] --> + <string name="notification_ringtone_title">Default notification ringtone</string> + + <!-- Sounds & notifications: Title for the option managing whether or not to vibrate when ringing. [CHAR LIMIT=NONE] --> + <string name="vibrate_when_ringing_title">Vibrate when ringing</string> + + <!-- Sounds & notifications: Title for the showing notifications option and associated settings page. [CHAR LIMIT=NONE] --> + <string name="notification_display_settings">Showing notifications</string> + + <!-- Sounds & notifications > Showing notifications: Title for the pulse notification light option. [CHAR LIMIT=NONE] --> + <string name="notification_pulse_title">Pulse notification light</string> + + <!-- Sounds & notifications > Showing notifications: Title for the option controlling notifications on the lockscreen. [CHAR LIMIT=NONE] --> + <string name="lock_screen_notifications_title">When device is locked</string> + + <!-- Sounds & notifications > Showing notifications: Value for lockscreen notifications: all information will be + shown in notifications shown on a secure lock screen + [CHAR LIMIT=50] --> + <string name="lock_screen_notifications_summary_show">Show all notification content</string> + + <!-- Sounds & notifications > Showing notifications: Value for lockscreen notifications: sensitive information will be + hidden or redacted from notifications shown on a secure lock screen + [CHAR LIMIT=50] --> + <string name="lock_screen_notifications_summary_hide">Hide sensitive notification content</string> + + <!-- Sounds & notifications > Showing notifications: Value for lockscreen notifications: notifications will not appear on a secure lock screen + [CHAR LIMIT=50] --> + <string name="lock_screen_notifications_summary_disable">Don\'t show notifications at all</string> + + <!-- Sounds & notifications > Showing notifications: Title for the option managing notification display in zen mode. [CHAR LIMIT=NONE] --> + <string name="zen_mode_notifications_title">When do not disturb is on</string> + + <!-- Sounds & notifications > Showing notifications: Value for zen mode notifications: notifications will be suppressed in zen mode [CHAR LIMIT=50] --> + <string name="zen_mode_notifications_summary_hide">Hide new notifications from the list</string> + + <!-- Sounds & notifications > Showing notifications: Value for zen mode notifications: notifications will be displayed in zen mode [CHAR LIMIT=50] --> + <string name="zen_mode_notifications_summary_show">Show all notifications in the list</string> + + <!-- Sounds & notifications > Showing notifications: Title for the option managing notifications per application. [CHAR LIMIT=NONE] --> <string name="app_notifications_title">App notifications</string> - <!-- [CHAR LIMIT=30] Notification settings: App notifications dialog show option --> + <!-- Sounds & notifications: Title for the touch sounds option and associated settings page. [CHAR LIMIT=NONE] --> + <string name="touch_sound_settings">Touch sounds</string> + + <!-- Sounds & notifications > Touch sounds: Title for the option enabling touch sounds for dial pad tones. [CHAR LIMIT=NONE] --> + <string name="dial_pad_tones_title">Dial pad tones</string> + + <!-- Sounds & notifications > Touch sounds: Title for the option enabling touch sounds for screen locking and unlocking. [CHAR LIMIT=NONE] --> + <string name="screen_locking_sounds_title">Screen locking & unlocking</string> + + <!-- Sounds & notifications > Touch sounds: Title for the option enabling other touch sounds. [CHAR LIMIT=NONE] --> + <string name="other_touch_sounds_title">Other touch sounds</string> + + <!-- Sounds & notifications > Touch sounds: Title for the option enabling haptic feedback on touch. [CHAR LIMIT=NONE] --> + <string name="vibrate_on_touch_title">Vibrate on touch</string> + + <!-- Sounds & notifications: Title for managing notification listeners option. [CHAR LIMIT=NONE] --> + <string name="manage_notification_access_title">Notification access</string> + + <!-- Summary of preference to manage notification listeners, when none are enabled --> + <string name="manage_notification_access_summary_zero">Apps cannot read notifications</string> + + <!-- Summary of preference to manage notification listeners, when one or more are enabled + and are therefore able to read the user's notifications --> + <plurals name="manage_notification_access_summary_nonzero"> + <item quantity="one">%d app can read notifications</item> + <item quantity="other">%d apps can read notifications</item> + </plurals> + + <!-- String to show in the list of notification listeners, when none is installed --> + <string name="no_notification_listeners">No notification listeners are installed.</string> + + <!-- Title for a warning message about security implications of enabling a notification + listener, displayed as a dialog message. [CHAR LIMIT=NONE] --> + <string name="notification_listener_security_warning_title">Enable + <xliff:g id="service" example="NotificationReader">%1$s</xliff:g>?</string> + <!-- Summary for a warning message about security implications of enabling a notification + listener, displayed as a dialog message. [CHAR LIMIT=NONE] --> + <string name="notification_listener_security_warning_summary"> + <xliff:g id="notification_listener_name">%1$s</xliff:g> will be able to + read all notifications posted by the system or any installed app, which may include personal + information such as contact names and the text of messages sent to you. It will also be able + 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> + + <!-- [CHAR LIMIT=NONE] Notification settings: App notifications dialog show option --> <string name="app_notifications_dialog_show">Show notifications</string> - <!-- [CHAR LIMIT=30] Notification settings: App notifications dialog priority option --> - <string name="app_notifications_dialog_priority">High priority</string> + <!-- [CHAR LIMIT=NONE] Notification settings: App notifications dialog priority option --> + <string name="app_notifications_dialog_priority">Display at the top of the list</string> + + <!-- [CHAR LIMIT=NONE] Notification settings: App notifications dialog visibility option --> + <string name="app_notifications_dialog_visibility">Hide sensitive content when device is locked</string> + + <!-- [CHAR LIMIT=20] Notification settings: App notifications row summary when banned --> + <string name="app_notification_row_banned">Blocked</string> + + <!-- [CHAR LIMIT=20] Notification settings: App notifications row summary when high priority --> + <string name="app_notification_row_priority">Top of list</string> + + <!-- [CHAR LIMIT=20] Notification settings: App notifications row summary when sensitive --> + <string name="app_notification_row_sensitive">Sensitive</string> <!-- [CHAR LIMIT=20] Notification settings: App notifications dialog dismiss button caption --> <string name="app_notifications_dialog_done">Done</string> @@ -5193,8 +5249,8 @@ <!-- [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: Entry conditions option: summary condition divider --> - <string name="zen_mode_entry_conditions_summary_divider">, </string> + <!-- [CHAR LIMIT=40] General divider text when concatenating multiple items in a text summary --> + <string name="summary_divider_text">, </string> <!-- [CHAR LIMIT=40] Zen mode settings: Entry conditions option: value when blank --> <string name="zen_mode_entry_conditions_summary_none">Never</string> @@ -5241,6 +5297,14 @@ <!-- [CHAR LIMIT=20] Zen mode settings: End time option: Summary text value format --> <string name="zen_mode_end_time_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> + + <!-- [CHAR LIMIT=NONE] Content description for per-app notification + settings button --> + <string name="notification_app_settings_button">Notification settings</string> + + <!-- [CHAR LIMIT=35] Feedback on the device --> <string name="device_feedback">Send feedback about this device</string> diff --git a/res/xml/notification_display_settings.xml b/res/xml/notification_display_settings.xml new file mode 100644 index 0000000..d5cade1 --- /dev/null +++ b/res/xml/notification_display_settings.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" + android:title="@string/notification_display_settings" + android:key="notification_display_settings" + xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"> + + <!-- Pulse notification light --> + <SwitchPreference + android:key="notification_pulse" + android:title="@string/notification_pulse_title" + android:switchTextOff="" + android:switchTextOn="" + android:persistent="false" /> + + <!-- When device is locked --> + <com.android.settings.notification.DropDownPreference + android:key="lock_screen_notifications" + android:title="@string/lock_screen_notifications_title" + android:persistent="false" /> + + <!-- When do not disturb is on --> + <com.android.settings.notification.DropDownPreference + android:key="zen_mode_notifications" + android:title="@string/zen_mode_notifications_title" + android:persistent="false" /> + + <!-- App notifications --> + <PreferenceScreen + android:key="app_notifications" + android:title="@string/app_notifications_title" + android:fragment="com.android.settings.notification.AppNotificationSettings" /> + +</PreferenceScreen> diff --git a/res/xml/notification_settings.xml b/res/xml/notification_settings.xml index 8cc1069..633c133 100644 --- a/res/xml/notification_settings.xml +++ b/res/xml/notification_settings.xml @@ -19,41 +19,78 @@ android:key="notification_settings" xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"> - <com.android.settings.DefaultRingtonePreference - android:key="notification_sound" - android:title="@string/default_sound" - android:dialogTitle="@string/notification_sound_dialog_title" - android:persistent="false" - android:ringtoneType="notification" /> + <!-- Media volume --> + <com.android.settings.notification.VolumeSeekBarPreference + android:key="media_volume" + android:icon="@*android:drawable/ic_audio_vol" + android:title="@string/media_volume_option_title" /> - <CheckBoxPreference - android:key="notification_pulse" - android:title="@string/notification_pulse_title" - android:persistent="false" /> + <!-- Alarm volume --> + <com.android.settings.notification.VolumeSeekBarPreference + android:key="alarm_volume" + android:icon="@*android:drawable/ic_audio_alarm" + android:title="@string/alarm_volume_option_title" /> - <CheckBoxPreference - android:key="heads_up" - android:title="@string/heads_up_enabled_title" - android:persistent="false" /> + <!-- Ring volume --> + <com.android.settings.notification.VolumeSeekBarPreference + android:key="ring_volume" + android:icon="@*android:drawable/ic_audio_ring_notif" + android:title="@string/ring_volume_option_title" /> + <!-- Do not disturb --> + <PreferenceScreen + android:key="zen_mode" + android:title="@string/zen_mode_settings_title" + android:fragment="com.android.settings.notification.ZenModeSettings" /> + + <!-- When calls and notifications arrive --> <com.android.settings.notification.DropDownPreference - android:key="toggle_lock_screen_notifications" - android:title="@string/lock_screen_notifications" + android:key="ringer_mode" + android:title="@string/ringer_mode_title" android:persistent="false" /> - <PreferenceScreen - android:key="configure" - android:title="@string/notification_settings_apps_title" - android:fragment="com.android.settings.notification.AppNotificationSettings" /> + <!-- Phone ringtone --> + <com.android.settings.DefaultRingtonePreference + android:key="ringtone" + android:title="@string/ringtone_title" + android:dialogTitle="@string/ringtone_title" + android:persistent="false" + android:ringtoneType="ringtone" /> - <PreferenceScreen - android:key="zen_mode" - android:title="@string/title_zen_mode" - android:fragment="com.android.settings.notification.ZenModeSettings" /> + <!-- Default notification ringtone --> + <com.android.settings.DefaultRingtonePreference + android:key="notification_ringtone" + android:title="@string/notification_ringtone_title" + android:dialogTitle="@string/notification_ringtone_title" + android:persistent="false" + android:ringtoneType="notification" /> + + <!-- Vibrate when ringing --> + <SwitchPreference + android:key="vibrate_when_ringing" + android:title="@string/vibrate_when_ringing_title" + android:switchTextOff="" + android:switchTextOn="" + android:persistent="false" /> + + <!-- Showing notifications --> + <Preference + android:key="showing_notifications" + android:title="@string/notification_display_settings" + android:persistent="false" + android:fragment="com.android.settings.notification.NotificationDisplaySettings" /> + + <!-- Touch sounds --> + <Preference + android:key="touch_sounds" + android:title="@string/touch_sound_settings" + android:persistent="false" + android:fragment="com.android.settings.notification.TouchSoundSettings" /> + <!-- Notification access --> <Preference android:key="manage_notification_access" - android:title="@string/manage_notification_access" + android:title="@string/manage_notification_access_title" android:persistent="false" android:fragment="com.android.settings.notification.NotificationAccessSettings" /> diff --git a/res/xml/touch_sound_settings.xml b/res/xml/touch_sound_settings.xml new file mode 100644 index 0000000..d10ef0d --- /dev/null +++ b/res/xml/touch_sound_settings.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" + android:title="@string/touch_sound_settings" + android:key="touch_sound_settings" + xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"> + + <!-- Dial pad tones --> + <SwitchPreference + android:key="dial_pad_tones" + android:title="@string/dial_pad_tones_title" + android:switchTextOff="" + android:switchTextOn="" + android:persistent="false" /> + + <!-- Screen locking / unlocking --> + <SwitchPreference + android:key="screen_locking_sounds" + android:title="@string/screen_locking_sounds_title" + android:switchTextOff="" + android:switchTextOn="" + android:persistent="false" /> + + <!-- Other touch sounds --> + <SwitchPreference + android:key="other_touch_sounds" + android:title="@string/other_touch_sounds_title" + android:switchTextOff="" + android:switchTextOn="" + android:persistent="false" /> + + <!-- Vibrate on touch --> + <SwitchPreference + android:key="vibrate_on_touch" + android:title="@string/vibrate_on_touch_title" + android:switchTextOff="" + android:switchTextOn="" + android:persistent="false" /> + +</PreferenceScreen> diff --git a/src/com/android/settings/RingerVolumePreference.java b/src/com/android/settings/RingerVolumePreference.java index dd81ded..0f28e06 100644 --- a/src/com/android/settings/RingerVolumePreference.java +++ b/src/com/android/settings/RingerVolumePreference.java @@ -34,6 +34,7 @@ import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.Parcelable; +import android.preference.SeekBarVolumizer; import android.preference.VolumePreference; import android.provider.Settings; import android.provider.Settings.System; @@ -173,10 +174,10 @@ public class RingerVolumePreference extends VolumePreference { mSeekBars[i] = seekBar; if (SEEKBAR_TYPE[i] == AudioManager.STREAM_MUSIC) { mSeekBarVolumizer[i] = new SeekBarVolumizer(getContext(), seekBar, - SEEKBAR_TYPE[i], getMediaVolumeUri(getContext())); + SEEKBAR_TYPE[i], getMediaVolumeUri(getContext()), this); } else { mSeekBarVolumizer[i] = new SeekBarVolumizer(getContext(), seekBar, - SEEKBAR_TYPE[i]); + SEEKBAR_TYPE[i], null, this); } } @@ -275,7 +276,7 @@ public class RingerVolumePreference extends VolumePreference { } @Override - protected void onSampleStarting(SeekBarVolumizer volumizer) { + public void onSampleStarting(SeekBarVolumizer volumizer) { super.onSampleStarting(volumizer); for (SeekBarVolumizer vol : mSeekBarVolumizer) { if (vol != null && vol != volumizer) vol.stopSample(); diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index 2537808..38176eb 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -88,6 +88,9 @@ public class Settings extends SettingsActivity { public static class PrintJobSettingsActivity extends SettingsActivity { /* empty */ } public static class ZenModeSettingsActivity extends SettingsActivity { /* empty */ } public static class NotificationSettingsActivity extends SettingsActivity { /* empty */ } + public static class NotificationDisplaySettingsActivity extends SettingsActivity { /* empty */ } + public static class AppNotificationSettingsActivity extends SettingsActivity { /* empty */ } + public static class TouchSoundSettingsActivity extends SettingsActivity { /* empty */ } public static class TopLevelSettings extends SettingsActivity { /* empty */ } } diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java index c63ae63..1cae805 100644 --- a/src/com/android/settings/notification/AppNotificationSettings.java +++ b/src/com/android/settings/notification/AppNotificationSettings.java @@ -29,11 +29,8 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.pm.Signature; -import android.graphics.Paint; -import android.graphics.Path; +import android.content.res.Resources; import android.graphics.drawable.Drawable; -import android.graphics.drawable.ShapeDrawable; -import android.graphics.drawable.shapes.PathShape; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; @@ -57,6 +54,9 @@ import android.widget.SectionIndexer; import android.widget.TextView; 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.Collator; import java.util.ArrayList; @@ -64,7 +64,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; -public class AppNotificationSettings extends ListFragment { +public class AppNotificationSettings extends ListFragment implements Indexable { private static final String TAG = "AppNotificationSettings"; private static final boolean DEBUG = true; @@ -187,6 +187,9 @@ public class AppNotificationSettings extends ListFragment { final TextView title = (TextView) layout.findViewById(android.R.id.title); title.setText(row.label); final CheckBox showBox = (CheckBox) layout.findViewById(android.R.id.button1); + final CheckBox priBox = (CheckBox) layout.findViewById(android.R.id.button2); + final CheckBox senBox = (CheckBox) layout.findViewById(android.R.id.button3); + showBox.setChecked(!row.banned); final OnCheckedChangeListener showListener = new OnCheckedChangeListener() { @Override @@ -195,6 +198,8 @@ public class AppNotificationSettings extends ListFragment { if (success) { row.banned = !isChecked; mAdapter.bindView(v, row, true /*animate*/); + priBox.setEnabled(!row.banned); + senBox.setEnabled(!row.banned); } else { showBox.setOnCheckedChangeListener(null); showBox.setChecked(!isChecked); @@ -203,6 +208,44 @@ public class AppNotificationSettings extends ListFragment { } }; showBox.setOnCheckedChangeListener(showListener); + + priBox.setChecked(row.priority); + final OnCheckedChangeListener priListener = new OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + boolean success = mBackend.setHighPriority(row.pkg, row.uid, isChecked); + if (success) { + row.priority = isChecked; + mAdapter.bindView(v, row, true /*animate*/); + } else { + priBox.setOnCheckedChangeListener(null); + priBox.setChecked(!isChecked); + priBox.setOnCheckedChangeListener(this); + } + } + }; + priBox.setOnCheckedChangeListener(priListener); + + senBox.setChecked(row.sensitive); + final OnCheckedChangeListener senListener = new OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + boolean success = mBackend.setSensitive(row.pkg, row.uid, isChecked); + if (success) { + row.sensitive = isChecked; + mAdapter.bindView(v, row, true /*animate*/); + } else { + senBox.setOnCheckedChangeListener(null); + senBox.setChecked(!isChecked); + senBox.setOnCheckedChangeListener(this); + } + } + }; + senBox.setOnCheckedChangeListener(senListener); + + priBox.setEnabled(!row.banned); + senBox.setEnabled(!row.banned); + final AlertDialog d = new AlertDialog.Builder(mContext) .setView(layout) .setPositiveButton(R.string.app_notifications_dialog_done, null) @@ -214,48 +257,16 @@ public class AppNotificationSettings extends ListFragment { ViewGroup row; ViewGroup appButton; ImageView icon; - ImageView banBadge; - ImageView priBadge; TextView title; + TextView subtitle; View settingsDivider; ImageView settingsButton; View rowDivider; } private class NotificationAppAdapter extends ArrayAdapter<Row> implements SectionIndexer { - private final ShapeDrawable mBanShape, mPriShape; - public NotificationAppAdapter(Context context) { super(context, 0, 0); - final int s = context.getResources() - .getDimensionPixelSize(R.dimen.notification_app_icon_badge_size); - mBanShape = shape(banPath(s), s); - mPriShape = shape(priPath(s), s); - } - - private ShapeDrawable shape(Path path, int s) { - final ShapeDrawable sd = new ShapeDrawable(new PathShape(path, s, s)); - sd.getPaint().setStyle(Paint.Style.STROKE); - sd.getPaint().setColor(0xffffffff); - sd.getPaint().setStrokeWidth(s / 12); - sd.setIntrinsicWidth(s); - sd.setIntrinsicHeight(s); - return sd; - } - - private Path banPath(int s) { - final Path p = new Path(); - final int d = s / 5; - p.moveTo(d, d); p.lineTo(s - d, s - d); - p.moveTo(d, s - d); p.lineTo(s - d, d); - return p; - } - - private Path priPath(int s) { - final Path p = new Path(); - final int d = s / 5; - p.moveTo(s / 2, d); p.lineTo(s / 2, s - d); - return p; } @Override @@ -302,11 +313,8 @@ public class AppNotificationSettings extends ListFragment { vh.appButton = (ViewGroup) v.findViewById(android.R.id.button1); vh.appButton.setLayoutTransition(new LayoutTransition()); vh.icon = (ImageView) v.findViewById(android.R.id.icon); - vh.banBadge = (ImageView) v.findViewById(android.R.id.icon1); - vh.banBadge.setImageDrawable(mBanShape); - vh.priBadge = (ImageView) v.findViewById(android.R.id.icon2); - vh.priBadge.setImageDrawable(mPriShape); vh.title = (TextView) v.findViewById(android.R.id.title); + vh.subtitle = (TextView) v.findViewById(android.R.id.text1); vh.settingsDivider = v.findViewById(R.id.settings_divider); vh.settingsButton = (ImageView) v.findViewById(android.R.id.button2); vh.rowDivider = v.findViewById(R.id.row_divider); @@ -326,6 +334,7 @@ public class AppNotificationSettings extends ListFragment { public void bindView(final View view, Row r, boolean animate) { if (!(r instanceof AppRow)) { + // it's a section row TextView tv = (TextView)view; tv.setText(r.section); return; @@ -343,9 +352,10 @@ public class AppNotificationSettings extends ListFragment { }); enableLayoutTransitions(vh.appButton, animate); vh.icon.setImageDrawable(row.icon); - vh.banBadge.setVisibility(row.banned ? View.VISIBLE : View.GONE); - vh.priBadge.setVisibility(row.priority ? View.VISIBLE : View.GONE); vh.title.setText(row.label); + final String sub = getSubtitle(row); + vh.subtitle.setText(sub); + vh.subtitle.setVisibility(!sub.isEmpty() ? View.VISIBLE : View.GONE); final boolean showSettings = !row.banned && row.settingsIntent != null; vh.settingsDivider.setVisibility(showSettings ? View.VISIBLE : View.GONE); vh.settingsButton.setVisibility(showSettings ? View.VISIBLE : View.GONE); @@ -359,6 +369,17 @@ public class AppNotificationSettings extends ListFragment { }); } + private String getSubtitle(AppRow row) { + if (row.banned) return mContext.getString(R.string.app_notification_row_banned); + if (!row.priority && !row.sensitive) return ""; + final String priString = mContext.getString(R.string.app_notification_row_priority); + final String senString = mContext.getString(R.string.app_notification_row_sensitive); + if (row.priority != row.sensitive) { + return row.priority ? priString : senString; + } + return priString + mContext.getString(R.string.summary_divider_text) + senString; + } + @Override public Object[] getSections() { return mSections.toArray(new Object[mSections.size()]); @@ -396,7 +417,8 @@ public class AppNotificationSettings extends ListFragment { public Intent settingsIntent; public boolean banned; public boolean priority; - public boolean first; + public boolean sensitive; + public boolean first; // first app in section } private static final Comparator<AppRow> mRowComparator = new Comparator<AppRow>() { @@ -435,6 +457,7 @@ public class AppNotificationSettings extends ListFragment { row.icon = pkg.applicationInfo.loadIcon(pm); row.banned = mBackend.getNotificationsBanned(row.pkg, row.uid); row.priority = mBackend.getHighPriority(row.pkg, row.uid); + row.sensitive = mBackend.getSensitive(row.pkg, row.uid); mRows.put(row.pkg, row); } // collect config activities @@ -552,5 +575,38 @@ public class AppNotificationSettings extends ListFragment { // TODO save high-pri state to NoMan return true; } + + public boolean getSensitive(String pkg, int uid) { + // TODO get visibility state from NoMan + return false; + } + + public boolean setSensitive(String pkg, int uid, boolean sensitive) { + // TODO save visibility state to NoMan + return true; + } } + + // === Indexing === + + public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider() { + @Override + public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) { + final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>(); + add(result, context, R.string.app_notifications_title); + add(result, context, R.string.app_notifications_dialog_show); + add(result, context, R.string.app_notifications_dialog_priority); + add(result, context, R.string.app_notifications_dialog_visibility); + return result; + } + + private void add(List<SearchIndexableRaw> result, Context context, int title) { + final Resources res = context.getResources(); + final SearchIndexableRaw data = new SearchIndexableRaw(context); + data.title = res.getString(title); + data.screenTitle = res.getString(R.string.app_notifications_title); + result.add(data); + } + }; } diff --git a/src/com/android/settings/notification/NotificationDisplaySettings.java b/src/com/android/settings/notification/NotificationDisplaySettings.java new file mode 100644 index 0000000..8c492e2 --- /dev/null +++ b/src/com/android/settings/notification/NotificationDisplaySettings.java @@ -0,0 +1,251 @@ +/* + * 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.content.ContentResolver; +import android.content.Context; +import android.content.res.Resources; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.preference.Preference; +import android.preference.Preference.OnPreferenceChangeListener; +import android.preference.Preference.OnPreferenceClickListener; +import android.preference.PreferenceScreen; +import android.preference.TwoStatePreference; +import android.provider.Settings; +import android.util.Log; + +import com.android.settings.R; +import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settings.search.Indexable; +import com.android.settings.search.SearchIndexableRaw; + +import java.util.ArrayList; +import java.util.List; + +public class NotificationDisplaySettings extends SettingsPreferenceFragment implements Indexable { + private static final String TAG = "NotificationDisplaySettings"; + + 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_ZEN_MODE_NOTIFICATIONS = "zen_mode_notifications"; + + private final Handler mHandler = new Handler(); + private final SettingsObserver mSettingsObserver = new SettingsObserver(); + + private TwoStatePreference mNotificationPulse; + private DropDownPreference mLockscreen; + private DropDownPreference mZenModeNotifications; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + addPreferencesFromResource(R.xml.notification_display_settings); + + final PreferenceScreen root = getPreferenceScreen(); + initPulse(root); + initLockscreenNotifications(root); + initZenModeNotifications(root); + } + + @Override + public void onResume() { + super.onResume(); + mSettingsObserver.register(true); + } + + @Override + public void onPause() { + super.onPause(); + mSettingsObserver.register(false); + } + + // === Pulse notification light === + + private void initPulse(PreferenceScreen parent) { + mNotificationPulse = (TwoStatePreference) parent.findPreference(KEY_NOTIFICATION_PULSE); + if (mNotificationPulse == null) 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(PreferenceScreen parent) { + mLockscreen = (DropDownPreference) parent.findPreference(KEY_LOCK_SCREEN_NOTIFICATIONS); + if (mLockscreen == null) return; + mLockscreen.addItem(R.string.lock_screen_notifications_summary_show, + R.string.lock_screen_notifications_summary_show); + mLockscreen.addItem(R.string.lock_screen_notifications_summary_hide, + R.string.lock_screen_notifications_summary_hide); + mLockscreen.addItem(R.string.lock_screen_notifications_summary_disable, + R.string.lock_screen_notifications_summary_disable); + updateLockscreenNotifications(); + mLockscreen.setCallback(new DropDownPreference.Callback() { + @Override + public boolean onItemSelected(int pos, Object value) { + final int val = (Integer) value; + 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.Global.putInt(getContentResolver(), + Settings.Global.LOCK_SCREEN_SHOW_NOTIFICATIONS, enabled ? 1 : 0); + return true; + } + }); + } + + private void updateLockscreenNotifications() { + if (mLockscreen == null) return; + final boolean allowPrivate = getLockscreenAllowPrivateNotifications(); + final boolean enabled = getLockscreenNotificationsEnabled(); + final int val = !enabled ? R.string.lock_screen_notifications_summary_disable : + allowPrivate ? R.string.lock_screen_notifications_summary_show : + R.string.lock_screen_notifications_summary_hide; + mLockscreen.setSelectedValue(val); + } + + private boolean getLockscreenNotificationsEnabled() { + return Settings.Global.getInt(getContentResolver(), + Settings.Global.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0; + } + + private boolean getLockscreenAllowPrivateNotifications() { + return Settings.Secure.getInt(getContentResolver(), + Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0) != 0; + } + + // === Zen mode notifications === + + private void initZenModeNotifications(PreferenceScreen parent) { + mZenModeNotifications = (DropDownPreference) + parent.findPreference(KEY_ZEN_MODE_NOTIFICATIONS); + if (mZenModeNotifications == null) return; + mZenModeNotifications.addItem(R.string.zen_mode_notifications_summary_hide, 0); + mZenModeNotifications.addItem(R.string.zen_mode_notifications_summary_show, 1); + updateZenModeNotifications(); + mZenModeNotifications.setCallback(new DropDownPreference.Callback() { + @Override + public boolean onItemSelected(int pos, Object value) { + final int val = (Integer) value; + Settings.Secure.putInt(getContentResolver(), + Settings.Secure.DISPLAY_INTERCEPTED_NOTIFICATIONS, val); + return true; + } + }); + } + + private void updateZenModeNotifications() { + if (mZenModeNotifications == null) return; + mZenModeNotifications.setSelectedValue(Settings.Secure.getInt(getContentResolver(), + Settings.Secure.DISPLAY_INTERCEPTED_NOTIFICATIONS, 0)); + } + + // === Indexing === + + public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider() { + @Override + public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) { + final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>(); + add(result, context, R.string.notification_display_settings); + add(result, context, R.string.notification_pulse_title); + add(result, context, R.string.lock_screen_notifications_title); + add(result, context, R.string.zen_mode_notifications_title); + return result; + } + + private void add(List<SearchIndexableRaw> result, Context context, int title) { + final Resources res = context.getResources(); + final SearchIndexableRaw data = new SearchIndexableRaw(context); + data.title = res.getString(title); + data.screenTitle = res.getString(R.string.notification_display_settings); + result.add(data); + } + }; + + // === 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.Global.getUriFor(Settings.Global.LOCK_SCREEN_SHOW_NOTIFICATIONS); + private final Uri DISPLAY_INTERCEPTED_NOTIFICATIONS_URI = + Settings.Secure.getUriFor(Settings.Secure.DISPLAY_INTERCEPTED_NOTIFICATIONS); + + public SettingsObserver() { + super(mHandler); + } + + 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); + cr.registerContentObserver(DISPLAY_INTERCEPTED_NOTIFICATIONS_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(); + } + if (DISPLAY_INTERCEPTED_NOTIFICATIONS_URI.equals(uri)) { + updateZenModeNotifications(); + } + } + } +} diff --git a/src/com/android/settings/notification/NotificationSettings.java b/src/com/android/settings/notification/NotificationSettings.java index d432bed..61df419 100644 --- a/src/com/android/settings/notification/NotificationSettings.java +++ b/src/com/android/settings/notification/NotificationSettings.java @@ -16,209 +16,212 @@ package com.android.settings.notification; +import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageManager; +import android.content.res.Resources; import android.database.ContentObserver; +import android.media.AudioManager; import android.media.RingtoneManager; -import android.os.Build; +import android.net.Uri; +import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.preference.Preference; -import android.preference.Preference.OnPreferenceClickListener; -import android.preference.PreferenceGroup; +import android.preference.Preference.OnPreferenceChangeListener; import android.preference.PreferenceScreen; +import android.preference.SeekBarVolumizer; import android.preference.TwoStatePreference; import android.provider.Settings; -import android.util.Log; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.SoundSettings; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settings.search.Indexable; +import com.android.settings.search.SearchIndexableRaw; -public class NotificationSettings extends SettingsPreferenceFragment implements - Preference.OnPreferenceChangeListener, OnPreferenceClickListener { +import java.util.ArrayList; +import java.util.List; + +public class NotificationSettings extends SettingsPreferenceFragment implements Indexable { private static final String TAG = "NotificationSettings"; - private static final String KEY_NOTIFICATION_SOUND = "notification_sound"; - private static final String KEY_NOTIFICATION_PULSE = "notification_pulse"; - private static final String KEY_HEADS_UP = "heads_up"; - private static final String KEY_LOCK_SCREEN_NOTIFICATIONS = "toggle_lock_screen_notifications"; + 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"; + private static final String KEY_RINGER_MODE = "ringer_mode"; + private static final String KEY_PHONE_RINGTONE = "ringtone"; + 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_NOTIFICATION_ACCESS = "manage_notification_access"; - private static final String KEY_TWEAKS_CATEGORY = "category_tweaks"; // power toys, eng only + private static final int SAMPLE_CUTOFF = 2000; // manually cap sample playback at 2 seconds - private static final int MSG_UPDATE_SOUND_SUMMARY = 2; + private final VolumePreferenceCallback mVolumeCallback = new VolumePreferenceCallback(); + private final H mHandler = new H(); + private final SettingsObserver mSettingsObserver = new SettingsObserver(); private Context mContext; private PackageManager mPM; - private Preference mNotificationSoundPreference; + private DropDownPreference mRingerMode; + private Preference mPhoneRingtonePreference; + private Preference mNotificationRingtonePreference; + private TwoStatePreference mVibrateWhenRinging; private Preference mNotificationAccess; - private DropDownPreference mLockscreen; - private TwoStatePreference mHeadsUp; - private TwoStatePreference mNotificationPulse; - - private final Runnable mRingtoneLookupRunnable = new Runnable() { - @Override - public void run() { - if (mNotificationSoundPreference != null) { - final CharSequence summary = SoundSettings.updateRingtoneName( - mContext, RingtoneManager.TYPE_NOTIFICATION); - if (summary != null) { - mHandler.sendMessage( - mHandler.obtainMessage(MSG_UPDATE_SOUND_SUMMARY, summary)); - } - } - } - }; - - private final Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_UPDATE_SOUND_SUMMARY: - mNotificationSoundPreference.setSummary((CharSequence) msg.obj); - break; - } - } - }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mContext = getActivity(); - final ContentResolver resolver = mContext.getContentResolver(); - mPM = mContext.getPackageManager(); addPreferencesFromResource(R.xml.notification_settings); final PreferenceScreen root = getPreferenceScreen(); - - PreferenceGroup tweaksCategory = (PreferenceGroup) - root.findPreference(KEY_TWEAKS_CATEGORY); - - if (tweaksCategory != null - && !(Build.TYPE.equals("eng") || Build.TYPE.equals("userdebug"))) { - root.removePreference(tweaksCategory); - tweaksCategory = null; - } - - mNotificationSoundPreference = findPreference(KEY_NOTIFICATION_SOUND); + initVolumePreference(KEY_MEDIA_VOLUME, AudioManager.STREAM_MUSIC); + initVolumePreference(KEY_ALARM_VOLUME, AudioManager.STREAM_ALARM); + initVolumePreference(KEY_RING_VOLUME, AudioManager.STREAM_RING); + initRingerMode(root); + initRingtones(root); + initVibrateWhenRinging(root); mNotificationAccess = findPreference(KEY_NOTIFICATION_ACCESS); refreshNotificationListeners(); - - mLockscreen = (DropDownPreference) root.findPreference(KEY_LOCK_SCREEN_NOTIFICATIONS); - if (mLockscreen != null) { - if (!getDeviceLockscreenNotificationsEnabled()) { - root.removePreference(mLockscreen); - } else { - mLockscreen.addItem(R.string.lock_screen_notifications_summary_show, 1); - mLockscreen.addItem(R.string.lock_screen_notifications_summary_hide, 0); - final int val = getLockscreenAllowPrivateNotifications() ? 1 : 0; - mLockscreen.setSelectedValue(val); - mLockscreen.setCallback(new DropDownPreference.Callback() { - @Override - public boolean onItemSelected(int pos, Object value) { - final int val = (Integer) value; - Settings.Secure.putInt(getContentResolver(), - Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, val); - return true; - } - }); - } - } - - mHeadsUp = (TwoStatePreference) findPreference(KEY_HEADS_UP); - if (mHeadsUp != null) { - updateHeadsUpMode(resolver); - mHeadsUp.setOnPreferenceChangeListener(this); - resolver.registerContentObserver( - Settings.Global.getUriFor(Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED), - false, new ContentObserver(mHandler) { - @Override - public void onChange(boolean selfChange) { - updateHeadsUpMode(resolver); - } - }); - } - mNotificationPulse = (TwoStatePreference) findPreference(KEY_NOTIFICATION_PULSE); - - if (mNotificationPulse != null - && getResources().getBoolean( - com.android.internal.R.bool.config_intrusiveNotificationLed) == false) { - getPreferenceScreen().removePreference(mNotificationPulse); - } else { - try { - mNotificationPulse.setChecked(Settings.System.getInt(resolver, - Settings.System.NOTIFICATION_LIGHT_PULSE) == 1); - mNotificationPulse.setOnPreferenceChangeListener(this); - } catch (Settings.SettingNotFoundException snfe) { - Log.e(TAG, Settings.System.NOTIFICATION_LIGHT_PULSE + " not found"); - } - } } @Override public void onResume() { super.onResume(); - refreshNotificationListeners(); lookupRingtoneNames(); + final IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION); + mContext.registerReceiver(mReceiver, filter); + mSettingsObserver.register(true); } @Override - public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { - final String key = preference.getKey(); - - if (KEY_HEADS_UP.equals(key)) { - setHeadsUpMode(getContentResolver(), mHeadsUp.isChecked()); - } else if (KEY_NOTIFICATION_PULSE.equals(key)) { - Settings.System.putInt(getContentResolver(), - Settings.System.NOTIFICATION_LIGHT_PULSE, - mNotificationPulse.isChecked() ? 1 : 0); - } else { - return super.onPreferenceTreeClick(preferenceScreen, preference); - } + public void onPause() { + super.onPause(); + mVolumeCallback.stopSample(); + mContext.unregisterReceiver(mReceiver); + mSettingsObserver.register(false); + } + + // === Volumes === - return true; + private void initVolumePreference(String key, int stream) { + final VolumeSeekBarPreference volumePref = (VolumeSeekBarPreference) findPreference(key); + volumePref.setStream(stream); + volumePref.setCallback(mVolumeCallback); } - @Override - public boolean onPreferenceChange(Preference preference, Object objValue) { - return true; + private final class VolumePreferenceCallback implements VolumeSeekBarPreference.Callback { + private SeekBarVolumizer mCurrent; + + @Override + public void onSampleStarting(SeekBarVolumizer sbv) { + if (mCurrent != null && mCurrent != sbv) { + mCurrent.stopSample(); + } + mCurrent = sbv; + if (mCurrent != null) { + mHandler.removeMessages(H.STOP_SAMPLE); + mHandler.sendEmptyMessageDelayed(H.STOP_SAMPLE, SAMPLE_CUTOFF); + } + } + + public void stopSample() { + if (mCurrent != null) { + mCurrent.stopSample(); + } + } + }; + + // === Ringer mode === + + private void initRingerMode(PreferenceScreen root) { + mRingerMode = (DropDownPreference) root.findPreference(KEY_RINGER_MODE); + if (mRingerMode == null) return; + final AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); + mRingerMode.addItem(R.string.ringer_mode_audible, AudioManager.RINGER_MODE_NORMAL); + mRingerMode.addItem(R.string.ringer_mode_vibrate, AudioManager.RINGER_MODE_VIBRATE); + mRingerMode.addItem(R.string.ringer_mode_silent, AudioManager.RINGER_MODE_SILENT); + updateRingerMode(); + mRingerMode.setCallback(new DropDownPreference.Callback() { + @Override + public boolean onItemSelected(int pos, Object value) { + final int val = (Integer) value; + am.setRingerMode(val); + return true; + } + }); } - @Override - public boolean onPreferenceClick(Preference preference) { - return false; + private void updateRingerMode() { + final AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); + mRingerMode.setSelectedValue(am.getRingerMode()); } - // === Heads-up notifications === + // === Phone & notification ringtone === - private void updateHeadsUpMode(ContentResolver resolver) { - mHeadsUp.setChecked(Settings.Global.HEADS_UP_ON == Settings.Global.getInt(resolver, - Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED, Settings.Global.HEADS_UP_OFF)); + private void initRingtones(PreferenceScreen root) { + mPhoneRingtonePreference = root.findPreference(KEY_PHONE_RINGTONE); + mNotificationRingtonePreference = root.findPreference(KEY_NOTIFICATION_RINGTONE); } - private void setHeadsUpMode(ContentResolver resolver, boolean value) { - Settings.Global.putInt(resolver, Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED, - value ? Settings.Global.HEADS_UP_ON : Settings.Global.HEADS_UP_OFF); + private void lookupRingtoneNames() { + AsyncTask.execute(mLookupRingtoneNames); } - // === Lockscreen (public / private) notifications === + private final Runnable mLookupRingtoneNames = new Runnable() { + @Override + public void run() { + if (mPhoneRingtonePreference != null) { + final CharSequence summary = SoundSettings.updateRingtoneName( + mContext, RingtoneManager.TYPE_RINGTONE); + if (summary != null) { + mHandler.obtainMessage(H.UPDATE_PHONE_RINGTONE, summary).sendToTarget(); + } + } + if (mNotificationRingtonePreference != null) { + final CharSequence summary = SoundSettings.updateRingtoneName( + mContext, RingtoneManager.TYPE_NOTIFICATION); + if (summary != null) { + mHandler.obtainMessage(H.UPDATE_NOTIFICATION_RINGTONE, summary).sendToTarget(); + } + } + } + }; - private boolean getDeviceLockscreenNotificationsEnabled() { - return 0 != Settings.Global.getInt(getContentResolver(), - Settings.Global.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0); + // === Vibrate when ringing === + + private void initVibrateWhenRinging(PreferenceScreen root) { + mVibrateWhenRinging = (TwoStatePreference) findPreference(KEY_VIBRATE_WHEN_RINGING); + if (mVibrateWhenRinging == null) return; + mVibrateWhenRinging.setPersistent(false); + updateVibrateWhenRinging(); + mVibrateWhenRinging.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + final boolean val = (Boolean) newValue; + return Settings.System.putInt(getContentResolver(), + Settings.System.VIBRATE_WHEN_RINGING, + val ? 1 : 0); + } + }); } - private boolean getLockscreenAllowPrivateNotifications() { - return 0 != Settings.Secure.getInt(getContentResolver(), - Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0); + private void updateVibrateWhenRinging() { + if (mVibrateWhenRinging == null) return; + mVibrateWhenRinging.setChecked(Settings.System.getInt(getContentResolver(), + Settings.System.VIBRATE_WHEN_RINGING, 0) != 0); } // === Notification listeners === @@ -242,9 +245,92 @@ public class NotificationSettings extends SettingsPreferenceFragment implements } } - // === Ringtone === + // === Indexing === + + public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider() { + @Override + public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) { + final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>(); + add(result, context, R.string.notification_settings); + add(result, context, R.string.media_volume_option_title); + add(result, context, R.string.alarm_volume_option_title); + add(result, context, R.string.ring_volume_option_title); + add(result, context, R.string.ringer_mode_title); + add(result, context, R.string.ringtone_title); + add(result, context, R.string.vibrate_when_ringing_title); + add(result, context, R.string.manage_notification_access_title); + return result; + } - private void lookupRingtoneNames() { - new Thread(mRingtoneLookupRunnable).start(); + private void add(List<SearchIndexableRaw> result, Context context, int title) { + final Resources res = context.getResources(); + final SearchIndexableRaw data = new SearchIndexableRaw(context); + data.title = res.getString(title); + data.screenTitle = res.getString(R.string.notification_settings); + result.add(data); + } + }; + + // === Callbacks === + + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(intent.getAction())) { + updateRingerMode(); + } + } + }; + + private final class SettingsObserver extends ContentObserver { + private final Uri VIBRATE_WHEN_RINGING_URI = + Settings.System.getUriFor(Settings.System.VIBRATE_WHEN_RINGING); + + public SettingsObserver() { + super(mHandler); + } + + public void register(boolean register) { + final ContentResolver cr = getContentResolver(); + if (register) { + cr.registerContentObserver(VIBRATE_WHEN_RINGING_URI, false, this); + } else { + cr.unregisterContentObserver(this); + } + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + super.onChange(selfChange, uri); + if (VIBRATE_WHEN_RINGING_URI.equals(uri)) { + updateVibrateWhenRinging(); + } + } + } + + private final class H extends Handler { + private static final int UPDATE_PHONE_RINGTONE = 1; + private static final int UPDATE_NOTIFICATION_RINGTONE = 2; + private static final int STOP_SAMPLE = 3; + + private H() { + super(Looper.getMainLooper()); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case UPDATE_PHONE_RINGTONE: + mPhoneRingtonePreference.setSummary((CharSequence) msg.obj); + break; + case UPDATE_NOTIFICATION_RINGTONE: + mNotificationRingtonePreference.setSummary((CharSequence) msg.obj); + break; + case STOP_SAMPLE: + mVolumeCallback.stopSample(); + break; + } + } } } diff --git a/src/com/android/settings/notification/TouchSoundSettings.java b/src/com/android/settings/notification/TouchSoundSettings.java new file mode 100644 index 0000000..fe122d3 --- /dev/null +++ b/src/com/android/settings/notification/TouchSoundSettings.java @@ -0,0 +1,208 @@ +/* + * 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.content.ContentResolver; +import android.content.Context; +import android.content.res.Resources; +import android.database.ContentObserver; +import android.media.AudioManager; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.Vibrator; +import android.preference.Preference; +import android.preference.Preference.OnPreferenceChangeListener; +import android.preference.Preference.OnPreferenceClickListener; +import android.preference.PreferenceScreen; +import android.preference.TwoStatePreference; +import android.provider.Settings.System; +import android.util.Log; + +import com.android.settings.R; +import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.Utils; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settings.search.Indexable; +import com.android.settings.search.SearchIndexableRaw; + +import java.util.ArrayList; +import java.util.List; + +public class TouchSoundSettings extends SettingsPreferenceFragment implements Indexable { + private static final String TAG = "TouchSoundSettings"; + + private static final String KEY_DIAL_PAD_TONES = "dial_pad_tones"; + private static final String KEY_SCREEN_LOCKING_SOUNDS = "screen_locking_sounds"; + private static final String KEY_OTHER_TOUCH_SOUNDS = "other_touch_sounds"; + private static final String KEY_VIBRATE_ON_TOUCH = "vibrate_on_touch"; + + private final Handler mHandler = new Handler(); + private final SettingsObserver mSettingsObserver = new SettingsObserver(); + + private AudioManager mAudioManager; + private SystemSettingPref mDialPadTones; + private SystemSettingPref mScreenLockingSounds; + private SystemSettingPref mOtherTouchSounds; + private SystemSettingPref mVibrateOnTouch; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + addPreferencesFromResource(R.xml.touch_sound_settings); + + mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); + + final boolean hasVoice = Utils.isVoiceCapable(getActivity()); + final Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); + final boolean hasHaptic = vibrator != null && vibrator.hasVibrator(); + + mDialPadTones = new SystemSettingPref(hasVoice, + KEY_DIAL_PAD_TONES, System.DTMF_TONE_WHEN_DIALING); + + mScreenLockingSounds = new SystemSettingPref(true, + KEY_SCREEN_LOCKING_SOUNDS, System.LOCKSCREEN_SOUNDS_ENABLED); + + mOtherTouchSounds = new SystemSettingPref(true, + KEY_OTHER_TOUCH_SOUNDS,System.SOUND_EFFECTS_ENABLED) { + @Override + protected void setSetting(boolean value) { + if (value) { + mAudioManager.loadSoundEffects(); + } else { + mAudioManager.unloadSoundEffects(); + } + super.setSetting(value); + } + }; + + mVibrateOnTouch = new SystemSettingPref(hasHaptic, + KEY_VIBRATE_ON_TOUCH, System.HAPTIC_FEEDBACK_ENABLED); + } + + @Override + public void onResume() { + super.onResume(); + mSettingsObserver.register(true); + } + + @Override + public void onPause() { + super.onPause(); + mSettingsObserver.register(false); + } + + // === Common system setting preference helper === + + private class SystemSettingPref { + private final String mSetting; + private final Uri mUri; + + private TwoStatePreference mPref; + + private SystemSettingPref(boolean applicable, String key, String setting) { + mSetting = setting; + mUri = System.getUriFor(mSetting); + if (!applicable) removePreference(key); + mPref = (TwoStatePreference) getPreferenceScreen().findPreference(key); + if (mPref == null) return; + update(); + mPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + setSetting((Boolean)newValue); + return true; + } + }); + } + + protected void setSetting(boolean value) { + System.putInt(getContentResolver(), mSetting, value ? 1 : 0); + } + + private Uri getUri() { + return mUri; + } + + private void update() { + if (mPref == null) return; + mPref.setChecked(System.getInt(getContentResolver(), mSetting, 1) != 0); + } + } + + // === Indexing === + + public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider() { + @Override + public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) { + final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>(); + add(result, context, R.string.touch_sound_settings); + add(result, context, R.string.dial_pad_tones_title); + add(result, context, R.string.screen_locking_sounds_title); + add(result, context, R.string.other_touch_sounds_title); + add(result, context, R.string.vibrate_on_touch_title); + return result; + } + + private void add(List<SearchIndexableRaw> result, Context context, int title) { + final Resources res = context.getResources(); + final SearchIndexableRaw data = new SearchIndexableRaw(context); + data.title = res.getString(title); + data.screenTitle = res.getString(R.string.touch_sound_settings); + result.add(data); + } + }; + + // === Callbacks === + + private final class SettingsObserver extends ContentObserver { + public SettingsObserver() { + super(mHandler); + } + + public void register(boolean register) { + final ContentResolver cr = getContentResolver(); + if (register) { + cr.registerContentObserver(mDialPadTones.getUri(), false, this); + cr.registerContentObserver(mScreenLockingSounds.getUri(), false, this); + cr.registerContentObserver(mOtherTouchSounds.getUri(), false, this); + cr.registerContentObserver(mVibrateOnTouch.getUri(), false, this); + } else { + cr.unregisterContentObserver(this); + } + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + super.onChange(selfChange, uri); + if (mDialPadTones.getUri().equals(uri)) { + mDialPadTones.update(); + } + if (mScreenLockingSounds.getUri().equals(uri)) { + mScreenLockingSounds.update(); + } + if (mOtherTouchSounds.getUri().equals(uri)) { + mOtherTouchSounds.update(); + } + if (mVibrateOnTouch.getUri().equals(uri)) { + mVibrateOnTouch.update(); + } + } + } +} diff --git a/src/com/android/settings/notification/VolumeSeekBarPreference.java b/src/com/android/settings/notification/VolumeSeekBarPreference.java new file mode 100644 index 0000000..5b0621d --- /dev/null +++ b/src/com/android/settings/notification/VolumeSeekBarPreference.java @@ -0,0 +1,97 @@ +/* + * 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.content.ContentResolver; +import android.content.Context; +import android.media.AudioManager; +import android.net.Uri; +import android.preference.PreferenceManager; +import android.preference.SeekBarPreference; +import android.preference.SeekBarVolumizer; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; +import android.widget.SeekBar; + +import com.android.settings.R; + +/** A slider preference that directly controls an audio stream volume (no dialog) **/ +public class VolumeSeekBarPreference extends SeekBarPreference + implements PreferenceManager.OnActivityStopListener { + private static final String TAG = "VolumeSeekBarPreference"; + + private final Context mContext; + + private int mStream; + private SeekBar mSeekBar; + private SeekBarVolumizer mVolumizer; + private Callback mCallback; + + public VolumeSeekBarPreference(Context context, AttributeSet attrs) { + super(context, attrs); + mContext = context; + } + + public void setStream(int stream) { + mStream = stream; + } + + public void setCallback(Callback callback) { + mCallback = callback; + } + + @Override + public void onActivityStop() { + if (mVolumizer != null) { + mVolumizer.stop(); + } + } + + @Override + protected void onBindView(View view) { + super.onBindView(view); + if (mStream == 0) { + Log.w(TAG, "No stream found, not binding volumizer"); + return; + } + getPreferenceManager().registerOnActivityStopListener(this); + final SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar); + if (seekBar == mSeekBar) return; + mSeekBar = seekBar; + final SeekBarVolumizer.Callback sbvc = new SeekBarVolumizer.Callback() { + @Override + public void onSampleStarting(SeekBarVolumizer sbv) { + if (mCallback != null) { + mCallback.onSampleStarting(sbv); + } + } + }; + final Uri sampleUri = mStream == AudioManager.STREAM_MUSIC ? getMediaVolumeUri() : null; + mVolumizer = new SeekBarVolumizer(mContext, seekBar, mStream, sampleUri, sbvc); + } + + private Uri getMediaVolumeUri() { + return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + + mContext.getPackageName() + + "/" + R.raw.media_volume); + } + + public interface Callback { + void onSampleStarting(SeekBarVolumizer sbv); + } +} diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java index e5ffd67..f72bde0 100644 --- a/src/com/android/settings/notification/ZenModeSettings.java +++ b/src/com/android/settings/notification/ZenModeSettings.java @@ -329,7 +329,7 @@ public class ZenModeSettings extends SettingsPreferenceFragment implements Index if (automatic == null || automatic.length == 0) { return null; } - final String divider = getString(R.string.zen_mode_entry_conditions_summary_divider); + 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); diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java index 80aef85..e3f004d 100644 --- a/src/com/android/settings/search/SearchIndexableResources.java +++ b/src/com/android/settings/search/SearchIndexableResources.java @@ -36,7 +36,10 @@ import com.android.settings.deviceinfo.Memory; import com.android.settings.fuelgauge.PowerUsageSummary; import com.android.settings.inputmethod.InputMethodAndLanguageSettings; import com.android.settings.location.LocationSettings; +import com.android.settings.notification.AppNotificationSettings; +import com.android.settings.notification.NotificationDisplaySettings; import com.android.settings.notification.NotificationSettings; +import com.android.settings.notification.TouchSoundSettings; import com.android.settings.notification.ZenModeSettings; import com.android.settings.print.PrintSettingsFragment; import com.android.settings.users.UserSettings; @@ -137,12 +140,30 @@ public final class SearchIndexableResources { NotificationSettings.class.getName(), R.drawable.ic_settings_notifications)); + sResMap.put(NotificationDisplaySettings.class.getName(), + new SearchIndexableResource(RANK_NOTIFICATIONS, + R.xml.notification_display_settings, + NotificationDisplaySettings.class.getName(), + R.drawable.ic_settings_notifications)); + + sResMap.put(TouchSoundSettings.class.getName(), + new SearchIndexableResource(RANK_NOTIFICATIONS, + R.xml.touch_sound_settings, + TouchSoundSettings.class.getName(), + R.drawable.ic_settings_notifications)); + sResMap.put(ZenModeSettings.class.getName(), new SearchIndexableResource(RANK_NOTIFICATIONS, NO_DATA_RES_ID, ZenModeSettings.class.getName(), R.drawable.ic_settings_notifications)); + sResMap.put(AppNotificationSettings.class.getName(), + new SearchIndexableResource(RANK_NOTIFICATIONS, + NO_DATA_RES_ID, + AppNotificationSettings.class.getName(), + R.drawable.ic_settings_notifications)); + sResMap.put(Memory.class.getName(), new SearchIndexableResource(RANK_MEMORY, NO_DATA_RES_ID, |