Snap for 4677756 from 362ba01789 to pi-release

Change-Id: Ia10d254af68bd3fe7a6cc97cc5e0deee523c12d7
This commit is contained in:
android-build-team Robot
2018-03-25 07:27:15 +00:00
118 changed files with 3318 additions and 571 deletions

View File

@@ -255,6 +255,8 @@
android:value="com.android.settings.wifi.WifiSettings" />
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
<meta-data android:name="android.metadata.SLICE_URI"
android:value="content://android.settings.slices/wifi" />
</activity>
<activity
@@ -983,7 +985,7 @@
</activity>
<activity android:name=".Settings$MyDeviceInfoActivity"
android:label="@string/device_info_settings"
android:label="@string/about_settings"
android:icon="@drawable/ic_settings_about"
android:taskAffinity="com.android.settings"
android:parentActivityName="Settings">
@@ -1127,6 +1129,17 @@
</intent-filter>
</activity>
<activity android:name=".slice.SliceDeepLinkSpringBoard"
android:theme="@android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="settings"
android:host="com.android.settings.slices" />
</intent-filter>
</activity>
<!-- Provide direct entry into manage apps showing running services.
This is for compatibility with old shortcuts. -->
<activity-alias android:name=".RunningServices"
@@ -2384,6 +2397,10 @@
android:taskAffinity="com.android.settings"
android:parentActivityName="Settings">
<!-- TODO(b/70950124): add shortcut intent-filter -->
<intent-filter android:priority="1">
<action android:name="android.settings.DATA_USAGE_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:priority="10">
<action android:name="com.android.settings.action.SETTINGS" />
</intent-filter>
@@ -2399,6 +2416,10 @@
android:icon="@drawable/ic_settings_data_usage"
android:taskAffinity="com.android.settings"
android:parentActivityName="Settings">
<intent-filter android:priority="1">
<action android:name="android.settings.DATA_USAGE_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" />
@@ -2661,6 +2682,23 @@
android:resource="@string/sound_dashboard_summary"/>
</activity>
<!-- Show apps for which application-level notification settings are applicable -->
<activity android:name="Settings$NotificationAppListActivity"
android:label="@string/app_notifications_title"
android:icon="@drawable/ic_notifications"
android:exported="true"
android:taskAffinity="">
<intent-filter android:priority="1">
<action android:name="android.settings.ALL_APPS_NOTIFICATION_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:priority="150">
<action android:name="com.android.settings.action.SETTINGS" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.applications.manageapplications.ManageApplications" />
</activity>
<!-- Show application-level notification settings (app passed in as extras) -->
<activity android:name="Settings$AppNotificationSettingsActivity"
android:exported="true">
@@ -3244,7 +3282,16 @@
<provider android:name=".slices.SettingsSliceProvider"
android:authorities="com.android.settings.slices;android.settings.slices"
android:exported="true">
android:exported="true"
android:grantUriPermissions="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.app.slice.category.SLICE" />
<data android:scheme="settings"
android:host="com.android.settings.slices" />
</intent-filter>
</provider>
<receiver

View File

@@ -1276,7 +1276,7 @@
errorLine1=" android:background=&quot;@color/lock_pattern_background&quot; />"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/layout-land/confirm_lock_pattern_internal.xml"
file="res/layout-land/confirm_lock_pattern_normal.xml"
line="111"
column="17"/>
</issue>

View File

@@ -82,7 +82,7 @@
android:minLines="2"
android:gravity="center"
android:paddingHorizontal="?attr/suwMarginSides"
android:textSize="18sp" />
android:textSize="12sp" />
<com.android.setupwizardlib.view.FillContentLayout
style="@style/LockPatternContainerStyle"

View File

@@ -22,7 +22,15 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- left : cancel, or re-try -->
<!-- left : skip -->
<Button android:id="@+id/skip_button"
style="@style/SuwGlifButton.Secondary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/skip_label"
android:visibility="gone" />
<!-- left : retry -->
<Button android:id="@+id/footerLeftButton"
style="@style/SuwGlifButton.Secondary"
android:layout_width="wrap_content"

View File

@@ -69,6 +69,7 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:textAppearance="@style/TextAppearance.Small"
android:textAlignment="viewStart"
android:textColor="?android:attr/textColorSecondary" />
<TextView android:id="@+id/appendix"

View File

@@ -37,6 +37,14 @@
android:id="@+id/sort_order_size"
android:title="@string/sort_order_size"
android:showAsAction="never" />
<item
android:id="@+id/sort_order_recent_notification"
android:title="@string/sort_order_recent_notification"
android:showAsAction="never" />
<item
android:id="@+id/sort_order_frequent_notification"
android:title="@string/sort_order_frequent_notification"
android:showAsAction="never" />
<item
android:id="@+id/reset_app_preferences"
android:title="@string/reset_app_preferences"

View File

@@ -20,6 +20,6 @@
<item name="fingerprint_enroll_enrolling" type="layout">@layout/fingerprint_enroll_enrolling_base</item>
<item name="fingerprint_enroll_finish" type="layout">@layout/fingerprint_enroll_finish_base</item>
<item name="choose_lock_pattern" type="layout">@layout/choose_lock_pattern_common</item>
<item name="confirm_lock_pattern_internal" type="layout">@layout/confirm_lock_pattern_internal_base</item>
<item name="confirm_lock_pattern_normal" type="layout">@layout/confirm_lock_pattern_normal_base</item>
</resources>

View File

@@ -17,7 +17,7 @@
<resources>
<item name="notification_app_section" type="layout">@*android:layout/preference_category_material</item>
<item name="confirm_lock_pattern" type="layout">@layout/confirm_lock_pattern_base</item>
<item name="confirm_lock_pattern_internal" type="layout">@layout/confirm_lock_pattern_internal_base</item>
<item name="confirm_lock_pattern_normal" type="layout">@layout/confirm_lock_pattern_normal_base</item>
<item name="confirm_lock_password" type="layout">@layout/confirm_lock_password_base</item>
<item name="fingerprint_enroll_find_sensor" type="layout">@layout/fingerprint_enroll_find_sensor_base</item>
<item name="fingerprint_enroll_enrolling" type="layout">@layout/fingerprint_enroll_enrolling_base</item>

View File

@@ -1095,4 +1095,17 @@
<item>no</item>
</string-array>
<string-array name="gesture_prevent_ringing_entries" translatable="false">
<item>@string/prevent_ringing_option_vibrate</item>
<item>@string/prevent_ringing_option_mute</item>
<item>@string/prevent_ringing_option_none</item>
</string-array>
<!-- Keep in sync with Settings.Secure.VOLUME_HUSH_* -->
<string-array name="gesture_prevent_ringing_values" translatable="false">
<item>1</item>
<item>2</item>
<item>0</item>
</string-array>
</resources>

View File

@@ -128,5 +128,7 @@
<color name="homepage_generic_icon_background">#1A73E8</color>
<!-- End of dashboard/homepage icon background colors -->
<color name="glif_error_color">@*android:color/material_red_A700</color>
</resources>

View File

@@ -754,10 +754,14 @@
<string name="date_time_set_date_title">Date</string>
<!-- Date & time setting screen setting option title -->
<string name="date_time_set_date">Set date</string>
<!-- Text hint to search region in time zone setting screen -->
<string name="date_time_search_region">Search region</string>
<!-- Setting option title to select region in time zone setting screen [CHAR LIMIT=30] -->
<string name="date_time_select_region">Region</string>
<!-- Setting option title to select time zone in time zone setting screen [CHAR LIMIT=30]-->
<string name="date_time_select_zone">Time Zone</string>
<!-- Setting option title to select time zone in a region -->
<string name="date_time_set_timezone_in_region">Time zones in <xliff:g id="region" example="United States">%1$s</xliff:g></string>
<!-- Setting option title in time zone setting screen [CHAR LIMIT=30] -->
<string name="date_time_select_fixed_offset_time_zones">Select UTC offset</string>
<!-- Menu item on Select time zone screen -->
@@ -1153,7 +1157,7 @@
<string name="suggested_lock_settings_summary" product="default">Set screen lock to protect phone</string>
<!-- Title for suggested actions for settings up a fingerprint lock [CHAR LIMIT=46] -->
<string name="suggested_fingerprint_lock_settings_title">Unlock with fingerprint</string>
<string name="suggested_fingerprint_lock_settings_title">Add fingerprint to unlock</string>
<!-- Summary for suggested actions for settings up a fingerprint lock (tablet) [CHAR LIMIT=55] -->
<string name="suggested_fingerprint_lock_settings_summary" product="tablet"></string>
@@ -1808,6 +1812,8 @@
<string name="wifi_wakeup">Turn on Wi\u2011Fi automatically</string>
<!-- Checkbox summary for option to enable Wi-Fi when high quality saved networks are nearby-->
<string name="wifi_wakeup_summary">Wi\u2011Fi will turn back on near high\u2011quality saved networks, like your home network</string>
<!-- Checkbox summary for auto-wifi when user needs to enable location scanning to toggle it -->
<string name="wifi_wakeup_summary_no_location">Unavailable because location is turned off. Turn on <annotation id="link">location</annotation>.</string>
<!-- Checkbox summary for Wi-Fi wakeup option to explain that Wi-Fi wakeup is disabled because Wi-Fi scanning is turned off -->
<string name="wifi_wakeup_summary_scanning_disabled">Unavailable because Wi\u2011Fi scanning is turned off</string>
<!-- Checkbox summary for Wi-Fi wakeup option to explain that a network rating provider needs to be selected to use the feature. -->
@@ -1901,6 +1907,14 @@
<string name="wifi_more">More</string>
<!-- Wi-Fi settings. wps menu title [CHAR LIMIT=25]-->
<string name="wifi_setup_wps">Automatic setup (WPS)</string>
<!-- Wi-Fi settings dialog. Title of dialog displayed asking user to enable Wi-Fi Scanning [CHAR LIMIT=60]-->
<string name="wifi_settings_scanning_required_title">Turn on Wi\u2011Fi scanning?</string>
<!-- Wi-Fi settings dialog. Summary text describing why we need Wi-Fi scanning on. [CHAR LIMIT=NONE]-->
<string name="wifi_settings_scanning_required_summary">To turn on Wi\u2011Fi automatically, you first need to turn on Wi\u2011Fi scanning.</string>
<!-- Wi-Fi settings dialog. Informational text describing what Wi-Fi scanning does. [CHAR LIMIT=NONE]-->
<string name="wifi_settings_scanning_required_info">Wi\2011Fi scanning allows apps and services to scan for Wi\u2011Fi networks at any time, even when Wi\u2011Fi is off. This can be used, for example, to improve location\u2011based features and services.</string>
<!-- Wi-Fi settings dialog. Text for the button that takes users to a help article about Wi-Fi scanning. [CHAR LIMIT = 20]-->
<string name="wifi_settings_scanning_required_turn_on">Turn on</string>
<!-- Dialog for Access Points --> <skip />
<!-- Label to show/hide advanced options [CHAR LIMIT=40] -->
@@ -1915,6 +1929,10 @@
<string name="wifi_ssid_hint">Enter the SSID</string>
<!-- Label for the security of the connection -->
<string name="wifi_security">Security</string>
<!-- Label for the hidden network status of this network -->
<string name="wifi_hidden_network">Hidden network</string>
<!-- Label for the warning shown to users if they try to connect to a network as "hidden" -->
<string name="wifi_hidden_network_warning">Hidden network might create privacy risk as this device has to broadcast this SSID name in order to connect.</string>
<!-- Label for the signal strength of the connection -->
<string name="wifi_signal">Signal strength</string>
<!-- Label for the status of the connection -->
@@ -1954,7 +1972,11 @@
<!-- 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 -->
<string name="wifi_ap_choose_5G">5 GHz Band</string>
<string name="wifi_ap_choose_5G">5.0 GHz Band</string>
<!-- Label for adding to the list of selected bands when 2.4 GHz is selected -->
<string name="wifi_ap_2G">2.4 GHz</string>
<!-- Label for adding to the list of selected bands when 5.0 GHz is selected -->
<string name="wifi_ap_5G">5.0 GHz</string>
<!-- Label for the spinner to show ip settings [CHAR LIMIT=25] -->
<string name="wifi_ip_settings">IP settings</string>
<!-- Label for the check box to share a network with other users on the same device -->
@@ -2033,6 +2055,10 @@
<string name="wifi_failed_save_message">Failed to save network</string>
<!-- Button label to dismiss the dialog -->
<string name="wifi_cancel">Cancel</string>
<!-- Dialog title for forget confirmation dialog -->
<string name="wifi_forget_dialog_title">Forget network?</string>
<!-- Dialog message for forget confirmation dialog -->
<string name="wifi_forget_dialog_message">All passwords for this network will be deleted</string>
<!-- Wi-Fi Advanced Settings --> <skip />
<!-- Wi-Fi settings screen, Saved networks, settings section. This is a header shown above Saved networks wifi settings. [CHAR LIMIT=30] -->
@@ -2435,6 +2461,12 @@
<string name="color_mode_option_boosted">Boosted</string>
<!-- Display settings screen, Color mode option for "Saturated color" [CHAR LIMIT=45] -->
<string name="color_mode_option_saturated">Saturated</string>
<!-- Display settings screen, Color mode option for "Automatic color" [CHAR LIMIT=45] -->
<string name="color_mode_option_automatic">Automatic</string>
<!-- Display settings screen, "natural(sRGB) color" setting option summary [CHAR LIMIT=NONE] -->
<string name="color_mode_summary_natural">Use accurate colors only</string>
<!-- Display settings screen, "Automatic color" setting option summary [CHAR LIMIT=NONE] -->
<string name="color_mode_summary_automatic">Adjust between vivid and accurate colors</string>
<!-- Sound & display settings screen, accelerometer-based rotation summary text when check box is selected -->
<string name="accelerometer_summary_on" product="tablet">Switch orientation automatically when rotating tablet</string>
@@ -2526,6 +2558,18 @@
<string name="night_display_summary_on_auto_mode_custom">Will turn off automatically at <xliff:g name="time" example="10 PM">%1$s</xliff:g></string>
<!-- Display settings screen, summary of night display when on and will turn off automatically at sunrise. [CHAR LIMIT=NONE] -->
<string name="night_display_summary_on_auto_mode_twilight">Will turn off automatically at sunrise</string>
<!-- Display settings screen, activation button action for manual mode. [CHAR LIMIT=40] -->
<string name="night_display_activation_on_manual">Turn on now</string>
<!-- Display settings screen, deactivation button action for manual mode. [CHAR LIMIT=40] -->
<string name="night_display_activation_off_manual">Turn off now</string>
<!-- Display settings screen, activation button action for sunset-to-sunrise schedule [CHAR LIMIT=40] -->
<string name="night_display_activation_on_twilight">Turn on until sunrise</string>
<!-- Display settings screen, deactivation button action for sunset-to-sunrise schedule [CHAR LIMIT=40] -->
<string name="night_display_activation_off_twilight">Turn off until sunset</string>
<!-- Display settings screen, activation button action for custom schedule [CHAR LIMIT=40] -->
<string name="night_display_activation_on_custom">Turn on until <xliff:g name="time" example="6 AM">%1$s</xliff:g></string>
<!-- Display settings screen, deactivation button action for custom schedule [CHAR LIMIT=40] -->
<string name="night_display_activation_off_custom">Turn off until <xliff:g name="time" example="10 PM">%1$s</xliff:g></string>
<!-- Sound & display settings screen, setting option name to change screen timeout -->
<string name="screen_timeout">Sleep</string>
@@ -3531,6 +3575,8 @@
<string name="lockpassword_confirm_passwords_dont_match">Passwords don\u2019t match</string>
<!-- Header on pin confirm screen if second pin doesn't match the first. [CHAR LIMIT=30]-->
<string name="lockpassword_confirm_pins_dont_match">PINs don\u2019t match</string>
<!-- Header on pattern confirm screen [CHAR LIMIT=40] -->
<string name="lockpassword_draw_your_pattern_again_header">Draw your pattern again</string>
<!-- Header shown to ask the user to select an unlock method [CHAR LIMIT=30] -->
<string name="lockpassword_choose_lock_generic_header">Unlock selection</string>
<!-- Toast shown if setting password was successful -->
@@ -3818,6 +3864,10 @@
<string name="sort_order_alpha">Sort by name</string>
<!-- Manage applications screen, menu item. Sorts all of the apps in the list based on their file size. This is used to uninstall when space is getting low. -->
<string name="sort_order_size">Sort by size</string>
<!-- Manage applications screen, menu item. Sorts all of the apps in the list based on how recently they sent notifications.-->
<string name="sort_order_recent_notification">Most recent</string>
<!-- Manage applications screen, menu item. Sorts all of the apps in the list based on how often they send notifications. -->
<string name="sort_order_frequent_notification">Most frequent</string>
<!-- [CHAR LIMIT=25] Manage applications screen, menu item. Show running services. -->
<string name="show_running_services">Show running services</string>
<!-- [CHAR LIMIT=25] Manage applications screen, menu item. Show background cached processes. -->
@@ -4432,6 +4482,24 @@
<!-- Used in the Captions settings screen to control turning on/off the feature entirely -->
<string name="accessibility_caption_master_switch_title">Use captions</string>
<!-- Title for the accessibility preference for hearing aid. [CHAR LIMIT=35] -->
<string name="accessibility_hearingaid_title">Hearing aids</string>
<!-- Summary for the accessibility preference for hearing aid when not connected. [CHAR LIMIT=50] -->
<string name="accessibility_hearingaid_not_connected_summary">No hearing aids connected</string>
<!-- Summary for the accessibility preference for hearing aid when adding new devices. [CHAR LIMIT=50] -->
<string name="accessibility_hearingaid_adding_summary">Add hearing aid</string>
<!-- Message to ask the user that if they want to pair the hearing aid, then they should find and tap the hearing aid device from the list on the next screen. [CHAR LIMIT=NONE] -->
<string name="accessibility_hearingaid_pair_instructions_first_message">To pair your hearing aids, find and tap your device on the next screen.</string>
<!-- Message to ask the user to make sure that their hearing aid devices are in pairing mode. [CHAR LIMIT=NONE] -->
<string name="accessibility_hearingaid_pair_instructions_second_message">Make sure your hearing aids are in pairing mode.</string>
<!-- Summary for the accessibility preference for hearing aid when there is an active device. [CHAR LIMIT=50] -->
<string name="accessibility_hearingaid_active_device_summary"><xliff:g id="device_name">%1$s</xliff:g> currently active</string>
<!-- Summary for the accessibility preference for hearing aid when there are saved devices. [CHAR LIMIT=50] -->
<plurals name="show_number_hearingaid_count">
<item quantity="one"><xliff:g id="number_device_count">%1$d</xliff:g> saved hearing aid</item>
<item quantity="other"><xliff:g id="number_device_count">%1$d</xliff:g> saved hearing aids</item>
</plurals>
<!-- Preference's state when enabled. -->
<string name="accessibility_summary_state_enabled">On</string>
<!-- Preference's state when disabled. -->
@@ -6299,7 +6367,7 @@
<!-- Title for add user confirmation dialog [CHAR LIMIT=30] -->
<string name="user_add_user_title">Add new user?</string>
<!-- Message for add user confirmation dialog - long version. [CHAR LIMIT=none] -->
<string name="user_add_user_message_long">You can share this device with other people by creating additional users. Each user has their own space, which they can customize with apps, wallpaper, and so on. Users can also adjust device settings like Wi\u2011Fi that affect everyone.\n\nWhen you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users.</string>
<string name="user_add_user_message_long">You can share this device with other people by creating additional users. Each user has their own space, which they can customize with apps, wallpaper, and so on. Users can also adjust device settings like Wi\u2011Fi that affect everyone.\n\nWhen you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users. Accessibility settings and services may not transfer to the new user.</string>
<!-- Message for add user confirmation dialog - short version. [CHAR LIMIT=none] -->
<string name="user_add_user_message_short">When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users. </string>
<!-- Title of dialog to setup a new user [CHAR LIMIT=30] -->
@@ -6780,16 +6848,16 @@
</string>
<!--Search Keywords [CHAR LIMIT=NONE]-->
<string name="keywords_wifi">wifi, wi-fi, network connection</string>
<string name="keywords_wifi">wifi, wi-fi, network connection, internet, wireless, data, wi fi</string>
<string name="keywords_change_wifi_state">wifi, wi-fi, toggle, control</string>
<string name="keywords_more_default_sms_app">text message, texting, messages, messaging</string>
<string name="keywords_more_default_sms_app">text message, texting, messages, messaging, default</string>
<string name="keywords_more_mobile_networks">cellular, mobile, cell carrier, wireless, data, 4g,3g, 2g, lte</string>
<string name="keywords_wifi_calling">wifi, wi-fi, call, calling</string>
<string name="keywords_home">launcher</string>
<string name="keywords_home">launcher, default, apps</string>
<string name="keywords_display">screen, touchscreen</string>
<string name="keywords_display_brightness_level">dim screen, touchscreen, battery</string>
<string name="keywords_display_brightness_level">dim screen, touchscreen, battery, bright</string>
<string name="keywords_display_auto_brightness">dim screen, touchscreen, battery</string>
<string name="keywords_display_night_display">dim screen, night, tint</string>
<string name="keywords_display_night_display">dim screen, night, tint, night shift, brightness, screen color, colour, color</string>
<string name="keywords_display_wallpaper">background, personalize, customize display</string>
<string name="keywords_display_font_size">text size</string>
<string name="keywords_display_cast_screen">project, cast</string>
@@ -6800,9 +6868,9 @@
<string name="keywords_text_to_speech_output">rate, language, default, speak, speaking, tts, accessibility, screen reader, blind</string>
<string name="keywords_date_and_time">clock, military</string>
<string name="keywords_network_reset">reset, restore, factory</string>
<string name="keywords_factory_data_reset">wipe, delete, restore, clear, remove</string>
<string name="keywords_factory_data_reset">wipe, delete, restore, clear, remove, factory reset</string>
<string name="keywords_printing">printer</string>
<string name="keywords_sounds">speaker beep</string>
<string name="keywords_sounds">speaker beep, speaker, volume, mute, silence, audio, music</string>
<string name="keywords_sounds_and_notifications_interruptions">dont don\u2019t disturb, interrupt, interruption, break</string>
<string name="keywords_app">RAM</string>
<string name="keywords_location">nearby, location, history, reporting</string>
@@ -6817,7 +6885,7 @@
<string name="keywords_default_apps">apps, default</string>
<string name="keywords_ignore_optimizations">ignore optimizations, doze, app standby</string>
<string name="keywords_color_mode">vibrant, RGB, sRGB, color, natural, standard</string>
<string name="keywords_color_temperature">color temperature D65 D73 white yellow blue warm cool</string>
<string name="keywords_color_temperature">color, temperature, D65, D73, white, yellow, blue, warm, cool</string>
<string name="keywords_lockscreen">slide to unlock, password, pattern, PIN</string>
<string name="keywords_profile_challenge">work challenge, work, profile</string>
<string name="keywords_unification">work profile, managed profile, unify, unification, work, profile</string>
@@ -6834,6 +6902,51 @@
<!-- Search keyword for fingerprint settings. -->
<string name="keywords_fingerprint_settings">fingerprint</string>
<!-- List of synonyms for the auto rotate (rotate the virtual display when the device rotates) setting, used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_auto_rotate">rotate, flip, rotation, portrait, landscape, orientation, vertical, horizontal</string>
<!-- List of synonyms for the System Update (update the operating system) setting, used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_system_update_settings">upgrade, android</string>
<!-- List of synonyms for the Do Not Disturb setting, used to match in settings search. Do Not Disturb turns of notification volume, notifications, vibrations, among other things on the device. [CHAR LIMIT=NONE] -->
<string name="keywords_zen_mode_settings">dnd, schedule, notifications, block, silence, vibrate, sleep, work, focus, sound, mute, day, weekday, weekend, weeknight, event</string>
<!-- List of synonyms for the display timeout (how long until the screen turns off) setting, used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_screen_timeout">screen, lock time, timeout, lockscreen</string>
<!-- List of synonyms for Storage settings (everything related to storage on the device), used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_storage_settings">memory, data, delete, clear, free, space</string>
<!-- List of synonyms for the Bluetooth setting, used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_bluetooth_settings">connected, device, headphones, headset, speaker, wireless, pair, earbuds, music, media </string>
<!-- List of synonyms for the Wallpaper picker setting, used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_wallpaper">background, screen, lockscreen, theme</string>
<!-- List of synonyms for the Default Assist and Voice input setting, used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_assist_input">default, assistant</string>
<!-- List of synonyms for the Wallpaper picker setting, used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_default_browser">default, default browser</string>
<!-- List of synonyms for the default payment app setting, used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_default_payment_app">payment, default</string>
<!-- List of synonyms for the default links setting, used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_default_links">default</string>
<!-- List of synonyms for Ambient display setting (when the screen is off), used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_ambient_display">incoming notification</string>
<!-- List of synonyms for hotspot and tethering setting (where you share your wifi with other devices), used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_hotspot_tethering">usb tether, bluetooth tether, wifi hotspot</string>
<!-- List of synonyms for touch vibration setting (where you get a haptic response for touching things on the screen), used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_touch_vibration">haptics, vibrate, screen, sensitivity</string>
<!-- List of synonyms for ring and notification vibration setting (changes whether your phone vibrates when it rings), used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_ring_vibration">haptics, vibrate, phone, call, sensitivity</string>
<!-- NFC Wi-Fi pairing/setup strings-->
<!-- Write NFC tag for Wi-Fi pairing/setup title [CHAR_LIMIT=30]-->
@@ -6925,7 +7038,10 @@
<string name="touch_sounds_title">Touch sounds</string>
<!-- Sound: Other sounds: Title for the option enabling haptic feedback on touch. [CHAR LIMIT=30] -->
<string name="vibrate_on_touch_title">Vibrate on tap</string>
<string name="vibrate_on_touch_title">Touch vibration</string>
<!-- Sound: Other sounds: Preference summary to the option enabling haptic feedback on touch. -->
<string name="vibrate_on_touch_summary">Haptic feedback for tap, keyboard, and more</string>
<!-- Sound: Other sounds: Title for the option enabling dock audio media. [CHAR LIMIT=50] -->
<string name="dock_audio_media_title">Dock speaker plays</string>
@@ -7305,6 +7421,13 @@
<!-- Default Apps > Default notification assistant -->
<string name="default_notification_assistant">Notification assistant</string>
<!-- app summary of notification app list screen [CHAR LIMIT=100] -->
<string name="notifications_sent_daily">~<xliff:g id="number">%1$s</xliff:g> sent daily</string>
<!-- app summary of notification app list screen [CHAR LIMIT=100] -->
<string name="notifications_sent_weekly">~<xliff:g id="number">%1$s</xliff:g> sent weekly</string>
<!-- app summary of notification app list screen [CHAR LIMIT=100] -->
<string name="notifications_sent_never">Never</string>
<!-- Sound & notification > Advanced section: Title for managing notification listeners option. [CHAR LIMIT=30] -->
<string name="manage_notification_access_title">Notification access</string>
@@ -7861,11 +7984,13 @@
<string name="change_storage">Change storage</string>
<!-- Label for notification settings for an specific app [CHAR LIMIT=40] -->
<string name="notifications_label">App notifications</string>
<string name="notifications_label">Notifications</string>
<!-- App notification summary with notifications enabled [CHAR LIMIT=40] -->
<string name="notifications_enabled">On</string>
<!-- App notification summary with notifications enabled [CHAR LIMIT=40] -->
<string name="notifications_enabled_with_info">On / <xliff:g id="notifications_categories_off" example="3 categories turned off">%1$s</xliff:g> </string>
<!-- Label for showing apps with blocked notifications in list [CHAR LIMIT=30] -->
<string name="notifications_disabled">Everything turned off</string>
<string name="notifications_disabled">Off</string>
<!-- Label for showing apps with some blocked notifications in list [CHAR LIMIT=30] -->
<string name="notifications_partly_blocked"><xliff:g id="count" example="1">%1$d</xliff:g> of <xliff:g id="count" example="10">%2$d</xliff:g> categories turned off</string>
<!-- App notification summary with notifications silenced [CHAR LIMIT=40] -->
@@ -7883,6 +8008,11 @@
<!-- App notification summary channel divider-->
<string name="notification_summary_channel"><xliff:g id="channel_name">%1$s</xliff:g> \u2022 <xliff:g id="group_name">%2$s</xliff:g></string>
<!-- Permissions preference summary [CHAR LIMIT=40] -->
<plurals name="notifications_categories_off">
<item quantity="one"><xliff:g id="count" example="1">%d</xliff:g> category turned off</item>
<item quantity="other"><xliff:g id="count" example="10">%d</xliff:g> categories turned off</item>
</plurals>
<!-- Permissions preference summary [CHAR LIMIT=40] -->
<plurals name="permissions_summary">
@@ -8047,6 +8177,9 @@
<!-- Link to the apps page for app usage settings [CHAR LIMIT=45] -->
<string name="app_usage_preference">App usage preferences</string>
<!-- Link title to show stats about how much time user spent in an app [CHAR LIMIT=45] -->
<string name="time_spent_in_app_pref_title">Time spent in app</string>
<!-- Description of the usage access setting [CHAR LIMIT=NONE] -->
<string name="usage_access_description">Usage access allows an app to track what other apps you\u2019re using and how often, as well as your carrier, language settings, and other details.</string>
@@ -8551,8 +8684,8 @@
<!-- Summary of Android version info (when there is a pending upgrade available) [CHAR LIMIT=NONE] -->
<string name="android_version_pending_update_summary">Update available</string>
<!-- Title for dialog displayed when user clicks on a setting locked by an admin [CHAR LIMIT=30] -->
<string name="disabled_by_policy_title">Action not allowed</string>
<!-- Title for dialog displayed when user selects on a setting locked by an admin [CHAR LIMIT=30] -->
<string name="disabled_by_policy_title">Can\'t change this setting</string>
<!-- Title for dialog displayed to tell user that changing volume was disallowed by an admin [CHAR LIMIT=50] -->
<string name="disabled_by_policy_title_adjust_volume">Can\'t change volume</string>
<!-- Title for dialog displayed to tell user that outgoing calls were disabled by an admin [CHAR LIMIT=50] -->
@@ -8566,8 +8699,7 @@
<!-- Title for dialog displayed to tell user that turning off backups is disallowed by an admin [CHAR LIMIT=50] -->
<string name="disabled_by_policy_title_turn_off_backups">Can\'t turn off backups</string>
<!-- Shown when the user tries to change a settings locked by an admin [CHAR LIMIT=200] -->
<string name="default_admin_support_msg">This action is disabled. To learn more, contact your
organization\'s admin.</string>
<string name="default_admin_support_msg">If you have questions, contact your IT admin</string>
<!-- Shown in dialog to allow user to see more information about the device admin [CHAR LIMIT=30] -->
<string name="admin_support_more_info">More details</string>
<!-- Shown in admin details page to warn user about policies the admin can set in a work profile. [CHAR LIMIT=NONE] -->
@@ -8614,7 +8746,7 @@
<string name="condition_battery_title">Battery Saver is on</string>
<!-- Summary of condition that battery saver is on [CHAR LIMIT=NONE] -->
<string name="condition_battery_summary">Performance is reduced. Location services and background data are turned off.</string>
<string name="condition_battery_summary">Battery Saver turns off some device features and restricts apps</string>
<!-- Title of condition that cellular data is off [CHAR LIMIT=50] -->
<string name="condition_cellular_title">Mobile data is off</string>
@@ -8634,6 +8766,27 @@
<!-- Summary of condition that work mode is off [CHAR LIMIT=NONE] -->
<string name="condition_work_summary">Apps, background sync, and other features related to your work profile are turned off.</string>
<!-- Title of condition that indicates device is muted [CHAR LIMIT=50] -->
<string name="condition_device_muted_title" product="tablet">Device is muted</string>
<!-- Title of condition that indicates device is muted [CHAR LIMIT=50] -->
<string name="condition_device_muted_title" product="default">Phone is muted</string>
<!-- Summary of condition that indicates device is muted -->
<string name="condition_device_muted_summary">Calls and notifications will be muted</string>
<!-- Title of condition that indicates device is set to vibrate [CHAR LIMIT=50] -->
<string name="condition_device_vibrate_title" product="tablet">Device is set to vibrate</string>
<!-- Title of condition that indicates device is muted [CHAR LIMIT=50] -->
<string name="condition_device_vibrate_title" product="default">Phone is set to vibrate</string>
<!-- Summary of condition that indicates device is set to vibrate -->
<string name="condition_device_vibrate_summary" product="tablet">Calls and notifications will vibrate device</string>
<!-- Summary of condition that indicates device is set to vibrate -->
<string name="condition_device_vibrate_summary" product="default">Calls and notifications will vibrate phone</string>
<!-- Night display: Title for the night display option Suggestion (renamed "Night Light" with title caps). [CHAR LIMIT=46] -->
<string name="night_display_suggestion_title">Set Night Light schedule</string>
@@ -8697,9 +8850,12 @@
<!-- Title for Camera laser sensor switch [CHAR LIMIT=NONE] -->
<string name="camera_laser_sensor_switch">Camera Laser Sensor</string>
<!-- Name of the setting to disable the automatic update -->
<!-- Title of the setting to disable the automatic update -->
<string name="ota_disable_automatic_update">Automatic system updates</string>
<!-- Summary for the setting to disable the automatic update -->
<string name="ota_disable_automatic_update_summary">Apply updates when device restarts</string>
<!-- Label for category for data usage [CHAR LIMIT=30] -->
<string name="usage">Usage</string>
@@ -8801,7 +8957,7 @@
</plurals>
<!-- Data usage title text [CHAR LIMIT=30] -->
<string name="data_usage_title">Primary data</string>
<string name="data_usage_title">Current data</string>
<!-- Data usage remaining string [CHAR LIMIT=30] -->
<string name="data_used"><xliff:g name="bytes" example="2 GB">^1</xliff:g> used</string>
@@ -8857,6 +9013,9 @@
<!-- Summary for the Data Saver feature being off [CHAR LIMIT=NONE] -->
<string name="data_saver_off">Off</string>
<!-- Switch label to enable the Data Saver feature [CHAR LIMIT=NONE] -->
<string name="data_saver_switch_title">Use Data Saver</string>
<!-- Title for switch to allow app unrestricted data usage [CHAR LIMIT=30] -->
<string name="unrestricted_app_title">Unrestricted data usage</string>
@@ -9331,6 +9490,8 @@
<item quantity="one"><xliff:g id="count">%d</xliff:g> attempt</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> attempts</item>
</plurals>
<!-- List item in a work device's settings. This text lets the user know that their IT administrator requires their device's data to be backed up. The user can't change this setting. [CHAR LIMIT=NONE] -->
<string name="enterprise_privacy_backups_enabled">This device\'s data is being backed up</string>
<!-- Message indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=NONE] -->
<string name="do_disclosure_generic">This device is managed by your organization.</string>
<!-- Message indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=NONE] -->
@@ -9507,6 +9668,27 @@
show both names, with the directory name wrapped in parenthesis -->
<string name="directory_on_volume"><xliff:g id="volume" example="SD Card">%1$s</xliff:g> (<xliff:g id="directory" example="Movies">%2$s</xliff:g>)</string>
<!-- Slices Strings -->
<!-- Summary text on a card explaining that a setting does not exist / is not supported on the device [CHAR_LIMIT=NONE]-->
<string name="unsupported_setting_summary" product="default">Setting isnt supported on this phone</string>
<!-- Summary text on a card explaining that a setting does not exist / is not supported on the device [CHAR_LIMIT=NONE]-->
<string name="unsupported_setting_summary" product="tablet">Setting isnt supported on this tablet</string>
<!-- Summary text on a card explaining that a setting does not exist / is not supported on the device [CHAR_LIMIT=NONE]-->
<string name="unsupported_setting_summary" product="device">Setting isnt supported on this device</string>
<!-- Summary text on a card explaining that a setting cannot be changed by the current user. [CHAR_LIMIT=NONE] -->
<string name="disabled_for_user_setting_summary">Setting cant be changed by current user</string>
<!-- Summary text on a card explaining a setting cannot be changed right now because it needs another setting to be changed. [CHAR_LIMIT=NONE] -->
<string name="disabled_dependent_setting_summary">Depends on another setting</string>
<!-- Summary text on a card explaining a setting cannot be changed right now, but we don't know the reason. [CHAR_LIMIT=NONE] -->
<string name="unknown_unavailability_setting_summary">Setting unavailable</string>
<!-- Account type associated with the backup account. Empty for AOSP. [DO NOT TRANSLATE] -->
<string name="account_type" translatable="false"></string>
<!-- Package to target for Account credential confirmation. This will allow users to
@@ -9518,12 +9700,6 @@
[DO NOT TRANSLATE] -->
<string name="account_confirmation_class" translatable="false"></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]-->
@@ -9575,7 +9751,27 @@
<!-- Summary for battery Suggestion. [CHAR LIMIT=55] -->
<string name="battery_suggestion_summary"></string>
<!-- Title for prevent ringing gesture screen -->
<string name="gesture_prevent_ringing_screen_title">Prevent ringing</string>
<!-- Title for prevent ringing setting -->
<string name="gesture_prevent_ringing_title">Press Power &amp; Volume Up together</string>
<!-- Option for prevent ringing setting -->
<string name="prevent_ringing_option_vibrate">Vibrate</string>
<!-- Option for prevent ringing setting -->
<string name="prevent_ringing_option_mute">Mute</string>
<!-- Option for prevent ringing setting -->
<string name="prevent_ringing_option_none">Do nothing</string>
<!-- Summary for prevent ringing setting -->
<string name="prevent_ringing_option_vibrate_summary">Vibrate all calls and notifications</string>
<!-- Summary for prevent ringing setting -->
<string name="prevent_ringing_option_mute_summary">Mute all calls and notifications</string>
<!-- Summary for prevent ringing setting -->
<string name="prevent_ringing_option_none_summary">Do nothing</string>
<!-- Title for detail page of wifi network [CHAR LIMIT=30] -->
<string name="pref_title_network_details">Network details</string>
<!-- Warning text about the visibility of device name. [CHAR LIMIT=NONE] -->
<string name="about_phone_device_name_warning">Your device name is visible to apps on your phone. It may also be seen by other people when you connect to Bluetooth devices or set up a Wi-Fi hotspot.</string>
</resources>

View File

@@ -53,6 +53,7 @@
<item name="preferenceTheme">@style/PreferenceTheme.SetupWizard</item>
<item name="*android:lockPatternStyle">@style/LockPatternStyle.Setup</item>
<item name="*android:colorError">@color/glif_error_color</item>
</style>
<style name="GlifV2Theme" parent="SuwThemeGlifV2">
@@ -88,6 +89,7 @@
<item name="preferenceTheme">@style/PreferenceTheme.SetupWizard</item>
<item name="*android:lockPatternStyle">@style/LockPatternStyle.Setup</item>
<item name="*android:colorError">@color/glif_error_color</item>
</style>
<style name="GlifV3Theme" parent="SuwThemeGlifV3">
@@ -123,6 +125,7 @@
<item name="preferenceTheme">@style/PreferenceTheme.SetupWizard</item>
<item name="*android:lockPatternStyle">@style/LockPatternStyle.Setup</item>
<item name="*android:colorError">@color/glif_error_color</item>
</style>
<style name="SetupWizardTheme.Transparent" parent="GlifTheme">

View File

@@ -17,6 +17,7 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="accessibility_settings_vibration_screen"
android:title="@string/accessibility_vibration_settings_title">
@@ -24,11 +25,13 @@
android:fragment="com.android.settings.accessibility.NotificationVibrationPreferenceFragment"
android:key="notification_vibration_preference_screen"
android:title="@string/accessibility_notification_vibration_title"
settings:keywords="@string/keywords_ring_vibration"
app:controller="com.android.settings.accessibility.NotificationVibrationIntensityPreferenceController" />
<Preference
android:fragment="com.android.settings.accessibility.TouchVibrationPreferenceFragment"
android:key="touch_vibration_preference_screen"
android:title="@string/accessibility_touch_vibration_title"
settings:keywords="@string/keywords_touch_vibration"
app:controller="com.android.settings.accessibility.HapticFeedbackIntensityPreferenceController" />
</PreferenceScreen>

View File

@@ -44,7 +44,8 @@
</PreferenceCategory>
<PreferenceCategory
android:key="ambient_display_category_notification">
android:key="ambient_display_category_notification"
android:layout="@layout/preference_category_no_label">
<SwitchPreference
android:key="ambient_display_notification"

View File

@@ -47,7 +47,9 @@
</PreferenceCategory>
<PreferenceCategory
android:key="app_data_usage_settings_category">
android:key="app_data_usage_settings_category"
android:layout="@layout/preference_category_no_label">
<Preference
android:key="app_settings"
android:title="@string/data_usage_app_settings" />

View File

@@ -24,12 +24,14 @@
<com.android.settings.widget.AppPreference
android:key="assist_and_voice_input"
android:title="@string/assist_and_voice_input_title"
android:fragment="com.android.settings.applications.assist.ManageAssist" />
android:fragment="com.android.settings.applications.assist.ManageAssist"
settings:keywords="@string/keywords_assist_input"/>
<com.android.settings.widget.AppPreference
android:key="default_browser"
android:title="@string/default_browser_title"
android:fragment="com.android.settings.applications.defaultapps.DefaultBrowserPicker">
android:fragment="com.android.settings.applications.defaultapps.DefaultBrowserPicker"
settings:keywords="@string/keywords_default_browser">
<extra android:name="for_work" android:value="false" />
</com.android.settings.widget.AppPreference>
@@ -55,7 +57,8 @@
android:key="default_payment_app"
android:title="@string/nfc_payment_settings_title"
android:summary="@string/summary_placeholder"
android:fragment="com.android.settings.nfc.PaymentSettings" />
android:fragment="com.android.settings.nfc.PaymentSettings"
settings:keywords="@string/keywords_default_payment_app"/>
<com.android.settings.widget.AppPreference
android:key="default_emergency_app"
@@ -73,7 +76,8 @@
<com.android.settings.widget.AppPreference
android:key="domain_urls"
android:title="@string/domain_urls_title"
android:fragment="com.android.settings.applications.ManageDomainUrls" />
android:fragment="com.android.settings.applications.ManageDomainUrls"
settings:keywords="@string/keywords_default_links"/>
<com.android.settings.widget.WorkOnlyCategory
android:key="work_app_defaults"

View File

@@ -25,13 +25,13 @@
android:key="header_view"
android:layout="@layout/settings_entity_header"
android:selectable="false"
android:order="-10000"/>
android:order="-10000" />
<com.android.settings.applications.LayoutPreference
android:key="instant_app_buttons"
android:layout="@layout/instant_app_buttons"
android:selectable="false"
android:order="-9999"/>
android:order="-9999" />
<com.android.settings.widget.ActionButtonPreference
android:key="action_buttons"
@@ -39,7 +39,7 @@
<Preference
android:key="notification_settings"
android:title="@string/notifications_label"/>
android:title="@string/notifications_label" />
<com.android.settings.widget.FixedLineSummaryPreference
android:key="permission_settings"
@@ -50,7 +50,7 @@
<Preference
android:key="storage_settings"
android:title="@string/storage_settings"
android:summary="@string/summary_placeholder"/>
android:summary="@string/summary_placeholder" />
<com.android.settings.applications.AppDomainsPreference
android:key="instant_app_launch_supported_domain_urls"
@@ -60,24 +60,29 @@
<Preference
android:key="data_settings"
android:title="@string/data_usage_summary_title"
android:summary="@string/summary_placeholder"/>
android:summary="@string/summary_placeholder" />
<Preference
android:key="time_spent_in_app"
android:title="@string/time_spent_in_app_pref_title"
app:controller="com.android.settings.applications.appinfo.TimeSpentInAppPreferenceController" />
<Preference
android:key="battery"
android:title="@string/power_usage_summary_title"
android:summary="@string/summary_placeholder"/>
android:summary="@string/summary_placeholder" />
<Preference
android:key="preferred_settings"
android:title="@string/launch_by_default"
android:summary="@string/summary_placeholder"
android:selectable="true"/>
android:selectable="true" />
<Preference
android:key="memory"
android:title="@string/memory_settings_title"
android:summary="@string/summary_placeholder"
android:enabled="false"/>
android:enabled="false" />
<!-- Default apps shortcuts -->
<Preference
@@ -146,6 +151,6 @@
<Preference
android:key="app_version"
android:selectable="false"
android:order="9999"/>
android:order="9999" />
</PreferenceScreen>

View File

@@ -69,14 +69,13 @@
<!-- See all apps button -->
<Preference
android:title="@string/notifications_title"
android:key="all_notifications"
android:title="@string/notifications_title"
android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
android:order="22">
<intent
android:action="android.intent.action.MAIN"
android:targetPackage="com.android.settings"
android:targetClass="com.android.settings.Settings$ManageApplicationsActivity">
</intent>
<extra
android:name="classname"
android:value="com.android.settings.Settings$NotificationAppListActivity" />
</Preference>
</PreferenceCategory>

View File

@@ -20,14 +20,15 @@
android:key="connected_devices_advanced_screen"
android:title="@string/connected_device_connections_title">
<SwitchPreference
android:key="toggle_bluetooth_switch"
android:title="@string/bluetooth_settings_title"
android:icon="@drawable/ic_settings_bluetooth"
android:summary="@string/bluetooth_pref_summary"
android:order="-7"
settings:controller="com.android.settings.bluetooth.BluetoothSwitchPreferenceController"
settings:platform_slice="true"/>
<com.android.settingslib.RestrictedSwitchPreference
android:key="toggle_bluetooth_switch"
android:title="@string/bluetooth_settings_title"
android:icon="@drawable/ic_settings_bluetooth"
android:summary="@string/bluetooth_pref_summary"
android:order="-7"
settings:controller="com.android.settings.bluetooth.BluetoothSwitchPreferenceController"
settings:userRestriction="no_bluetooth"
settings:platform_slice="true"/>
<SwitchPreference
android:key="toggle_nfc"

View File

@@ -22,7 +22,8 @@
settings:keywords="@string/keywords_date_and_time">
<PreferenceCategory
android:key="date_time_preference_category">
android:key="date_time_preference_category"
android:layout="@layout/preference_category_no_label">
<com.android.settingslib.RestrictedSwitchPreference
android:key="auto_time"
android:title="@string/date_time_auto"
@@ -46,7 +47,8 @@
</PreferenceCategory>
<PreferenceCategory
android:key="time_zone_preference_category">
android:key="time_zone_preference_category"
android:layout="@layout/preference_category_no_label">
<com.android.settingslib.RestrictedSwitchPreference
android:key="auto_zone"
android:title="@string/zone_auto"
@@ -63,7 +65,8 @@
</PreferenceCategory>
<PreferenceCategory
android:key="time_format_preference_category">
android:key="time_format_preference_category"
android:layout="@layout/preference_category_no_label">
<SwitchPreference
android:key="auto_24hour"
android:title="@string/date_time_24hour_auto"

View File

@@ -104,7 +104,8 @@
<SwitchPreference
android:key="ota_disable_automatic_update"
android:title="@string/ota_disable_automatic_update" />
android:title="@string/ota_disable_automatic_update"
android:summary="@string/ota_disable_automatic_update_summary" />
<Preference
android:key="demo_mode"

View File

@@ -65,11 +65,13 @@
android:title="@string/screen_timeout"
android:summary="@string/summary_placeholder"
android:entries="@array/screen_timeout_entries"
android:entryValues="@array/screen_timeout_values" />
android:entryValues="@array/screen_timeout_values"
settings:keywords="@string/keywords_screen_timeout"/>
<SwitchPreference
android:key="auto_rotate"
android:title="@string/accelerometer_title" />
android:title="@string/accelerometer_title"
settings:keywords="@string/keywords_auto_rotate"/>
<Preference
android:key="color_mode"
@@ -99,7 +101,6 @@
android:title="@string/screensaver_settings_title"
android:fragment="com.android.settings.dream.DreamSettings" />
<!-- Cross-listed item, if you change this, also change it in power_usage_summary.xml -->
<com.android.settingslib.RestrictedPreference
android:key="ambient_display"
android:title="@string/ambient_display_screen_title"

View File

@@ -50,4 +50,9 @@
android:title="@string/ambient_display_pickup_title"
android:fragment="com.android.settings.gestures.PickupGestureSettings" />
<Preference
android:key="gesture_prevent_ringing_summary"
android:title="@string/gesture_prevent_ringing_screen_title"
android:fragment="com.android.settings.gestures.PreventRingingGestureSettings" />
</PreferenceScreen>

View File

@@ -67,7 +67,8 @@
</PreferenceCategory>
<PreferenceCategory
android:key="pointer_and_tts_category">
android:key="pointer_and_tts_category"
android:layout="@layout/preference_category_no_label">
<com.android.settings.PointerSpeedPreference
android:key="pointer_speed"

View File

@@ -19,7 +19,7 @@
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"
android:title="@string/about_settings"
settings:initialExpandedChildrenCount="7">
<com.android.settings.applications.LayoutPreference

View File

@@ -55,6 +55,7 @@
android:icon="@drawable/ic_wifi_tethering"
android:order="-5"
android:summary="@string/summary_placeholder"
settings:keywords="@string/keywords_hotspot_tethering"
settings:userRestriction="no_config_tethering"
settings:useAdminDisabledSummary="true" />

View File

@@ -16,8 +16,10 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/night_display_title"
android:key="night_display_title">
android:key="night_display_title"
settings:keywords="@string/keywords_display_night_display">
<DropDownPreference
android:key="night_display_auto_mode"

View File

@@ -47,7 +47,8 @@
<!-- Vibrate on touch -->
<SwitchPreference
android:key="vibrate_on_touch"
android:title="@string/vibrate_on_touch_title" />
android:title="@string/vibrate_on_touch_title"
android:summary="@string/vibrate_on_touch_summary" />
<!-- Dock speaker plays -->
<DropDownPreference

View File

@@ -24,48 +24,41 @@
<com.android.settings.applications.LayoutPreference
android:key="battery_header"
android:selectable="false"
android:layout="@layout/battery_header"/>
android:layout="@layout/battery_header" />
<PreferenceCategory
android:key="battery_tip"
android:layout="@layout/preference_category_no_title"/>
android:layout="@layout/preference_category_no_title" />
<PreferenceCategory
android:key="power_management">
<Preference
android:fragment="com.android.settings.fuelgauge.batterysaver.BatterySaverSettings"
android:key="battery_saver_summary"
android:title="@string/battery_saver"
settings:controller="com.android.settings.fuelgauge.BatterySaverController"
settings:platform_slice="true"
settings:allowDividerAbove="true" />
<Preference
android:fragment="com.android.settings.fuelgauge.batterysaver.BatterySaverSettings"
android:key="battery_saver_summary"
android:title="@string/battery_saver"
settings:controller="com.android.settings.fuelgauge.BatterySaverController"
settings:platform_slice="true"/>
<Preference
android:fragment="com.android.settings.fuelgauge.SmartBatterySettings"
android:key="smart_battery_manager"
android:title="@string/smart_battery_manager_title"
settings:controller="com.android.settings.fuelgauge.batterytip.BatteryManagerPreferenceController" />
<Preference
android:fragment="com.android.settings.fuelgauge.SmartBatterySettings"
android:key="smart_battery_manager"
android:title="@string/smart_battery_manager_title"
settings:controller="com.android.settings.fuelgauge.batterytip.BatteryManagerPreferenceController"/>
<SwitchPreference
android:key="battery_percentage"
android:title="@string/battery_percentage"
android:summary="@string/battery_percentage_description" />
<SwitchPreference
android:key="battery_percentage"
android:title="@string/battery_percentage"
android:summary="@string/battery_percentage_description"/>
</PreferenceCategory>
<com.android.settings.fuelgauge.PowerGaugePreference
android:key="last_full_charge"
android:title="@string/battery_last_full_charge"
android:selectable="false"
settings:allowDividerAbove="true" />
<PreferenceCategory
android:key="device_usage_list">
<com.android.settings.fuelgauge.PowerGaugePreference
android:key="last_full_charge"
android:title="@string/battery_last_full_charge"
android:selectable="false"/>
<com.android.settings.fuelgauge.PowerGaugePreference
android:key="screen_usage"
android:title="@string/device_screen_usage"
android:selectable="false"/>
</PreferenceCategory>
<com.android.settings.fuelgauge.PowerGaugePreference
android:key="screen_usage"
android:title="@string/device_screen_usage"
android:selectable="false" />
</PreferenceScreen>

View File

@@ -0,0 +1,35 @@
<?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:app="http://schemas.android.com/apk/res-auto"
android:key="gesture_prevent_ringing_screen"
android:title="@string/gesture_prevent_ringing_screen_title">
<!-- TODO: Add video preference when it exists -->
<com.android.settings.widget.VideoPreference
android:key="gesture_prevent_ringing_video" />
<ListPreference
android:key="gesture_prevent_ringing"
android:title="@string/gesture_prevent_ringing_title"
android:entries="@array/gesture_prevent_ringing_entries"
android:entryValues="@array/gesture_prevent_ringing_values"
app:keywords="@string/keywords_gesture" />
</PreferenceScreen>

View File

@@ -129,7 +129,8 @@
<!-- Vibrate on touch -->
<SwitchPreference
android:key="vibrate_on_touch"
android:title="@string/vibrate_on_touch_title" />
android:title="@string/vibrate_on_touch_title"
android:summary="@string/vibrate_on_touch_summary" />
<!-- Dock speaker plays -->
<DropDownPreference

View File

@@ -56,6 +56,7 @@
android:summary="@string/summary_placeholder"
android:icon="@drawable/ic_system_update"
android:order="-30"
settings:keywords="@string/keywords_system_update_settings"
settings:controller="com.android.settings.system.SystemUpdatePreferenceController">
<intent android:action="android.settings.SYSTEM_UPDATE_SETTINGS" />
</Preference>

View File

@@ -20,11 +20,17 @@
android:title="@string/wifi_settings"
settings:keywords="@string/keywords_wifi">
<PreferenceCategory android:key="connected_access_point" />
<PreferenceCategory
android:key="connected_access_point"
android:layout="@layout/preference_category_no_label"/>
<PreferenceCategory android:key="access_points"/>
<PreferenceCategory
android:key="access_points"
android:layout="@layout/preference_category_no_label"/>
<PreferenceCategory android:key="additional_settings">
<PreferenceCategory
android:key="additional_settings"
android:layout="@layout/preference_category_no_label">
<Preference
android:key="configure_settings"
android:title="@string/wifi_configure_settings_preference_title"

View File

@@ -15,9 +15,12 @@
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="zen_mode_settings"
android:title="@string/zen_mode_settings_title">
android:title="@string/zen_mode_settings_title"
settings:keywords="@string/keywords_zen_mode_settings">
<!-- What to block (effects) -->
<Preference

View File

@@ -124,7 +124,6 @@ public class DisplaySettings extends DashboardFragment {
List<String> keys = super.getNonIndexableKeys(context);
keys.add(KEY_DISPLAY_SIZE);
keys.add(WallpaperPreferenceController.KEY_WALLPAPER);
keys.add(KEY_AMBIENT_DISPLAY);
keys.add(KEY_NIGHT_DISPLAY);
return keys;
}

View File

@@ -1,71 +0,0 @@
/*
* Copyright (C) 2012 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;
import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.EditText;
import com.android.settingslib.CustomEditTextPreference;
public class SelectableEditTextPreference extends CustomEditTextPreference {
private int mSelectionMode;
public static final int SELECTION_CURSOR_END = 0;
public static final int SELECTION_CURSOR_START = 1;
public static final int SELECTION_SELECT_ALL = 2;
public SelectableEditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* Sets the selection mode for the text when it shows up in the dialog
* @hide
* @param selectionMode can be SELECTION_CURSOR_START, SELECTION_CURSOR_END or
* SELECTION_SELECT_ALL. Default is SELECTION_CURSOR_END
*/
public void setInitialSelectionMode(int selectionMode) {
mSelectionMode = selectionMode;
}
@Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
EditText editText = getEditText();
// Set the selection based on the mSelectionMode
int length = editText.getText() != null ? editText.getText().length() : 0;
if (!TextUtils.isEmpty(editText.getText())) {
switch (mSelectionMode) {
case SELECTION_CURSOR_END:
editText.setSelection(length);
break;
case SELECTION_CURSOR_START:
editText.setSelection(0);
break;
case SELECTION_SELECT_ALL:
editText.setSelection(0, length);
break;
}
}
}
}

View File

@@ -106,6 +106,7 @@ public class Settings extends SettingsActivity {
public static class ZenModeEventRuleSettingsActivity extends SettingsActivity { /* empty */ }
public static class SoundSettingsActivity extends SettingsActivity { /* empty */ }
public static class ConfigureNotificationSettingsActivity extends SettingsActivity { /* empty */ }
public static class NotificationAppListActivity extends SettingsActivity { /* empty */ }
public static class AppNotificationSettingsActivity extends SettingsActivity { /* empty */ }
public static class ChannelNotificationSettingsActivity extends SettingsActivity { /* empty */ }
public static class ChannelGroupNotificationSettingsActivity extends SettingsActivity { /* empty */ }

View File

@@ -63,7 +63,9 @@ import com.android.settings.core.SubSettingLauncher;
import com.android.settings.core.gateway.SettingsGateway;
import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.dashboard.DashboardSummary;
import com.android.settings.development.DevelopmentSettingsDashboardFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.DeviceIndexFeatureProvider;
import com.android.settings.wfd.WifiDisplaySettings;
import com.android.settings.widget.SwitchBar;
import com.android.settingslib.core.instrumentation.Instrumentable;
@@ -71,6 +73,7 @@ import com.android.settingslib.core.instrumentation.SharedPreferencesLogger;
import com.android.settingslib.development.DevelopmentSettingsEnabler;
import com.android.settingslib.drawer.DashboardCategory;
import com.android.settingslib.drawer.SettingsDrawerActivity;
import com.android.settingslib.utils.ThreadUtils;
import java.util.ArrayList;
import java.util.List;
@@ -488,6 +491,7 @@ public class SettingsActivity extends SettingsDrawerActivity
registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
updateTilesList();
updateDeviceIndex();
}
@Override
@@ -608,6 +612,14 @@ public class SettingsActivity extends SettingsDrawerActivity
});
}
private void updateDeviceIndex() {
DeviceIndexFeatureProvider indexProvider = FeatureFactory.getFactory(
this).getDeviceIndexFeatureProvider();
ThreadUtils.postOnBackgroundThread(
() -> indexProvider.updateIndex(SettingsActivity.this, false /* force */));
}
private void doUpdateTilesList() {
PackageManager pm = getPackageManager();
final UserManager um = UserManager.get(this);
@@ -686,10 +698,10 @@ public class SettingsActivity extends SettingsDrawerActivity
final boolean showDev = DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(this)
&& !Utils.isMonkeyRunning();
final boolean isAdminOrDemo = um.isAdminUser() || um.isDemoUser();
somethingChanged = setTileEnabled(new ComponentName(packageName,
Settings.DevelopmentSettingsDashboardActivity.class.getName()),
showDev, isAdmin)
showDev, isAdminOrDemo)
|| somethingChanged;
// Enable/disable backup settings depending on whether the user is admin.
@@ -724,10 +736,11 @@ public class SettingsActivity extends SettingsDrawerActivity
final int tileCount = category.getTilesCount();
for (int i = 0; i < tileCount; i++) {
final ComponentName component = category.getTile(i).intent.getComponent();
final String name = component.getClassName();
final boolean isEnabledForRestricted = ArrayUtils.contains(
SettingsGateway.SETTINGS_FOR_RESTRICTED, name);
SettingsGateway.SETTINGS_FOR_RESTRICTED, name) || (isAdminOrDemo
&& Settings.DevelopmentSettingsDashboardActivity.class.getName()
.equals(name));
if (packageName.equals(component.getPackageName())
&& !isEnabledForRestricted) {
somethingChanged = setTileEnabled(component, false, isAdmin)

View File

@@ -15,70 +15,191 @@
*/
package com.android.settings.applications;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.service.notification.NotificationListenerService;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.notification.NotificationBackend.AppRow;
import com.android.settings.R;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.ApplicationsState.AppFilter;
import com.android.settingslib.utils.StringUtil;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Map;
/**
* Connects the info provided by ApplicationsState and the NotificationBackend.
* Connects the info provided by ApplicationsState and UsageStatsManager.
* Also provides app filters that can use the notification data.
*/
public class AppStateNotificationBridge extends AppStateBaseBridge {
private final NotificationBackend mNotifBackend;
private final PackageManager mPm;
private final Context mContext;
private UsageStatsManager mUsageStatsManager;
private static final int DAYS_TO_CHECK = 7;
public AppStateNotificationBridge(Context context, ApplicationsState appState,
Callback callback, NotificationBackend notifBackend) {
public AppStateNotificationBridge(ApplicationsState appState,
Callback callback, UsageStatsManager usageStatsManager) {
super(appState, callback);
mContext = context;
mPm = mContext.getPackageManager();
mNotifBackend = notifBackend;
mUsageStatsManager = usageStatsManager;
}
@Override
protected void loadAllExtraInfo() {
ArrayList<AppEntry> apps = mAppSession.getAllApps();
final int N = apps.size();
for (int i = 0; i < N; i++) {
AppEntry app = apps.get(i);
app.extraInfo = mNotifBackend.loadAppRow(mContext, mPm, app.info);
if (apps == null) return;
final Map<String, NotificationsSentState> map = getAggregatedUsageEvents();
for (AppEntry entry : apps) {
NotificationsSentState stats = map.get(entry.info.packageName);
calculateAvgSentCounts(stats);
entry.extraInfo = stats;
}
}
@Override
protected void updateExtraInfo(AppEntry app, String pkg, int uid) {
app.extraInfo = mNotifBackend.loadAppRow(mContext, mPm, app.info);
protected void updateExtraInfo(AppEntry entry, String pkg, int uid) {
Map<String, NotificationsSentState> map = getAggregatedUsageEvents();
NotificationsSentState stats = map.get(entry.info.packageName);
calculateAvgSentCounts(stats);
entry.extraInfo = stats;
}
public static final AppFilter FILTER_APP_NOTIFICATION_BLOCKED = new AppFilter() {
public static CharSequence getSummary(Context context, NotificationsSentState state,
boolean sortByRecency) {
if (sortByRecency) {
if (state.lastSent == 0) {
return context.getString(R.string.notifications_sent_never);
}
return StringUtil.formatRelativeTime(
context, System.currentTimeMillis() - state.lastSent, true);
} else {
if (state.avgSentWeekly > 0) {
return context.getString(R.string.notifications_sent_weekly, state.avgSentWeekly);
}
return context.getString(R.string.notifications_sent_daily, state.avgSentDaily);
}
}
private void calculateAvgSentCounts(NotificationsSentState stats) {
if (stats != null) {
stats.avgSentDaily = Math.round((float) stats.sentCount / DAYS_TO_CHECK);
if (stats.sentCount < DAYS_TO_CHECK) {
stats.avgSentWeekly = stats.sentCount;
}
}
}
protected Map<String, NotificationsSentState> getAggregatedUsageEvents() {
ArrayMap<String, NotificationsSentState> aggregatedStats = new ArrayMap<>();
long now = System.currentTimeMillis();
long startTime = now - (DateUtils.DAY_IN_MILLIS * DAYS_TO_CHECK);
UsageEvents events = mUsageStatsManager.queryEvents(startTime, now);
if (events != null) {
UsageEvents.Event event = new UsageEvents.Event();
while (events.hasNextEvent()) {
events.getNextEvent(event);
NotificationsSentState stats = aggregatedStats.get(event.getPackageName());
if (stats == null) {
stats = new NotificationsSentState();
aggregatedStats.put(event.getPackageName(), stats);
}
if (event.getEventType() == UsageEvents.Event.NOTIFICATION_INTERRUPTION) {
if (event.getTimeStamp() > stats.lastSent) {
stats.lastSent = event.getTimeStamp();
}
stats.sentCount++;
}
}
}
return aggregatedStats;
}
private static NotificationsSentState getNotificationsSentState(AppEntry entry) {
if (entry == null || entry.extraInfo == null) {
return null;
}
if (entry.extraInfo instanceof NotificationsSentState) {
return (NotificationsSentState) entry.extraInfo;
}
return null;
}
public static final AppFilter FILTER_APP_NOTIFICATION_RECENCY = new AppFilter() {
@Override
public void init() {
}
@Override
public boolean filterApp(AppEntry info) {
if (info == null || info.extraInfo == null) {
return false;
}
if (info.extraInfo instanceof AppRow) {
AppRow row = (AppRow) info.extraInfo;
return row.banned;
NotificationsSentState state = getNotificationsSentState(info);
if (state != null) {
return state.lastSent != 0;
}
return false;
}
};
public static final AppFilter FILTER_APP_NOTIFICATION_FREQUENCY = new AppFilter() {
@Override
public void init() {
}
@Override
public boolean filterApp(AppEntry info) {
NotificationsSentState state = getNotificationsSentState(info);
if (state != null) {
return state.sentCount != 0;
}
return false;
}
};
public static final Comparator<AppEntry> RECENT_NOTIFICATION_COMPARATOR
= new Comparator<AppEntry>() {
@Override
public int compare(AppEntry object1, AppEntry object2) {
NotificationsSentState state1 = getNotificationsSentState(object1);
NotificationsSentState state2 = getNotificationsSentState(object2);
if (state1 == null && state2 != null) return -1;
if (state1 != null && state2 == null) return 1;
if (state1 != null && state2 != null) {
if (state1.lastSent < state2.lastSent) return 1;
if (state1.lastSent > state2.lastSent) return -1;
}
return ApplicationsState.ALPHA_COMPARATOR.compare(object1, object2);
}
};
public static final Comparator<AppEntry> FREQUENCY_NOTIFICATION_COMPARATOR
= new Comparator<AppEntry>() {
@Override
public int compare(AppEntry object1, AppEntry object2) {
NotificationsSentState state1 = getNotificationsSentState(object1);
NotificationsSentState state2 = getNotificationsSentState(object2);
if (state1 == null && state2 != null) return -1;
if (state1 != null && state2 == null) return 1;
if (state1 != null && state2 != null) {
if (state1.sentCount < state2.sentCount) return 1;
if (state1.sentCount > state2.sentCount) return -1;
}
return ApplicationsState.ALPHA_COMPARATOR.compare(object1, object2);
}
};
/**
* NotificationsSentState contains how often an app sends notifications and how recently it sent
* one.
*/
public static class NotificationsSentState {
public int avgSentDaily = 0;
public int avgSentWeekly = 0;
public long lastSent = 0;
public int sentCount = 0;
}
}

View File

@@ -45,20 +45,16 @@ import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.DeviceAdminAdd;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.applications.manageapplications.ManageApplications;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.widget.EntityHeaderController;
import com.android.settings.widget.PreferenceCategoryController;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.RestrictedLockUtils;
@@ -157,7 +153,12 @@ public class AppInfoDashboardFragment extends DashboardFragment
== PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
}
/** Called when the activity is first created. */
@Override
public void onAttach(Context context) {
super.onAttach(context);
use(TimeSpentInAppPreferenceController.class).setPackageName(getPackageName());
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -191,9 +192,10 @@ public class AppInfoDashboardFragment extends DashboardFragment
@Override
public void onResume() {
super.onResume();
mAppsControlDisallowedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(getActivity(),
final Activity activity = getActivity();
mAppsControlDisallowedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(activity,
UserManager.DISALLOW_APPS_CONTROL, mUserId);
mAppsControlDisallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(getActivity(),
mAppsControlDisallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(activity,
UserManager.DISALLOW_APPS_CONTROL, mUserId);
if (!refreshUi()) {
@@ -300,7 +302,7 @@ public class AppInfoDashboardFragment extends DashboardFragment
*
* @return true if packageInfo is available.
*/
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
@VisibleForTesting
boolean ensurePackageInfoAvailable(Activity activity) {
if (mPackageInfo == null) {
mFinishing = true;

View File

@@ -0,0 +1,75 @@
/*
* 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.applications.appinfo;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
import com.android.settings.core.BasePreferenceController;
import java.util.List;
public class TimeSpentInAppPreferenceController extends BasePreferenceController {
@VisibleForTesting
static final Intent SEE_TIME_IN_APP_TEMPLATE =
new Intent("com.android.settings.action.TIME_SPENT_IN_APP");
private final PackageManager mPackageManager;
private Intent mIntent;
private String mPackageName;
public TimeSpentInAppPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mPackageManager = context.getPackageManager();
}
public void setPackageName(String packageName) {
mPackageName = packageName;
mIntent = new Intent(SEE_TIME_IN_APP_TEMPLATE)
.putExtra(Intent.EXTRA_PACKAGE_NAME, mPackageName);
}
@Override
public int getAvailabilityStatus() {
if (TextUtils.isEmpty(mPackageName)) {
return DISABLED_UNSUPPORTED;
}
final List<ResolveInfo> resolved = mPackageManager.queryIntentActivities(mIntent,
0 /* flags */);
if (resolved == null || resolved.isEmpty()) {
return DISABLED_UNSUPPORTED;
}
return AVAILABLE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
final Preference pref = screen.findPreference(getPreferenceKey());
if (pref != null) {
pref.setIntent(mIntent);
}
}
}

View File

@@ -41,7 +41,8 @@ public class AppFilterRegistry {
FILTER_APPS_ENABLED,
FILTER_APPS_INSTANT,
FILTER_APPS_DISABLED,
FILTER_APPS_BLOCKED,
FILTER_APPS_RECENT,
FILTER_APPS_FREQUENT,
FILTER_APPS_PERSONAL,
FILTER_APPS_WORK,
FILTER_APPS_USAGE_ACCESS,
@@ -60,23 +61,24 @@ public class AppFilterRegistry {
public static final int FILTER_APPS_ENABLED = 3;
public static final int FILTER_APPS_INSTANT = 4;
public static final int FILTER_APPS_DISABLED = 5;
public static final int FILTER_APPS_BLOCKED = 6;
public static final int FILTER_APPS_PERSONAL = 7;
public static final int FILTER_APPS_WORK = 8;
public static final int FILTER_APPS_USAGE_ACCESS = 9;
public static final int FILTER_APPS_WITH_OVERLAY = 10;
public static final int FILTER_APPS_WRITE_SETTINGS = 11;
public static final int FILTER_APPS_INSTALL_SOURCES = 12;
public static final int FILTER_APP_HAS_DIRECTORY_ACCESS = 13;
public static final int FILTER_APP_CAN_CHANGE_WIFI_STATE = 14;
// Next id: 15
public static final int FILTER_APPS_RECENT = 6;
public static final int FILTER_APPS_FREQUENT = 7;
public static final int FILTER_APPS_PERSONAL = 8;
public static final int FILTER_APPS_WORK = 9;
public static final int FILTER_APPS_USAGE_ACCESS = 10;
public static final int FILTER_APPS_WITH_OVERLAY = 11;
public static final int FILTER_APPS_WRITE_SETTINGS = 12;
public static final int FILTER_APPS_INSTALL_SOURCES = 13;
public static final int FILTER_APP_HAS_DIRECTORY_ACCESS = 14;
public static final int FILTER_APP_CAN_CHANGE_WIFI_STATE = 15;
// Next id: 16
private static AppFilterRegistry sRegistry;
private final AppFilterItem[] mFilters;
private AppFilterRegistry() {
mFilters = new AppFilterItem[15];
mFilters = new AppFilterItem[16];
// High power whitelist, on
mFilters[FILTER_APPS_POWER_WHITELIST] = new AppFilterItem(
@@ -118,11 +120,17 @@ public class AppFilterRegistry {
FILTER_APPS_INSTANT,
R.string.filter_instant_apps);
// Blocked Notifications
mFilters[FILTER_APPS_BLOCKED] = new AppFilterItem(
AppStateNotificationBridge.FILTER_APP_NOTIFICATION_BLOCKED,
FILTER_APPS_BLOCKED,
R.string.filter_notif_blocked_apps);
// Recent Notifications
mFilters[FILTER_APPS_RECENT] = new AppFilterItem(
AppStateNotificationBridge.FILTER_APP_NOTIFICATION_RECENCY,
FILTER_APPS_RECENT,
R.string.sort_order_recent_notification);
// Frequent Notifications
mFilters[FILTER_APPS_FREQUENT] = new AppFilterItem(
AppStateNotificationBridge.FILTER_APP_NOTIFICATION_FREQUENCY,
FILTER_APPS_FREQUENT,
R.string.sort_order_frequent_notification);
// Personal
mFilters[FILTER_APPS_PERSONAL] = new AppFilterItem(
@@ -196,6 +204,8 @@ public class AppFilterRegistry {
return FILTER_APP_HAS_DIRECTORY_ACCESS;
case ManageApplications.LIST_TYPE_WIFI_ACCESS:
return FILTER_APP_CAN_CHANGE_WIFI_STATE;
case ManageApplications.LIST_TYPE_NOTIFICATION:
return FILTER_APPS_RECENT;
default:
return FILTER_APPS_ALL;
}

View File

@@ -17,11 +17,13 @@
package com.android.settings.applications.manageapplications;
import static com.android.settings.applications.manageapplications.AppFilterRegistry
.FILTER_APPS_BLOCKED;
.FILTER_APPS_ALL;
import static com.android.settings.applications.manageapplications.AppFilterRegistry
.FILTER_APPS_DISABLED;
import static com.android.settings.applications.manageapplications.AppFilterRegistry
.FILTER_APPS_ENABLED;
import static com.android.settings.applications.manageapplications.AppFilterRegistry
.FILTER_APPS_FREQUENT;
import static com.android.settings.applications.manageapplications.AppFilterRegistry
.FILTER_APPS_INSTANT;
import static com.android.settings.applications.manageapplications.AppFilterRegistry
@@ -30,12 +32,15 @@ import static com.android.settings.applications.manageapplications.AppFilterRegi
.FILTER_APPS_POWER_WHITELIST;
import static com.android.settings.applications.manageapplications.AppFilterRegistry
.FILTER_APPS_POWER_WHITELIST_ALL;
import static com.android.settings.applications.manageapplications.AppFilterRegistry
.FILTER_APPS_RECENT;
import static com.android.settings.applications.manageapplications.AppFilterRegistry
.FILTER_APPS_WORK;
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.app.Activity;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -81,6 +86,7 @@ import com.android.settings.applications.AppStateBaseBridge;
import com.android.settings.applications.AppStateDirectoryAccessBridge;
import com.android.settings.applications.AppStateInstallAppsBridge;
import com.android.settings.applications.AppStateNotificationBridge;
import com.android.settings.applications.AppStateNotificationBridge.NotificationsSentState;
import com.android.settings.applications.AppStateOverlayBridge;
import com.android.settings.applications.AppStatePowerBridge;
import com.android.settings.applications.AppStateUsageBridge;
@@ -92,7 +98,6 @@ import com.android.settings.applications.DirectoryAccessDetails;
import com.android.settings.applications.InstalledAppCounter;
import com.android.settings.applications.UsageAccessDetails;
import com.android.settings.applications.appinfo.AppInfoDashboardFragment;
import com.android.settings.applications.appinfo.AppNotificationPreferenceController;
import com.android.settings.applications.appinfo.DrawOverlayDetails;
import com.android.settings.applications.appinfo.ExternalSourcesDetails;
import com.android.settings.applications.appinfo.WriteSettingsDetails;
@@ -102,8 +107,6 @@ import com.android.settings.dashboard.SummaryLoader;
import com.android.settings.fuelgauge.HighPowerDetail;
import com.android.settings.notification.AppNotificationSettings;
import com.android.settings.notification.ConfigureNotificationSettings;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.notification.NotificationBackend.AppRow;
import com.android.settings.widget.LoadingViewController;
import com.android.settings.wifi.AppStateChangeWifiStateBridge;
import com.android.settings.wifi.ChangeWifiStateDetails;
@@ -217,7 +220,7 @@ public class ManageApplications extends InstrumentedFragment
private View mSpinnerHeader;
private Spinner mFilterSpinner;
private FilterSpinnerAdapter mFilterAdapter;
private NotificationBackend mNotifBackend;
private UsageStatsManager mUsageStatsManager;
private ResetAppsHelper mResetAppsHelper;
private String mVolumeUuid;
private int mStorageType;
@@ -283,6 +286,12 @@ public class ManageApplications extends InstrumentedFragment
} else if (className.equals(Settings.ChangeWifiStateActivity.class.getName())) {
mListType = LIST_TYPE_WIFI_ACCESS;
screenTitle = R.string.change_wifi_state_title;
} else if (className.equals(Settings.NotificationAppListActivity.class.getName())) {
mListType = LIST_TYPE_NOTIFICATION;
mUsageStatsManager =
(UsageStatsManager) getContext().getSystemService(Context.USAGE_STATS_SERVICE);
mSortOrder = R.id.sort_order_recent_notification;
screenTitle = R.string.app_notifications_title;
} else {
if (screenTitle == -1) {
screenTitle = R.string.application_info_label;
@@ -383,7 +392,9 @@ public class ManageApplications extends InstrumentedFragment
}
}
if (mListType == LIST_TYPE_NOTIFICATION) {
mFilterAdapter.enableFilter(FILTER_APPS_BLOCKED);
mFilterAdapter.enableFilter(FILTER_APPS_RECENT);
mFilterAdapter.enableFilter(FILTER_APPS_FREQUENT);
mFilterAdapter.disableFilter(FILTER_APPS_ALL);
}
if (mListType == LIST_TYPE_HIGH_POWER) {
mFilterAdapter.enableFilter(FILTER_APPS_POWER_WHITELIST_ALL);
@@ -579,6 +590,7 @@ public class ManageApplications extends InstrumentedFragment
HelpUtils.prepareHelpMenuItem(activity, menu, getHelpResource(), getClass().getName());
mOptionsMenu = menu;
inflater.inflate(R.menu.manage_apps, menu);
updateOptionsMenu();
}
@@ -620,6 +632,10 @@ public class ManageApplications extends InstrumentedFragment
&& mListType != LIST_TYPE_HIGH_POWER);
mOptionsMenu.findItem(R.id.reset_app_preferences).setVisible(mListType == LIST_TYPE_MAIN);
// Hide notification menu items, because sorting happens when filtering
mOptionsMenu.findItem(R.id.sort_order_recent_notification).setVisible(false);
mOptionsMenu.findItem(R.id.sort_order_frequent_notification).setVisible(false);
}
@Override
@@ -846,8 +862,8 @@ public class ManageApplications extends InstrumentedFragment
mContext = manageApplications.getActivity();
mAppFilter = appFilter;
if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
mExtraInfoBridge = new AppStateNotificationBridge(mContext, mState, this,
manageApplications.mNotifBackend);
mExtraInfoBridge = new AppStateNotificationBridge(mState, this,
manageApplications.mUsageStatsManager);
} else if (mManageApplications.mListType == LIST_TYPE_USAGE_ACCESS) {
mExtraInfoBridge = new AppStateUsageBridge(mContext, mState, this);
} else if (mManageApplications.mListType == LIST_TYPE_HIGH_POWER) {
@@ -877,7 +893,15 @@ public class ManageApplications extends InstrumentedFragment
public void setFilter(AppFilterItem appFilter) {
mAppFilter = appFilter;
rebuild();
// Notification filters require resorting the list
if (FILTER_APPS_FREQUENT == appFilter.getFilterType()) {
rebuild(R.id.sort_order_frequent_notification);
} else if (FILTER_APPS_RECENT == appFilter.getFilterType()) {
rebuild(R.id.sort_order_recent_notification);
} else {
rebuild();
}
}
public void setExtraViewController(FileViewHolderController extraViewController) {
@@ -995,6 +1019,12 @@ public class ManageApplications extends InstrumentedFragment
break;
}
break;
case R.id.sort_order_recent_notification:
comparatorObj = AppStateNotificationBridge.RECENT_NOTIFICATION_COMPARATOR;
break;
case R.id.sort_order_frequent_notification:
comparatorObj = AppStateNotificationBridge.FREQUENCY_NOTIFICATION_COMPARATOR;
break;
default:
comparatorObj = ApplicationsState.ALPHA_COMPARATOR;
break;
@@ -1235,9 +1265,9 @@ public class ManageApplications extends InstrumentedFragment
switch (mManageApplications.mListType) {
case LIST_TYPE_NOTIFICATION:
if (entry.extraInfo != null) {
holder.setSummary(
AppNotificationPreferenceController.getNotificationSummary(
(AppRow) entry.extraInfo, mContext));
holder.setSummary(AppStateNotificationBridge.getSummary(mContext,
(NotificationsSentState) entry.extraInfo,
(mLastSortMode == R.id.sort_order_recent_notification)));
} else {
holder.setSummary(null);
}

View File

@@ -31,6 +31,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
@@ -89,8 +90,15 @@ abstract class BluetoothNameDialogFragment extends InstrumentedDialogFragment
})
.setNegativeButton(android.R.string.cancel, null);
mAlertDialog = builder.create();
mAlertDialog.getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
mAlertDialog.setOnShowListener(d -> {
if (mDeviceNameView != null && mDeviceNameView.requestFocus()) {
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(
Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.showSoftInput(mDeviceNameView, InputMethodManager.SHOW_IMPLICIT);
}
}
});
return mAlertDialog;
}

View File

@@ -434,6 +434,7 @@ public class BluetoothSettings extends DeviceListPreferenceFragment implements I
data.title = res.getString(R.string.bluetooth_settings);
data.screenTitle = res.getString(R.string.bluetooth_settings);
data.key = DATA_KEY_REFERENCE;
data.keywords = res.getString(R.string.keywords_bluetooth_settings);
result.add(data);
// Removed paired bluetooth device indexing. See BluetoothSettingsObsolete.java.

View File

@@ -109,7 +109,7 @@ public class BluetoothSwitchPreferenceController extends TogglePreferenceControl
* Control the switch inside {@link SwitchPreference}
*/
@VisibleForTesting
class SwitchController extends SwitchWidgetController implements
static class SwitchController extends SwitchWidgetController implements
Preference.OnPreferenceChangeListener {
private SwitchPreference mSwitchPreference;
@@ -156,7 +156,7 @@ public class BluetoothSwitchPreferenceController extends TogglePreferenceControl
@Override
public void setDisabledByAdmin(RestrictedLockUtils.EnforcedAdmin admin) {
mBtPreference.setEnabled(admin == null);
mSwitchPreference.setEnabled(admin == null);
}
}
}

View File

@@ -56,7 +56,7 @@ public class PreferenceControllerListHelper {
preferenceMetadata = PreferenceXmlParserUtils.extractMetadata(context, xmlResId,
MetadataFlag.FLAG_NEED_KEY | MetadataFlag.FLAG_NEED_PREF_CONTROLLER);
} catch (IOException | XmlPullParserException e) {
Log.e(TAG, "Failed to parse preference xml for getting controllers");
Log.e(TAG, "Failed to parse preference xml for getting controllers", e);
return controllers;
}

View File

@@ -0,0 +1,62 @@
/*
* 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.core;
import android.content.Context;
import android.support.v7.preference.Preference;
import android.support.v7.preference.SeekBarPreference;
import com.android.settings.slices.SliceData;
public abstract class SliderPreferenceController extends BasePreferenceController implements
Preference.OnPreferenceChangeListener {
public SliderPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
return setSliderPosition((int) newValue);
}
@Override
public void updateState(Preference preference) {
((SeekBarPreference) preference).setValue(getSliderPosition());
}
/**
* @return the value of the Slider's position based on the range: [0, maxSteps).
*/
public abstract int getSliderPosition();
/**
* Set the slider to a new value.
*
* @param position of the slider.
* @return {@code true} if the position is successfully set.
*/
public abstract boolean setSliderPosition(int position);
/**
* @return the number of steps supported by the slider.
*/
public abstract int getMaxSteps();
@Override
public int getSliceType() {
return SliceData.SliceType.SLIDER;
}
}

View File

@@ -58,7 +58,7 @@ public abstract class TogglePreferenceController extends BasePreferenceControlle
@Override
public final boolean onPreferenceChange(Preference preference, Object newValue) {
return setChecked((Boolean) newValue);
return setChecked((boolean) newValue);
}
@Override

View File

@@ -152,7 +152,9 @@ public class DndCondition extends Condition {
@Override
public void onPause() {
mManager.getContext().unregisterReceiver(mReceiver);
mRegistered = false;
if (mRegistered) {
mManager.getContext().unregisterReceiver(mReceiver);
mRegistered = false;
}
}
}

View File

@@ -23,6 +23,7 @@ import static android.telephony.TelephonyManager.SIM_STATE_READY;
import android.app.ActivityManager;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.Context;
import android.content.Intent;
import android.content.Loader;
import android.content.pm.UserInfo;
import android.graphics.Color;
@@ -39,6 +40,8 @@ import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
import android.telephony.SubscriptionInfo;
@@ -98,8 +101,10 @@ public class DataUsageList extends DataUsageBase {
private INetworkStatsSession mStatsSession;
private ChartDataUsagePreference mChart;
private NetworkTemplate mTemplate;
private int mSubId;
@VisibleForTesting
NetworkTemplate mTemplate;
@VisibleForTesting
int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private ChartData mChartData;
private LoadingViewController mLoadingViewController;
@@ -138,10 +143,7 @@ public class DataUsageList extends DataUsageBase {
mUsageAmount = findPreference(KEY_USAGE_AMOUNT);
mChart = (ChartDataUsagePreference) findPreference(KEY_CHART_DATA);
mApps = (PreferenceGroup) findPreference(KEY_APPS_GROUP);
final Bundle args = getArguments();
mSubId = args.getInt(EXTRA_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mTemplate = args.getParcelable(EXTRA_NETWORK_TEMPLATE);
processArgument();
}
@Override
@@ -232,6 +234,20 @@ public class DataUsageList extends DataUsageBase {
super.onDestroy();
}
void processArgument() {
final Bundle args = getArguments();
if (args != null) {
mSubId = args.getInt(EXTRA_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mTemplate = args.getParcelable(EXTRA_NETWORK_TEMPLATE);
}
if (mTemplate == null && mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
final Intent intent = getIntent();
mSubId = intent.getIntExtra(Settings.EXTRA_SUB_ID,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mTemplate = intent.getParcelableExtra(Settings.EXTRA_NETWORK_TEMPLATE);
}
}
/**
* Update body content based on current tab. Loads
* {@link NetworkStatsHistory} and {@link NetworkPolicy} from system, and

View File

@@ -27,13 +27,19 @@ import java.util.stream.Collectors;
*/
public class FilteredCountryTimeZones {
// New timezone list and the meta data of time zone, notUsedAfter, is introduced in Android P
// in 2018. Only show time zone used in or after 2018.
private static final long MIN_USE_DATE_OF_TIMEZONE = 1514764800000L; // 1/1/2018 00:00 UTC
private final CountryTimeZones mCountryTimeZones;
private final List<String> mTimeZoneIds;
public FilteredCountryTimeZones(CountryTimeZones countryTimeZones) {
mCountryTimeZones = countryTimeZones;
List<String> timeZoneIds = countryTimeZones.getTimeZoneMappings().stream()
.filter(timeZoneMapping -> timeZoneMapping.showInPicker)
.filter(timeZoneMapping ->
timeZoneMapping.showInPicker && (timeZoneMapping.notUsedAfter == null
|| timeZoneMapping.notUsedAfter >= MIN_USE_DATE_OF_TIMEZONE))
.map(timeZoneMapping -> timeZoneMapping.timeZoneId)
.collect(Collectors.toList());
mTimeZoneIds = Collections.unmodifiableList(timeZoneIds);

View File

@@ -16,6 +16,7 @@
package com.android.settings.datetime.timezone.model;
import android.support.annotation.VisibleForTesting;
import android.support.v4.util.ArraySet;
import libcore.util.CountryTimeZones;
import libcore.util.CountryZonesFinder;
@@ -27,12 +28,11 @@ import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Wrapper of CountryZonesFinder to normalize the country code and only show the regions that are
* has time zone shown in the time zone picker.
* The constructor reads the data from underlying file, and this means it should not be called
* getInstance() reads the data from underlying file, and this means it should not be called
* from the UI thread.
*/
public class TimeZoneData {
@@ -47,15 +47,11 @@ public class TimeZoneData {
if (data != null) {
return data;
}
data = new TimeZoneData();
data = new TimeZoneData(TimeZoneFinder.getInstance().getCountryZonesFinder());
sCache = new WeakReference<>(data);
return data;
}
public TimeZoneData() {
this(TimeZoneFinder.getInstance().getCountryZonesFinder());
}
@VisibleForTesting
public TimeZoneData(CountryZonesFinder countryZonesFinder) {
mCountryZonesFinder = countryZonesFinder;
@@ -70,13 +66,16 @@ public class TimeZoneData {
if (tzId == null) {
return Collections.emptySet();
}
return mCountryZonesFinder.lookupCountryTimeZonesForZoneId(tzId).stream()
.filter(countryTimeZones ->
countryTimeZones.getTimeZoneMappings().stream()
.anyMatch(mapping ->
mapping.timeZoneId.equals(tzId) && mapping.showInPicker))
.map(countryTimeZones -> normalizeRegionId(countryTimeZones.getCountryIso()))
.collect(Collectors.toSet());
List<CountryTimeZones> countryTimeZones = mCountryZonesFinder
.lookupCountryTimeZonesForZoneId(tzId);
Set<String> regionIds = new ArraySet<>();
for (CountryTimeZones countryTimeZone : countryTimeZones) {
FilteredCountryTimeZones filteredZones = new FilteredCountryTimeZones(countryTimeZone);
if (filteredZones.getTimeZoneIds().contains(tzId)) {
regionIds.add(filteredZones.getRegionId());
}
}
return regionIds;
}
public FilteredCountryTimeZones lookupCountryTimeZones(String regionId) {

View File

@@ -32,7 +32,7 @@ public class TimeZoneDataLoader extends AsyncLoader<TimeZoneData> {
@Override
public TimeZoneData loadInBackground() {
// Heavy operation due to reading the underlying file
return new TimeZoneData();
return TimeZoneData.getInstance();
}
@Override

View File

@@ -18,8 +18,10 @@ package com.android.settings.deviceinfo;
import android.app.Activity;
import android.app.Fragment;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.UserHandle;
import android.os.UserManager;
@@ -118,8 +120,8 @@ public class BuildNumberPreferenceController extends AbstractPreferenceControlle
if (Utils.isMonkeyRunning()) {
return false;
}
// Don't enable developer options for secondary users.
if (!mUm.isAdminUser()) {
// Don't enable developer options for secondary non-demo users.
if (!(mUm.isAdminUser() || mUm.isDemoUser())) {
mMetricsFeatureProvider.action(
mContext, MetricsEvent.ACTION_SETTINGS_BUILD_NUMBER_PREF);
return false;
@@ -133,6 +135,21 @@ public class BuildNumberPreferenceController extends AbstractPreferenceControlle
}
if (mUm.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES)) {
if (mUm.isDemoUser()) {
// Route to demo device owner to lift the debugging restriction.
final ComponentName componentName = Utils.getDeviceOwnerComponent(mContext);
if (componentName != null) {
final Intent requestDebugFeatures = new Intent()
.setPackage(componentName.getPackageName())
.setAction("com.android.settings.action.REQUEST_DEBUG_FEATURES");
final ResolveInfo resolveInfo = mContext.getPackageManager().resolveActivity(
requestDebugFeatures, 0);
if (resolveInfo != null) {
mContext.startActivity(requestDebugFeatures);
return false;
}
}
}
if (mDebuggingFeaturesDisallowedAdmin != null &&
!mDebuggingFeaturesDisallowedBySystem) {
RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext,

View File

@@ -571,6 +571,7 @@ public class StorageSettings extends SettingsPreferenceFragment implements Index
data.title = context.getString(R.string.storage_settings);
data.key = "storage_settings";
data.screenTitle = context.getString(R.string.storage_settings);
data.keywords = context.getString(R.string.keywords_storage_settings);
result.add(data);
data = new SearchIndexableRaw(context);

View File

@@ -38,6 +38,9 @@ public class ColorModePreferenceFragment extends RadioButtonPickerFragment {
static final String KEY_COLOR_MODE_BOOSTED = "color_mode_boosted";
@VisibleForTesting
static final String KEY_COLOR_MODE_SATURATED = "color_mode_saturated";
// TODO have a real key for "automatic" rather than just re-using "saturated"
@VisibleForTesting
static final String KEY_COLOR_MODE_AUTOMATIC = "color_mode_saturated";
private ColorDisplayController mController;
@@ -74,7 +77,9 @@ public class ColorModePreferenceFragment extends RadioButtonPickerFragment {
new ColorModeCandidateInfo(c.getString(R.string.color_mode_option_boosted),
KEY_COLOR_MODE_BOOSTED),
new ColorModeCandidateInfo(c.getString(R.string.color_mode_option_saturated),
KEY_COLOR_MODE_SATURATED)
KEY_COLOR_MODE_SATURATED),
new ColorModeCandidateInfo(c.getString(R.string.color_mode_option_automatic),
KEY_COLOR_MODE_AUTOMATIC)
);
}

View File

@@ -244,7 +244,8 @@ public class EnterprisePrivacyFeatureProviderImpl implements EnterprisePrivacyFe
@Override
public void onClick(View widget) {
mContext.startActivity(new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS));
mContext.startActivity(new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
@Override

View File

@@ -38,13 +38,16 @@ import android.os.UserManager;
import android.provider.Settings;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
import android.util.Pair;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.util.ArrayUtils;
import com.android.settings.R;
import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.fuelgauge.PowerWhitelistBackend;
import com.android.settingslib.utils.ThreadUtils;
@@ -78,6 +81,7 @@ public class AnomalyDetectionJobService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
ThreadUtils.postOnBackgroundThread(() -> {
final Context context = AnomalyDetectionJobService.this;
final BatteryDatabaseManager batteryDatabaseManager =
BatteryDatabaseManager.getInstance(this);
final BatteryTipPolicy policy = new BatteryTipPolicy(this);
@@ -89,12 +93,14 @@ public class AnomalyDetectionJobService extends JobService {
final PowerWhitelistBackend powerWhitelistBackend = PowerWhitelistBackend.getInstance();
final PowerUsageFeatureProvider powerUsageFeatureProvider = FeatureFactory
.getFactory(this).getPowerUsageFeatureProvider(this);
final MetricsFeatureProvider metricsFeatureProvider = FeatureFactory
.getFactory(this).getMetricsFeatureProvider();
for (JobWorkItem item = params.dequeueWork(); item != null;
item = params.dequeueWork()) {
saveAnomalyToDatabase(batteryStatsHelper, userManager, batteryDatabaseManager,
batteryUtils, policy, powerWhitelistBackend, contentResolver,
powerUsageFeatureProvider,
saveAnomalyToDatabase(context, batteryStatsHelper, userManager,
batteryDatabaseManager, batteryUtils, policy, powerWhitelistBackend,
contentResolver, powerUsageFeatureProvider, metricsFeatureProvider,
item.getIntent().getExtras());
}
jobFinished(params, false /* wantsReschedule */);
@@ -109,11 +115,12 @@ public class AnomalyDetectionJobService extends JobService {
}
@VisibleForTesting
void saveAnomalyToDatabase(BatteryStatsHelper batteryStatsHelper, UserManager userManager,
void saveAnomalyToDatabase(Context context, BatteryStatsHelper batteryStatsHelper,
UserManager userManager,
BatteryDatabaseManager databaseManager, BatteryUtils batteryUtils,
BatteryTipPolicy policy, PowerWhitelistBackend powerWhitelistBackend,
ContentResolver contentResolver, PowerUsageFeatureProvider powerUsageFeatureProvider,
Bundle bundle) {
MetricsFeatureProvider metricsFeatureProvider, Bundle bundle) {
// The Example of intentDimsValue is: 35:{1:{1:{1:10013|}|}|}
final StatsDimensionsValue intentDimsValue =
bundle.getParcelable(StatsManager.EXTRA_STATS_DIMENSIONS_VALUE);
@@ -158,6 +165,11 @@ public class AnomalyDetectionJobService extends JobService {
AnomalyDatabaseHelper.State.NEW,
timeMs);
}
metricsFeatureProvider.action(context,
MetricsProto.MetricsEvent.ACTION_ANOMALY_TRIGGERED,
packageName,
Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT,
anomalyInfo.anomalyType));
}
}
} catch (NullPointerException | IndexOutOfBoundsException e) {

View File

@@ -44,6 +44,7 @@ public class GestureSettings extends DashboardFragment {
private static final String KEY_DOUBLE_TWIST = "gesture_double_twist_input_summary";
private static final String KEY_DOUBLE_TAP_SCREEN = "gesture_double_tap_screen_input_summary";
private static final String KEY_PICK_UP = "gesture_pick_up_input_summary";
private static final String KEY_PREVENT_RINGING = "gesture_prevent_ringing_summary";
private AmbientDisplayConfiguration mAmbientDisplayConfig;
@@ -86,6 +87,8 @@ public class GestureSettings extends DashboardFragment {
ambientDisplayConfiguration, UserHandle.myUserId(), KEY_PICK_UP));
controllers.add(new DoubleTapScreenPreferenceController(context, lifecycle,
ambientDisplayConfiguration, UserHandle.myUserId(), KEY_DOUBLE_TAP_SCREEN));
controllers.add(new PreventRingingPreferenceController(
context, lifecycle, UserHandle.myUserId(), KEY_PREVENT_RINGING));
return controllers;
}

View File

@@ -0,0 +1,94 @@
/*
* 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.gestures;
import android.content.Context;
import android.os.UserHandle;
import android.provider.SearchIndexableResource;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
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 PreventRingingGestureSettings extends DashboardFragment {
private static final String TAG = "RingingGestureSettings";
private static final String KEY_PREVENT_RINGING = "gesture_prevent_ringing";
@Override
public void onAttach(Context context) {
super.onAttach(context);
}
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.SETTINGS_PREVENT_RINGING;
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.prevent_ringing_gesture_settings;
}
@Override
public int getHelpResource() {
return 0;
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return buildPreferenceControllers(context, getLifecycle());
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new PreventRingingPreferenceController(context, lifecycle,
UserHandle.myUserId(), KEY_PREVENT_RINGING));
return controllers;
}
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.prevent_ringing_gesture_settings;
return Arrays.asList(sir);
}
@Override
public List<AbstractPreferenceController> createPreferenceControllers(
Context context) {
return buildPreferenceControllers(context, null /* lifecycle */);
}
};
}

View File

@@ -0,0 +1,169 @@
/*
* 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.gestures;
import static android.provider.Settings.Secure.VOLUME_HUSH_GESTURE;
import static android.provider.Settings.Secure.VOLUME_HUSH_MUTE;
import static android.provider.Settings.Secure.VOLUME_HUSH_OFF;
import static android.provider.Settings.Secure.VOLUME_HUSH_VIBRATE;
import android.annotation.UserIdInt;
import android.content.Context;
import android.os.Bundle;
import android.provider.Settings;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.ListPreference;
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.settings.widget.VideoPreference;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnCreate;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
public class PreventRingingPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener,
LifecycleObserver, OnResume, OnPause, OnCreate, OnSaveInstanceState {
private static final String PREF_KEY_VIDEO = "gesture_prevent_ringing_video";
private final String mPrefKey;
@VisibleForTesting
static final String KEY_VIDEO_PAUSED = "key_video_paused";
private VideoPreference mVideoPreference;
@VisibleForTesting
boolean mVideoPaused;
private final String SECURE_KEY = VOLUME_HUSH_GESTURE;
@UserIdInt
private final int mUserId;
public PreventRingingPreferenceController(Context context, Lifecycle lifecycle,
@UserIdInt int userId, String key) {
super(context);
if (lifecycle != null) {
lifecycle.addObserver(this);
}
mUserId = userId;
mPrefKey = key;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
if (isAvailable()) {
mVideoPreference = (VideoPreference) screen.findPreference(getVideoPrefKey());
}
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
if (preference != null) {
if (preference instanceof ListPreference) {
ListPreference pref = (ListPreference) preference;
int value = Settings.Secure.getInt(
mContext.getContentResolver(), SECURE_KEY, VOLUME_HUSH_VIBRATE);
switch (value) {
case VOLUME_HUSH_VIBRATE:
pref.setValue(String.valueOf(value));
break;
case VOLUME_HUSH_MUTE:
pref.setValue(String.valueOf(value));
break;
default:
pref.setValue(String.valueOf(VOLUME_HUSH_OFF));
}
}
}
}
@Override
public CharSequence getSummary() {
int value = Settings.Secure.getInt(
mContext.getContentResolver(), SECURE_KEY, VOLUME_HUSH_VIBRATE);
int summary;
switch (value) {
case VOLUME_HUSH_VIBRATE:
summary = R.string.prevent_ringing_option_vibrate_summary;
break;
case VOLUME_HUSH_MUTE:
summary = R.string.prevent_ringing_option_mute_summary;
break;
default:
summary = R.string.prevent_ringing_option_none_summary;
}
return mContext.getString(summary);
}
@Override
public void onCreate(Bundle savedInstanceState) {
if (savedInstanceState != null) {
mVideoPaused = savedInstanceState.getBoolean(KEY_VIDEO_PAUSED, false);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean(KEY_VIDEO_PAUSED, mVideoPaused);
}
@Override
public void onPause() {
if (mVideoPreference != null) {
mVideoPaused = mVideoPreference.isVideoPaused();
mVideoPreference.onViewInvisible();
}
}
@Override
public void onResume() {
if (mVideoPreference != null) {
mVideoPreference.onViewVisible(mVideoPaused);
}
}
@Override
public boolean isAvailable() {
return mContext.getResources()
.getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled);
}
protected String getVideoPrefKey() {
return PREF_KEY_VIDEO;
}
@Override
public String getPreferenceKey() {
return mPrefKey;
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
int value = Integer.parseInt((String) newValue);
Settings.Secure.putInt(mContext.getContentResolver(), SECURE_KEY, value);
preference.setSummary(getSummary());
return true;
}
}

View File

@@ -30,6 +30,7 @@ import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
import com.android.settings.gestures.AssistGestureFeatureProvider;
import com.android.settings.localepicker.LocaleFeatureProvider;
import com.android.settings.search.DeviceIndexFeatureProvider;
import com.android.settings.search.SearchFeatureProvider;
import com.android.settings.security.SecurityFeatureProvider;
import com.android.settings.slices.SlicesFeatureProvider;
@@ -106,6 +107,8 @@ public abstract class FeatureFactory {
public abstract AccountFeatureProvider getAccountFeatureProvider();
public abstract DeviceIndexFeatureProvider getDeviceIndexFeatureProvider();
public static final class FactoryNotFoundException extends RuntimeException {
public FactoryNotFoundException(Throwable throwable) {
super("Unable to create factory. Did you misconfigure Proguard?", throwable);

View File

@@ -41,6 +41,8 @@ import com.android.settings.gestures.AssistGestureFeatureProvider;
import com.android.settings.gestures.AssistGestureFeatureProviderImpl;
import com.android.settings.localepicker.LocaleFeatureProvider;
import com.android.settings.localepicker.LocaleFeatureProviderImpl;
import com.android.settings.search.DeviceIndexFeatureProvider;
import com.android.settings.search.DeviceIndexFeatureProviderImpl;
import com.android.settings.search.SearchFeatureProvider;
import com.android.settings.search.SearchFeatureProviderImpl;
import com.android.settings.security.SecurityFeatureProvider;
@@ -75,6 +77,7 @@ public class FeatureFactoryImpl extends FeatureFactory {
private BluetoothFeatureProvider mBluetoothFeatureProvider;
private SlicesFeatureProvider mSlicesFeatureProvider;
private AccountFeatureProvider mAccountFeatureProvider;
private DeviceIndexFeatureProviderImpl mDeviceIndexFeatureProvider;
@Override
public SupportFeatureProvider getSupportFeatureProvider(Context context) {
@@ -208,4 +211,12 @@ public class FeatureFactoryImpl extends FeatureFactory {
}
return mAccountFeatureProvider;
}
@Override
public DeviceIndexFeatureProvider getDeviceIndexFeatureProvider() {
if (mDeviceIndexFeatureProvider == null) {
mDeviceIndexFeatureProvider = new DeviceIndexFeatureProviderImpl();
}
return mDeviceIndexFeatureProvider;
}
}

View File

@@ -20,9 +20,11 @@ import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.content.res.Resources.Theme;
import android.os.Bundle;
import android.util.Log;
import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@@ -171,6 +173,7 @@ public class ChooseLockPattern extends SettingsActivity {
private String mCurrentPattern;
private boolean mHasChallenge;
private long mChallenge;
protected TextView mTitleText;
protected TextView mHeaderText;
protected TextView mMessageText;
protected LockPatternView mLockPatternView;
@@ -179,6 +182,7 @@ public class ChooseLockPattern extends SettingsActivity {
private TextView mFooterRightButton;
protected List<LockPatternView.Cell> mChosenPattern = null;
private boolean mHideDrawer = false;
private ColorStateList mDefaultHeaderColorList;
// ScrollView that contains title and header, only exist in land mode
private ScrollView mTitleHeaderScrollView;
@@ -265,6 +269,9 @@ public class ChooseLockPattern extends SettingsActivity {
private void patternInProgress() {
mHeaderText.setText(R.string.lockpattern_recording_inprogress);
if (mDefaultHeaderColorList != null) {
mHeaderText.setTextColor(mDefaultHeaderColorList);
}
mFooterText.setText("");
mFooterLeftButton.setEnabled(false);
mFooterRightButton.setEnabled(false);
@@ -465,10 +472,13 @@ public class ChooseLockPattern extends SettingsActivity {
return layout;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mTitleText = view.findViewById(R.id.suw_layout_title);
mHeaderText = (TextView) view.findViewById(R.id.headerText);
mDefaultHeaderColorList = mHeaderText.getTextColors();
mMessageText = view.findViewById(R.id.message);
mLockPatternView = (LockPatternView) view.findViewById(R.id.lockPattern);
mLockPatternView.setOnPatternListener(mChooseNewLockPatternListener);
@@ -664,6 +674,23 @@ public class ChooseLockPattern extends SettingsActivity {
mFooterText.setText(stage.footerMessage);
}
if (stage == Stage.ConfirmWrong || stage == Stage.ChoiceTooShort) {
TypedValue typedValue = new TypedValue();
Theme theme = getActivity().getTheme();
theme.resolveAttribute(R.attr.colorError, typedValue, true);
mHeaderText.setTextColor(typedValue.data);
} else {
if (mDefaultHeaderColorList != null) {
mHeaderText.setTextColor(mDefaultHeaderColorList);
}
if (stage == Stage.NeedToConfirm && mForFingerprint) {
mHeaderText.setText("");
mTitleText.setText(R.string.lockpassword_draw_your_pattern_again_header);
}
}
updateFooterLeftButton(stage, mFooterLeftButton);
setRightButtonText(stage.rightMode.text);

View File

@@ -279,13 +279,12 @@ public final class ChooseLockSettingsHelper {
CharSequence message, Class<?> activityClass, boolean returnCredentials,
boolean external, boolean hasChallenge, long challenge,
int userId, @Nullable CharSequence alternateButton, Bundle extras) {
final boolean frp = (userId == LockPatternUtils.USER_FRP);
final Intent intent = new Intent();
intent.putExtra(ConfirmDeviceCredentialBaseFragment.TITLE_TEXT, title);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.HEADER_TEXT, header);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.DETAILS_TEXT, message);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.ALLOW_FP_AUTHENTICATION, external);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.DARK_THEME, external && !frp);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.DARK_THEME, false);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.SHOW_CANCEL_BUTTON, external);
intent.putExtra(ConfirmDeviceCredentialBaseFragment.SHOW_WHEN_LOCKED, external);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_RETURN_CREDENTIALS, returnCredentials);

View File

@@ -34,8 +34,8 @@ public abstract class ConfirmDeviceCredentialBaseActivity extends SettingsActivi
private static final String STATE_IS_KEYGUARD_LOCKED = "STATE_IS_KEYGUARD_LOCKED";
enum ConfirmCredentialTheme {
INTERNAL,
DARK,
NORMAL,
DARK, // TODO(yukl): Clean up DARK theme, as it should no longer be used
WORK
}
@@ -63,11 +63,11 @@ public abstract class ConfirmDeviceCredentialBaseActivity extends SettingsActivi
mConfirmCredentialTheme = ConfirmCredentialTheme.DARK;
} else {
setTheme(SetupWizardUtils.getTheme(getIntent()));
mConfirmCredentialTheme = ConfirmCredentialTheme.INTERNAL;
mConfirmCredentialTheme = ConfirmCredentialTheme.NORMAL;
}
super.onCreate(savedState);
if (mConfirmCredentialTheme == ConfirmCredentialTheme.INTERNAL) {
if (mConfirmCredentialTheme == ConfirmCredentialTheme.NORMAL) {
// Prevent the content parent from consuming the window insets because GlifLayout uses
// it to show the status bar background.
LinearLayout layout = (LinearLayout) findViewById(R.id.content_parent);

View File

@@ -121,8 +121,8 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
ConfirmLockPassword activity = (ConfirmLockPassword) getActivity();
View view = inflater.inflate(
activity.getConfirmCredentialTheme() == ConfirmCredentialTheme.INTERNAL
? R.layout.confirm_lock_password_internal
activity.getConfirmCredentialTheme() == ConfirmCredentialTheme.NORMAL
? R.layout.confirm_lock_password_normal
: R.layout.confirm_lock_password,
container,
false);

View File

@@ -109,8 +109,8 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
Bundle savedInstanceState) {
ConfirmLockPattern activity = (ConfirmLockPattern) getActivity();
View view = inflater.inflate(
activity.getConfirmCredentialTheme() == ConfirmCredentialTheme.INTERNAL
? R.layout.confirm_lock_pattern_internal
activity.getConfirmCredentialTheme() == ConfirmCredentialTheme.NORMAL
? R.layout.confirm_lock_pattern_normal
: R.layout.confirm_lock_pattern,
container,
false);

View File

@@ -25,7 +25,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.SetupRedactionInterstitial;
@@ -70,6 +69,17 @@ public class SetupChooseLockPattern extends ChooseLockPattern {
ChooseLockTypeDialogFragment.newInstance(mUserId)
.show(getChildFragmentManager(), null));
}
// enable skip button only during setup wizard and not with fingerprint flow.
if (!mForFingerprint) {
Button skipButton = view.findViewById(R.id.skip_button);
skipButton.setVisibility(View.VISIBLE);
skipButton.setOnClickListener(v -> {
SetupSkipDialog dialog = SetupSkipDialog.newInstance(
getActivity().getIntent()
.getBooleanExtra(SetupSkipDialog.EXTRA_FRP_SUPPORTED, false));
dialog.show(getFragmentManager());
});
}
return view;
}
@@ -81,16 +91,6 @@ public class SetupChooseLockPattern extends ChooseLockPattern {
startChooseLockActivity(lock, getActivity());
}
@Override
protected void updateFooterLeftButton(Stage stage, TextView footerLeftButton) {
super.updateFooterLeftButton(stage, footerLeftButton);
// enable skip button only during setupwizard and not with fingerprint flow.
if (!mForFingerprint) {
footerLeftButton.setVisibility(View.VISIBLE);
footerLeftButton.setText(R.string.skip_label);
}
}
@Override
protected void updateStage(Stage stage) {
super.updateStage(stage);
@@ -101,14 +101,6 @@ public class SetupChooseLockPattern extends ChooseLockPattern {
}
}
@Override
public void handleLeftButton() {
SetupSkipDialog dialog = SetupSkipDialog.newInstance(
getActivity().getIntent()
.getBooleanExtra(SetupSkipDialog.EXTRA_FRP_SUPPORTED, false));
dialog.show(getFragmentManager());
}
@Override
protected Intent getRedactionInterstitialIntent(Context context) {
// Setup wizard's redaction interstitial is deferred to optional step. Enable that

View File

@@ -0,0 +1,89 @@
/*
* 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.search;
import static com.android.settings.slices.SliceDeepLinkSpringBoard.INTENT;
import static com.android.settings.slices.SliceDeepLinkSpringBoard.SETTINGS;
import android.app.slice.SliceManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.provider.Settings;
import android.util.Log;
import com.android.settings.slices.SettingsSliceProvider;
public interface DeviceIndexFeatureProvider {
// TODO: Remove this and index all action and intent slices through search index.
String[] ACTIONS_TO_INDEX = new String[]{
Settings.ACTION_WIFI_SETTINGS,
};
String TAG = "DeviceIndex";
String INDEX_VERSION = "settings:index_version";
// Increment when new items are added to ensure they get pushed to the device index.
int VERSION = 1;
boolean isIndexingEnabled();
void index(Context context, CharSequence title, Uri sliceUri, Uri launchUri);
default void updateIndex(Context context, boolean force) {
if (!isIndexingEnabled()) return;
if (!force && Settings.Secure.getInt(context.getContentResolver(), INDEX_VERSION, -1)
== VERSION) {
// No need to update.
return;
}
PackageManager pm = context.getPackageManager();
for (String action : ACTIONS_TO_INDEX) {
Intent intent = new Intent(action);
intent.setPackage(context.getPackageName());
ResolveInfo activity = pm.resolveActivity(intent, PackageManager.GET_META_DATA);
if (activity == null) {
Log.e(TAG, "Unable to resolve " + action);
continue;
}
String sliceUri = activity.activityInfo.metaData
.getString(SliceManager.SLICE_METADATA_KEY);
if (sliceUri != null) {
Log.d(TAG, "Intent: " + createDeepLink(intent.toUri(Intent.URI_ANDROID_APP_SCHEME)));
index(context, activity.activityInfo.loadLabel(pm),
Uri.parse(sliceUri),
Uri.parse(createDeepLink(intent.toUri(Intent.URI_ANDROID_APP_SCHEME))));
} else {
Log.e(TAG, "No slice uri found for " + activity.activityInfo.name);
}
}
Settings.Secure.putInt(context.getContentResolver(), INDEX_VERSION, VERSION);
}
static String createDeepLink(String s) {
return new Uri.Builder().scheme(SETTINGS)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendQueryParameter(INTENT, s)
.build()
.toString();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 The Android Open Source Project
* 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
@@ -12,18 +12,20 @@
* permissions and limitations under the License.
*/
package com.android.settings.wrapper;
package com.android.settings.search;
import android.content.pm.PackageInfo;
import android.content.pm.UserInfo;
import android.content.Context;
import android.net.Uri;
/**
* Wrapper class around android.webkit.UserPackage - to be able to use UserPackage in Robolectric
* tests (such tests currently don't support mocking hidden classes).
*/
public interface UserPackageWrapper {
UserInfo getUserInfo();
PackageInfo getPackageInfo();
boolean isEnabledPackage();
boolean isInstalledPackage();
public class DeviceIndexFeatureProviderImpl implements DeviceIndexFeatureProvider {
@Override
public boolean isIndexingEnabled() {
return false;
}
@Override
public void index(Context context, CharSequence title, Uri sliceUri, Uri launchUri) {
// Not enabled by default.
}
}

View File

@@ -17,27 +17,26 @@
package com.android.settings.slices;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.app.slice.SliceManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.provider.SettingsSlicesContract;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
import com.android.settings.R;
import com.android.settingslib.utils.ThreadUtils;
import java.net.URISyntaxException;
import java.util.Map;
import java.util.WeakHashMap;
import androidx.slice.Slice;
import androidx.slice.SliceProvider;
import androidx.slice.builders.SliceAction;
import androidx.slice.builders.ListBuilder;
import androidx.slice.builders.SliceAction;
/**
* A {@link SliceProvider} for Settings to enabled inline results in system apps.
@@ -74,11 +73,29 @@ public class SettingsSliceProvider extends SliceProvider {
public static final String ACTION_WIFI_CHANGED =
"com.android.settings.slice.action.WIFI_CHANGED";
/**
* Action passed for changes to Toggle Slices.
*/
public static final String ACTION_TOGGLE_CHANGED =
"com.android.settings.slice.action.TOGGLE_CHANGED";
/**
* Action passed for changes to Slider Slices.
*/
public static final String ACTION_SLIDER_CHANGED =
"com.android.settings.slice.action.SLIDER_CHANGED";
/**
* Intent Extra passed for the key identifying the Setting Slice.
*/
public static final String EXTRA_SLICE_KEY = "com.android.settings.slice.extra.key";
/**
* Boolean extra to indicate if the Slice is platform-defined.
*/
public static final String EXTRA_SLICE_PLATFORM_DEFINED =
"com.android.settings.slice.extra.platform";
// TODO -- Associate slice URI with search result instead of separate hardcoded thing
@VisibleForTesting
@@ -94,6 +111,17 @@ public class SettingsSliceProvider extends SliceProvider {
return true;
}
@Override
public Uri onMapIntentToUri(Intent intent) {
try {
return getContext().getSystemService(SliceManager.class).mapIntentToUri(
SliceDeepLinkSpringBoard.parse(
intent.getData(), getContext().getPackageName()));
} catch (URISyntaxException e) {
return null;
}
}
@Override
public Slice onBindSlice(Uri sliceUri) {
String path = sliceUri.getPath();

View File

@@ -16,22 +16,30 @@
package com.android.settings.slices;
import static com.android.settings.slices.SettingsSliceProvider.ACTION_SLIDER_CHANGED;
import static com.android.settings.slices.SettingsSliceProvider.ACTION_TOGGLE_CHANGED;
import static com.android.settings.slices.SettingsSliceProvider.ACTION_WIFI_CHANGED;
import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_KEY;
import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_PLATFORM_DEFINED;
import android.app.slice.Slice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.provider.SettingsSlicesContract;
import android.text.TextUtils;
import android.util.Log;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.SliderPreferenceController;
import com.android.settings.core.TogglePreferenceController;
import android.app.slice.Slice;
import androidx.slice.core.SliceHints;
/**
* Responds to actions performed on slices and notifies slices of updates in state changes.
*/
@@ -44,12 +52,18 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
*/
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
String key = intent.getStringExtra(EXTRA_SLICE_KEY);
final String action = intent.getAction();
final String key = intent.getStringExtra(EXTRA_SLICE_KEY);
final boolean isPlatformDefined = intent.getBooleanExtra(EXTRA_SLICE_PLATFORM_DEFINED,
false /* default */);
switch (action) {
case ACTION_TOGGLE_CHANGED:
handleToggleAction(context, key);
handleToggleAction(context, key, isPlatformDefined);
break;
case ACTION_SLIDER_CHANGED:
int newPosition = intent.getIntExtra(SliceHints.EXTRA_RANGE_VALUE, -1);
handleSliderAction(context, key, newPosition);
break;
case ACTION_WIFI_CHANGED:
WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
@@ -67,7 +81,7 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
}
}
private void handleToggleAction(Context context, String key) {
private void handleToggleAction(Context context, String key, boolean isPlatformSlice) {
if (TextUtils.isEmpty(key)) {
throw new IllegalStateException("No key passed to Intent for toggle controller");
}
@@ -78,11 +92,44 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
throw new IllegalStateException("Toggle action passed for a non-toggle key: " + key);
}
if (!controller.isAvailable()) {
Log.d(TAG, "Can't update " + key + " since the setting is unavailable");
updateUri(context, key, isPlatformSlice);
}
// TODO post context.getContentResolver().notifyChanged(uri, null) in the Toggle controller
// so that it's automatically broadcast to any slice.
final TogglePreferenceController toggleController = (TogglePreferenceController) controller;
final boolean currentValue = toggleController.isChecked();
toggleController.setChecked(!currentValue);
updateUri(context, key, isPlatformSlice);
}
private void handleSliderAction(Context context, String key, int newPosition) {
if (TextUtils.isEmpty(key)) {
throw new IllegalArgumentException(
"No key passed to Intent for slider controller. Use extra: " + EXTRA_SLICE_KEY);
}
if (newPosition == -1) {
throw new IllegalArgumentException("Invalid position passed to Slider controller");
}
final BasePreferenceController controller = getPreferenceController(context, key);
if (!(controller instanceof SliderPreferenceController)) {
throw new IllegalArgumentException("Slider action passed for a non-slider key: " + key);
}
final SliderPreferenceController sliderController = (SliderPreferenceController) controller;
final int maxSteps = sliderController.getMaxSteps();
if (newPosition < 0 || newPosition > maxSteps) {
throw new IllegalArgumentException(
"Invalid position passed to Slider controller. Expected between 0 and "
+ maxSteps + " but found " + newPosition);
}
sliderController.setSliderPosition(newPosition);
}
private BasePreferenceController getPreferenceController(Context context, String key) {
@@ -90,4 +137,10 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
final SliceData sliceData = accessor.getSliceDataFromKey(key);
return SliceBuilderUtils.getPreferenceController(context, sliceData);
}
private void updateUri(Context context, String key, boolean isPlatformDefined) {
final String path = SettingsSlicesContract.PATH_SETTING_ACTION + "/" + key;
final Uri uri = SliceBuilderUtils.getUri(path, isPlatformDefined);
context.getContentResolver().notifyChange(uri, null /* observer */);
}
}

View File

@@ -16,12 +16,20 @@
package com.android.settings.slices;
import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
import static com.android.settings.core.BasePreferenceController.DISABLED_FOR_USER;
import static com.android.settings.core.BasePreferenceController.DISABLED_UNSUPPORTED;
import static com.android.settings.core.BasePreferenceController.UNAVAILABLE_UNKNOWN;
import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_KEY;
import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_PLATFORM_DEFINED;
import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.provider.SettingsSlicesContract;
@@ -32,6 +40,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.SubSettings;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.SliderPreferenceController;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.search.DatabaseIndexingUtils;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -39,7 +48,7 @@ import com.android.settingslib.core.AbstractPreferenceController;
import androidx.slice.Slice;
import androidx.slice.builders.SliceAction;
import androidx.slice.builders.ListBuilder;
import androidx.slice.builders.ListBuilder.RowBuilder;
/**
* Utility class to build Slices objects and Preference Controllers based on the Database managed
@@ -57,28 +66,23 @@ public class SliceBuilderUtils {
* {@param sliceData} is an inline controller.
*/
public static Slice buildSlice(Context context, SliceData sliceData) {
final PendingIntent contentIntent = getContentIntent(context, sliceData);
final Icon icon = Icon.createWithResource(context, sliceData.getIconResource());
final BasePreferenceController controller = getPreferenceController(context, sliceData);
final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
final RowBuilder builder = new RowBuilder(context, sliceData.getUri())
.setTitle(sliceData.getTitle())
.setTitleItem(icon)
.setSubtitle(subtitleText)
.setPrimaryAction(new SliceAction(contentIntent, null, null));
// TODO (b/71640747) Respect setting availability.
if (sliceData.getSliceType() == SliceData.SliceType.SWITCH) {
addToggleAction(context, builder, ((TogglePreferenceController) controller).isChecked(),
sliceData.getKey());
if (!controller.isAvailable()) {
return buildUnavailableSlice(context, sliceData, controller);
}
return new ListBuilder(context, sliceData.getUri())
.addRow(builder)
.build();
switch (sliceData.getSliceType()) {
case SliceData.SliceType.INTENT:
return buildIntentSlice(context, sliceData, controller);
case SliceData.SliceType.SWITCH:
return buildToggleSlice(context, sliceData, controller);
case SliceData.SliceType.SLIDER:
return buildSliderSlice(context, sliceData, controller);
default:
throw new IllegalArgumentException(
"Slice type passed was invalid: " + sliceData.getSliceType());
}
}
/**
@@ -125,8 +129,8 @@ public class SliceBuilderUtils {
}
/**
* Looks at the {@link SliceData#preferenceController} from {@param sliceData} and attempts to
* build an {@link AbstractPreferenceController}.
* Looks at the controller classname in in {@link SliceData} from {@param sliceData}
* and attempts to build an {@link AbstractPreferenceController}.
*/
public static BasePreferenceController getPreferenceController(Context context,
SliceData sliceData) {
@@ -145,6 +149,55 @@ public class SliceBuilderUtils {
.build();
}
private static Slice buildToggleSlice(Context context, SliceData sliceData,
BasePreferenceController controller) {
final PendingIntent contentIntent = getContentIntent(context, sliceData);
final Icon icon = Icon.createWithResource(context, sliceData.getIconResource());
final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
final TogglePreferenceController toggleController =
(TogglePreferenceController) controller;
final SliceAction sliceAction = getToggleAction(context, sliceData,
toggleController.isChecked());
return new ListBuilder(context, sliceData.getUri())
.addRow(rowBuilder -> rowBuilder
.setTitle(sliceData.getTitle())
.setTitleItem(icon, ICON_IMAGE)
.setSubtitle(subtitleText)
.setPrimaryAction(new SliceAction(contentIntent, null, null))
.addEndItem(sliceAction))
.build();
}
private static Slice buildIntentSlice(Context context, SliceData sliceData,
BasePreferenceController controller) {
final PendingIntent contentIntent = getContentIntent(context, sliceData);
final Icon icon = Icon.createWithResource(context, sliceData.getIconResource());
final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
return new ListBuilder(context, sliceData.getUri())
.addRow(rowBuilder -> rowBuilder
.setTitle(sliceData.getTitle())
.setTitleItem(icon, ICON_IMAGE)
.setSubtitle(subtitleText)
.setPrimaryAction(new SliceAction(contentIntent, null, null)))
.build();
}
private static Slice buildSliderSlice(Context context, SliceData sliceData,
BasePreferenceController controller) {
final SliderPreferenceController sliderController =
(SliderPreferenceController) controller;
final PendingIntent actionIntent = getSliderAction(context, sliceData);
return new ListBuilder(context, sliceData.getUri())
.addInputRange(builder -> builder
.setTitle(sliceData.getTitle())
.setMax(sliderController.getMaxSteps())
.setValue(sliderController.getSliderPosition())
.setAction(actionIntent))
.build();
}
private static BasePreferenceController getPreferenceController(Context context,
String controllerClassName, String controllerKey) {
try {
@@ -156,17 +209,22 @@ public class SliceBuilderUtils {
return BasePreferenceController.createInstance(context, controllerClassName, controllerKey);
}
private static void addToggleAction(Context context, RowBuilder builder, boolean isChecked,
String key) {
private static SliceAction getToggleAction(Context context, SliceData sliceData,
boolean isChecked) {
PendingIntent actionIntent = getActionIntent(context,
SettingsSliceProvider.ACTION_TOGGLE_CHANGED, key);
builder.addEndItem(new SliceAction(actionIntent, null, isChecked));
SettingsSliceProvider.ACTION_TOGGLE_CHANGED, sliceData);
return new SliceAction(actionIntent, null, isChecked);
}
private static PendingIntent getActionIntent(Context context, String action, String key) {
private static PendingIntent getSliderAction(Context context, SliceData sliceData) {
return getActionIntent(context, SettingsSliceProvider.ACTION_SLIDER_CHANGED, sliceData);
}
private static PendingIntent getActionIntent(Context context, String action, SliceData data) {
Intent intent = new Intent(action);
intent.setClass(context, SliceBroadcastReceiver.class);
intent.putExtra(EXTRA_SLICE_KEY, key);
intent.putExtra(EXTRA_SLICE_KEY, data.getKey());
intent.putExtra(EXTRA_SLICE_PLATFORM_DEFINED, data.isPlatformDefined());
return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
}
@@ -179,6 +237,12 @@ public class SliceBuilderUtils {
return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 0 /* flags */);
}
private static PendingIntent getSettingsIntent(Context context) {
final PackageManager manager = context.getPackageManager();
final Intent intent = manager.getLaunchIntentForPackage(context.getPackageName());
return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 0 /* flags */);
}
@VisibleForTesting
static CharSequence getSubtitleText(Context context, AbstractPreferenceController controller,
SliceData sliceData) {
@@ -210,4 +274,41 @@ public class SliceBuilderUtils {
return !(TextUtils.equals(summary, placeHolder)
|| TextUtils.equals(summary, doublePlaceHolder));
}
private static Slice buildUnavailableSlice(Context context, SliceData data,
BasePreferenceController controller) {
final String title = data.getTitle();
final String summary;
final SliceAction primaryAction;
switch (controller.getAvailabilityStatus()) {
case DISABLED_UNSUPPORTED:
summary = context.getString(R.string.unsupported_setting_summary);
primaryAction = new SliceAction(getSettingsIntent(context), null /* actionIcon */,
null /* actionTitle */);
break;
case DISABLED_FOR_USER:
summary = context.getString(R.string.disabled_for_user_setting_summary);
primaryAction = new SliceAction(getContentIntent(context, data),
null /* actionIcon */, null /* actionTitle */);
break;
case DISABLED_DEPENDENT_SETTING:
summary = context.getString(R.string.disabled_dependent_setting_summary);
primaryAction = new SliceAction(getContentIntent(context, data),
null /* actionIcon */, null /* actionTitle */);
break;
case UNAVAILABLE_UNKNOWN:
default:
summary = context.getString(R.string.unknown_unavailability_setting_summary);
primaryAction = new SliceAction(getSettingsIntent(context),
null /* actionIcon */, null /* actionTitle */);
}
return new ListBuilder(context, data.getUri())
.addRow(builder -> builder
.setTitle(title)
.setSubtitle(summary)
.setPrimaryAction(primaryAction))
.build();
}
}

View File

@@ -0,0 +1,64 @@
/*
* 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.slices;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import java.net.URISyntaxException;
public class SliceDeepLinkSpringBoard extends Activity {
private static final String TAG = "DeeplinkSpringboard";
public static final String INTENT = "intent";
public static final String SETTINGS = "settings";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Uri uri = getIntent().getData();
if (uri == null) {
Log.e(TAG, "No data found");
finish();
return;
}
try {
Intent intent = parse(uri, getPackageName());
startActivity(intent);
finish();
} catch (URISyntaxException e) {
Log.e(TAG, "Error decoding uri", e);
finish();
}
}
public static Intent parse(Uri uri, String pkg) throws URISyntaxException {
Intent intent = Intent.parseUri(uri.getQueryParameter(INTENT),
Intent.URI_ANDROID_APP_SCHEME);
// Start with some really strict constraints and loosen them if we need to.
// Don't allow components.
intent.setComponent(null);
// Clear out the extras.
if (intent.getExtras() != null) {
intent.getExtras().clear();
}
// Make sure this points at Settings.
intent.setPackage(pkg);
return intent;
}
}

View File

@@ -118,6 +118,7 @@ public class WallpaperTypeSettings extends SettingsPreferenceFragment implements
data.intentAction = Intent.ACTION_SET_WALLPAPER;
data.intentTargetPackage = info.activityInfo.packageName;
data.intentTargetClass = info.activityInfo.name;
data.keywords = context.getString(R.string.keywords_wallpaper);
result.add(data);
}

View File

@@ -27,11 +27,11 @@ import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
import android.webkit.UserPackage;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.applications.defaultapps.DefaultAppPickerFragment;
import com.android.settings.wrapper.UserPackageWrapper;
import com.android.settingslib.applications.DefaultAppInfo;
import com.android.settingslib.wrapper.PackageManagerWrapper;
@@ -150,9 +150,9 @@ public class WebViewAppPicker extends DefaultAppPickerFragment {
@VisibleForTesting
String getDisabledReason(WebViewUpdateServiceWrapper webviewUpdateServiceWrapper,
Context context, String packageName) {
List<UserPackageWrapper> userPackages =
List<UserPackage> userPackages =
webviewUpdateServiceWrapper.getPackageInfosAllUsers(context, packageName);
for (UserPackageWrapper userPackage : userPackages) {
for (UserPackage userPackage : userPackages) {
if (!userPackage.isInstalledPackage()) {
// Package uninstalled/hidden
return context.getString(

View File

@@ -28,8 +28,6 @@ import android.webkit.WebViewProviderInfo;
import android.widget.Toast;
import com.android.settings.R;
import com.android.settings.wrapper.UserPackageWrapper;
import com.android.settings.wrapper.UserPackageWrapperImpl;
import java.util.ArrayList;
import java.util.List;
@@ -37,7 +35,8 @@ import java.util.List;
public class WebViewUpdateServiceWrapper {
private static final String TAG = "WVUSWrapper";
public WebViewUpdateServiceWrapper() {}
public WebViewUpdateServiceWrapper() {
}
/**
* Fetch the package currently used as WebView implementation.
@@ -75,6 +74,7 @@ public class WebViewUpdateServiceWrapper {
/**
* Change WebView provider to {@param packageName}.
*
* @return whether the change succeeded.
*/
public boolean setWebViewProvider(String packageName) {
@@ -90,14 +90,8 @@ public class WebViewUpdateServiceWrapper {
/**
* Fetch PackageInfos for the package named {@param packageName} for all users on the device.
*/
public List<UserPackageWrapper> getPackageInfosAllUsers(Context context, String packageName) {
List<UserPackageWrapper> userPackageWrappers = new ArrayList<>();
List<UserPackage> userPackages =
UserPackage.getPackageInfosAllUsers(context, packageName, PACKAGE_FLAGS);
for (UserPackage userPackage : userPackages) {
userPackageWrappers.add(new UserPackageWrapperImpl(userPackage));
}
return userPackageWrappers;
public List<UserPackage> getPackageInfosAllUsers(Context context, String packageName) {
return UserPackage.getPackageInfosAllUsers(context, packageName, PACKAGE_FLAGS);
}
/**

View File

@@ -19,6 +19,7 @@ package com.android.settings.widget;
import android.app.AlertDialog;
import android.content.Context;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.PreferenceViewHolder;
import android.text.Editable;
import android.text.InputType;
import android.text.TextUtils;
@@ -27,6 +28,7 @@ import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import com.android.settingslib.CustomEditTextPreference;
@@ -42,6 +44,7 @@ public class ValidatedEditTextPreference extends CustomEditTextPreference {
private final EditTextWatcher mTextWatcher = new EditTextWatcher();
private Validator mValidator;
private boolean mIsPassword;
private boolean mIsSummaryPassword;
public ValidatedEditTextPreference(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
@@ -78,10 +81,25 @@ public class ValidatedEditTextPreference extends CustomEditTextPreference {
}
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
final TextView textView = (TextView) holder.findViewById(android.R.id.summary);
if (textView != null && mIsSummaryPassword) {
textView.setInputType(
InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
}
}
public void setIsPassword(boolean isPassword) {
mIsPassword = isPassword;
}
public void setIsSummaryPassword(boolean isPassword) {
mIsSummaryPassword = isPassword;
}
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
public boolean isPassword() {
return mIsPassword;

View File

@@ -51,6 +51,7 @@ public class WifiTetherPasswordPreferenceController extends WifiTetherBasePrefer
Log.d(TAG, "Updating password in Preference, " + mPassword);
}
((ValidatedEditTextPreference) mPreference).setValidator(this);
((ValidatedEditTextPreference) mPreference).setIsSummaryPassword(true);
updatePasswordDisplay((EditTextPreference) mPreference);
}

View File

@@ -27,6 +27,7 @@ import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.support.annotation.VisibleForTesting;
import com.android.settings.datausage.DataSaverBackend;
import com.android.settings.widget.SwitchWidgetController;
@@ -44,6 +45,16 @@ public class WifiTetherSwitchBarController implements SwitchWidgetController.OnS
private final ConnectivityManager mConnectivityManager;
private final DataSaverBackend mDataSaverBackend;
private final WifiManager mWifiManager;
@VisibleForTesting
final ConnectivityManager.OnStartTetheringCallback mOnStartTetheringCallback =
new ConnectivityManager.OnStartTetheringCallback() {
@Override
public void onTetheringFailed() {
super.onTetheringFailed();
mSwitchBar.setChecked(false);
updateWifiSwitch();
}
};
static {
WIFI_INTENT_FILTER = new IntentFilter(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
@@ -59,6 +70,7 @@ public class WifiTetherSwitchBarController implements SwitchWidgetController.OnS
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mSwitchBar.setChecked(mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED);
mSwitchBar.setListener(this);
updateWifiSwitch();
}
@Override
@@ -91,7 +103,7 @@ public class WifiTetherSwitchBarController implements SwitchWidgetController.OnS
void startTether() {
mSwitchBar.setEnabled(false);
mConnectivityManager.startTethering(TETHERING_WIFI, true /* showProvisioningUi */,
NoOpOnStartTetheringCallback.newInstance(), new Handler(Looper.getMainLooper()));
mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -103,7 +115,7 @@ public class WifiTetherSwitchBarController implements SwitchWidgetController.OnS
WifiManager.EXTRA_WIFI_AP_STATE, WifiManager.WIFI_AP_STATE_FAILED);
handleWifiApStateChanged(state);
} else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
enableWifiSwitch();
updateWifiSwitch();
}
}
};
@@ -117,7 +129,7 @@ public class WifiTetherSwitchBarController implements SwitchWidgetController.OnS
if (!mSwitchBar.isChecked()) {
mSwitchBar.setChecked(true);
}
enableWifiSwitch();
updateWifiSwitch();
break;
case WifiManager.WIFI_AP_STATE_DISABLING:
if (mSwitchBar.isChecked()) {
@@ -127,16 +139,16 @@ public class WifiTetherSwitchBarController implements SwitchWidgetController.OnS
break;
case WifiManager.WIFI_AP_STATE_DISABLED:
mSwitchBar.setChecked(false);
enableWifiSwitch();
updateWifiSwitch();
break;
default:
mSwitchBar.setChecked(false);
enableWifiSwitch();
updateWifiSwitch();
break;
}
}
private void enableWifiSwitch() {
private void updateWifiSwitch() {
boolean isAirplaneMode = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
if (!isAirplaneMode) {

View File

@@ -1,46 +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.wrapper;
import android.content.pm.PackageInfo;
import android.content.pm.UserInfo;
import android.webkit.UserPackage;
/**
* Default implementation of UserPackageWrapper.
*/
public class UserPackageWrapperImpl implements UserPackageWrapper {
private final UserPackage mUserPackage;
public UserPackageWrapperImpl(UserPackage userPackage) {
mUserPackage = userPackage;
}
public UserInfo getUserInfo() {
return mUserPackage.getUserInfo();
}
public PackageInfo getPackageInfo() {
return mUserPackage.getPackageInfo();
}
public boolean isEnabledPackage() {
return mUserPackage.isEnabledPackage();
}
public boolean isInstalledPackage() {
return mUserPackage.isInstalledPackage();
}
}

View File

@@ -0,0 +1,413 @@
/*
* 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.applications;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static com.android.settings.applications.AppStateNotificationBridge
.FILTER_APP_NOTIFICATION_FREQUENCY;
import static com.android.settings.applications.AppStateNotificationBridge
.FILTER_APP_NOTIFICATION_RECENCY;
import static com.android.settings.applications.AppStateNotificationBridge
.FREQUENCY_NOTIFICATION_COMPARATOR;
import static com.android.settings.applications.AppStateNotificationBridge
.RECENT_NOTIFICATION_COMPARATOR;
import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.app.usage.UsageEvents;
import android.app.usage.UsageEvents.Event;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.Looper;
import android.os.Parcel;
import com.android.settings.R;
import com.android.settings.applications.AppStateNotificationBridge.NotificationsSentState;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@RunWith(SettingsRobolectricTestRunner.class)
public class AppStateNotificationBridgeTest {
private static String PKG1 = "pkg1";
private static String PKG2 = "pkg2";
@Mock
private ApplicationsState.Session mSession;
@Mock
private ApplicationsState mState;
@Mock
private UsageStatsManager mUsageStats;
private Context mContext;
private AppStateNotificationBridge mBridge;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mState.newSession(any())).thenReturn(mSession);
when(mState.getBackgroundLooper()).thenReturn(mock(Looper.class));
mContext = RuntimeEnvironment.application.getApplicationContext();
mBridge = new AppStateNotificationBridge(mState,
mock(AppStateBaseBridge.Callback.class), mUsageStats);
}
private AppEntry getMockAppEntry(String pkg) {
AppEntry entry = mock(AppEntry.class);
entry.info = mock(ApplicationInfo.class);
entry.info.packageName = pkg;
return entry;
}
private UsageEvents getUsageEvents(List<Event> events) {
UsageEvents usageEvents = new UsageEvents(events, new String[] {PKG1, PKG2});
Parcel parcel = Parcel.obtain();
parcel.setDataPosition(0);
usageEvents.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
return UsageEvents.CREATOR.createFromParcel(parcel);
}
@Test
public void testGetAggregatedUsageEvents_noEvents() {
when(mUsageStats.queryEvents(anyLong(), anyLong())).thenReturn(mock(UsageEvents.class));
assertThat(mBridge.getAggregatedUsageEvents()).isEmpty();
}
@Test
public void testGetAggregatedUsageEvents_onlyNotificationEvents() {
List<Event> events = new ArrayList<>();
Event good = new Event();
good.mEventType = Event.NOTIFICATION_INTERRUPTION;
good.mPackage = PKG1;
good.mTimeStamp = 1;
events.add(good);
Event bad = new Event();
bad.mEventType = Event.CHOOSER_ACTION;
bad.mPackage = PKG1;
bad.mTimeStamp = 2;
events.add(bad);
UsageEvents usageEvents = getUsageEvents(events);
when(mUsageStats.queryEvents(anyLong(), anyLong())).thenReturn(usageEvents);
Map<String, NotificationsSentState> map = mBridge.getAggregatedUsageEvents();
assertThat(map.get(PKG1).sentCount).isEqualTo(1);
}
@Test
public void testGetAggregatedUsageEvents_multipleEventsAgg() {
List<Event> events = new ArrayList<>();
Event good = new Event();
good.mEventType = Event.NOTIFICATION_INTERRUPTION;
good.mPackage = PKG1;
good.mTimeStamp = 6;
events.add(good);
Event good1 = new Event();
good1.mEventType = Event.NOTIFICATION_INTERRUPTION;
good1.mPackage = PKG1;
good1.mTimeStamp = 1;
events.add(good1);
UsageEvents usageEvents = getUsageEvents(events);
when(mUsageStats.queryEvents(anyLong(), anyLong())).thenReturn(usageEvents);
Map<String, NotificationsSentState> map = mBridge.getAggregatedUsageEvents();
assertThat(map.get(PKG1).sentCount).isEqualTo(2);
assertThat(map.get(PKG1).lastSent).isEqualTo(6);
}
@Test
public void testGetAggregatedUsageEvents_multiplePkgs() {
List<Event> events = new ArrayList<>();
Event good = new Event();
good.mEventType = Event.NOTIFICATION_INTERRUPTION;
good.mPackage = PKG1;
good.mTimeStamp = 6;
events.add(good);
Event good1 = new Event();
good1.mEventType = Event.NOTIFICATION_INTERRUPTION;
good1.mPackage = PKG2;
good1.mTimeStamp = 1;
events.add(good1);
UsageEvents usageEvents = getUsageEvents(events);
when(mUsageStats.queryEvents(anyLong(), anyLong())).thenReturn(usageEvents);
Map<String, NotificationsSentState> map
= mBridge.getAggregatedUsageEvents();
assertThat(map.get(PKG1).sentCount).isEqualTo(1);
assertThat(map.get(PKG2).sentCount).isEqualTo(1);
assertThat(map.get(PKG1).lastSent).isEqualTo(6);
assertThat(map.get(PKG2).lastSent).isEqualTo(1);
}
@Test
public void testLoadAllExtraInfo_noEvents() {
when(mUsageStats.queryEvents(anyLong(), anyLong())).thenReturn(mock(UsageEvents.class));
ArrayList<AppEntry> apps = new ArrayList<>();
apps.add(getMockAppEntry(PKG1));
when(mSession.getAllApps()).thenReturn(apps);
mBridge.loadAllExtraInfo();
assertThat(apps.get(0).extraInfo).isNull();
}
@Test
public void testLoadAllExtraInfo_multipleEventsAgg() {
List<Event> events = new ArrayList<>();
for (int i = 0; i < 7; i++) {
Event good = new Event();
good.mEventType = Event.NOTIFICATION_INTERRUPTION;
good.mPackage = PKG1;
good.mTimeStamp = i;
events.add(good);
}
UsageEvents usageEvents = getUsageEvents(events);
when(mUsageStats.queryEvents(anyLong(), anyLong())).thenReturn(usageEvents);
ArrayList<AppEntry> apps = new ArrayList<>();
apps.add(getMockAppEntry(PKG1));
when(mSession.getAllApps()).thenReturn(apps);
mBridge.loadAllExtraInfo();
assertThat(((NotificationsSentState) apps.get(0).extraInfo).sentCount).isEqualTo(7);
assertThat(((NotificationsSentState) apps.get(0).extraInfo).lastSent).isEqualTo(6);
assertThat(((NotificationsSentState) apps.get(0).extraInfo).avgSentDaily).isEqualTo(1);
assertThat(((NotificationsSentState) apps.get(0).extraInfo).avgSentWeekly).isEqualTo(0);
}
@Test
public void testLoadAllExtraInfo_multiplePkgs() {
List<Event> events = new ArrayList<>();
for (int i = 0; i < 8; i++) {
Event good = new Event();
good.mEventType = Event.NOTIFICATION_INTERRUPTION;
good.mPackage = PKG1;
good.mTimeStamp = i;
events.add(good);
}
Event good1 = new Event();
good1.mEventType = Event.NOTIFICATION_INTERRUPTION;
good1.mPackage = PKG2;
good1.mTimeStamp = 1;
events.add(good1);
UsageEvents usageEvents = getUsageEvents(events);
when(mUsageStats.queryEvents(anyLong(), anyLong())).thenReturn(usageEvents);
ArrayList<AppEntry> apps = new ArrayList<>();
apps.add(getMockAppEntry(PKG1));
apps.add(getMockAppEntry(PKG2));
when(mSession.getAllApps()).thenReturn(apps);
mBridge.loadAllExtraInfo();
assertThat(((NotificationsSentState) apps.get(0).extraInfo).sentCount).isEqualTo(8);
assertThat(((NotificationsSentState) apps.get(0).extraInfo).lastSent).isEqualTo(7);
assertThat(((NotificationsSentState) apps.get(0).extraInfo).avgSentWeekly).isEqualTo(0);
assertThat(((NotificationsSentState) apps.get(0).extraInfo).avgSentDaily).isEqualTo(1);
assertThat(((NotificationsSentState) apps.get(1).extraInfo).sentCount).isEqualTo(1);
assertThat(((NotificationsSentState) apps.get(1).extraInfo).lastSent).isEqualTo(1);
assertThat(((NotificationsSentState) apps.get(1).extraInfo).avgSentWeekly).isEqualTo(1);
assertThat(((NotificationsSentState) apps.get(1).extraInfo).avgSentDaily).isEqualTo(0);
}
@Test
public void testUpdateExtraInfo_noEvents() {
when(mUsageStats.queryEvents(anyLong(), anyLong())).thenReturn(mock(UsageEvents.class));
AppEntry entry = getMockAppEntry(PKG1);
mBridge.updateExtraInfo(entry, "", 0);
assertThat(entry.extraInfo).isNull();
}
@Test
public void testUpdateExtraInfo_multipleEventsAgg() {
List<Event> events = new ArrayList<>();
for (int i = 0; i < 13; i++) {
Event good = new Event();
good.mEventType = Event.NOTIFICATION_INTERRUPTION;
good.mPackage = PKG1;
good.mTimeStamp = i;
events.add(good);
}
UsageEvents usageEvents = getUsageEvents(events);
when(mUsageStats.queryEvents(anyLong(), anyLong())).thenReturn(usageEvents);
AppEntry entry = getMockAppEntry(PKG1);
mBridge.updateExtraInfo(entry, "", 0);
assertThat(((NotificationsSentState) entry.extraInfo).sentCount).isEqualTo(13);
assertThat(((NotificationsSentState) entry.extraInfo).lastSent).isEqualTo(12);
assertThat(((NotificationsSentState) entry.extraInfo).avgSentDaily).isEqualTo(2);
assertThat(((NotificationsSentState) entry.extraInfo).avgSentWeekly).isEqualTo(0);
}
@Test
public void testSummary_recency() {
NotificationsSentState neverSent = new NotificationsSentState();
NotificationsSentState sent = new NotificationsSentState();
sent.lastSent = System.currentTimeMillis() - (2 * DAY_IN_MILLIS);
assertThat(AppStateNotificationBridge.getSummary(mContext, neverSent, true)).isEqualTo(
mContext.getString(R.string.notifications_sent_never));
assertThat(AppStateNotificationBridge.getSummary(mContext, sent, true).toString())
.contains("2");
}
@Test
public void testSummary_frequency() {
NotificationsSentState sentRarely = new NotificationsSentState();
sentRarely.avgSentWeekly = 1;
NotificationsSentState sentOften = new NotificationsSentState();
sentOften.avgSentDaily = 8;
assertThat(AppStateNotificationBridge.getSummary(mContext, sentRarely, false).toString())
.contains("1");
assertThat(AppStateNotificationBridge.getSummary(mContext, sentOften, false).toString())
.contains("8");
}
@Test
public void testFilterRecency() {
NotificationsSentState allowState = new NotificationsSentState();
allowState.lastSent = 1;
AppEntry allow = mock(AppEntry.class);
allow.extraInfo = allowState;
assertTrue(FILTER_APP_NOTIFICATION_RECENCY.filterApp(allow));
NotificationsSentState denyState = new NotificationsSentState();
denyState.lastSent = 0;
AppEntry deny = mock(AppEntry.class);
deny.extraInfo = denyState;
assertFalse(FILTER_APP_NOTIFICATION_RECENCY.filterApp(deny));
}
@Test
public void testFilterFrequency() {
NotificationsSentState allowState = new NotificationsSentState();
allowState.sentCount = 1;
AppEntry allow = mock(AppEntry.class);
allow.extraInfo = allowState;
assertTrue(FILTER_APP_NOTIFICATION_FREQUENCY.filterApp(allow));
NotificationsSentState denyState = new NotificationsSentState();
denyState.sentCount = 0;
AppEntry deny = mock(AppEntry.class);
deny.extraInfo = denyState;
assertFalse(FILTER_APP_NOTIFICATION_FREQUENCY.filterApp(deny));
}
@Test
public void testComparators_nullsNoCrash() {
List<AppEntry> entries = new ArrayList<>();
AppEntry a = mock(AppEntry.class);
a.label = "1";
AppEntry b = mock(AppEntry.class);
b.label = "2";
entries.add(a);
entries.add(b);
entries.sort(RECENT_NOTIFICATION_COMPARATOR);
entries.sort(FREQUENCY_NOTIFICATION_COMPARATOR);
}
@Test
public void testRecencyComparator() {
List<AppEntry> entries = new ArrayList<>();
NotificationsSentState earlier = new NotificationsSentState();
earlier.lastSent = 1;
AppEntry earlyEntry = mock(AppEntry.class);
earlyEntry.extraInfo = earlier;
entries.add(earlyEntry);
NotificationsSentState later = new NotificationsSentState();
later.lastSent = 8;
AppEntry lateEntry = mock(AppEntry.class);
lateEntry.extraInfo = later;
entries.add(lateEntry);
entries.sort(RECENT_NOTIFICATION_COMPARATOR);
assertThat(entries).containsExactly(lateEntry, earlyEntry);
}
@Test
public void testFrequencyComparator() {
List<AppEntry> entries = new ArrayList<>();
NotificationsSentState notFrequentWeekly = new NotificationsSentState();
notFrequentWeekly.sentCount = 2;
AppEntry notFrequentWeeklyEntry = mock(AppEntry.class);
notFrequentWeeklyEntry.extraInfo = notFrequentWeekly;
entries.add(notFrequentWeeklyEntry);
NotificationsSentState notFrequentDaily = new NotificationsSentState();
notFrequentDaily.sentCount = 7;
AppEntry notFrequentDailyEntry = mock(AppEntry.class);
notFrequentDailyEntry.extraInfo = notFrequentDaily;
entries.add(notFrequentDailyEntry);
NotificationsSentState veryFrequentWeekly = new NotificationsSentState();
veryFrequentWeekly.sentCount = 6;
AppEntry veryFrequentWeeklyEntry = mock(AppEntry.class);
veryFrequentWeeklyEntry.extraInfo = veryFrequentWeekly;
entries.add(veryFrequentWeeklyEntry);
NotificationsSentState veryFrequentDaily = new NotificationsSentState();
veryFrequentDaily.sentCount = 19;
AppEntry veryFrequentDailyEntry = mock(AppEntry.class);
veryFrequentDailyEntry.extraInfo = veryFrequentDaily;
entries.add(veryFrequentDailyEntry);
entries.sort(FREQUENCY_NOTIFICATION_COMPARATOR);
assertThat(entries).containsExactly(veryFrequentDailyEntry, notFrequentDailyEntry,
veryFrequentWeeklyEntry, notFrequentWeeklyEntry);
}
}

View File

@@ -312,7 +312,7 @@ public class RecentAppsPreferenceControllerTest {
mController.displayPreference(mScreen);
verify(mCategory).addPreference(argThat(summaryMatches("0 min. ago")));
verify(mCategory).addPreference(argThat(summaryMatches("0 minutes ago")));
}
private static ArgumentMatcher<Preference> summaryMatches(String expected) {

View File

@@ -0,0 +1,98 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications.appinfo;
import static android.content.Intent.EXTRA_PACKAGE_NAME;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.core.BasePreferenceController;
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.Shadows;
import org.robolectric.shadows.ShadowPackageManager;
@RunWith(SettingsRobolectricTestRunner.class)
public class TimeSpentInAppPreferenceControllerTest {
private static final String TEST_KEY = "test_tey";
private static final Intent TEST_INTENT = new Intent(
TimeSpentInAppPreferenceController.SEE_TIME_IN_APP_TEMPLATE)
.putExtra(EXTRA_PACKAGE_NAME, "com.android.settings");
@Mock
private PreferenceScreen mScreen;
private Context mContext;
private ShadowPackageManager mPackageManager;
private TimeSpentInAppPreferenceController mController;
private Preference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mPackageManager = Shadows.shadowOf(mContext.getPackageManager());
mController = new TimeSpentInAppPreferenceController(mContext, TEST_KEY);
mPreference = new Preference(mContext);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
}
@Test
public void noPackageName_shouldBeDisabled() {
mController.setPackageName(null);
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.DISABLED_UNSUPPORTED);
}
@Test
public void noIntentHandler_shouldBeDisabled() {
mController.setPackageName(TEST_INTENT.getStringExtra(EXTRA_PACKAGE_NAME));
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.DISABLED_UNSUPPORTED);
}
@Test
public void hasIntentHandler_shouldBeAvailable() {
mPackageManager.addResolveInfoForIntent(TEST_INTENT, new ResolveInfo());
mController.setPackageName(TEST_INTENT.getStringExtra(EXTRA_PACKAGE_NAME));
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.AVAILABLE);
mController.displayPreference(mScreen);
final Intent intent = mPreference.getIntent();
assertThat(intent.getAction()).isEqualTo(TEST_INTENT.getAction());
assertThat(intent.getStringExtra(EXTRA_PACKAGE_NAME))
.isEqualTo(TEST_INTENT.getStringExtra(EXTRA_PACKAGE_NAME));
}
}

View File

@@ -16,7 +16,6 @@
package com.android.settings.applications.manageapplications;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_BLOCKED;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_ENABLED;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_USAGE_ACCESS;
import static com.google.common.truth.Truth.assertThat;
@@ -80,7 +79,7 @@ public class AppFilterItemTest {
@Test
public void hash_differentItem_differentHash() {
final AppFilterItem item = AppFilterRegistry.getInstance().get(FILTER_APPS_USAGE_ACCESS);
final AppFilterItem item2 = AppFilterRegistry.getInstance().get(FILTER_APPS_BLOCKED);
final AppFilterItem item2 = AppFilterRegistry.getInstance().get(FILTER_APPS_ENABLED);
assertThat(item.hashCode()).isNotEqualTo(item2.hashCode());
}

View File

@@ -19,6 +19,9 @@ package com.android.settings.applications.manageapplications;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_ALL;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_INSTALL_SOURCES;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_POWER_WHITELIST;
import static com.android.settings.applications.manageapplications.AppFilterRegistry
.FILTER_APPS_RECENT;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_USAGE_ACCESS;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_WITH_OVERLAY;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_WRITE_SETTINGS;
@@ -45,24 +48,25 @@ public class AppFilterRegistryTest {
@Test
public void getDefaultType_shouldMatchForAllListType() {
final AppFilterRegistry registry = AppFilterRegistry.getInstance();
assertThat(registry.getDefaultFilterType(LIST_TYPE_USAGE_ACCESS))
.isEqualTo(FILTER_APPS_USAGE_ACCESS);
assertThat(registry.getDefaultFilterType(LIST_TYPE_HIGH_POWER))
.isEqualTo(FILTER_APPS_POWER_WHITELIST);
assertThat(registry.getDefaultFilterType(LIST_TYPE_OVERLAY))
.isEqualTo(FILTER_APPS_WITH_OVERLAY);
assertThat(registry.getDefaultFilterType(LIST_TYPE_WRITE_SETTINGS))
.isEqualTo(FILTER_APPS_WRITE_SETTINGS);
assertThat(registry.getDefaultFilterType(LIST_TYPE_MANAGE_SOURCES))
.isEqualTo(FILTER_APPS_INSTALL_SOURCES);
final AppFilterRegistry registry = AppFilterRegistry.getInstance();
assertThat(registry.getDefaultFilterType(LIST_TYPE_USAGE_ACCESS))
.isEqualTo(FILTER_APPS_USAGE_ACCESS);
assertThat(registry.getDefaultFilterType(LIST_TYPE_HIGH_POWER))
.isEqualTo(FILTER_APPS_POWER_WHITELIST);
assertThat(registry.getDefaultFilterType(LIST_TYPE_OVERLAY))
.isEqualTo(FILTER_APPS_WITH_OVERLAY);
assertThat(registry.getDefaultFilterType(LIST_TYPE_WRITE_SETTINGS))
.isEqualTo(FILTER_APPS_WRITE_SETTINGS);
assertThat(registry.getDefaultFilterType(LIST_TYPE_MANAGE_SOURCES))
.isEqualTo(FILTER_APPS_INSTALL_SOURCES);
assertThat(registry.getDefaultFilterType(LIST_TYPE_MAIN)).isEqualTo(FILTER_APPS_ALL);
assertThat(registry.getDefaultFilterType(LIST_TYPE_NOTIFICATION)).isEqualTo(FILTER_APPS_ALL);
assertThat(registry.getDefaultFilterType(LIST_TYPE_STORAGE)).isEqualTo(FILTER_APPS_ALL);
assertThat(registry.getDefaultFilterType(LIST_TYPE_MAIN)).isEqualTo(FILTER_APPS_ALL);
assertThat(registry.getDefaultFilterType(LIST_TYPE_NOTIFICATION))
.isEqualTo(FILTER_APPS_RECENT);
assertThat(registry.getDefaultFilterType(LIST_TYPE_STORAGE)).isEqualTo(FILTER_APPS_ALL);
assertThat(registry.getDefaultFilterType(LIST_TYPE_GAMES)).isEqualTo(FILTER_APPS_ALL);
assertThat(registry.getDefaultFilterType(LIST_TYPE_MOVIES)).isEqualTo(FILTER_APPS_ALL);
assertThat(registry.getDefaultFilterType(LIST_TYPE_PHOTOGRAPHY)).isEqualTo(FILTER_APPS_ALL);
assertThat(registry.getDefaultFilterType(LIST_TYPE_GAMES)).isEqualTo(FILTER_APPS_ALL);
assertThat(registry.getDefaultFilterType(LIST_TYPE_MOVIES)).isEqualTo(FILTER_APPS_ALL);
assertThat(registry.getDefaultFilterType(LIST_TYPE_PHOTOGRAPHY)).isEqualTo(FILTER_APPS_ALL);
}
}

View File

@@ -67,12 +67,16 @@ public class ManageApplicationsTest {
@Mock
private Menu mMenu;
private MenuItem mAppReset;
private MenuItem mSortRecent;
private MenuItem mSortFrequent;
private ManageApplications mFragment;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mAppReset = new RoboMenuItem(R.id.reset_app_preferences);
mSortRecent = new RoboMenuItem(R.id.sort_order_recent_notification);
mSortFrequent = new RoboMenuItem(R.id.sort_order_frequent_notification);
ReflectionHelpers.setStaticField(ApplicationsState.class, "sInstance", mState);
when(mState.newSession(any())).thenReturn(mSession);
when(mState.getBackgroundLooper()).thenReturn(Looper.myLooper());
@@ -100,6 +104,18 @@ public class ManageApplicationsTest {
assertThat(mMenu.findItem(R.id.reset_app_preferences).isVisible()).isFalse();
}
@Test
public void updateMenu_hideNotificationOptions() {
setUpOptionMenus();
ReflectionHelpers.setField(mFragment, "mListType", LIST_TYPE_NOTIFICATION);
ReflectionHelpers.setField(mFragment, "mOptionsMenu", mMenu);
mFragment.updateOptionsMenu();
assertThat(mMenu.findItem(R.id.sort_order_recent_notification).isVisible()).isFalse();
assertThat(mMenu.findItem(R.id.sort_order_frequent_notification).isVisible()).isFalse();
}
@Test
public void onCreateView_shouldNotShowLoadingContainer() {
final ManageApplications fragment = spy(new ManageApplications());
@@ -220,6 +236,12 @@ public class ManageApplicationsTest {
if (id == mAppReset.getItemId()) {
return mAppReset;
}
if (id == mSortFrequent.getItemId()) {
return mSortFrequent;
}
if (id == mSortRecent.getItemId()) {
return mSortRecent;
}
return new RoboMenuItem(id);
});
}

View File

@@ -16,6 +16,7 @@
package com.android.settings.bluetooth;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Mockito.mock;
@@ -36,11 +37,11 @@ import android.view.View;
import android.widget.Switch;
import com.android.settings.R;
import com.android.settings.bluetooth.BluetoothSwitchPreferenceController.SwitchController;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settings.widget.MasterSwitchController;
import com.android.settings.widget.MasterSwitchPreference;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
@@ -60,6 +61,8 @@ import org.robolectric.annotation.Config;
public class BluetoothEnablerTest {
private static EnforcedAdmin sFakeEnforcedAdmin;
private PreferenceViewHolder mHolder;
private RestrictedSwitchPreference mRestrictedSwitchPreference;
@BeforeClass
public static void beforeClass() {
@@ -76,8 +79,7 @@ public class BluetoothEnablerTest {
private LocalBluetoothAdapter mBluetoothAdapter;
private Context mContext;
private Switch mSwitch;
private MasterSwitchController mMasterSwitchController;
private SwitchController mSwitchController;
private BluetoothEnabler mBluetoothEnabler;
@Before
@@ -86,19 +88,17 @@ public class BluetoothEnablerTest {
mContext = spy(RuntimeEnvironment.application);
when(mBluetoothManager.getBluetoothAdapter()).thenReturn(mBluetoothAdapter);
mSwitch = new Switch(mContext);
MasterSwitchPreference masterSwitchPreference = new MasterSwitchPreference(mContext);
mMasterSwitchController = spy(new MasterSwitchController(masterSwitchPreference));
mRestrictedSwitchPreference = new RestrictedSwitchPreference(mContext);
mSwitchController = spy(new SwitchController(mRestrictedSwitchPreference));
mBluetoothEnabler = new BluetoothEnabler(
mContext,
mMasterSwitchController,
mSwitchController,
mMetricsFeatureProvider,
mBluetoothManager,
123,
mRestrictionUtils);
PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(mock(View.class));
when(holder.findViewById(R.id.switchWidget)).thenReturn(mSwitch);
masterSwitchPreference.onBindViewHolder(holder);
mHolder = PreferenceViewHolder.createInstanceForTests(mock(View.class));
mRestrictedSwitchPreference.onBindViewHolder(mHolder);
}
@Test
@@ -121,9 +121,9 @@ public class BluetoothEnablerTest {
assertThat(mBluetoothEnabler.maybeEnforceRestrictions()).isFalse();
// THEN a null EnfoceAdmin is set.
verify(mMasterSwitchController).setDisabledByAdmin(null);
verify(mSwitchController).setDisabledByAdmin(null);
// THEN the state of the switch isn't changed.
verify(mMasterSwitchController, never()).setChecked(anyBoolean());
verify(mSwitchController, never()).setChecked(anyBoolean());
}
@Test
@@ -139,10 +139,10 @@ public class BluetoothEnablerTest {
assertThat(mBluetoothEnabler.maybeEnforceRestrictions()).isTrue();
// THEN the expected EnfoceAdmin is set.
verify(mMasterSwitchController).setDisabledByAdmin(sFakeEnforcedAdmin);
verify(mSwitchController).setDisabledByAdmin(sFakeEnforcedAdmin);
// THEN the switch is unchecked.
verify(mMasterSwitchController).setChecked(false);
verify(mSwitchController).setChecked(false);
}
@Test
@@ -158,10 +158,10 @@ public class BluetoothEnablerTest {
assertThat(mBluetoothEnabler.maybeEnforceRestrictions()).isTrue();
// THEN the expected EnfoceAdmin is set.
verify(mMasterSwitchController).setDisabledByAdmin(sFakeEnforcedAdmin);
verify(mSwitchController).setDisabledByAdmin(sFakeEnforcedAdmin);
// THEN the switch is unchecked.
verify(mMasterSwitchController).setChecked(false);
verify(mSwitchController).setChecked(false);
}
@Test
@@ -174,37 +174,36 @@ public class BluetoothEnablerTest {
mBluetoothEnabler.resume(mContext);
verify(mMasterSwitchController, never()).setEnabled(true);
verify(mSwitchController, never()).setEnabled(true);
}
@Test
public void startWithBluetoothOff_switchIsOff() {
when(mBluetoothAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_OFF);
verify(mMasterSwitchController, never()).setChecked(anyBoolean());
verify(mSwitchController, never()).setChecked(anyBoolean());
mBluetoothEnabler.resume(mContext);
verify(mMasterSwitchController, never()).setChecked(true);
verify(mSwitchController, never()).setChecked(true);
}
@Test
public void startWithBluetoothOn_switchIsOn() {
when(mBluetoothAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON);
verify(mMasterSwitchController, never()).setChecked(anyBoolean());
verify(mSwitchController, never()).setChecked(anyBoolean());
mBluetoothEnabler.resume(mContext);
verify(mMasterSwitchController, never()).setChecked(false);
verify(mMasterSwitchController).setChecked(true);
verify(mSwitchController, never()).setChecked(false);
verify(mSwitchController).setChecked(true);
}
@Test
public void bluetoothTurnsOff_switchTurnsOff() {
// Start up with bluetooth turned on. The switch should get turned on.
assertThat(mSwitch.isChecked()).isFalse();
ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class);
when(mContext.registerReceiver(captor.capture(), any(IntentFilter.class))).thenReturn(null);
when(mBluetoothAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON);
verify(mMasterSwitchController, never()).setChecked(anyBoolean());
verify(mSwitchController, never()).setChecked(anyBoolean());
mBluetoothEnabler.resume(mContext);
verify(mMasterSwitchController, never()).setChecked(false);
verify(mMasterSwitchController).setChecked(true);
verify(mSwitchController, never()).setChecked(false);
verify(mSwitchController).setChecked(true);
// Now simulate bluetooth being turned off via an event.
BroadcastReceiver receiver = captor.getValue();
@@ -216,20 +215,18 @@ public class BluetoothEnablerTest {
receiver.onReceive(mContext, off);
// Make sure the switch was turned off.
verify(mMasterSwitchController).setChecked(false);
assertThat(mSwitch.isChecked()).isFalse();
verify(mSwitchController).setChecked(false);
}
@Test
public void bluetoothTurnsOn_switchTurnsOn() {
// Start up with bluetooth turned on. The switch should be left off.
assertThat(mSwitch.isChecked()).isFalse();
ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class);
when(mContext.registerReceiver(captor.capture(), any(IntentFilter.class))).thenReturn(null);
when(mBluetoothAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_OFF);
verify(mMasterSwitchController, never()).setChecked(anyBoolean());
verify(mSwitchController, never()).setChecked(anyBoolean());
mBluetoothEnabler.resume(mContext);
verify(mMasterSwitchController, never()).setChecked(anyBoolean());
verify(mSwitchController, never()).setChecked(anyBoolean());
// Now simulate bluetooth being turned on via an event.
BroadcastReceiver receiver = captor.getValue();
@@ -241,7 +238,6 @@ public class BluetoothEnablerTest {
receiver.onReceive(mContext, on);
// Make sure the switch was turned on.
verify(mMasterSwitchController).setChecked(true);
assertThat(mSwitch.isChecked()).isTrue();
verify(mSwitchController).setChecked(true);
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.bluetooth;
import static com.google.common.truth.Truth.assertThat;
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.AlertDialog;
import android.content.Context;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowAlertDialog;
import org.robolectric.util.FragmentTestUtil;
import org.robolectric.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
public class LocalDeviceNameDialogFragmentTest {
@Mock
private LocalBluetoothManager mManager;
@Mock
private LocalBluetoothAdapter mAdapter;
@Mock
private InputMethodManager mInputMethodManager;
private Context mContext;
private LocalDeviceNameDialogFragment mFragment;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
doReturn(mInputMethodManager).when(mContext).getSystemService(Context.INPUT_METHOD_SERVICE);
ReflectionHelpers.setStaticField(LocalBluetoothManager.class, "sInstance", mManager);
when(mManager.getBluetoothAdapter()).thenReturn(mAdapter);
mFragment = spy(LocalDeviceNameDialogFragment.newInstance());
when(mFragment.getContext()).thenReturn(mContext);
}
@Test
public void diaglogTriggersShowSoftInput() {
FragmentTestUtil.startFragment(mFragment);
AlertDialog dialog = ShadowAlertDialog.getLatestAlertDialog();
assertThat(dialog).isNotNull();
View view = dialog.findViewById(R.id.edittext);
verify(mInputMethodManager).showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.settings.core;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.support.v7.preference.SeekBarPreference;
import com.android.settings.slices.SliceData;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
@RunWith(SettingsRobolectricTestRunner.class)
public class SliderPreferenceControllerTest {
FakeSlider mSliderController;
Context mContext;
SeekBarPreference mPreference;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mPreference = new SeekBarPreference(mContext);
mSliderController = new FakeSlider(mContext, "key");
}
@Test
public void onPreferenceChange_updatesPosition() {
final int newValue = 28;
mSliderController.onPreferenceChange(mPreference, newValue);
assertThat(mSliderController.getSliderPosition()).isEqualTo(newValue);
}
@Test
public void updateState_setsPreferenceToCurrentValue() {
final int newValue = 28;
mSliderController.setSliderPosition(newValue);
mSliderController.updateState(mPreference);
assertThat(mPreference.getValue()).isEqualTo(newValue);
}
@Test
public void testSliceType_returnsSliceType() {
assertThat(mSliderController.getSliceType()).isEqualTo(
SliceData.SliceType.SLIDER);
}
private class FakeSlider extends SliderPreferenceController {
private final int MAX_STEPS = 2112;
private int mPosition;
public FakeSlider(Context context, String key) {
super(context, key);
}
@Override
public int getSliderPosition() {
return mPosition;
}
@Override
public boolean setSliderPosition(int position) {
mPosition = position;
return true;
}
@Override
public int getMaxSteps() {
return MAX_STEPS;
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
}
}

View File

@@ -18,6 +18,7 @@ package com.android.settings.dashboard.conditional;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -26,6 +27,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
@@ -47,6 +49,7 @@ public class DndConditionTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
FakeFeatureFactory.setupForTest();
when(mConditionManager.getContext()).thenReturn(mContext);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
}
@@ -90,4 +93,15 @@ public class DndConditionTest {
verify(mContext).unregisterReceiver(any(DndCondition.Receiver.class));
}
@Test
public void onPause_noReceiverRegistered_shouldNotUnregisterReceiver() {
DndCondition condition = new DndCondition(mConditionManager);
condition.onPause();
reset(mContext);
condition.onPause();
verify(mContext, never()).unregisterReceiver(any(DndCondition.Receiver.class));
}
}

View File

@@ -16,12 +16,19 @@
package com.android.settings.datausage;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.NetworkTemplate;
import android.os.Bundle;
import android.provider.Settings;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -62,10 +69,38 @@ public class DataUsageListTest {
mDataUsageList.onAttach(mContext);
mDataUsageList.onResume();
verify(mListener).setListener(true, 0, mContext);
verify(mListener).setListener(true, mDataUsageList.mSubId, mContext);
mDataUsageList.onPause();
verify(mListener).setListener(false, 0, mContext);
verify(mListener).setListener(false, mDataUsageList.mSubId, mContext);
}
@Test
public void processArgument_shouldGetTemplateFromArgument() {
final Bundle args = new Bundle();
args.putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE, mock(NetworkTemplate.class));
args.putInt(DataUsageList.EXTRA_SUB_ID, 3);
mDataUsageList.setArguments(args);
mDataUsageList.processArgument();
assertThat(mDataUsageList.mTemplate).isNotNull();
assertThat(mDataUsageList.mSubId).isEqualTo(3);
}
@Test
public void processArgument_fromIntent_shouldGetTemplateFromIntent() {
final Activity activity = mock(Activity.class);
final Intent intent = new Intent();
intent.putExtra(Settings.EXTRA_NETWORK_TEMPLATE, mock(NetworkTemplate.class));
intent.putExtra(Settings.EXTRA_SUB_ID, 3);
when(activity.getIntent()).thenReturn(intent);
doReturn(activity).when(mDataUsageList).getActivity();
mDataUsageList.processArgument();
assertThat(mDataUsageList.mTemplate).isNotNull();
assertThat(mDataUsageList.mSubId).isEqualTo(3);
}
}

View File

@@ -118,6 +118,7 @@ public class DevelopmentSettingsDashboardFragmentTest {
final Context appContext = RuntimeEnvironment.application;
DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(appContext, true);
mShadowUserManager.setIsAdminUser(false);
mShadowUserManager.setIsDemoUser(false);
final List<String> nonIndexableKeys =
DevelopmentSettingsDashboardFragment.SEARCH_INDEX_DATA_PROVIDER

View File

@@ -22,7 +22,6 @@ import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -57,7 +56,6 @@ import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowUserManager;
import org.robolectric.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = ShadowUtils.class)
@@ -84,24 +82,27 @@ public class BuildNumberPreferenceControllerTest {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
final UserManager userManager =
(UserManager) mContext.getSystemService(Context.USER_SERVICE);
(UserManager) mContext.getSystemService(Context.USER_SERVICE);
mShadowUserManager = Shadows.shadowOf(userManager);
mShadowUserManager.setIsAdminUser(true);
mFactory = FakeFeatureFactory.setupForTest();
mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner);
mController =
new BuildNumberPreferenceController(mContext, mActivity, mFragment, mLifecycle);
new BuildNumberPreferenceController(mContext, mActivity, mFragment, mLifecycle);
mPreference = new Preference(mContext);
mPreference.setKey(mController.getPreferenceKey());
DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(mContext, false);
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 1);
}
@After
public void tearDown() {
ShadowUtils.reset();
mShadowUserManager.setIsAdminUser(false);
mShadowUserManager.setIsDemoUser(false);
}
@Test
@@ -119,20 +120,36 @@ public class BuildNumberPreferenceControllerTest {
}
@Test
public void handlePrefTreeClick_notAdminUser_doNothing() {
public void handlePrefTreeClick_notAdminUser_notDemoUser_doNothing() {
mShadowUserManager.setIsAdminUser(false);
mShadowUserManager.setIsDemoUser(false);
assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
}
@Test
public void handlePrefTreeClick_deviceNotProvisioned_doNothing() {
final Context context = RuntimeEnvironment.application;
Settings.Global.putInt(context.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0);
public void handlePrefTreeClick_isAdminUser_notDemoUser_handleBuildNumberPref() {
mShadowUserManager.setIsAdminUser(true);
mShadowUserManager.setIsDemoUser(false);
mController =
new BuildNumberPreferenceController(context, mActivity, mFragment, mLifecycle);
ReflectionHelpers.setField(mController, "mContext", context);
assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
}
@Test
public void handlePrefTreeClick_notAdminUser_isDemoUser_handleBuildNumberPref() {
mShadowUserManager.setIsAdminUser(false);
mShadowUserManager.setIsDemoUser(true);
assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
}
@Test
public void handlePrefTreeClick_deviceNotProvisioned_doNothing() {
mShadowUserManager.setIsAdminUser(true);
mShadowUserManager.setIsDemoUser(false);
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED,
0);
assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
verify(mFactory.metricsFeatureProvider).action(
@@ -142,26 +159,17 @@ public class BuildNumberPreferenceControllerTest {
@Test
public void handlePrefTreeClick_isMonkeyRun_doNothing() {
final Context context = spy(RuntimeEnvironment.application);
Settings.Global.putInt(context.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);
ShadowUtils.setIsUserAMonkey(true);
mController =
new BuildNumberPreferenceController(context, mActivity, mFragment, mLifecycle);
assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
}
@Test
public void handlePrefTreeClick_userHasRestriction_doNothing() {
final Context context = spy(RuntimeEnvironment.application);
Settings.Global.putInt(context.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);
mShadowUserManager.setIsAdminUser(true);
mShadowUserManager.setIsDemoUser(false);
mShadowUserManager.setUserRestriction(Process.myUserHandle(),
UserManager.DISALLOW_DEBUGGING_FEATURES, true);
mController =
new BuildNumberPreferenceController(mContext, mActivity, mFragment, mLifecycle);
ReflectionHelpers.setField(mController, "mContext", context);
UserManager.DISALLOW_DEBUGGING_FEATURES, true);
assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
verify(mFactory.metricsFeatureProvider).action(
@@ -197,7 +205,7 @@ public class BuildNumberPreferenceControllerTest {
.thenReturn(mock(DatabaseIndexingManager.class));
mController =
new BuildNumberPreferenceController(mContext, mActivity, mFragment, mLifecycle);
new BuildNumberPreferenceController(mContext, mActivity, mFragment, mLifecycle);
final boolean activityResultHandled = mController.onActivityResult(
BuildNumberPreferenceController.REQUEST_CONFIRM_PASSWORD_FOR_DEV_PREF,

View File

@@ -73,13 +73,15 @@ public class ColorModePreferenceFragmentTest {
when(mFragment.getContext()).thenReturn(RuntimeEnvironment.application);
List<? extends CandidateInfo> candidates = mFragment.getCandidates();
assertThat(candidates.size()).isEqualTo(3);
assertThat(candidates.size()).isEqualTo(4);
assertThat(candidates.get(0).getKey())
.isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_NATURAL);
assertThat(candidates.get(1).getKey())
.isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_BOOSTED);
assertThat(candidates.get(2).getKey())
.isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_SATURATED);
assertThat(candidates.get(3).getKey())
.isEqualTo(ColorModePreferenceFragment.KEY_COLOR_MODE_AUTOMATIC);
}
@Test

Some files were not shown because too many files have changed in this diff Show More