Merge "Improve power fail/reset"
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/dashboard.xml b/res/layout/dashboard.xml
index 116580a..e63acd7 100644
--- a/res/layout/dashboard.xml
+++ b/res/layout/dashboard.xml
@@ -27,6 +27,7 @@
android:id="@+id/dashboard_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:paddingBottom="12dp"
android:layout_gravity="center_horizontal"
android:orientation="vertical"
/>
diff --git a/res/layout/dashboard_category.xml b/res/layout/dashboard_category.xml
index 8abbee2..74d7ed5 100644
--- a/res/layout/dashboard_category.xml
+++ b/res/layout/dashboard_category.xml
@@ -22,9 +22,10 @@
<TextView android:id="@+id/category_title"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="@dimen/dashboard_category_title_height"
android:singleLine="true"
android:ellipsize="marquee"
+ android:gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textAlignment="viewStart"
/>
diff --git a/res/layout/nfc_payment_option.xml b/res/layout/nfc_payment_option.xml
index 04fdc07..76fea4f 100644
--- a/res/layout/nfc_payment_option.xml
+++ b/res/layout/nfc_payment_option.xml
@@ -19,7 +19,7 @@
android:layout_weight="1"
android:id="@+id/nfc_payment_pref"
android:focusable="true"
- android:clickable="true"
+ android:clickable="false"
android:gravity="center_vertical"
android:paddingTop="10dp"
android:paddingBottom="10dp"
@@ -37,6 +37,7 @@
android:layout_width="wrap_content"
android:layout_height="96dp"
android:scaleType="centerInside"
+ android:clickable="true"
/>
</FrameLayout>
<RadioButton
@@ -46,6 +47,6 @@
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:duplicateParentState="true"
- android:clickable="false"
+ android:clickable="true"
android:focusable="false" />
</RelativeLayout>
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/dimens.xml b/res/values/dimens.xml
index 562dd80..fdd8ed0 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -88,4 +88,6 @@
<!-- Dashboard padding between each tiles within the layout -->
<dimen name="dashboard_cell_gap">4dp</dimen>
+ <dimen name="dashboard_category_title_height">48dp</dimen>
+
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index aa0c77d..f2c00f3 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -44,13 +44,13 @@
<!-- Category headings in left-pane header menu --> <skip />
<!-- Settings main menu category heading. Wireless and networks (Wi-Fi, Bluetooth, data usage...). [CHAR LIMIT=40] -->
- <string name="header_category_wireless_networks">WIRELESS & NETWORKS</string>
+ <string name="header_category_wireless_networks">Wireless & Networks</string>
<!-- Settings main menu category heading. Device (Sound, display, battery, applications...). [CHAR LIMIT=40] -->
- <string name="header_category_device">DEVICE</string>
+ <string name="header_category_device">Device</string>
<!-- Settings main menu category heading. Personal (Accounts, security, language, backup...). [CHAR LIMIT=40] -->
- <string name="header_category_personal">PERSONAL</string>
+ <string name="header_category_personal">Personal</string>
<!-- Settings main menu category heading. System (Updates, data, accessibility, about phone). [CHAR LIMIT=40] -->
- <string name="header_category_system">SYSTEM</string>
+ <string name="header_category_system">System</string>
<!-- Phone info -->
<!-- Phone Info screen. Button label to turn on the radio . Only shown in diagnostic screen, so precise translation is not needed. -->
@@ -737,35 +737,27 @@
<!-- Title of the preferences item to control encryption -->
<string name="crypt_keeper_encrypt_title" product="default">Encrypt phone</string>
- <!-- Summary of the preferences item to control encryption, when encryption is inactive -->
- <string name="crypt_keeper_encrypt_summary" product="tablet">
- Require a numeric PIN or password to decrypt your tablet each time you
- power it on</string>
- <!-- Summary of the preferences item to control encryption, when encryption is inactive -->
- <string name="crypt_keeper_encrypt_summary" product="default">
- Require a numeric PIN or password to decrypt your phone each time you
- power it on</string>
<!-- Summary of the preferences item to control encryption, when encryption is active -->
<string name="crypt_keeper_encrypted_summary">Encrypted</string>
<!-- Informational text in the first confirmation screen before starting device encryption -->
<string name="crypt_keeper_desc" product="tablet">
You can encrypt your accounts, settings, downloaded apps and their data,
- media, and other files. Once you encrypt your tablet, you need to type a numeric PIN
- or password to decrypt it each time you power it on. You can\'t decrypt your tablet
- except by performing a factory data reset, erasing all your data.\n\nEncryption takes
- an hour or more. You must start with a charged battery and keep your tablet plugged in
- until encryption is complete. If you interrupt the encryption process, you will lose
- some or all of your data.</string>
+ media, and other files. After you encrypt your tablet, assuming you\’ve set up a screen lock
+ (that is, a pattern or numeric PIN or password), you\'ll need to unlock the screen to decrypt
+ the tablet every time you power it on. The only other way to decrypt is to perform a factory
+ data reset, erasing all your data.\n\nEncryption takes an hour or more. You must start with
+ a charged battery and keep your tablet plugged in throughout the process. If you interrupt,
+ you\’ll lose some or all of your data</string>
<!-- Informational text in the first confirmation screen before starting device encryption -->
<string name="crypt_keeper_desc" product="default">
You can encrypt your accounts, settings, downloaded apps and their data,
- media, and other files. Once you encrypt your phone, you need to type a numeric PIN or
- password to decrypt it each time you power it on. You can\'t decrypt your phone
- except by performing a factory data reset, erasing all your data.\n\nEncryption takes
- an hour or more. You must start with a charged battery and keep your phone plugged in
- until encryption is complete. If you interrupt the encryption process, you will lose
- some or all of your data.</string>
+ media, and other files. After you encrypt your phone, assuming you’ve set up a screen lock
+ (that is, a pattern or numeric PIN or password), you\'ll need to unlock the screen to decrypt
+ the phone every time you power it on. The only other way to decrypt is to perform a factory
+ data reset, erasing all your data.\n\nEncryption takes an hour or more. You must start with
+ a charged battery and keep your phone plugged in throughout the process. If you interrupt,
+ you\’ll lose some or all of your data.</string>
<!-- Button text to start encryption process -->
<string name="crypt_keeper_button_text" product="tablet">Encrypt tablet</string>
@@ -1028,63 +1020,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 +1713,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 +1725,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 +1770,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>
@@ -4366,6 +4294,10 @@
<string name="status_wimax_mac_address">4G MAC address</string>
<!-- This is displayed to the user when the device needs to be decrypted -->
<string name="enter_password">Type password to decrypt storage</string>
+ <!-- Informational text on the pin entry screen prompting the user for their pin -->
+ <string name="enter_pin">Enter your PIN to decrypt storage</string>
+ <!-- Informational text on the pattern entry screen prompting the user for their pattern -->
+ <string name="enter_pattern">Draw your pattern to decrypt storage</string>
<!-- This is displayed when the password is entered incorrectly -->
<string name="try_again">Try again.</string>
@@ -4957,6 +4889,9 @@
<string name="nfc_payment_settings_title">Tap & pay</string>
<!-- String shown when there are no NFC payment applications installed -->
<string name="nfc_payment_no_apps">Pay with just a tap</string>
+ <!-- String shown before a checkbox, allowing the user to indicate that he wants foreground apps
+ to be able to override the configured default app -->
+ <string name="nfc_payment_favor_foreground">Favor foreground app</string>
<!-- String shown when there are no NFC payment applications installed, clickable, pointing to
a website to learn more-->
<string name="nfc_payment_learn_more">Learn more</string>
@@ -5107,39 +5042,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]-->
@@ -5160,17 +5062,170 @@
<!-- Option title for the default sound, context based on screen -->
<string name="default_sound">Default sound</string>
+
+ <!-- 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>
+
+ <!-- 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=40] Notification settings: App notifications screen title -->
- <string name="app_notifications_title">App notifications</string>
-
- <!-- [CHAR LIMIT=30] Notification settings: App notifications dialog show option -->
+ <!-- [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>
@@ -5190,8 +5245,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>
@@ -5238,6 +5293,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/values/styles.xml b/res/values/styles.xml
index f9e7b2b..bc584bb 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -242,10 +242,6 @@
<item name="android:widgetLayout">@layout/preference_inputmethod_widget</item>
</style>
- <style name="TextAppearance.Switch" parent="@*android:style/TextAppearance.Quantum.Widget.Switch">
- <item name="android:textAllCaps">true</item>
- </style>
-
<style name="TextAppearance.PagerTabs" parent="@android:style/TextAppearance.Quantum.Small">
<item name="android:textAllCaps">true</item>
<item name="android:textStyle">bold</item>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 97dc0d4..9612530 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -59,7 +59,7 @@
<item name="wifi_signal">@drawable/wifi_signal_light</item>
</style>
- <style name="Theme.Settings" parent="@android:style/Theme.Quantum.Light">
+ <style name="Theme.Settings" parent="@android:style/Theme.Quantum.Light.DarkActionBar">
<item name="@*android:preferenceHeaderPanelStyle">@style/PreferenceHeaderPanelSinglePane</item>
<item name="@*android:preferencePanelStyle">@style/PreferencePanelSinglePane</item>
<item name="@*android:preferenceListStyle">@style/PreferenceHeaderListSinglePane</item>
@@ -71,22 +71,11 @@
<item name="ic_wps">@drawable/ic_wps_dark</item>
<item name="wifi_signal">@drawable/wifi_signal_dark</item>
- <item name="android:actionBarTheme">@style/Theme.Settings.ActionBar.Quantum</item>
-
<item name="android:colorPrimary">@color/actionbar_background_color</item>
- <item name="android:colorPrimaryLight">@color/quantum_blue_grey_100</item>
- <item name="android:colorPrimaryDark">@color/quantum_blue_grey_700</item>
- <item name="android:colorAccent">@color/quantum_orange_A200</item>
- </style>
-
- <style name="Theme.Settings.ActionBar.Quantum" parent="@android:style/Theme.Quantum">
- <!--Set the background color-->
- <item name="android:colorPrimary">@color/actionbar_background_color</item>
- <!--Set the activated state color for the on/off switches-->
- <item name="android:colorControlActivated">?android:attr/colorControlNormal</item>
- <!--Other colors-->
- <item name="android:colorPrimaryLight">@color/quantum_blue_grey_100</item>
- <item name="android:colorPrimaryDark">@color/quantum_blue_grey_700</item>
+ <!-- Used by the bouncing effect for ListView and ScrollView -->
+ <item name="android:colorPrimaryLight">@color/actionbar_background_color</item>
+ <!-- Used by the StatusBar and NavBar -->
+ <item name="android:colorPrimaryDark">@color/actionbar_background_color</item>
<item name="android:colorAccent">@color/quantum_orange_A200</item>
</style>
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">
+ <!-- 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" />
+
+ <!-- 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" />
+
+ <!-- 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="ringer_mode"
+ android:title="@string/ringer_mode_title"
+ android:persistent="false" />
+
+ <!-- Phone ringtone -->
<com.android.settings.DefaultRingtonePreference
- android:key="notification_sound"
- android:title="@string/default_sound"
- android:dialogTitle="@string/notification_sound_dialog_title"
+ android:key="ringtone"
+ android:title="@string/ringtone_title"
+ android:dialogTitle="@string/ringtone_title"
+ android:persistent="false"
+ android:ringtoneType="ringtone" />
+
+ <!-- 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" />
- <CheckBoxPreference
- android:key="notification_pulse"
- android:title="@string/notification_pulse_title"
+ <!-- Vibrate when ringing -->
+ <SwitchPreference
+ android:key="vibrate_when_ringing"
+ android:title="@string/vibrate_when_ringing_title"
+ android:switchTextOff=""
+ android:switchTextOn=""
android:persistent="false" />
- <CheckBoxPreference
- android:key="heads_up"
- android:title="@string/heads_up_enabled_title"
- 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" />
- <com.android.settings.notification.DropDownPreference
- android:key="toggle_lock_screen_notifications"
- android:title="@string/lock_screen_notifications"
- android:persistent="false" />
+ <!-- Touch sounds -->
+ <Preference
+ android:key="touch_sounds"
+ android:title="@string/touch_sound_settings"
+ android:persistent="false"
+ android:fragment="com.android.settings.notification.TouchSoundSettings" />
- <PreferenceScreen
- android:key="configure"
- android:title="@string/notification_settings_apps_title"
- android:fragment="com.android.settings.notification.AppNotificationSettings" />
-
- <PreferenceScreen
- android:key="zen_mode"
- android:title="@string/title_zen_mode"
- android:fragment="com.android.settings.notification.ZenModeSettings" />
-
+ <!-- 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/security_settings_unencrypted.xml b/res/xml/security_settings_unencrypted.xml
index 00213df..947317c 100644
--- a/res/xml/security_settings_unencrypted.xml
+++ b/res/xml/security_settings_unencrypted.xml
@@ -23,7 +23,6 @@
<PreferenceScreen
android:key="encryption"
android:title="@string/crypt_keeper_encrypt_title"
- android:summary="@string/crypt_keeper_encrypt_summary"
android:fragment="com.android.settings.CryptKeeperSettings" />
</PreferenceCategory>
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/CryptKeeper.java b/src/com/android/settings/CryptKeeper.java
index c4e3e66..661e304 100644
--- a/src/com/android/settings/CryptKeeper.java
+++ b/src/com/android/settings/CryptKeeper.java
@@ -398,9 +398,11 @@
public void onPostExecute(java.lang.Void v) {
if(type == StorageManager.CRYPT_TYPE_PIN) {
setContentView(R.layout.crypt_keeper_pin_entry);
+ ((TextView)findViewById(R.id.status)).setText(R.string.enter_pin);
} else if (type == StorageManager.CRYPT_TYPE_PATTERN) {
setContentView(R.layout.crypt_keeper_pattern_entry);
setBackFunctionality(false);
+ ((TextView)findViewById(R.id.status)).setText(R.string.enter_pattern);
} else {
setContentView(R.layout.crypt_keeper_password_entry);
}
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index d21e4ab..cc7a116 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -387,19 +387,6 @@
mEnabledSwitch.setEnabled(false);
return;
}
- mSwitchBar.addOnSwitchChangeListener(this);
- }
-
- @Override
- public void onStart() {
- super.onStart();
- mSwitchBar.show();
- }
-
- @Override
- public void onStop() {
- super.onStop();
- mSwitchBar.hide();
}
private boolean removePreferenceForProduction(Preference preference) {
@@ -464,6 +451,17 @@
mEnabledSwitch.setChecked(mLastEnabledState);
setPrefsEnabledState(mLastEnabledState);
}
+
+ mSwitchBar.addOnSwitchChangeListener(this);
+ mSwitchBar.show();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+
+ mSwitchBar.removeOnSwitchChangeListener(this);
+ mSwitchBar.hide();
}
void updateCheckBox(CheckBoxPreference checkBox, boolean value) {
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.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 @@
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 @@
}
@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 25378086..38176eb 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -88,6 +88,9 @@
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/applications/AppOpsSummary.java b/src/com/android/settings/applications/AppOpsSummary.java
index 4cee8e5..92515ac 100644
--- a/src/com/android/settings/applications/AppOpsSummary.java
+++ b/src/com/android/settings/applications/AppOpsSummary.java
@@ -16,7 +16,6 @@
package com.android.settings.applications;
-import android.app.AppOpsManager;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
diff --git a/src/com/android/settings/nfc/PaymentBackend.java b/src/com/android/settings/nfc/PaymentBackend.java
index f84bc74..25572a7 100644
--- a/src/com/android/settings/nfc/PaymentBackend.java
+++ b/src/com/android/settings/nfc/PaymentBackend.java
@@ -24,6 +24,7 @@
import android.nfc.cardemulation.ApduServiceInfo;
import android.nfc.cardemulation.CardEmulation;
import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
import java.util.ArrayList;
import java.util.List;
@@ -74,6 +75,20 @@
return appInfos;
}
+ boolean isForegroundMode() {
+ try {
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.NFC_PAYMENT_FOREGROUND) != 0;
+ } catch (SettingNotFoundException e) {
+ return false;
+ }
+ }
+
+ void setForegroundMode(boolean foreground) {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.NFC_PAYMENT_FOREGROUND, foreground ? 1 : 0) ;
+ }
+
ComponentName getDefaultPaymentApp() {
String componentString = Settings.Secure.getString(mContext.getContentResolver(),
Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT);
diff --git a/src/com/android/settings/nfc/PaymentDefaultDialog.java b/src/com/android/settings/nfc/PaymentDefaultDialog.java
index 61c6fdb..6bc29e1 100644
--- a/src/com/android/settings/nfc/PaymentDefaultDialog.java
+++ b/src/com/android/settings/nfc/PaymentDefaultDialog.java
@@ -19,14 +19,7 @@
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.nfc.cardemulation.ApduServiceInfo;
import android.nfc.cardemulation.CardEmulation;
-import android.nfc.cardemulation.HostApduService;
-import android.nfc.cardemulation.OffHostApduService;
import android.os.Bundle;
import android.util.Log;
@@ -35,11 +28,8 @@
import com.android.settings.R;
import com.android.settings.nfc.PaymentBackend.PaymentAppInfo;
-import java.io.IOException;
import java.util.List;
-import org.xmlpull.v1.XmlPullParserException;
-
public final class PaymentDefaultDialog extends AlertActivity implements
DialogInterface.OnClickListener {
diff --git a/src/com/android/settings/nfc/PaymentSettings.java b/src/com/android/settings/nfc/PaymentSettings.java
index 7548c50..df4e396 100644
--- a/src/com/android/settings/nfc/PaymentSettings.java
+++ b/src/com/android/settings/nfc/PaymentSettings.java
@@ -22,7 +22,9 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.preference.CheckBoxPreference;
import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.provider.Settings;
@@ -48,7 +50,7 @@
import java.util.List;
public class PaymentSettings extends SettingsPreferenceFragment implements
- OnClickListener {
+ OnClickListener, OnPreferenceChangeListener {
public static final String TAG = "PaymentSettings";
private LayoutInflater mInflater;
private PaymentBackend mPaymentBackend;
@@ -67,6 +69,7 @@
public void refresh() {
PreferenceManager manager = getPreferenceManager();
PreferenceScreen screen = manager.createPreferenceScreen(getActivity());
+
// Get all payment services
List<PaymentAppInfo> appInfos = mPaymentBackend.getPaymentAppInfos();
if (appInfos != null && appInfos.size() > 0) {
@@ -92,6 +95,13 @@
emptyImage.setVisibility(View.VISIBLE);
getListView().setVisibility(View.GONE);
} else {
+ CheckBoxPreference foreground = new CheckBoxPreference(getActivity());
+ boolean foregroundMode = mPaymentBackend.isForegroundMode();
+ foreground.setPersistent(false);
+ foreground.setTitle(getString(R.string.nfc_payment_favor_foreground));
+ foreground.setChecked(foregroundMode);
+ foreground.setOnPreferenceChangeListener(this);
+ screen.addPreference(foreground);
emptyText.setVisibility(View.GONE);
learnMore.setVisibility(View.GONE);
emptyImage.setVisibility(View.GONE);
@@ -207,14 +217,25 @@
protected void onBindView(View view) {
super.onBindView(view);
- view.setOnClickListener(listener);
- view.setTag(appInfo);
-
RadioButton radioButton = (RadioButton) view.findViewById(android.R.id.button1);
radioButton.setChecked(appInfo.isDefault);
+ radioButton.setOnClickListener(listener);
+ radioButton.setTag(appInfo);
ImageView banner = (ImageView) view.findViewById(R.id.banner);
banner.setImageDrawable(appInfo.banner);
+ banner.setOnClickListener(listener);
+ banner.setTag(appInfo);
+ }
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (preference instanceof CheckBoxPreference) {
+ mPaymentBackend.setForegroundMode(((Boolean) newValue).booleanValue());
+ return true;
+ } else {
+ return false;
}
}
}
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.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.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.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 @@
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 @@
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 @@
}
};
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 @@
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 @@
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 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 @@
});
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 @@
});
}
+ 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 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 @@
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 @@
// 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();
+ public void onPause() {
+ super.onPause();
+ mVolumeCallback.stopSample();
+ mContext.unregisterReceiver(mReceiver);
+ mSettingsObserver.register(false);
+ }
- 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);
+ // === Volumes ===
+
+ private void initVolumePreference(String key, int stream) {
+ final VolumeSeekBarPreference volumePref = (VolumeSeekBarPreference) findPreference(key);
+ volumePref.setStream(stream);
+ volumePref.setCallback(mVolumeCallback);
+ }
+
+ 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);
+ }
}
- return true;
+ 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 onPreferenceChange(Preference preference, Object objValue) {
- return true;
+ private void updateRingerMode() {
+ final AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+ mRingerMode.setSelectedValue(am.getRingerMode());
}
- @Override
- public boolean onPreferenceClick(Preference preference) {
- return false;
+ // === Phone & notification ringtone ===
+
+ private void initRingtones(PreferenceScreen root) {
+ mPhoneRingtonePreference = root.findPreference(KEY_PHONE_RINGTONE);
+ mNotificationRingtonePreference = root.findPreference(KEY_NOTIFICATION_RINGTONE);
}
- // === Heads-up notifications ===
-
- 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 lookupRingtoneNames() {
+ AsyncTask.execute(mLookupRingtoneNames);
}
- 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 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();
+ }
+ }
+ }
+ };
+
+ // === 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);
+ }
+ });
}
- // === Lockscreen (public / private) notifications ===
-
- private boolean getDeviceLockscreenNotificationsEnabled() {
- return 0 != Settings.Global.getInt(getContentResolver(),
- Settings.Global.LOCK_SCREEN_SHOW_NOTIFICATIONS, 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 @@
}
}
- // === Ringtone ===
+ // === Indexing ===
- private void lookupRingtoneNames() {
- new Thread(mRingtoneLookupRunnable).start();
+ 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 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/NotificationStation.java b/src/com/android/settings/notification/NotificationStation.java
index 69a7a89..3f37f6d 100644
--- a/src/com/android/settings/notification/NotificationStation.java
+++ b/src/com/android/settings/notification/NotificationStation.java
@@ -35,8 +35,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
-import android.service.notification.INotificationListener;
-import android.service.notification.NotificationOrderUpdate;
+import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.view.LayoutInflater;
@@ -73,14 +72,13 @@
}
};
- private INotificationListener.Stub mListener = new INotificationListener.Stub() {
+ private NotificationListenerService mListener = new NotificationListenerService() {
@Override
- public void onListenerConnected(NotificationOrderUpdate update) throws RemoteException {
+ public void onListenerConnected(String[] notificationKeys) {
// noop
}
@Override
- public void onNotificationPosted(StatusBarNotification notification,
- NotificationOrderUpdate update) throws RemoteException {
+ public void onNotificationPosted(StatusBarNotification notification) {
Log.v(TAG, "onNotificationPosted: " + notification);
final Handler h = getListView().getHandler();
h.removeCallbacks(mRefreshListRunnable);
@@ -88,17 +86,11 @@
}
@Override
- public void onNotificationRemoved(StatusBarNotification notification,
- NotificationOrderUpdate update) throws RemoteException {
+ public void onNotificationRemoved(StatusBarNotification notification) {
final Handler h = getListView().getHandler();
h.removeCallbacks(mRefreshListRunnable);
h.postDelayed(mRefreshListRunnable, 100);
}
-
- @Override
- public void onNotificationOrderUpdate(NotificationOrderUpdate update)
- throws RemoteException {
- }
};
private NotificationHistoryAdapter mAdapter;
@@ -122,16 +114,24 @@
mNoMan = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
try {
- mNoMan.registerListener(mListener,
- new ComponentName(mContext.getPackageName(),
- this.getClass().getCanonicalName()),
- ActivityManager.getCurrentUser());
+ mListener.registerAsSystemService(new ComponentName(mContext.getPackageName(),
+ this.getClass().getCanonicalName()), ActivityManager.getCurrentUser());
} catch (RemoteException e) {
// well, that didn't work out
}
}
@Override
+ public void onDetach() {
+ try {
+ mListener.unregisterAsSystemService();
+ } catch (RemoteException e) {
+ // well, that didn't work out
+ }
+ super.onDetach();
+ }
+
+ @Override
public void onCreate(Bundle icicle) {
logd("onCreate(%s)", icicle);
super.onCreate(icicle);
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 @@
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.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 @@
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,