Merge "Fix new DataUsageSummary page line spacing." into pi-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index d0ed638..a94938e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -87,6 +87,7 @@
<uses-permission android:name="android.permission.DELETE_PACKAGES"/>
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
<uses-permission android:name="android.permission.MANAGE_APP_OPS_RESTRICTIONS"/>
+ <uses-permission android:name="android.permission.MANAGE_APP_OPS_MODES" />
<uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"/>
<uses-permission android:name="android.permission.READ_PRINT_SERVICES" />
<uses-permission android:name="android.permission.NETWORK_SETTINGS" />
@@ -746,7 +747,7 @@
android:taskAffinity="com.android.settings"
android:parentActivityName="Settings">
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
- android:value="com.android.settings.notification.ZenModeBlockedEffectsSetting" />
+ android:value="com.android.settings.notification.ZenModeBlockedEffectsSettings" />
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
</activity>
@@ -3231,7 +3232,7 @@
</activity>
<provider android:name=".slices.SettingsSliceProvider"
- android:authorities="com.android.settings.slices"
+ android:authorities="com.android.settings.slices;android.settings.slices"
android:exported="true">
</provider>
diff --git a/res/layout/data_usage_summary_preference.xml b/res/layout/data_usage_summary_preference.xml
index c2cb841..c1a676a 100644
--- a/res/layout/data_usage_summary_preference.xml
+++ b/res/layout/data_usage_summary_preference.xml
@@ -101,7 +101,8 @@
android:id="@+id/data_limits"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingBottom="5dp" />
+ android:paddingBottom="5dp"
+ android:textColor="?android:attr/textColorSecondary" />
</LinearLayout>
diff --git a/res/layout/instant_app_buttons.xml b/res/layout/instant_app_buttons.xml
index 1ef9f41..f80ac10 100644
--- a/res/layout/instant_app_buttons.xml
+++ b/res/layout/instant_app_buttons.xml
@@ -48,11 +48,16 @@
<Space
android:layout_width="16dp"
android:layout_height="wrap_content" />
- <Button
- android:id="@+id/clear_data"
+ <FrameLayout
android:layout_width="0dp"
android:layout_weight="1"
- android:layout_height="wrap_content"
- android:layout_marginBottom="4dp"
- android:text="@string/clear_instant_app_data"/>
+ android:layout_height="wrap_content">
+ <Button
+ android:id="@+id/clear_data"
+ style="@style/ActionSecondaryButton"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="4dp"
+ android:text="@string/clear_instant_app_data"/>
+ </FrameLayout>
</LinearLayout>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index d37091c..d0ddab6 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -96,8 +96,12 @@
<!-- For Search -->
<declare-styleable name="Preference">
+ <!-- Synonyms for search results -->
<attr name="keywords" format="string" />
+ <!-- Classname of a PreferenceController corresponding to the preference -->
<attr name="controller" format="string" />
+ <!-- {@code true} when the controller declared represents a slice from {@link android.app.SettingsSliceContract} -->
+ <attr name="platform_slice" format="boolean" />
</declare-styleable>
<!-- For DotsPageIndicator -->
diff --git a/res/values/bools.xml b/res/values/bools.xml
index 4665f2e..61a3c75 100644
--- a/res/values/bools.xml
+++ b/res/values/bools.xml
@@ -96,6 +96,9 @@
<!-- Whether device_administrators should be shown or not. -->
<bool name="config_show_device_administrators">true</bool>
+ <!-- Whether encryption_and_credentials_encryption_status should be shown or not. -->
+ <bool name="config_show_encryption_and_credentials_encryption_status">true</bool>
+
<!-- Whether premium_sms should be shown or not. -->
<bool name="config_show_premium_sms">true</bool>
@@ -153,6 +156,9 @@
<!-- Whether assist_and_voice_input should be shown or not. -->
<bool name="config_show_assist_and_voice_input">true</bool>
+ <!-- Whether reset_dashboard should be shown or not. -->
+ <bool name="config_show_reset_dashboard">true</bool>
+
<!-- Whether system_update_settings should be shown or not. -->
<bool name="config_show_system_update_settings">true</bool>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c64880e..978c294 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1136,25 +1136,25 @@
<!-- Security Picker --><skip />
- <!-- Title for suggested actions for screen lock [CHAR LIMIT=34] -->
- <string name="suggested_lock_settings_title">Set screen lock for security</string>
+ <!-- Title for suggested actions for screen lock [CHAR LIMIT=46] -->
+ <string name="suggested_lock_settings_title">Secure your phone</string>
- <!-- Summary for suggested actions for screen lock (tablet) -->
- <string name="suggested_lock_settings_summary" product="tablet">Prevent others from using your tablet</string>
- <!-- Summary for suggested actions for screen lock (device) -->
- <string name="suggested_lock_settings_summary" product="device">Prevent others from using your device</string>
- <!-- Summary for suggested actions for screen lock (phone) -->
- <string name="suggested_lock_settings_summary" product="default">Prevent others from using your phone</string>
+ <!-- Summary for suggested actions for screen lock (tablet) [CHAR LIMIT=55] -->
+ <string name="suggested_lock_settings_summary" product="tablet">Set screen lock to protect tablet</string>
+ <!-- Summary for suggested actions for screen lock (device) [CHAR LIMIT=55] -->
+ <string name="suggested_lock_settings_summary" product="device">Set screen lock to protect device</string>
+ <!-- Summary for suggested actions for screen lock (phone) [CHAR LIMIT=55] -->
+ <string name="suggested_lock_settings_summary" product="default">Set screen lock to protect phone</string>
- <!-- Title for suggested actions for settings up a fingerprint lock [CHAR LIMIT=34] -->
+ <!-- Title for suggested actions for settings up a fingerprint lock [CHAR LIMIT=46] -->
<string name="suggested_fingerprint_lock_settings_title">Unlock with fingerprint</string>
- <!-- Summary for suggested actions for settings up a fingerprint lock (tablet) -->
- <string name="suggested_fingerprint_lock_settings_summary" product="tablet">Unlock with your fingerprint</string>
- <!-- Summary for suggested actions for settings up a fingerprint lock (device) -->
- <string name="suggested_fingerprint_lock_settings_summary" product="device">Unlock with your fingerprint</string>
- <!-- Summary for suggested actions for settings up a fingerprint lock (phone) -->
- <string name="suggested_fingerprint_lock_settings_summary" product="default">Unlock with your fingerprint</string>
+ <!-- Summary for suggested actions for settings up a fingerprint lock (tablet) [CHAR LIMIT=55] -->
+ <string name="suggested_fingerprint_lock_settings_summary" product="tablet"></string>
+ <!-- Summary for suggested actions for settings up a fingerprint lock (device) [CHAR LIMIT=55] -->
+ <string name="suggested_fingerprint_lock_settings_summary" product="device"></string>
+ <!-- Summary for suggested actions for settings up a fingerprint lock (phone) [CHAR LIMIT=55] -->
+ <string name="suggested_fingerprint_lock_settings_summary" product="default"></string>
<!-- Title for security picker to choose the unlock method: None/Pattern/PIN/Password [CHAR LIMIT=22] -->
<string name="lock_settings_picker_title">Choose screen lock</string>
@@ -1676,10 +1676,10 @@
<string name="bluetooth_max_connected_audio_devices_string">Maximum connected Bluetooth audio devices</string>
<!-- Bluetooth developer settings: Maximum number of connected audio devices -->
<string name="bluetooth_max_connected_audio_devices_dialog_title">Select maximum number of connected Bluetooth audio devices</string>
- <!-- Bluetooth developer settings: Checkbox title for enabling Bluetooth receiving AVDTP delay reports -->
- <string name="bluetooth_enable_avdtp_delay_reports">Enable Bluetooth AVDTP delay reports</string>
- <!-- Bluetooth developer settings: Summary of checkbox for enabling Bluetooth receiving AVDTP delay reports -->
- <string name="bluetooth_enable_avdtp_delay_reports_summary">Allow receiving Bluetooth AVDTP delay reports</string>
+ <!-- Bluetooth developer settings: Checkbox title for disabling Bluetooth receiving AVDTP delay reports -->
+ <string name="bluetooth_disable_avdtp_delay_reports">Disable Bluetooth AVDTP delay reports</string>
+ <!-- Bluetooth developer settings: Summary of checkbox for disabling Bluetooth receiving AVDTP delay reports -->
+ <string name="bluetooth_disable_avdtp_delay_reports_summary">Disallow receiving Bluetooth AVDTP delay reports</string>
<!-- Wifi Display settings. The title of the screen. [CHAR LIMIT=40] -->
<string name="wifi_display_settings_title">Cast</string>
@@ -2251,10 +2251,10 @@
<!-- Wireless networks, item title to go into the WFC settings [CHAR LIMIT=30] -->
<string name="wifi_calling_settings_title">Wi-Fi calling</string>
- <!-- Title of suggestion to turn on wifi calling [CHAR LIMIT=30] -->
- <string name="wifi_calling_suggestion_title">Extend call coverage with Wi\u2011Fi</string>
- <!-- Summary of suggestion to turn on wifi calling [CHAR LIMIT=60] -->
- <string name="wifi_calling_suggestion_summary">Turn on Wi\u2011Fi calling</string>
+ <!-- Title of suggestion to turn on wifi calling [CHAR LIMIT=46] -->
+ <string name="wifi_calling_suggestion_title">Extend calls with Wi\u2011Fi</string>
+ <!-- Summary of suggestion to turn on wifi calling [CHAR LIMIT=55] -->
+ <string name="wifi_calling_suggestion_summary">Turn on Wi\u2011Fi calling to extend coverage</string>
<!-- Title of WFC preference item [CHAR LIMIT=30] -->
<string name="wifi_calling_mode_title">Calling preference</string>
<!-- Title of WFC preference selection dialog [CHAR LIMIT=30] -->
@@ -2532,9 +2532,9 @@
<string name="wallpaper_settings_summary_default">Default</string>
<!-- Wallpaper settings summary when wallpaper has been updated [CHAR LIMIT=NONE] -->
<string name="wallpaper_settings_summary_custom">Custom</string>
- <!-- Wallpaper suggestion title [CHAR LIMIT=30] -->
+ <!-- Wallpaper suggestion title [CHAR LIMIT=46] -->
<string name="wallpaper_suggestion_title">Change wallpaper</string>
- <!-- Wallpaper suggestion title [CHAR LIMIT=60] -->
+ <!-- Wallpaper suggestion summary [CHAR LIMIT=55] -->
<string name="wallpaper_suggestion_summary">Personalize your screen</string>
<!-- Wallpaper settings fragment title [CHAR LIMIT=30] -->
<string name="wallpaper_settings_fragment_title">Choose wallpaper from</string>
@@ -4177,10 +4177,6 @@
<string name="keyboard_shortcuts_helper">Keyboard shortcuts helper</string>
<!-- Summary text for the 'keyboard shortcuts helper' dialog. [CHAR LIMIT=100] -->
<string name="keyboard_shortcuts_helper_summary">Display available shortcuts</string>
- <!--
- Format string for a physical device in the form: InputMethodSubtype - InputMethodEditor.
- e.g. English (US) - X Keyboard -->
- <string name="physical_device_title" translatable="false"><xliff:g id="input_method_editor" example="X Keyboard">%1$s</xliff:g> - <xliff:g id="input_method_subtype" example="English (US)">%2$s</xliff:g></string>
<!-- Summary text for keyboards when no layout has been selected. [CHAR LIMIT=35] -->
<string name="default_keyboard_layout">Default</string>
@@ -4896,6 +4892,11 @@
<!-- CANCEL button for dialog to remove restriction for app [CHAR LIMIT=NONE] -->
<string name="battery_tip_unrestrict_app_dialog_cancel">Not now</string>
+ <!-- Message for battery tip dialog to show the battery summary -->
+ <string name="battery_tip_dialog_summary_message">Based on your usage, your battery usually lasts about <xliff:g id="time_duration">%1$s</xliff:g> when fully charged.\n\nIf you need to extend your battery life, turn on Battery Saver.</string>
+ <!-- Message for battery tip dialog to show the battery summary -->
+ <string name="battery_tip_dialog_summary_message_no_estimation">If you need to extend your battery life, turn on Battery Saver</string>
+
<!-- Title for the smart battery manager preference [CHAR LIMIT=NONE] -->
<string name="smart_battery_manager_title">Smart battery manager</string>
<!-- Title for the smart battery toggle [CHAR LIMIT=NONE] -->
@@ -6921,6 +6922,9 @@
<!-- Do not disturb: Title for the page describing what can bypass DND. [CHAR LIMIT=30] -->
<string name="zen_mode_behavior_settings_title">Exceptions</string>
+ <!-- Do not disturb: Title for the dnd duration setting (user can specify how long dnd will last when toggling dnd on from qs or settings) [CHAR LIMIT=30] -->
+ <string name="zen_mode_duration_settings_title">Duration</string>
+
<!-- Do not disturb: Instructions indicating what types of sounds can bypass DND. [CHAR LIMIT=52] -->
<string name="zen_mode_behavior_allow_title">Allow sounds and vibrations from</string>
@@ -6945,10 +6949,10 @@
<!-- Do not disturb: Title for a specific zen mode automatic rule in settings. [CHAR LIMIT=30] -->
<string name="zen_mode_automatic_rule_settings_page_title">Automatic rule</string>
- <!-- Do not disturb: Title for the zen mode automation option Suggestion. [CHAR LIMIT=34] -->
+ <!-- Do not disturb: Title for the zen mode automation option Suggestion. [CHAR LIMIT=46] -->
<string name="zen_mode_automation_suggestion_title">Silence phone at certain times</string>
- <!-- Do not disturb: Summary for the zen mode automation option Suggestion. [CHAR LIMIT=NONE] -->
+ <!-- Do not disturb: Summary for the zen mode automation option Suggestion. [CHAR LIMIT=55] -->
<string name="zen_mode_automation_suggestion_summary">Set Do Not Disturb rules</string>
<!-- Do not disturb: Switch toggle to toggle whether to use an automatic dnd rule or not [CHAR LIMIT=40] -->
@@ -7000,6 +7004,11 @@
<!-- Do not disturb: what to block summary, all effects -->
<string name="zen_mode_block_effect_summary_all">Sound, vibration, and visual signs of notifications</string>
+ <!-- Do not disturb: Zen mode no sounds are exceptions to bypass do not disturb-->
+ <string name="zen_mode_no_exceptions">None</string>
+ <!-- Do not disturb: Zen mode catch all "other" sounds can bypass do not disturb -->
+ <string name="zen_mode_other_options">other options</string>
+
<!-- Do not disturb: Button to add new automatic rule to DND. [CHAR LIMIT=30] -->
<string name="zen_mode_add">Add</string>
@@ -7030,8 +7039,8 @@
<!-- [CHAR LIMIT=20] Accessibility string for current zen mode and selected exit condition. A template that simply concatenates existing mode string and the current condition description. -->
<string name="zen_mode_and_condition"><xliff:g id="zen_mode" example="Priority interruptions only">%1$s</xliff:g>. <xliff:g id="exit_condition" example="For one hour">%2$s</xliff:g></string>
- <!-- Sound settings screen, summary format of do not disturb when on. [CHAR LIMIT=NONE] -->
- <string name="zen_mode_sound_summary_on">On / <xliff:g name="dnd_summary" example="No sound except alarms and media">%1$s</xliff:g></string>
+ <!-- Sound settings screen, summary format of do not disturb when on with extra info. [CHAR LIMIT=NONE] -->
+ <string name="zen_mode_sound_summary_on_with_info">On / <xliff:g name="dnd_summary" example="No sound except alarms and media">%1$s</xliff:g></string>
<!-- Sound settings screen, summary format of do not disturb when off with extra information. [CHAR LIMIT=NONE] -->
<string name="zen_mode_sound_summary_off_with_info">Off / <xliff:g name="dnd_summary" example="1 rule can turn on automatically">%1$s</xliff:g></string>
@@ -7039,6 +7048,24 @@
<!-- Sound settings screen, summary format of do not disturb when off with no extra information. [CHAR LIMIT=NONE] -->
<string name="zen_mode_sound_summary_off">Off</string>
+ <!-- Sound settings screen, summary format of do not disturb when on with no extra information. [CHAR LIMIT=NONE] -->
+ <string name="zen_mode_sound_summary_on">On</string>
+
+ <!-- Do not disturb: Summary for zen mode duration setting indicating user will be prompted to set dnd duration whenever dnd is manually toggled on [CHAR LIMIT=NONE]-->
+ <string name="zen_mode_duration_summary_always_prompt">Ask every time (unless turned on automatically)</string>
+
+ <!-- Do not disturb: Summary for zen mode duration setting indicating how long dnd will last when dnd is manually toggled on [CHAR LIMIT=NONE] -->
+ <string name="zen_mode_duration_summary_forever">Until you turn off (unless turned on automatically)</string>
+
+ <!-- Do not disturb: Summary for zen mode duration setting indicating how long dnd will last when dnd is manually toggled on [CHAR LIMIT=NONE] -->
+ <plurals name="zen_mode_duration_summary_time_hours">
+ <item quantity="one">1 hour (unless turned on automatically)</item>
+ <item quantity="other"><xliff:g id="num_hours" example="3">%d</xliff:g> hours (unless turned on automatically)</item>
+ </plurals>
+
+ <!-- Do not disturb: Summary for zen mode duration setting indicating how long dnd will last when toggled on -->
+ <string name="zen_mode_duration_summary_time_minutes"><xliff:g id="num_minutes" example="5">%d</xliff:g> minutes (unless turned on automatically)</string>
+
<!-- Summary for the Sound Do not Disturb option when at least one automatic rules is enabled. [CHAR LIMIT=NONE]-->
<plurals name="zen_mode_sound_summary_summary_off_info">
<item quantity="one">1 rule can turn on automatically</item>
@@ -7575,8 +7602,8 @@
<!-- [CHAR LIMIT=50] Zen mode settings: Media option -->
<string name="zen_mode_media">Media</string>
- <!-- [CHAR LIMIT=50] Zen mode settings: System option which includes sounds such as touch and charging sounds -->
- <string name="zen_mode_system">Touch and charging sounds</string>
+ <!-- [CHAR LIMIT=50] Zen mode settings: System option which includes sounds such as touch sounds -->
+ <string name="zen_mode_system">Touch sounds</string>
<!-- [CHAR LIMIT=50] Zen mode settings: Reminders option -->
<string name="zen_mode_reminders">Reminders</string>
@@ -8558,10 +8585,10 @@
<!-- Summary of condition that work mode is off [CHAR LIMIT=NONE] -->
<string name="condition_work_summary">Apps, background sync, and other features related to your work profile are turned off.</string>
- <!-- Night display: Title for the night display option Suggestion (renamed "Night Light" with title caps). [CHAR LIMIT=30] -->
+ <!-- Night display: Title for the night display option Suggestion (renamed "Night Light" with title caps). [CHAR LIMIT=46] -->
<string name="night_display_suggestion_title">Set Night Light schedule</string>
- <!-- Night display: Summary for the night display option Suggestion (renamed "Night Light" with title caps). [CHAR LIMIT=NONE] -->
+ <!-- Night display: Summary for the night display option Suggestion (renamed "Night Light" with title caps). [CHAR LIMIT=55] -->
<string name="night_display_suggestion_summary">Automatically tint screen every night</string>
<!-- Title of condition that night display is on (renamed "Night Light" with title caps). [CHAR LIMIT=30] -->
@@ -8657,10 +8684,10 @@
<!-- Format for a summary describing the amount of data before the user is warned or limited [CHAR LIMIT=NONE] -->
<string name="cell_warning_and_limit"><xliff:g name="amount" example="1 GB">%1$s</xliff:g> Data warning / <xliff:g name="amount" example="2 GB">%2$s</xliff:g> Data limit</string>
- <!-- Title of button and screen for billing cycle preferences [CHAR LIMIT=30] -->
+ <!-- Title of button and screen for billing cycle preferences [CHAR LIMIT=40] -->
<string name="billing_cycle">Data warning & limit</string>
- <!-- Title of button for application usage cycle preferences [CHAR LIMIT=30] -->
+ <!-- Title of button for application usage cycle preferences [CHAR LIMIT=40] -->
<string name="app_usage_cycle">App data usage cycle</string>
<!-- Summary describing when the billing cycle for their phone carrier starts [CHAR LIMIT=NONE] -->
@@ -8687,6 +8714,9 @@
<!-- Label for button to set the amount of data before user is warned about usage [CHAR LIMIT=30] -->
<string name="data_warning">Data warning</string>
+ <!-- Label for footnote on Data warning and limit page to warn of device discrepancies -->
+ <string name="data_warning_footnote">Data warning and data limit are measured by your device. This may be different from carrier data.</string>
+
<!-- Label for switch about whether to limit how much data can be used [CHAR LIMIT=30] -->
<string name="set_data_limit">Set data limit</string>
@@ -8769,10 +8799,10 @@
<!-- Summary of the preference controlling whether the device encryption *password* must be entered before being able to start the device. [CHAR LIMIT=NONE]-->
<string name="lockpattern_settings_require_password_before_startup_summary">Require password to start up your device. While off, this device can\'t receive calls, messages, notifications, or alarms.</string>
- <!-- Title for suggestion adding more fingerprints [CHAR LIMIT=30] -->
+ <!-- Title for suggestion adding more fingerprints [CHAR LIMIT=46] -->
<string name="suggestion_additional_fingerprints">Add another fingerprint</string>
- <!-- Summary for suggestion adding more fingerprints [CHAR LIMIT=60] -->
+ <!-- Summary for suggestion adding more fingerprints [CHAR LIMIT=55] -->
<string name="suggestion_additional_fingerprints_summary">Unlock with a different finger</string>
<!-- Summary of battery saver when on [CHAR LIMIT=NONE] -->
@@ -9453,4 +9483,13 @@
<!-- Summary for media output settings when the media stream is being captured by something else. -->
<string name="media_output_summary_unavailable">Unavailable</string>
+ <!-- Title for battery Suggestion. (tablet) [CHAR LIMIT=46] -->
+ <string name="battery_suggestion_title" product="tablet" >Improve tablet\'s battery life</string>
+ <!-- Title for battery Suggestion. (device) [CHAR LIMIT=46] -->
+ <string name="battery_suggestion_title" product="device" >Improve device\'s battery life</string>
+ <!-- Title for battery Suggestion. (phone) [CHAR LIMIT=46] -->
+ <string name="battery_suggestion_title" product="default" >Improve phone\'s battery life</string>
+ <!-- Summary for battery Suggestion. [CHAR LIMIT=55] -->
+ <string name="battery_suggestion_summary"></string>
+
</resources>
diff --git a/res/xml/connected_devices_advanced.xml b/res/xml/connected_devices_advanced.xml
index 36eab22..dda5655 100644
--- a/res/xml/connected_devices_advanced.xml
+++ b/res/xml/connected_devices_advanced.xml
@@ -26,7 +26,8 @@
android:icon="@drawable/ic_settings_bluetooth"
android:summary="@string/bluetooth_pref_summary"
android:order="-7"
- settings:controller="com.android.settings.bluetooth.BluetoothSwitchPreferenceController"/>
+ settings:controller="com.android.settings.bluetooth.BluetoothSwitchPreferenceController"
+ settings:platform_slice="true"/>
<SwitchPreference
android:key="toggle_nfc"
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index 571f38e..282a5121 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -264,9 +264,9 @@
android:summary="@string/bluetooth_disable_inband_ringing_summary" />
<SwitchPreference
- android:key="bluetooth_enable_avdtp_delay_reports"
- android:title="@string/bluetooth_enable_avdtp_delay_reports"
- android:summary="@string/bluetooth_enable_avdtp_delay_reports_summary"/>
+ android:key="bluetooth_disable_avdtp_delay_reports"
+ android:title="@string/bluetooth_disable_avdtp_delay_reports"
+ android:summary="@string/bluetooth_disable_avdtp_delay_reports_summary"/>
<ListPreference
android:key="bluetooth_select_avrcp_version"
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index b5bfc49..9500e24 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -20,41 +20,41 @@
android:title="@string/sound_settings"
android:key="sound_settings"
settings:keywords="@string/keywords_sounds"
- settings:initialExpandedChildrenCount="6">
+ settings:initialExpandedChildrenCount="7">
<!-- Media volume -->
<com.android.settings.notification.VolumeSeekBarPreference
android:key="media_volume"
android:icon="@*android:drawable/ic_audio_media"
android:title="@string/media_volume_option_title"
- android:order="-106"/>
+ android:order="-170"/>
<!-- 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"
- android:order="-105"/>
+ android:order="-160"/>
<!-- 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"
- android:order="-104"/>
+ android:order="-150"/>
<!-- Notification volume -->
<com.android.settings.notification.VolumeSeekBarPreference
android:key="notification_volume"
android:icon="@*android:drawable/ic_audio_ring_notif"
android:title="@string/notification_volume_option_title"
- android:order="-103"/>
+ android:order="-140"/>
<!-- Also vibrate for calls -->
<SwitchPreference
android:key="vibrate_when_ringing"
android:title="@string/vibrate_when_ringing_title"
- android:order="-102"/>
+ android:order="-130"/>
<!-- Interruptions -->
<com.android.settingslib.RestrictedPreference
@@ -64,7 +64,7 @@
settings:keywords="@string/keywords_sounds_and_notifications_interruptions"
android:fragment="com.android.settings.notification.ZenModeSettings"
settings:allowDividerAbove="true"
- android:order="-101"/>
+ android:order="-120"/>
<!-- Phone ringtone -->
<com.android.settings.DefaultRingtonePreference
@@ -83,7 +83,7 @@
android:dialogTitle="@string/notification_ringtone_title"
android:summary="@string/summary_placeholder"
android:ringtoneType="notification"
- android:order="-99"/>
+ android:order="-90"/>
<!-- Default alarm ringtone -->
<com.android.settings.DefaultRingtonePreference
@@ -93,7 +93,7 @@
android:summary="@string/summary_placeholder"
android:persistent="false"
android:ringtoneType="alarm"
- android:order="-98"/>
+ android:order="-80"/>
<!-- Other sounds -->
<PreferenceCategory
diff --git a/res/xml/system_dashboard_fragment.xml b/res/xml/system_dashboard_fragment.xml
index d8459dd..c3f15b9 100644
--- a/res/xml/system_dashboard_fragment.xml
+++ b/res/xml/system_dashboard_fragment.xml
@@ -46,7 +46,8 @@
android:summary="@string/reset_dashboard_summary"
android:icon="@drawable/ic_restore"
android:order="-50"
- android:fragment="com.android.settings.system.ResetDashboardFragment" />
+ android:fragment="com.android.settings.system.ResetDashboardFragment"
+ settings:controller="com.android.settings.system.ResetPreferenceController"/>
<!-- System updates -->
<Preference
diff --git a/res/xml/zen_mode_settings.xml b/res/xml/zen_mode_settings.xml
index 1f863c2..65fb7ab 100644
--- a/res/xml/zen_mode_settings.xml
+++ b/res/xml/zen_mode_settings.xml
@@ -31,6 +31,11 @@
android:title="@string/zen_mode_behavior_settings_title"
android:fragment="com.android.settings.notification.ZenModeBehaviorSettings" />
+ <!-- DND duration settings -->
+ <Preference
+ android:key="zen_mode_duration_settings"
+ android:title="@string/zen_mode_duration_settings_title" />
+
<!-- Automatic rules -->
<Preference
android:key="zen_mode_automation_settings"
diff --git a/src/com/android/settings/bluetooth/BluetoothFilesPreferenceController.java b/src/com/android/settings/bluetooth/BluetoothFilesPreferenceController.java
index 1ecfed4..6fbb84a 100644
--- a/src/com/android/settings/bluetooth/BluetoothFilesPreferenceController.java
+++ b/src/com/android/settings/bluetooth/BluetoothFilesPreferenceController.java
@@ -16,12 +16,14 @@
package com.android.settings.bluetooth;
+import android.content.pm.PackageManager;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -30,7 +32,7 @@
/**
* Controller that shows received files
*/
-public class BluetoothFilesPreferenceController extends AbstractPreferenceController
+public class BluetoothFilesPreferenceController extends BasePreferenceController
implements PreferenceControllerMixin {
private static final String TAG = "BluetoothFilesPrefCtrl";
@@ -47,13 +49,15 @@
private MetricsFeatureProvider mMetricsFeatureProvider;
public BluetoothFilesPreferenceController(Context context) {
- super(context);
+ super(context, KEY_RECEIVED_FILES);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
}
@Override
- public boolean isAvailable() {
- return true;
+ public int getAvailabilityStatus() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
+ ? AVAILABLE
+ : DISABLED_UNSUPPORTED;
}
@Override
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingDetail.java b/src/com/android/settings/bluetooth/BluetoothPairingDetail.java
index 0e556c4..1a64f26 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingDetail.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingDetail.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.VisibleForTesting;
+import android.util.Log;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
@@ -71,7 +72,10 @@
@Override
public void onStart() {
super.onStart();
-
+ if (mLocalManager == null){
+ Log.e(TAG, "Bluetooth is not supported on this device");
+ return;
+ }
updateBluetooth();
mAvailableDevicesCategory.setProgress(mLocalAdapter.isDiscovering());
}
@@ -89,7 +93,10 @@
@Override
public void onStop() {
super.onStop();
-
+ if (mLocalManager == null){
+ Log.e(TAG, "Bluetooth is not supported on this device");
+ return;
+ }
// Make the device only visible to connected devices.
mAlwaysDiscoverable.stop();
disableScanning();
diff --git a/src/com/android/settings/connecteddevice/ConnectedDeviceGroupController.java b/src/com/android/settings/connecteddevice/ConnectedDeviceGroupController.java
index 3d5d0e5..c77a735 100644
--- a/src/com/android/settings/connecteddevice/ConnectedDeviceGroupController.java
+++ b/src/com/android/settings/connecteddevice/ConnectedDeviceGroupController.java
@@ -15,15 +15,18 @@
*/
package com.android.settings.connecteddevice;
+import android.content.pm.PackageManager;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.connecteddevice.usb.ConnectedUsbDeviceUpdater;
+import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.bluetooth.BluetoothDeviceUpdater;
import com.android.settings.bluetooth.ConnectedBluetoothDeviceUpdater;
+import com.android.settings.search.ResultPayload;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -35,7 +38,7 @@
* Controller to maintain the {@link android.support.v7.preference.PreferenceGroup} for all
* connected devices. It uses {@link DevicePreferenceCallback} to add/remove {@link Preference}
*/
-public class ConnectedDeviceGroupController extends AbstractPreferenceController
+public class ConnectedDeviceGroupController extends BasePreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnStart, OnStop,
DevicePreferenceCallback {
@@ -47,7 +50,7 @@
private ConnectedUsbDeviceUpdater mConnectedUsbDeviceUpdater;
public ConnectedDeviceGroupController(DashboardFragment fragment, Lifecycle lifecycle) {
- super(fragment.getContext());
+ super(fragment.getContext(), KEY);
init(lifecycle, new ConnectedBluetoothDeviceUpdater(fragment, this),
new ConnectedUsbDeviceUpdater(fragment, this));
}
@@ -56,7 +59,7 @@
ConnectedDeviceGroupController(DashboardFragment fragment, Lifecycle lifecycle,
BluetoothDeviceUpdater bluetoothDeviceUpdater,
ConnectedUsbDeviceUpdater connectedUsbDeviceUpdater) {
- super(fragment.getContext());
+ super(fragment.getContext(), KEY);
init(lifecycle, bluetoothDeviceUpdater, connectedUsbDeviceUpdater);
}
@@ -75,17 +78,21 @@
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
- mPreferenceGroup = (PreferenceGroup) screen.findPreference(KEY);
- mPreferenceGroup.setVisible(false);
+ if (isAvailable()) {
+ mPreferenceGroup = (PreferenceGroup) screen.findPreference(KEY);
+ mPreferenceGroup.setVisible(false);
- mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
- mBluetoothDeviceUpdater.forceUpdate();
- mConnectedUsbDeviceUpdater.initUsbPreference(screen.getContext());
+ mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
+ mBluetoothDeviceUpdater.forceUpdate();
+ mConnectedUsbDeviceUpdater.initUsbPreference(screen.getContext());
+ }
}
@Override
- public boolean isAvailable() {
- return true;
+ public int getAvailabilityStatus() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
+ ? AVAILABLE
+ : DISABLED_UNSUPPORTED;
}
@Override
@@ -111,7 +118,7 @@
private void init(Lifecycle lifecycle, BluetoothDeviceUpdater bluetoothDeviceUpdater,
ConnectedUsbDeviceUpdater connectedUsbDeviceUpdater) {
- if (lifecycle != null) {
+ if (lifecycle != null && isAvailable()) {
lifecycle.addObserver(this);
}
mBluetoothDeviceUpdater = bluetoothDeviceUpdater;
diff --git a/src/com/android/settings/connecteddevice/SavedDeviceGroupController.java b/src/com/android/settings/connecteddevice/SavedDeviceGroupController.java
index 7445047..da38d9f 100644
--- a/src/com/android/settings/connecteddevice/SavedDeviceGroupController.java
+++ b/src/com/android/settings/connecteddevice/SavedDeviceGroupController.java
@@ -15,6 +15,7 @@
*/
package com.android.settings.connecteddevice;
+import android.content.pm.PackageManager;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
@@ -22,6 +23,7 @@
import com.android.settings.bluetooth.BluetoothDeviceUpdater;
import com.android.settings.bluetooth.SavedBluetoothDeviceUpdater;
+import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -34,7 +36,7 @@
* Controller to maintain the {@link PreferenceGroup} for all
* saved devices. It uses {@link DevicePreferenceCallback} to add/remove {@link Preference}
*/
-public class SavedDeviceGroupController extends AbstractPreferenceController
+public class SavedDeviceGroupController extends BasePreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnStart, OnStop,
DevicePreferenceCallback {
@@ -45,14 +47,14 @@
private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
public SavedDeviceGroupController(DashboardFragment fragment, Lifecycle lifecycle) {
- super(fragment.getContext());
+ super(fragment.getContext(), KEY);
init(lifecycle, new SavedBluetoothDeviceUpdater(fragment, SavedDeviceGroupController.this));
}
@VisibleForTesting
SavedDeviceGroupController(DashboardFragment fragment, Lifecycle lifecycle,
BluetoothDeviceUpdater bluetoothDeviceUpdater) {
- super(fragment.getContext());
+ super(fragment.getContext(), KEY);
init(lifecycle, bluetoothDeviceUpdater);
}
@@ -68,15 +70,19 @@
@Override
public void displayPreference(PreferenceScreen screen) {
- mPreferenceGroup = (PreferenceGroup) screen.findPreference(KEY);
- mPreferenceGroup.setVisible(false);
- mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
- mBluetoothDeviceUpdater.forceUpdate();
+ if (isAvailable()) {
+ mPreferenceGroup = (PreferenceGroup) screen.findPreference(KEY);
+ mPreferenceGroup.setVisible(false);
+ mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
+ mBluetoothDeviceUpdater.forceUpdate();
+ }
}
@Override
- public boolean isAvailable() {
- return true;
+ public int getAvailabilityStatus() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
+ ? AVAILABLE
+ : DISABLED_UNSUPPORTED;
}
@Override
@@ -101,7 +107,7 @@
}
private void init(Lifecycle lifecycle, BluetoothDeviceUpdater bluetoothDeviceUpdater) {
- if (lifecycle != null) {
+ if (lifecycle != null && isAvailable()) {
lifecycle.addObserver(this);
}
mBluetoothDeviceUpdater = bluetoothDeviceUpdater;
diff --git a/src/com/android/settings/core/PreferenceXmlParserUtils.java b/src/com/android/settings/core/PreferenceXmlParserUtils.java
index 7afe8d8..8620dce 100644
--- a/src/com/android/settings/core/PreferenceXmlParserUtils.java
+++ b/src/com/android/settings/core/PreferenceXmlParserUtils.java
@@ -76,6 +76,7 @@
int FLAG_NEED_PREF_TITLE = 1 << 4;
int FLAG_NEED_PREF_SUMMARY = 1 << 5;
int FLAG_NEED_PREF_ICON = 1 << 6;
+ int FLAG_NEED_PLATFORM_SLICE_FLAG = 1 << 7;
}
public static final String METADATA_PREF_TYPE = "type";
@@ -84,35 +85,48 @@
public static final String METADATA_TITLE = "title";
public static final String METADATA_SUMMARY = "summary";
public static final String METADATA_ICON = "icon";
+ public static final String METADATA_PLATFORM_SLICE_FLAG = "platform_slice";
private static final String ENTRIES_SEPARATOR = "|";
+ /**
+ * Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_KEY} instead.
+ */
+ @Deprecated
public static String getDataKey(Context context, AttributeSet attrs) {
- return getData(context, attrs,
+ return getStringData(context, attrs,
com.android.internal.R.styleable.Preference,
com.android.internal.R.styleable.Preference_key);
}
+ /**
+ * Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_TITLE} instead.
+ */
+ @Deprecated
public static String getDataTitle(Context context, AttributeSet attrs) {
- return getData(context, attrs,
+ return getStringData(context, attrs,
com.android.internal.R.styleable.Preference,
com.android.internal.R.styleable.Preference_title);
}
+ /**
+ * Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_SUMMARY} instead.
+ */
+ @Deprecated
public static String getDataSummary(Context context, AttributeSet attrs) {
- return getData(context, attrs,
+ return getStringData(context, attrs,
com.android.internal.R.styleable.Preference,
com.android.internal.R.styleable.Preference_summary);
}
public static String getDataSummaryOn(Context context, AttributeSet attrs) {
- return getData(context, attrs,
+ return getStringData(context, attrs,
com.android.internal.R.styleable.CheckBoxPreference,
com.android.internal.R.styleable.CheckBoxPreference_summaryOn);
}
public static String getDataSummaryOff(Context context, AttributeSet attrs) {
- return getData(context, attrs,
+ return getStringData(context, attrs,
com.android.internal.R.styleable.CheckBoxPreference,
com.android.internal.R.styleable.CheckBoxPreference_summaryOff);
}
@@ -124,13 +138,23 @@
}
public static String getDataKeywords(Context context, AttributeSet attrs) {
- return getData(context, attrs, R.styleable.Preference, R.styleable.Preference_keywords);
+ return getStringData(context, attrs, R.styleable.Preference,
+ R.styleable.Preference_keywords);
}
+ /**
+ * Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_CONTROLLER} instead.
+ */
+ @Deprecated
public static String getController(Context context, AttributeSet attrs) {
- return getData(context, attrs, R.styleable.Preference, R.styleable.Preference_controller);
+ return getStringData(context, attrs, R.styleable.Preference,
+ R.styleable.Preference_controller);
}
+ /**
+ * Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_ICON} instead.
+ */
+ @Deprecated
public static int getDataIcon(Context context, AttributeSet attrs) {
final TypedArray ta = context.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.Preference);
@@ -176,25 +200,35 @@
}
final Bundle preferenceMetadata = new Bundle();
final AttributeSet attrs = Xml.asAttributeSet(parser);
+ final TypedArray preferenceAttributes = context.obtainStyledAttributes(attrs,
+ R.styleable.Preference);
+
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_TYPE)) {
preferenceMetadata.putString(METADATA_PREF_TYPE, nodeName);
}
if (hasFlag(flags, MetadataFlag.FLAG_NEED_KEY)) {
- preferenceMetadata.putString(METADATA_KEY, getDataKey(context, attrs));
+ preferenceMetadata.putString(METADATA_KEY, getKey(preferenceAttributes));
}
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_CONTROLLER)) {
- preferenceMetadata.putString(METADATA_CONTROLLER, getController(context, attrs));
+ preferenceMetadata.putString(METADATA_CONTROLLER,
+ getController(preferenceAttributes));
}
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_TITLE)) {
- preferenceMetadata.putString(METADATA_TITLE, getDataTitle(context, attrs));
+ preferenceMetadata.putString(METADATA_TITLE, getTitle(preferenceAttributes));
}
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_SUMMARY)) {
- preferenceMetadata.putString(METADATA_SUMMARY, getDataSummary(context, attrs));
+ preferenceMetadata.putString(METADATA_SUMMARY, getSummary(preferenceAttributes));
}
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_ICON)) {
- preferenceMetadata.putInt(METADATA_ICON, getDataIcon(context, attrs));
+ preferenceMetadata.putInt(METADATA_ICON, getIcon(preferenceAttributes));
+ }
+ if (hasFlag(flags, MetadataFlag.FLAG_NEED_PLATFORM_SLICE_FLAG)) {
+ preferenceMetadata.putBoolean(METADATA_PLATFORM_SLICE_FLAG,
+ getPlatformSlice(preferenceAttributes));
}
metadata.add(preferenceMetadata);
+
+ preferenceAttributes.recycle();
} while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth));
parser.close();
@@ -205,12 +239,16 @@
* Returns the fragment name if this preference launches a child fragment.
*/
public static String getDataChildFragment(Context context, AttributeSet attrs) {
- return getData(context, attrs, R.styleable.Preference,
+ return getStringData(context, attrs, R.styleable.Preference,
R.styleable.Preference_android_fragment);
}
+ /**
+ * Call {@link #extractMetadata(Context, int, int)} with a {@link MetadataFlag} instead.
+ */
+ @Deprecated
@Nullable
- private static String getData(Context context, AttributeSet set, int[] attrs, int resId) {
+ private static String getStringData(Context context, AttributeSet set, int[] attrs, int resId) {
final TypedArray ta = context.obtainStyledAttributes(set, attrs);
String data = ta.getString(resId);
ta.recycle();
@@ -243,4 +281,28 @@
}
return result.toString();
}
+
+ private static String getKey(TypedArray styledAttributes) {
+ return styledAttributes.getString(com.android.internal.R.styleable.Preference_key);
+ }
+
+ private static String getTitle(TypedArray styledAttributes) {
+ return styledAttributes.getString(com.android.internal.R.styleable.Preference_title);
+ }
+
+ private static String getSummary(TypedArray styledAttributes) {
+ return styledAttributes.getString(com.android.internal.R.styleable.Preference_summary);
+ }
+
+ private static String getController(TypedArray styledAttributes) {
+ return styledAttributes.getString(R.styleable.Preference_controller);
+ }
+
+ private static int getIcon(TypedArray styledAttributes) {
+ return styledAttributes.getResourceId(com.android.internal.R.styleable.Icon_icon, 0);
+ }
+
+ private static boolean getPlatformSlice(TypedArray styledAttributes) {
+ return styledAttributes.getBoolean(R.styleable.Preference_platform_slice, false /* def */);
+ }
}
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index f9c7847..0cbc539 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -105,6 +105,7 @@
import com.android.settings.notification.ZenAccessSettings;
import com.android.settings.notification.ZenModeAutomationSettings;
import com.android.settings.notification.ZenModeBehaviorSettings;
+import com.android.settings.notification.ZenModeBlockedEffectsSettings;
import com.android.settings.notification.ZenModeEventRuleSettings;
import com.android.settings.notification.ZenModeScheduleRuleSettings;
import com.android.settings.notification.ZenModeSettings;
@@ -220,6 +221,7 @@
ZenModeBehaviorSettings.class.getName(),
ZenModeScheduleRuleSettings.class.getName(),
ZenModeEventRuleSettings.class.getName(),
+ ZenModeBlockedEffectsSettings.class.getName(),
ProcessStatsUi.class.getName(),
AdvancedPowerUsageDetail.class.getName(),
ProcessStatsSummary.class.getName(),
diff --git a/src/com/android/settings/datausage/BillingCycleSettings.java b/src/com/android/settings/datausage/BillingCycleSettings.java
index 34d18e9..8cec3e7 100644
--- a/src/com/android/settings/datausage/BillingCycleSettings.java
+++ b/src/com/android/settings/datausage/BillingCycleSettings.java
@@ -91,6 +91,8 @@
mEnableDataLimit = (SwitchPreference) findPreference(KEY_SET_DATA_LIMIT);
mEnableDataLimit.setOnPreferenceChangeListener(this);
mDataLimit = findPreference(KEY_DATA_LIMIT);
+
+ mFooterPreferenceMixin.createFooterPreference().setTitle(R.string.data_warning_footnote);
}
@Override
diff --git a/src/com/android/settings/datetime/timezone/BaseTimeZoneInfoPicker.java b/src/com/android/settings/datetime/timezone/BaseTimeZoneInfoPicker.java
index b133582..c1a3f8b 100644
--- a/src/com/android/settings/datetime/timezone/BaseTimeZoneInfoPicker.java
+++ b/src/com/android/settings/datetime/timezone/BaseTimeZoneInfoPicker.java
@@ -31,6 +31,7 @@
import java.util.Date;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
/**
* Render a list of {@class TimeZoneInfo} into the list view in {@class BaseTimeZonePicker}
@@ -135,8 +136,11 @@
name = mTimeZoneInfo.getStandardName();
}
}
- if (name == null) {
- return mTimeZoneInfo.getGmtOffset();
+
+ // Ignore name / GMT offset if the title shows the same information
+ if (name == null || name.equals(mTitle)) {
+ CharSequence gmtOffset = mTimeZoneInfo.getGmtOffset();
+ return gmtOffset == null || gmtOffset.toString().equals(mTitle) ? "" : gmtOffset;
} else {
return SpannableUtil.getResourcesText(mResources,
R.string.zone_info_offset_and_name, mTimeZoneInfo.getGmtOffset(), name);
diff --git a/src/com/android/settings/datetime/timezone/BaseTimeZonePicker.java b/src/com/android/settings/datetime/timezone/BaseTimeZonePicker.java
index c5e1ccb..032e2d2 100644
--- a/src/com/android/settings/datetime/timezone/BaseTimeZonePicker.java
+++ b/src/com/android/settings/datetime/timezone/BaseTimeZonePicker.java
@@ -25,7 +25,9 @@
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.LinearLayout;
import android.widget.SearchView;
+import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
@@ -130,6 +132,19 @@
mSearchView.setActivated(true);
mSearchView.setQuery("", true /* submit */);
}
+
+ // Set zero margin and padding to align with the text horizontally in the preference
+ final TextView searchViewView = (TextView) mSearchView.findViewById(
+ com.android.internal.R.id.search_src_text);
+ searchViewView.setPadding(0, searchViewView.getPaddingTop(), 0,
+ searchViewView.getPaddingBottom());
+ final View editFrame = mSearchView.findViewById(
+ com.android.internal.R.id.search_edit_frame);
+ final LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) editFrame
+ .getLayoutParams();
+ params.setMarginStart(0);
+ params.setMarginEnd(0);
+ editFrame.setLayoutParams(params);
}
}
@@ -146,12 +161,6 @@
return false;
}
- @Override
- public int getMetricsCategory() {
- // TODO: use a new metrics id?
- return MetricsEvent.ZONE_PICKER;
- }
-
public interface OnListItemClickListener {
void onListItemClick(int position);
}
diff --git a/src/com/android/settings/datetime/timezone/FixedOffsetPicker.java b/src/com/android/settings/datetime/timezone/FixedOffsetPicker.java
index 3d8b826..f134051 100644
--- a/src/com/android/settings/datetime/timezone/FixedOffsetPicker.java
+++ b/src/com/android/settings/datetime/timezone/FixedOffsetPicker.java
@@ -18,6 +18,7 @@
import android.icu.util.TimeZone;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.datetime.timezone.model.TimeZoneData;
@@ -43,6 +44,11 @@
}
@Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.SETTINGS_ZONE_PICKER_FIXED_OFFSET;
+ }
+
+ @Override
public List<TimeZoneInfo> getAllTimeZoneInfos(TimeZoneData timeZoneData) {
return loadFixedOffsets();
}
diff --git a/src/com/android/settings/datetime/timezone/RegionSearchPicker.java b/src/com/android/settings/datetime/timezone/RegionSearchPicker.java
index 1381b20..bb87e85 100644
--- a/src/com/android/settings/datetime/timezone/RegionSearchPicker.java
+++ b/src/com/android/settings/datetime/timezone/RegionSearchPicker.java
@@ -24,6 +24,7 @@
import android.os.Bundle;
import android.util.Log;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.datetime.timezone.model.FilteredCountryTimeZones;
@@ -50,6 +51,11 @@
}
@Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.SETTINGS_ZONE_PICKER_REGION;
+ }
+
+ @Override
protected BaseTimeZoneAdapter createAdapter(TimeZoneData timeZoneData) {
mTimeZoneData = timeZoneData;
mAdapter = new BaseTimeZoneAdapter<>(createAdapterItem(timeZoneData.getRegionIds()),
@@ -104,56 +110,25 @@
private List<RegionItem> createAdapterItem(Set<String> regionIds) {
final Collator collator = Collator.getInstance(getLocale());
final TreeSet<RegionItem> items = new TreeSet<>(new RegionInfoComparator(collator));
- final Paint paint = new Paint();
final LocaleDisplayNames localeDisplayNames = LocaleDisplayNames.getInstance(getLocale());
long i = 0;
for (String regionId : regionIds) {
String name = localeDisplayNames.regionDisplayName(regionId);
- String regionalIndicator = createRegionalIndicator(regionId, paint);
- items.add(new RegionItem(i++, regionId, name, regionalIndicator));
+ items.add(new RegionItem(i++, regionId, name));
}
return new ArrayList<>(items);
}
- /**
- * Create a Unicode Region Indicator Symbol for a given region id (a.k.a flag emoji). If the
- * system can't render a flag for this region or the input is not a region id, this returns
- * {@code null}.
- *
- * @param id the two-character region id.
- * @param paint Paint contains the glyph
- * @return a String representing the flag of the region or {@code null}.
- */
- private static String createRegionalIndicator(String id, Paint paint) {
- if (id.length() != 2) {
- return null;
- }
- final char c1 = id.charAt(0);
- final char c2 = id.charAt(1);
- if ('A' > c1 || c1 > 'Z' || 'A' > c2 || c2 > 'Z') {
- return null;
- }
- // Regional Indicator A is U+1F1E6 which is 0xD83C 0xDDE6 in UTF-16.
- final String regionalIndicator = new String(
- new char[]{0xd83c, (char) (0xdde6 - 'A' + c1), 0xd83c, (char) (0xdde6 - 'A' + c2)});
- if (!paint.hasGlyph(regionalIndicator)) {
- return null;
- }
- return regionalIndicator;
- }
-
private static class RegionItem implements BaseTimeZoneAdapter.AdapterItem {
private final String mId;
private final String mName;
- private final String mRegionalIndicator;
private final long mItemId;
private final String[] mSearchKeys;
- RegionItem(long itemId, String id, String name, String regionalIndicator) {
+ RegionItem(long itemId, String id, String name) {
mId = id;
mName = name;
- mRegionalIndicator = regionalIndicator;
mItemId = itemId;
// Allow to search with ISO_3166-1 alpha-2 code. It's handy for english users in some
// countries, e.g. US for United States. It's not best search keys for users, but
@@ -177,7 +152,7 @@
@Override
public String getIconText() {
- return mRegionalIndicator;
+ return null;
}
@Override
diff --git a/src/com/android/settings/datetime/timezone/RegionZonePicker.java b/src/com/android/settings/datetime/timezone/RegionZonePicker.java
index 7805241..37365a8 100644
--- a/src/com/android/settings/datetime/timezone/RegionZonePicker.java
+++ b/src/com/android/settings/datetime/timezone/RegionZonePicker.java
@@ -22,6 +22,7 @@
import android.support.annotation.VisibleForTesting;
import android.util.Log;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.datetime.timezone.model.FilteredCountryTimeZones;
import com.android.settings.datetime.timezone.model.TimeZoneData;
@@ -46,6 +47,11 @@
super(R.string.date_time_select_zone, R.string.search_settings, true, false);
}
+ @Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.SETTINGS_ZONE_PICKER_TIME_ZONE;
+ }
+
/**
* Add the extra region id into the result.
*/
diff --git a/src/com/android/settings/datetime/timezone/TimeZoneSettings.java b/src/com/android/settings/datetime/timezone/TimeZoneSettings.java
index aeb5a80..16976c2 100644
--- a/src/com/android/settings/datetime/timezone/TimeZoneSettings.java
+++ b/src/com/android/settings/datetime/timezone/TimeZoneSettings.java
@@ -98,7 +98,7 @@
final List<AbstractPreferenceController> controllers = new ArrayList<>();
RegionPreferenceController regionPreferenceController =
new RegionPreferenceController(context);
- regionPreferenceController.setOnClickListener(this::onRegionPreferenceClicked);
+ regionPreferenceController.setOnClickListener(this::startRegionPicker);
RegionZonePreferenceController regionZonePreferenceController =
new RegionZonePreferenceController(context);
regionZonePreferenceController.setOnClickListener(this::onRegionZonePreferenceClicked);
@@ -106,7 +106,7 @@
new TimeZoneInfoPreferenceController(context);
FixedOffsetPreferenceController fixedOffsetPreferenceController =
new FixedOffsetPreferenceController(context);
- fixedOffsetPreferenceController.setOnClickListener(this::onFixedOffsetPreferenceClicked);
+ fixedOffsetPreferenceController.setOnClickListener(this::startFixedOffsetPicker);
controllers.add(regionPreferenceController);
controllers.add(regionZonePreferenceController);
@@ -172,7 +172,7 @@
}
- private void onRegionPreferenceClicked() {
+ private void startRegionPicker() {
startPickerFragment(RegionSearchPicker.class, new Bundle(), REQUEST_CODE_REGION_PICKER);
}
@@ -183,7 +183,7 @@
startPickerFragment(RegionZonePicker.class, args, REQUEST_CODE_ZONE_PICKER);
}
- private void onFixedOffsetPreferenceClicked() {
+ private void startFixedOffsetPicker() {
startPickerFragment(FixedOffsetPicker.class, new Bundle(),
REQUEST_CODE_FIXED_OFFSET_ZONE_PICKER);
}
@@ -240,12 +240,18 @@
setDisplayedRegion(regionId);
setDisplayedTimeZoneInfo(regionId, mSelectedTimeZoneId);
saveTimeZone(regionId, mSelectedTimeZoneId);
+
+ // Switch to the region mode if the user switching from the fixed offset
+ setSelectByRegion(true);
}
private void onFixedOffsetZoneChanged(String tzId) {
mSelectedTimeZoneId = tzId;
setDisplayedFixedOffsetTimeZoneInfo(tzId);
saveTimeZone(null, mSelectedTimeZoneId);
+
+ // Switch to the fixed offset mode if the user switching from the region mode
+ setSelectByRegion(false);
}
private void saveTimeZone(String regionId, String tzId) {
@@ -277,11 +283,11 @@
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_BY_REGION:
- setSelectByRegion(true);
+ startRegionPicker();
return true;
case MENU_BY_OFFSET:
- setSelectByRegion(false);
+ startFixedOffsetPicker();
return true;
default:
diff --git a/src/com/android/settings/development/BluetoothDelayReportsPreferenceController.java b/src/com/android/settings/development/BluetoothDelayReportsPreferenceController.java
index 0858555..6c7a7dd 100644
--- a/src/com/android/settings/development/BluetoothDelayReportsPreferenceController.java
+++ b/src/com/android/settings/development/BluetoothDelayReportsPreferenceController.java
@@ -28,11 +28,11 @@
public class BluetoothDelayReportsPreferenceController extends DeveloperOptionsPreferenceController
implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
- private static final String BLUETOOTH_ENABLE_AVDTP_DELAY_REPORT_KEY =
- "bluetooth_enable_avdtp_delay_reports";
+ private static final String BLUETOOTH_DISABLE_AVDTP_DELAY_REPORT_KEY =
+ "bluetooth_disable_avdtp_delay_reports";
@VisibleForTesting
- static final String BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY =
- "persist.bluetooth.enabledelayreports";
+ static final String BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY =
+ "persist.bluetooth.disabledelayreports";
public BluetoothDelayReportsPreferenceController(Context context) {
super(context);
@@ -40,22 +40,22 @@
@Override
public String getPreferenceKey() {
- return BLUETOOTH_ENABLE_AVDTP_DELAY_REPORT_KEY;
+ return BLUETOOTH_DISABLE_AVDTP_DELAY_REPORT_KEY;
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
- final boolean isEnabled = (Boolean) newValue;
- SystemProperties.set(BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY,
- isEnabled ? "true" : "false");
+ final boolean isDisabled = (Boolean) newValue;
+ SystemProperties.set(BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY,
+ isDisabled ? "true" : "false");
return true;
}
@Override
public void updateState(Preference preference) {
- final boolean isEnabled = SystemProperties.getBoolean(
- BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */);
- ((SwitchPreference) mPreference).setChecked(isEnabled);
+ final boolean isDisabled = SystemProperties.getBoolean(
+ BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */);
+ ((SwitchPreference) mPreference).setChecked(isDisabled);
}
@Override
@@ -63,7 +63,7 @@
super.onDeveloperOptionsSwitchDisabled();
// the default setting for this preference is the disabled state
((SwitchPreference) mPreference).setChecked(false);
- SystemProperties.set(BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY, "false");
+ SystemProperties.set(BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY, "false");
}
}
diff --git a/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceController.java b/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceController.java
index 25ff096..34d354f 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceController.java
@@ -63,6 +63,7 @@
super.displayPreference(screen);
mPreference = (SeekBarPreference) screen.findPreference(
KEY_AUTO_BATTERY_SEEK_BAR);
+ mPreference.setContinuousUpdates(true);
updatePreference(mPreference);
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragment.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragment.java
index 9e172de..b39e4ef 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragment.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragment.java
@@ -32,11 +32,13 @@
import com.android.settings.Utils;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.fuelgauge.Estimate;
import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController.BatteryTipListener;
import com.android.settings.fuelgauge.batterytip.actions.BatteryTipAction;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip;
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
+import com.android.settings.fuelgauge.batterytip.tips.SummaryTip;
import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip;
import com.android.settingslib.utils.StringUtil;
@@ -72,9 +74,18 @@
switch (mBatteryTip.getType()) {
case BatteryTip.TipType.SUMMARY:
- case BatteryTip.TipType.LOW_BATTERY:
- //TODO(b/70570352): add dialog
- return null;
+ final long averageTimeMs = ((SummaryTip) mBatteryTip).getAverageTimeMs();
+ final String message = context.getString(
+ averageTimeMs == Estimate.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN
+ ? R.string.battery_tip_dialog_summary_message_no_estimation
+ : R.string.battery_tip_dialog_summary_message,
+ StringUtil.formatElapsedTime(context, averageTimeMs,
+ false /* withSeconds */));
+
+ return new AlertDialog.Builder(context)
+ .setMessage(message)
+ .setPositiveButton(android.R.string.ok, null)
+ .create();
case BatteryTip.TipType.HIGH_DEVICE_USAGE:
final HighUsageTip highUsageTip = (HighUsageTip) mBatteryTip;
final RecyclerView view = (RecyclerView) LayoutInflater.from(context).inflate(
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
index ebb4790..5efc04a 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
@@ -22,6 +22,7 @@
import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.fuelgauge.BatteryInfo;
import com.android.settings.fuelgauge.BatteryUtils;
+import com.android.settings.fuelgauge.Estimate;
import com.android.settings.fuelgauge.batterytip.detectors.EarlyWarningDetector;
import com.android.settings.fuelgauge.batterytip.detectors.HighUsageDetector;
import com.android.settings.fuelgauge.batterytip.detectors.LowBatteryDetector;
@@ -70,7 +71,7 @@
tips.add(new HighUsageDetector(context, policy, mBatteryStatsHelper).detect());
tips.add(new SmartBatteryDetector(policy, context.getContentResolver()).detect());
tips.add(new EarlyWarningDetector(policy, context).detect());
- tips.add(new SummaryDetector(policy).detect());
+ tips.add(new SummaryDetector(policy, batteryInfo.averageTimeToDischarge).detect());
tips.add(new RestrictAppDetector(context, policy).detect());
Collections.sort(tips);
@@ -83,7 +84,8 @@
private List<BatteryTip> getFakeData() {
final List<BatteryTip> tips = new ArrayList<>();
- tips.add(new SummaryTip(BatteryTip.StateType.NEW));
+ tips.add(new SummaryTip(BatteryTip.StateType.NEW,
+ Estimate.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN));
tips.add(new LowBatteryTip(BatteryTip.StateType.NEW));
return tips;
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
index 2702bb6..9e47782 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
@@ -27,6 +27,7 @@
import com.android.settings.SettingsActivity;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.InstrumentedPreferenceFragment;
+import com.android.settings.fuelgauge.Estimate;
import com.android.settings.fuelgauge.batterytip.actions.BatteryTipAction;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.SummaryTip;
@@ -82,7 +83,8 @@
mPreferenceGroup = (PreferenceGroup) screen.findPreference(getPreferenceKey());
// Add summary tip in advance to avoid UI flakiness
- final SummaryTip summaryTip = new SummaryTip(BatteryTip.StateType.NEW);
+ final SummaryTip summaryTip = new SummaryTip(BatteryTip.StateType.NEW,
+ Estimate.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN);
mPreferenceGroup.addPreference(summaryTip.buildPreference(mPrefContext));
}
@@ -104,9 +106,7 @@
final Preference preference = batteryTip.buildPreference(mPrefContext);
mBatteryTipMap.put(preference.getKey(), batteryTip);
mPreferenceGroup.addPreference(preference);
- mMetricsFeatureProvider.action(mContext,
- MetricsProto.MetricsEvent.ACTION_BATTERY_TIP_SHOWN,
- batteryTip.getType());
+ batteryTip.log(mContext, mMetricsFeatureProvider);
break;
}
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/SummaryDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/SummaryDetector.java
index a45dc09..0a20aac 100644
--- a/src/com/android/settings/fuelgauge/batterytip/detectors/SummaryDetector.java
+++ b/src/com/android/settings/fuelgauge/batterytip/detectors/SummaryDetector.java
@@ -26,9 +26,11 @@
*/
public class SummaryDetector implements BatteryTipDetector {
private BatteryTipPolicy mPolicy;
+ private long mAverageTimeMs;
- public SummaryDetector(BatteryTipPolicy policy) {
+ public SummaryDetector(BatteryTipPolicy policy, long averageTimeMs) {
mPolicy = policy;
+ mAverageTimeMs = averageTimeMs;
}
@Override
@@ -37,6 +39,6 @@
final int state = mPolicy.summaryEnabled
? BatteryTip.StateType.NEW
: BatteryTip.StateType.INVISIBLE;
- return new SummaryTip(state);
+ return new SummaryTip(state, mAverageTimeMs);
}
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java
index f252638..3c3a5c0 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java
@@ -25,6 +25,8 @@
import android.support.v7.preference.Preference;
import android.util.SparseIntArray;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -123,6 +125,11 @@
*/
public abstract void updateState(BatteryTip tip);
+ /**
+ * Log the battery tip
+ */
+ public abstract void log(Context context, MetricsFeatureProvider metricsFeatureProvider);
+
public Preference buildPreference(Context context) {
Preference preference = new Preference(context);
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTip.java
index 7b8f624..908b873 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTip.java
@@ -19,7 +19,9 @@
import android.content.Context;
import android.os.Parcel;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Tip to show early warning if battery couldn't make to usual charging time
@@ -76,6 +78,12 @@
}
@Override
+ public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
+ metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_EARLY_WARNING_TIP,
+ mState);
+ }
+
+ @Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeBoolean(mPowerSaveModeOn);
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTip.java
index 475ea56..3ce7538 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTip.java
@@ -21,9 +21,11 @@
import android.os.Parcelable;
import android.support.annotation.VisibleForTesting;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.fuelgauge.batterytip.AppInfo;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.utils.StringUtil;
import java.util.List;
@@ -78,6 +80,18 @@
mState = tip.mState;
}
+ @Override
+ public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
+ metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_HIGH_USAGE_TIP,
+ mState);
+ for (int i = 0, size = mHighUsageAppList.size(); i < size; i++) {
+ final AppInfo appInfo = mHighUsageAppList.get(i);
+ metricsFeatureProvider.action(context,
+ MetricsProto.MetricsEvent.ACTION_HIGH_USAGE_TIP_LIST,
+ appInfo.packageName);
+ }
+ }
+
public long getScreenTimeMs() {
return mScreenTimeMs;
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/LowBatteryTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/LowBatteryTip.java
index 32cbe02..86237dd 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/LowBatteryTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/LowBatteryTip.java
@@ -20,7 +20,9 @@
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Tip to show current battery life is short
@@ -55,6 +57,12 @@
mState = tip.mState;
}
+ @Override
+ public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
+ metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_LOW_BATTERY_TIP,
+ mState);
+ }
+
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public BatteryTip createFromParcel(Parcel in) {
return new LowBatteryTip(in);
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java
index 037457a..566cbfa 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java
@@ -19,11 +19,14 @@
import android.content.Context;
import android.content.res.Resources;
import android.os.Parcel;
+import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.fuelgauge.batterytip.AppInfo;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import java.util.ArrayList;
import java.util.List;
@@ -93,6 +96,24 @@
}
}
+ @Override
+ public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
+ metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_APP_RESTRICTION_TIP,
+ mState);
+ if (mState == StateType.NEW) {
+ for (int i = 0, size = mRestrictAppList.size(); i < size; i++) {
+ final AppInfo appInfo = mRestrictAppList.get(i);
+ for (Integer anomalyType : appInfo.anomalyTypes) {
+ metricsFeatureProvider.action(context,
+ MetricsProto.MetricsEvent.ACTION_APP_RESTRICTION_TIP_LIST,
+ appInfo.packageName,
+ Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, anomalyType));
+ }
+
+ }
+ }
+ }
+
public List<AppInfo> getRestrictAppList() {
return mRestrictAppList;
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/SmartBatteryTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/SmartBatteryTip.java
index 7b408bb..68c7d70 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/SmartBatteryTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/SmartBatteryTip.java
@@ -20,7 +20,9 @@
import android.os.Parcel;
import android.provider.Settings;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Tip to suggest turn on smart battery if it is not on
@@ -55,6 +57,12 @@
mState = tip.mState;
}
+ @Override
+ public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
+ metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_SMART_BATTERY_TIP,
+ mState);
+ }
+
public static final Creator CREATOR = new Creator() {
public BatteryTip createFromParcel(Parcel in) {
return new SmartBatteryTip(in);
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/SummaryTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/SummaryTip.java
index 458bd2e..8ed8692 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/SummaryTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/SummaryTip.java
@@ -19,20 +19,27 @@
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
+import android.support.annotation.VisibleForTesting;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Tip to show general summary about battery life
*/
public class SummaryTip extends BatteryTip {
+ private long mAverageTimeMs;
- public SummaryTip(@StateType int state) {
- super(TipType.SUMMARY, state, false /* showDialog */);
+ public SummaryTip(@StateType int state, long averageTimeMs) {
+ super(TipType.SUMMARY, state, true /* showDialog */);
+ mAverageTimeMs = averageTimeMs;
}
- private SummaryTip(Parcel in) {
+ @VisibleForTesting
+ SummaryTip(Parcel in) {
super(in);
+ mAverageTimeMs = in.readLong();
}
@Override
@@ -55,6 +62,22 @@
mState = tip.mState;
}
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeLong(mAverageTimeMs);
+ }
+
+ @Override
+ public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
+ metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_SUMMARY_TIP,
+ mState);
+ }
+
+ public long getAverageTimeMs() {
+ return mAverageTimeMs;
+ }
+
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public BatteryTip createFromParcel(Parcel in) {
return new SummaryTip(in);
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/UnrestrictAppTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/UnrestrictAppTip.java
index ec67f6a..93de9b7 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/UnrestrictAppTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/UnrestrictAppTip.java
@@ -21,6 +21,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.fuelgauge.batterytip.AppInfo;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Tip to suggest user to remove app restriction. This is the empty tip and it is only used in
@@ -67,6 +68,11 @@
}
@Override
+ public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
+ // Do nothing
+ }
+
+ @Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeParcelable(mAppInfo, flags);
diff --git a/src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java b/src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java
index 80d3531..4c9715c 100644
--- a/src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java
+++ b/src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java
@@ -16,43 +16,31 @@
package com.android.settings.inputmethod;
-import android.annotation.Nullable;
-import android.app.Activity;
+import android.content.Context;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
import android.hardware.input.InputManager.InputDeviceListener;
import android.hardware.input.KeyboardLayout;
import android.os.Bundle;
+import android.support.v7.preference.CheckBoxPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.view.InputDevice;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodSubtype;
-import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.util.Preconditions;
-import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.inputmethod.PhysicalKeyboardFragment.KeyboardInfoPreference;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
-public final class KeyboardLayoutPickerFragment extends SettingsPreferenceFragment
+public class KeyboardLayoutPickerFragment extends SettingsPreferenceFragment
implements InputDeviceListener {
-
private InputDeviceIdentifier mInputDeviceIdentifier;
private int mInputDeviceId = -1;
private InputManager mIm;
- private InputMethodInfo mImi;
- @Nullable
- private InputMethodSubtype mSubtype;
private KeyboardLayout[] mKeyboardLayouts;
- private Map<Preference, KeyboardLayout> mPreferenceMap = new HashMap<>();
-
- // TODO: Make these constants public API for b/25752827
+ private HashMap<CheckBoxPreference, KeyboardLayout> mPreferenceMap = new HashMap<>();
/**
* Intent extra: The input device descriptor of the keyboard whose keyboard
@@ -60,16 +48,6 @@
*/
public static final String EXTRA_INPUT_DEVICE_IDENTIFIER = "input_device_identifier";
- /**
- * Intent extra: The associated {@link InputMethodInfo}.
- */
- public static final String EXTRA_INPUT_METHOD_INFO = "input_method_info";
-
- /**
- * Intent extra: The associated {@link InputMethodSubtype}.
- */
- public static final String EXTRA_INPUT_METHOD_SUBTYPE = "input_method_subtype";
-
@Override
public int getMetricsCategory() {
return MetricsEvent.INPUTMETHOD_KEYBOARD;
@@ -78,18 +56,14 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- Activity activity = Preconditions.checkNotNull(getActivity());
- mInputDeviceIdentifier = activity.getIntent().getParcelableExtra(
+ mInputDeviceIdentifier = getActivity().getIntent().getParcelableExtra(
EXTRA_INPUT_DEVICE_IDENTIFIER);
- mImi = activity.getIntent().getParcelableExtra(EXTRA_INPUT_METHOD_INFO);
- mSubtype = activity.getIntent().getParcelableExtra(EXTRA_INPUT_METHOD_SUBTYPE);
-
- if (mInputDeviceIdentifier == null || mImi == null) {
- activity.finish();
+ if (mInputDeviceIdentifier == null) {
+ getActivity().finish();
}
- mIm = activity.getSystemService(InputManager.class);
+ mIm = (InputManager) getSystemService(Context.INPUT_SERVICE);
mKeyboardLayouts = mIm.getKeyboardLayoutsForInputDevice(mInputDeviceIdentifier);
Arrays.sort(mKeyboardLayouts);
setPreferenceScreen(createPreferenceHierarchy());
@@ -108,6 +82,8 @@
return;
}
mInputDeviceId = inputDevice.getId();
+
+ updateCheckedState();
}
@Override
@@ -120,21 +96,34 @@
@Override
public boolean onPreferenceTreeClick(Preference preference) {
- KeyboardLayout layout = mPreferenceMap.get(preference);
- if (layout != null) {
- mIm.setKeyboardLayoutForInputDevice(mInputDeviceIdentifier, mImi, mSubtype,
- layout.getDescriptor());
- getActivity().finish();
- return true;
+ if (preference instanceof CheckBoxPreference) {
+ CheckBoxPreference checkboxPref = (CheckBoxPreference)preference;
+ KeyboardLayout layout = mPreferenceMap.get(checkboxPref);
+ if (layout != null) {
+ boolean checked = checkboxPref.isChecked();
+ if (checked) {
+ mIm.addKeyboardLayoutForInputDevice(mInputDeviceIdentifier,
+ layout.getDescriptor());
+ } else {
+ mIm.removeKeyboardLayoutForInputDevice(mInputDeviceIdentifier,
+ layout.getDescriptor());
+ }
+ return true;
+ }
}
return super.onPreferenceTreeClick(preference);
}
@Override
- public void onInputDeviceAdded(int deviceId) {}
+ public void onInputDeviceAdded(int deviceId) {
+ }
@Override
- public void onInputDeviceChanged(int deviceId) {}
+ public void onInputDeviceChanged(int deviceId) {
+ if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
+ updateCheckedState();
+ }
+ }
@Override
public void onInputDeviceRemoved(int deviceId) {
@@ -147,14 +136,23 @@
PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity());
for (KeyboardLayout layout : mKeyboardLayouts) {
- Preference pref = new Preference(getPrefContext());
+ CheckBoxPreference pref = new CheckBoxPreference(getPrefContext());
pref.setTitle(layout.getLabel());
pref.setSummary(layout.getCollection());
root.addPreference(pref);
mPreferenceMap.put(pref, layout);
}
-
- root.setTitle(KeyboardInfoPreference.getDisplayName(getContext(), mImi, mSubtype));
return root;
}
+
+ private void updateCheckedState() {
+ String[] enabledKeyboardLayouts = mIm.getEnabledKeyboardLayoutsForInputDevice(
+ mInputDeviceIdentifier);
+ Arrays.sort(enabledKeyboardLayouts);
+
+ for (Map.Entry<CheckBoxPreference, KeyboardLayout> entry : mPreferenceMap.entrySet()) {
+ entry.getKey().setChecked(Arrays.binarySearch(enabledKeyboardLayouts,
+ entry.getValue().getDescriptor()) >= 0);
+ }
+ }
}
diff --git a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
index 83d501d..a02a6d0 100644
--- a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
@@ -19,11 +19,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
-import android.app.LoaderManager;
-import android.content.AsyncTaskLoader;
import android.content.Context;
import android.content.Intent;
-import android.content.Loader;
import android.database.ContentObserver;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
@@ -40,9 +37,6 @@
import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
import android.view.InputDevice;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
import com.android.internal.inputmethod.InputMethodUtils;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -52,33 +46,25 @@
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
-import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
+import com.android.settingslib.utils.ThreadUtils;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Objects;
public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
- implements InputManager.InputDeviceListener, Indexable {
+ implements InputManager.InputDeviceListener,
+ KeyboardLayoutDialogFragment.OnSetupKeyboardLayoutsListener, Indexable {
private static final String KEYBOARD_ASSISTANCE_CATEGORY = "keyboard_assistance_category";
private static final String SHOW_VIRTUAL_KEYBOARD_SWITCH = "show_virtual_keyboard_switch";
private static final String KEYBOARD_SHORTCUTS_HELPER = "keyboard_shortcuts_helper";
- private static final String IM_SUBTYPE_MODE_KEYBOARD = "keyboard";
@NonNull
- private final List<HardKeyboardDeviceInfo> mLastHardKeyboards = new ArrayList<>();
- @NonNull
- private final List<KeyboardInfoPreference> mTempKeyboardInfoList = new ArrayList<>();
-
- @NonNull
- private final HashSet<Integer> mLoaderIDs = new HashSet<>();
- private int mNextLoaderId = 0;
+ private final ArrayList<HardKeyboardDeviceInfo> mLastHardKeyboards = new ArrayList<>();
private InputManager mIm;
@NonNull
@@ -88,6 +74,8 @@
@NonNull
private InputMethodUtils.InputMethodSettings mSettings;
+ private Intent mIntentWaitingForResult;
+
@Override
public void onCreatePreferences(Bundle bundle, String s) {
Activity activity = Preconditions.checkNotNull(getActivity());
@@ -118,9 +106,8 @@
@Override
public void onResume() {
super.onResume();
- clearLoader();
mLastHardKeyboards.clear();
- updateHardKeyboards();
+ scheduleUpdateHardKeyboards();
mIm.registerInputDeviceListener(this, null);
mShowVirtualKeyboardSwitch.setOnPreferenceChangeListener(
mShowVirtualKeyboardSwitchPreferenceChangeListener);
@@ -130,67 +117,25 @@
@Override
public void onPause() {
super.onPause();
- clearLoader();
mLastHardKeyboards.clear();
mIm.unregisterInputDeviceListener(this);
mShowVirtualKeyboardSwitch.setOnPreferenceChangeListener(null);
unregisterShowVirtualKeyboardSettingsObserver();
}
- private void onLoadFinishedInternal(
- final int loaderId, @NonNull final List<Keyboards> keyboardsList) {
- if (!mLoaderIDs.remove(loaderId)) {
- // Already destroyed loader. Ignore.
- return;
- }
-
- Collections.sort(keyboardsList);
- final PreferenceScreen preferenceScreen = getPreferenceScreen();
- preferenceScreen.removeAll();
- for (Keyboards keyboards : keyboardsList) {
- final PreferenceCategory category = new PreferenceCategory(getPrefContext(), null);
- category.setTitle(keyboards.mDeviceInfo.mDeviceName);
- category.setOrder(0);
- preferenceScreen.addPreference(category);
- for (Keyboards.KeyboardInfo info : keyboards.mKeyboardInfoList) {
- mTempKeyboardInfoList.clear();
- final InputMethodInfo imi = info.mImi;
- final InputMethodSubtype imSubtype = info.mImSubtype;
- if (imi != null) {
- KeyboardInfoPreference pref =
- new KeyboardInfoPreference(getPrefContext(), info);
- pref.setOnPreferenceClickListener(preference -> {
- showKeyboardLayoutScreen(
- keyboards.mDeviceInfo.mDeviceIdentifier, imi, imSubtype);
- return true;
- });
- mTempKeyboardInfoList.add(pref);
- Collections.sort(mTempKeyboardInfoList);
- }
- for (KeyboardInfoPreference pref : mTempKeyboardInfoList) {
- category.addPreference(pref);
- }
- }
- }
- mTempKeyboardInfoList.clear();
- mKeyboardAssistanceCategory.setOrder(1);
- preferenceScreen.addPreference(mKeyboardAssistanceCategory);
- updateShowVirtualKeyboardSwitch();
- }
-
@Override
public void onInputDeviceAdded(int deviceId) {
- updateHardKeyboards();
+ scheduleUpdateHardKeyboards();
}
@Override
public void onInputDeviceRemoved(int deviceId) {
- updateHardKeyboards();
+ scheduleUpdateHardKeyboards();
}
@Override
public void onInputDeviceChanged(int deviceId) {
- updateHardKeyboards();
+ scheduleUpdateHardKeyboards();
}
@Override
@@ -198,50 +143,57 @@
return MetricsEvent.PHYSICAL_KEYBOARDS;
}
- @NonNull
- public static List<HardKeyboardDeviceInfo> getHardKeyboards() {
- final List<HardKeyboardDeviceInfo> keyboards = new ArrayList<>();
- final int[] devicesIds = InputDevice.getDeviceIds();
- for (int deviceId : devicesIds) {
- final InputDevice device = InputDevice.getDevice(deviceId);
- if (device != null && !device.isVirtual() && device.isFullKeyboard()) {
- keyboards.add(new HardKeyboardDeviceInfo(device.getName(), device.getIdentifier()));
- }
- }
- return keyboards;
+ private void scheduleUpdateHardKeyboards() {
+ final Context context = getContext();
+ ThreadUtils.postOnBackgroundThread(() -> {
+ final List<HardKeyboardDeviceInfo> newHardKeyboards = getHardKeyboards(context);
+ ThreadUtils.postOnMainThread(() -> updateHardKeyboards(newHardKeyboards));
+ });
}
- private void updateHardKeyboards() {
- final List<HardKeyboardDeviceInfo> newHardKeyboards = getHardKeyboards();
- if (!Objects.equals(newHardKeyboards, mLastHardKeyboards)) {
- clearLoader();
- mLastHardKeyboards.clear();
- mLastHardKeyboards.addAll(newHardKeyboards);
- mLoaderIDs.add(mNextLoaderId);
- getLoaderManager().initLoader(mNextLoaderId, null,
- new Callbacks(getContext(), this, mLastHardKeyboards));
- ++mNextLoaderId;
+ private void updateHardKeyboards(@NonNull List<HardKeyboardDeviceInfo> newHardKeyboards) {
+ if (Objects.equals(mLastHardKeyboards, newHardKeyboards)) {
+ // Nothing has changed. Ignore.
+ return;
}
+
+ // TODO(yukawa): Maybe we should follow the style used in ConnectedDeviceDashboardFragment.
+
+ mLastHardKeyboards.clear();
+ mLastHardKeyboards.addAll(newHardKeyboards);
+
+ final PreferenceScreen preferenceScreen = getPreferenceScreen();
+ preferenceScreen.removeAll();
+ final PreferenceCategory category = new PreferenceCategory(getPrefContext());
+ category.setTitle(R.string.builtin_keyboard_settings_title);
+ category.setOrder(0);
+ preferenceScreen.addPreference(category);
+
+ for (HardKeyboardDeviceInfo hardKeyboardDeviceInfo : newHardKeyboards) {
+ // TODO(yukawa): Consider using com.android.settings.widget.GearPreference
+ final Preference pref = new Preference(getPrefContext());
+ pref.setTitle(hardKeyboardDeviceInfo.mDeviceName);
+ pref.setSummary(hardKeyboardDeviceInfo.mLayoutLabel);
+ pref.setOnPreferenceClickListener(preference -> {
+ showKeyboardLayoutDialog(hardKeyboardDeviceInfo.mDeviceIdentifier);
+ return true;
+ });
+ category.addPreference(pref);
+ }
+
+ mKeyboardAssistanceCategory.setOrder(1);
+ preferenceScreen.addPreference(mKeyboardAssistanceCategory);
+ updateShowVirtualKeyboardSwitch();
}
- private void showKeyboardLayoutScreen(
- @NonNull InputDeviceIdentifier inputDeviceIdentifier,
- @NonNull InputMethodInfo imi,
- @Nullable InputMethodSubtype imSubtype) {
- final Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setClass(getActivity(), Settings.KeyboardLayoutPickerActivity.class);
- intent.putExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER,
- inputDeviceIdentifier);
- intent.putExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_METHOD_INFO, imi);
- intent.putExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_METHOD_SUBTYPE, imSubtype);
- startActivity(intent);
- }
-
- private void clearLoader() {
- for (final int loaderId : mLoaderIDs) {
- getLoaderManager().destroyLoader(loaderId);
+ private void showKeyboardLayoutDialog(InputDeviceIdentifier inputDeviceIdentifier) {
+ KeyboardLayoutDialogFragment fragment = (KeyboardLayoutDialogFragment)
+ getFragmentManager().findFragmentByTag("keyboardLayout");
+ if (fragment == null) {
+ fragment = new KeyboardLayoutDialogFragment(inputDeviceIdentifier);
+ fragment.setTargetFragment(this, 0);
+ fragment.show(getActivity().getFragmentManager(), "keyboardLayout");
}
- mLoaderIDs.clear();
}
private void registerShowVirtualKeyboardSettingsObserver() {
@@ -282,102 +234,75 @@
}
};
- private static final class Callbacks implements LoaderManager.LoaderCallbacks<List<Keyboards>> {
- @NonNull
- final Context mContext;
- @NonNull
- final PhysicalKeyboardFragment mPhysicalKeyboardFragment;
- @NonNull
- final List<HardKeyboardDeviceInfo> mHardKeyboards;
+ @Override
+ public void onSetupKeyboardLayouts(InputDeviceIdentifier inputDeviceIdentifier) {
+ final Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClass(getActivity(), Settings.KeyboardLayoutPickerActivity.class);
+ intent.putExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER,
+ inputDeviceIdentifier);
+ mIntentWaitingForResult = intent;
+ startActivityForResult(intent, 0);
+ }
- public Callbacks(
- @NonNull Context context,
- @NonNull PhysicalKeyboardFragment physicalKeyboardFragment,
- @NonNull List<HardKeyboardDeviceInfo> hardKeyboards) {
- mContext = context;
- mPhysicalKeyboardFragment = physicalKeyboardFragment;
- mHardKeyboards = hardKeyboards;
- }
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
- @Override
- public Loader<List<Keyboards>> onCreateLoader(int id, Bundle args) {
- return new KeyboardLayoutLoader(mContext, mHardKeyboards);
- }
-
- @Override
- public void onLoadFinished(Loader<List<Keyboards>> loader, List<Keyboards> data) {
- mPhysicalKeyboardFragment.onLoadFinishedInternal(loader.getId(), data);
- }
-
- @Override
- public void onLoaderReset(Loader<List<Keyboards>> loader) {
+ if (mIntentWaitingForResult != null) {
+ InputDeviceIdentifier inputDeviceIdentifier = mIntentWaitingForResult
+ .getParcelableExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER);
+ mIntentWaitingForResult = null;
+ showKeyboardLayoutDialog(inputDeviceIdentifier);
}
}
- private static final class KeyboardLayoutLoader extends AsyncTaskLoader<List<Keyboards>> {
- @NonNull
- private final List<HardKeyboardDeviceInfo> mHardKeyboards;
-
- public KeyboardLayoutLoader(
- @NonNull Context context,
- @NonNull List<HardKeyboardDeviceInfo> hardKeyboards) {
- super(context);
- mHardKeyboards = Preconditions.checkNotNull(hardKeyboards);
+ private static String getLayoutLabel(@NonNull InputDevice device,
+ @NonNull Context context, @NonNull InputManager im) {
+ final String currentLayoutDesc =
+ im.getCurrentKeyboardLayoutForInputDevice(device.getIdentifier());
+ if (currentLayoutDesc == null) {
+ return context.getString(R.string.keyboard_layout_default_label);
}
+ final KeyboardLayout currentLayout = im.getKeyboardLayout(currentLayoutDesc);
+ if (currentLayout == null) {
+ return context.getString(R.string.keyboard_layout_default_label);
+ }
+ // If current layout is specified but the layout is null, just return an empty string
+ // instead of falling back to R.string.keyboard_layout_default_label.
+ return TextUtils.emptyIfNull(currentLayout.getLabel());
+ }
- private Keyboards loadInBackground(HardKeyboardDeviceInfo deviceInfo) {
- final ArrayList<Keyboards.KeyboardInfo> keyboardInfoList = new ArrayList<>();
- final InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
- final InputManager im = getContext().getSystemService(InputManager.class);
- if (imm != null && im != null) {
- for (InputMethodInfo imi : imm.getEnabledInputMethodList()) {
- final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(
- imi, true /* allowsImplicitlySelectedSubtypes */);
- if (subtypes.isEmpty()) {
- // Here we use null to indicate that this IME has no subtype.
- final InputMethodSubtype nullSubtype = null;
- final KeyboardLayout layout = im.getKeyboardLayoutForInputDevice(
- deviceInfo.mDeviceIdentifier, imi, nullSubtype);
- keyboardInfoList.add(new Keyboards.KeyboardInfo(imi, nullSubtype, layout));
- continue;
- }
-
- // If the IME supports subtypes, we pick up "keyboard" subtypes only.
- final int N = subtypes.size();
- for (int i = 0; i < N; ++i) {
- final InputMethodSubtype subtype = subtypes.get(i);
- if (!IM_SUBTYPE_MODE_KEYBOARD.equalsIgnoreCase(subtype.getMode())) {
- continue;
- }
- final KeyboardLayout layout = im.getKeyboardLayoutForInputDevice(
- deviceInfo.mDeviceIdentifier, imi, subtype);
- keyboardInfoList.add(new Keyboards.KeyboardInfo(imi, subtype, layout));
- }
- }
+ @NonNull
+ static List<HardKeyboardDeviceInfo> getHardKeyboards(@NonNull Context context) {
+ final List<HardKeyboardDeviceInfo> keyboards = new ArrayList<>();
+ final InputManager im = context.getSystemService(InputManager.class);
+ if (im == null) {
+ return new ArrayList<>();
+ }
+ for (int deviceId : InputDevice.getDeviceIds()) {
+ final InputDevice device = InputDevice.getDevice(deviceId);
+ if (device == null || device.isVirtual() || !device.isFullKeyboard()) {
+ continue;
}
- return new Keyboards(deviceInfo, keyboardInfoList);
+ keyboards.add(new HardKeyboardDeviceInfo(
+ device.getName(), device.getIdentifier(), getLayoutLabel(device, context, im)));
}
- @Override
- public List<Keyboards> loadInBackground() {
- List<Keyboards> keyboardsList = new ArrayList<>(mHardKeyboards.size());
- for (HardKeyboardDeviceInfo deviceInfo : mHardKeyboards) {
- keyboardsList.add(loadInBackground(deviceInfo));
+ // We intentionally don't reuse Comparator because Collator may not be thread-safe.
+ final Collator collator = Collator.getInstance();
+ keyboards.sort((a, b) -> {
+ int result = collator.compare(a.mDeviceName, b.mDeviceName);
+ if (result != 0) {
+ return result;
}
- return keyboardsList;
- }
-
- @Override
- protected void onStartLoading() {
- super.onStartLoading();
- forceLoad();
- }
-
- @Override
- protected void onStopLoading() {
- super.onStopLoading();
- cancelLoad();
- }
+ result = a.mDeviceIdentifier.getDescriptor().compareTo(
+ b.mDeviceIdentifier.getDescriptor());
+ if (result != 0) {
+ return result;
+ }
+ return collator.compare(a.mLayoutLabel, b.mLayoutLabel);
+ });
+ return keyboards;
}
public static final class HardKeyboardDeviceInfo {
@@ -385,12 +310,16 @@
public final String mDeviceName;
@NonNull
public final InputDeviceIdentifier mDeviceIdentifier;
+ @NonNull
+ public final String mLayoutLabel;
public HardKeyboardDeviceInfo(
- @Nullable final String deviceName,
- @NonNull final InputDeviceIdentifier deviceIdentifier) {
- mDeviceName = deviceName != null ? deviceName : "";
+ @Nullable String deviceName,
+ @NonNull InputDeviceIdentifier deviceIdentifier,
+ @NonNull String layoutLabel) {
+ mDeviceName = TextUtils.emptyIfNull(deviceName);
mDeviceIdentifier = deviceIdentifier;
+ mLayoutLabel = layoutLabel;
}
@Override
@@ -404,14 +333,10 @@
if (!TextUtils.equals(mDeviceName, that.mDeviceName)) {
return false;
}
- if (mDeviceIdentifier.getVendorId() != that.mDeviceIdentifier.getVendorId()) {
+ if (!Objects.equals(mDeviceIdentifier, that.mDeviceIdentifier)) {
return false;
}
- if (mDeviceIdentifier.getProductId() != that.mDeviceIdentifier.getProductId()) {
- return false;
- }
- if (!TextUtils.equals(mDeviceIdentifier.getDescriptor(),
- that.mDeviceIdentifier.getDescriptor())) {
+ if (!TextUtils.equals(mLayoutLabel, that.mLayoutLabel)) {
return false;
}
@@ -419,121 +344,6 @@
}
}
- public static final class Keyboards implements Comparable<Keyboards> {
- @NonNull
- public final HardKeyboardDeviceInfo mDeviceInfo;
- @NonNull
- public final ArrayList<KeyboardInfo> mKeyboardInfoList;
- @NonNull
- public final Collator mCollator = Collator.getInstance();
-
- public Keyboards(
- @NonNull final HardKeyboardDeviceInfo deviceInfo,
- @NonNull final ArrayList<KeyboardInfo> keyboardInfoList) {
- mDeviceInfo = deviceInfo;
- mKeyboardInfoList = keyboardInfoList;
- }
-
- @Override
- public int compareTo(@NonNull Keyboards another) {
- return mCollator.compare(mDeviceInfo.mDeviceName, another.mDeviceInfo.mDeviceName);
- }
-
- public static final class KeyboardInfo {
- @NonNull
- public final InputMethodInfo mImi;
- @Nullable
- public final InputMethodSubtype mImSubtype;
- @NonNull
- public final KeyboardLayout mLayout;
-
- public KeyboardInfo(
- @NonNull final InputMethodInfo imi,
- @Nullable final InputMethodSubtype imSubtype,
- @NonNull final KeyboardLayout layout) {
- mImi = imi;
- mImSubtype = imSubtype;
- mLayout = layout;
- }
- }
- }
-
- static final class KeyboardInfoPreference extends Preference {
-
- @NonNull
- private final CharSequence mImeName;
- @Nullable
- private final CharSequence mImSubtypeName;
- @NonNull
- private final Collator collator = Collator.getInstance();
-
- private KeyboardInfoPreference(
- @NonNull Context context, @NonNull Keyboards.KeyboardInfo info) {
- super(context);
- mImeName = info.mImi.loadLabel(context.getPackageManager());
- mImSubtypeName = getImSubtypeName(context, info.mImi, info.mImSubtype);
- setTitle(formatDisplayName(context, mImeName, mImSubtypeName));
- if (info.mLayout != null) {
- setSummary(info.mLayout.getLabel());
- }
- }
-
- @NonNull
- static CharSequence getDisplayName(
- @NonNull Context context, @NonNull InputMethodInfo imi,
- @Nullable InputMethodSubtype imSubtype) {
- final CharSequence imeName = imi.loadLabel(context.getPackageManager());
- final CharSequence imSubtypeName = getImSubtypeName(context, imi, imSubtype);
- return formatDisplayName(context, imeName, imSubtypeName);
- }
-
- private static CharSequence formatDisplayName(
- @NonNull Context context,
- @NonNull CharSequence imeName, @Nullable CharSequence imSubtypeName) {
- if (imSubtypeName == null) {
- return imeName;
- }
- return String.format(
- context.getString(R.string.physical_device_title), imeName, imSubtypeName);
- }
-
- @Nullable
- private static CharSequence getImSubtypeName(
- @NonNull Context context, @NonNull InputMethodInfo imi,
- @Nullable InputMethodSubtype imSubtype) {
- if (imSubtype != null) {
- return InputMethodAndSubtypeUtil.getSubtypeLocaleNameAsSentence(
- imSubtype, context, imi);
- }
- return null;
- }
-
- @Override
- public int compareTo(@NonNull Preference object) {
- if (!(object instanceof KeyboardInfoPreference)) {
- return super.compareTo(object);
- }
- KeyboardInfoPreference another = (KeyboardInfoPreference) object;
- int result = compare(mImeName, another.mImeName);
- if (result == 0) {
- result = compare(mImSubtypeName, another.mImSubtypeName);
- }
- return result;
- }
-
- private int compare(@Nullable CharSequence lhs, @Nullable CharSequence rhs) {
- if (!TextUtils.isEmpty(lhs) && !TextUtils.isEmpty(rhs)) {
- return collator.compare(lhs.toString(), rhs.toString());
- } else if (TextUtils.isEmpty(lhs) && TextUtils.isEmpty(rhs)) {
- return 0;
- } else if (!TextUtils.isEmpty(lhs)) {
- return -1;
- } else {
- return 1;
- }
- }
- }
-
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
diff --git a/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceController.java b/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceController.java
index f80b68f..b9e95be 100644
--- a/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceController.java
+++ b/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceController.java
@@ -94,7 +94,7 @@
return;
}
final List<HardKeyboardDeviceInfo> keyboards =
- PhysicalKeyboardFragment.getHardKeyboards();
+ PhysicalKeyboardFragment.getHardKeyboards(mContext);
if (keyboards.isEmpty()) {
mPreference.setSummary(R.string.disconnected);
return;
diff --git a/src/com/android/settings/notification/AbstractZenModePreferenceController.java b/src/com/android/settings/notification/AbstractZenModePreferenceController.java
index 9180791..c60299e 100644
--- a/src/com/android/settings/notification/AbstractZenModePreferenceController.java
+++ b/src/com/android/settings/notification/AbstractZenModePreferenceController.java
@@ -112,10 +112,17 @@
mBackend.mZenMode);
}
+ protected int getZenDuration() {
+ return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.ZEN_DURATION,
+ 0);
+ }
+
class SettingObserver extends ContentObserver {
private final Uri ZEN_MODE_URI = Settings.Global.getUriFor(Settings.Global.ZEN_MODE);
private final Uri ZEN_MODE_CONFIG_ETAG_URI = Settings.Global.getUriFor(
Settings.Global.ZEN_MODE_CONFIG_ETAG);
+ private final Uri ZEN_MODE_DURATION_URI = Settings.Global.getUriFor(
+ Settings.Global.ZEN_DURATION);
private final Preference mPreference;
@@ -127,6 +134,7 @@
public void register(ContentResolver cr) {
cr.registerContentObserver(ZEN_MODE_URI, false, this, UserHandle.USER_ALL);
cr.registerContentObserver(ZEN_MODE_CONFIG_ETAG_URI, false, this, UserHandle.USER_ALL);
+ cr.registerContentObserver(ZEN_MODE_DURATION_URI, false, this, UserHandle.USER_ALL);
}
public void unregister(ContentResolver cr) {
@@ -136,11 +144,8 @@
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
- if (ZEN_MODE_URI.equals(uri)) {
- updateState(mPreference);
- }
-
- if (ZEN_MODE_CONFIG_ETAG_URI.equals(uri)) {
+ if (ZEN_MODE_URI.equals(uri) || ZEN_MODE_CONFIG_ETAG_URI.equals(uri)
+ || ZEN_MODE_DURATION_URI.equals(uri)) {
updateState(mPreference);
}
}
diff --git a/src/com/android/settings/notification/SettingsZenDurationDialog.java b/src/com/android/settings/notification/SettingsZenDurationDialog.java
new file mode 100644
index 0000000..23bf1a9
--- /dev/null
+++ b/src/com/android/settings/notification/SettingsZenDurationDialog.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.app.Dialog;
+import android.os.Bundle;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+public class SettingsZenDurationDialog extends InstrumentedDialogFragment {
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ return new com.android.settingslib.notification.ZenDurationDialog(
+ getContext()).createDialog();
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.NOTIFICATION_ZEN_MODE_DURATION_DIALOG;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenModeAutomationPreferenceController.java b/src/com/android/settings/notification/ZenModeAutomationPreferenceController.java
index aa46d4e..792a272 100644
--- a/src/com/android/settings/notification/ZenModeAutomationPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeAutomationPreferenceController.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 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.Context;
diff --git a/src/com/android/settings/notification/ZenModeBackend.java b/src/com/android/settings/notification/ZenModeBackend.java
index 8817417..3c6a026 100644
--- a/src/com/android/settings/notification/ZenModeBackend.java
+++ b/src/com/android/settings/notification/ZenModeBackend.java
@@ -16,9 +16,11 @@
package com.android.settings.notification;
+import android.app.ActivityManager;
import android.app.AutomaticZenRule;
import android.app.NotificationManager;
import android.content.Context;
+import android.net.Uri;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
import android.support.annotation.VisibleForTesting;
@@ -79,7 +81,15 @@
protected void setZenMode(int zenMode) {
NotificationManager.from(mContext).setZenMode(zenMode, null, TAG);
- mZenMode = zenMode;
+ mZenMode = getZenMode();
+ }
+
+ protected void setZenModeForDuration(int minutes) {
+ Uri conditionId = ZenModeConfig.toTimeCondition(mContext, minutes,
+ ActivityManager.getCurrentUser(), true).id;
+ mNotificationManager.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ conditionId, TAG);
+ mZenMode = getZenMode();
}
protected int getZenMode() {
diff --git a/src/com/android/settings/notification/ZenModeBehaviorPreferenceController.java b/src/com/android/settings/notification/ZenModeBehaviorPreferenceController.java
index 0e1f066..cf6218c 100644
--- a/src/com/android/settings/notification/ZenModeBehaviorPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeBehaviorPreferenceController.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 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.Context;
diff --git a/src/com/android/settings/notification/ZenModeButtonPreferenceController.java b/src/com/android/settings/notification/ZenModeButtonPreferenceController.java
index d9c9691..12008a1 100644
--- a/src/com/android/settings/notification/ZenModeButtonPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeButtonPreferenceController.java
@@ -61,8 +61,7 @@
if (null == mZenButtonOn) {
mZenButtonOn = (Button) ((LayoutPreference) preference)
.findViewById(R.id.zen_mode_settings_turn_on_button);
- mZenButtonOn.setOnClickListener(v ->
- new SettingsEnableZenModeDialog().show(mFragment, TAG));
+ updateZenButtonOnClickListener();
}
if (null == mZenButtonOff) {
@@ -89,7 +88,34 @@
case Settings.Global.ZEN_MODE_OFF:
default:
mZenButtonOff.setVisibility(View.GONE);
+ updateZenButtonOnClickListener();
mZenButtonOn.setVisibility(View.VISIBLE);
}
}
+
+ private void updateZenButtonOnClickListener() {
+ int zenDuration = getZenDuration();
+ switch (zenDuration) {
+ case Settings.Global.ZEN_DURATION_PROMPT:
+ mZenButtonOn.setOnClickListener(v -> {
+ mMetricsFeatureProvider.action(mContext,
+ MetricsProto.MetricsEvent.ACTION_ZEN_TOGGLE_DND_BUTTON, false);
+ new SettingsEnableZenModeDialog().show(mFragment, TAG);
+ });
+ break;
+ case Settings.Global.ZEN_DURATION_FOREVER:
+ mZenButtonOn.setOnClickListener(v -> {
+ mMetricsFeatureProvider.action(mContext,
+ MetricsProto.MetricsEvent.ACTION_ZEN_TOGGLE_DND_BUTTON, false);
+ mBackend.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+ });
+ break;
+ default:
+ mZenButtonOn.setOnClickListener(v -> {
+ mMetricsFeatureProvider.action(mContext,
+ MetricsProto.MetricsEvent.ACTION_ZEN_TOGGLE_DND_BUTTON, false);
+ mBackend.setZenModeForDuration(zenDuration);
+ });
+ }
+ }
}
\ No newline at end of file
diff --git a/src/com/android/settings/notification/ZenModeDurationPreferenceController.java b/src/com/android/settings/notification/ZenModeDurationPreferenceController.java
new file mode 100644
index 0000000..0cd0eb3
--- /dev/null
+++ b/src/com/android/settings/notification/ZenModeDurationPreferenceController.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.app.FragmentManager;
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenModeDurationPreferenceController extends AbstractZenModePreferenceController
+ implements PreferenceControllerMixin, Preference.OnPreferenceClickListener {
+
+ private static final String TAG = "ZenModeDurationDialog";
+ protected static final String KEY = "zen_mode_duration_settings";
+ private FragmentManager mFragment;
+
+ public ZenModeDurationPreferenceController(Context context, Lifecycle lifecycle, FragmentManager
+ fragment) {
+ super(context, KEY, lifecycle);
+ mFragment = fragment;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ screen.findPreference(KEY).setOnPreferenceClickListener(this);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+
+ String summary = "";
+ int zenDuration = getZenDuration();
+ if (zenDuration < 0) {
+ summary = mContext.getString(R.string.zen_mode_duration_summary_always_prompt);
+ } else if (zenDuration == 0) {
+ summary = mContext.getString(R.string.zen_mode_duration_summary_forever);
+ } else {
+ if (zenDuration >= 60) {
+ int hours = zenDuration / 60;
+ summary = mContext.getResources().getQuantityString(
+ R.plurals.zen_mode_duration_summary_time_hours, hours, hours);
+ } else {
+ summary = mContext.getResources().getString(
+ R.string.zen_mode_duration_summary_time_minutes, zenDuration);
+ }
+ }
+
+ preference.setSummary(summary);
+ }
+
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ new SettingsZenDurationDialog().show(mFragment, TAG);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java
index fdb5cc6..2718756 100644
--- a/src/com/android/settings/notification/ZenModeSettings.java
+++ b/src/com/android/settings/notification/ZenModeSettings.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.provider.SearchIndexableResource;
import android.provider.Settings;
+import android.service.notification.ZenModeConfig;
import android.support.annotation.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -64,6 +65,8 @@
List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new ZenModeBehaviorPreferenceController(context, lifecycle));
controllers.add(new ZenModeBlockedEffectsPreferenceController(context, lifecycle));
+ controllers.add(new ZenModeDurationPreferenceController(context, lifecycle,
+ fragmentManager));
controllers.add(new ZenModeAutomationPreferenceController(context));
controllers.add(new ZenModeButtonPreferenceController(context, lifecycle, fragmentManager));
controllers.add(new ZenModeSettingsFooterPreferenceController(context, lifecycle));
@@ -91,40 +94,44 @@
};
String getBehaviorSettingSummary(Policy policy, int zenMode) {
- List<String> enabledCategories;
+ List<String> enabledCategories = getEnabledCategories(policy);
- if (zenMode == Settings.Global.ZEN_MODE_NO_INTERRUPTIONS) {
- return mContext.getString(R.string.zen_mode_behavior_total_silence);
- } else if (zenMode == Settings.Global.ZEN_MODE_ALARMS) {
- return mContext.getString(R.string.zen_mode_behavior_alarms_only);
- } else {
- enabledCategories = getEnabledCategories(policy);
- }
-
- // no sound categories can bypass dnd
int numCategories = enabledCategories.size();
if (numCategories == 0) {
- return mContext.getString(R.string.zen_mode_behavior_total_silence);
+ return mContext.getString(R.string.zen_mode_no_exceptions);
+ } else if (numCategories == 1) {
+ return enabledCategories.get(0);
+ } else if (numCategories == 2) {
+ return mContext.getString(R.string.join_two_items, enabledCategories.get(0),
+ enabledCategories.get(1).toLowerCase());
+ } else if (numCategories == 3){
+ String secondaryText = mContext.getString(R.string.join_two_unrelated_items,
+ enabledCategories.get(0), enabledCategories.get(1).toLowerCase());
+ return mContext.getString(R.string.join_two_items, secondaryText,
+ enabledCategories.get(2).toLowerCase());
+ } else {
+ String secondaryText = mContext.getString(R.string.join_many_items_middle,
+ enabledCategories.get(0), enabledCategories.get(1).toLowerCase());
+ secondaryText = mContext.getString(R.string.join_many_items_middle, secondaryText,
+ enabledCategories.get(2).toLowerCase());
+ return mContext.getString(R.string.join_many_items_last, secondaryText,
+ mContext.getString(R.string.zen_mode_other_options));
}
-
- // only alarms and media can bypass dnd
- if (numCategories == 2 &&
- isCategoryEnabled(policy, Policy.PRIORITY_CATEGORY_ALARMS) &&
- isCategoryEnabled(policy, Policy.PRIORITY_CATEGORY_MEDIA)) {
- return mContext.getString(R.string.zen_mode_behavior_alarms_only);
- }
-
- // custom
- return mContext.getString(R.string.zen_mode_behavior_summary_custom);
}
String getSoundSummary() {
int zenMode = NotificationManager.from(mContext).getZenMode();
if (zenMode != Settings.Global.ZEN_MODE_OFF) {
- Policy policy = NotificationManager.from(mContext).getNotificationPolicy();
- return mContext.getString(R.string.zen_mode_sound_summary_on,
- getBehaviorSettingSummary(policy, zenMode));
+ ZenModeConfig config = NotificationManager.from(mContext).getZenModeConfig();
+ String description = ZenModeConfig.getDescription(mContext, true, config);
+
+ if (description == null) {
+ return mContext.getString(R.string.zen_mode_sound_summary_on);
+ } else {
+ return mContext.getString(R.string.zen_mode_sound_summary_on_with_info,
+ description);
+ }
} else {
final int count = getEnabledAutomaticRulesCount();
if (count > 0) {
@@ -243,6 +250,7 @@
@Override
public List<String> getNonIndexableKeys(Context context) {
List<String> keys = super.getNonIndexableKeys(context);
+ keys.add(ZenModeDurationPreferenceController.KEY);
keys.add(ZenModeButtonPreferenceController.KEY);
return keys;
}
diff --git a/src/com/android/settings/security/EncryptionStatusPreferenceController.java b/src/com/android/settings/security/EncryptionStatusPreferenceController.java
index 2341248..8125599 100644
--- a/src/com/android/settings/security/EncryptionStatusPreferenceController.java
+++ b/src/com/android/settings/security/EncryptionStatusPreferenceController.java
@@ -41,6 +41,12 @@
@Override
public int getAvailabilityStatus() {
+ if (TextUtils.equals(getPreferenceKey(), PREF_KEY_ENCRYPTION_DETAIL_PAGE) &&
+ !mContext.getResources().getBoolean(
+ R.bool.config_show_encryption_and_credentials_encryption_status)) {
+ return DISABLED_UNSUPPORTED;
+ }
+
return mUserManager.isAdminUser() ? AVAILABLE : DISABLED_FOR_USER;
}
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index d8ba991..68c9731 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -24,6 +24,7 @@
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.net.wifi.WifiManager;
+import android.provider.SettingsSlicesContract;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
@@ -63,6 +64,10 @@
private static final String TAG = "SettingsSliceProvider";
+ /**
+ * Authority for Settings slices not officially supported by the platform, but extensible for
+ * OEMs.
+ */
public static final String SLICE_AUTHORITY = "com.android.settings.slices";
public static final String PATH_WIFI = "wifi";
@@ -82,13 +87,6 @@
@VisibleForTesting
Map<Uri, SliceData> mSliceDataCache;
- public static Uri getUri(String path) {
- return new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SLICE_AUTHORITY)
- .appendPath(path).build();
- }
-
@Override
public boolean onCreateSliceProvider() {
mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(getContext());
@@ -176,7 +174,8 @@
.setSubtitle(state)
.addEndItem(new SliceAction(getBroadcastIntent(ACTION_WIFI_CHANGED),
null, finalWifiEnabled))
- .setPrimaryAction(new SliceAction(getIntent(Intent.ACTION_MAIN), null, null)))
+ .setPrimaryAction(
+ new SliceAction(getIntent(Intent.ACTION_MAIN), null, null)))
.build();
}
diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java
index a68ed19..4124df7 100644
--- a/src/com/android/settings/slices/SliceBroadcastReceiver.java
+++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java
@@ -59,7 +59,8 @@
// Wait a bit for wifi to update (TODO: is there a better way to do this?)
Handler h = new Handler();
h.postDelayed(() -> {
- Uri uri = SettingsSliceProvider.getUri(SettingsSliceProvider.PATH_WIFI);
+ Uri uri = SliceBuilderUtils.getUri(SettingsSliceProvider.PATH_WIFI,
+ false /* isPlatformSlice */);
context.getContentResolver().notifyChange(uri, null);
}, 1000);
break;
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index e94ee56..e90ea8e 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -19,9 +19,12 @@
import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_KEY;
import android.app.PendingIntent;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.provider.SettingsSlicesContract;
import android.text.TextUtils;
import com.android.internal.annotations.VisibleForTesting;
@@ -98,6 +101,17 @@
sliceData.getKey());
}
+ public static Uri getUri(String path, boolean isPlatformSlice) {
+ final String authority = isPlatformSlice
+ ? SettingsSlicesContract.AUTHORITY
+ : SettingsSliceProvider.SLICE_AUTHORITY;
+ return new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(authority)
+ .appendPath(path)
+ .build();
+ }
+
private static BasePreferenceController getPreferenceController(Context context,
String controllerClassName, String controllerKey) {
try {
diff --git a/src/com/android/settings/slices/SliceData.java b/src/com/android/settings/slices/SliceData.java
index a7c9a11..c02b113 100644
--- a/src/com/android/settings/slices/SliceData.java
+++ b/src/com/android/settings/slices/SliceData.java
@@ -70,6 +70,8 @@
@SliceType
private final int mSliceType;
+ private final boolean mIsPlatformDefined;
+
public String getKey() {
return mKey;
}
@@ -106,6 +108,10 @@
return mSliceType;
}
+ public boolean isPlatformDefined() {
+ return mIsPlatformDefined;
+ }
+
private SliceData(Builder builder) {
mKey = builder.mKey;
mTitle = builder.mTitle;
@@ -116,6 +122,7 @@
mUri = builder.mUri;
mPreferenceController = builder.mPrefControllerClassName;
mSliceType = builder.mSliceType;
+ mIsPlatformDefined = builder.mIsPlatformDefined;
}
@Override
@@ -151,6 +158,8 @@
private int mSliceType;
+ private boolean mIsPlatformDefined;
+
public Builder setKey(String key) {
mKey = key;
return this;
@@ -196,6 +205,11 @@
return this;
}
+ public Builder setPlatformDefined(boolean isPlatformDefined) {
+ mIsPlatformDefined = isPlatformDefined;
+ return this;
+ }
+
public SliceData build() {
if (TextUtils.isEmpty(mKey)) {
throw new IllegalStateException("Key cannot be empty");
diff --git a/src/com/android/settings/slices/SliceDataConverter.java b/src/com/android/settings/slices/SliceDataConverter.java
index e7b53d0..7cf1994 100644
--- a/src/com/android/settings/slices/SliceDataConverter.java
+++ b/src/com/android/settings/slices/SliceDataConverter.java
@@ -19,6 +19,7 @@
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_CONTROLLER;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_ICON;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY;
+import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_PLATFORM_SLICE_FLAG;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_SUMMARY;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_TITLE;
@@ -164,7 +165,8 @@
| MetadataFlag.FLAG_NEED_PREF_TYPE
| MetadataFlag.FLAG_NEED_PREF_TITLE
| MetadataFlag.FLAG_NEED_PREF_ICON
- | MetadataFlag.FLAG_NEED_PREF_SUMMARY);
+ | MetadataFlag.FLAG_NEED_PREF_SUMMARY
+ | MetadataFlag.FLAG_NEED_PLATFORM_SLICE_FLAG);
for (Bundle bundle : metadata) {
// TODO (b/67996923) Non-controller Slices should become intent-only slices.
@@ -179,6 +181,7 @@
final int iconResId = bundle.getInt(METADATA_ICON);
final int sliceType = SliceBuilderUtils.getSliceType(mContext, controllerClassName,
key);
+ final boolean isPlatformSlice = bundle.getBoolean(METADATA_PLATFORM_SLICE_FLAG);
final SliceData xmlSlice = new SliceData.Builder()
.setKey(key)
@@ -189,6 +192,7 @@
.setPreferenceControllerClassName(controllerClassName)
.setFragmentName(fragmentName)
.setSliceType(sliceType)
+ .setPlatformDefined(isPlatformSlice)
.build();
xmlSliceData.add(xmlSlice);
diff --git a/src/com/android/settings/system/ResetPreferenceController.java b/src/com/android/settings/system/ResetPreferenceController.java
new file mode 100644
index 0000000..16f7ce3
--- /dev/null
+++ b/src/com/android/settings/system/ResetPreferenceController.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 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.system;
+
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+
+public class ResetPreferenceController extends BasePreferenceController {
+
+ public ResetPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return mContext.getResources().getBoolean(R.bool.config_show_reset_dashboard)
+ ? AVAILABLE
+ : DISABLED_UNSUPPORTED;
+ }
+}
diff --git a/src/com/android/settings/wifi/tether/WifiTetherAutoOffPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherAutoOffPreferenceController.java
index 5fa4e25..8fdae80 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherAutoOffPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherAutoOffPreferenceController.java
@@ -38,7 +38,7 @@
@Override
public void updateState(Preference preference) {
final boolean settingsOn = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.SOFT_AP_TIMEOUT_ENABLED, 0) != 0;
+ Settings.Global.SOFT_AP_TIMEOUT_ENABLED, 1) != 0;
((SwitchPreference) preference).setChecked(settingsOn);
}
diff --git a/tests/robotests/res/values-mcc999/config.xml b/tests/robotests/res/values-mcc999/config.xml
index 788c593..39620d8 100644
--- a/tests/robotests/res/values-mcc999/config.xml
+++ b/tests/robotests/res/values-mcc999/config.xml
@@ -34,6 +34,7 @@
<bool name="config_show_screen_locking_sounds">false</bool>
<bool name="config_show_touch_sounds">false</bool>
<bool name="config_show_device_administrators">false</bool>
+ <bool name="config_show_encryption_and_credentials_encryption_status">false</bool>
<bool name="config_show_premium_sms">false</bool>
<bool name="config_show_data_saver">false</bool>
<bool name="config_show_enabled_vr_listeners">false</bool>
@@ -54,6 +55,7 @@
<bool name="config_show_tts_settings_summary">false</bool>
<bool name="config_show_pointer_speed">false</bool>
<bool name="config_show_vibrate_input_devices">false</bool>
+ <bool name="config_show_reset_dashboard">false</bool>
<bool name="config_show_system_update_settings">false</bool>
<bool name="config_wifi_support_connected_mac_randomization">false</bool>
<bool name="config_show_device_model">false</bool>
diff --git a/tests/robotests/res/xml-mcc999/location_settings.xml b/tests/robotests/res/xml-mcc999/location_settings.xml
index de77bfa..e04f1be 100644
--- a/tests/robotests/res/xml-mcc999/location_settings.xml
+++ b/tests/robotests/res/xml-mcc999/location_settings.xml
@@ -24,6 +24,7 @@
android:title="title"
android:icon="@drawable/ic_android"
android:summary="summary"
- settings:controller="com.android.settings.slices.FakePreferenceController"/>
+ settings:controller="com.android.settings.slices.FakePreferenceController"
+ settings:platform_slice="true"/>
</PreferenceScreen>
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothFilesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothFilesPreferenceControllerTest.java
index 2c1e46d..4335f05 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothFilesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothFilesPreferenceControllerTest.java
@@ -18,6 +18,10 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.pm.PackageManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@@ -28,6 +32,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowApplication;
@@ -38,15 +43,18 @@
private Context mContext;
private BluetoothFilesPreferenceController mController;
private Preference mPreference;
+ @Mock
+ private PackageManager mPackageManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
-
- mContext = RuntimeEnvironment.application;
+ mContext = spy(RuntimeEnvironment.application);
mController = new BluetoothFilesPreferenceController(mContext);
mPreference = new Preference(mContext);
mPreference.setKey(BluetoothFilesPreferenceController.KEY_RECEIVED_FILES);
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java
index 3656b38..373c255 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java
@@ -15,6 +15,8 @@
*/
package com.android.settings.connecteddevice;
+import static com.android.settings.core.BasePreferenceController.DISABLED_UNSUPPORTED;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
@@ -24,6 +26,7 @@
import android.arch.lifecycle.LifecycleOwner;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceManager;
@@ -58,6 +61,8 @@
private PreferenceScreen mPreferenceScreen;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PreferenceManager mPreferenceManager;
+ @Mock
+ private PackageManager mPackageManager;
private PreferenceGroup mPreferenceGroup;
private Context mContext;
@@ -70,7 +75,7 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
- mContext = RuntimeEnvironment.application;
+ mContext = spy(RuntimeEnvironment.application);
mPreference = new Preference(mContext);
mPreference.setKey(PREFERENCE_KEY_1);
mLifecycleOwner = () -> mLifecycle;
@@ -78,6 +83,8 @@
mPreferenceGroup = spy(new PreferenceScreen(mContext, null));
when(mPreferenceGroup.getPreferenceManager()).thenReturn(mPreferenceManager);
doReturn(mContext).when(mDashboardFragment).getContext();
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
mConnectedDeviceGroupController = new ConnectedDeviceGroupController(mDashboardFragment,
mLifecycle, mConnectedBluetoothDeviceUpdater, mConnectedUsbDeviceUpdater);
@@ -134,4 +141,12 @@
verify(mConnectedBluetoothDeviceUpdater).unregisterCallback();
verify(mConnectedUsbDeviceUpdater).unregisterCallback();
}
+
+ @Test
+ public void testGetAvailabilityStatus_noBluetoothFeature_returnUnSupported() {
+ doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
+
+ assertThat(mConnectedDeviceGroupController.getAvailabilityStatus()).isEqualTo(
+ DISABLED_UNSUPPORTED);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/SavedDeviceGroupControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/SavedDeviceGroupControllerTest.java
new file mode 100644
index 0000000..3d606dd
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/connecteddevice/SavedDeviceGroupControllerTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2018 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.connecteddevice;
+
+import static android.arch.lifecycle.Lifecycle.Event.ON_START;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.DISABLED_UNSUPPORTED;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.arch.lifecycle.LifecycleOwner;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceGroup;
+import android.support.v7.preference.PreferenceManager;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.bluetooth.BluetoothDeviceUpdater;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class SavedDeviceGroupControllerTest {
+ private static final String PREFERENCE_KEY_1 = "pref_key_1";
+
+ @Mock
+ private DashboardFragment mDashboardFragment;
+ @Mock
+ private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private PreferenceManager mPreferenceManager;
+ @Mock
+ private PackageManager mPackageManager;
+
+ private PreferenceGroup mPreferenceGroup;
+ private Context mContext;
+ private Preference mPreference;
+ private SavedDeviceGroupController mConnectedDeviceGroupController;
+ private LifecycleOwner mLifecycleOwner;
+ private Lifecycle mLifecycle;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = spy(RuntimeEnvironment.application);
+ mLifecycleOwner = () -> mLifecycle;
+ mLifecycle = new Lifecycle(mLifecycleOwner);
+
+ doReturn(mContext).when(mDashboardFragment).getContext();
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ }
+
+ @Test
+ public void constructor_noBluetoothFeature_shouldNotRegisterCallback() {
+ doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
+
+ mConnectedDeviceGroupController = new SavedDeviceGroupController(mDashboardFragment,
+ mLifecycle, mBluetoothDeviceUpdater);
+
+ assertThat(mConnectedDeviceGroupController.getAvailabilityStatus()).isEqualTo(
+ DISABLED_UNSUPPORTED);
+
+ mLifecycle.handleLifecycleEvent(ON_START);
+ verify(mBluetoothDeviceUpdater, never()).registerCallback();
+ }
+
+
+ @Test
+ public void constructor_hasBluetoothFeature_shouldRegisterCallback() {
+ doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
+
+ mConnectedDeviceGroupController = new SavedDeviceGroupController(mDashboardFragment,
+ mLifecycle, mBluetoothDeviceUpdater);
+
+ assertThat(mConnectedDeviceGroupController.getAvailabilityStatus()).isEqualTo(
+ AVAILABLE);
+
+ mLifecycle.handleLifecycleEvent(ON_START);
+ verify(mBluetoothDeviceUpdater).registerCallback();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java
index 533d4e9..dc492a9 100644
--- a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java
@@ -44,6 +44,7 @@
import com.android.settings.dashboard.DashboardAdapter;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowCardView;
import com.android.settingslib.suggestions.SuggestionControllerMixin;
import com.android.settingslib.utils.IconCache;
@@ -54,12 +55,14 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = ShadowCardView.class)
public class SuggestionAdapterTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
diff --git a/tests/robotests/src/com/android/settings/datetime/timezone/BaseTimeZoneInfoPickerTest.java b/tests/robotests/src/com/android/settings/datetime/timezone/BaseTimeZoneInfoPickerTest.java
index 0d47a3a..3491b03 100644
--- a/tests/robotests/src/com/android/settings/datetime/timezone/BaseTimeZoneInfoPickerTest.java
+++ b/tests/robotests/src/com/android/settings/datetime/timezone/BaseTimeZoneInfoPickerTest.java
@@ -119,5 +119,11 @@
public Context getContext() {
return RuntimeEnvironment.application;
}
+
+ @Override
+ public int getMetricsCategory() {
+ // the metric id doesn't matter in test
+ return 1;
+ }
}
}
diff --git a/tests/robotests/src/com/android/settings/datetime/timezone/FixedOffsetPickerTest.java b/tests/robotests/src/com/android/settings/datetime/timezone/FixedOffsetPickerTest.java
index 1c555b0..007d3c5 100644
--- a/tests/robotests/src/com/android/settings/datetime/timezone/FixedOffsetPickerTest.java
+++ b/tests/robotests/src/com/android/settings/datetime/timezone/FixedOffsetPickerTest.java
@@ -16,41 +16,78 @@
package com.android.settings.datetime.timezone;
+import android.content.Context;
+
+import com.android.settings.datetime.timezone.BaseTimeZoneAdapter.AdapterItem;
import com.android.settings.datetime.timezone.model.TimeZoneData;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import libcore.util.CountryZonesFinder;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
+import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(SettingsRobolectricTestRunner.class)
public class FixedOffsetPickerTest {
+ private CountryZonesFinder mFinder;
+
+ @Before
+ public void setUp() {
+ List regionList = Collections.emptyList();
+ mFinder = mock(CountryZonesFinder.class);
+ when(mFinder.lookupAllCountryIsoCodes()).thenReturn(regionList);
+ }
+
@Test
public void getAllTimeZoneInfos_containsUtcAndGmtZones() {
- List regionList = Collections.emptyList();
- CountryZonesFinder finder = mock(CountryZonesFinder.class);
- when(finder.lookupAllCountryIsoCodes()).thenReturn(regionList);
-
- FixedOffsetPicker picker = new FixedOffsetPicker() {
- @Override
- protected Locale getLocale() {
- return Locale.US;
- }
- };
- List<TimeZoneInfo> infos = picker.getAllTimeZoneInfos(new TimeZoneData(finder));
+ TestFixedOffsetPicker picker = new TestFixedOffsetPicker();
+ List<TimeZoneInfo> infos = picker.getAllTimeZoneInfos(new TimeZoneData(mFinder));
List<String> tzIds = infos.stream().map(info -> info.getId()).collect(Collectors.toList());
- tzIds.contains("Etc/Utc");
- tzIds.contains("Etc/GMT-12");
- tzIds.contains("Etc/GMT+14");
+ assertThat(tzIds).contains("Etc/UTC");
+ assertThat(tzIds).contains("Etc/GMT-14"); // Etc/GMT-14 means GMT+14:00
+ assertThat(tzIds).contains("Etc/GMT+12"); // Etc/GMT+14 means GMT-12:00
+ }
+
+ @Test
+ public void createAdapter_verifyTitleAndOffset() {
+ TestFixedOffsetPicker picker = new TestFixedOffsetPicker();
+ BaseTimeZoneAdapter adapter = picker.createAdapter(new TimeZoneData(mFinder));
+ assertThat(adapter.getItemCount()).isEqualTo(12 + 1 + 14); // 27 GMT offsets from -12 to +14
+ AdapterItem utc = adapter.getItem(0);
+ assertThat(utc.getTitle().toString()).isEqualTo("Coordinated Universal Time");
+ assertThat(utc.getSummary().toString()).isEqualTo("GMT+00:00");
+ AdapterItem gmtMinus12 = adapter.getItem(1);
+ assertThat(gmtMinus12.getTitle().toString()).isEqualTo("GMT-12:00");
+ assertThat(gmtMinus12.getSummary().toString()).isEmpty();
+ }
+
+ public static class TestFixedOffsetPicker extends FixedOffsetPicker {
+ // Make the method public
+ @Override
+ public BaseTimeZoneAdapter createAdapter(TimeZoneData timeZoneData) {
+ return super.createAdapter(timeZoneData);
+ }
+
+ @Override
+ protected Locale getLocale() {
+ return Locale.US;
+ }
+
+ @Override
+ public Context getContext() {
+ return RuntimeEnvironment.application;
+ }
}
}
diff --git a/tests/robotests/src/com/android/settings/development/BluetoothDelayReportsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothDelayReportsPreferenceControllerTest.java
index d529fc1..bdaad0a 100644
--- a/tests/robotests/src/com/android/settings/development/BluetoothDelayReportsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/BluetoothDelayReportsPreferenceControllerTest.java
@@ -16,7 +16,9 @@
package com.android.settings.development;
-import static com.android.settings.development.BluetoothDelayReportsPreferenceController.BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY;
+import static com.android.settings.development.BluetoothDelayReportsPreferenceController
+ .BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -57,11 +59,11 @@
}
@Test
- public void onPreferenceChanged_settingEnabled_turnOnDelayReports() {
+ public void onPreferenceChanged_settingDisabled_turnOnDelayReports() {
mController.onPreferenceChange(mPreference, true /* new value */);
final boolean mode = SystemProperties.getBoolean(
- BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */);
+ BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */);
assertThat(mode).isTrue();
}
@@ -71,14 +73,14 @@
mController.onPreferenceChange(mPreference, false /* new value */);
final boolean mode = SystemProperties.getBoolean(
- BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */);
+ BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */);
assertThat(mode).isFalse();
}
@Test
- public void updateState_settingEnabled_preferenceShouldBeChecked() {
- SystemProperties.set(BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY,
+ public void updateState_settingDisabled_preferenceShouldBeChecked() {
+ SystemProperties.set(BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY,
Boolean.toString(true));
mController.updateState(mPreference);
@@ -87,7 +89,7 @@
@Test
public void updateState_settingDisabled_preferenceShouldNotBeChecked() {
- SystemProperties.set(BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY,
+ SystemProperties.set(BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY,
Boolean.toString(false));
mController.updateState(mPreference);
@@ -99,10 +101,10 @@
mController.onDeveloperOptionsDisabled();
final boolean mode = SystemProperties.getBoolean(
- BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */);
+ BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */);
assertThat(mode).isFalse();
assertThat(mPreference.isEnabled()).isFalse();
assertThat(mPreference.isChecked()).isFalse();
}
-}
\ No newline at end of file
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java
index a3dabba..6f8bb26 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java
@@ -17,6 +17,8 @@
package com.android.settings.fuelgauge.batterytip;
import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.robolectric.Shadows.shadowOf;
@@ -25,11 +27,12 @@
import android.text.format.DateUtils;
import com.android.settings.R;
+import com.android.settings.fuelgauge.Estimate;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip;
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
+import com.android.settings.fuelgauge.batterytip.tips.SummaryTip;
import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip;
-import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowUtils;
@@ -54,6 +57,7 @@
private static final String PACKAGE_NAME = "com.android.app";
private static final String DISPLAY_NAME = "app";
private static final long SCREEN_TIME_MS = DateUtils.HOUR_IN_MILLIS;
+ private static final long AVERAGE_TIME_MS = DateUtils.HOUR_IN_MILLIS;
private BatteryTipDialogFragment mDialogFragment;
private Context mContext;
@@ -61,13 +65,13 @@
private RestrictAppTip mRestrictedOneAppTip;
private RestrictAppTip mRestrictAppsTip;
private UnrestrictAppTip mUnrestrictAppTip;
+ private SummaryTip mSummaryTip;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
- FakeFeatureFactory.setupForTest();
List<AppInfo> highUsageTips = new ArrayList<>();
final AppInfo appInfo = new AppInfo.Builder()
@@ -86,6 +90,8 @@
new ArrayList<>(restrictApps));
mUnrestrictAppTip = new UnrestrictAppTip(BatteryTip.StateType.NEW, appInfo);
+ mSummaryTip = spy(new SummaryTip(BatteryTip.StateType.NEW,
+ Estimate.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN));
}
@Test
@@ -102,7 +108,7 @@
ShadowAlertDialog shadowDialog = shadowOf(dialog);
assertThat(shadowDialog.getMessage())
- .isEqualTo(mContext.getString(R.string.battery_tip_dialog_message, "1h"));
+ .isEqualTo(mContext.getString(R.string.battery_tip_dialog_message, "1h"));
}
@Test
@@ -116,7 +122,7 @@
assertThat(shadowDialog.getTitle()).isEqualTo("Restrict app?");
assertThat(shadowDialog.getMessage())
- .isEqualTo(mContext.getString(R.string.battery_tip_restrict_app_dialog_message));
+ .isEqualTo(mContext.getString(R.string.battery_tip_restrict_app_dialog_message));
}
@Test
@@ -134,7 +140,7 @@
assertThat(shadowDialog.getTitle()).isEqualTo("Restrict 2 apps?");
assertThat(shadowDialog.getMessage())
- .isEqualTo(mContext.getString(R.string.battery_tip_restrict_app_dialog_message));
+ .isEqualTo(mContext.getString(R.string.battery_tip_restrict_app_dialog_message));
assertThat(shadowDialog.getView()).isNotNull();
}
@@ -150,6 +156,34 @@
assertThat(shadowDialog.getTitle()).isEqualTo("Remove restriction for app?");
assertThat(shadowDialog.getMessage())
- .isEqualTo(mContext.getString(R.string.battery_tip_unrestrict_app_dialog_message));
+ .isEqualTo(mContext.getString(R.string.battery_tip_unrestrict_app_dialog_message));
+ }
+
+ @Test
+ public void testOnCreateDialog_summaryTipWithEstimation_fireDialogWithEstimation() {
+ doReturn(AVERAGE_TIME_MS).when(mSummaryTip).getAverageTimeMs();
+ mDialogFragment = BatteryTipDialogFragment.newInstance(mSummaryTip);
+
+ FragmentTestUtil.startFragment(mDialogFragment);
+
+ final AlertDialog dialog = (AlertDialog) ShadowDialog.getLatestDialog();
+ ShadowAlertDialog shadowDialog = shadowOf(dialog);
+
+ assertThat(shadowDialog.getMessage()).isEqualTo(
+ "Based on your usage, your battery usually lasts about 1h when fully charged"
+ + ".\n\nIf you need to extend your battery life, turn on Battery Saver.");
+ }
+
+ @Test
+ public void testOnCreateDialog_summaryTipWithoutEstimation_fireDialogWithoutEstimation() {
+ mDialogFragment = BatteryTipDialogFragment.newInstance(mSummaryTip);
+
+ FragmentTestUtil.startFragment(mDialogFragment);
+
+ final AlertDialog dialog = (AlertDialog) ShadowDialog.getLatestDialog();
+ ShadowAlertDialog shadowDialog = shadowOf(dialog);
+
+ assertThat(shadowDialog.getMessage()).isEqualTo(
+ "If you need to extend your battery life, turn on Battery Saver");
}
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java
index b5cb173..0ac94c0 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java
@@ -15,8 +15,11 @@
*/
package com.android.settings.fuelgauge.batterytip;
-import static com.android.settings.fuelgauge.batterytip.tips.BatteryTip.TipType.SMART_BATTERY_MANAGER;
+import static com.android.settings.fuelgauge.batterytip.tips.BatteryTip.TipType
+ .SMART_BATTERY_MANAGER;
+
import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
@@ -30,6 +33,7 @@
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceManager;
import android.support.v7.preference.PreferenceScreen;
+import android.text.format.DateUtils;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.SettingsActivity;
@@ -54,6 +58,8 @@
private static final String KEY_PREF = "battery_tip";
private static final String KEY_TIP = "key_battery_tip";
+ private static final long AVERAGE_TIME_MS = DateUtils.HOUR_IN_MILLIS;
+
@Mock
private BatteryTipPreferenceController.BatteryTipListener mBatteryTipListener;
@Mock
@@ -87,9 +93,9 @@
mFeatureFactory = FakeFeatureFactory.setupForTest();
mOldBatteryTips = new ArrayList<>();
- mOldBatteryTips.add(new SummaryTip(BatteryTip.StateType.NEW));
+ mOldBatteryTips.add(new SummaryTip(BatteryTip.StateType.NEW, AVERAGE_TIME_MS));
mNewBatteryTips = new ArrayList<>();
- mNewBatteryTips.add(new SummaryTip(BatteryTip.StateType.INVISIBLE));
+ mNewBatteryTips.add(new SummaryTip(BatteryTip.StateType.INVISIBLE, AVERAGE_TIME_MS));
mBatteryTipPreferenceController = new BatteryTipPreferenceController(mContext, KEY_PREF,
mSettingsActivity, null, mBatteryTipListener);
@@ -119,9 +125,9 @@
public void testUpdateBatteryTips_logBatteryTip() {
mBatteryTipPreferenceController.updateBatteryTips(mOldBatteryTips);
- verify(mFeatureFactory.metricsFeatureProvider).action(any(Context.class),
- eq(MetricsProto.MetricsEvent.ACTION_BATTERY_TIP_SHOWN),
- eq(BatteryTip.TipType.SUMMARY));
+ verify(mFeatureFactory.metricsFeatureProvider).action(mContext,
+ MetricsProto.MetricsEvent.ACTION_SUMMARY_TIP,
+ BatteryTip.StateType.NEW);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/SummaryDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/SummaryDetectorTest.java
index 5ca1ad2..df38d34 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/SummaryDetectorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/SummaryDetectorTest.java
@@ -19,6 +19,8 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
+import android.text.format.DateUtils;
+
import com.android.settings.fuelgauge.batterytip.BatteryTipPolicy;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -33,6 +35,7 @@
public class SummaryDetectorTest {
private BatteryTipPolicy mPolicy;
+ private static final long AVERAGE_TIME_MS = DateUtils.HOUR_IN_MILLIS;
@Before
public void setUp() {
@@ -44,14 +47,14 @@
@Test
public void testDetect_disabledByPolicy_tipInvisible() {
ReflectionHelpers.setField(mPolicy, "summaryEnabled", false);
- SummaryDetector detector = new SummaryDetector(mPolicy);
+ SummaryDetector detector = new SummaryDetector(mPolicy, AVERAGE_TIME_MS);
assertThat(detector.detect().isVisible()).isFalse();
}
@Test
public void testDetect_notDisabled_tipVisible() {
- SummaryDetector detector = new SummaryDetector(mPolicy);
+ SummaryDetector detector = new SummaryDetector(mPolicy, AVERAGE_TIME_MS);
assertThat(detector.detect().isVisible()).isTrue();
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTipTest.java
index 753fc48..cee647e 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTipTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTipTest.java
@@ -25,6 +25,7 @@
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import org.junit.Before;
import org.junit.Test;
@@ -122,6 +123,11 @@
// do nothing
}
+ @Override
+ public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
+ // do nothing
+ }
+
public final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public BatteryTip createFromParcel(Parcel in) {
return new TestBatteryTip(in);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTipTest.java
index c30563d..1cac495 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTipTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTipTest.java
@@ -17,28 +17,38 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.verify;
+
import android.content.Context;
import android.os.Parcel;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
@RunWith(SettingsRobolectricTestRunner.class)
public class EarlyWarningTipTest {
+ @Mock
+ private MetricsFeatureProvider mMetricsFeatureProvider;
private Context mContext;
private EarlyWarningTip mEarlyWarningTip;
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
mContext = RuntimeEnvironment.application;
mEarlyWarningTip =
- new EarlyWarningTip(BatteryTip.StateType.NEW, false /* powerSaveModeOn */);
+ new EarlyWarningTip(BatteryTip.StateType.NEW, false /* powerSaveModeOn */);
}
@Test
@@ -55,7 +65,7 @@
@Test
public void testInfo_stateNew_displayPowerModeInfo() {
final EarlyWarningTip tip =
- new EarlyWarningTip(BatteryTip.StateType.NEW, false /* powerModeOn */);
+ new EarlyWarningTip(BatteryTip.StateType.NEW, false /* powerModeOn */);
assertThat(tip.getTitle(mContext)).isEqualTo("Turn on Low Battery Mode");
assertThat(tip.getSummary(mContext)).isEqualTo("Extend your battery life");
@@ -65,7 +75,7 @@
@Test
public void testInfo_stateHandled_displayPowerModeHandledInfo() {
final EarlyWarningTip tip =
- new EarlyWarningTip(BatteryTip.StateType.HANDLED, false /* powerModeOn */);
+ new EarlyWarningTip(BatteryTip.StateType.HANDLED, false /* powerModeOn */);
assertThat(tip.getTitle(mContext)).isEqualTo("Low Battery Mode is on");
assertThat(tip.getSummary(mContext)).isEqualTo("Some features are limited");
@@ -75,7 +85,7 @@
@Test
public void testUpdate_powerModeTurnedOn_typeBecomeHandled() {
final EarlyWarningTip nextTip =
- new EarlyWarningTip(BatteryTip.StateType.INVISIBLE, true /* powerModeOn */);
+ new EarlyWarningTip(BatteryTip.StateType.INVISIBLE, true /* powerModeOn */);
mEarlyWarningTip.updateState(nextTip);
@@ -115,4 +125,12 @@
assertThat(earlyWarningTip.getState()).isEqualTo(BatteryTip.StateType.INVISIBLE);
}
+
+ @Test
+ public void testLog() {
+ mEarlyWarningTip.log(mContext, mMetricsFeatureProvider);
+
+ verify(mMetricsFeatureProvider).action(mContext,
+ MetricsProto.MetricsEvent.ACTION_EARLY_WARNING_TIP, BatteryTip.StateType.NEW);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTipTest.java
index 85b1b02..b038a91 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTipTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTipTest.java
@@ -17,16 +17,22 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.verify;
+
import android.content.Context;
import android.os.Parcel;
import android.text.format.DateUtils;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.fuelgauge.batterytip.AppInfo;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList;
@@ -38,14 +44,17 @@
private static final String PACKAGE_NAME = "com.android.app";
private static final long SCREEN_TIME = 30 * DateUtils.MINUTE_IN_MILLIS;
+ @Mock
+ private MetricsFeatureProvider mMetricsFeatureProvider;
private Context mContext;
private HighUsageTip mBatteryTip;
private List<AppInfo> mUsageAppList;
@Before
public void setUp() {
- mContext = RuntimeEnvironment.application;
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
mUsageAppList = new ArrayList<>();
mUsageAppList.add(new AppInfo.Builder()
.setPackageName(PACKAGE_NAME)
@@ -80,4 +89,15 @@
"type=2 state=0 { packageName=com.android.app,anomalyTypes={},screenTime=1800000 "
+ "}");
}
+
+ @Test
+ public void testLog_logAppInfo() {
+ mBatteryTip.log(mContext, mMetricsFeatureProvider);
+ verify(mMetricsFeatureProvider).action(mContext,
+ MetricsProto.MetricsEvent.ACTION_HIGH_USAGE_TIP, BatteryTip.StateType.NEW);
+
+ verify(mMetricsFeatureProvider).action(mContext,
+ MetricsProto.MetricsEvent.ACTION_HIGH_USAGE_TIP_LIST,
+ PACKAGE_NAME);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTipTest.java
index a2e91cb..9d32b2b 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTipTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTipTest.java
@@ -16,16 +16,25 @@
package com.android.settings.fuelgauge.batterytip.tips;
import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Parcel;
+import android.util.Pair;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.fuelgauge.batterytip.AppInfo;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import org.junit.Before;
import org.junit.Test;
@@ -53,6 +62,8 @@
private ApplicationInfo mApplicationInfo;
@Mock
private PackageManager mPackageManager;
+ @Mock
+ private MetricsFeatureProvider mMetricsFeatureProvider;
@Before
public void setUp() throws Exception {
@@ -132,4 +143,30 @@
assertThat(mNewBatteryTip.toString()).isEqualTo(
"type=1 state=0 { packageName=com.android.app,anomalyTypes={0, 1},screenTime=0 }");
}
+
+ @Test
+ public void testLog_stateNew_logAppInfo() {
+ mNewBatteryTip.log(mContext, mMetricsFeatureProvider);
+
+ verify(mMetricsFeatureProvider).action(mContext,
+ MetricsProto.MetricsEvent.ACTION_APP_RESTRICTION_TIP, BatteryTip.StateType.NEW);
+ verify(mMetricsFeatureProvider).action(mContext,
+ MetricsProto.MetricsEvent.ACTION_APP_RESTRICTION_TIP_LIST,
+ PACKAGE_NAME,
+ Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, ANOMALY_WAKEUP));
+ verify(mMetricsFeatureProvider).action(mContext,
+ MetricsProto.MetricsEvent.ACTION_APP_RESTRICTION_TIP_LIST,
+ PACKAGE_NAME,
+ Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, ANOMALY_WAKELOCK));
+ }
+
+ @Test
+ public void testLog_stateHandled_doNotLogAppInfo() {
+ mHandledBatteryTip.log(mContext, mMetricsFeatureProvider);
+
+ verify(mMetricsFeatureProvider).action(mContext,
+ MetricsProto.MetricsEvent.ACTION_APP_RESTRICTION_TIP, BatteryTip.StateType.HANDLED);
+ verify(mMetricsFeatureProvider, never()).action(any(), anyInt(), anyString(), any());
+
+ }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/SmartBatteryTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/SmartBatteryTipTest.java
new file mode 100644
index 0000000..1e4aef8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/SmartBatteryTipTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 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.fuelgauge.batterytip.tips;
+
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class SmartBatteryTipTest {
+
+ @Mock
+ private MetricsFeatureProvider mMetricsFeatureProvider;
+ private Context mContext;
+ private SmartBatteryTip mSmartBatteryTip;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = RuntimeEnvironment.application;
+ mSmartBatteryTip = new SmartBatteryTip(BatteryTip.StateType.NEW);
+ }
+
+ @Test
+ public void testLog() {
+ mSmartBatteryTip.log(mContext, mMetricsFeatureProvider);
+
+ verify(mMetricsFeatureProvider).action(mContext,
+ MetricsProto.MetricsEvent.ACTION_SMART_BATTERY_TIP, BatteryTip.StateType.NEW);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/SummaryTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/SummaryTipTest.java
new file mode 100644
index 0000000..221c37f
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/SummaryTipTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2018 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.fuelgauge.batterytip.tips;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.os.Parcel;
+import android.text.format.DateUtils;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class SummaryTipTest {
+
+ private static final long AVERAGE_TIME_MS = DateUtils.HOUR_IN_MILLIS;
+
+ @Mock
+ private MetricsFeatureProvider mMetricsFeatureProvider;
+ private Context mContext;
+ private SummaryTip mSummaryTip;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = RuntimeEnvironment.application;
+ mSummaryTip =
+ new SummaryTip(BatteryTip.StateType.NEW, AVERAGE_TIME_MS);
+ }
+
+ @Test
+ public void testParcelable() {
+ Parcel parcel = Parcel.obtain();
+ mSummaryTip.writeToParcel(parcel, mSummaryTip.describeContents());
+ parcel.setDataPosition(0);
+
+ final SummaryTip parcelTip = new SummaryTip(parcel);
+
+ assertThat(parcelTip.getAverageTimeMs()).isEqualTo(AVERAGE_TIME_MS);
+ }
+
+ @Test
+ public void testLog() {
+ mSummaryTip.log(mContext, mMetricsFeatureProvider);
+
+ verify(mMetricsFeatureProvider).action(mContext,
+ MetricsProto.MetricsEvent.ACTION_SUMMARY_TIP, BatteryTip.StateType.NEW);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceControllerTest.java
index 13c99a6..3c8f3c4 100644
--- a/tests/robotests/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceControllerTest.java
@@ -55,7 +55,7 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- when(mContext.getSystemService(Context.INPUT_SERVICE)).thenReturn(mIm);
+ when(mContext.getSystemService(InputManager.class)).thenReturn(mIm);
mController = new PhysicalKeyboardPreferenceController(mContext, null /* lifecycle */);
}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeDurationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeDurationPreferenceControllerTest.java
new file mode 100644
index 0000000..9a94e6c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeDurationPreferenceControllerTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.FragmentManager;
+import android.app.NotificationManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ZenModeDurationPreferenceControllerTest {
+ private ZenModeDurationPreferenceController mController;
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private Preference mockPref;
+ @Mock
+ private NotificationManager.Policy mPolicy;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+ private ContentResolver mContentResolver;
+ private Context mContext;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+
+ mContext = shadowApplication.getApplicationContext();
+ mContentResolver = RuntimeEnvironment.application.getContentResolver();
+ mController = new ZenModeDurationPreferenceController(mContext, mock(Lifecycle.class),
+ mock(FragmentManager.class));
+ when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(
+ mockPref);
+ mController.displayPreference(mPreferenceScreen);
+ }
+
+ @Test
+ public void updateState_DurationForever() {
+ Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION,
+ Settings.Global.ZEN_DURATION_FOREVER);
+ final Preference mockPref = mock(Preference.class);
+ mController.updateState(mockPref);
+
+ verify(mockPref).setSummary(mContext.getString(R.string.zen_mode_duration_summary_forever));
+ }
+
+ @Test
+ public void updateState_DurationPrompt() {
+ Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION,
+ Settings.Global.ZEN_DURATION_PROMPT);
+ final Preference mockPref = mock(Preference.class);
+ mController.updateState(mockPref);
+
+ verify(mockPref).setSummary(mContext.getString(
+ R.string.zen_mode_duration_summary_always_prompt));
+ }
+
+ @Test
+ public void updateState_DurationCustom() {
+ int zenDuration = 45;
+ Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION,
+ zenDuration);
+ final Preference mockPref = mock(Preference.class);
+ mController.updateState(mockPref);
+
+ verify(mockPref).setSummary(mContext.getResources().getString(
+ R.string.zen_mode_duration_summary_time_minutes, zenDuration));
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeSettingsTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeSettingsTest.java
index 5c81efc..bd94bf5 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeSettingsTest.java
@@ -47,27 +47,12 @@
}
@Test
- public void testGetBehaviorSettingSummary_customBehavior() {
- NotificationManager.Policy policy = new NotificationManager.Policy(
- NotificationManager.Policy.PRIORITY_CATEGORY_EVENTS
- | NotificationManager.Policy.PRIORITY_CATEGORY_REMINDERS
- | NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS
- | NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA,
- 0, 0);
- final String result = mBuilder.getBehaviorSettingSummary(policy,
- Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
-
- String custom = mContext.getString(R.string.zen_mode_behavior_summary_custom);
- assertEquals(custom, result);
- }
-
- @Test
- public void testGetBehaviorSettingSummary_totalSilence() {
+ public void testGetBehaviorSettingSummary_noSoundsCanBypass() {
NotificationManager.Policy policy = new NotificationManager.Policy(0, 0, 0);
final String result = mBuilder.getBehaviorSettingSummary(policy,
Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
- String totalSilence = mContext.getString(R.string.zen_mode_behavior_total_silence);
+ String totalSilence = mContext.getString(R.string.zen_mode_no_exceptions);
assertEquals(totalSilence, result);
}
@@ -80,7 +65,9 @@
final String result = mBuilder.getBehaviorSettingSummary(policy,
Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
- String alarmsAndMedia = mContext.getString(R.string.zen_mode_behavior_alarms_only);
+ String alarmsAndMedia = mContext.getString(R.string.join_two_items,
+ mContext.getString(R.string.zen_mode_alarms),
+ mContext.getString(R.string.zen_mode_media).toLowerCase());
assertEquals(alarmsAndMedia, result);
}
diff --git a/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java
index ee6d33a..2e6b703 100644
--- a/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java
@@ -68,6 +68,23 @@
}
@Test
+ @Config(qualifiers = "mcc999")
+ public void isAvailable_notVisible_false() {
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ @Config(qualifiers = "mcc999")
+ public void isAvailable_notVisible_butNotDetailPage_true() {
+ mController = new EncryptionStatusPreferenceController(mContext,
+ PREF_KEY_ENCRYPTION_SECURITY_PAGE);
+
+ UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ Shadows.shadowOf(userManager).setIsAdminUser(true);
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
public void updateSummary_encrypted_shouldSayEncrypted() {
ShadowLockPatternUtils.setDeviceEncryptionEnabled(true);
diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
index 50f47ff..9edae7e 100644
--- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
@@ -18,8 +18,7 @@
package com.android.settings.slices;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
+
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -28,6 +27,7 @@
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
+import android.provider.SettingsSlicesContract;
import com.android.settings.testutils.DatabaseTestUtils;
import com.android.settings.testutils.FakeToggleController;
@@ -50,6 +50,8 @@
public class SettingsSliceProviderTest {
private final String KEY = "KEY";
+ private final String INTENT_PATH = SettingsSlicesContract.PATH_SETTING_INTENT + "/" + KEY;
+ private final String ACTION_PATH = SettingsSlicesContract.PATH_SETTING_ACTION + "/" + KEY;
private final String TITLE = "title";
private final String SUMMARY = "summary";
private final String SCREEN_TITLE = "screen title";
@@ -67,6 +69,8 @@
mProvider = spy(new SettingsSliceProvider());
mProvider.mSliceDataCache = new HashMap<>();
mProvider.mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(mContext);
+ when(mProvider.getContext()).thenReturn(mContext);
+
mDb = SlicesDatabaseHelper.getInstance(mContext).getWritableDatabase();
SlicesDatabaseHelper.getInstance(mContext).setIndexedState();
}
@@ -78,12 +82,8 @@
@Test
public void testInitialSliceReturned_emptySlice() {
- insertSpecialCase(KEY);
- ContentResolver mockResolver = mock(ContentResolver.class);
- doReturn(mockResolver).when(mContext).getContentResolver();
- when(mProvider.getContext()).thenReturn(mContext);
-
- Uri uri = SettingsSliceProvider.getUri(KEY);
+ insertSpecialCase(INTENT_PATH);
+ Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
Slice slice = mProvider.onBindSlice(uri);
assertThat(slice.getUri()).isEqualTo(uri);
@@ -91,21 +91,9 @@
}
@Test
- public void testUriBuilder_returnsValidSliceUri() {
- Uri uri = SettingsSliceProvider.getUri(KEY);
-
- assertThat(uri.getScheme()).isEqualTo(ContentResolver.SCHEME_CONTENT);
- assertThat(uri.getAuthority()).isEqualTo(SettingsSliceProvider.SLICE_AUTHORITY);
- assertThat(uri.getLastPathSegment()).isEqualTo(KEY);
- }
-
- @Test
public void testLoadSlice_returnsSliceFromAccessor() {
- ContentResolver mockResolver = mock(ContentResolver.class);
- doReturn(mockResolver).when(mContext).getContentResolver();
- when(mProvider.getContext()).thenReturn(mContext);
insertSpecialCase(KEY);
- Uri uri = SettingsSliceProvider.getUri(KEY);
+ Uri uri = SliceBuilderUtils.getUri(KEY, false);
mProvider.loadSlice(uri);
SliceData data = mProvider.mSliceDataCache.get(uri);
@@ -116,7 +104,6 @@
@Test
public void testLoadSlice_cachedEntryRemovedOnBuild() {
- when(mProvider.getContext()).thenReturn(mContext);
SliceData data = getDummyData();
mProvider.mSliceDataCache.put(data.getUri(), data);
mProvider.onBindSlice(data.getUri());
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
index 5a2271a..0fcce5f 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
@@ -20,8 +20,10 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
+import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
+import android.provider.SettingsSlicesContract;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
@@ -48,6 +50,9 @@
private final Class PREF_CONTROLLER = FakeToggleController.class;
private final Class PREF_CONTROLLER2 = FakeContextOnlyPreferenceController.class;
+ private final String INTENT_PATH = SettingsSlicesContract.PATH_SETTING_INTENT + "/" + KEY;
+ private final String ACTION_PATH = SettingsSlicesContract.PATH_SETTING_ACTION + "/" + KEY;
+
private Context mContext;
@Before
@@ -63,6 +68,58 @@
}
@Test
+ public void testUriBuilder_oemAuthority_intentPath_returnsValidSliceUri() {
+ Uri expectedUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(INTENT_PATH)
+ .build();
+
+ Uri actualUri = SliceBuilderUtils.getUri(INTENT_PATH, false);
+
+ assertThat(actualUri).isEqualTo(expectedUri);
+ }
+
+ @Test
+ public void testUriBuilder_oemAuthority_actionPath_returnsValidSliceUri() {
+ Uri expectedUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(ACTION_PATH)
+ .build();
+
+ Uri actualUri = SliceBuilderUtils.getUri(ACTION_PATH, false);
+
+ assertThat(actualUri).isEqualTo(expectedUri);
+ }
+
+ @Test
+ public void testUriBuilder_platformAuthority_intentPath_returnsValidSliceUri() {
+ Uri expectedUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSlicesContract.AUTHORITY)
+ .appendPath(ACTION_PATH)
+ .build();
+
+ Uri actualUri = SliceBuilderUtils.getUri(ACTION_PATH, true);
+
+ assertThat(actualUri).isEqualTo(expectedUri);
+ }
+
+ @Test
+ public void testUriBuilder_platformAuthority_actionPath_returnsValidSliceUri() {
+ Uri expectedUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSlicesContract.AUTHORITY)
+ .appendPath(ACTION_PATH)
+ .build();
+
+ Uri actualUri = SliceBuilderUtils.getUri(ACTION_PATH, true);
+
+ assertThat(actualUri).isEqualTo(expectedUri);
+ }
+
+ @Test
public void testGetPreferenceController_buildsMatchingController() {
BasePreferenceController controller =
SliceBuilderUtils.getPreferenceController(mContext, getDummyData());
diff --git a/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java b/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
index 4d6c08d..36c2754 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
@@ -81,6 +81,7 @@
assertThat(fakeSlice.getUri()).isNull();
assertThat(fakeSlice.getFragmentClassName()).isEqualTo(fakeFragmentClassName);
assertThat(fakeSlice.getPreferenceController()).isEqualTo(fakeControllerName);
- assertThat(fakeSlice.getSliceType()).isEqualTo(SliceData.SliceType.SLIDER);
+ assertThat(fakeSlice.getSliceType()).isEqualTo(SliceData.SliceType.SLIDER); // from XML
+ assertThat(fakeSlice.isPlatformDefined()).isTrue(); // from XML
}
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/slices/SliceDataTest.java b/tests/robotests/src/com/android/settings/slices/SliceDataTest.java
index 7cd19b5..c2ab0af 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceDataTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceDataTest.java
@@ -37,6 +37,7 @@
private final Uri URI = Uri.parse("content://com.android.settings.slices/test");
private final String PREF_CONTROLLER = "com.android.settings.slices.tester";
private final int SLICE_TYPE = SliceData.SliceType.SWITCH;
+ private final boolean IS_PLATFORM_DEFINED = true;
@Test
public void testBuilder_buildsMatchingObject() {
@@ -49,7 +50,8 @@
.setFragmentName(FRAGMENT_NAME)
.setUri(URI)
.setPreferenceControllerClassName(PREF_CONTROLLER)
- .setSliceType(SLICE_TYPE);
+ .setSliceType(SLICE_TYPE)
+ .setPlatformDefined(IS_PLATFORM_DEFINED);
SliceData data = builder.build();
@@ -62,6 +64,7 @@
assertThat(data.getUri()).isEqualTo(URI);
assertThat(data.getPreferenceController()).isEqualTo(PREF_CONTROLLER);
assertThat(data.getSliceType()).isEqualTo(SLICE_TYPE);
+ assertThat(data.isPlatformDefined()).isEqualTo(IS_PLATFORM_DEFINED);
}
@Test(expected = IllegalStateException.class)
diff --git a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java
index 8989de9..331058c 100644
--- a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java
@@ -90,7 +90,7 @@
public void testGetSliceFromUri_validUri_validSliceReturned() {
String key = "key";
insertSpecialCase(key);
- Uri uri = SettingsSliceProvider.getUri(key);
+ Uri uri = SliceBuilderUtils.getUri(key, false);
SliceData data = mAccessor.getSliceDataFromUri(uri);
@@ -106,7 +106,7 @@
@Test(expected = IllegalStateException.class)
public void testGetSliceFromUri_invalidUri_errorThrown() {
- Uri uri = SettingsSliceProvider.getUri("durr");
+ Uri uri = SliceBuilderUtils.getUri("durr", false);
mAccessor.getSliceDataFromUri(uri);
}
diff --git a/tests/robotests/src/com/android/settings/system/ResetPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/system/ResetPreferenceControllerTest.java
new file mode 100644
index 0000000..3869903
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/system/ResetPreferenceControllerTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 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.system;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ResetPreferenceControllerTest {
+
+ private static final String KEY_RESET_DASHBOARD = "reset_dashboard";
+
+ private Context mContext;
+ private ResetPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = new ResetPreferenceController(mContext, KEY_RESET_DASHBOARD);
+ }
+
+ @Test
+ public void isAvailable_byDefault_true() {
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ @Config(qualifiers = "mcc999")
+ public void isAvailable_ifNotVisible_false() {
+ assertThat(mController.isAvailable()).isFalse();
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowCardView.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowCardView.java
new file mode 100644
index 0000000..e349ee3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowCardView.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 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.testutils.shadow;
+
+import android.content.Context;
+import android.support.v7.widget.CardView;
+import android.util.AttributeSet;
+
+import org.robolectric.annotation.Implements;
+import org.robolectric.shadows.ShadowFrameLayout;
+
+/**
+ * Shadow for CardView to get around view not implemented error.
+ */
+@Implements(CardView.class)
+public class ShadowCardView extends ShadowFrameLayout {
+
+ public void __constructor__(Context context, AttributeSet attrs, int defStyleAttr) {
+ // do nothing
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherAutoOffPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherAutoOffPreferenceControllerTest.java
index 2b14e88..c553764 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherAutoOffPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherAutoOffPreferenceControllerTest.java
@@ -81,6 +81,13 @@
assertThat(mSwitchPreference.isChecked()).isFalse();
}
+ @Test
+ public void testUpdateState_toggleDefaultOn() {
+ mController.updateState(mSwitchPreference);
+
+ assertThat(mSwitchPreference.isChecked()).isTrue();
+ }
+
private int getAutoOffSetting() {
return Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.SOFT_AP_TIMEOUT_ENABLED, OFF);