Snap for 4562879 from 0ad01ef2e0 to pi-release

Change-Id: Ia3c88dd78e9dd4b6e7d7c4b5643a5f2d22a8fe6e
This commit is contained in:
android-build-team Robot
2018-01-24 08:21:00 +00:00
66 changed files with 2962 additions and 474 deletions

View File

@@ -1004,6 +1004,34 @@
android:value="true" />
</activity>
<activity android:name="Settings$MeCardActivity"
android:label="@string/device_info_settings"
android:icon="@drawable/ic_settings_about"
android:taskAffinity="com.android.settings"
android:parentActivityName="Settings">
<intent-filter android:priority="1">
<action android:name="android.settings.DEVICE_INFO_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.VOICE_LAUNCH" />
</intent-filter>
<intent-filter android:priority="10">
<action android:name="com.android.settings.action.SETTINGS" />
</intent-filter>
<meta-data android:name="com.android.settings.category"
android:value="com.android.settings.category.ia.system" />
<meta-data android:name="com.android.settings.title"
android:resource="@string/about_settings" />
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.deviceinfo.aboutphone.MyDeviceInfoFragment" />
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
</activity>
<activity android:name="SettingsLicenseActivity"
android:label="@string/settings_license_activity_title"
android:theme="@android:style/Theme.DeviceDefault.Light.Panel"
@@ -2200,12 +2228,15 @@
android:label="@string/power_usage_summary_title"
android:icon="@drawable/ic_settings_battery"
android:enabled="false">
<!-- TODO(b/69867246): add priority for this intent-filter -->
<intent-filter>
<intent-filter android:priority="1">
<action android:name="android.intent.action.POWER_USAGE_SUMMARY" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<!-- TODO(b/69867246): add shortcut intent-filter -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.android.settings.SHORTCUT" />
</intent-filter>
<intent-filter android:priority="8">
<action android:name="com.android.settings.action.SETTINGS" />
</intent-filter>
@@ -2227,15 +2258,10 @@
<activity android:name=".Settings$PowerUsageSummaryLegacyActivity"
android:label="@string/power_usage_summary_title"
android:icon="@drawable/ic_settings_battery">
<intent-filter android:priority="1">
<intent-filter>
<action android:name="android.intent.action.POWER_USAGE_SUMMARY" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.android.settings.SHORTCUT" />
</intent-filter>
<intent-filter android:priority="8">
<action android:name="com.android.settings.action.SETTINGS" />
</intent-filter>
@@ -2686,10 +2712,6 @@
<!-- Show channel group-level notification settings (group passed in as extras) -->
<activity android:name="Settings$ChannelGroupNotificationSettingsActivity"
android:exported="true">
<intent-filter android:priority="1">
<action android:name="android.settings.CHANNEL_GROUP_NOTIFICATION_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
@@ -3200,99 +3222,6 @@
android:permission="android.permission.DUMP"
android:enabled="@bool/config_has_help" />
<!-- Activities for moves/gestures suggestions -->
<activity
android:name=".Settings$DoubleTapPowerSuggestionActivity"
android:label="@string/double_tap_power_for_camera_title"
android:icon="@drawable/ic_settings_gestures">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="com.android.settings.suggested.category.GESTURE" />
</intent-filter>
<meta-data android:name="com.android.settings.dismiss"
android:value="4,8,30" />
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.gestures.DoubleTapPowerSettings"/>
<meta-data android:name="com.android.settings.title"
android:resource="@string/double_tap_power_for_camera_suggestion_title" />
<meta-data android:name="com.android.settings.summary"
android:resource="@string/double_tap_power_for_camera_suggestion_summary" />
</activity>
<activity
android:name=".Settings$DoubleTwistSuggestionActivity"
android:label="@string/double_twist_for_camera_mode_title"
android:icon="@drawable/ic_settings_gestures">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="com.android.settings.suggested.category.GESTURE" />
</intent-filter>
<meta-data android:name="com.android.settings.dismiss"
android:value="4,8,30" />
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.gestures.DoubleTwistGestureSettings"/>
<meta-data android:name="com.android.settings.title"
android:resource="@string/double_twist_for_camera_suggestion_title" />
<meta-data android:name="com.android.settings.summary"
android:resource="@string/double_twist_for_camera_suggestion_summary" />
</activity>
<activity
android:name=".Settings$AmbientDisplaySuggestionActivity"
android:label="@string/ambient_display_title"
android:icon="@drawable/ic_settings_gestures">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="com.android.settings.suggested.category.GESTURE" />
</intent-filter>
<meta-data android:name="com.android.settings.dismiss"
android:value="9,13,30" />
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.gestures.DoubleTapScreenSettings"/>
<meta-data android:name="com.android.settings.title"
android:resource="@string/ambient_display_title" />
<meta-data android:name="com.android.settings.summary"
android:resource="@string/ambient_display_suggestion_summary" />
</activity>
<activity
android:name=".Settings$AmbientDisplayPickupSuggestionActivity"
android:label="@string/ambient_display_pickup_title"
android:icon="@drawable/ic_settings_gestures">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="com.android.settings.suggested.category.GESTURE" />
</intent-filter>
<meta-data android:name="com.android.settings.dismiss"
android:value="9,13,30" />
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.gestures.PickupGestureSettings"/>
<meta-data android:name="com.android.settings.title"
android:resource="@string/ambient_display_pickup_title" />
<meta-data android:name="com.android.settings.summary"
android:resource="@string/ambient_display_pickup_suggestion_summary" />
</activity>
<activity
android:name=".Settings$SwipeToNotificationSuggestionActivity"
android:label="@string/fingerprint_swipe_for_notifications_title"
android:icon="@drawable/ic_settings_gestures">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="com.android.settings.suggested.category.GESTURE" />
</intent-filter>
<meta-data android:name="com.android.settings.dismiss"
android:value="9,13,30" />
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.gestures.SwipeToNotificationSettings"/>
<meta-data android:name="com.android.settings.title"
android:resource="@string/fingerprint_swipe_for_notifications_suggestion_title" />
<meta-data android:name="com.android.settings.summary"
android:resource="@string/fingerprint_swipe_for_notifications_suggestion_summary" />
</activity>
<!-- End activities for moves/gestures suggestions -->
<activity android:name=".applications.autofill.AutofillPickerActivity"
android:excludeFromRecents="true"
android:launchMode="singleInstance"
@@ -3330,6 +3259,17 @@
android:value="true" />
</activity>
<activity android:name="Settings$DirectoryAccessSettingsActivity"
android:label="@string/directory_access"
android:taskAffinity="">
<intent-filter>
<action android:name="android.settings.STORAGE_VOLUME_ACCESS_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.applications.manageapplications.ManageApplications" />
</activity>
<provider android:name=".slices.SettingsSliceProvider"
android:authorities="com.android.settings.slices"
android:exported="true">

View File

@@ -30,7 +30,7 @@
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_gravity="left"
android:text="@string/zen_mode_button_turn_on"
android:paddingEnd="8dp" />
@@ -40,7 +40,7 @@
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_gravity="left"
android:text="@string/zen_mode_button_turn_off"
android:paddingEnd="8dp" />

View File

@@ -266,14 +266,16 @@
<item>PWD</item>
</string-array>
<!-- Wi-Fi AP band settings. Either 2.4GHz or 5GHz. -->
<!-- Wi-Fi AP band settings. Either Auto, 2.4GHz or 5GHz. -->
<!-- Note that adding/removing/moving the items will need wifi settings code change. -->
<string-array name="wifi_ap_band_config_full">
<item>@string/wifi_ap_choose_auto</item>
<item>@string/wifi_ap_choose_2G</item>
<item>@string/wifi_ap_choose_5G</item>
</string-array>
<string-array name="wifi_ap_band_config_2G_only">
<item>@string/wifi_ap_choose_auto</item>
<item>@string/wifi_ap_choose_2G</item>
</string-array>

View File

@@ -44,6 +44,10 @@
<!-- Whether to show Camera laser sensor switch in Developer Options -->
<bool name="config_show_camera_laser_sensor">false</bool>
<!-- Whether to show Connected MAC Randomization in Developer Options
as not all devices can support dynamic MAC address change. -->
<bool name="config_wifi_support_connected_mac_randomization">false</bool>
<!-- Fully-qualified class name for the implementation of the FeatureFactory to be instantiated. -->
<string name="config_featureFactory" translatable="false">com.android.settings.overlay.FeatureFactoryImpl</string>

View File

@@ -106,13 +106,9 @@
<!-- Dashboard tile image margin start / end -->
<dimen name="dashboard_tile_image_margin">24dp</dimen>
<!-- SwitchBar margin start / end -->
<dimen name="switchbar_margin_start">16dp</dimen>
<dimen name="switchbar_margin_end">16dp</dimen>
<!-- SwitchBar sub settings margin start / end -->
<dimen name="switchbar_subsettings_margin_start">72dp</dimen>
<dimen name="switchbar_subsettings_margin_end">24dp</dimen>
<dimen name="switchbar_subsettings_margin_end">16dp</dimen>
<!-- The following two margins need to match, with the caveat that
the second should be negative. The second one ensures that the icons and text

View File

@@ -788,6 +788,10 @@
<string name="security_enable_widgets_title">Enable widgets</string>
<!-- Summary for settings checkbox to disable widgets when the setting has been disabled by an installed device admin [CHAR LIMIT=50] -->
<string name="security_enable_widgets_disabled_summary">Disabled by admin</string>
<!-- Text shown for the title of the lockdown option -->
<string name="lockdown_settings_title">Show lockdown option</string>
<!-- Text shown for the description of the lockdown option -->
<string name="lockdown_settings_summary">Display power button option that turns off extended access and fingerprint unlocking.</string>
<!-- Text shown for summary of owner info setting (if none set) [CHAR LIMIT=40]-->
<string name="owner_info_settings_summary">None</string>
<!-- Description of how many characters are used in owner info [CHAR LIMIT=40]-->
@@ -1116,14 +1120,18 @@
<!-- Security Picker --><skip />
<!-- Title for suggested actions for screen lock -->
<string name="suggested_lock_settings_title">Set screen lock</string>
<!-- Title for suggested actions for screen lock [CHAR LIMIT=34] -->
<string name="suggested_lock_settings_title">Set screen lock for security</string>
<!-- Summary for suggested actions for screen lock -->
<string name="suggested_lock_settings_summary">Protect your device</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>
<!-- Title for suggested actions for settings up a fingerprint lock -->
<string name="suggested_fingerprint_lock_settings_title">Use fingerprint</string>
<!-- Title for suggested actions for settings up a fingerprint lock [CHAR LIMIT=34] -->
<string name="suggested_fingerprint_lock_settings_title">Unlock with fingerprint</string>
<!-- Summary for suggested actions for settings up a fingerprint lock -->
<string name="suggested_fingerprint_lock_settings_summary">Unlock with your fingerprint</string>
@@ -1941,6 +1949,8 @@
<string name="wifi_show_password">Show password</string>
<!-- Label for the RadioGroup to choose wifi ap band -->
<string name="wifi_ap_band_config">Select AP Band</string>
<!-- Label for the radio button to choose wifi ap channel automatically-->
<string name="wifi_ap_choose_auto">Auto</string>
<!-- Label for the radio button to choose wifi ap 2.4 GHz band -->
<string name="wifi_ap_choose_2G">2.4 GHz Band</string>
<!-- Label for the radio button to choose wifi ap 5GHz band -->
@@ -2247,7 +2257,7 @@
<!-- Title of suggestion to turn on wifi calling [CHAR LIMIT=30] -->
<string name="wifi_calling_suggestion_title">Turn on Wi-Fi Calling</string>
<!-- Summary of suggestion to turn on wifi calling [CHAR LIMIT=60] -->
<string name="wifi_calling_suggestion_summary">Use Wi-Fi instead of mobile network</string>
<string name="wifi_calling_suggestion_summary">Extend coverage by calling over Wi-Fi</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] -->
@@ -5588,10 +5598,12 @@
<string name="add_account_label">Add account</string>
<!-- Label for the state of the work profile [CHAR LIMIT=80] -->
<string name="managed_profile_not_available_label">Work profile isn\u2019t available yet</string>
<!-- Account Settings. The preference title for enabling work mode -->
<string name="work_mode_label">Work mode</string>
<!-- Account Settings. The preference summary for enabling work mode -->
<string name="work_mode_summary">Allow work profile to function, including apps, background sync, and related features</string>
<!-- This string is the title of a setting. If a user taps the setting, they can turn their work profile on or off. The work profile is a section of their phone that's managed by their employer. "Work" is an adjective. -->
<string name="work_mode_label">Work profile</string>
<!-- This string is located under a setting and describes what the setting does. It's letting a user know whether their work profile is on or off, and they can use the setting to turn it on or off. The work profile is a section of their phone that's managed by their employer. "Work" is an adjective.-->
<string name="work_mode_on_summary">Managed by your organization</string>
<!-- This string is located under a setting and describes what the setting does. It's letting a user know whether their work profile is on or off, and they can use the setting to turn it on or off. The work profile is a section of their phone that's managed by their employer. "Work" is an adjective.-->
<string name="work_mode_off_summary">Apps and notifications are off</string>
<!-- Button label to remove the work profile [CHAR LIMIT=35] -->
<string name="remove_managed_profile_label">Remove work profile</string>
<!-- Data synchronization settings screen, title of setting that controls whether background data should be used [CHAR LIMIT=30] -->
@@ -6437,6 +6449,7 @@
<string name="help_uri_process_stats_summary" translatable="false"></string>
<string name="help_uri_process_stats_apps" translatable="false"></string>
<string name="help_uri_private_dns" translatable="false"></string>
<string name="help_uri_about_phone_v2" translatable="false"></string>
<!-- User account title [CHAR LIMIT=30] -->
<string name="user_account_title">Account for content</string>
@@ -6845,6 +6858,9 @@
<!-- Sound: Title for the Do not Disturb option and associated settings page. [CHAR LIMIT=50]-->
<string name="zen_mode_settings_title">Do Not Disturb</string>
<!-- Do not disturb: Title for the Do not Disturb dialog to turn on Do not disturb. [CHAR LIMIT=50]-->
<string name="zen_mode_settings_turn_on_dialog_title">Turn on Do Not Disturb</string>
<!-- Do not disturb: Title for the behaviors option and associated settings page. [CHAR LIMIT=30] -->
<string name="zen_mode_behavior_settings_title">Behavior</string>
@@ -6872,11 +6888,11 @@
<!-- 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=50] -->
<string name="zen_mode_automation_suggestion_title">Set Do Not Disturb rules</string>
<!-- Do not disturb: Title for the zen mode automation option Suggestion. [CHAR LIMIT=34] -->
<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] -->
<string name="zen_mode_automation_suggestion_summary">Limit sounds &amp; vibrations at certain times</string>
<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] -->
<string name="zen_mode_use_automatic_rule">Use rule</string>
@@ -6902,6 +6918,9 @@
<!-- Do not disturb: Button to add new automatic rule to DND. [CHAR LIMIT=30] -->
<string name="zen_mode_add">Add</string>
<!-- Do not disturb: Label for button in enable zen dialog that will turn on zen mode. [CHAR LIMIT=30] -->
<string name="zen_mode_enable_dialog_turn_on">Turn on</string>
<!-- Do not disturb: Label for button that will turn on zen mode. [CHAR LIMIT=30] -->
<string name="zen_mode_button_turn_on">Turn on now</string>
@@ -6920,6 +6939,12 @@
<!-- [CHAR LIMIT=110] Zen mode settings footer: Footer how DND was triggered by an app -->
<string name="zen_mode_settings_dnd_automatic_rule_app">Do Not Disturb was automatically turned on by an app (<xliff:g id="app_name" example="Android Services">%s</xliff:g>)</string>
<!--[CHAR LIMIT=40] Zen Interruption level: Priority. -->
<string name="zen_interruption_level_priority">Priority only</string>
<!-- [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>
<!-- Work Sounds: Work sound settings section header. [CHAR LIMIT=50] -->
<string name="sound_work_settings">Work profile sounds</string>
@@ -6965,6 +6990,9 @@
<!-- Configure Notifications Settings title. [CHAR LIMIT=30] -->
<string name="configure_notification_settings">Notifications</string>
<!-- notification header - apps that have recently sent notifications -->
<string name="recent_notifications">Recently sent</string>
<!-- Configure Notifications: Advanced section header [CHAR LIMIT=30] -->
<string name="advanced_section_header">Advanced</string>
@@ -8415,7 +8443,7 @@
<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] -->
<string name="night_display_suggestion_summary">Tint screen amber to help you fall asleep</string>
<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] -->
<string name="condition_night_display_title">Night Light is on</string>
@@ -8696,7 +8724,10 @@
<string name="notification_log_details_ranking_none">Ranking object doesn\'t contain this key.</string>
<!-- [CHAR_LIMIT=NONE] Developer Settings: Title of the setting which turns on emulation of a display cutout. -->
<string name="display_cutout_emulation">Emulate a display with a cutout</string>
<string name="display_cutout_emulation">Simulate a display with a cutout</string>
<!-- [CHAR_LIMIT=NONE] Developer Settings: Label for the option that turns off display cutout emulation. -->
<string name="display_cutout_emulation_none">None</string>
<!-- [CHAR_LIMIT=60] Label for special access screen -->
<string name="special_access">Special app access</string>
@@ -8834,9 +8865,6 @@
<!-- Title for settings suggestion for double tap power for camera [CHAR LIMIT=60] -->
<string name="double_tap_power_for_camera_suggestion_title">Open camera quickly</string>
<!-- Summary for settings suggestion for double tap power for camera [CHAR LIMIT=60] -->
<string name="double_tap_power_for_camera_suggestion_summary">Press power button twice to open camera</string>
<!-- Title text for double twist for camera mode [CHAR LIMIT=60]-->
<string name="double_twist_for_camera_mode_title">Flip camera</string>
@@ -8846,13 +8874,6 @@
<!-- Title for settings suggestion for double twist for camera [CHAR LIMIT=60] -->
<string name="double_twist_for_camera_suggestion_title">Take selfies faster</string>
<!-- Summary for settings suggestion for double twist for camera (phone) [CHAR LIMIT=60] -->
<string name="double_twist_for_camera_suggestion_summary" product="default">Double-twist phone for selfie mode</string>
<!-- Summary for settings suggestion for double twist for camera (tablet) [CHAR LIMIT=60] -->
<string name="double_twist_for_camera_suggestion_summary" product="tablet">Double-twist tablet for selfie mode</string>
<!-- Summary for settings suggestion for double twist for camera (device) [CHAR LIMIT=60] -->
<string name="double_twist_for_camera_suggestion_summary" product="device">Double-twist device for selfie mode</string>
<!-- Preference and settings suggestion title text for ambient display double tap (phone) [CHAR LIMIT=60]-->
<string name="ambient_display_title" product="default">Double-tap to check phone</string>
<!-- Preference and settings suggestion title text for ambient display double tap (tablet) [CHAR LIMIT=60]-->
@@ -8863,9 +8884,6 @@
<!-- Summary text for ambient display double tap [CHAR LIMIT=NONE]-->
<string name="ambient_display_summary">To check time, notification icons, and other info, double-tap your screen.</string>
<!-- Summary for settings suggestion for double tap power for camera [CHAR LIMIT=60] -->
<string name="ambient_display_suggestion_summary">Check notifications when screen is off</string>
<!-- Preference and settings suggestion title text for ambient display pick up (phone) [CHAR LIMIT=60]-->
<string name="ambient_display_pickup_title" product="default">Lift to check phone</string>
<!-- Preference and settings suggestion title text for ambient display pick up (tablet) [CHAR LIMIT=60]-->
@@ -8880,9 +8898,6 @@
<!-- Summary text for ambient display (device) [CHAR LIMIT=NONE]-->
<string name="ambient_display_pickup_summary" product="device">To check time, notification icons, and other info, pick up your device.</string>
<!-- Summary for settings suggestion for ambient display pick up [CHAR LIMIT=60] -->
<string name="ambient_display_pickup_suggestion_summary">Check notifications when screen is off</string>
<!-- Title text for swiping downwards on fingerprint sensor for notifications [CHAR LIMIT=80]-->
<string name="fingerprint_swipe_for_notifications_title">Swipe fingerprint for notifications</string>
<!-- Title text for fingerprint gesture preference screen [CHAR LIMIT=25] -->
@@ -8898,9 +8913,6 @@
<!-- Title for settings suggestion for fingerprint swipe for notifications [CHAR LIMIT=60] -->
<string name="fingerprint_swipe_for_notifications_suggestion_title">See notifications quickly</string>
<!-- Summary for settings suggestion for fingerprint swipe for notifications [CHAR LIMIT=60] -->
<string name="fingerprint_swipe_for_notifications_suggestion_summary">Swipe down on the fingerprint sensor</string>
<!-- Title text for the assist gesture [CHAR LIMIT=60] DO NOT TRANSLATE -->
<string name="assist_gesture_title" translatable="false"></string>
@@ -9223,4 +9235,15 @@
[DO NOT TRANSLATE] -->
<string name="account_confirmation_package"></string>
<!-- Title for the new About Phone screen [CHAR LIMIT=40] -->
<string name="my_device_info_title" product="default">My Phone</string>
<!-- Title for the new About Phone screen [CHAR LIMIT=40] -->
<string name="my_device_info_title" product="tablet">My Tablet</string>
<!-- Title for the new About Phone screen [CHAR LIMIT=40] -->
<string name="my_device_info_title" product="device">My Device</string>
<!-- Title for preference showing the primary account on the device [CHAR LIMIT=60]-->
<string name="my_device_info_account_preference_title">Account</string>
<!-- Title for preference showing the name of the device. [CHAR LIMIT=60]-->
<string name="my_device_info_device_name_preference_title">Device name</string>
</resources>

View File

@@ -19,8 +19,28 @@
android:key="configure_notification_settings">
<PreferenceCategory
android:key="dashboard_tile_placeholder"
android:order="1"/>
android:key="recent_notifications_category"
android:title="@string/recent_notifications"
android:order="-200">
<!-- Placeholder for a list of recent apps -->
<!-- See all apps button -->
<Preference
android:title="@string/notifications_title"
android:key="all_notifications"
android:order="20">
<intent
android:action="android.intent.action.MAIN"
android:targetPackage="com.android.settings"
android:targetClass="com.android.settings.Settings$NotificationAppListActivity">
</intent>
</Preference>
</PreferenceCategory>
<!-- Empty category to draw divider -->
<PreferenceCategory
android:key="all_notifications_divider"
android:order="-190"/>
<!-- When device is locked -->
<com.android.settings.notification.RestrictedDropDownPreference

View File

@@ -202,6 +202,11 @@
android:title="@string/wifi_verbose_logging"
android:summary="@string/wifi_verbose_logging_summary"/>
<SwitchPreference
android:key="wifi_connected_mac_randomization"
android:title="@string/wifi_connected_mac_randomization"
android:summary="@string/wifi_connected_mac_randomization_summary"/>
<SwitchPreference
android:key="mobile_data_always_on"
android:title="@string/mobile_data_always_on"
@@ -346,7 +351,7 @@
android:key="density"
android:title="@string/developer_smallest_width" />
<SwitchPreference
<ListPreference
android:key="display_cutout_emulation"
android:title="@string/display_cutout_emulation" />

View File

@@ -20,14 +20,13 @@
<SwitchPreference
android:key="work_mode"
android:summary="@string/work_mode_summary"
android:title="@string/work_mode_label"/>
android:title="@string/work_mode_label"
android:summary="@string/summary_placeholder"/>
<com.android.settingslib.RestrictedSwitchPreference
android:key="contacts_search"
android:summary="@string/managed_profile_contact_search_summary"
android:title="@string/managed_profile_contact_search_title"
settings:useAdditionalSummary="true"
/>
settings:useAdditionalSummary="true"/>
</PreferenceScreen>

167
res/xml/my_device_info.xml Normal file
View File

@@ -0,0 +1,167 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="my_device_info_pref_screen"
android:title="@string/my_device_info_title"
settings:initialExpandedChildrenCount="4">
<com.android.settings.applications.LayoutPreference
android:key="my_device_info_header"
android:order="0"
android:layout="@layout/settings_entity_header"
android:selectable="false"/>
<!-- Account name -->
<Preference
android:key="account"
android:order="1"
android:title="@string/my_device_info_account_preference_title"
android:summary="@string/summary_placeholder"/>
<!-- Phone number -->
<Preference
android:key="phone_number"
android:order="2"
android:title="@string/status_number"
android:summary="@string/summary_placeholder"/>
<!-- Device name -->
<Preference
android:key="device_name"
android:order="3"
android:title="@string/my_device_info_device_name_preference_title"
android:summary="@string/summary_placeholder"/>
<!-- SIM status -->
<Preference
android:key="sim_status"
android:order="4"
android:title="@string/sim_status_title"
settings:keywords="@string/keywords_sim_status"
android:summary="@string/summary_placeholder"/>
<!-- Model & hardware -->
<Preference
android:key="device_model"
android:order="21"
android:title="@string/hardware_info"
settings:keywords="@string/keywords_model_and_hardware"
android:summary="@string/summary_placeholder"/>
<!-- IMEI -->
<Preference
android:key="imei_info"
android:order="22"
android:title="@string/status_imei"
settings:keywords="@string/keywords_imei_info"
android:summary="@string/summary_placeholder"/>
<!-- Android version -->
<Preference
android:key="firmware_version"
android:order="32"
android:title="@string/firmware_version"
settings:keywords="@string/keywords_android_version"
android:summary="@string/summary_placeholder"/>
<!-- IMS registration -->
<Preference
android:key="ims_reg_state"
android:order="33"
android:title="@string/ims_reg_title"
android:summary="@string/summary_placeholder"/>
<!--IP address -->
<Preference
android:key="wifi_ip_address"
android:order="34"
android:title="@string/wifi_ip_address"
android:summary="@string/summary_placeholder"
settings:allowDividerAbove="true"/>
<!-- Wi-Fi MAC address -->
<Preference
android:key="wifi_mac_address"
android:order="35"
android:title="@string/status_wifi_mac_address"
android:summary="@string/summary_placeholder"/>
<!-- Bluetooth address -->
<Preference
android:key="bt_address"
android:order="36"
android:title="@string/status_bt_address"
android:summary="@string/summary_placeholder"/>
<!-- Legal information -->
<Preference
android:key="legal_container"
android:order="37"
android:title="@string/legal_information"
android:fragment="com.android.settings.LegalSettings"
settings:allowDividerAbove="true"/>
<!-- Regulatory labels -->
<Preference
android:key="regulatory_info"
android:order="38"
android:title="@string/regulatory_labels">
<intent android:action="android.settings.SHOW_REGULATORY_INFO"/>
</Preference>
<!-- Safety & regulatory manual -->
<Preference
android:key="safety_info"
android:order="39"
android:title="@string/safety_and_regulatory_info">
<intent android:action="android.settings.SHOW_SAFETY_AND_REGULATORY_INFO"/>
</Preference>
<!-- Manual -->
<Preference
android:key="manual"
android:order="40"
android:title="@string/manual">
<intent android:action="android.settings.SHOW_MANUAL"/>
</Preference>
<!-- Feedback on the device -->
<Preference
android:key="device_feedback"
android:order="41"
android:title="@string/device_feedback"/>
<!-- Device FCC equipment id -->
<Preference
android:key="fcc_equipment_id"
android:order="42"
android:title="@string/fcc_equipment_id"
android:summary="@string/summary_placeholder"/>
<!-- Build number -->
<Preference
android:key="build_number"
android:order="43"
android:title="@string/build_number"
android:summary="@string/summary_placeholder"
settings:allowDividerAbove="true"/>
</PreferenceScreen>

View File

@@ -33,6 +33,11 @@
android:title="@string/owner_info_settings_title"
android:summary="@string/owner_info_settings_summary" />
<SwitchPreference
android:key="security_setting_lockdown_enabled"
android:title="@string/lockdown_settings_title"
android:summary="@string/lockdown_settings_summary" />
<PreferenceCategory
android:key="security_setting_lock_screen_notif_work_header"
android:title="@string/profile_section_header">

View File

@@ -16,6 +16,7 @@
package com.android.settings;
import static android.provider.Telephony.Carriers.CONTENT_URI;
import static android.provider.Telephony.Carriers.FILTERED_URI;
import android.content.ContentUris;
@@ -36,6 +37,7 @@ import android.widget.RelativeLayout;
public class ApnPreference extends Preference implements
CompoundButton.OnCheckedChangeListener, OnClickListener {
final static String TAG = "ApnPreference";
private boolean mDpcEnforced = false;
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -119,7 +121,8 @@ public class ApnPreference extends Preference implements
Context context = getContext();
if (context != null) {
int pos = Integer.parseInt(getKey());
Uri url = ContentUris.withAppendedId(FILTERED_URI, pos);
Uri url = ContentUris.withAppendedId(
mDpcEnforced ? FILTERED_URI : CONTENT_URI, pos);
Intent editIntent = new Intent(Intent.ACTION_EDIT, url);
editIntent.putExtra(ApnSettings.SUB_ID, mSubId);
context.startActivity(editIntent);
@@ -138,4 +141,8 @@ public class ApnPreference extends Preference implements
public void setSubId(int subId) {
mSubId = subId;
}
public void setDpcEnforced(boolean enforced) {
mDpcEnforced = enforced;
}
}

View File

@@ -16,6 +16,7 @@
package com.android.settings;
import static android.provider.Telephony.Carriers.CONTENT_URI;
import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI;
import static android.provider.Telephony.Carriers.FILTERED_URI;
@@ -291,6 +292,7 @@ public class ApnSettings extends RestrictedSettingsFragment implements
mSelectedKey = getSelectedApnKey();
cursor.moveToFirst();
boolean enforced = isDpcApnEnforced();
while (!cursor.isAfterLast()) {
String name = cursor.getString(NAME_INDEX);
String apn = cursor.getString(APN_INDEX);
@@ -307,6 +309,7 @@ public class ApnSettings extends RestrictedSettingsFragment implements
pref.setPersistent(false);
pref.setOnPreferenceChangeListener(this);
pref.setSubId(subId);
pref.setDpcEnforced(enforced);
boolean selectable = ((type == null) || !type.equals("mms"));
pref.setSelectable(selectable);
@@ -398,7 +401,7 @@ public class ApnSettings extends RestrictedSettingsFragment implements
@Override
public boolean onPreferenceTreeClick(Preference preference) {
int pos = Integer.parseInt(preference.getKey());
Uri url = ContentUris.withAppendedId(FILTERED_URI, pos);
Uri url = ContentUris.withAppendedId(isDpcApnEnforced() ? FILTERED_URI : CONTENT_URI, pos);
startActivity(new Intent(Intent.ACTION_EDIT, url));
return true;
}

View File

@@ -16,7 +16,6 @@
package com.android.settings;
import static com.android.settings.core.FeatureFlags.BATTERY_SETTINGS_V2;
import static com.android.settings.core.FeatureFlags.CONNECTED_DEVICE_V2;
import android.os.Bundle;
@@ -55,6 +54,7 @@ public class Settings extends SettingsActivity {
public static class NightDisplaySettingsActivity extends SettingsActivity { /* empty */ }
public static class NightDisplaySuggestionActivity extends NightDisplaySettingsActivity { /* empty */ }
public static class DeviceInfoSettingsActivity extends SettingsActivity { /* empty */ }
public static class MeCardActivity extends SettingsActivity { /* empty */ }
public static class ApplicationSettingsActivity extends SettingsActivity { /* empty */ }
public static class ManageApplicationsActivity extends SettingsActivity { /* empty */ }
public static class ManageAssistActivity extends SettingsActivity { /* empty */ }
@@ -133,16 +133,8 @@ public class Settings extends SettingsActivity {
public static class AppWriteSettingsActivity extends SettingsActivity { /* empty */ }
public static class AdvancedAppsActivity extends SettingsActivity { /* empty */ }
public static class ManageExternalSourcesActivity extends SettingsActivity {
/* empty */ }
public static class ManageExternalSourcesActivity extends SettingsActivity {/* empty */ }
public static class ManageAppExternalSourcesActivity extends SettingsActivity { /* empty */ }
public static class DoubleTapPowerSuggestionActivity extends SettingsActivity { /* empty */ }
public static class DoubleTwistSuggestionActivity extends SettingsActivity { /* empty */ }
public static class AmbientDisplaySuggestionActivity extends SettingsActivity { /* empty */ }
public static class AmbientDisplayPickupSuggestionActivity extends SettingsActivity {
/* empty */ }
public static class SwipeToNotificationSuggestionActivity extends SettingsActivity {
/* empty */ }
public static class WallpaperSettingsActivity extends SettingsActivity { /* empty */ }
public static class ManagedProfileSettingsActivity extends SettingsActivity { /* empty */ }
public static class DeletionHelperActivity extends SettingsActivity { /* empty */ }

View File

@@ -877,6 +877,19 @@ public class SettingsActivity extends SettingsDrawerActivity
WifiDisplaySettings.isAvailable(this), isAdmin)
|| somethingChanged;
// Enable/disable the Me Card page.
final boolean isMeCardEnabled = featureFactory
.getAccountFeatureProvider()
.isMeCardEnabled(this);
somethingChanged = setTileEnabled(new ComponentName(packageName,
Settings.MeCardActivity.class.getName()),
isMeCardEnabled, isAdmin)
|| somethingChanged;
somethingChanged = setTileEnabled(new ComponentName(packageName,
Settings.DeviceInfoSettingsActivity.class.getName()),
!isMeCardEnabled, isAdmin)
|| somethingChanged;
if (UserHandle.MU_ENABLED && !isAdmin) {
// When on restricted users, disable all extra categories (but only the settings ones).

View File

@@ -0,0 +1,34 @@
/*
* 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.accounts;
import android.accounts.Account;
import android.content.Context;
import android.util.FeatureFlagUtils;
import com.android.settings.core.FeatureFlags;
public interface AccountFeatureProvider {
String getAccountType();
Account[] getAccounts(Context context);
/**
* Checks whether or not to display the new About Phone page.
*/
default boolean isMeCardEnabled(Context context) {
return FeatureFlagUtils.isEnabled(context, FeatureFlags.ABOUT_PHONE_V2);
}
}

View File

@@ -0,0 +1,16 @@
package com.android.settings.accounts;
import android.accounts.Account;
import android.content.Context;
public class AccountFeatureProviderImpl implements AccountFeatureProvider {
@Override
public String getAccountType() {
return null;
}
@Override
public Account[] getAccounts(Context context) {
return new Account[0];
}
}

View File

@@ -104,8 +104,7 @@ public class ManagedProfileSettings extends SettingsPreferenceFragment
private void loadDataAndPopulateUi() {
if (mWorkModePreference != null) {
mWorkModePreference.setChecked(
!mUserManager.isQuietModeEnabled(mManagedUser));
updateWorkModePreference();
}
if (mContactPrefrence != null) {
@@ -124,6 +123,14 @@ public class ManagedProfileSettings extends SettingsPreferenceFragment
return MetricsProto.MetricsEvent.ACCOUNTS_WORK_PROFILE_SETTINGS;
}
private void updateWorkModePreference() {
boolean isWorkModeOn = !mUserManager.isQuietModeEnabled(mManagedUser);
mWorkModePreference.setChecked(isWorkModeOn);
mWorkModePreference.setSummary(isWorkModeOn
? R.string.work_mode_on_summary
: R.string.work_mode_off_summary);
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
@@ -159,8 +166,7 @@ public class ManagedProfileSettings extends SettingsPreferenceFragment
|| action.equals(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)) {
if (intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
UserHandle.USER_NULL) == mManagedUser.getIdentifier()) {
mWorkModePreference.setChecked(
!mUserManager.isQuietModeEnabled(mManagedUser));
updateWorkModePreference();
}
return;
}

View File

@@ -27,4 +27,5 @@ public class FeatureFlags {
public static final String SECURITY_SETTINGS_V2 = "settings_security_settings_v2";
public static final String ZONE_PICKER_V2 = "settings_zone_picker_v2";
public static final String SUGGESTION_UI_V2 = "settings_suggestion_ui_v2";
public static final String ABOUT_PHONE_V2 = "settings_about_phone_v2";
}

View File

@@ -298,5 +298,6 @@ public class SettingsGateway {
Settings.DateTimeSettingsActivity.class.getName(),
Settings.DeviceInfoSettingsActivity.class.getName(),
Settings.EnterprisePrivacySettingsActivity.class.getName(),
Settings.MeCardActivity.class.getName(),
};
}

View File

@@ -30,20 +30,10 @@ import android.util.Pair;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.Settings.AmbientDisplayPickupSuggestionActivity;
import com.android.settings.Settings.AmbientDisplaySuggestionActivity;
import com.android.settings.Settings.DoubleTapPowerSuggestionActivity;
import com.android.settings.Settings.DoubleTwistSuggestionActivity;
import com.android.settings.Settings.NightDisplaySuggestionActivity;
import com.android.settings.Settings.SwipeToNotificationSuggestionActivity;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.fingerprint.FingerprintEnrollSuggestionActivity;
import com.android.settings.fingerprint.FingerprintSuggestionActivity;
import com.android.settings.gestures.DoubleTapPowerPreferenceController;
import com.android.settings.gestures.DoubleTapScreenPreferenceController;
import com.android.settings.gestures.DoubleTwistPreferenceController;
import com.android.settings.gestures.PickupGesturePreferenceController;
import com.android.settings.gestures.SwipeToNotificationPreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ScreenLockSuggestionActivity;
import com.android.settings.support.NewDeviceIntroSuggestionActivity;
@@ -98,21 +88,6 @@ public class SuggestionFeatureProviderImpl implements SuggestionFeatureProvider
return hasUsedNightDisplay(context);
} else if (className.equals(NewDeviceIntroSuggestionActivity.class.getName())) {
return NewDeviceIntroSuggestionActivity.isSuggestionComplete(context);
} else if (className.equals(DoubleTapPowerSuggestionActivity.class.getName())) {
return DoubleTapPowerPreferenceController
.isSuggestionComplete(context, getSharedPrefs(context));
} else if (className.equals(DoubleTwistSuggestionActivity.class.getName())) {
return DoubleTwistPreferenceController
.isSuggestionComplete(context, getSharedPrefs(context));
} else if (className.equals(AmbientDisplaySuggestionActivity.class.getName())) {
return DoubleTapScreenPreferenceController
.isSuggestionComplete(context, getSharedPrefs(context));
} else if (className.equals(AmbientDisplayPickupSuggestionActivity.class.getName())) {
return PickupGesturePreferenceController
.isSuggestionComplete(context, getSharedPrefs(context));
} else if (className.equals(SwipeToNotificationSuggestionActivity.class.getName())) {
return SwipeToNotificationPreferenceController
.isSuggestionComplete(context, getSharedPrefs(context));
}
return false;
}

View File

@@ -398,6 +398,7 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
controllers.add(new CameraLaserSensorPreferenceController(context));
controllers.add(new WifiDisplayCertificationPreferenceController(context));
controllers.add(new WifiVerboseLoggingPreferenceController(context));
controllers.add(new WifiConnectedMacRandomizationPreferenceController(context));
controllers.add(new MobileDataAlwaysOnPreferenceController(context));
controllers.add(new TetheringHardwareAccelPreferenceController(context));
controllers.add(new SelectUsbConfigPreferenceController(context, lifecycle));

View File

@@ -16,41 +16,52 @@
package com.android.settings.development;
import static android.os.UserHandle.USER_SYSTEM;
import android.content.Context;
import android.content.om.IOverlayManager;
import android.content.om.OverlayInfo;
import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.support.v7.preference.TwoStatePreference;
import android.text.TextUtils;
import com.android.internal.util.ArrayUtils;
import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.development.DeveloperOptionsPreferenceController;
import java.util.List;
public class EmulateDisplayCutoutPreferenceController extends
DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener,
PreferenceControllerMixin {
private static final String EMULATION_OVERLAY = "com.android.internal.display.cutout.emulation";
public static final String EMULATION_OVERLAY_PREFIX =
"com.android.internal.display.cutout.emulation.";
private static final String KEY = "display_cutout_emulation";
private final IOverlayManager mOverlayManager;
private final boolean mAvailable;
private TwoStatePreference mPreference;
private ListPreference mPreference;
private PackageManager mPackageManager;
@VisibleForTesting
EmulateDisplayCutoutPreferenceController(Context context, IOverlayManager overlayManager) {
EmulateDisplayCutoutPreferenceController(Context context, PackageManager packageManager,
IOverlayManager overlayManager) {
super(context);
mOverlayManager = overlayManager;
mAvailable = overlayManager != null && getEmulationOverlayInfo() != null;
mPackageManager = packageManager;
mAvailable = overlayManager != null && getOverlayInfos().length > 0;
}
public EmulateDisplayCutoutPreferenceController(Context context) {
this(context, IOverlayManager.Stub.asInterface(
this(context, context.getPackageManager(), IOverlayManager.Stub.asInterface(
ServiceManager.getService(Context.OVERLAY_SERVICE)));
}
@@ -67,45 +78,95 @@ public class EmulateDisplayCutoutPreferenceController extends
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
setPreference((TwoStatePreference) screen.findPreference(getPreferenceKey()));
setPreference((ListPreference) screen.findPreference(getPreferenceKey()));
}
@VisibleForTesting
void setPreference(TwoStatePreference preference) {
void setPreference(ListPreference preference) {
mPreference = preference;
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
return writeEnabled((boolean) newValue);
return setEmulationOverlay((String) newValue);
}
private boolean writeEnabled(boolean newValue) {
OverlayInfo current = getEmulationOverlayInfo();
if (current == null || current.isEnabled() == newValue) {
return false;
private boolean setEmulationOverlay(String packageName) {
OverlayInfo[] overlays = getOverlayInfos();
CharSequence currentPackageName = null;
for (OverlayInfo o : overlays) {
if (o.isEnabled()) {
currentPackageName = o.packageName;
}
}
try {
return mOverlayManager.setEnabled(EMULATION_OVERLAY, newValue, UserHandle.USER_SYSTEM);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
if (TextUtils.isEmpty(packageName) && TextUtils.isEmpty(currentPackageName)
|| TextUtils.equals(packageName, currentPackageName)) {
// Already set.
return true;
}
for (OverlayInfo o : overlays) {
boolean isEnabled = o.isEnabled();
boolean shouldBeEnabled = TextUtils.equals(o.packageName, packageName);
if (isEnabled != shouldBeEnabled) {
try {
mOverlayManager.setEnabled(o.packageName, shouldBeEnabled, USER_SYSTEM);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
updateState(mPreference);
return true;
}
@Override
public void updateState(Preference preference) {
OverlayInfo overlayInfo = getEmulationOverlayInfo();
mPreference.setChecked(overlayInfo != null && overlayInfo.isEnabled());
OverlayInfo[] overlays = getOverlayInfos();
CharSequence[] pkgs = new CharSequence[overlays.length + 1];
CharSequence[] labels = new CharSequence[pkgs.length];
int current = 0;
pkgs[0] = "";
labels[0] = mContext.getString(R.string.display_cutout_emulation_none);
for (int i = 0; i < overlays.length; i++) {
OverlayInfo o = overlays[i];
pkgs[i+1] = o.packageName;
if (o.isEnabled()) {
current = i+1;
}
}
for (int i = 1; i < pkgs.length; i++) {
try {
labels[i] = mPackageManager.getApplicationInfo(pkgs[i].toString(), 0)
.loadLabel(mPackageManager);
} catch (PackageManager.NameNotFoundException e) {
labels[i] = pkgs[i];
}
}
mPreference.setEntries(labels);
mPreference.setEntryValues(pkgs);
mPreference.setValueIndex(current);
mPreference.setSummary(labels[current]);
}
private OverlayInfo getEmulationOverlayInfo() {
OverlayInfo overlayInfo = null;
private OverlayInfo[] getOverlayInfos() {
try {
overlayInfo = mOverlayManager.getOverlayInfo(EMULATION_OVERLAY, UserHandle.USER_SYSTEM);
@SuppressWarnings("unchecked") List<OverlayInfo> overlayInfos =
mOverlayManager.getOverlayInfosForTarget("android", USER_SYSTEM);
for (int i = overlayInfos.size() - 1; i >= 0; i--) {
if (!overlayInfos.get(i).packageName.startsWith(EMULATION_OVERLAY_PREFIX)) {
overlayInfos.remove(i);
}
}
return overlayInfos.toArray(new OverlayInfo[overlayInfos.size()]);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return overlayInfo;
}
@Override
@@ -115,8 +176,8 @@ public class EmulateDisplayCutoutPreferenceController extends
@Override
protected void onDeveloperOptionsSwitchDisabled() {
writeEnabled(false);
mPreference.setChecked(false);
setEmulationOverlay("");
updateState(mPreference);
mPreference.setEnabled(false);
}
}

View File

@@ -0,0 +1,93 @@
/*
* 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.development;
import android.content.Context;
import android.provider.Settings;
import android.support.annotation.VisibleForTesting;
import android.support.v14.preference.SwitchPreference;
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.development.DeveloperOptionsPreferenceController;
public class WifiConnectedMacRandomizationPreferenceController extends
DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener,
PreferenceControllerMixin {
private static final String WIFI_CONNECTED_MAC_RANDOMIZATION_KEY =
"wifi_connected_mac_randomization";
@VisibleForTesting
static final int SETTING_VALUE_ON = 1;
@VisibleForTesting
static final int SETTING_VALUE_OFF = 0;
private SwitchPreference mPreference;
public WifiConnectedMacRandomizationPreferenceController(Context context) {
super(context);
}
@Override
public boolean isAvailable() {
return mContext.getResources().getBoolean(
R.bool.config_wifi_support_connected_mac_randomization);
}
@Override
public String getPreferenceKey() {
return WIFI_CONNECTED_MAC_RANDOMIZATION_KEY;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = (SwitchPreference) screen.findPreference(getPreferenceKey());
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean isEnabled = (Boolean) newValue;
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED,
isEnabled ? SETTING_VALUE_ON : SETTING_VALUE_OFF);
return true;
}
@Override
public void updateState(Preference preference) {
final int enableMode = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, SETTING_VALUE_OFF);
mPreference.setChecked(enableMode != SETTING_VALUE_OFF);
}
@Override
protected void onDeveloperOptionsSwitchEnabled() {
mPreference.setEnabled(true);
}
@Override
protected void onDeveloperOptionsSwitchDisabled() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, SETTING_VALUE_OFF);
mPreference.setChecked(false);
mPreference.setEnabled(false);
}
}

View File

@@ -0,0 +1,78 @@
/*
* 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.deviceinfo;
import android.accounts.Account;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.accounts.AccountDetailDashboardFragment;
import com.android.settings.accounts.AccountFeatureProvider;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory;
public class BrandedAccountPreferenceController extends BasePreferenceController {
private static final String KEY_PREFERENCE_TITLE = "account";
private final Account[] mAccounts;
public BrandedAccountPreferenceController(Context context) {
super(context, KEY_PREFERENCE_TITLE);
final AccountFeatureProvider accountFeatureProvider = FeatureFactory.getFactory(
mContext).getAccountFeatureProvider();
mAccounts = accountFeatureProvider.getAccounts(mContext);
}
@Override
public int getAvailabilityStatus() {
if (mAccounts != null && mAccounts.length > 0) {
return AVAILABLE;
}
return DISABLED_FOR_USER;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
final AccountFeatureProvider accountFeatureProvider = FeatureFactory.getFactory(
mContext).getAccountFeatureProvider();
final Preference accountPreference = screen.findPreference(KEY_PREFERENCE_TITLE);
if (accountPreference != null && (mAccounts == null || mAccounts.length == 0)) {
screen.removePreference(accountPreference);
return;
}
accountPreference.setSummary(mAccounts[0].name);
accountPreference.setOnPreferenceClickListener(preference -> {
final Bundle args = new Bundle();
args.putParcelable(AccountDetailDashboardFragment.KEY_ACCOUNT,
mAccounts[0]);
args.putParcelable(AccountDetailDashboardFragment.KEY_USER_HANDLE,
android.os.Process.myUserHandle());
args.putString(AccountDetailDashboardFragment.KEY_ACCOUNT_TYPE,
accountFeatureProvider.getAccountType());
Utils.startWithFragment(mContext, AccountDetailDashboardFragment.class.getName(),
args, null, 0,
R.string.account_sync_title, null, MetricsEvent.ACCOUNT);
return true;
});
}
}

View File

@@ -0,0 +1,180 @@
/*
* 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.deviceinfo.aboutphone;
import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.pm.UserInfo;
import android.os.Bundle;
import android.os.UserManager;
import android.provider.SearchIndexableResource;
import android.telephony.TelephonyManager;
import android.view.View;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.deviceinfo.BluetoothAddressPreferenceController;
import com.android.settings.deviceinfo.BrandedAccountPreferenceController;
import com.android.settings.deviceinfo.BuildNumberPreferenceController;
import com.android.settings.deviceinfo.DeviceModelPreferenceController;
import com.android.settings.deviceinfo.FccEquipmentIdPreferenceController;
import com.android.settings.deviceinfo.FeedbackPreferenceController;
import com.android.settings.deviceinfo.ImsStatusPreferenceController;
import com.android.settings.deviceinfo.IpAddressPreferenceController;
import com.android.settings.deviceinfo.ManualPreferenceController;
import com.android.settings.deviceinfo.PhoneNumberPreferenceController;
import com.android.settings.deviceinfo.RegulatoryInfoPreferenceController;
import com.android.settings.deviceinfo.SafetyInfoPreferenceController;
import com.android.settings.deviceinfo.WifiMacAddressPreferenceController;
import com.android.settings.deviceinfo.firmwareversion.FirmwareVersionPreferenceController;
import com.android.settings.deviceinfo.imei.ImeiInfoPreferenceController;
import com.android.settings.deviceinfo.simstatus.SimStatusPreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MyDeviceInfoFragment extends DashboardFragment {
private static final String LOG_TAG = "MeCardFragment";
private static final String KEY_MY_DEVICE_INFO_HEADER = "my_device_info_header";
private static final String KEY_LEGAL_CONTAINER = "legal_container";
@Override
public int getMetricsCategory() {
return MetricsEvent.DEVICEINFO;
}
@Override
public int getHelpResource() {
return R.string.help_uri_about;
}
@Override
public void onResume() {
super.onResume();
initHeader();
}
@Override
protected String getLogTag() {
return LOG_TAG;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.my_device_info;
}
@Override
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
return buildPreferenceControllers(context, getActivity(), this /* fragment */,
getLifecycle());
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Activity activity, Fragment fragment, Lifecycle lifecycle) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new PhoneNumberPreferenceController(context));
controllers.add(new BrandedAccountPreferenceController(context));
controllers.add(new SimStatusPreferenceController(context, fragment));
controllers.add(new DeviceModelPreferenceController(context, fragment));
controllers.add(new ImeiInfoPreferenceController(context, fragment));
controllers.add(new FirmwareVersionPreferenceController(context, fragment));
controllers.add(new ImsStatusPreferenceController(context, lifecycle));
controllers.add(new IpAddressPreferenceController(context, lifecycle));
controllers.add(new WifiMacAddressPreferenceController(context, lifecycle));
controllers.add(new BluetoothAddressPreferenceController(context, lifecycle));
controllers.add(new RegulatoryInfoPreferenceController(context));
controllers.add(new SafetyInfoPreferenceController(context));
controllers.add(new ManualPreferenceController(context));
controllers.add(new FeedbackPreferenceController(fragment, context));
controllers.add(new FccEquipmentIdPreferenceController(context));
controllers.add(
new BuildNumberPreferenceController(context, activity, fragment, lifecycle));
// TODO: Add preference controller for getting the device name.
return controllers;
}
private void initHeader() {
// TODO: Migrate into its own controller.
final LayoutPreference headerPreference =
(LayoutPreference) getPreferenceScreen().findPreference(KEY_MY_DEVICE_INFO_HEADER);
final View appSnippet = headerPreference.findViewById(R.id.entity_header);
final Activity context = getActivity();
final Bundle bundle = getArguments();
EntityHeaderController controller = EntityHeaderController
.newInstance(context, this, appSnippet)
.setRecyclerView(getListView(), getLifecycle())
.setButtonActions(EntityHeaderController.ActionType.ACTION_NONE,
EntityHeaderController.ActionType.ACTION_NONE);
// TODO: There may be an avatar setting action we can use here.
final int iconId = bundle.getInt("icon_id", 0);
if (iconId == 0) {
UserManager userManager = (UserManager) getActivity().getSystemService(
Context.USER_SERVICE);
UserInfo info = Utils.getExistingUser(userManager, android.os.Process.myUserHandle());
controller.setLabel(info.name);
controller.setIcon(
com.android.settingslib.Utils.getUserIcon(getActivity(), userManager, info));
}
controller.done(context, true /* rebindActions */);
}
/**
* For Search.
*/
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.my_device_info;
return Arrays.asList(sir);
}
@Override
public List<AbstractPreferenceController> getPreferenceControllers(
Context context) {
return buildPreferenceControllers(context, null /*activity */,
null /* fragment */, null /* lifecycle */);
}
@Override
public List<String> getNonIndexableKeys(Context context) {
List<String> keys = super.getNonIndexableKeys(context);
// The legal container is duplicated, so we ignore it here.
keys.add(KEY_LEGAL_CONTAINER);
return keys;
}
};
}

View File

@@ -20,11 +20,9 @@ import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle;
import android.support.v14.preference.PreferenceFragment;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.CheckBoxPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
@@ -36,9 +34,7 @@ import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.fuelgauge.anomaly.Anomaly;
import com.android.settings.fuelgauge.anomaly.AnomalyDialogFragment;
import com.android.settings.fuelgauge.anomaly.AnomalyPreference;
import com.android.settings.widget.AppCheckBoxPreference;
import com.android.settingslib.core.AbstractPreferenceController;
import java.util.List;
@@ -120,7 +116,7 @@ public class RestrictedAppDetails extends DashboardFragment {
final Context context = getPrefContext();
for (int i = 0, size = mPackageOpsList.size(); i < size; i++) {
final CheckBoxPreference checkBoxPreference = new CheckBoxPreference(context);
final CheckBoxPreference checkBoxPreference = new AppCheckBoxPreference(context);
final AppOpsManager.PackageOps packageOps = mPackageOpsList.get(i);
try {
final ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(
@@ -128,6 +124,10 @@ public class RestrictedAppDetails extends DashboardFragment {
checkBoxPreference.setChecked(true);
checkBoxPreference.setTitle(mPackageManager.getApplicationLabel(applicationInfo));
checkBoxPreference.setKey(packageOps.getPackageName());
checkBoxPreference.setIcon(
Utils.getBadgedIcon(mIconDrawableFactory, mPackageManager,
packageOps.getPackageName(),
UserHandle.getUserId(packageOps.getUid())));
checkBoxPreference.setOnPreferenceChangeListener((pref, value) -> {
// change the toggle
final int mode = (Boolean) value ? AppOpsManager.MODE_IGNORED

View File

@@ -34,8 +34,10 @@ import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
import static com.android.settingslib.Utils.updateLocationMode;
import static com.android.settingslib.Utils.updateLocationEnabled;
import static com.android.settingslib.RestrictedLockUtils.checkIfRestrictionEnforced;
/**
* A class that listens to location settings change and modifies location settings
* settings.
@@ -106,6 +108,25 @@ public class LocationEnabler implements LifecycleObserver, OnResume, OnPause {
}
}
void setLocationEnabled(boolean enabled) {
final int currentMode = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
if (isRestricted()) {
// Location toggling disabled by user restriction. Read the current location mode to
// update the location master switch.
if (Log.isLoggable(TAG, Log.INFO)) {
Log.i(TAG, "Restricted user, not setting location mode");
}
if (mListener != null) {
mListener.onLocationModeChanged(currentMode, true);
}
return;
}
updateLocationEnabled(mContext, enabled, UserHandle.myUserId());
refreshLocationMode();
}
void setLocationMode(int mode) {
final int currentMode = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);

View File

@@ -47,15 +47,8 @@ import java.util.List;
* <ul>
* <li>Platform location controls</li>
* <ul>
* <li>In switch bar: location master switch. Used to toggle
* {@link android.provider.Settings.Secure#LOCATION_MODE} between
* {@link android.provider.Settings.Secure#LOCATION_MODE_OFF} and another location mode.
* <li>In switch bar: location master switch. Used to toggle location on and off.
* </li>
* <li>Mode preference: only available if the master switch is on, selects between
* {@link android.provider.Settings.Secure#LOCATION_MODE} of
* {@link android.provider.Settings.Secure#LOCATION_MODE_HIGH_ACCURACY},
* {@link android.provider.Settings.Secure#LOCATION_MODE_BATTERY_SAVING}, or
* {@link android.provider.Settings.Secure#LOCATION_MODE_SENSORS_ONLY}.</li>
* </ul>
* <li>Recent location requests: automatically populated by {@link RecentLocationApps}</li>
* <li>Location services: multi-app settings provided from outside the Android framework. Each

View File

@@ -96,9 +96,6 @@ public class LocationSwitchBarController implements SwitchBar.OnSwitchChangeList
*/
@Override
public void onSwitchChanged(Switch switchView, boolean isChecked) {
mLocationEnabler.setLocationMode(isChecked
? android.provider.Settings.Secure.LOCATION_MODE_PREVIOUS
: android.provider.Settings.Secure.LOCATION_MODE_OFF);
mLocationEnabler.setLocationEnabled(isChecked);
}
}

View File

@@ -176,15 +176,6 @@ public class AppNotificationSettings extends NotificationSettingsBase {
} else {
groupCategory.setTitle(group.getName());
groupCategory.setKey(group.getId());
Bundle groupArgs = new Bundle();
groupArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mUid);
groupArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mPkg);
groupArgs.putString(Settings.EXTRA_CHANNEL_GROUP_ID, group.getId());
Intent channelIntent = Utils.onBuildStartFragmentIntent(getActivity(),
ChannelGroupNotificationSettings.class.getName(),
groupArgs, null, R.string.notification_group_title,
null, false, getMetricsCategory());
groupCategory.setIntent(channelIntent);
populateGroupToggle(groupCategory, group);
}

View File

@@ -17,6 +17,8 @@
package com.android.settings.notification;
import android.app.Activity;
import android.app.Application;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@@ -77,11 +79,18 @@ public class ConfigureNotificationSettings extends DashboardFragment {
@Override
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
return buildPreferenceControllers(context, getLifecycle());
final Activity activity = getActivity();
final Application app;
if (activity != null) {
app = activity.getApplication();
} else {
app = null;
}
return buildPreferenceControllers(context, getLifecycle(), app, this);
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle) {
Lifecycle lifecycle, Application app, Fragment host) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
final BadgingNotificationPreferenceController badgeController =
new BadgingNotificationPreferenceController(context);
@@ -96,6 +105,8 @@ public class ConfigureNotificationSettings extends DashboardFragment {
lifecycle.addObserver(pulseController);
lifecycle.addObserver(lockScreenNotificationController);
}
controllers.add(new RecentNotifyingAppsPreferenceController(
context, new NotificationBackend(), app, host));
controllers.add(new SwipeToNotificationPreferenceController(context, lifecycle,
KEY_SWIPE_DOWN));
controllers.add(badgeController);
@@ -167,7 +178,7 @@ public class ConfigureNotificationSettings extends DashboardFragment {
@Override
public List<AbstractPreferenceController> getPreferenceControllers(
Context context) {
return buildPreferenceControllers(context, null);
return buildPreferenceControllers(context, null, null, null);
}
@Override

View File

@@ -0,0 +1,467 @@
package com.android.settings.notification;
/*
* 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.
*/
import static android.util.Log.wtf;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.NotificationManager;
import android.content.Context;
import android.content.DialogInterface;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.service.notification.Condition;
import android.service.notification.ZenModeConfig;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.ScrollView;
import android.widget.TextView;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import java.util.Arrays;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Objects;
public class EnableZenModeDialog extends InstrumentedDialogFragment {
private static final String TAG = "EnableZenModeDialog";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final int[] MINUTE_BUCKETS = ZenModeConfig.MINUTE_BUCKETS;
private static final int MIN_BUCKET_MINUTES = MINUTE_BUCKETS[0];
private static final int MAX_BUCKET_MINUTES = MINUTE_BUCKETS[MINUTE_BUCKETS.length - 1];
private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60);
@VisibleForTesting
public static final int FOREVER_CONDITION_INDEX = 0;
@VisibleForTesting
public static final int COUNTDOWN_CONDITION_INDEX = 1;
@VisibleForTesting
public static final int COUNTDOWN_ALARM_CONDITION_INDEX = 2;
@VisibleForTesting
protected Activity mActivity;
private static final int SECONDS_MS = 1000;
private static final int MINUTES_MS = 60 * SECONDS_MS;
@VisibleForTesting
protected Uri mForeverId;
private int mBucketIndex = -1;
private AlarmManager mAlarmManager;
private int mUserId;
private boolean mAttached;
@VisibleForTesting
protected Context mContext;
private RadioGroup mZenRadioGroup;
@VisibleForTesting
protected LinearLayout mZenRadioGroupContent;
private int MAX_MANUAL_DND_OPTIONS = 3;
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
NotificationManager noMan = (NotificationManager) getContext().
getSystemService(Context.NOTIFICATION_SERVICE);
mContext = getContext();
mForeverId = Condition.newId(mContext).appendPath("forever").build();
mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
mUserId = mContext.getUserId();
mAttached = false;
final AlertDialog.Builder builder = new AlertDialog.Builder(getContext())
.setTitle(R.string.zen_mode_settings_turn_on_dialog_title)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.zen_mode_enable_dialog_turn_on,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int checkedId = mZenRadioGroup.getCheckedRadioButtonId();
ConditionTag tag = getConditionTagAt(checkedId);
if (isForever(tag.condition)) {
MetricsLogger.action(getContext(),
MetricsProto.MetricsEvent.
NOTIFICATION_ZEN_MODE_TOGGLE_ON_FOREVER);
} else if (isAlarm(tag.condition)) {
MetricsLogger.action(getContext(),
MetricsProto.MetricsEvent.
NOTIFICATION_ZEN_MODE_TOGGLE_ON_ALARM);
} else if (isCountdown(tag.condition)) {
MetricsLogger.action(getContext(),
MetricsProto.MetricsEvent.
NOTIFICATION_ZEN_MODE_TOGGLE_ON_COUNTDOWN);
} else {
wtf(TAG, "Invalid manual condition: " + tag.condition);
}
// always triggers priority-only dnd with chosen condition
noMan.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
getRealConditionId(tag.condition), TAG);
}
});
View contentView = getContentView();
bindConditions(forever());
builder.setView(contentView);
return builder.create();
}
private void hideAllConditions() {
final int N = mZenRadioGroupContent.getChildCount();
for (int i = 0; i < N; i++) {
mZenRadioGroupContent.getChildAt(i).setVisibility(View.GONE);
}
}
protected View getContentView() {
if (mActivity == null) {
mActivity = getActivity();
}
final LayoutInflater inflater = mActivity.getLayoutInflater();
View contentView = inflater.inflate(R.layout.zen_mode_turn_on_dialog_container, null);
ScrollView container = (ScrollView) contentView.findViewById(R.id.container);
mZenRadioGroup = container.findViewById(R.id.zen_radio_buttons);
mZenRadioGroupContent = container.findViewById(R.id.zen_radio_buttons_content);
for (int i = 0; i < MAX_MANUAL_DND_OPTIONS; i++) {
final View radioButton = inflater.inflate(R.layout.zen_mode_radio_button,
mZenRadioGroup, false);
mZenRadioGroup.addView(radioButton);
radioButton.setId(i);
final View radioButtonContent = inflater.inflate(R.layout.zen_mode_condition,
mZenRadioGroupContent, false);
radioButtonContent.setId(i + MAX_MANUAL_DND_OPTIONS);
mZenRadioGroupContent.addView(radioButtonContent);
}
hideAllConditions();
return contentView;
}
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.NOTIFICATION_ZEN_MODE_ENABLE_DIALOG;
}
@VisibleForTesting
protected void bind(final Condition condition, final View row, final int rowId) {
if (condition == null) throw new IllegalArgumentException("condition must not be null");
final boolean enabled = condition.state == Condition.STATE_TRUE;
final ConditionTag tag = row.getTag() != null ? (ConditionTag) row.getTag() :
new ConditionTag();
row.setTag(tag);
final boolean first = tag.rb == null;
if (tag.rb == null) {
tag.rb = (RadioButton) mZenRadioGroup.getChildAt(rowId);
}
tag.condition = condition;
final Uri conditionId = getConditionId(tag.condition);
if (DEBUG) Log.d(TAG, "bind i=" + mZenRadioGroupContent.indexOfChild(row) + " first="
+ first + " condition=" + conditionId);
tag.rb.setEnabled(enabled);
tag.rb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
tag.rb.setChecked(true);
if (DEBUG) Log.d(TAG, "onCheckedChanged " + conditionId);
MetricsLogger.action(mContext,
MetricsProto.MetricsEvent.QS_DND_CONDITION_SELECT);
announceConditionSelection(tag);
}
}
});
updateUi(tag, row, condition, enabled, rowId, conditionId);
row.setVisibility(View.VISIBLE);
}
@VisibleForTesting
protected ConditionTag getConditionTagAt(int index) {
return (ConditionTag) mZenRadioGroupContent.getChildAt(index).getTag();
}
@VisibleForTesting
protected void bindConditions(Condition c) {
// forever
bind(forever(), mZenRadioGroupContent.getChildAt(FOREVER_CONDITION_INDEX),
FOREVER_CONDITION_INDEX);
if (c == null) {
bindGenericCountdown();
bindNextAlarm(getTimeUntilNextAlarmCondition());
} else if (isForever(c)) {
getConditionTagAt(FOREVER_CONDITION_INDEX).rb.setChecked(true);
bindGenericCountdown();
bindNextAlarm(getTimeUntilNextAlarmCondition());
} else {
if (isAlarm(c)) {
bindGenericCountdown();
bindNextAlarm(c);
getConditionTagAt(COUNTDOWN_ALARM_CONDITION_INDEX).rb.setChecked(true);
} else if (isCountdown(c)) {
bindNextAlarm(getTimeUntilNextAlarmCondition());
bind(c, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX),
COUNTDOWN_CONDITION_INDEX);
getConditionTagAt(COUNTDOWN_CONDITION_INDEX).rb.setChecked(true);
} else {
wtf(TAG, "Invalid manual condition: " + c);
}
}
}
public static Uri getConditionId(Condition condition) {
return condition != null ? condition.id : null;
}
public Condition forever() {
Uri foreverId = Condition.newId(mContext).appendPath("forever").build();
return new Condition(foreverId, foreverSummary(mContext), "", "", 0 /*icon*/,
Condition.STATE_TRUE, 0 /*flags*/);
}
public long getNextAlarm() {
final AlarmManager.AlarmClockInfo info = mAlarmManager.getNextAlarmClock(mUserId);
return info != null ? info.getTriggerTime() : 0;
}
@VisibleForTesting
protected boolean isAlarm(Condition c) {
return c != null && ZenModeConfig.isValidCountdownToAlarmConditionId(c.id);
}
@VisibleForTesting
protected boolean isCountdown(Condition c) {
return c != null && ZenModeConfig.isValidCountdownConditionId(c.id);
}
private boolean isForever(Condition c) {
return c != null && mForeverId.equals(c.id);
}
private Uri getRealConditionId(Condition condition) {
return isForever(condition) ? null : getConditionId(condition);
}
private String foreverSummary(Context context) {
return context.getString(com.android.internal.R.string.zen_mode_forever);
}
private static void setToMidnight(Calendar calendar) {
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
}
// Returns a time condition if the next alarm is within the next week.
@VisibleForTesting
protected Condition getTimeUntilNextAlarmCondition() {
GregorianCalendar weekRange = new GregorianCalendar();
setToMidnight(weekRange);
weekRange.add(Calendar.DATE, 6);
final long nextAlarmMs = getNextAlarm();
if (nextAlarmMs > 0) {
GregorianCalendar nextAlarm = new GregorianCalendar();
nextAlarm.setTimeInMillis(nextAlarmMs);
setToMidnight(nextAlarm);
if (weekRange.compareTo(nextAlarm) >= 0) {
return ZenModeConfig.toNextAlarmCondition(mContext, nextAlarmMs,
ActivityManager.getCurrentUser());
}
}
return null;
}
@VisibleForTesting
protected void bindGenericCountdown() {
mBucketIndex = DEFAULT_BUCKET_INDEX;
Condition countdown = ZenModeConfig.toTimeCondition(mContext,
MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
if (!mAttached || getConditionTagAt(COUNTDOWN_CONDITION_INDEX).condition == null) {
bind(countdown, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX),
COUNTDOWN_CONDITION_INDEX);
}
}
private void updateUi(ConditionTag tag, View row, Condition condition,
boolean enabled, int rowId, Uri conditionId) {
if (tag.lines == null) {
tag.lines = row.findViewById(android.R.id.content);
}
if (tag.line1 == null) {
tag.line1 = (TextView) row.findViewById(android.R.id.text1);
}
if (tag.line2 == null) {
tag.line2 = (TextView) row.findViewById(android.R.id.text2);
}
final String line1 = !TextUtils.isEmpty(condition.line1) ? condition.line1
: condition.summary;
final String line2 = condition.line2;
tag.line1.setText(line1);
if (TextUtils.isEmpty(line2)) {
tag.line2.setVisibility(View.GONE);
} else {
tag.line2.setVisibility(View.VISIBLE);
tag.line2.setText(line2);
}
tag.lines.setEnabled(enabled);
tag.lines.setAlpha(enabled ? 1 : .4f);
tag.lines.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tag.rb.setChecked(true);
}
});
// minus button
final ImageView button1 = (ImageView) row.findViewById(android.R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onClickTimeButton(row, tag, false /*down*/, rowId);
}
});
// plus button
final ImageView button2 = (ImageView) row.findViewById(android.R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onClickTimeButton(row, tag, true /*up*/, rowId);
}
});
final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
if (rowId == COUNTDOWN_CONDITION_INDEX && time > 0) {
button1.setVisibility(View.VISIBLE);
button2.setVisibility(View.VISIBLE);
if (mBucketIndex > -1) {
button1.setEnabled(mBucketIndex > 0);
button2.setEnabled(mBucketIndex < MINUTE_BUCKETS.length - 1);
} else {
final long span = time - System.currentTimeMillis();
button1.setEnabled(span > MIN_BUCKET_MINUTES * MINUTES_MS);
final Condition maxCondition = ZenModeConfig.toTimeCondition(mContext,
MAX_BUCKET_MINUTES, ActivityManager.getCurrentUser());
button2.setEnabled(!Objects.equals(condition.summary, maxCondition.summary));
}
button1.setAlpha(button1.isEnabled() ? 1f : .5f);
button2.setAlpha(button2.isEnabled() ? 1f : .5f);
} else {
button1.setVisibility(View.GONE);
button2.setVisibility(View.GONE);
}
}
@VisibleForTesting
protected void bindNextAlarm(Condition c) {
View alarmContent = mZenRadioGroupContent.getChildAt(COUNTDOWN_ALARM_CONDITION_INDEX);
ConditionTag tag = (ConditionTag) alarmContent.getTag();
if (c != null && (!mAttached || tag == null || tag.condition == null)) {
bind(c, alarmContent, COUNTDOWN_ALARM_CONDITION_INDEX);
}
// hide the alarm radio button if there isn't a "next alarm condition"
tag = (ConditionTag) alarmContent.getTag();
boolean showAlarm = tag != null && tag.condition != null;
mZenRadioGroup.getChildAt(COUNTDOWN_ALARM_CONDITION_INDEX).setVisibility(
showAlarm ? View.VISIBLE : View.GONE);
alarmContent.setVisibility(showAlarm ? View.VISIBLE : View.GONE);
}
private void onClickTimeButton(View row, ConditionTag tag, boolean up, int rowId) {
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.QS_DND_TIME, up);
Condition newCondition = null;
final int N = MINUTE_BUCKETS.length;
if (mBucketIndex == -1) {
// not on a known index, search for the next or prev bucket by time
final Uri conditionId = getConditionId(tag.condition);
final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
final long now = System.currentTimeMillis();
for (int i = 0; i < N; i++) {
int j = up ? i : N - 1 - i;
final int bucketMinutes = MINUTE_BUCKETS[j];
final long bucketTime = now + bucketMinutes * MINUTES_MS;
if (up && bucketTime > time || !up && bucketTime < time) {
mBucketIndex = j;
newCondition = ZenModeConfig.toTimeCondition(mContext,
bucketTime, bucketMinutes, ActivityManager.getCurrentUser(),
false /*shortVersion*/);
break;
}
}
if (newCondition == null) {
mBucketIndex = DEFAULT_BUCKET_INDEX;
newCondition = ZenModeConfig.toTimeCondition(mContext,
MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
}
} else {
// on a known index, simply increment or decrement
mBucketIndex = Math.max(0, Math.min(N - 1, mBucketIndex + (up ? 1 : -1)));
newCondition = ZenModeConfig.toTimeCondition(mContext,
MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
}
bind(newCondition, row, rowId);
tag.rb.setChecked(true);
announceConditionSelection(tag);
}
private void announceConditionSelection(ConditionTag tag) {
// condition will always be priority-only
String modeText = mContext.getString(R.string.zen_interruption_level_priority);
if (tag.line1 != null) {
mZenRadioGroupContent.announceForAccessibility(mContext.getString(
R.string.zen_mode_and_condition, modeText, tag.line1.getText()));
}
}
// used as the view tag on condition rows
@VisibleForTesting
protected static class ConditionTag {
public RadioButton rb;
public View lines;
public TextView line1;
public TextView line2;
public Condition condition;
}
}

View File

@@ -27,12 +27,16 @@ import android.content.pm.ParceledListSlice;
import android.graphics.drawable.Drawable;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.service.notification.NotifyingApp;
import android.util.IconDrawableFactory;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.Utils;
import java.util.ArrayList;
import java.util.List;
public class NotificationBackend {
private static final String TAG = "NotificationBackend";
@@ -185,7 +189,6 @@ public class NotificationBackend {
}
}
public int getDeletedChannelCount(String pkg, int uid) {
try {
return sINM.getDeletedChannelCount(pkg, uid);
@@ -204,6 +207,15 @@ public class NotificationBackend {
}
}
public List<NotifyingApp> getRecentApps() {
try {
return sINM.getRecentNotifyingAppsForUser(UserHandle.myUserId()).getList();
} catch (Exception e) {
Log.w(TAG, "Error calling NoMan", e);
return new ArrayList<>();
}
}
static class Row {
public String section;
}

View File

@@ -168,14 +168,7 @@ abstract public class NotificationSettingsBase extends DashboardFragment {
mChannel = (args != null && args.containsKey(Settings.EXTRA_CHANNEL_ID)) ?
mBackend.getChannel(mPkg, mUid, args.getString(Settings.EXTRA_CHANNEL_ID)) : null;
NotificationChannelGroup group =
(args != null && args.containsKey(Settings.EXTRA_CHANNEL_GROUP_ID))
? mBackend.getGroupWithChannels(mPkg, mUid,
args.getString(Settings.EXTRA_CHANNEL_GROUP_ID))
: null;
if (group != null) {
mChannelGroup = new NotificationChannelGroupWrapper(group);
}
NotificationChannelGroup group = null;
mSuspendedAppsAdmin = RestrictedLockUtils.checkIfApplicationIsSuspended(
mContext, mPkg, mUserId);

View File

@@ -0,0 +1,293 @@
/*
* 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.Application;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.service.notification.NotifyingApp;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IconDrawableFactory;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.applications.InstalledAppCounter;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.widget.AppPreference;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.wrapper.PackageManagerWrapper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* This controller displays a list of recently used apps and a "See all" button. If there is
* no recently used app, "See all" will be displayed as "Notifications".
*/
public class RecentNotifyingAppsPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin {
private static final String TAG = "RecentNotisCtrl";
private static final String KEY_PREF_CATEGORY = "recent_notifications_category";
@VisibleForTesting
static final String KEY_DIVIDER = "all_notifications_divider";
@VisibleForTesting
static final String KEY_SEE_ALL = "all_notifications";
private static final int SHOW_RECENT_APP_COUNT = 5;
private static final Set<String> SKIP_SYSTEM_PACKAGES = new ArraySet<>();
private final Fragment mHost;
private final PackageManager mPm;
private final NotificationBackend mNotificationBackend;
private final int mUserId;
private final IconDrawableFactory mIconDrawableFactory;
private List<NotifyingApp> mApps;
private final ApplicationsState mApplicationsState;
private PreferenceCategory mCategory;
private Preference mSeeAllPref;
private Preference mDivider;
private boolean mHasRecentApps;
static {
SKIP_SYSTEM_PACKAGES.addAll(Arrays.asList(
"android",
"com.android.phone",
"com.android.settings",
"com.android.systemui",
"com.android.providers.calendar",
"com.android.providers.media"
));
}
public RecentNotifyingAppsPreferenceController(Context context, NotificationBackend backend,
Application app, Fragment host) {
this(context, backend, app == null ? null : ApplicationsState.getInstance(app), host);
}
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
RecentNotifyingAppsPreferenceController(Context context, NotificationBackend backend,
ApplicationsState appState, Fragment host) {
super(context);
mIconDrawableFactory = IconDrawableFactory.newInstance(context);
mUserId = UserHandle.myUserId();
mPm = context.getPackageManager();
mHost = host;
mApplicationsState = appState;
mNotificationBackend = backend;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public String getPreferenceKey() {
return KEY_PREF_CATEGORY;
}
@Override
public void updateNonIndexableKeys(List<String> keys) {
PreferenceControllerMixin.super.updateNonIndexableKeys(keys);
// Don't index category name into search. It's not actionable.
keys.add(KEY_PREF_CATEGORY);
keys.add(KEY_DIVIDER);
}
@Override
public void displayPreference(PreferenceScreen screen) {
mCategory = (PreferenceCategory) screen.findPreference(getPreferenceKey());
mSeeAllPref = screen.findPreference(KEY_SEE_ALL);
mDivider = screen.findPreference(KEY_DIVIDER);
super.displayPreference(screen);
refreshUi(mCategory.getContext());
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
refreshUi(mCategory.getContext());
// Show total number of installed apps as See all's summary.
new InstalledAppCounter(mContext, InstalledAppCounter.IGNORE_INSTALL_REASON,
new PackageManagerWrapper(mContext.getPackageManager())) {
@Override
protected void onCountComplete(int num) {
if (mHasRecentApps) {
mSeeAllPref.setTitle(mContext.getString(R.string.see_all_apps_title, num));
} else {
mSeeAllPref.setSummary(mContext.getString(R.string.apps_summary, num));
}
}
}.execute();
}
@VisibleForTesting
void refreshUi(Context prefContext) {
reloadData();
final List<NotifyingApp> recentApps = getDisplayableRecentAppList();
if (recentApps != null && !recentApps.isEmpty()) {
mHasRecentApps = true;
displayRecentApps(prefContext, recentApps);
} else {
mHasRecentApps = false;
displayOnlyAllAppsLink();
}
}
@VisibleForTesting
void reloadData() {
mApps = mNotificationBackend.getRecentApps();
}
private void displayOnlyAllAppsLink() {
mCategory.setTitle(null);
mDivider.setVisible(false);
mSeeAllPref.setTitle(R.string.notifications_title);
mSeeAllPref.setIcon(null);
int prefCount = mCategory.getPreferenceCount();
for (int i = prefCount - 1; i >= 0; i--) {
final Preference pref = mCategory.getPreference(i);
if (!TextUtils.equals(pref.getKey(), KEY_SEE_ALL)) {
mCategory.removePreference(pref);
}
}
}
private void displayRecentApps(Context prefContext, List<NotifyingApp> recentApps) {
mCategory.setTitle(R.string.recent_notifications);
mDivider.setVisible(true);
mSeeAllPref.setSummary(null);
mSeeAllPref.setIcon(R.drawable.ic_chevron_right_24dp);
// Rebind prefs/avoid adding new prefs if possible. Adding/removing prefs causes jank.
// Build a cached preference pool
final Map<String, Preference> appPreferences = new ArrayMap<>();
int prefCount = mCategory.getPreferenceCount();
for (int i = 0; i < prefCount; i++) {
final Preference pref = mCategory.getPreference(i);
final String key = pref.getKey();
if (!TextUtils.equals(key, KEY_SEE_ALL)) {
appPreferences.put(key, pref);
}
}
final int recentAppsCount = recentApps.size();
for (int i = 0; i < recentAppsCount; i++) {
final NotifyingApp app = recentApps.get(i);
// Bind recent apps to existing prefs if possible, or create a new pref.
final String pkgName = app.getPackage();
final ApplicationsState.AppEntry appEntry =
mApplicationsState.getEntry(app.getPackage(), mUserId);
if (appEntry == null) {
continue;
}
boolean rebindPref = true;
Preference pref = appPreferences.remove(pkgName);
if (pref == null) {
pref = new AppPreference(prefContext);
rebindPref = false;
}
pref.setKey(pkgName);
pref.setTitle(appEntry.label);
pref.setIcon(mIconDrawableFactory.getBadgedIcon(appEntry.info));
pref.setSummary(Utils.formatRelativeTime(mContext,
System.currentTimeMillis() - app.getLastNotified(), false));
pref.setOrder(i);
pref.setOnPreferenceClickListener(preference -> {
AppInfoBase.startAppInfoFragment(AppNotificationSettings.class,
R.string.notifications_title, pkgName, appEntry.info.uid, mHost,
1001 /*RequestCode */,
MetricsProto.MetricsEvent.MANAGE_APPLICATIONS_NOTIFICATIONS);
return true;
});
if (!rebindPref) {
mCategory.addPreference(pref);
}
}
// Remove unused prefs from pref cache pool
for (Preference unusedPrefs : appPreferences.values()) {
mCategory.removePreference(unusedPrefs);
}
}
private List<NotifyingApp> getDisplayableRecentAppList() {
Collections.sort(mApps);
List<NotifyingApp> displayableApps = new ArrayList<>(SHOW_RECENT_APP_COUNT);
int count = 0;
for (NotifyingApp app : mApps) {
final ApplicationsState.AppEntry appEntry = mApplicationsState.getEntry(
app.getPackage(), mUserId);
if (appEntry == null) {
continue;
}
if (!shouldIncludePkgInRecents(app.getPackage())) {
continue;
}
displayableApps.add(app);
count++;
if (count >= SHOW_RECENT_APP_COUNT) {
break;
}
}
return displayableApps;
}
/**
* Whether or not the app should be included in recent list.
*/
private boolean shouldIncludePkgInRecents(String pkgName) {
if (SKIP_SYSTEM_PACKAGES.contains(pkgName)) {
Log.d(TAG, "System package, skipping " + pkgName);
return false;
}
final Intent launchIntent = new Intent().addCategory(Intent.CATEGORY_LAUNCHER)
.setPackage(pkgName);
if (mPm.resolveActivity(launchIntent, 0) == null) {
// Not visible on launcher -> likely not a user visible app, skip if non-instant.
final ApplicationsState.AppEntry appEntry =
mApplicationsState.getEntry(pkgName, mUserId);
if (!AppUtils.isInstant(appEntry.info)) {
Log.d(TAG, "Not a user visible or instant app, skipping " + pkgName);
return false;
}
}
return true;
}
}

View File

@@ -16,6 +16,7 @@
package com.android.settings.notification;
import android.app.FragmentManager;
import android.content.Context;
import android.provider.Settings;
import android.support.v7.preference.Preference;
@@ -31,12 +32,16 @@ import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeButtonPreferenceController extends AbstractZenModePreferenceController
implements PreferenceControllerMixin {
private static final String TAG = "EnableZenModeButton";
protected static final String KEY = "zen_mode_settings_button_container";
private Button mZenButtonOn;
private Button mZenButtonOff;
private FragmentManager mFragment;
public ZenModeButtonPreferenceController(Context context, Lifecycle lifecycle) {
public ZenModeButtonPreferenceController(Context context, Lifecycle lifecycle, FragmentManager
fragment) {
super(context, KEY, lifecycle);
mFragment = fragment;
}
@Override
@@ -56,11 +61,8 @@ public class ZenModeButtonPreferenceController extends AbstractZenModePreference
if (null == mZenButtonOn) {
mZenButtonOn = (Button) ((LayoutPreference) preference)
.findViewById(R.id.zen_mode_settings_turn_on_button);
mZenButtonOn.setOnClickListener(v -> {
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_TOGGLE_DND_BUTTON, true);
mBackend.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
});
mZenButtonOn.setOnClickListener(v ->
new EnableZenModeDialog().show(mFragment, TAG));
}
if (null == mZenButtonOff) {

View File

@@ -17,6 +17,7 @@
package com.android.settings.notification;
import android.app.AutomaticZenRule;
import android.app.FragmentManager;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.content.Context;
@@ -50,7 +51,7 @@ public class ZenModeSettings extends ZenModeSettingsBase {
@Override
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
return buildPreferenceControllers(context, getLifecycle());
return buildPreferenceControllers(context, getLifecycle(), getFragmentManager());
}
@Override
@@ -59,11 +60,11 @@ public class ZenModeSettings extends ZenModeSettingsBase {
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle) {
Lifecycle lifecycle, FragmentManager fragmentManager) {
List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new ZenModeBehaviorPreferenceController(context, lifecycle));
controllers.add(new ZenModeAutomationPreferenceController(context));
controllers.add(new ZenModeButtonPreferenceController(context, lifecycle));
controllers.add(new ZenModeButtonPreferenceController(context, lifecycle, fragmentManager));
controllers.add(new ZenModeSettingsFooterPreferenceController(context, lifecycle));
return controllers;
}
@@ -211,7 +212,7 @@ public class ZenModeSettings extends ZenModeSettingsBase {
@Override
public List<AbstractPreferenceController> getPreferenceControllers(Context
context) {
return buildPreferenceControllers(context, null);
return buildPreferenceControllers(context, null, null);
}
};
}

View File

@@ -21,6 +21,7 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.settings.R;
import com.android.settings.accounts.AccountFeatureProvider;
import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.bluetooth.BluetoothFeatureProvider;
import com.android.settings.connecteddevice.SmsMirroringFeatureProvider;
@@ -109,6 +110,8 @@ public abstract class FeatureFactory {
public abstract SlicesFeatureProvider getSlicesFeatureProvider();
public abstract AccountFeatureProvider getAccountFeatureProvider();
public static final class FactoryNotFoundException extends RuntimeException {
public FactoryNotFoundException(Throwable throwable) {
super("Unable to create factory. Did you misconfigure Proguard?", throwable);

View File

@@ -23,6 +23,8 @@ import android.net.ConnectivityManager;
import android.os.UserManager;
import android.support.annotation.Keep;
import com.android.settings.accounts.AccountFeatureProvider;
import com.android.settings.accounts.AccountFeatureProviderImpl;
import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.applications.ApplicationFeatureProviderImpl;
import com.android.settings.bluetooth.BluetoothFeatureProvider;
@@ -78,6 +80,7 @@ public class FeatureFactoryImpl extends FeatureFactory {
private DataPlanFeatureProvider mDataPlanFeatureProvider;
private SmsMirroringFeatureProvider mSmsMirroringFeatureProvider;
private SlicesFeatureProvider mSlicesFeatureProvider;
private AccountFeatureProvider mAccountFeatureProvider;
@Override
public SupportFeatureProvider getSupportFeatureProvider(Context context) {
@@ -219,4 +222,12 @@ public class FeatureFactoryImpl extends FeatureFactory {
}
return mSlicesFeatureProvider;
}
@Override
public AccountFeatureProvider getAccountFeatureProvider() {
if (mAccountFeatureProvider == null) {
mAccountFeatureProvider = new AccountFeatureProviderImpl();
}
return mAccountFeatureProvider;
}
}

View File

@@ -21,6 +21,7 @@ import android.support.annotation.VisibleForTesting;
import com.android.settings.DateTimeSettings;
import com.android.settings.DisplaySettings;
import com.android.settings.LegalSettings;
import com.android.settings.deviceinfo.aboutphone.MyDeviceInfoFragment;
import com.android.settings.accessibility.AccessibilitySettings;
import com.android.settings.accessibility.AccessibilityShortcutPreferenceFragment;
import com.android.settings.accessibility.MagnificationPreferenceFragment;
@@ -173,6 +174,7 @@ public class SearchIndexableResourcesImpl implements SearchIndexableResources {
addIndex(ZenModeAutomationSettings.class);
addIndex(NightDisplaySettings.class);
addIndex(SmartBatterySettings.class);
addIndex(MyDeviceInfoFragment.class);
}
@Override

View File

@@ -0,0 +1,61 @@
/*
* 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.security;
import android.content.Context;
import android.os.UserHandle;
import android.provider.Settings;
import android.support.v7.preference.Preference;
import android.support.v7.preference.TwoStatePreference;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.TogglePreferenceController;
public class LockdownButtonPreferenceController extends TogglePreferenceController {
private static final String KEY_LOCKDOWN_ENALBED = "security_setting_lockdown_enabled";
private final LockPatternUtils mLockPatternUtils;
public LockdownButtonPreferenceController(Context context) {
super(context, KEY_LOCKDOWN_ENALBED);
mLockPatternUtils = new LockPatternUtils(context);
}
@Override
public int getAvailabilityStatus() {
if (mLockPatternUtils.isSecure(UserHandle.myUserId())) {
return BasePreferenceController.AVAILABLE;
} else {
return BasePreferenceController.DISABLED_FOR_USER;
}
}
@Override
public boolean isChecked() {
return Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0) != 0;
}
@Override
public boolean setChecked(boolean isChecked) {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.LOCKDOWN_IN_POWER_MENU, isChecked ? 1 : 0);
return true;
}
}

View File

@@ -93,6 +93,8 @@ public class LockscreenDashboardFragment extends DashboardFragment
mOwnerInfoPreferenceController =
new OwnerInfoPreferenceController(context, this, lifecycle);
controllers.add(mOwnerInfoPreferenceController);
controllers.add(new LockdownButtonPreferenceController(context));
return controllers;
}
@@ -122,6 +124,7 @@ public class LockscreenDashboardFragment extends DashboardFragment
KEY_ADD_USER_FROM_LOCK_SCREEN));
controllers.add(new OwnerInfoPreferenceController(
context, null /* fragment */, null /* lifecycle */));
controllers.add(new LockdownButtonPreferenceController(context));
return controllers;
}

View File

@@ -0,0 +1,38 @@
/*
* 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.widget;
import android.content.Context;
import android.support.v7.preference.CheckBoxPreference;
import android.util.AttributeSet;
import com.android.settings.R;
/**
* {@link CheckBoxPreference} that used only to display app
*/
public class AppCheckBoxPreference extends CheckBoxPreference {
public AppCheckBoxPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setLayoutResource(R.layout.preference_app);
}
public AppCheckBoxPreference(Context context) {
super(context);
setLayoutResource(R.layout.preference_app);
}
}

View File

@@ -16,6 +16,7 @@
package com.android.settings.widget;
import android.app.ActivityManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
@@ -33,10 +34,12 @@ import android.os.AsyncTask;
import android.os.Handler;
import android.os.IPowerManager;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserManager;
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.util.Log;
import android.widget.RemoteViews;
@@ -561,27 +564,14 @@ public class SettingsAppWidgetProvider extends AppWidgetProvider {
final UserManager um =
(UserManager) context.getSystemService(Context.USER_SERVICE);
if (!um.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION)) {
int currentMode = Settings.Secure.getInt(resolver,
Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
int mode = Settings.Secure.LOCATION_MODE_HIGH_ACCURACY;
switch (currentMode) {
case Settings.Secure.LOCATION_MODE_HIGH_ACCURACY:
mode = Settings.Secure.LOCATION_MODE_BATTERY_SAVING;
break;
case Settings.Secure.LOCATION_MODE_BATTERY_SAVING:
mode = Settings.Secure.LOCATION_MODE_HIGH_ACCURACY;
break;
case Settings.Secure.LOCATION_MODE_SENSORS_ONLY:
mode = Settings.Secure.LOCATION_MODE_OFF;
break;
case Settings.Secure.LOCATION_MODE_OFF:
mode = Settings.Secure.LOCATION_MODE_PREVIOUS;
break;
}
Settings.Secure.putInt(resolver, Settings.Secure.LOCATION_MODE, mode);
return mode != Settings.Secure.LOCATION_MODE_OFF;
LocationManager lm =
(LocationManager) context.getSystemService(
Context.LOCATION_SERVICE);
boolean currentLocationEnabled = lm.isLocationEnabled();
lm.setLocationEnabledForUser(
!currentLocationEnabled, Process.myUserHandle());
return lm.isLocationEnabled();
}
return getActualState(context) == STATE_ENABLED;
}

View File

@@ -18,6 +18,7 @@ package com.android.settings.wifi.tether;
import static android.net.wifi.WifiConfiguration.AP_BAND_2GHZ;
import static android.net.wifi.WifiConfiguration.AP_BAND_5GHZ;
import static android.net.wifi.WifiConfiguration.AP_BAND_ANY;
import android.content.Context;
import android.net.wifi.WifiConfiguration;
@@ -32,7 +33,8 @@ public class WifiTetherApBandPreferenceController extends WifiTetherBasePreferen
private static final String TAG = "WifiTetherApBandPref";
private static final String PREF_KEY = "wifi_tether_network_ap_band";
private static final String[] BAND_VALUES =
{String.valueOf(AP_BAND_2GHZ), String.valueOf(AP_BAND_5GHZ)};
{String.valueOf(AP_BAND_ANY), String.valueOf(AP_BAND_2GHZ),
String.valueOf(AP_BAND_5GHZ)};
private final String[] mBandEntries;
private int mBandIndex;
@@ -65,7 +67,7 @@ public class WifiTetherApBandPreferenceController extends WifiTetherBasePreferen
} else {
preference.setEntries(mBandEntries);
preference.setEntryValues(BAND_VALUES);
preference.setSummary(mBandEntries[mBandIndex]);
preference.setSummary(mBandEntries[mBandIndex + 1]);
preference.setValue(String.valueOf(mBandIndex));
}
}
@@ -78,7 +80,8 @@ public class WifiTetherApBandPreferenceController extends WifiTetherBasePreferen
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
mBandIndex = Integer.parseInt((String) newValue);
preference.setSummary(mBandEntries[mBandIndex]);
Log.d(TAG, "Band preference changed, updating band index to " + mBandIndex);
preference.setSummary(mBandEntries[mBandIndex + 1]);
mListener.onTetherConfigUpdated();
return true;
}

View File

@@ -54,4 +54,5 @@
<bool name="config_show_vibrate_input_devices">false</bool>
<bool name="config_show_color_correction_preference">false</bool>
<bool name="config_show_color_inversion_preference">false</bool>
<bool name="config_wifi_support_connected_mac_randomization">false</bool>
</resources>

View File

@@ -21,4 +21,5 @@
<bool name="config_show_camera_laser_sensor">true</bool>
<bool name="config_show_connectivity_monitor">true</bool>
<bool name="config_display_recent_apps">true</bool>
<bool name="config_wifi_support_connected_mac_randomization">true</bool>
</resources>

View File

@@ -16,10 +16,15 @@ package android.content.om;
import android.os.IBinder;
import java.util.ArrayList;
import java.util.LinkedList;
public interface IOverlayManager {
public OverlayInfo getOverlayInfo(String packageName, int userId);
public java.util.List getOverlayInfosForTarget(java.lang.String targetPackageName, int userId);
public boolean setEnabled(java.lang.String packageName, boolean enable, int userId);
public static class Stub {

View File

@@ -14,8 +14,17 @@
package android.content.om;
import android.annotation.NonNull;
public class OverlayInfo {
public final String packageName;
public OverlayInfo(@NonNull String packageName, @NonNull String targetPackageName,
@NonNull String baseCodePath, int state, int userId) {
this.packageName = packageName;
}
public boolean isEnabled() {
return false;
}

View File

@@ -0,0 +1,112 @@
/*
* 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 android.service.notification;
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Objects;
/**
* Stub implementation of framework's NotifyingApp for Robolectric tests. Otherwise Robolectric
* throws ClassNotFoundError.
*
* TODO: Remove this class when Robolectric supports P
*/
public final class NotifyingApp implements Comparable<NotifyingApp> {
private int mUid;
private String mPkg;
private long mLastNotified;
public NotifyingApp() {}
public int getUid() {
return mUid;
}
/**
* Sets the uid of the package that sent the notification. Returns self.
*/
public NotifyingApp setUid(int mUid) {
this.mUid = mUid;
return this;
}
public String getPackage() {
return mPkg;
}
/**
* Sets the package that sent the notification. Returns self.
*/
public NotifyingApp setPackage(@NonNull String mPkg) {
this.mPkg = mPkg;
return this;
}
public long getLastNotified() {
return mLastNotified;
}
/**
* Sets the time the notification was originally sent. Returns self.
*/
public NotifyingApp setLastNotified(long mLastNotified) {
this.mLastNotified = mLastNotified;
return this;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
NotifyingApp that = (NotifyingApp) o;
return getUid() == that.getUid()
&& getLastNotified() == that.getLastNotified()
&& Objects.equals(mPkg, that.mPkg);
}
@Override
public int hashCode() {
return Objects.hash(getUid(), mPkg, getLastNotified());
}
/**
* Sorts notifying apps from newest last notified date to oldest.
*/
@Override
public int compareTo(NotifyingApp o) {
if (getLastNotified() == o.getLastNotified()) {
if (getUid() == o.getUid()) {
return getPackage().compareTo(o.getPackage());
}
return Integer.compare(getUid(), o.getUid());
}
return -Long.compare(getLastNotified(), o.getLastNotified());
}
@Override
public String toString() {
return "NotifyingApp{"
+ "mUid=" + mUid
+ ", mPkg='" + mPkg + '\''
+ ", mLastNotified=" + mLastNotified
+ '}';
}
}

View File

@@ -16,6 +16,9 @@
package com.android.settings.development;
import static com.android.settings.development.EmulateDisplayCutoutPreferenceController
.EMULATION_OVERLAY_PREFIX;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -29,7 +32,8 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.om.IOverlayManager;
import android.content.om.OverlayInfo;
import android.support.v7.preference.TwoStatePreference;
import android.content.pm.PackageManager;
import android.support.v7.preference.ListPreference;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -41,78 +45,95 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
import java.util.Arrays;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class EmulateDisplayCutoutPreferenceControllerTest {
static final OverlayInfo ONE_DISABLED =
new FakeOverlay(EMULATION_OVERLAY_PREFIX + ".one", false);
static final OverlayInfo ONE_ENABLED =
new FakeOverlay(EMULATION_OVERLAY_PREFIX + ".one", true);
static final OverlayInfo TWO_DISABLED =
new FakeOverlay(EMULATION_OVERLAY_PREFIX + ".two", false);
static final OverlayInfo TWO_ENABLED =
new FakeOverlay(EMULATION_OVERLAY_PREFIX + ".two", true);
@Mock Context mContext;
@Mock IOverlayManager mOverlayManager;
@Mock TwoStatePreference mPreference;
@Mock PackageManager mPackageManager;
@Mock ListPreference mPreference;
EmulateDisplayCutoutPreferenceController mController;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(mOverlayManager.getOverlayInfo(any(), anyInt())).thenReturn(DISABLED);
mController = new EmulateDisplayCutoutPreferenceController(mContext, mOverlayManager);
mockCurrentOverlays();
when(mPackageManager.getApplicationInfo(any(), anyInt())).thenThrow(
PackageManager.NameNotFoundException.class);
mController = createController();
mController.setPreference(mPreference);
}
Object mockCurrentOverlays(OverlayInfo... overlays) {
return when(mOverlayManager.getOverlayInfosForTarget(eq("android"), anyInt()))
.thenReturn(Arrays.<OverlayInfo>asList(overlays));
}
@Test
public void isAvailable_true() throws Exception {
when(mOverlayManager.getOverlayInfo(any(), anyInt())).thenReturn(DISABLED);
mockCurrentOverlays(ONE_DISABLED, TWO_DISABLED);
assertThat(new EmulateDisplayCutoutPreferenceController(mContext, mOverlayManager)
.isAvailable()).isTrue();
assertThat(createController().isAvailable()).isTrue();
}
@Test
public void isAvailable_false() throws Exception {
when(mOverlayManager.getOverlayInfo(any(), anyInt())).thenReturn(null);
mockCurrentOverlays();
assertThat(new EmulateDisplayCutoutPreferenceController(mContext, mOverlayManager)
.isAvailable()).isFalse();
assertThat(createController().isAvailable()).isFalse();
}
@Test
public void onPreferenceChange_enable() throws Exception {
when(mOverlayManager.getOverlayInfo(any(), anyInt())).thenReturn(DISABLED);
mockCurrentOverlays(ONE_DISABLED, TWO_DISABLED);
mController.onPreferenceChange(null, true);
mController.onPreferenceChange(null, TWO_DISABLED.packageName);
verify(mOverlayManager).setEnabled(any(), eq(true), anyInt());
verify(mOverlayManager).setEnabled(eq(TWO_DISABLED.packageName), eq(true), anyInt());
}
@Test
public void onPreferenceChange_disable() throws Exception {
when(mOverlayManager.getOverlayInfo(any(), anyInt())).thenReturn(ENABLED);
mockCurrentOverlays(ONE_DISABLED, TWO_ENABLED);
mController.onPreferenceChange(null, false);
mController.onPreferenceChange(null, "");
verify(mOverlayManager).setEnabled(any(), eq(false), anyInt());
verify(mOverlayManager).setEnabled(eq(TWO_ENABLED.packageName), eq(false), anyInt());
}
@Test
public void updateState_enabled() throws Exception {
when(mOverlayManager.getOverlayInfo(any(), anyInt())).thenReturn(ENABLED);
mockCurrentOverlays(ONE_DISABLED, TWO_ENABLED);
mController.updateState(null);
verify(mPreference).setChecked(true);
verify(mPreference).setValueIndex(2);
}
@Test
public void updateState_disabled() throws Exception {
when(mOverlayManager.getOverlayInfo(any(), anyInt())).thenReturn(DISABLED);
mockCurrentOverlays(ONE_DISABLED, TWO_DISABLED);
mController.updateState(null);
verify(mPreference).setChecked(false);
verify(mPreference).setValueIndex(0);
}
@Test
public void onDeveloperOptionsSwitchEnabled() throws Exception {
when(mOverlayManager.getOverlayInfo(any(), anyInt())).thenReturn(DISABLED);
mockCurrentOverlays();
mController.onDeveloperOptionsSwitchEnabled();
@@ -122,27 +143,30 @@ public class EmulateDisplayCutoutPreferenceControllerTest {
@Test
public void onDeveloperOptionsSwitchDisabled() throws Exception {
when(mOverlayManager.getOverlayInfo(any(), anyInt())).thenReturn(ENABLED);
mockCurrentOverlays(ONE_ENABLED, TWO_DISABLED);
mController.onDeveloperOptionsSwitchDisabled();
verify(mPreference).setEnabled(false);
verify(mPreference).setChecked(false);
verify(mOverlayManager).setEnabled(any(), eq(false), anyInt());
verify(mOverlayManager).setEnabled(eq(ONE_ENABLED.packageName), eq(false), anyInt());
}
static final OverlayInfo ENABLED = new OverlayInfo() {
private EmulateDisplayCutoutPreferenceController createController() {
return new EmulateDisplayCutoutPreferenceController(mContext, mPackageManager,
mOverlayManager);
}
private static class FakeOverlay extends OverlayInfo {
private final boolean mEnabled;
public FakeOverlay(String pkg, boolean enabled) {
super(pkg, "android", "/", 0, 0);
mEnabled = enabled;
}
@Override
public boolean isEnabled() {
return true;
return mEnabled;
}
};
static final OverlayInfo DISABLED = new OverlayInfo() {
@Override
public boolean isEnabled() {
return false;
}
};
}
}

View File

@@ -0,0 +1,133 @@
/*
* 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.development;
import static com.android.settings.development.WifiConnectedMacRandomizationPreferenceController
.SETTING_VALUE_OFF;
import static com.android.settings.development.WifiConnectedMacRandomizationPreferenceController
.SETTING_VALUE_ON;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.provider.Settings;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
import org.robolectric.RuntimeEnvironment;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class WifiConnectedMacRandomizationPreferenceControllerTest {
@Mock
private PreferenceScreen mPreferenceScreen;
private Context mContext;
private SwitchPreference mPreference;
private WifiConnectedMacRandomizationPreferenceController mController;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mController = new WifiConnectedMacRandomizationPreferenceController(mContext);
mPreference = new SwitchPreference(mContext);
when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(
mPreference);
mController.displayPreference(mPreferenceScreen);
}
@Test
public void isAvailable_trueSupportFlag_shouldReturnTrue() {
assertThat(mController.isAvailable()).isTrue();
}
@Test
@Config(qualifiers = "mcc999")
public void isAvailable_falseSupportFlag_shouldReturnFalse() {
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void onPreferenceChange_settingEnabled_shouldEnableConnectedMacRandomization() {
mController.onPreferenceChange(mPreference, true /* new value */);
final int mode = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, -1 /* default */);
assertThat(mode).isEqualTo(SETTING_VALUE_ON);
}
@Test
public void onPreferenceChange_settingDisabled_shouldDisableConnectedMacRandomization() {
mController.onPreferenceChange(mPreference, false /* new value */);
final int mode = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, -1 /* default */);
assertThat(mode).isEqualTo(SETTING_VALUE_OFF);
}
@Test
public void updateState_settingEnabled_shouldEnablePreference() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, SETTING_VALUE_ON);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isTrue();
}
@Test
public void updateState_settingDisabled_shouldDisablePreference() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, SETTING_VALUE_OFF);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isFalse();
}
@Test
public void onDeveloperOptionsSwitchEnabled_shouldEnablePreference() {
mController.onDeveloperOptionsSwitchEnabled();
assertThat(mPreference.isEnabled()).isTrue();
}
@Test
public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() {
mController.onDeveloperOptionsSwitchDisabled();
final int mode = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, -1 /* default */);
assertThat(mode).isEqualTo(SETTING_VALUE_OFF);
assertThat(mPreference.isChecked()).isFalse();
assertThat(mPreference.isEnabled()).isFalse();
}
}

View File

@@ -0,0 +1,67 @@
/*
* 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.deviceinfo;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import android.accounts.Account;
import android.content.Context;
import com.android.settings.TestConfig;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
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.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class BrandedAccountPreferenceControllerTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
private BrandedAccountPreferenceController mController;
private FakeFeatureFactory fakeFeatureFactory;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
fakeFeatureFactory = FakeFeatureFactory.setupForTest();
mController = new BrandedAccountPreferenceController(mContext);
}
@Test
public void isAvailable_defaultOff() {
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_onWhenAccountIsAvailable() {
when(fakeFeatureFactory.mAccountFeatureProvider.getAccounts(any(Context.class))).thenReturn(
new Account[]
{new Account("fake@account.foo", "fake.reallyfake")});
mController = new BrandedAccountPreferenceController(mContext);
assertThat(mController.isAvailable()).isTrue();
}
}

View File

@@ -0,0 +1,100 @@
/*
* 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.deviceinfo;
import static com.android.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.preference.PreferenceScreen;
import android.telephony.TelephonyManager;
import com.android.settings.deviceinfo.aboutphone.MyDeviceInfoFragment;
import com.android.settings.TestConfig;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settings.testutils.shadow.SettingsShadowSystemProperties;
import com.android.settings.testutils.shadow.ShadowConnectivityManager;
import com.android.settings.testutils.shadow.ShadowUserManager;
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;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(
manifest = TestConfig.MANIFEST_PATH,
sdk = TestConfig.SDK_VERSION,
shadows = {ShadowConnectivityManager.class, ShadowUserManager.class}
)
public class MyDeviceInfoFragmentTest {
@Mock
private Activity mActivity;
@Mock
private PreferenceScreen mScreen;
@Mock
private TelephonyManager mTelephonyManager;
private Context mContext;
private MyDeviceInfoFragment mSettings;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
FakeFeatureFactory.setupForTest();
mContext = RuntimeEnvironment.application;
mSettings = spy(new MyDeviceInfoFragment());
when(mSettings.getActivity()).thenReturn(mActivity);
when(mSettings.getContext()).thenReturn(mContext);
when(mActivity.getTheme()).thenReturn(mContext.getTheme());
when(mActivity.getResources()).thenReturn(mContext.getResources());
doNothing().when(mSettings).onCreatePreferences(any(), any());
doReturn(mScreen).when(mSettings).getPreferenceScreen();
when(mSettings.getPreferenceScreen()).thenReturn(mScreen);
ShadowApplication.getInstance().setSystemService(Context.TELEPHONY_SERVICE,
mTelephonyManager);
}
@Test
@Config(shadows = {SettingsShadowResources.SettingsShadowTheme.class,
SettingsShadowSystemProperties.class})
public void onCreate_fromSearch_shouldNotOverrideInitialExpandedCount() {
final Bundle args = new Bundle();
args.putString(EXTRA_FRAGMENT_ARG_KEY, "search_key");
mSettings.setArguments(args);
mSettings.onCreate(null /* icicle */);
verify(mScreen).setInitialExpandedChildrenCount(Integer.MAX_VALUE);
}
}

View File

@@ -28,6 +28,7 @@ import android.content.pm.PackageManager;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceManager;
import android.util.IconDrawableFactory;
import com.android.settings.TestConfig;
@@ -53,6 +54,8 @@ public class RestrictedAppDetailsTest {
private PackageManager mPackageManager;
@Mock
private ApplicationInfo mApplicationInfo;
@Mock
private IconDrawableFactory mIconDrawableFactory;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PreferenceManager mPreferenceManager;
private RestrictedAppDetails mFragment;
@@ -68,6 +71,7 @@ public class RestrictedAppDetailsTest {
doReturn(mPreferenceManager).when(mFragment).getPreferenceManager();
doReturn(mContext).when(mPreferenceManager).getContext();
mFragment.mPackageManager = mPackageManager;
mFragment.mIconDrawableFactory = mIconDrawableFactory;
mFragment.mPackageOpsList = new ArrayList<>();
mFragment.mPackageOpsList.add(
new AppOpsManager.PackageOps(PACKAGE_NAME, UID, null /* entries */));

View File

@@ -43,6 +43,7 @@ import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowSecureSettings;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.wrapper.LocationManagerWrapper;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
@@ -53,11 +54,15 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH,
sdk = TestConfig.SDK_VERSION,
shadows = {ShadowSecureSettings.class})
shadows = {
ShadowSecureSettings.class,
LocationEnablerTest.ShadowLocationManagerWrapper.class})
public class LocationEnablerTest {
@Mock
@@ -124,7 +129,7 @@ public class LocationEnablerTest {
}
@Test
public void isEnabled_locationONotRestricted_shouldReturnTrue() {
public void isEnabled_locationNotRestricted_shouldReturnTrue() {
when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
assertThat(mEnabler.isEnabled(Settings.Secure.LOCATION_MODE_BATTERY_SAVING)).isTrue();
@@ -178,14 +183,35 @@ public class LocationEnablerTest {
when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_BATTERY_SAVING);
mEnabler.setLocationMode(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
verify(mContext).sendBroadcastAsUser(
argThat(actionMatches(LocationManager.MODE_CHANGING_ACTION)),
eq(UserHandle.of(ActivityManager.getCurrentUser())),
eq(WRITE_SECURE_SETTINGS));
}
@Test
public void setLocationEnabled_notRestricted_shouldRefreshLocation() {
when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
mEnabler.setLocationEnabled(true);
verify(mEnabler).refreshLocationMode();
}
@Test
public void setLocationEnabled_notRestricted_shouldBroadcastUpdate() {
when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
mEnabler.setLocationEnabled(true);
verify(mContext).sendBroadcastAsUser(
argThat(actionMatches(LocationManager.MODE_CHANGING_ACTION)),
eq(UserHandle.of(ActivityManager.getCurrentUser())),
eq(WRITE_SECURE_SETTINGS));
}
@Test
@@ -241,5 +267,12 @@ public class LocationEnablerTest {
return intent -> TextUtils.equals(expected, intent.getAction());
}
@Implements(value = LocationManagerWrapper.class)
public static class ShadowLocationManagerWrapper {
@Implementation
public void setLocationEnabledForUser(boolean enabled, UserHandle userHandle) {
// Do nothing
}
}
}

View File

@@ -88,18 +88,17 @@ public class LocationSwitchBarControllerTest {
}
@Test
public void onSwitchChanged_switchChecked_shouldSetPreviousLocationMode() {
public void onSwitchChanged_switchChecked_shouldSetLocationEnabled() {
mController.onSwitchChanged(mSwitch, true);
verify(mEnabler).setLocationMode(
android.provider.Settings.Secure.LOCATION_MODE_PREVIOUS);
verify(mEnabler).setLocationEnabled(true);
}
@Test
public void onSwitchChanged_switchUnchecked_shouldSetLocationModeOff() {
public void onSwitchChanged_switchUnchecked_shouldSetLocationDisabled() {
mController.onSwitchChanged(mSwitch, false);
verify(mEnabler).setLocationMode(android.provider.Settings.Secure.LOCATION_MODE_OFF);
verify(mEnabler).setLocationEnabled(false);
}
@Test

View File

@@ -0,0 +1,152 @@
/*
* 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 junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.net.Uri;
import android.service.notification.Condition;
import android.view.LayoutInflater;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
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;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class EnableZenModeDialogTest {
private EnableZenModeDialog mController;
@Mock
private Context mContext;
@Mock
private Activity mActivity;
@Mock
private Fragment mFragment;
private Context mShadowContext;
private LayoutInflater mLayoutInflater;
private Condition mCountdownCondition;
private Condition mAlarmCondition;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mShadowContext = RuntimeEnvironment.application;
when(mActivity.getApplicationContext()).thenReturn(mShadowContext);
when(mContext.getApplicationContext()).thenReturn(mContext);
when(mFragment.getContext()).thenReturn(mShadowContext);
mLayoutInflater = LayoutInflater.from(mShadowContext);
when(mActivity.getLayoutInflater()).thenReturn(mLayoutInflater);
mController = spy(new EnableZenModeDialog());
mController.mContext = mContext;
mController.mActivity = mActivity;
mController.mForeverId = Condition.newId(mContext).appendPath("forever").build();
when(mContext.getString(com.android.internal.R.string.zen_mode_forever))
.thenReturn("testSummary");
mController.getContentView();
// these methods use static calls to ZenModeConfig which would normally fail in robotests,
// so instead do nothing:
doNothing().when(mController).bindGenericCountdown();
doReturn(null).when(mController).getTimeUntilNextAlarmCondition();
doNothing().when(mController).bindNextAlarm(any());
// as a result of doing nothing above, must bind manually:
Uri alarm = Condition.newId(mContext).appendPath("alarm").build();
mAlarmCondition = new Condition(alarm, "alarm", "", "", 0, 0, 0);
Uri countdown = Condition.newId(mContext).appendPath("countdown").build();
mCountdownCondition = new Condition(countdown, "countdown", "", "", 0, 0, 0);
mController.bind(mCountdownCondition,
mController.mZenRadioGroupContent.getChildAt(
EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX),
EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX);
mController.bind(mAlarmCondition,
mController.mZenRadioGroupContent.getChildAt(
EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX),
EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX);
}
@Test
public void testForeverChecked() {
mController.bindConditions(mController.forever());
assertTrue(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
.isChecked());
assertFalse(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
.isChecked());
assertFalse(mController.getConditionTagAt(
EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
}
@Test
public void testNoneChecked() {
mController.bindConditions(null);
assertFalse(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
.isChecked());
assertFalse(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
.isChecked());
assertFalse(mController.getConditionTagAt(
EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
}
@Test
public void testAlarmChecked() {
doReturn(false).when(mController).isCountdown(mAlarmCondition);
doReturn(true).when(mController).isAlarm(mAlarmCondition);
mController.bindConditions(mAlarmCondition);
assertFalse(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
.isChecked());
assertFalse(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
.isChecked());
assertTrue(mController.getConditionTagAt(
EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
}
@Test
public void testCountdownChecked() {
doReturn(false).when(mController).isAlarm(mCountdownCondition);
doReturn(true).when(mController).isCountdown(mCountdownCondition);
mController.bindConditions(mCountdownCondition);
assertFalse(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
.isChecked());
assertTrue(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
.isChecked());
assertFalse(mController.getConditionTagAt(
EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
}
}

View File

@@ -0,0 +1,301 @@
/*
* 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 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.Matchers.argThat;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.UserHandle;
import android.os.UserManager;
import android.service.notification.NotifyingApp;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
import com.android.settings.R;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
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(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class RecentNotifyingAppsPreferenceControllerTest {
@Mock
private PreferenceScreen mScreen;
@Mock
private PreferenceCategory mCategory;
@Mock
private Preference mSeeAllPref;
@Mock
private PreferenceCategory mDivider;
@Mock
private UserManager mUserManager;
@Mock
private ApplicationsState mAppState;
@Mock
private PackageManager mPackageManager;
@Mock
private ApplicationsState.AppEntry mAppEntry;
@Mock
private ApplicationInfo mApplicationInfo;
@Mock
private NotificationBackend mBackend;
private Context mContext;
private RecentNotifyingAppsPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
doReturn(mPackageManager).when(mContext).getPackageManager();
mController = new RecentNotifyingAppsPreferenceController(
mContext, mBackend, mAppState, null);
when(mScreen.findPreference(anyString())).thenReturn(mCategory);
when(mScreen.findPreference(RecentNotifyingAppsPreferenceController.KEY_SEE_ALL))
.thenReturn(mSeeAllPref);
when(mScreen.findPreference(RecentNotifyingAppsPreferenceController.KEY_DIVIDER))
.thenReturn(mDivider);
when(mCategory.getContext()).thenReturn(mContext);
}
@Test
public void isAlwaysAvailable() {
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void doNotIndexCategory() {
final List<String> nonIndexable = new ArrayList<>();
mController.updateNonIndexableKeys(nonIndexable);
assertThat(nonIndexable).containsAllOf(mController.getPreferenceKey(),
RecentNotifyingAppsPreferenceController.KEY_DIVIDER);
}
@Test
public void onDisplayAndUpdateState_shouldRefreshUi() {
mController = spy(new RecentNotifyingAppsPreferenceController(
mContext, null, (ApplicationsState) null, null));
doNothing().when(mController).refreshUi(mContext);
mController.displayPreference(mScreen);
mController.updateState(mCategory);
verify(mController, times(2)).refreshUi(mContext);
}
@Test
@Config(qualifiers = "mcc999")
public void display_shouldNotShowRecents_showAppInfoPreference() {
mController.displayPreference(mScreen);
verify(mCategory, never()).addPreference(any(Preference.class));
verify(mCategory).setTitle(null);
verify(mSeeAllPref).setTitle(R.string.notifications_title);
verify(mSeeAllPref).setIcon(null);
verify(mDivider).setVisible(false);
}
@Test
public void display_showRecents() {
final List<NotifyingApp> apps = new ArrayList<>();
final NotifyingApp app1 = new NotifyingApp()
.setPackage("pkg.class")
.setLastNotified(System.currentTimeMillis());
final NotifyingApp app2 = new NotifyingApp()
.setLastNotified(System.currentTimeMillis())
.setPackage("com.android.settings");
final NotifyingApp app3 = new NotifyingApp()
.setLastNotified(System.currentTimeMillis() - 1000)
.setPackage("pkg.class2");
apps.add(app1);
apps.add(app2);
apps.add(app3);
// app1, app2 are valid apps. app3 is invalid.
when(mAppState.getEntry(app1.getPackage(), UserHandle.myUserId()))
.thenReturn(mAppEntry);
when(mAppState.getEntry(app2.getPackage(), UserHandle.myUserId()))
.thenReturn(mAppEntry);
when(mAppState.getEntry(app3.getPackage(), UserHandle.myUserId()))
.thenReturn(null);
when(mPackageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(
new ResolveInfo());
when(mBackend.getRecentApps()).thenReturn(apps);
mAppEntry.info = mApplicationInfo;
mController.displayPreference(mScreen);
verify(mCategory).setTitle(R.string.recent_notifications);
// Only add app1. app2 is skipped because of the package name, app3 skipped because
// it's invalid app.
verify(mCategory, times(1)).addPreference(any(Preference.class));
verify(mSeeAllPref).setSummary(null);
verify(mSeeAllPref).setIcon(R.drawable.ic_chevron_right_24dp);
verify(mDivider).setVisible(true);
}
@Test
public void display_showRecentsWithInstantApp() {
// Regular app.
final List<NotifyingApp> apps = new ArrayList<>();
final NotifyingApp app1 = new NotifyingApp().
setLastNotified(System.currentTimeMillis())
.setPackage("com.foo.bar");
apps.add(app1);
// Instant app.
final NotifyingApp app2 = new NotifyingApp()
.setLastNotified(System.currentTimeMillis() + 200)
.setPackage("com.foo.barinstant");
apps.add(app2);
ApplicationsState.AppEntry app1Entry = mock(ApplicationsState.AppEntry.class);
ApplicationsState.AppEntry app2Entry = mock(ApplicationsState.AppEntry.class);
app1Entry.info = mApplicationInfo;
app2Entry.info = mApplicationInfo;
when(mAppState.getEntry(app1.getPackage(), UserHandle.myUserId())).thenReturn(app1Entry);
when(mAppState.getEntry(app2.getPackage(), UserHandle.myUserId())).thenReturn(app2Entry);
// Only the regular app app1 should have its intent resolve.
when(mPackageManager.resolveActivity(argThat(intentMatcher(app1.getPackage())),
anyInt())).thenReturn(new ResolveInfo());
when(mBackend.getRecentApps()).thenReturn(apps);
// Make sure app2 is considered an instant app.
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (ApplicationInfo info) -> {
if (info == app2Entry.info) {
return true;
} else {
return false;
}
});
mController.displayPreference(mScreen);
ArgumentCaptor<Preference> prefCaptor = ArgumentCaptor.forClass(Preference.class);
verify(mCategory, times(2)).addPreference(prefCaptor.capture());
List<Preference> prefs = prefCaptor.getAllValues();
assertThat(prefs.get(1).getKey()).isEqualTo(app1.getPackage());
assertThat(prefs.get(0).getKey()).isEqualTo(app2.getPackage());
}
@Test
public void display_hasRecentButNoneDisplayable_showAppInfo() {
final List<NotifyingApp> apps = new ArrayList<>();
final NotifyingApp app1 = new NotifyingApp()
.setPackage("com.android.phone")
.setLastNotified(System.currentTimeMillis());
final NotifyingApp app2 = new NotifyingApp()
.setPackage("com.android.settings")
.setLastNotified(System.currentTimeMillis());
apps.add(app1);
apps.add(app2);
// app1, app2 are not displayable
when(mAppState.getEntry(app1.getPackage(), UserHandle.myUserId()))
.thenReturn(mock(ApplicationsState.AppEntry.class));
when(mAppState.getEntry(app2.getPackage(), UserHandle.myUserId()))
.thenReturn(mock(ApplicationsState.AppEntry.class));
when(mPackageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(
new ResolveInfo());
when(mBackend.getRecentApps()).thenReturn(apps);
mController.displayPreference(mScreen);
verify(mCategory, never()).addPreference(any(Preference.class));
verify(mCategory).setTitle(null);
verify(mSeeAllPref).setTitle(R.string.notifications_title);
verify(mSeeAllPref).setIcon(null);
}
@Test
public void display_showRecents_formatSummary() {
final List<NotifyingApp> apps = new ArrayList<>();
final NotifyingApp app1 = new NotifyingApp()
.setLastNotified(System.currentTimeMillis())
.setPackage("pkg.class");
apps.add(app1);
when(mAppState.getEntry(app1.getPackage(), UserHandle.myUserId()))
.thenReturn(mAppEntry);
when(mPackageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(
new ResolveInfo());
when(mBackend.getRecentApps()).thenReturn(apps);
mAppEntry.info = mApplicationInfo;
mController.displayPreference(mScreen);
verify(mCategory).addPreference(argThat(summaryMatches("0 min. ago")));
}
private static ArgumentMatcher<Preference> summaryMatches(String expected) {
return preference -> TextUtils.equals(expected, preference.getSummary());
}
// Used for matching an intent with a specific package name.
private static ArgumentMatcher<Intent> intentMatcher(String packageName) {
return intent -> packageName.equals(intent.getPackage());
}
}

View File

@@ -26,6 +26,7 @@ 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;
@@ -79,7 +80,8 @@ public class ZenModeButtonPreferenceControllerTest {
mContext = shadowApplication.getApplicationContext();
mContentResolver = RuntimeEnvironment.application.getContentResolver();
mController = new ZenModeButtonPreferenceController(mContext, mock(Lifecycle.class));
mController = new ZenModeButtonPreferenceController(mContext, mock(Lifecycle.class),
mock(FragmentManager.class));
when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
ReflectionHelpers.setField(mController, "mBackend", mBackend);
ReflectionHelpers.setField(mController, "mZenButtonOn", mZenButtonOn);

View File

@@ -0,0 +1,98 @@
/*
* 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.security;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.provider.Settings;
import android.support.v14.preference.SwitchPreference;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
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.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class LockdownButtonPreferenceControllerTest {
@Mock
private LockPatternUtils mLockPatternUtils;
private SwitchPreference mPreference;
private Context mContext;
private LockdownButtonPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mPreference = new SwitchPreference(mContext);
mController = spy(new LockdownButtonPreferenceController(mContext));
ReflectionHelpers.setField(mController, "mLockPatternUtils", mLockPatternUtils);
}
@Test
public void isAvailable_lockSet_shouldReturnTrue() throws Exception {
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void isAvailable_lockUnset_shouldReturnFalse() throws Exception {
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(false);
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void onPreferenceChange_settingIsUpdated() throws Exception {
boolean state = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0) != 0;
assertThat(mController.onPreferenceChange(mPreference, !state)).isTrue();
boolean newState = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0) != 0;
assertThat(newState).isEqualTo(!state);
}
@Test
public void onSettingChange_preferenceIsUpdated() throws Exception {
boolean state = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0) != 0;
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isEqualTo(state);
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.LOCKDOWN_IN_POWER_MENU, state ? 0 : 1);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isEqualTo(!state);
}
}

View File

@@ -21,6 +21,7 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import com.android.settings.accounts.AccountFeatureProvider;
import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.bluetooth.BluetoothFeatureProvider;
import com.android.settings.connecteddevice.SmsMirroringFeatureProvider;
@@ -65,6 +66,7 @@ public class FakeFeatureFactory extends FeatureFactory {
public final SmsMirroringFeatureProvider smsMirroringFeatureProvider;
public final SlicesFeatureProvider slicesFeatureProvider;
public SearchFeatureProvider searchFeatureProvider;
public final AccountFeatureProvider mAccountFeatureProvider;
/**
* Call this in {@code @Before} method of the test class to use fake factory.
@@ -104,6 +106,7 @@ public class FakeFeatureFactory extends FeatureFactory {
dataPlanFeatureProvider = mock(DataPlanFeatureProvider.class);
smsMirroringFeatureProvider = mock(SmsMirroringFeatureProvider.class);
slicesFeatureProvider = mock(SlicesFeatureProvider.class);
mAccountFeatureProvider = mock(AccountFeatureProvider.class);
}
@Override
@@ -190,4 +193,9 @@ public class FakeFeatureFactory extends FeatureFactory {
public SlicesFeatureProvider getSlicesFeatureProvider() {
return slicesFeatureProvider;
}
@Override
public AccountFeatureProvider getAccountFeatureProvider() {
return mAccountFeatureProvider;
}
}

View File

@@ -0,0 +1,53 @@
/*
* 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.widget;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import com.android.settings.R;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class AppCheckBoxPreferenceTest {
private Context mContext;
private AppCheckBoxPreference mPreference;
private AppCheckBoxPreference mAttrPreference;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mPreference = new AppCheckBoxPreference(mContext);
mAttrPreference = new AppCheckBoxPreference(mContext, null /* attrs */);
}
@Test
public void testGetLayoutResource() {
assertThat(mPreference.getLayoutResource()).isEqualTo(R.layout.preference_app);
assertThat(mAttrPreference.getLayoutResource()).isEqualTo(R.layout.preference_app);
}
}

View File

@@ -80,7 +80,7 @@ public class WifiTetherApBandPreferenceControllerTest {
mController.displayPreference(mScreen);
assertThat(mListPreference.getEntries().length).isEqualTo(2);
assertThat(mListPreference.getEntries().length).isEqualTo(3);
}
@Test
@@ -113,13 +113,18 @@ public class WifiTetherApBandPreferenceControllerTest {
when(mWifiManager.is5GHzBandSupported()).thenReturn(true);
mController.displayPreference(mScreen);
// -1 is WifiConfiguration.AP_BAND_ANY, for 'Auto' option.
mController.onPreferenceChange(mListPreference, "-1");
assertThat(mController.getBandIndex()).isEqualTo(-1);
mController.onPreferenceChange(mListPreference, "1");
assertThat(mController.getBandIndex()).isEqualTo(1);
mController.onPreferenceChange(mListPreference, "0");
assertThat(mController.getBandIndex()).isEqualTo(0);
verify(mListener, times(2)).onTetherConfigUpdated();
verify(mListener, times(3)).onTetherConfigUpdated();
}
@Test

View File

@@ -1,133 +0,0 @@
/*
* 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 static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;
import static org.junit.Assert.fail;
import android.app.INotificationManager;
import android.app.Instrumentation;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.os.Process;
import android.os.ServiceManager;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class ChannelGroupNotificationSettingsTest {
private Context mTargetContext;
private Instrumentation mInstrumentation;
private NotificationManager mNm;
@Before
public void setUp() {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mTargetContext = mInstrumentation.getTargetContext();
mNm = (NotificationManager) mTargetContext.getSystemService(Context.NOTIFICATION_SERVICE);
}
@Test
public void launchNotificationSetting_displaysChannels() {
NotificationChannelGroup group =
new NotificationChannelGroup(this.getClass().getName(), this.getClass().getName());
group.setDescription("description");
NotificationChannel channel = new NotificationChannel(this.getClass().getName(),
"channel" + this.getClass().getName(), IMPORTANCE_MIN);
channel.setGroup(this.getClass().getName());
NotificationChannel channel2 = new NotificationChannel("2"+this.getClass().getName(),
"2channel" + this.getClass().getName(), IMPORTANCE_MIN);
channel2.setGroup(this.getClass().getName());
mNm.createNotificationChannelGroup(group);
mNm.createNotificationChannel(channel);
mNm.createNotificationChannel(channel2);
final Intent intent = new Intent(Settings.ACTION_CHANNEL_GROUP_NOTIFICATION_SETTINGS)
.putExtra(Settings.EXTRA_APP_PACKAGE, mTargetContext.getPackageName())
.putExtra(Settings.EXTRA_CHANNEL_GROUP_ID, group.getId());
mInstrumentation.startActivitySync(intent);
onView(allOf(withText(group.getName().toString()))).check(matches(isDisplayed()));
onView(allOf(withText(channel.getName().toString()))).check(
matches(isDisplayed()));
onView(allOf(withText(group.getDescription().toString()))).check(
matches(isDisplayed()));
onView(allOf(withText(channel2.getName().toString()))).check(
matches(isDisplayed()));
try {
onView(allOf(withText("Android is blocking this group of notifications from"
+ " appearing on this device"))).check(matches(isDisplayed()));
fail("Blocking footer erroneously appearing");
} catch (Exception e) {
// expected
}
}
@Test
public void launchNotificationSettings_blockedGroup() throws Exception {
NotificationChannelGroup blocked =
new NotificationChannelGroup("blocked", "blocked");
NotificationChannel channel =
new NotificationChannel("channel", "channel", IMPORTANCE_HIGH);
channel.setGroup(blocked.getId());
mNm.createNotificationChannelGroup(blocked);
mNm.createNotificationChannel(channel);
INotificationManager sINM = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
blocked.setBlocked(true);
sINM.updateNotificationChannelGroupForPackage(
mTargetContext.getPackageName(), Process.myUid(), blocked);
final Intent intent = new Intent(Settings.ACTION_CHANNEL_GROUP_NOTIFICATION_SETTINGS)
.putExtra(Settings.EXTRA_APP_PACKAGE, mTargetContext.getPackageName())
.putExtra(Settings.EXTRA_CHANNEL_GROUP_ID, blocked.getId());
mInstrumentation.startActivitySync(intent);
onView(allOf(withText("Off"), isDisplayed())).check(matches(isDisplayed()));
onView(allOf(withText("Android is blocking this group of notifications from"
+ " appearing on this device"))).check(matches(isDisplayed()));
try {
onView(allOf(withText(channel.getName().toString()))).check(matches(isDisplayed()));
fail("settings appearing for blocked group");
} catch (Exception e) {
// expected
}
}
}