Snap for 4562879 from 0ad01ef2e0 to pi-release
Change-Id: Ia3c88dd78e9dd4b6e7d7c4b5643a5f2d22a8fe6e
This commit is contained in:
@@ -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">
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 & 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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -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
167
res/xml/my_device_info.xml
Normal 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>
|
||||
@@ -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">
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */ }
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -298,5 +298,6 @@ public class SettingsGateway {
|
||||
Settings.DateTimeSettingsActivity.class.getName(),
|
||||
Settings.DeviceInfoSettingsActivity.class.getName(),
|
||||
Settings.EnterprisePrivacySettingsActivity.class.getName(),
|
||||
Settings.MeCardActivity.class.getName(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
467
src/com/android/settings/notification/EnableZenModeDialog.java
Normal file
467
src/com/android/settings/notification/EnableZenModeDialog.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
38
src/com/android/settings/widget/AppCheckBoxPreference.java
Normal file
38
src/com/android/settings/widget/AppCheckBoxPreference.java
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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 */));
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user