Merge "Add a helper class for listening to subscription and airplane mode changes"
diff --git a/res/drawable/ic_find_in_page_24px.xml b/res/drawable/ic_find_in_page_24px.xml
new file mode 100644
index 0000000..18895e4
--- /dev/null
+++ b/res/drawable/ic_find_in_page_24px.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?android:attr/colorControlNormal">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M6,2C4.9,2 4.01,2.9 4.01,4L4,20c0,1.1 0.89,2 1.99,2H18c1.1,0 2,-0.9 2,-2V8l-6,-6H6zM18,17.59l-2.2,-2.2c0.44,-0.69 0.7,-1.51 0.7,-2.39c0,-2.48 -2.02,-4.5 -4.5,-4.5S7.5,10.52 7.5,13s2.02,4.5 4.5,4.5c0.88,0 1.69,-0.26 2.39,-0.7l3.2,3.2L6,20V4h7.17L18,8.83V17.59zM12,15.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5s2.5,1.12 2.5,2.5S13.38,15.5 12,15.5z"/>
+</vector>
diff --git a/res/drawable/ic_qrcode_24dp.xml b/res/drawable/ic_qrcode_24dp.xml
new file mode 100644
index 0000000..ff7806f
--- /dev/null
+++ b/res/drawable/ic_qrcode_24dp.xml
@@ -0,0 +1,39 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M7,4v3H4V4H7M9,2H2v7h7V2L9,2z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M15,11l-8,0l0,2l8,0l0,-2z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M13,2l-2,0l0,11l2,0l0,-11z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M22,15l-11,0l0,2l11,0l0,-2z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M13,17l-2,0l0,5l2,0l0,-5z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M17,13l-2,0l0,9l2,0l0,-9z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M22,19l-3,0l0,3l3,0l0,-3z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M5,11l-3,0l0,2l3,0l0,-2z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M22,11l-5,0l0,2l5,0l0,-2z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M20,4v3h-3V4H20M22,2h-7v7h7V2L22,2z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M7,17v3H4v-3H7M9,15H2v7h7V15L9,15z"/>
+</vector>
diff --git a/res/drawable/ic_scan_24dp.xml b/res/drawable/ic_scan_24dp.xml
new file mode 100644
index 0000000..bcef8e3
--- /dev/null
+++ b/res/drawable/ic_scan_24dp.xml
@@ -0,0 +1,33 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M9,2l-7,0l0,2l7,0l0,-2z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M22,2l-7,0l0,2l7,0l0,-2z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M22,11l-20,0l0,2l20,0l0,-2z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M22,2l-2,0l0,7l2,0l0,-7z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M4,2l-2,0l0,7l2,0l0,-7z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M9,20l-7,0l0,2l7,0l0,-2z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M22,20l-7,0l0,2l7,0l0,-2z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M22,15l-2,0l0,7l2,0l0,-7z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M4,15l-2,0l0,7l2,0l0,-7z"/>
+</vector>
diff --git a/res/layout/homepage_condition_half_tile.xml b/res/layout/homepage_condition_half_tile.xml
index fb83389..eff167a 100644
--- a/res/layout/homepage_condition_half_tile.xml
+++ b/res/layout/homepage_condition_half_tile.xml
@@ -61,6 +61,7 @@
android:id="@+id/first_action"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:scrollbars="none"
style="@style/ConditionHalfCardBorderlessButton"/>
</LinearLayout>
diff --git a/res/layout/settings_homepage_container.xml b/res/layout/settings_homepage_container.xml
index 8d81e82..75d449f 100644
--- a/res/layout/settings_homepage_container.xml
+++ b/res/layout/settings_homepage_container.xml
@@ -21,24 +21,17 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
- <com.google.android.material.appbar.AppBarLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="@android:color/transparent"
- app:elevation="0dp">
- <include layout="@layout/search_bar"/>
- </com.google.android.material.appbar.AppBarLayout>
-
<androidx.core.widget.NestedScrollView
android:id="@+id/main_content_scrollable_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:layout_behavior="@string/appbar_scrolling_view_behavior">
+ app:layout_behavior="com.android.settings.widget.FloatingAppBarScrollingViewBehavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
+ android:paddingTop="@dimen/app_bar_height"
android:descendantFocusability="blocksDescendants">
<FrameLayout
@@ -55,4 +48,10 @@
</LinearLayout>
</androidx.core.widget.NestedScrollView>
+
+ <com.google.android.material.appbar.AppBarLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <include layout="@layout/search_bar"/>
+ </com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/res/menu/manage_apps.xml b/res/menu/manage_apps.xml
index 99dba37..51189a0 100644
--- a/res/menu/manage_apps.xml
+++ b/res/menu/manage_apps.xml
@@ -16,6 +16,13 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
+ android:id="@+id/search_app_list_menu"
+ android:title="@string/search_settings"
+ android:icon="@drawable/ic_find_in_page_24px"
+ android:showAsAction="always|collapseActionView"
+ android:actionViewClass="android.widget.SearchView" />
+
+ <item
android:id="@+id/advanced"
android:title="@string/advanced_apps"
android:icon="@drawable/ic_settings_24dp"
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 33976a6..f95809e 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1077,11 +1077,18 @@
<item>never</item>
</string-array>
- <string-array name="zen_mode_contacts_entries" translatable="false">
+ <string-array name="zen_mode_contacts_messages_entries" translatable="false">
<item>@string/zen_mode_from_anyone</item>
<item>@string/zen_mode_from_contacts</item>
<item>@string/zen_mode_from_starred</item>
- <item>@string/zen_mode_from_none</item>
+ <item>@string/zen_mode_from_none_calls</item>
+ </string-array>
+
+ <string-array name="zen_mode_contacts_calls_entries" translatable="false">
+ <item>@string/zen_mode_from_anyone</item>
+ <item>@string/zen_mode_from_contacts</item>
+ <item>@string/zen_mode_from_starred</item>
+ <item>@string/zen_mode_from_none_messages</item>
</string-array>
<string-array name="zen_mode_contacts_values" translatable="false">
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 752fd3d..86763b7 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -72,6 +72,14 @@
<attr name="allowDynamicSummaryInSlice" format="boolean" />
</declare-styleable>
+ <declare-styleable name="PreferenceScreen">
+ <!-- Determines if static preferences defined in addStaticPreferences are added before or after the radio buttons -->
+ <attr name="staticPreferenceLocation">
+ <enum name="prepend" value="0" />
+ <enum name="append" value="1" />
+ </attr>
+ </declare-styleable>
+
<!-- For DotsPageIndicator -->
<declare-styleable name="DotsPageIndicator">
<attr name="dotDiameter" format="dimension" />
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 83848af..a6c6c37 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -105,6 +105,8 @@
<dimen name="search_bar_avatar_size">32dp</dimen>
<dimen name="search_bar_avatar_start_margin">4dp</dimen>
<dimen name="search_bar_avatar_end_margin">16dp</dimen>
+ <!-- appbar height is equal search bar height (48dp) plus search bar top and bottom margin -->
+ <dimen name="app_bar_height">80dp</dimen>
<!-- Dimensions for Wifi Assistant Card -->
<dimen name="wifi_assistant_padding_top_bottom">16dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4aa0951..0116ed4 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -653,6 +653,8 @@
<string name="done">Done</string>
<!-- Button label for generic apply action [CHAR LIMIT=20] -->
<string name="apply">Apply</string>
+ <!-- Button label for generic share action [CHAR LIMIT=20] -->
+ <string name="share">Share</string>
<!-- Title of the Settings activity shown within the application itself. -->
<string name="settings_label">Settings</string>
@@ -670,7 +672,7 @@
<!-- check box cellular data title [CHAR LIMIT=30] -->
<string name="cellular_data_title">Mobile data</string>
<!-- check box Calls title [CHAR LIMIT=30] -->
- <string name="calls_title">Calls</string>
+ <string name="calls_title">Allow calls</string>
<!-- check box SMS Messges title [CHAR LIMIT=30] -->
<string name="sms_messages_title">SMS messages</string>
<!-- check box cellular data summary [CHAR LIMIT=85] -->
@@ -2878,6 +2880,14 @@
<string name="status_prl_version">PRL version</string>
<!-- About phone screen, title for MEID for multi-sim devices -->
<string name="meid_multi_sim">MEID (sim slot %1$d)</string>
+ <!-- The status text when both Wi-Fi scanning and Bluetooth scanning are on. [CHAR LIMIT=120] -->
+ <string name="scanning_status_text_wifi_on_ble_on">Both Wi\u2011Fi and Bluetooth are allowed to determine location</string>
+ <!-- The status text when Wi-Fi scanning is on and Bluetooth scanning are off. [CHAR LIMIT=120] -->
+ <string name="scanning_status_text_wifi_on_ble_off">Only Wi\u2011Fi is allowed to determine location</string>
+ <!-- The status text when Wi-Fi scanning is off and Bluetooth scanning are on. [CHAR LIMIT=120] -->
+ <string name="scanning_status_text_wifi_off_ble_on">Only Bluetooth is allowed to determine location</string>
+ <!-- The status text when both Wi-Fi scanning and Bluetooth scanning are off. [CHAR LIMIT=120] -->
+ <string name="scanning_status_text_wifi_off_ble_off">Neither Wi\u2011Fi nor Bluetooth is allowed to determine location</string>
<!-- About phone, status item title. The phone MEID number of the current LTE/CDMA device. [CHAR LIMIT=30] -->
<string name="status_meid_number">MEID</string>
<!-- About phone, status item title. The ICCID of the current LTE device. [CHAR LIMIT=30] -->
@@ -3612,8 +3622,8 @@
<string name="location_high_battery_use">High battery use</string>
<!-- [CHAR LIMIT=30] Location settings screen, recent location requests low battery use-->
<string name="location_low_battery_use">Low battery use</string>
- <!-- [CHAR LIMIT=30] Wireless background scanning settings screen, screen title -->
- <string name="location_scanning_screen_title">Scanning</string>
+ <!-- [CHAR LIMIT=60] Wireless background scanning settings screen, screen title -->
+ <string name="location_scanning_screen_title">Wi\u2011Fi and Bluetooth scanning</string>
<!-- [CHAR LIMIT=130] Preference title for Wi-Fi always scanning -->
<string name="location_scanning_wifi_always_scanning_title">Wi\u2011Fi scanning</string>
<!-- Preference description text for Wi-Fi always scanning -->
@@ -3757,6 +3767,8 @@
<string name="lockpassword_choose_your_pattern_header_for_face">To use face authentication, set pattern</string>
<!-- Header on first screen of choose password/PIN as backup for face authentication flow. If this string cannot be translated in under 40 characters, please translate "Set face authentication backup" [CHAR LIMIT=40] -->
<string name="lockpassword_choose_your_pin_header_for_face">To use face authentication, set PIN</string>
+ <!-- Message on Wi-Fi Sharing screen [CHAR LIMIT=NONE] -->
+ <string name="wifi_sharing_message">Your Wi\u2011Fi name and password for \"<xliff:g id="SSID" example="GoogleGuest">%1$s</xliff:g>\" will be shared.</string>
<!-- Message to be used to explain the user that he needs to enter his pattern to continue a
particular operation. [CHAR LIMIT=70]-->
@@ -5406,6 +5418,12 @@
<!-- Battery saver: Label for preference to turn on battery saver automatically when battery is low [CHAR_LIMIT=40] -->
<string name="battery_saver_auto_title">Turn on automatically</string>
+ <!-- Battery saver: Label for preference to indicate there is no battery saver schedule [CHAR_LIMIT=40] -->
+ <string name="battery_saver_auto_no_schedule">No schedule</string>
+
+ <!-- Battery saver: Title for battery saver schedule screen [CHAR_LIMIT=40] -->
+ <string name="battery_saver_schedule_settings_title">Set a schedule</string>
+
<!-- Battery saver: Label for seekbar to change battery saver threshold [CHAR_LIMIT=40] -->
<string name="battery_saver_seekbar_title">At <xliff:g id="percent">%1$s</xliff:g></string>
@@ -7083,8 +7101,8 @@
<!-- Sound: Summary for the Do not Disturb option when at least one automatic rules turned on. [CHAR LIMIT=NONE]-->
<plurals name="zen_mode_settings_summary_on">
- <item quantity="one">1 rule</item>
- <item quantity="other"><xliff:g id="on_count" example="10">%d</xliff:g> rules</item>
+ <item quantity="one">1 enabled</item>
+ <item quantity="other"><xliff:g id="on_count" example="10">%d</xliff:g> enabled</item>
</plurals>
<!-- Sound: Title for the Do not Disturb option and associated settings page. [CHAR LIMIT=50]-->
@@ -7124,10 +7142,10 @@
<string name="zen_mode_schedule_delete">Delete</string>
<!-- Do not disturb: Title for the zen mode automatic rules page in settings. [CHAR LIMIT=30] -->
- <string name="zen_mode_automation_settings_page_title">Do Not Disturb</string>
+ <string name="zen_mode_automation_settings_page_title">Schedules</string>
<!-- Do not disturb: Title for a specific zen mode automatic rule in settings. [CHAR LIMIT=30] -->
- <string name="zen_mode_automatic_rule_settings_page_title">Automatic rule</string>
+ <string name="zen_mode_automatic_rule_settings_page_title">Schedule</string>
<!-- Do not disturb: Title do not disturb settings representing automatic (scheduled) do not disturb rules. [CHAR LIMIT=30] -->
<string name="zen_mode_schedule_category_title">Schedule</string>
@@ -7142,7 +7160,7 @@
<string name="zen_mode_schedule_title">Schedule</string>
<!-- Do not disturb: Switch toggle to toggle whether to use an automatic dnd rule or not [CHAR LIMIT=40] -->
- <string name="zen_mode_use_automatic_rule">Use rule</string>
+ <string name="zen_mode_use_automatic_rule">Use schedule</string>
<!-- Do not disturb: Zen mode option: Important interruptions [CHAR LIMIT=60] -->
<string name="zen_mode_option_important_interruptions">Priority only</string>
@@ -7166,7 +7184,7 @@
<string name="zen_mode_settings_category">When Do Not Disturb is on</string>
<!-- Do not disturb: restrict notifications title [CHAR LIMIT=80] -->
- <string name="zen_mode_restrict_notifications_title">Notification restrictions</string>
+ <string name="zen_mode_restrict_notifications_title">Restrict notifications</string>
<!-- Do not disturb: Mute notifications option [CHAR LIMIT=60] -->
<string name="zen_mode_restrict_notifications_mute">No sound from notifications</string>
<!-- Do not disturb:Mute notifications summary [CHAR LIMIT=NONE] -->
@@ -7272,7 +7290,7 @@
<string name="zen_mode_sound_summary_on_with_info">On / <xliff:g name="dnd_summary" example="No sound except alarms and media">%1$s</xliff:g></string>
<!-- Sound settings screen, summary format of do not disturb when off with extra information. [CHAR LIMIT=NONE] -->
- <string name="zen_mode_sound_summary_off_with_info">Off / <xliff:g name="dnd_summary" example="1 rule can turn on automatically">%1$s</xliff:g></string>
+ <string name="zen_mode_sound_summary_off_with_info">Off / <xliff:g name="dnd_summary" example="1 schedule can turn on automatically">%1$s</xliff:g></string>
<!-- Sound settings screen, summary format of do not disturb when off with no extra information. [CHAR LIMIT=NONE] -->
<string name="zen_mode_sound_summary_off">Off</string>
@@ -7297,12 +7315,12 @@
<!-- Summary for the Sound Do not Disturb option when at least one automatic rules is enabled. [CHAR LIMIT=NONE]-->
<plurals name="zen_mode_sound_summary_summary_off_info">
- <item quantity="one">1 rule can turn on automatically</item>
- <item quantity="other"><xliff:g id="on_count" example="3">%d</xliff:g> rules can turn on automatically</item>
+ <item quantity="one">1 schedule can turn on automatically</item>
+ <item quantity="other"><xliff:g id="on_count" example="3">%d</xliff:g> schedules can turn on automatically</item>
</plurals>
<!-- Do not disturb settings, category header [CHAR LIMIT=120]-->
- <string name="zen_category_behavior">Mute phone, but allow exceptions</string>
+ <string name="zen_category_behavior">Mute device but allow exceptions</string>
<!-- Do not disturb settings, exceptions to dnd title [CHAR LIMIT=100]-->
<string name="zen_category_exceptions">Exceptions</string>
<!-- Do not disturb settings, category header [CHAR LIMIT=100]-->
@@ -7753,28 +7771,28 @@
<string name="zen_mode_rule_rename_button">Rename</string>
<!-- [CHAR LIMIT=40] Zen mode settings: Rule name option and edit dialog title -->
- <string name="zen_mode_rule_name">Rule name</string>
+ <string name="zen_mode_rule_name">Schedule name</string>
<!-- [CHAR LIMIT=40] Zen mode settings: Rule name hint text -->
- <string name="zen_mode_rule_name_hint">Enter rule name</string>
+ <string name="zen_mode_rule_name_hint">Enter schedule name</string>
<!-- [CHAR LIMIT=100] Zen mode settings: Warning text for invalid zen rule names -->
- <string name="zen_mode_rule_name_warning">Rule name already in use</string>
+ <string name="zen_mode_rule_name_warning">Schedule name already in use</string>
<!-- [CHAR LIMIT=40] Zen mode settings: Add another automatic zen rule option name-->
<string name="zen_mode_add_rule">Add more</string>
<!-- [CHAR LIMIT=40] Zen mode settings: Add event-based rule, set rule name title -->
- <string name="zen_mode_add_event_rule">Add event rule</string>
+ <string name="zen_mode_add_event_rule">Add event schedule</string>
<!-- [CHAR LIMIT=40] Zen mode settings: Add time-based rule, set rule name title -->
- <string name="zen_mode_add_time_rule">Add time rule</string>
+ <string name="zen_mode_add_time_rule">Add time schedule</string>
<!-- [CHAR LIMIT=40] Zen mode settings: Delete rule menu option name -->
- <string name="zen_mode_delete_rule">Delete rule</string>
+ <string name="zen_mode_delete_rule">Delete schedule</string>
<!-- [CHAR LIMIT=60] Zen mode settings: Choose rule type dialog title -->
- <string name="zen_mode_choose_rule_type">Choose rule type</string>
+ <string name="zen_mode_choose_rule_type">Choose schedule type</string>
<!-- [CHAR LIMIT=40] Zen mode settings: Delete rule dialog confirmation message -->
<string name="zen_mode_delete_rule_confirmation">Delete \u201c<xliff:g id="rule" example="Weekends">%1$s</xliff:g>\u201d rule?</string>
@@ -7855,7 +7873,7 @@
<string name="zen_mode_schedule_alarm_title">Alarm can override end time</string>
<!-- [CHAR LIMIT=NONE] Zen mode settings: Downtime rule setting -->
- <string name="zen_mode_schedule_alarm_summary">Stop at the end time or next alarm, whichever comes first</string>
+ <string name="zen_mode_schedule_alarm_summary">Schedule turns off when an alarm rings</string>
<!-- [CHAR LIMIT=80] Zen mode settings: Title for preference to allow custom behavior for the dnd schedule -->
<string name="zen_mode_custom_behavior_title">Do Not Disturb behavior</string>
@@ -7876,10 +7894,10 @@
<string name="summary_range_verbal_combination"><xliff:g id="start" example="Sun">%1$s</xliff:g> to <xliff:g id="end" example="Thu">%2$s</xliff:g></string>
<!-- [CHAR LIMIT=20] Zen mode settings: Calls option -->
- <string name="zen_mode_calls">Calls</string>
+ <string name="zen_mode_calls">Allow calls</string>
<!-- [CHAR LIMIT=40] Zen mode settings: Allow calls toggle title -->
- <string name="zen_mode_calls_title">Allow calls</string>
+ <string name="zen_mode_calls_title">Calls</string>
<!-- [CHAR LIMIT=20] Zen mode settings: Calls screen footer -->
<string name="zen_mode_calls_footer">When Do Not Disturb is on, incoming calls are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you.</string>
@@ -7894,25 +7912,13 @@
</plurals>
<!-- [CHAR LIMIT=20] Zen mode settings: Messages option -->
- <string name="zen_mode_messages">Messages</string>
+ <string name="zen_mode_messages">Allow text messages</string>
<!-- Do not disturb settings, messages, events and reminders footer [CHAR LIMIT=NONE]-->
<string name="zen_mode_messages_footer">When Do Not Disturb is on, incoming text messages are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you.</string>
- <!-- [CHAR LIMIT=40] Zen mode settings: Allow messages toggle title -->
- <string name="zen_mode_messages_title">Allow messages</string>
-
- <!-- [CHAR LIMIT=50] Zen mode settings: All messages summary -->
- <string name="zen_mode_all_messages">Messages</string>
-
- <!-- [CHAR LIMIT=50] Zen mode settings: Messages option (ie: text messages) -->
- <string name="zen_mode_all_messages_list">messages</string>
-
- <!-- [CHAR LIMIT=50] Zen mode settings: Selected messages summary -->
- <string name="zen_mode_selected_messages">Some messages</string>
-
- <!-- [CHAR LIMIT=50] Zen mode settings: Selected messages (ie: some text messages are allowed to bypass dnd) -->
- <string name="zen_mode_selected_messages_list">some messages</string>
+ <!-- [CHAR LIMIT=40] Zen mode settings: Allow messages to bypass DND title -->
+ <string name="zen_mode_messages_title">Text messages</string>
<!-- [CHAR LIMIT=40] Zen mode settings: Calls or messages option value: From anyone -->
<string name="zen_mode_from_anyone">From anyone</string>
@@ -7932,9 +7938,15 @@
<!-- Do not disturb settings, calls summary [CHAR LIMIT=100]-->
<string name="zen_calls_summary_repeat_only">From repeat callers only</string>
- <!-- [CHAR LIMIT=40] Zen mode settings: Calls or messages option value: None -->
+ <!-- [CHAR LIMIT=40] Zen mode settings: Calls and/or messages from none-->
<string name="zen_mode_from_none">None</string>
+ <!-- [CHAR LIMIT=40] Zen mode settings: Calls option value: No calls allowed -->
+ <string name="zen_mode_from_none_calls">Don\u2019t allow any calls</string>
+
+ <!-- [CHAR LIMIT=40] Zen mode settings: Messages option value: No messages allowed -->
+ <string name="zen_mode_from_none_messages">Don\u2019t allow any messages</string>
+
<!-- [CHAR LIMIT=80] Zen mode settings: Allow alarms option -->
<string name="zen_mode_alarms">Allow alarms</string>
@@ -7942,7 +7954,7 @@
<string name="zen_mode_alarms_list">alarms</string>
<!-- [CHAR LIMIT=80] Zen mode settings: Allow media (sound from video) to bypass dnd -->
- <string name="zen_mode_media">Allow media</string>
+ <string name="zen_mode_media">Allow media sounds</string>
<!-- [CHAR LIMIT=50] Zen mode settings: Media (ie: sound from video) -->
<string name="zen_mode_media_list">media</string>
@@ -7966,7 +7978,7 @@
<string name="zen_mode_bypassing_apps">Allow apps to override</string>
<!-- [CHAR LIMIT=100] Zen mode settings: Allow apps to bypass DND title-->
- <string name="zen_mode_bypassing_apps_title">Overrides Do Not Disturb</string>
+ <string name="zen_mode_bypassing_apps_title">App exceptions</string>
<!-- [CHAR LIMIT=80] Zen mode settings: Allow apps to bypass DND -->
<plurals name="zen_mode_bypassing_apps_subtext">
@@ -7997,10 +8009,10 @@
<string name="zen_mode_repeat_callers_title">Allow repeat callers</string>
<!-- [CHAR LIMIT=50] Zen mode settings: calls summary -->
- <string name="zen_mode_calls_summary_one">From <xliff:g id="caller type" example="contacts">%1$s</xliff:g></string>
+ <string name="zen_mode_calls_summary_one">Allow from <xliff:g id="caller type" example="contacts">%1$s</xliff:g></string>
<!-- [CHAR LIMIT=50] Zen mode settings: calls summary -->
- <string name="zen_mode_calls_summary_two">From <xliff:g id="caller type" example="starred contacts">%1$s</xliff:g> and <xliff:g id="callert tpye" example="repeat callers">%2$s</xliff:g></string>
+ <string name="zen_mode_calls_summary_two">Allow from <xliff:g id="caller type" example="starred contacts">%1$s</xliff:g> and <xliff:g id="callert tpye" example="repeat callers">%2$s</xliff:g></string>
<!-- [CHAR LIMIT=200] Zen mode settings: Repeat callers option summary -->
<string name="zen_mode_repeat_callers_summary">If the same person calls a second time within a <xliff:g id="minutes">%d</xliff:g> minute period</string>
@@ -8976,7 +8988,7 @@
<string name="condition_cellular_title">Mobile data is off</string>
<!-- Summary of condition that cellular data is off [CHAR LIMIT=NONE] -->
- <string name="condition_cellular_summary">Internet is available only via Wi-Fi</string>
+ <string name="condition_cellular_summary">Internet only available via Wi\u2011Fi</string>
<!-- Title of condition that background data is off [CHAR LIMIT=30] -->
<string name="condition_bg_data_title">Data Saver</string>
@@ -8988,7 +9000,7 @@
<string name="condition_work_title">Work profile is off</string>
<!-- 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>
+ <string name="condition_work_summary">For apps & notifications</string>
<!-- Action label on device muted card - clicking action will turn on ringtone sound [CHAR LIMIT=50] -->
<string name="condition_device_muted_action_turn_on_sound">Turn on sound</string>
@@ -9450,6 +9462,11 @@
<string name="managed_profile_contact_search_title">Contact search</string>
<!-- [CHAR LIMIT=NONE] The preference summary for enabling cross-profile remote contact search -->
<string name="managed_profile_contact_search_summary">Allow contact searches by your organization to identify callers and contacts</string>
+ <!-- [CHAR LIMIT=60] The preference title for enabling cross profile calendar sync -->
+ <string name="cross_profile_calendar_title">Cross-profile calendar</string>
+ <!-- [CHAR LIMIT=NONE] The preference summary for enabling cross profile calendar sync -->
+ <string name="cross_profile_calendar_summary">Show work events on personal calendar</string>
+
<!-- Time in hours -->
<plurals name="hours">
@@ -10237,15 +10254,13 @@
<!-- OK button for Network connection timeout Dialog [CHAR LIMIT=30] -->
<string name="network_connection_timeout_dialog_ok">Scan again</string>
- <!-- Summary for connected devices count in connected device slice. [CHAR LIMIT=NONE] -->
- <plurals name="show_connected_devices">
+ <!-- Summary for bluetooth devices count in Bluetooth devices slice. [CHAR LIMIT=NONE] -->
+ <plurals name="show_bluetooth_devices">
<item quantity="one"><xliff:g id="number_device_count">%1$d</xliff:g> device connected</item>
<item quantity="other"><xliff:g id="number_device_count">%1$d</xliff:g> devices connected</item>
</plurals>
- <!-- Title for bluetooth connected devices in connected device slice. [CHAR LIMIT=NONE] -->
- <string name="bluetooth_connected_devices">Bluetooth Devices</string>
- <!-- Title for no connected devices in connected device slice. [CHAR LIMIT=NONE] -->
- <string name="no_connected_devices">No connected devices</string>
+ <!-- Title for no bluetooth devices in Bluetooth devices slice. [CHAR LIMIT=NONE] -->
+ <string name="no_bluetooth_devices">No Bluetooth devices</string>
<!-- Default title for the settings panel [CHAR LIMIT=NONE] -->
<string name="settings_panel_title">Settings Panel</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 141426e..19ce333 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -461,8 +461,9 @@
<style name="SearchBarStyle">
<item name="android:layout_margin">@dimen/search_bar_margin</item>
<item name="cardCornerRadius">8dp</item>
- <item name="strokeColor">@color/homepage_card_stroke_color</item>
- <item name="strokeWidth">1dp</item>
+ <item name="enforceMaterialTheme">true</item>
+ <item name="cardElevation">3dp</item>
+ <item name="shapeAppearance">@null</item>
</style>
<style name="ConditionCardBorderlessButton"
diff --git a/res/xml/accessibility_content_timeout_settings.xml b/res/xml/accessibility_content_timeout_settings.xml
index d450449..2d9072b 100644
--- a/res/xml/accessibility_content_timeout_settings.xml
+++ b/res/xml/accessibility_content_timeout_settings.xml
@@ -17,27 +17,23 @@
<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_content_timeout_preference"
android:title="@string/accessibility_content_timeout_preference_title"
android:persistent="false" >
<com.android.settings.widget.VideoPreference
android:key="accessibility_content_timeout_video"
- app:animation="@raw/gesture_swipe_up"
- app:preview="@drawable/gesture_swipe_up"
- android:persistent="false" />
-
- <Preference
- android:key="accessibility_content_timeout_summary"
- android:selectable="false"
- android:enabled="true"
- android:summary="@string/accessibility_content_timeout_preference_summary"
+ android:title="@string/summary_placeholder"
+ settings:animation="@raw/gesture_swipe_up"
+ settings:preview="@drawable/gesture_swipe_up"
+ settings:controller="com.android.settings.widget.VideoPreferenceController"
android:persistent="false" />
<com.android.settings.widget.RadioButtonPreference
android:key="accessibility_content_timeout_default"
android:title="@string/accessibility_timeout_default"
+ settings:allowDividerAbove="true"
android:persistent="false" />
<com.android.settings.widget.RadioButtonPreference
@@ -60,4 +56,8 @@
android:title="@string/accessibility_timeout_2mins"
android:persistent="false" />
+ <com.android.settingslib.widget.FooterPreference
+ android:title="@string/accessibility_content_timeout_preference_summary"
+ android:selectable="false" />
+
</PreferenceScreen>
diff --git a/res/xml/accessibility_control_timeout_settings.xml b/res/xml/accessibility_control_timeout_settings.xml
index 6d8e1d0..ea8d8c6 100644
--- a/res/xml/accessibility_control_timeout_settings.xml
+++ b/res/xml/accessibility_control_timeout_settings.xml
@@ -17,27 +17,23 @@
<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_control_timeout_preference"
android:title="@string/accessibility_control_timeout_preference_title"
android:persistent="false" >
<com.android.settings.widget.VideoPreference
android:key="accessibility_control_timeout_video"
- app:animation="@raw/gesture_swipe_up"
- app:preview="@drawable/gesture_swipe_up"
- android:persistent="false" />
-
- <Preference
- android:key="accessibility_control_timeout_summary"
- android:selectable="false"
- android:enabled="true"
- android:summary="@string/accessibility_control_timeout_preference_summary"
+ android:title="@string/summary_placeholder"
+ settings:animation="@raw/gesture_swipe_up"
+ settings:preview="@drawable/gesture_swipe_up"
+ settings:controller="com.android.settings.widget.VideoPreferenceController"
android:persistent="false" />
<com.android.settings.widget.RadioButtonPreference
android:key="accessibility_control_timeout_default"
android:title="@string/accessibility_timeout_default"
+ settings:allowDividerAbove="true"
android:persistent="false" />
<com.android.settings.widget.RadioButtonPreference
@@ -60,4 +56,8 @@
android:title="@string/accessibility_timeout_2mins"
android:persistent="false" />
+ <com.android.settingslib.widget.FooterPreference
+ android:title="@string/accessibility_control_timeout_preference_summary"
+ android:selectable="false" />
+
</PreferenceScreen>
diff --git a/res/xml/battery_saver_schedule_settings.xml b/res/xml/battery_saver_schedule_settings.xml
new file mode 100644
index 0000000..f91e4ca
--- /dev/null
+++ b/res/xml/battery_saver_schedule_settings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/battery_saver_schedule_settings_title"
+ settings:staticPreferenceLocation="append">
+</PreferenceScreen >
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index a0f019d..be45cd0 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -424,9 +424,6 @@
android:summary="%s"
android:title="@string/simulate_color_space" />
- <Preference android:key="angle_enabled_app"
- android:title="@string/angle_enabled_app" />
-
<Preference android:key="updated_gfx_driver_dev_opt_in_app"
android:summary="@string/updated_gfx_driver_dev_opt_in_app_summary"
android:title="@string/updated_gfx_driver_dev_opt_in_app" />
diff --git a/res/xml/managed_profile_settings.xml b/res/xml/managed_profile_settings.xml
index ee1e4fa..bd44cc1 100644
--- a/res/xml/managed_profile_settings.xml
+++ b/res/xml/managed_profile_settings.xml
@@ -32,4 +32,11 @@
settings:useAdditionalSummary="true"
settings:controller="com.android.settings.accounts.ContactSearchPreferenceController"/>
+ <com.android.settingslib.RestrictedSwitchPreference
+ android:key="cross_profile_calendar"
+ android:summary="@string/cross_profile_calendar_summary"
+ android:title="@string/cross_profile_calendar_title"
+ settings:useAdditionalSummary="true"
+ settings:controller="com.android.settings.accounts.CrossProfileCalendarPreferenceController"/>
+
</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/network_and_internet_v2.xml b/res/xml/network_and_internet_v2.xml
index 680b268..974739d 100644
--- a/res/xml/network_and_internet_v2.xml
+++ b/res/xml/network_and_internet_v2.xml
@@ -21,13 +21,20 @@
android:title="@string/network_dashboard_title"
settings:initialExpandedChildrenCount="5">
+ <PreferenceCategory
+ android:key="multi_network_header"
+ settings:allowDividerBelow="true"
+ android:order="-40"
+ settings:controller="com.android.settings.network.MultiNetworkHeaderController"/>
+
<com.android.settings.widget.MasterSwitchPreference
android:fragment="com.android.settings.wifi.WifiSettings"
android:key="toggle_wifi"
android:title="@string/wifi_settings"
android:summary="@string/summary_placeholder"
android:icon="@drawable/ic_settings_wireless"
- android:order="-30">
+ android:order="-30"
+ settings:allowDividerAbove="true">
<intent
android:action="android.settings.WIFI_SETTINGS"
android:targetClass="Settings$WifiSettingsActivity" />
@@ -44,16 +51,15 @@
settings:useAdminDisabledSummary="true">
</com.android.settingslib.RestrictedPreference>
- <com.android.settingslib.RestrictedPreference
- android:fragment="com.android.settings.TetherSettings"
- android:key="tether_settings"
- android:title="@string/tether_settings_title_all"
- android:icon="@drawable/ic_wifi_tethering"
+ <com.android.settingslib.RestrictedSwitchPreference
+ android:key="toggle_airplane"
+ android:title="@string/airplane_mode"
+ android:icon="@drawable/ic_airplanemode_active"
+ android:disableDependentsState="true"
android:order="-5"
- android:summary="@string/summary_placeholder"
- settings:keywords="@string/keywords_hotspot_tethering"
- settings:userRestriction="no_config_tethering"
- settings:useAdminDisabledSummary="true" />
+ settings:controller="com.android.settings.network.AirplaneModePreferenceController"
+ settings:platform_slice="true"
+ settings:userRestriction="no_airplane_mode"/>
<com.android.settingslib.RestrictedPreference
android:key="manage_mobile_plan"
@@ -63,20 +69,16 @@
settings:userRestriction="no_config_mobile_networks"
settings:useAdminDisabledSummary="true" />
- <com.android.settingslib.RestrictedSwitchPreference
- android:key="toggle_airplane"
- android:title="@string/airplane_mode"
- android:icon="@drawable/ic_airplanemode_active"
- android:disableDependentsState="true"
+ <com.android.settingslib.RestrictedPreference
+ android:fragment="com.android.settings.TetherSettings"
+ android:key="tether_settings"
+ android:title="@string/tether_settings_title_all"
+ android:icon="@drawable/ic_wifi_tethering"
android:order="5"
- settings:controller="com.android.settings.network.AirplaneModePreferenceController"
- settings:platform_slice="true"
- settings:userRestriction="no_airplane_mode"/>
-
- <Preference
- android:fragment="com.android.settings.ProxySelector"
- android:key="proxy_settings"
- android:title="@string/proxy_settings_title" />
+ android:summary="@string/summary_placeholder"
+ settings:keywords="@string/keywords_hotspot_tethering"
+ settings:userRestriction="no_config_tethering"
+ settings:useAdminDisabledSummary="true" />
<com.android.settingslib.RestrictedPreference
android:fragment="com.android.settings.vpn2.VpnSettings"
diff --git a/res/xml/wifi_configure_settings.xml b/res/xml/wifi_configure_settings.xml
index 8ec320a..15ab1aa 100644
--- a/res/xml/wifi_configure_settings.xml
+++ b/res/xml/wifi_configure_settings.xml
@@ -41,7 +41,8 @@
<SwitchPreference
android:key="wifi_cellular_data_fallback"
android:title="@string/wifi_cellular_data_fallback_title"
- android:summary="@string/wifi_cellular_data_fallback_summary" />
+ android:summary="@string/wifi_cellular_data_fallback_summary"
+ settings:controller="com.android.settings.wifi.CellularFallbackPreferenceController" />
<Preference
android:key="install_credentials"
diff --git a/res/xml/zen_mode_calls_settings.xml b/res/xml/zen_mode_calls_settings.xml
index 74b6986..4616cf8 100644
--- a/res/xml/zen_mode_calls_settings.xml
+++ b/res/xml/zen_mode_calls_settings.xml
@@ -19,7 +19,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="zen_mode_calls_settings_page"
- android:title="@string/zen_mode_calls" >
+ android:title="@string/zen_mode_calls_title" >
<PreferenceCategory
android:title="@string/zen_mode_settings_category"
@@ -27,8 +27,8 @@
<!-- Calls -->
<ListPreference
android:key="zen_mode_calls"
- android:title="@string/zen_mode_calls_title"
- android:entries="@array/zen_mode_contacts_entries"
+ android:title="@string/zen_mode_calls"
+ android:entries="@array/zen_mode_contacts_calls_entries"
android:entryValues="@array/zen_mode_contacts_values"/>
<Preference
diff --git a/res/xml/zen_mode_messages_settings.xml b/res/xml/zen_mode_messages_settings.xml
index 4ca6c92..2d0129e 100644
--- a/res/xml/zen_mode_messages_settings.xml
+++ b/res/xml/zen_mode_messages_settings.xml
@@ -18,7 +18,7 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:key="zen_mode_messages_settings_page"
- android:title="@string/zen_mode_messages" >
+ android:title="@string/zen_mode_messages_title" >
<PreferenceCategory
android:title="@string/zen_mode_settings_category"
@@ -26,8 +26,8 @@
<!-- Messages -->
<ListPreference
android:key="zen_mode_messages"
- android:title="@string/zen_mode_messages_title"
- android:entries="@array/zen_mode_contacts_entries"
+ android:title="@string/zen_mode_messages"
+ android:entries="@array/zen_mode_contacts_messages_entries"
android:entryValues="@array/zen_mode_contacts_values"/>
<Preference
diff --git a/res/xml/zen_mode_sound_vibration_settings.xml b/res/xml/zen_mode_sound_vibration_settings.xml
index 30e2abb..73b5b05 100644
--- a/res/xml/zen_mode_sound_vibration_settings.xml
+++ b/res/xml/zen_mode_sound_vibration_settings.xml
@@ -27,13 +27,13 @@
<!-- Calls -->
<Preference
android:key="zen_mode_calls_settings"
- android:title="@string/zen_mode_calls_title"
+ android:title="@string/zen_mode_calls"
android:fragment="com.android.settings.notification.ZenModeCallsSettings" />
<!-- Messages -->
<Preference
android:key="zen_mode_messages_settings"
- android:title="@string/zen_mode_messages_title"
+ android:title="@string/zen_mode_messages"
android:fragment="com.android.settings.notification.ZenModeMessagesSettings" />
<!-- Alarms -->
diff --git a/src/com/android/settings/CredentialStorage.java b/src/com/android/settings/CredentialStorage.java
index 7b0be94..5ab543f 100644
--- a/src/com/android/settings/CredentialStorage.java
+++ b/src/com/android/settings/CredentialStorage.java
@@ -172,8 +172,9 @@
dialog.show(getSupportFragmentManager(), ConfigureKeyGuardDialog.TAG);
return;
}
- installIfAvailable();
- finish();
+ if (installIfAvailable()) {
+ finish();
+ }
return;
}
}
@@ -217,10 +218,13 @@
/**
* Install credentials if available, otherwise do nothing.
+ *
+ * @return true if the installation is done and the activity should be finished, false if
+ * an asynchronous task is pending and will finish the activity when it's done.
*/
- private void installIfAvailable() {
+ private boolean installIfAvailable() {
if (mInstallBundle == null || mInstallBundle.isEmpty()) {
- return;
+ return true;
}
final Bundle bundle = mInstallBundle;
@@ -235,16 +239,17 @@
if (uid != Process.WIFI_UID) {
Log.e(TAG, "Failed to install credentials as uid " + uid + ": cross-user installs"
+ " may only target wifi uids");
- return;
+ return true;
}
final Intent installIntent = new Intent(ACTION_INSTALL)
.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT)
.putExtras(bundle);
startActivityAsUser(installIntent, new UserHandle(dstUserId));
- return;
+ return true;
}
+ boolean shouldFinish = true;
if (bundle.containsKey(Credentials.EXTRA_USER_PRIVATE_KEY_NAME)) {
final String key = bundle.getString(Credentials.EXTRA_USER_PRIVATE_KEY_NAME);
final byte[] value = bundle.getByteArray(Credentials.EXTRA_USER_PRIVATE_KEY_DATA);
@@ -259,7 +264,7 @@
if (!mKeyStore.importKey(key, value, uid, flags)) {
Log.e(TAG, "Failed to install " + key + " as uid " + uid);
- return;
+ return true;
}
// The key was prepended USER_PRIVATE_KEY by the CredentialHelper. However,
// KeyChain internally uses the raw alias name and only prepends USER_PRIVATE_KEY
@@ -270,6 +275,7 @@
if (uid == Process.SYSTEM_UID || uid == KeyStore.UID_SELF) {
new MarkKeyAsUserSelectable(
key.replaceFirst("^" + Credentials.USER_PRIVATE_KEY, "")).execute();
+ shouldFinish = false;
}
}
@@ -281,7 +287,7 @@
if (!mKeyStore.put(certName, certData, uid, flags)) {
Log.e(TAG, "Failed to install " + certName + " as uid " + uid);
- return;
+ return shouldFinish;
}
}
@@ -291,7 +297,7 @@
if (!mKeyStore.put(caListName, caListData, uid, flags)) {
Log.e(TAG, "Failed to install " + caListName + " as uid " + uid);
- return;
+ return shouldFinish;
}
}
@@ -300,6 +306,7 @@
sendBroadcast(broadcast);
setResult(RESULT_OK);
+ return shouldFinish;
}
/**
@@ -411,6 +418,13 @@
return false;
}
}
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ Log.i(TAG, String.format("Marked alias %s as selectable, success? %s",
+ mAlias, result));
+ CredentialStorage.this.finish();
+ }
}
/**
diff --git a/src/com/android/settings/CryptKeeper.java b/src/com/android/settings/CryptKeeper.java
index ca54b07..05054b4 100644
--- a/src/com/android/settings/CryptKeeper.java
+++ b/src/com/android/settings/CryptKeeper.java
@@ -772,9 +772,10 @@
if (imeSwitcher != null && hasMultipleEnabledIMEsOrSubtypes(imm, false)) {
imeSwitcher.setVisibility(View.VISIBLE);
imeSwitcher.setOnClickListener(new OnClickListener() {
- @Override
+ @Override
public void onClick(View v) {
- imm.showInputMethodPicker(false /* showAuxiliarySubtypes */);
+ imm.showInputMethodPickerFromSystem(false /* showAuxiliarySubtypes */,
+ v.getDisplay().getDisplayId());
}
});
}
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index d6590fa..76be66d 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -667,6 +667,8 @@
mToggleInversionPreference.getOrder() + 1);
mToggleDisableAnimationsPreference.setOrder(
mToggleLargePointerIconPreference.getOrder() + 1);
+ findPreference(ACCESSIBILITY_CONTENT_TIMEOUT_PREFERENCE).setOrder(
+ mToggleDisableAnimationsPreference.getOrder() + 1);
mToggleInversionPreference.setSummary(R.string.summary_empty);
displayCategory.addPreference(mToggleInversionPreference);
displayCategory.addPreference(mDisplayDaltonizerPreferenceScreen);
diff --git a/src/com/android/settings/accounts/CrossProfileCalendarPreferenceController.java b/src/com/android/settings/accounts/CrossProfileCalendarPreferenceController.java
new file mode 100644
index 0000000..38c95dc
--- /dev/null
+++ b/src/com/android/settings/accounts/CrossProfileCalendarPreferenceController.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package com.android.settings.accounts;
+
+import static android.provider.Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.slices.SliceData;
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+import androidx.preference.Preference;
+
+public class CrossProfileCalendarPreferenceController extends TogglePreferenceController {
+
+ private UserHandle mManagedUser;
+
+ public CrossProfileCalendarPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ public void setManagedUser(UserHandle managedUser) {
+ mManagedUser = managedUser;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return (mManagedUser != null) ? AVAILABLE : DISABLED_FOR_USER;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (preference instanceof RestrictedSwitchPreference && mManagedUser != null) {
+ final RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
+ final RestrictedLockUtils.EnforcedAdmin enforcedAdmin =
+ RestrictedLockUtilsInternal.getCrossProfileCalendarEnforcingAdmin(
+ mContext, mManagedUser.getIdentifier());
+ pref.setDisabledByAdmin(enforcedAdmin);
+ }
+ }
+
+ @Override
+ public boolean isChecked() {
+ if (mManagedUser == null) {
+ return false;
+ }
+ return Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ CROSS_PROFILE_CALENDAR_ENABLED, /* default= */ 0,
+ mManagedUser.getIdentifier()) == 1;
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ if (mManagedUser == null) {
+ return false;
+ }
+ final int value = isChecked ? 1 : 0;
+ return Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ CROSS_PROFILE_CALENDAR_ENABLED, value, mManagedUser.getIdentifier());
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/accounts/EmergencyInfoPreferenceController.java b/src/com/android/settings/accounts/EmergencyInfoPreferenceController.java
index 408db09..33e7771 100644
--- a/src/com/android/settings/accounts/EmergencyInfoPreferenceController.java
+++ b/src/com/android/settings/accounts/EmergencyInfoPreferenceController.java
@@ -36,8 +36,9 @@
public class EmergencyInfoPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin {
+ public static final String ACTION_EDIT_EMERGENCY_INFO = "android.settings.EDIT_EMERGENCY_INFO";
+
private static final String KEY_EMERGENCY_INFO = "emergency_info";
- private static final String ACTION_EDIT_EMERGENCY_INFO = "android.settings.EDIT_EMERGENCY_INFO";
private static final String PACKAGE_NAME_EMERGENCY = "com.android.emergency";
public EmergencyInfoPreferenceController(Context context) {
@@ -57,7 +58,7 @@
public void updateState(Preference preference) {
UserInfo info = mContext.getSystemService(UserManager.class).getUserInfo(
- UserHandle.myUserId());
+ UserHandle.myUserId());
preference.setSummary(mContext.getString(R.string.emergency_info_summary, info.name));
}
diff --git a/src/com/android/settings/accounts/ManagedProfileSettings.java b/src/com/android/settings/accounts/ManagedProfileSettings.java
index 07e5845..dccd7f6 100644
--- a/src/com/android/settings/accounts/ManagedProfileSettings.java
+++ b/src/com/android/settings/accounts/ManagedProfileSettings.java
@@ -23,17 +23,25 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.SearchIndexableResource;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settingslib.search.SearchIndexable;
+
+import java.util.ArrayList;
+import java.util.List;
/**
* Setting page for managed profile.
* FIXME: It currently assumes there is only one managed profile.
*/
+@SearchIndexable
public class ManagedProfileSettings extends DashboardFragment {
private UserManager mUserManager;
@@ -63,6 +71,7 @@
}
use(WorkModePreferenceController.class).setManagedUser(mManagedUser);
use(ContactSearchPreferenceController.class).setManagedUser(mManagedUser);
+ use(CrossProfileCalendarPreferenceController.class).setManagedUser(mManagedUser);
}
@Override
@@ -99,6 +108,23 @@
return MetricsProto.MetricsEvent.ACCOUNTS_WORK_PROFILE_SETTINGS;
}
+ public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
+ boolean enabled) {
+ final ArrayList<SearchIndexableResource> result = new ArrayList<>();
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.managed_profile_settings;
+ result.add(sir);
+ return result;
+ }
+ @Override
+ protected boolean isPageSearchEnabled(Context context) {
+ return false;
+ }
+ };
+
private class ManagedProfileBroadcastReceiver extends BroadcastReceiver {
@Override
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index 6b2fb91..c2db019 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -67,11 +67,14 @@
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.Filter;
import android.widget.FrameLayout;
+import android.widget.SearchView;
import android.widget.Spinner;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
+import androidx.annotation.WorkerThread;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -140,7 +143,7 @@
* intent.
*/
public class ManageApplications extends InstrumentedFragment
- implements View.OnClickListener, OnItemSelectedListener {
+ implements View.OnClickListener, OnItemSelectedListener, SearchView.OnQueryTextListener {
static final String TAG = "ManageApplications";
static final boolean DEBUG = true;
@@ -196,6 +199,7 @@
private View mListContainer;
private RecyclerView mRecyclerView;
+ private SearchView mSearchView;
// Size resource used for packages whose size computation failed for some reason
CharSequence mInvalidSizeStr;
@@ -599,6 +603,13 @@
mOptionsMenu = menu;
inflater.inflate(R.menu.manage_apps, menu);
+ final MenuItem searchMenuItem = menu.findItem(R.id.search_app_list_menu);
+ if (searchMenuItem != null) {
+ mSearchView = (SearchView) searchMenuItem.getActionView();
+ mSearchView.setQueryHint(getText(R.string.search_settings));
+ mSearchView.setOnQueryTextListener(this);
+ }
+
updateOptionsMenu();
}
@@ -724,6 +735,17 @@
public void onNothingSelected(AdapterView<?> parent) {
}
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ return false;
+ }
+
+ @Override
+ public boolean onQueryTextChange(String newText) {
+ mApplications.filterSearch(newText);
+ return false;
+ }
+
public void updateView() {
updateOptionsMenu();
final Activity host = getActivity();
@@ -859,6 +881,7 @@
private AppFilterItem mAppFilter;
private ArrayList<ApplicationsState.AppEntry> mEntries;
+ private ArrayList<ApplicationsState.AppEntry> mOriginalEntries;
private boolean mResumed;
private int mLastSortMode = -1;
private int mWhichSize = SIZE_TOTAL;
@@ -866,6 +889,7 @@
private boolean mHasReceivedLoadEntries;
private boolean mHasReceivedBridgeCallback;
private FileViewHolderController mExtraViewController;
+ private SearchFilter mSearchFilter;
// This is to remember and restore the last scroll position when this
// fragment is paused. We need this special handling because app entries are added gradually
@@ -1100,6 +1124,13 @@
});
}
+ public void filterSearch(String query) {
+ if (mSearchFilter == null) {
+ mSearchFilter = new SearchFilter();
+ }
+ mSearchFilter.filter(query);
+ }
+
@VisibleForTesting
static boolean shouldUseStableItemHeight(int listType) {
return true;
@@ -1146,6 +1177,7 @@
entries = removeDuplicateIgnoringUser(entries);
}
mEntries = entries;
+ mOriginalEntries = entries;
notifyDataSetChanged();
if (getItemCount() == 0) {
mManageApplications.mRecyclerView.setVisibility(View.GONE);
@@ -1153,6 +1185,14 @@
} else {
mManageApplications.mEmptyView.setVisibility(View.GONE);
mManageApplications.mRecyclerView.setVisibility(View.VISIBLE);
+
+ if (mManageApplications.mSearchView != null
+ && mManageApplications.mSearchView.isVisibleToUser()) {
+ final CharSequence query = mManageApplications.mSearchView.getQuery();
+ if (!TextUtils.isEmpty(query)) {
+ filterSearch(query.toString());
+ }
+ }
}
// Restore the last scroll position if the number of entries added so far is bigger than
// it.
@@ -1405,6 +1445,38 @@
}
}
}
+
+ /**
+ * An array filter that constrains the content of the array adapter with a substring.
+ * Item that does not contains the specified substring will be removed from the list.</p>
+ */
+ private class SearchFilter extends Filter {
+ @WorkerThread
+ @Override
+ protected FilterResults performFiltering(CharSequence query) {
+ final ArrayList<ApplicationsState.AppEntry> matchedEntries;
+ if (TextUtils.isEmpty(query)) {
+ matchedEntries = mOriginalEntries;
+ } else {
+ matchedEntries = new ArrayList<>();
+ for (ApplicationsState.AppEntry entry : mOriginalEntries) {
+ if (entry.label.toLowerCase().contains(query.toString().toLowerCase())) {
+ matchedEntries.add(entry);
+ }
+ }
+ }
+ final FilterResults results = new FilterResults();
+ results.values = matchedEntries;
+ results.count = matchedEntries.size();
+ return results;
+ }
+
+ @Override
+ protected void publishResults(CharSequence constraint, FilterResults results) {
+ mEntries = (ArrayList<ApplicationsState.AppEntry>) results.values;
+ notifyDataSetChanged();
+ }
+ }
}
private static class SummaryProvider implements SummaryLoader.SummaryProvider {
diff --git a/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java b/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java
index de8902a..19339cd 100644
--- a/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java
+++ b/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java
@@ -199,20 +199,7 @@
private void onNegative() {
if (DEBUG) Log.d(TAG, "onNegative");
-
- boolean always = true;
- if (mRequestType == BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS) {
- LocalBluetoothManager bluetoothManager = Utils.getLocalBtManager(this);
- CachedBluetoothDeviceManager cachedDeviceManager =
- bluetoothManager.getCachedDeviceManager();
- CachedBluetoothDevice cachedDevice = cachedDeviceManager.findDevice(mDevice);
- if (cachedDevice == null) {
- cachedDevice = cachedDeviceManager.addDevice(mDevice);
- }
- always = cachedDevice.checkAndIncreaseMessageRejectionCount();
- }
-
- sendReplyIntentToReceiver(false, always);
+ sendReplyIntentToReceiver(false, true);
}
private void sendReplyIntentToReceiver(final boolean allowed, final boolean always) {
diff --git a/src/com/android/settings/core/FeatureFlags.java b/src/com/android/settings/core/FeatureFlags.java
index daa1e7b..b350778 100644
--- a/src/com/android/settings/core/FeatureFlags.java
+++ b/src/com/android/settings/core/FeatureFlags.java
@@ -26,4 +26,5 @@
public static final String MOBILE_NETWORK_V2 = "settings_mobile_network_v2";
public static final String WIFI_MAC_RANDOMIZATION = "settings_wifi_mac_randomization";
public static final String NETWORK_INTERNET_V2 = "settings_network_and_internet_v2";
+ public static final String WIFI_SHARING = "settings_wifi_sharing";
}
diff --git a/src/com/android/settings/core/PreferenceXmlParserUtils.java b/src/com/android/settings/core/PreferenceXmlParserUtils.java
index 9fdeeef..ce5c505 100644
--- a/src/com/android/settings/core/PreferenceXmlParserUtils.java
+++ b/src/com/android/settings/core/PreferenceXmlParserUtils.java
@@ -55,6 +55,8 @@
private static final List<String> SUPPORTED_PREF_TYPES = Arrays.asList(
"Preference", "PreferenceCategory", "PreferenceScreen",
"com.android.settings.widget.WorkOnlyCategory");
+ public static final int PREPEND_VALUE = 0;
+ public static final int APPEND_VALUE = 1;
/**
* Flag definition to indicate which metadata should be extracted when
@@ -84,6 +86,7 @@
int FLAG_NEED_KEYWORDS = 1 << 8;
int FLAG_NEED_SEARCHABLE = 1 << 9;
int FLAG_ALLOW_DYNAMIC_SUMMARY_IN_SLICE = 1 << 10;
+ int FLAG_NEED_PREF_APPEND = 1 << 11;
}
public static final String METADATA_PREF_TYPE = "type";
@@ -97,6 +100,7 @@
public static final String METADATA_SEARCHABLE = "searchable";
public static final String METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE =
"allow_dynamic_summary_in_slice";
+ public static final String METADATA_APPEND = "staticPreferenceLocation";
private static final String ENTRIES_SEPARATOR = "|";
@@ -184,14 +188,13 @@
// Parse next until start tag is found
}
final int outerDepth = parser.getDepth();
-
+ final boolean hasPrefScreenFlag = hasFlag(flags, MetadataFlag.FLAG_INCLUDE_PREF_SCREEN);
do {
if (type != XmlPullParser.START_TAG) {
continue;
}
final String nodeName = parser.getName();
- if (!hasFlag(flags, MetadataFlag.FLAG_INCLUDE_PREF_SCREEN)
- && TextUtils.equals(PREF_SCREEN_TAG, nodeName)) {
+ if (!hasPrefScreenFlag && TextUtils.equals(PREF_SCREEN_TAG, nodeName)) {
continue;
}
if (!SUPPORTED_PREF_TYPES.contains(nodeName) && !nodeName.endsWith("Preference")) {
@@ -199,8 +202,14 @@
}
final Bundle preferenceMetadata = new Bundle();
final AttributeSet attrs = Xml.asAttributeSet(parser);
+
final TypedArray preferenceAttributes = context.obtainStyledAttributes(attrs,
R.styleable.Preference);
+ TypedArray preferenceScreenAttributes = null;
+ if (hasPrefScreenFlag) {
+ preferenceScreenAttributes = context.obtainStyledAttributes(
+ attrs, R.styleable.PreferenceScreen);
+ }
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_TYPE)) {
preferenceMetadata.putString(METADATA_PREF_TYPE, nodeName);
@@ -236,6 +245,10 @@
preferenceMetadata.putBoolean(METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE,
isDynamicSummaryAllowed(preferenceAttributes));
}
+ if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_APPEND) && hasPrefScreenFlag) {
+ preferenceMetadata.putBoolean(METADATA_APPEND,
+ isAppended(preferenceScreenAttributes));
+ }
metadata.add(preferenceMetadata);
preferenceAttributes.recycle();
@@ -325,7 +338,12 @@
false /* default */);
}
- private static String getKeywords(TypedArray styleAttributes) {
- return styleAttributes.getString(R.styleable.Preference_keywords);
+ private static String getKeywords(TypedArray styledAttributes) {
+ return styledAttributes.getString(R.styleable.Preference_keywords);
+ }
+
+ private static boolean isAppended(TypedArray styledAttributes) {
+ return styledAttributes.getInt(R.styleable.PreferenceScreen_staticPreferenceLocation,
+ PREPEND_VALUE) == APPEND_VALUE;
}
}
diff --git a/src/com/android/settings/datausage/ChartDataUsagePreference.java b/src/com/android/settings/datausage/ChartDataUsagePreference.java
index 1c8eb52..17f23c4 100644
--- a/src/com/android/settings/datausage/ChartDataUsagePreference.java
+++ b/src/com/android/settings/datausage/ChartDataUsagePreference.java
@@ -95,9 +95,13 @@
final SparseIntArray points = new SparseIntArray();
points.put(0, 0);
+ final long now = System.currentTimeMillis();
long totalData = 0;
for (NetworkCycleData data : usageSummary) {
final long startTime = data.getStartTime();
+ if (startTime > now) {
+ break;
+ }
final long endTime = data.getEndTime();
// increment by current bucket total
diff --git a/src/com/android/settings/development/AngleEnabledAppPreferenceController.java b/src/com/android/settings/development/AngleEnabledAppPreferenceController.java
deleted file mode 100644
index 3a7f6bf..0000000
--- a/src/com/android/settings/development/AngleEnabledAppPreferenceController.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * 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.development;
-
-import static com.android.settings.development.DevelopmentOptionsActivityRequestCodes
- .REQUEST_CODE_ANGLE_ENABLED_APP;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.provider.Settings;
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-
-import com.android.settings.R;
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.development.DeveloperOptionsPreferenceController;
-
-public class AngleEnabledAppPreferenceController extends DeveloperOptionsPreferenceController
- implements PreferenceControllerMixin, OnActivityResultListener {
-
- private static final String ANGLE_ENABLED_APP_KEY = "angle_enabled_app";
-
- private final DevelopmentSettingsDashboardFragment mFragment;
- private final PackageManager mPackageManager;
-
- public AngleEnabledAppPreferenceController(Context context,
- DevelopmentSettingsDashboardFragment fragment) {
- super(context);
- mFragment = fragment;
- mPackageManager = mContext.getPackageManager();
- }
-
- @Override
- public String getPreferenceKey() {
- return ANGLE_ENABLED_APP_KEY;
- }
-
- @Override
- public boolean handlePreferenceTreeClick(Preference preference) {
- if (ANGLE_ENABLED_APP_KEY.equals(preference.getKey())) {
- // pass it on to settings
- final Intent intent = getActivityStartIntent();
- mFragment.startActivityForResult(intent, REQUEST_CODE_ANGLE_ENABLED_APP);
- return true;
- }
- return false;
- }
-
- @Override
- public void updateState(Preference preference) {
- updatePreferenceSummary();
- }
-
- @Override
- public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode != REQUEST_CODE_ANGLE_ENABLED_APP || resultCode != Activity.RESULT_OK) {
- return false;
- }
- Settings.Global.putString(mContext.getContentResolver(), Settings.Global.ANGLE_ENABLED_APP,
- data.getAction());
- updatePreferenceSummary();
- return true;
- }
-
- @Override
- protected void onDeveloperOptionsSwitchDisabled() {
- super.onDeveloperOptionsSwitchDisabled();
- mPreference.setSummary(mContext.getResources().getString(
- R.string.angle_enabled_app_not_set));
- }
-
- @VisibleForTesting
- Intent getActivityStartIntent() {
- Intent intent = new Intent(mContext, AppPicker.class);
- intent.putExtra(AppPicker.EXTRA_NON_SYSTEM, true /* value */);
- return intent;
- }
-
- private void updatePreferenceSummary() {
- final String angleEnabledApp = Settings.Global.getString(
- mContext.getContentResolver(), Settings.Global.ANGLE_ENABLED_APP);
- if (angleEnabledApp != null && angleEnabledApp.length() > 0) {
- mPreference.setSummary(mContext.getResources().getString(
- R.string.angle_enabled_app_set,
- getAppLabel(angleEnabledApp)));
- } else {
- mPreference.setSummary(mContext.getResources().getString(
- R.string.angle_enabled_app_not_set));
- }
- }
-
- private String getAppLabel(String angleEnabledApp) {
- try {
- final ApplicationInfo ai = mPackageManager.getApplicationInfo(angleEnabledApp,
- PackageManager.GET_DISABLED_COMPONENTS);
- final CharSequence lab = mPackageManager.getApplicationLabel(ai);
- return lab != null ? lab.toString() : angleEnabledApp;
- } catch (PackageManager.NameNotFoundException e) {
- return angleEnabledApp;
- }
- }
-}
diff --git a/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java b/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java
index 0fcec05..95e663b 100644
--- a/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java
+++ b/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java
@@ -66,6 +66,25 @@
}
}
+ @Override
+ protected void onDeveloperOptionsSwitchDisabled() {
+ super.onDeveloperOptionsSwitchDisabled();
+ final boolean offloadSupported =
+ SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false);
+ if (offloadSupported) {
+ ((SwitchPreference) mPreference).setChecked(false);
+ SystemProperties.set(A2DP_OFFLOAD_DISABLED_PROPERTY, "false");
+ }
+ }
+
+ public boolean isDefaultValue() {
+ final boolean offloadSupported =
+ SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false);
+ final boolean offloadDisabled =
+ SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false);
+ return offloadSupported ? !offloadDisabled : true;
+ }
+
public void onA2dpHwDialogConfirmed() {
final boolean offloadDisabled =
SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false);
diff --git a/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java b/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java
index 3532a15..e65d2ad 100644
--- a/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java
+++ b/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java
@@ -26,7 +26,11 @@
int REQUEST_MOCK_LOCATION_APP = 2;
- int REQUEST_CODE_ANGLE_ENABLED_APP = 3;
+ int REQUEST_CODE_ANGLE_ALL_USE_ANGLE = 3;
- int REQUEST_CODE_UPDATED_GFX_DRIVER_DEV_OPT_IN_APP = 4;
+ int REQUEST_CODE_ANGLE_DRIVER_PKGS = 4;
+
+ int REQUEST_CODE_ANGLE_DRIVER_VALUES = 5;
+
+ int REQUEST_CODE_UPDATED_GFX_DRIVER_DEV_OPT_IN_APP = 6;
}
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 762686a..aa9918c 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -221,7 +221,16 @@
if (isChecked) {
EnableDevelopmentSettingWarningDialog.show(this /* host */);
} else {
- disableDeveloperOptions();
+ final BluetoothA2dpHwOffloadPreferenceController controller =
+ getDevelopmentOptionsController(
+ BluetoothA2dpHwOffloadPreferenceController.class);
+ // If A2DP hardware offload isn't default value, we must reboot after disable
+ // developer options. Show a dialog for the user to confirm.
+ if (controller == null || controller.isDefaultValue()) {
+ disableDeveloperOptions();
+ } else {
+ DisableDevSettingsDialogFragment.show(this /* host */);
+ }
}
}
}
@@ -380,6 +389,15 @@
mSwitchBar.setChecked(false);
}
+ void onDisableDevelopmentOptionsConfirmed() {
+ disableDeveloperOptions();
+ }
+
+ void onDisableDevelopmentOptionsRejected() {
+ // Reset the toggle
+ mSwitchBar.setChecked(true);
+ }
+
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Activity activity, Lifecycle lifecycle, DevelopmentSettingsDashboardFragment fragment,
BluetoothA2dpConfigStore bluetoothA2dpConfigStore) {
@@ -405,7 +423,6 @@
controllers.add(new SelectDebugAppPreferenceController(context, fragment));
controllers.add(new WaitForDebuggerPreferenceController(context));
controllers.add(new EnableGpuDebugLayersPreferenceController(context));
- controllers.add(new AngleEnabledAppPreferenceController(context, fragment));
controllers.add(new UpdatedGfxDriverDevOptInPreferenceController(context, fragment));
controllers.add(new VerifyAppsOverUsbPreferenceController(context));
controllers.add(new LogdSizePreferenceController(context));
diff --git a/src/com/android/settings/development/DisableDevSettingsDialogFragment.java b/src/com/android/settings/development/DisableDevSettingsDialogFragment.java
new file mode 100644
index 0000000..9b3ba58
--- /dev/null
+++ b/src/com/android/settings/development/DisableDevSettingsDialogFragment.java
@@ -0,0 +1,88 @@
+/*
+ * 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.development;
+
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.os.PowerManager;
+import android.util.Log;
+import androidx.annotation.VisibleForTesting;
+import androidx.fragment.app.Fragment;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.FragmentManager;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+public class DisableDevSettingsDialogFragment extends InstrumentedDialogFragment
+ implements DialogInterface.OnClickListener {
+
+ public static final String TAG = "DisableDevSettingDlg";
+
+ @VisibleForTesting
+ static DisableDevSettingsDialogFragment newInstance() {
+ final DisableDevSettingsDialogFragment dialog = new DisableDevSettingsDialogFragment();
+ return dialog;
+ }
+
+ public static void show(DevelopmentSettingsDashboardFragment host) {
+ final DisableDevSettingsDialogFragment dialog = new DisableDevSettingsDialogFragment();
+ dialog.setTargetFragment(host, 0 /* requestCode */);
+ final FragmentManager manager = host.getActivity().getSupportFragmentManager();
+ dialog.show(manager, TAG);
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.DIALOG_DISABLE_DEVELOPMENT_OPTIONS;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ // Reuse the same text of disable_a2dp_hw_offload_dialog.
+ // The text is generic enough to be used for turning off Dev options.
+ return new AlertDialog.Builder(getActivity())
+ .setMessage(R.string.bluetooth_disable_a2dp_hw_offload_dialog_message)
+ .setTitle(R.string.bluetooth_disable_a2dp_hw_offload_dialog_title)
+ .setPositiveButton(
+ R.string.bluetooth_disable_a2dp_hw_offload_dialog_confirm, this)
+ .setNegativeButton(
+ R.string.bluetooth_disable_a2dp_hw_offload_dialog_cancel, this)
+ .create();
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Fragment fragment = getTargetFragment();
+ if (!(fragment instanceof DevelopmentSettingsDashboardFragment)){
+ Log.e(TAG, "getTargetFragment return unexpected type");
+ }
+
+ final DevelopmentSettingsDashboardFragment host =
+ (DevelopmentSettingsDashboardFragment) fragment;
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ host.onDisableDevelopmentOptionsConfirmed();
+ PowerManager pm = getContext().getSystemService(PowerManager.class);
+ pm.reboot(null);
+ } else {
+ host.onDisableDevelopmentOptionsRejected();
+ }
+ }
+}
diff --git a/src/com/android/settings/flashlight/FlashlightSliceBuilder.java b/src/com/android/settings/flashlight/FlashlightSlice.java
similarity index 66%
rename from src/com/android/settings/flashlight/FlashlightSliceBuilder.java
rename to src/com/android/settings/flashlight/FlashlightSlice.java
index 5833229..a2c4561 100644
--- a/src/com/android/settings/flashlight/FlashlightSliceBuilder.java
+++ b/src/com/android/settings/flashlight/FlashlightSlice.java
@@ -28,6 +28,7 @@
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
+import android.net.Uri;
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.util.Log;
@@ -41,69 +42,78 @@
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.slices.CustomSliceRegistry;
-import com.android.settings.slices.SliceBroadcastReceiver;
+import com.android.settings.slices.CustomSliceable;
/**
* Utility class to build a Flashlight Slice, and handle all associated actions.
*/
-public class FlashlightSliceBuilder {
+public class FlashlightSlice implements CustomSliceable {
- private static final String TAG = "FlashlightSliceBuilder";
-
- /**
- * Action notifying a change on the Flashlight Slice.
- */
- public static final String ACTION_FLASHLIGHT_SLICE_CHANGED =
- "com.android.settings.flashlight.action.FLASHLIGHT_SLICE_CHANGED";
+ private static final String TAG = "FlashlightSlice";
/**
* Action broadcasting a change on whether flashlight is on or off.
*/
- public static final String ACTION_FLASHLIGHT_CHANGED =
+ private static final String ACTION_FLASHLIGHT_CHANGED =
"com.android.settings.flashlight.action.FLASHLIGHT_CHANGED";
- public static final IntentFilter INTENT_FILTER = new IntentFilter(ACTION_FLASHLIGHT_CHANGED);
+ private final Context mContext;
- private FlashlightSliceBuilder() {
+ public FlashlightSlice(Context context) {
+ mContext = context;
}
- public static Slice getSlice(Context context) {
- if (!isFlashlightAvailable(context)) {
+ @Override
+ public Slice getSlice() {
+ if (!isFlashlightAvailable(mContext)) {
return null;
}
- final PendingIntent toggleAction = getBroadcastIntent(context);
- @ColorInt final int color = Utils.getColorAccentDefaultColor(context);
+ final PendingIntent toggleAction = getBroadcastIntent(mContext);
+ @ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
final IconCompat icon =
- IconCompat.createWithResource(context, R.drawable.ic_signal_flashlight);
- return new ListBuilder(context, CustomSliceRegistry.FLASHLIGHT_SLICE_URI,
+ IconCompat.createWithResource(mContext, R.drawable.ic_signal_flashlight);
+ return new ListBuilder(mContext, CustomSliceRegistry.FLASHLIGHT_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor(color)
.addRow(new RowBuilder()
- .setTitle(context.getText(R.string.power_flashlight))
+ .setTitle(mContext.getText(R.string.power_flashlight))
.setTitleItem(icon, ICON_IMAGE)
.setPrimaryAction(
- SliceAction.createToggle(toggleAction, null, isFlashlightEnabled(context))))
+ SliceAction.createToggle(toggleAction, null,
+ isFlashlightEnabled(mContext))))
.build();
}
- /**
- * Update the current flashlight status to the boolean value keyed by
- * {@link android.app.slice.Slice#EXTRA_TOGGLE_STATE} on {@param intent}.
- */
- public static void handleUriChange(Context context, Intent intent) {
+ @Override
+ public Uri getUri() {
+ return CustomSliceRegistry.FLASHLIGHT_SLICE_URI;
+ }
+
+ @Override
+ public IntentFilter getIntentFilter() {
+ return new IntentFilter(ACTION_FLASHLIGHT_CHANGED);
+ }
+
+ @Override
+ public void onNotifyChange(Intent intent) {
try {
- final String cameraId = getCameraId(context);
+ final String cameraId = getCameraId(mContext);
if (cameraId != null) {
final boolean state = intent.getBooleanExtra(
- EXTRA_TOGGLE_STATE, isFlashlightEnabled(context));
- final CameraManager cameraManager = context.getSystemService(CameraManager.class);
+ EXTRA_TOGGLE_STATE, isFlashlightEnabled(mContext));
+ final CameraManager cameraManager = mContext.getSystemService(CameraManager.class);
cameraManager.setTorchMode(cameraId, state);
}
} catch (CameraAccessException e) {
Log.e(TAG, "Camera couldn't set torch mode.", e);
}
- context.getContentResolver().notifyChange(CustomSliceRegistry.FLASHLIGHT_SLICE_URI, null);
+ mContext.getContentResolver().notifyChange(CustomSliceRegistry.FLASHLIGHT_SLICE_URI, null);
+ }
+
+ @Override
+ public Intent getIntent() {
+ return null;
}
private static String getCameraId(Context context) throws CameraAccessException {
@@ -121,12 +131,6 @@
return null;
}
- private static PendingIntent getBroadcastIntent(Context context) {
- final Intent intent = new Intent(ACTION_FLASHLIGHT_SLICE_CHANGED);
- intent.setClass(context, SliceBroadcastReceiver.class);
- return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
- PendingIntent.FLAG_CANCEL_CURRENT);
- }
private static boolean isFlashlightAvailable(Context context) {
return Settings.Secure.getInt(
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
index e437e2b..32a86e8 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
@@ -16,8 +16,10 @@
package com.android.settings.homepage.contextualcards;
+import android.annotation.NonNull;
import android.content.Context;
import android.content.Intent;
+import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
@@ -25,6 +27,7 @@
import androidx.slice.widget.EventInfo;
import com.android.settings.R;
+import com.android.settings.intelligence.ContextualCardProto.ContextualCardList;
import java.util.List;
@@ -38,10 +41,6 @@
// Contextual card shows, log card name and rank
private static final int CONTEXTUAL_CARD_SHOW = 39;
- // Contextual card is eligible to be shown, but doesn't rank high
- // enough, log card name and score
- private static final int CONTEXTUAL_CARD_NOT_SHOW = 40;
-
// Contextual card is dismissed, log card name
private static final int CONTEXTUAL_CARD_DISMISS = 41;
@@ -67,6 +66,11 @@
// log type
private static final String EXTRA_CONTEXTUALCARD_ACTION_TYPE = "type";
+ // displayed contextual cards
+ private static final String EXTRA_CONTEXTUALCARD_VISIBLE = "visible";
+
+ // hidden contextual cards
+ private static final String EXTRA_CONTEXTUALCARD_HIDDEN = "hidden";
// Contextual card tap target
private static final int TARGET_DEFAULT = 0;
@@ -82,6 +86,10 @@
@Override
public void logHomepageDisplay(Context context, Long latency) {
+ final Intent intent = new Intent();
+ intent.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_HOME_SHOW);
+ intent.putExtra(EXTRA_LATENCY, latency);
+ sendBroadcast(context, intent);
}
@Override
@@ -94,8 +102,13 @@
}
@Override
- public void logContextualCardDisplay(Context context, List<ContextualCard> showCards,
+ public void logContextualCardDisplay(Context context, List<ContextualCard> visibleCards,
List<ContextualCard> hiddenCards) {
+ final Intent intent = new Intent();
+ intent.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_CARD_SHOW);
+ intent.putExtra(EXTRA_CONTEXTUALCARD_VISIBLE, serialize(visibleCards));
+ intent.putExtra(EXTRA_CONTEXTUALCARD_HIDDEN, serialize(hiddenCards));
+ sendBroadcast(context, intent);
}
@Override
@@ -116,7 +129,7 @@
final String action = context.getString(R.string.config_settingsintelligence_log_action);
if (!TextUtils.isEmpty(action)) {
intent.setAction(action);
- context.sendBroadcast(intent);
+ context.sendBroadcastAsUser(intent, UserHandle.ALL);
}
}
@@ -133,4 +146,16 @@
return TARGET_DEFAULT;
}
}
+
+ @VisibleForTesting
+ @NonNull
+ byte[] serialize(List<ContextualCard> cards) {
+ final ContextualCardList.Builder builder = ContextualCardList.newBuilder();
+ cards.stream().forEach(card -> builder.addCard(
+ com.android.settings.intelligence.ContextualCardProto.ContextualCard.newBuilder()
+ .setSliceUri(card.getSliceUri().toString())
+ .setCardName(card.getName())
+ .build()));
+ return builder.build().toByteArray();
+ }
}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
index 3ef4653..e631d22 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
@@ -20,6 +20,9 @@
import static androidx.slice.widget.SliceLiveData.SUPPORTED_SPECS;
+import static com.android.settings.slices.CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI;
+import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;
+
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
@@ -34,7 +37,7 @@
import androidx.annotation.VisibleForTesting;
import androidx.slice.Slice;
-import com.android.settings.slices.CustomSliceRegistry;
+import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.utils.AsyncLoaderCompat;
import java.util.ArrayList;
@@ -103,27 +106,50 @@
return getFinalDisplayableCards(result);
}
+ // Get final displayed cards and log what cards will be displayed/hidden
@VisibleForTesting
List<ContextualCard> getFinalDisplayableCards(List<ContextualCard> candidates) {
- List<ContextualCard> eligibleCards = filterEligibleCards(candidates);
- eligibleCards = eligibleCards.stream().limit(DEFAULT_CARD_COUNT).collect(
- Collectors.toList());
+ final List<ContextualCard> eligibleCards = filterEligibleCards(candidates);
+ final List<ContextualCard> visibleCards = new ArrayList<>();
+ final List<ContextualCard> hiddenCards = new ArrayList<>();
- if (eligibleCards.size() <= 2 || getNumberOfLargeCard(eligibleCards) == 0) {
- return eligibleCards;
+ final int size = eligibleCards.size();
+ for (int i = 0; i < size; i++) {
+ if (i < DEFAULT_CARD_COUNT) {
+ visibleCards.add(eligibleCards.get(i));
+ } else {
+ hiddenCards.add(eligibleCards.get(i));
+ }
}
- if (eligibleCards.size() == DEFAULT_CARD_COUNT) {
- eligibleCards.remove(eligibleCards.size() - 1);
+ try {
+ // The maximum cards are four small cards OR
+ // one large card with two small cards OR
+ // two large cards
+ if (visibleCards.size() <= 2 || getNumberOfLargeCard(visibleCards) == 0) {
+ // four small cards
+ return visibleCards;
+ }
+
+ if (visibleCards.size() == DEFAULT_CARD_COUNT) {
+ hiddenCards.add(visibleCards.remove(visibleCards.size() - 1));
+ }
+
+ if (getNumberOfLargeCard(visibleCards) == 1) {
+ // One large card with two small cards
+ return visibleCards;
+ }
+
+ hiddenCards.add(visibleCards.remove(visibleCards.size() - 1));
+
+ // Two large cards
+ return visibleCards;
+ } finally {
+ final ContextualCardFeatureProvider contextualCardFeatureProvider =
+ FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
+ contextualCardFeatureProvider.logContextualCardDisplay(mContext, visibleCards,
+ hiddenCards);
}
-
- if (getNumberOfLargeCard(eligibleCards) == 1) {
- return eligibleCards;
- }
-
- eligibleCards.remove(eligibleCards.size() - 1);
-
- return eligibleCards;
}
@VisibleForTesting
@@ -169,8 +195,8 @@
private int getNumberOfLargeCard(List<ContextualCard> cards) {
return (int) cards.stream()
- .filter(card -> card.getSliceUri().equals(CustomSliceRegistry.WIFI_SLICE_URI)
- || card.getSliceUri().equals(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI))
+ .filter(card -> card.getSliceUri().equals(WIFI_SLICE_URI)
+ || card.getSliceUri().equals(BLUETOOTH_DEVICES_SLICE_URI))
.count();
}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
index 5f397d7..28ad0d3 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
@@ -16,8 +16,7 @@
package com.android.settings.homepage.contextualcards;
-import static com.android.settings.homepage.contextualcards.ContextualCardLoader
- .CARD_CONTENT_LOADER_ID;
+import static com.android.settings.homepage.contextualcards.ContextualCardLoader.CARD_CONTENT_LOADER_ID;
import static java.util.stream.Collectors.groupingBy;
@@ -33,6 +32,7 @@
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;
+import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -72,6 +72,7 @@
private final List<LifecycleObserver> mLifecycleObservers;
private ContextualCardUpdateListener mListener;
+ private long mStartTime;
public ContextualCardManager(Context context, Lifecycle lifecycle) {
mContext = context;
@@ -86,6 +87,7 @@
}
void loadContextualCards(ContextualCardsFragment fragment) {
+ mStartTime = System.currentTimeMillis();
final CardContentLoaderCallbacks cardContentLoaderCallbacks =
new CardContentLoaderCallbacks(mContext);
cardContentLoaderCallbacks.setListener(this);
@@ -168,6 +170,10 @@
@Override
public void onFinishCardLoading(List<ContextualCard> cards) {
onContextualCardUpdated(cards.stream().collect(groupingBy(ContextualCard::getCardType)));
+ final long elapsedTime = System.currentTimeMillis() - mStartTime;
+ final ContextualCardFeatureProvider contextualCardFeatureProvider =
+ FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
+ contextualCardFeatureProvider.logHomepageDisplay(mContext, elapsedTime);
}
public ControllerRendererPool getControllerRendererPool() {
diff --git a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
index 376bb83..d5500fb 100644
--- a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
+++ b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
@@ -40,8 +40,8 @@
.build();
final ContextualCard connectedDeviceCard =
ContextualCard.newBuilder()
- .setSliceUri(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI.toString())
- .setCardName(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI.toString())
+ .setSliceUri(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI.toString())
+ .setCardName(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI.toString())
.setCardCategory(ContextualCard.Category.IMPORTANT)
.build();
final ContextualCard lowStorageCard =
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/BatterySlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/BatterySlice.java
index b0d6963..5271e12 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/BatterySlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/BatterySlice.java
@@ -16,8 +16,6 @@
package com.android.settings.homepage.contextualcards.deviceinfo;
-import static com.android.settings.slices.CustomSliceRegistry.BATTERY_INFO_SLICE_URI;
-
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
@@ -37,6 +35,7 @@
import com.android.settings.Utils;
import com.android.settings.fuelgauge.BatteryInfo;
import com.android.settings.fuelgauge.PowerUsageSummary;
+import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
import com.android.settings.slices.SliceBuilderUtils;
@@ -66,7 +65,8 @@
final CharSequence title = mContext.getText(R.string.power_usage_summary_title);
final SliceAction primarySliceAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
ListBuilder.ICON_IMAGE, title);
- final Slice slice = new ListBuilder(mContext, BATTERY_INFO_SLICE_URI, ListBuilder.INFINITY)
+ final Slice slice = new ListBuilder(mContext, CustomSliceRegistry.BATTERY_INFO_SLICE_URI,
+ ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
.setHeader(new ListBuilder.HeaderBuilder().setTitle(title))
.addRow(new ListBuilder.RowBuilder()
@@ -81,7 +81,7 @@
@Override
public Uri getUri() {
- return BATTERY_INFO_SLICE_URI;
+ return CustomSliceRegistry.BATTERY_INFO_SLICE_URI;
}
@Override
@@ -95,7 +95,8 @@
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
PowerUsageSummary.class.getName(), "" /* key */, screenTitle,
MetricsProto.MetricsEvent.SLICE)
- .setClassName(mContext.getPackageName(), SubSettings.class.getName());
+ .setClassName(mContext.getPackageName(), SubSettings.class.getName())
+ .setData(CustomSliceRegistry.BATTERY_INFO_SLICE_URI);
}
@Override
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/DataUsageSlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/DataUsageSlice.java
index bb78586..6e94f6d 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/DataUsageSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/DataUsageSlice.java
@@ -94,7 +94,8 @@
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
DataUsageSummary.class.getName(), "" /* key */, screenTitle,
MetricsProto.MetricsEvent.SLICE)
- .setClassName(mContext.getPackageName(), SubSettings.class.getName());
+ .setClassName(mContext.getPackageName(), SubSettings.class.getName())
+ .setData(CustomSliceRegistry.DATA_USAGE_SLICE_URI);
}
private PendingIntent getPrimaryAction() {
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/DeviceInfoSlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/DeviceInfoSlice.java
index 694336d..1f75ab1 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/DeviceInfoSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/DeviceInfoSlice.java
@@ -85,7 +85,8 @@
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
MyDeviceInfoFragment.class.getName(), "" /* key */, screenTitle,
MetricsProto.MetricsEvent.SLICE)
- .setClassName(mContext.getPackageName(), SubSettings.class.getName());
+ .setClassName(mContext.getPackageName(), SubSettings.class.getName())
+ .setData(CustomSliceRegistry.DEVICE_INFO_SLICE_URI);
}
private PendingIntent getPrimaryAction() {
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/EmergencyInfoSlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/EmergencyInfoSlice.java
index 2484e53..f8be2d6 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/EmergencyInfoSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/EmergencyInfoSlice.java
@@ -16,9 +16,12 @@
package com.android.settings.homepage.contextualcards.deviceinfo;
+import static com.android.settings.accounts.EmergencyInfoPreferenceController.ACTION_EDIT_EMERGENCY_INFO;
+
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
+import android.net.Uri;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
@@ -27,37 +30,57 @@
import com.android.settings.R;
import com.android.settings.slices.CustomSliceRegistry;
+import com.android.settings.slices.CustomSliceable;
// This is a slice helper class for EmergencyInfo
-public class EmergencyInfoSlice {
+public class EmergencyInfoSlice implements CustomSliceable {
- private static final String ACTION_EDIT_EMERGENCY_INFO = "android.settings.EDIT_EMERGENCY_INFO";
+ private final Context mContext;
- public static Slice getSlice(Context context) {
- final ListBuilder listBuilder = new ListBuilder(context,
+ public EmergencyInfoSlice(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ public Slice getSlice() {
+ final ListBuilder listBuilder = new ListBuilder(mContext,
CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI,
ListBuilder.INFINITY);
listBuilder.addRow(
new ListBuilder.RowBuilder()
- .setTitle(context.getText(R.string.emergency_info_title))
+ .setTitle(mContext.getText(R.string.emergency_info_title))
.setSubtitle(
- context.getText(R.string.emergency_info_contextual_card_summary))
- .setPrimaryAction(createPrimaryAction(context)));
+ mContext.getText(R.string.emergency_info_contextual_card_summary))
+ .setPrimaryAction(createPrimaryAction()));
return listBuilder.build();
}
- private static SliceAction createPrimaryAction(Context context) {
- PendingIntent pendingIntent =
+ @Override
+ public Uri getUri() {
+ return CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI;
+ }
+
+ @Override
+ public Intent getIntent() {
+ return new Intent(ACTION_EDIT_EMERGENCY_INFO);
+ }
+
+ @Override
+ public void onNotifyChange(Intent intent) {
+ }
+
+ private SliceAction createPrimaryAction() {
+ final PendingIntent pendingIntent =
PendingIntent.getActivity(
- context,
+ mContext,
0 /* requestCode */,
- new Intent(ACTION_EDIT_EMERGENCY_INFO),
+ getIntent(),
PendingIntent.FLAG_UPDATE_CURRENT);
return SliceAction.createDeeplink(
pendingIntent,
- IconCompat.createWithResource(context, R.drawable.empty_icon),
+ IconCompat.createWithResource(mContext, R.drawable.empty_icon),
ListBuilder.ICON_IMAGE,
- context.getText(R.string.emergency_info_title));
+ mContext.getText(R.string.emergency_info_title));
}
}
diff --git a/src/com/android/settings/homepage/contextualcards/deviceinfo/StorageSlice.java b/src/com/android/settings/homepage/contextualcards/deviceinfo/StorageSlice.java
index eba831a..799a701 100644
--- a/src/com/android/settings/homepage/contextualcards/deviceinfo/StorageSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/deviceinfo/StorageSlice.java
@@ -80,7 +80,8 @@
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
StorageDashboardFragment.class.getName(), "" /* key */, screenTitle,
MetricsProto.MetricsEvent.SLICE)
- .setClassName(mContext.getPackageName(), SubSettings.class.getName());
+ .setClassName(mContext.getPackageName(), SubSettings.class.getName())
+ .setData(CustomSliceRegistry.STORAGE_SLICE_URI);
}
private PendingIntent getPrimaryAction() {
diff --git a/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
similarity index 67%
rename from src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java
rename to src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
index 0c79b6b..ad8d4a6 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
@@ -17,6 +17,7 @@
package com.android.settings.homepage.contextualcards.slices;
import android.app.PendingIntent;
+import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
@@ -40,6 +41,7 @@
import com.android.settings.SubSettings;
import com.android.settings.Utils;
import com.android.settings.bluetooth.BluetoothDeviceDetailsFragment;
+import com.android.settings.bluetooth.BluetoothPairingDetail;
import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.slices.CustomSliceRegistry;
@@ -48,7 +50,6 @@
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
-import com.android.settingslib.core.instrumentation.Instrumentable;
import java.util.ArrayList;
import java.util.Collection;
@@ -56,28 +57,27 @@
import java.util.List;
import java.util.stream.Collectors;
-/**
- * TODO(b/114807655): Contextual Home Page - Connected Device
- *
- * Show connected device info if one is currently connected. UI for connected device should
- * match Connected Devices > Currently Connected Devices
- *
- * TODO This class will be refactor for Bluetooth connected devices only.
- */
-public class ConnectedDeviceSlice implements CustomSliceable {
+public class BluetoothDevicesSlice implements CustomSliceable {
/**
- * To sort the Bluetooth devices by {@link CachedBluetoothDevice}.
- * Refer compareTo method from {@link com.android.settings.bluetooth.BluetoothDevicePreference}.
+ * TODO(b/114807655): Contextual Home Page - Connected Device
+ * Re-design sorting for new rule:
+ * Sorting rule: Audio Streaming > Last connected > Recently connected.
*/
private static final Comparator<CachedBluetoothDevice> COMPARATOR
= Comparator.naturalOrder();
- private static final String TAG = "ConnectedDeviceSlice";
+ /**
+ * Add the "Pair new device" in the end of slice, when the number of Bluetooth devices is less
+ * than {@link #DEFAULT_EXPANDED_ROW_COUNT}.
+ */
+ private static final int DEFAULT_EXPANDED_ROW_COUNT = 3;
+
+ private static final String TAG = "BluetoothDevicesSlice";
private final Context mContext;
- public ConnectedDeviceSlice(Context context) {
+ public BluetoothDevicesSlice(Context context) {
mContext = context;
}
@@ -94,47 +94,53 @@
@Override
public Uri getUri() {
- return CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI;
+ return CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI;
}
@Override
public Slice getSlice() {
final IconCompat icon = IconCompat.createWithResource(mContext,
- R.drawable.ic_homepage_connected_device);
- final CharSequence title = mContext.getText(R.string.bluetooth_connected_devices);
- final CharSequence titleNoConnectedDevices = mContext.getText(
- R.string.no_connected_devices);
+ R.drawable.ic_settings_bluetooth);
+ final CharSequence title = mContext.getText(R.string.bluetooth_devices);
+ final CharSequence titleNoBluetoothDevices = mContext.getText(
+ R.string.no_bluetooth_devices);
final PendingIntent primaryActionIntent = PendingIntent.getActivity(mContext, 0,
getIntent(), 0);
final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryActionIntent, icon,
ListBuilder.ICON_IMAGE, title);
final ListBuilder listBuilder =
- new ListBuilder(mContext, CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI,
+ new ListBuilder(mContext, CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext));
- // Get row builders by connected devices, e.g. Bluetooth.
+ // Get row builders by Bluetooth devices.
final List<ListBuilder.RowBuilder> rows = getBluetoothRowBuilder(primarySliceAction);
- // Return a header with IsError flag, if no connected devices.
+ // Return a header with IsError flag, if no Bluetooth devices.
if (rows.isEmpty()) {
return listBuilder.setHeader(new ListBuilder.HeaderBuilder()
- .setTitle(titleNoConnectedDevices)
+ .setTitle(titleNoBluetoothDevices)
.setPrimaryAction(primarySliceAction))
.setIsError(true)
.build();
}
- // According the number of connected devices to set sub title of header.
+ // According the number of Bluetooth devices to set sub title of header.
listBuilder.setHeader(new ListBuilder.HeaderBuilder()
.setTitle(title)
.setSubtitle(getSubTitle(rows.size()))
.setPrimaryAction(primarySliceAction));
- // Add rows.
+ // Add bluetooth device rows.
for (ListBuilder.RowBuilder rowBuilder : rows) {
listBuilder.addRow(rowBuilder);
}
+
+ // Add "Pair new device" if need.
+ if (rows.size() < DEFAULT_EXPANDED_ROW_COUNT) {
+ listBuilder.addRow(getPairNewDeviceRowBuilder());
+ }
+
return listBuilder.build();
}
@@ -147,7 +153,8 @@
ConnectedDeviceDashboardFragment.class.getName(), "" /* key */,
screenTitle,
MetricsProto.MetricsEvent.SLICE)
- .setClassName(mContext.getPackageName(), SubSettings.class.getName());
+ .setClassName(mContext.getPackageName(), SubSettings.class.getName())
+ .setData(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI);
}
@Override
@@ -160,25 +167,30 @@
}
@VisibleForTesting
- List<CachedBluetoothDevice> getBluetoothConnectedDevices() {
- final List<CachedBluetoothDevice> connectedBluetoothList = new ArrayList<>();
+ List<CachedBluetoothDevice> getBluetoothDevices() {
+ final List<CachedBluetoothDevice> bluetoothDeviceList = new ArrayList<>();
// If Bluetooth is disable, skip to get the bluetooth devices.
if (!BluetoothAdapter.getDefaultAdapter().isEnabled()) {
- Log.i(TAG, "Cannot get Bluetooth connected devices, Bluetooth is disabled.");
- return connectedBluetoothList;
+ Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is disabled.");
+ return bluetoothDeviceList;
}
// Get the Bluetooth devices from LocalBluetoothManager.
final LocalBluetoothManager bluetoothManager =
com.android.settings.bluetooth.Utils.getLocalBtManager(mContext);
if (bluetoothManager == null) {
- Log.i(TAG, "Cannot get Bluetooth connected devices, Bluetooth is unsupported.");
- return connectedBluetoothList;
+ Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is unsupported.");
+ return bluetoothDeviceList;
}
final Collection<CachedBluetoothDevice> cachedDevices =
bluetoothManager.getCachedDeviceManager().getCachedDevicesCopy();
+ /**
+ * TODO(b/114807655): Contextual Home Page - Connected Device
+ * Re-design to get all Bluetooth devices and sort them by new rule:
+ * Sorting rule: Audio Streaming > Last connected > Recently connected.
+ */
// Get connected Bluetooth devices and sort them.
return cachedDevices.stream().filter(device -> device.isConnected()).sorted(
COMPARATOR).collect(Collectors.toList());
@@ -193,7 +205,7 @@
subSettingLauncher.setDestination(BluetoothDeviceDetailsFragment.class.getName())
.setArguments(args)
.setTitleRes(R.string.device_details_title)
- .setSourceMetricsCategory(Instrumentable.METRICS_CATEGORY_UNKNOWN);
+ .setSourceMetricsCategory(SettingsEnums.BLUETOOTH_DEVICE_DETAILS);
// The requestCode should be unique, use the hashcode of device as request code.
return PendingIntent
@@ -203,25 +215,29 @@
}
@VisibleForTesting
- IconCompat getConnectedDeviceIcon(CachedBluetoothDevice device) {
+ IconCompat getBluetoothDeviceIcon(CachedBluetoothDevice device) {
final Pair<Drawable, String> pair = BluetoothUtils
.getBtClassDrawableWithDescription(mContext, device);
if (pair.first != null) {
return IconCompat.createWithBitmap(getBitmapFromVectorDrawable(pair.first));
} else {
- return IconCompat.createWithResource(mContext, R.drawable.ic_homepage_connected_device);
+ return IconCompat.createWithResource(mContext, R.drawable.ic_settings_bluetooth);
}
}
private List<ListBuilder.RowBuilder> getBluetoothRowBuilder(SliceAction primarySliceAction) {
final List<ListBuilder.RowBuilder> bluetoothRows = new ArrayList<>();
- // According Bluetooth connected device to create row builders.
- final List<CachedBluetoothDevice> bluetoothDevices = getBluetoothConnectedDevices();
+ /**
+ * TODO(b/114807655): Contextual Home Page - Connected Device
+ * Re-design to do action "activating" in primary action.
+ */
+ // According Bluetooth device to create row builders.
+ final List<CachedBluetoothDevice> bluetoothDevices = getBluetoothDevices();
for (CachedBluetoothDevice bluetoothDevice : bluetoothDevices) {
bluetoothRows.add(new ListBuilder.RowBuilder()
- .setTitleItem(getConnectedDeviceIcon(bluetoothDevice), ListBuilder.ICON_IMAGE)
+ .setTitleItem(getBluetoothDeviceIcon(bluetoothDevice), ListBuilder.ICON_IMAGE)
.setTitle(bluetoothDevice.getName())
.setSubtitle(bluetoothDevice.getConnectionSummary())
.setPrimaryAction(primarySliceAction)
@@ -240,7 +256,31 @@
}
private CharSequence getSubTitle(int deviceCount) {
- return mContext.getResources().getQuantityString(R.plurals.show_connected_devices,
+ return mContext.getResources().getQuantityString(R.plurals.show_bluetooth_devices,
deviceCount, deviceCount);
}
+
+ private ListBuilder.RowBuilder getPairNewDeviceRowBuilder() {
+ final CharSequence title = mContext.getText(R.string.bluetooth_pairing_pref_title);
+ final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_menu_add);
+ final SliceAction sliceAction = SliceAction.createDeeplink(
+ getPairNewDeviceIntent(),
+ IconCompat.createWithResource(mContext, R.drawable.ic_settings),
+ ListBuilder.ICON_IMAGE, title);
+
+ return new ListBuilder.RowBuilder()
+ .setTitleItem(icon, ListBuilder.ICON_IMAGE)
+ .setTitle(title)
+ .setPrimaryAction(sliceAction);
+ }
+
+ private PendingIntent getPairNewDeviceIntent() {
+ final Intent intent = new SubSettingLauncher(mContext)
+ .setDestination(BluetoothPairingDetail.class.getName())
+ .setTitleRes(R.string.bluetooth_pairing_page_title)
+ .setSourceMetricsCategory(SettingsEnums.BLUETOOTH_PAIRING)
+ .toIntent();
+
+ return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */);
+ }
}
\ No newline at end of file
diff --git a/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java b/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
index 3cbbb0c..e0f3116 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
@@ -110,7 +110,8 @@
StorageSettings.class.getName(), "" /* key */,
screenTitle,
MetricsProto.MetricsEvent.SLICE)
- .setClassName(mContext.getPackageName(), SubSettings.class.getName());
+ .setClassName(mContext.getPackageName(), SubSettings.class.getName())
+ .setData(CustomSliceRegistry.LOW_STORAGE_SLICE_URI);
}
private RowBuilder buildRowBuilder(CharSequence title, String summary, IconCompat icon) {
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
index 4df2a04..be03c28 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
@@ -41,6 +41,7 @@
import androidx.slice.widget.SliceView;
import com.android.settings.R;
+import com.android.settings.homepage.contextualcards.CardContentProvider;
import com.android.settings.homepage.contextualcards.ContextualCard;
import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
import com.android.settings.homepage.contextualcards.ContextualCardRenderer;
@@ -60,7 +61,7 @@
private static final String TAG = "SliceCardRenderer";
@VisibleForTesting
- final Map<String, LiveData<Slice>> mSliceLiveDataMap;
+ final Map<Uri, LiveData<Slice>> mSliceLiveDataMap;
@VisibleForTesting
final Set<SliceViewHolder> mFlippedCardSet;
@@ -94,9 +95,9 @@
public void bindView(RecyclerView.ViewHolder holder, ContextualCard card) {
final SliceViewHolder cardHolder = (SliceViewHolder) holder;
final Uri uri = card.getSliceUri();
+ //TODO(b/120629936): Take this out once blank card issue is fixed.
+ Log.d(TAG, "bindView - uri = " + uri);
- //TODO(b/116063073): The URI check should be done earlier when we are performing final
- // filtering after having the full list.
if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Log.w(TAG, "Invalid uri, skipping slice: " + uri);
return;
@@ -106,11 +107,11 @@
cardHolder.sliceView.setTag(uri);
//TODO(b/114009676): We will soon have a field to decide what slice mode we should set.
cardHolder.sliceView.setMode(SliceView.MODE_LARGE);
- LiveData<Slice> sliceLiveData = mSliceLiveDataMap.get(uri.toString());
+ LiveData<Slice> sliceLiveData = mSliceLiveDataMap.get(uri);
if (sliceLiveData == null) {
sliceLiveData = SliceLiveData.fromUri(mContext, uri);
- mSliceLiveDataMap.put(uri.toString(), sliceLiveData);
+ mSliceLiveDataMap.put(uri, sliceLiveData);
}
mCardSet.add(card);
@@ -118,6 +119,11 @@
sliceLiveData.observe(mLifecycleOwner, slice -> {
if (slice == null) {
Log.w(TAG, "Slice is null");
+ mContext.getContentResolver().notifyChange(CardContentProvider.URI, null);
+ return;
+ } else {
+ //TODO(b/120629936): Take this out once blank card issue is fixed.
+ Log.d(TAG, "Slice callback - uri = " + slice.getUri());
}
cardHolder.sliceView.setSlice(slice);
});
@@ -146,6 +152,7 @@
mControllerRendererPool.getController(mContext, card.getCardType()).onDismissed(card);
cardHolder.resetCard();
mFlippedCardSet.remove(cardHolder);
+ mSliceLiveDataMap.get(card.getSliceUri()).removeObservers(mLifecycleOwner);
});
}
diff --git a/src/com/android/settings/location/LocationScanningPreferenceController.java b/src/com/android/settings/location/LocationScanningPreferenceController.java
index 9d1bdc0..2c05a39 100644
--- a/src/com/android/settings/location/LocationScanningPreferenceController.java
+++ b/src/com/android/settings/location/LocationScanningPreferenceController.java
@@ -17,6 +17,7 @@
package com.android.settings.location;
import android.content.Context;
+import android.provider.Settings;
import androidx.annotation.VisibleForTesting;
@@ -25,11 +26,31 @@
public class LocationScanningPreferenceController extends BasePreferenceController {
-
@VisibleForTesting static final String KEY_LOCATION_SCANNING = "location_scanning";
+ private final Context mContext;
public LocationScanningPreferenceController(Context context) {
super(context, KEY_LOCATION_SCANNING);
+ mContext = context;
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ final boolean wifiScanOn = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 1;
+ final boolean bleScanOn = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0) == 1;
+ int resId;
+ if (wifiScanOn && bleScanOn) {
+ resId = R.string.scanning_status_text_wifi_on_ble_on;
+ } else if (wifiScanOn && !bleScanOn) {
+ resId = R.string.scanning_status_text_wifi_on_ble_off;
+ } else if (!wifiScanOn && bleScanOn) {
+ resId = R.string.scanning_status_text_wifi_off_ble_on;
+ } else {
+ resId = R.string.scanning_status_text_wifi_off_ble_off;
+ }
+ return mContext.getString(resId);
}
@AvailabilityStatus
diff --git a/src/com/android/settings/location/LocationSliceBuilder.java b/src/com/android/settings/location/LocationSlice.java
similarity index 66%
rename from src/com/android/settings/location/LocationSliceBuilder.java
rename to src/com/android/settings/location/LocationSlice.java
index f70d09b..6dc4241 100644
--- a/src/com/android/settings/location/LocationSliceBuilder.java
+++ b/src/com/android/settings/location/LocationSlice.java
@@ -38,29 +38,31 @@
import com.android.settings.SubSettings;
import com.android.settings.Utils;
import com.android.settings.slices.CustomSliceRegistry;
+import com.android.settings.slices.CustomSliceable;
import com.android.settings.slices.SliceBuilderUtils;
/**
* Utility class to build an intent-based Location Slice.
*/
-public class LocationSliceBuilder {
+public class LocationSlice implements CustomSliceable {
- private LocationSliceBuilder() {
+ private final Context mContext;
+
+ public LocationSlice(Context context) {
+ mContext = context;
}
- /**
- * Return a Location Slice bound to {@link CustomSliceRegistry#LOCATION_SLICE_URI}.
- */
- public static Slice getSlice(Context context) {
- final IconCompat icon = IconCompat.createWithResource(context,
+ @Override
+ public Slice getSlice() {
+ final IconCompat icon = IconCompat.createWithResource(mContext,
R.drawable.ic_signal_location);
- final String title = context.getString(R.string.location_settings_title);
- @ColorInt final int color = Utils.getColorAccentDefaultColor(context);
- final PendingIntent primaryAction = getPrimaryAction(context);
+ final CharSequence title = mContext.getText(R.string.location_settings_title);
+ @ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
+ final PendingIntent primaryAction = getPrimaryAction();
final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon,
ListBuilder.ICON_IMAGE, title);
- return new ListBuilder(context, CustomSliceRegistry.LOCATION_SLICE_URI,
+ return new ListBuilder(mContext, CustomSliceRegistry.LOCATION_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor(color)
.addRow(new RowBuilder()
@@ -70,19 +72,30 @@
.build();
}
- public static Intent getIntent(Context context) {
- final String screenTitle = context.getText(R.string.location_settings_title).toString();
+ @Override
+ public Uri getUri() {
+ return CustomSliceRegistry.LOCATION_SLICE_URI;
+ }
+
+ @Override
+ public void onNotifyChange(Intent intent) {
+
+ }
+
+ @Override
+ public Intent getIntent() {
+ final String screenTitle = mContext.getText(R.string.location_settings_title).toString();
final Uri contentUri = new Uri.Builder().appendPath(KEY_LOCATION).build();
- return SliceBuilderUtils.buildSearchResultPageIntent(context,
+ return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
LocationSettings.class.getName(), KEY_LOCATION, screenTitle,
MetricsEvent.LOCATION)
- .setClassName(context.getPackageName(), SubSettings.class.getName())
+ .setClassName(mContext.getPackageName(), SubSettings.class.getName())
.setData(contentUri);
}
- private static PendingIntent getPrimaryAction(Context context) {
- final Intent intent = getIntent(context);
- return PendingIntent.getActivity(context, 0 /* requestCode */,
+ private PendingIntent getPrimaryAction() {
+ final Intent intent = getIntent();
+ return PendingIntent.getActivity(mContext, 0 /* requestCode */,
intent, 0 /* flags */);
}
}
diff --git a/src/com/android/settings/network/ApnEditor.java b/src/com/android/settings/network/ApnEditor.java
index 633fc45..a16be66 100644
--- a/src/com/android/settings/network/ApnEditor.java
+++ b/src/com/android/settings/network/ApnEditor.java
@@ -167,7 +167,7 @@
Telephony.Carriers.ROAMING_PROTOCOL, // 20
Telephony.Carriers.MVNO_TYPE, // 21
Telephony.Carriers.MVNO_MATCH_DATA, // 22
- Telephony.Carriers.EDITED, // 23
+ Telephony.Carriers.EDITED_STATUS, // 23
Telephony.Carriers.USER_EDITABLE //24
};
@@ -1035,7 +1035,7 @@
callUpdate,
CARRIER_ENABLED_INDEX);
- values.put(Telephony.Carriers.EDITED, Telephony.Carriers.USER_EDITED);
+ values.put(Telephony.Carriers.EDITED_STATUS, Telephony.Carriers.USER_EDITED);
if (callUpdate) {
final Uri uri = mApnData.getUri() == null ? mCarrierUri : mApnData.getUri();
diff --git a/src/com/android/settings/network/ApnSettings.java b/src/com/android/settings/network/ApnSettings.java
index 4bd964e..261d889 100755
--- a/src/com/android/settings/network/ApnSettings.java
+++ b/src/com/android/settings/network/ApnSettings.java
@@ -82,7 +82,7 @@
Telephony.Carriers.TYPE,
Telephony.Carriers.MVNO_TYPE,
Telephony.Carriers.MVNO_MATCH_DATA,
- Telephony.Carriers.EDITED,
+ Telephony.Carriers.EDITED_STATUS,
};
private static final int ID_INDEX = 0;
diff --git a/src/com/android/settings/network/MultiNetworkHeaderController.java b/src/com/android/settings/network/MultiNetworkHeaderController.java
new file mode 100644
index 0000000..1c0fc74
--- /dev/null
+++ b/src/com/android/settings/network/MultiNetworkHeaderController.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network;
+
+import android.content.Context;
+
+import com.android.settings.core.BasePreferenceController;
+
+// This controls a header at the top of the Network & internet page that only appears when there
+// are two or more active mobile subscriptions. It shows an overview of available network
+// connections with an entry for wifi (if connected) and an entry for each subscription.
+public class MultiNetworkHeaderController extends BasePreferenceController {
+
+ public MultiNetworkHeaderController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return UNSUPPORTED_ON_DEVICE;
+ }
+}
diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java
new file mode 100644
index 0000000..cfe27db
--- /dev/null
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -0,0 +1,44 @@
+/*
+ * 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.network;
+
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class SubscriptionUtil {
+ public static List<SubscriptionInfo> getAvailableSubscriptions(SubscriptionManager manager) {
+ List<SubscriptionInfo> subscriptions = manager.getAvailableSubscriptionInfoList();
+ if (subscriptions == null) {
+ subscriptions = new ArrayList<>();
+ }
+ // With some carriers such as Google Fi which provide a sort of virtual service that spans
+ // across multiple underlying networks, we end up with subscription entries for the
+ // underlying networks that need to be hidden from the user in the UI.
+ for (Iterator<SubscriptionInfo> iter = subscriptions.iterator(); iter.hasNext(); ) {
+ SubscriptionInfo info = iter.next();
+ if (TextUtils.isEmpty(info.getMncString())) {
+ iter.remove();
+ }
+ }
+ return subscriptions;
+ }
+}
diff --git a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
index b1124f8..9ebeda0 100644
--- a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
+++ b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
@@ -22,7 +22,6 @@
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
-import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -131,16 +130,12 @@
@VisibleForTesting
boolean isDialogNeeded() {
final boolean enableData = !mTelephonyManager.isDataEnabled();
- final SubscriptionInfo currentSir = mSubscriptionManager.getActiveSubscriptionInfo(
- mSubId);
- final SubscriptionInfo nextSir = mSubscriptionManager.getDefaultDataSubscriptionInfo();
final boolean isMultiSim = (mTelephonyManager.getSimCount() > 1);
- final boolean isMultipleDataOnCapable =
- (mTelephonyManager.getNumberOfModemsWithSimultaneousDataConnections() > 1);
- final boolean isDefaultDataSubscription = (nextSir != null && currentSir != null
- && currentSir.getSubscriptionId() == nextSir.getSubscriptionId());
+ final int defaultSubId = mSubscriptionManager.getDefaultDataSubscriptionId();
+ final boolean needToDisableOthers = mSubscriptionManager
+ .isActiveSubscriptionId(defaultSubId) && defaultSubId != mSubId;
if (enableData) {
- if (isMultiSim && !isMultipleDataOnCapable && !isDefaultDataSubscription) {
+ if (isMultiSim && needToDisableOthers) {
mDialogType = MobileDataDialogFragment.TYPE_MULTI_SIM_DIALOG;
return true;
}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkUtils.java b/src/com/android/settings/network/telephony/MobileNetworkUtils.java
index dc184d3..27cc367 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkUtils.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkUtils.java
@@ -230,7 +230,8 @@
subscriptionManager.getActiveSubscriptionInfoList();
if (subInfoList != null) {
for (SubscriptionInfo subInfo : subInfoList) {
- if (subInfo.getSubscriptionId() != subId) {
+ // We never disable mobile data for opportunistic subscriptions.
+ if (subInfo.getSubscriptionId() != subId && !subInfo.isOpportunistic()) {
context.getSystemService(TelephonyManager.class).createForSubscriptionId(
subInfo.getSubscriptionId()).setDataEnabled(false);
}
diff --git a/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java b/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java
index 615b26c..7da90c8 100644
--- a/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java
@@ -73,8 +73,7 @@
// 2. rule was added or deleted, so reload the entire list
if (Objects.equals(pref.mId, sortedRules[i].getKey())) {
AutomaticZenRule rule = sortedRules[i].getValue();
- pref.setName(rule.getName());
- pref.setChecked(rule.isEnabled());
+ pref.updatePreference(rule);
} else {
reloadAllRules(sortedRules);
break;
diff --git a/src/com/android/settings/notification/ZenModeBackend.java b/src/com/android/settings/notification/ZenModeBackend.java
index 4824825..a75f51c 100644
--- a/src/com/android/settings/notification/ZenModeBackend.java
+++ b/src/com/android/settings/notification/ZenModeBackend.java
@@ -250,15 +250,17 @@
}
}
+ protected int getAlarmsTotalSilenceCallsMessagesSummary(int category) {
+ if (category == NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES) {
+ return R.string.zen_mode_from_none_messages;
+ } else if (category == NotificationManager.Policy.PRIORITY_CATEGORY_CALLS){
+ return R.string.zen_mode_from_none_calls;
+ }
+ return 0;
+ }
+
protected int getContactsSummary(int category) {
int contactType = -1;
-
- // SOURCE_NONE can be used when in total silence or alarms only
- // (policy is based on user's preferences but the UI displayed is based on zenMode)
- if (category == SOURCE_NONE) {
- return R.string.zen_mode_from_none;
- }
-
if (category == NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES) {
if (isPriorityCategoryEnabled(category)) {
contactType = getPriorityMessageSenders();
@@ -273,12 +275,16 @@
case NotificationManager.Policy.PRIORITY_SENDERS_ANY:
return R.string.zen_mode_from_anyone;
case NotificationManager.Policy.PRIORITY_SENDERS_CONTACTS:
- return R.string.zen_mode_from_contacts;
+ return R.string.zen_mode_from_contacts;
case NotificationManager.Policy.PRIORITY_SENDERS_STARRED:
- return R.string.zen_mode_from_starred;
+ return R.string.zen_mode_from_starred;
case SOURCE_NONE:
default:
- return R.string.zen_mode_from_none;
+ if (category == NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES) {
+ return R.string.zen_mode_from_none_messages;
+ } else {
+ return R.string.zen_mode_from_none_calls;
+ }
}
}
diff --git a/src/com/android/settings/notification/ZenModeMessagesPreferenceController.java b/src/com/android/settings/notification/ZenModeMessagesPreferenceController.java
index 19ee809..2e41f20 100644
--- a/src/com/android/settings/notification/ZenModeMessagesPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeMessagesPreferenceController.java
@@ -18,11 +18,11 @@
import android.content.Context;
+import androidx.preference.Preference;
+
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.lifecycle.Lifecycle;
-import androidx.preference.Preference;
-
public class ZenModeMessagesPreferenceController extends
AbstractZenModePreferenceController implements PreferenceControllerMixin {
@@ -48,6 +48,7 @@
@Override
public void updateState(Preference preference) {
super.updateState(preference);
- // TODO: (b/111475013 - beverlyt) set messages summary
+
+ preference.setSummary(mSummaryBuilder.getMessagesSettingSummary(getPolicy()));
}
}
diff --git a/src/com/android/settings/notification/ZenModePriorityCallsPreferenceController.java b/src/com/android/settings/notification/ZenModePriorityCallsPreferenceController.java
index 44b6c24..9872188 100644
--- a/src/com/android/settings/notification/ZenModePriorityCallsPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModePriorityCallsPreferenceController.java
@@ -21,14 +21,14 @@
import android.provider.Settings;
import android.text.TextUtils;
-import com.android.settings.R;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
import androidx.annotation.VisibleForTesting;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
+import com.android.settings.R;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
public class ZenModePriorityCallsPreferenceController extends AbstractZenModePreferenceController
implements Preference.OnPreferenceChangeListener {
@@ -80,7 +80,8 @@
case Settings.Global.ZEN_MODE_ALARMS:
mPreference.setEnabled(false);
mPreference.setValue(ZenModeBackend.ZEN_MODE_FROM_NONE);
- mPreference.setSummary(mBackend.getContactsSummary(ZenModeBackend.SOURCE_NONE));
+ mPreference.setSummary(mBackend.getAlarmsTotalSilenceCallsMessagesSummary(
+ NotificationManager.Policy.PRIORITY_CATEGORY_CALLS));
break;
default:
preference.setEnabled(true);
diff --git a/src/com/android/settings/notification/ZenModePriorityMessagesPreferenceController.java b/src/com/android/settings/notification/ZenModePriorityMessagesPreferenceController.java
index 56829a7..cfda367 100644
--- a/src/com/android/settings/notification/ZenModePriorityMessagesPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModePriorityMessagesPreferenceController.java
@@ -21,14 +21,14 @@
import android.provider.Settings;
import android.text.TextUtils;
-import com.android.settings.R;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
import androidx.annotation.VisibleForTesting;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
+import com.android.settings.R;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
public class ZenModePriorityMessagesPreferenceController extends AbstractZenModePreferenceController
implements Preference.OnPreferenceChangeListener {
@@ -80,7 +80,8 @@
case Settings.Global.ZEN_MODE_ALARMS:
mPreference.setEnabled(false);
mPreference.setValue(ZenModeBackend.ZEN_MODE_FROM_NONE);
- mPreference.setSummary(mBackend.getContactsSummary(ZenModeBackend.SOURCE_NONE));
+ mPreference.setSummary(mBackend.getAlarmsTotalSilenceCallsMessagesSummary(
+ NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES));
break;
default:
preference.setEnabled(true);
diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java
index 293c429..a3f59c6 100644
--- a/src/com/android/settings/notification/ZenModeSettings.java
+++ b/src/com/android/settings/notification/ZenModeSettings.java
@@ -145,7 +145,7 @@
|| PRIORITY_CATEGORY_REPEAT_CALLERS == category, false);
int numCategories = enabledCategories.size();
if (numCategories == 0) {
- return mContext.getString(R.string.zen_mode_no_exceptions);
+ return mContext.getString(R.string.zen_mode_from_none_calls);
} else if (numCategories == 1) {
return mContext.getString(R.string.zen_mode_calls_summary_one,
enabledCategories.get(0));
@@ -156,34 +156,14 @@
}
}
- String getMsgEventReminderSettingSummary(Policy policy) {
+ String getMessagesSettingSummary(Policy policy) {
List<String> enabledCategories = getEnabledCategories(policy,
- category -> PRIORITY_CATEGORY_EVENTS == category
- || PRIORITY_CATEGORY_REMINDERS == category
- || PRIORITY_CATEGORY_MESSAGES == category, true);
+ category -> PRIORITY_CATEGORY_MESSAGES == category, false);
int numCategories = enabledCategories.size();
if (numCategories == 0) {
- return mContext.getString(R.string.zen_mode_no_exceptions);
- } else if (numCategories == 1) {
- return enabledCategories.get(0);
- } else if (numCategories == 2) {
- return mContext.getString(R.string.join_two_items, enabledCategories.get(0),
- enabledCategories.get(1));
- } else if (numCategories == 3){
- final List<String> summaries = new ArrayList<>();
- summaries.add(enabledCategories.get(0));
- summaries.add(enabledCategories.get(1));
- summaries.add(enabledCategories.get(2));
-
- return ListFormatter.getInstance().format(summaries);
+ return mContext.getString(R.string.zen_mode_from_none_messages);
} else {
- final List<String> summaries = new ArrayList<>();
- summaries.add(enabledCategories.get(0));
- summaries.add(enabledCategories.get(1));
- summaries.add(enabledCategories.get(2));
- summaries.add(mContext.getString(R.string.zen_mode_other_options));
-
- return ListFormatter.getInstance().format(summaries);
+ return enabledCategories.get(0);
}
}
@@ -292,17 +272,11 @@
}
} else if (category == Policy.PRIORITY_CATEGORY_MESSAGES) {
if (policy.priorityMessageSenders == Policy.PRIORITY_SENDERS_ANY) {
- if (isFirst) {
- return mContext.getString(R.string.zen_mode_all_messages);
- } else {
- return mContext.getString(R.string.zen_mode_all_messages_list);
- }
+ return mContext.getString(R.string.zen_mode_from_anyone);
+ } else if (policy.priorityMessageSenders == Policy.PRIORITY_SENDERS_CONTACTS){
+ return mContext.getString(R.string.zen_mode_from_contacts);
} else {
- if (isFirst) {
- return mContext.getString(R.string.zen_mode_selected_messages);
- } else {
- return mContext.getString(R.string.zen_mode_selected_messages_list);
- }
+ return mContext.getString(R.string.zen_mode_from_starred);
}
} else if (category == Policy.PRIORITY_CATEGORY_EVENTS) {
if (isFirst) {
diff --git a/src/com/android/settings/notification/ZenRulePreference.java b/src/com/android/settings/notification/ZenRulePreference.java
index 48a879b..10b49eb 100644
--- a/src/com/android/settings/notification/ZenRulePreference.java
+++ b/src/com/android/settings/notification/ZenRulePreference.java
@@ -31,6 +31,7 @@
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.utils.ManagedServiceSettings;
import com.android.settings.utils.ZenServiceListing;
@@ -122,17 +123,17 @@
return mChecked;
}
- public void setChecked(boolean checked) {
- mChecked = checked;
- if (mCheckBox != null) {
- mCheckBox.setChecked(checked);
- }
- }
-
- public void setName(String name) {
- if (!Objects.equals(mName, name)) {
- mName = name;
+ public void updatePreference(AutomaticZenRule rule) {
+ if (!mRule.getName().equals(rule.getName())) {
+ mName = rule.getName();
setTitle(mName);
+ mRule.setName(mName.toString());
+ }
+
+ if (mRule.isEnabled() != rule.isEnabled()) {
+ mRule.setEnabled(rule.isEnabled());
+ setChecked(mRule.isEnabled());
+ setSummary(computeRuleSummary(mRule));
}
}
@@ -141,6 +142,13 @@
mOnCheckBoxClickListener.onClick(null);
}
+ private void setChecked(boolean checked) {
+ mChecked = checked;
+ if (mCheckBox != null) {
+ mCheckBox.setChecked(checked);
+ }
+ }
+
private View.OnClickListener mOnCheckBoxClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -159,7 +167,7 @@
try {
ApplicationInfo info = mPm.getApplicationInfo(rule.getOwner().getPackageName(), 0);
- setSummary(computeRuleSummary(rule, mIsSystemRule, info.loadLabel(mPm)));
+ setSummary(computeRuleSummary(rule));
} catch (PackageManager.NameNotFoundException e) {
appExists = false;
return;
@@ -179,8 +187,7 @@
setKey(mId);
}
- private String computeRuleSummary(AutomaticZenRule rule, boolean isSystemRule,
- CharSequence providerLabel) {
+ private String computeRuleSummary(AutomaticZenRule rule) {
return (rule == null || !rule.isEnabled())
? mContext.getResources().getString(R.string.switch_off_text)
: mContext.getResources().getString(R.string.switch_on_text);
diff --git a/src/com/android/settings/slices/CustomSliceManager.java b/src/com/android/settings/slices/CustomSliceManager.java
index bef72b7..4a9de15 100644
--- a/src/com/android/settings/slices/CustomSliceManager.java
+++ b/src/com/android/settings/slices/CustomSliceManager.java
@@ -22,13 +22,16 @@
import androidx.annotation.VisibleForTesting;
+import com.android.settings.flashlight.FlashlightSlice;
import com.android.settings.homepage.contextualcards.deviceinfo.BatterySlice;
import com.android.settings.homepage.contextualcards.deviceinfo.DataUsageSlice;
import com.android.settings.homepage.contextualcards.deviceinfo.DeviceInfoSlice;
+import com.android.settings.homepage.contextualcards.deviceinfo.EmergencyInfoSlice;
import com.android.settings.homepage.contextualcards.deviceinfo.StorageSlice;
import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;
-import com.android.settings.homepage.contextualcards.slices.ConnectedDeviceSlice;
+import com.android.settings.homepage.contextualcards.slices.BluetoothDevicesSlice;
import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
+import com.android.settings.location.LocationSlice;
import com.android.settings.wifi.WifiSlice;
import java.util.Map;
@@ -103,9 +106,12 @@
private void addSlices() {
mUriMap.put(CustomSliceRegistry.BATTERY_FIX_SLICE_URI, BatteryFixSlice.class);
mUriMap.put(CustomSliceRegistry.BATTERY_INFO_SLICE_URI, BatterySlice.class);
- mUriMap.put(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI, ConnectedDeviceSlice.class);
+ mUriMap.put(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI, BluetoothDevicesSlice.class);
mUriMap.put(CustomSliceRegistry.DATA_USAGE_SLICE_URI, DataUsageSlice.class);
mUriMap.put(CustomSliceRegistry.DEVICE_INFO_SLICE_URI, DeviceInfoSlice.class);
+ mUriMap.put(CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI, EmergencyInfoSlice.class);
+ mUriMap.put(CustomSliceRegistry.FLASHLIGHT_SLICE_URI, FlashlightSlice.class);
+ mUriMap.put(CustomSliceRegistry.LOCATION_SLICE_URI, LocationSlice.class);
mUriMap.put(CustomSliceRegistry.LOW_STORAGE_SLICE_URI, LowStorageSlice.class);
mUriMap.put(CustomSliceRegistry.STORAGE_SLICE_URI, StorageSlice.class);
mUriMap.put(CustomSliceRegistry.WIFI_SLICE_URI, WifiSlice.class);
diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java
index 80de3b2..1b8cffe 100644
--- a/src/com/android/settings/slices/CustomSliceRegistry.java
+++ b/src/com/android/settings/slices/CustomSliceRegistry.java
@@ -72,13 +72,13 @@
.build();
/**
- * Backing Uri for Connected device Slice.
+ * Backing Uri for Bluetooth devices Slice.
*/
- public static final Uri CONNECTED_DEVICE_SLICE_URI = new Uri.Builder()
+ public static final Uri BLUETOOTH_DEVICES_SLICE_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
- .appendPath("connected_device")
+ .appendPath("bluetooth_devices")
.build();
/**
* Backing Uri for the Data usage Slice.
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index 109f02e..80b7133 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -41,9 +41,6 @@
import com.android.settings.R;
import com.android.settings.bluetooth.BluetoothSliceBuilder;
import com.android.settings.core.BasePreferenceController;
-import com.android.settings.flashlight.FlashlightSliceBuilder;
-import com.android.settings.homepage.contextualcards.deviceinfo.EmergencyInfoSlice;
-import com.android.settings.location.LocationSliceBuilder;
import com.android.settings.notification.ZenModeSliceBuilder;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.SliceBroadcastRelay;
@@ -182,12 +179,6 @@
} else if (CustomSliceRegistry.BLUETOOTH_URI.equals(sliceUri)) {
registerIntentToUri(BluetoothSliceBuilder.INTENT_FILTER, sliceUri);
return;
- } else if (CustomSliceRegistry.FLASHLIGHT_SLICE_URI.equals(sliceUri)) {
- registerIntentToUri(FlashlightSliceBuilder.INTENT_FILTER, sliceUri);
- mRegisteredUris.add(sliceUri);
- return;
- } else if (CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI.equals(sliceUri)) {
- return;
}
// Start warming the slice, we expect someone will want it soon.
@@ -240,8 +231,6 @@
return ZenModeSliceBuilder.getSlice(getContext());
} else if (CustomSliceRegistry.BLUETOOTH_URI.equals(sliceUri)) {
return BluetoothSliceBuilder.getSlice(getContext());
- } else if (CustomSliceRegistry.LOCATION_SLICE_URI.equals(sliceUri)) {
- return LocationSliceBuilder.getSlice(getContext());
} else if (CustomSliceRegistry.ENHANCED_4G_SLICE_URI.equals(sliceUri)) {
return FeatureFactory.getFactory(getContext())
.getSlicesFeatureProvider()
@@ -252,10 +241,6 @@
.getSlicesFeatureProvider()
.getNewWifiCallingSliceHelper(getContext())
.createWifiCallingPreferenceSlice(sliceUri);
- } else if (CustomSliceRegistry.FLASHLIGHT_SLICE_URI.equals(sliceUri)) {
- return FlashlightSliceBuilder.getSlice(getContext());
- } else if (CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI.equals(sliceUri)) {
- return EmergencyInfoSlice.getSlice(getContext());
}
SliceData cachedSliceData = mSliceWeakDataCache.get(sliceUri);
diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java
index 2860e9a..823c729 100644
--- a/src/com/android/settings/slices/SliceBroadcastReceiver.java
+++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java
@@ -17,7 +17,6 @@
package com.android.settings.slices;
import static com.android.settings.bluetooth.BluetoothSliceBuilder.ACTION_BLUETOOTH_SLICE_CHANGED;
-import static com.android.settings.flashlight.FlashlightSliceBuilder.ACTION_FLASHLIGHT_SLICE_CHANGED;
import static com.android.settings.network.telephony.Enhanced4gLteSliceHelper.ACTION_ENHANCED_4G_LTE_CHANGED;
import static com.android.settings.notification.ZenModeSliceBuilder.ACTION_ZEN_MODE_SLICE_CHANGED;
import static com.android.settings.slices.SettingsSliceProvider.ACTION_COPY;
@@ -46,7 +45,6 @@
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.SliderPreferenceController;
import com.android.settings.core.TogglePreferenceController;
-import com.android.settings.flashlight.FlashlightSliceBuilder;
import com.android.settings.notification.ZenModeSliceBuilder;
import com.android.settings.overlay.FeatureFactory;
@@ -108,9 +106,6 @@
.getNewWifiCallingSliceHelper(context)
.handleWifiCallingPreferenceChanged(intent);
break;
- case ACTION_FLASHLIGHT_SLICE_CHANGED:
- FlashlightSliceBuilder.handleUriChange(context, intent);
- break;
case ACTION_COPY:
handleCopyAction(context, key, isPlatformSlice);
break;
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index c16a8ba..d75eaa2 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -449,6 +449,12 @@
if (iconResource == 0) {
iconResource = R.drawable.ic_settings;
}
- return IconCompat.createWithResource(context, iconResource);
+ try {
+ return IconCompat.createWithResource(context, iconResource);
+ } catch (Exception e) {
+ Log.w(TAG, "Falling back to settings icon because there is an error getting slice icon "
+ + data.getUri(), e);
+ return IconCompat.createWithResource(context, R.drawable.ic_settings);
+ }
}
}
diff --git a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
index 01708af..d633b7a 100644
--- a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
+++ b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
@@ -24,7 +24,6 @@
import androidx.annotation.Keep;
import com.android.settings.bluetooth.BluetoothSliceBuilder;
-import com.android.settings.location.LocationSliceBuilder;
import com.android.settings.notification.ZenModeSliceBuilder;
import com.android.settings.overlay.FeatureFactory;
@@ -66,8 +65,6 @@
launchIntent = ZenModeSliceBuilder.getIntent(this /* context */);
} else if (CustomSliceRegistry.BLUETOOTH_URI.equals(sliceUri)) {
launchIntent = BluetoothSliceBuilder.getIntent(this /* context */);
- } else if (CustomSliceRegistry.LOCATION_SLICE_URI.equals(sliceUri)) {
- launchIntent = LocationSliceBuilder.getIntent(this /* context */);
} else {
final SlicesDatabaseAccessor slicesDatabaseAccessor =
new SlicesDatabaseAccessor(this /* context */);
diff --git a/src/com/android/settings/widget/FloatingAppBarScrollingViewBehavior.java b/src/com/android/settings/widget/FloatingAppBarScrollingViewBehavior.java
new file mode 100644
index 0000000..23f6ccd
--- /dev/null
+++ b/src/com/android/settings/widget/FloatingAppBarScrollingViewBehavior.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.widget;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.util.AttributeSet;
+import android.view.View;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
+
+import com.google.android.material.appbar.AppBarLayout;
+
+/**
+ * This scrolling view behavior will set the background of the {@link AppBarLayout} as
+ * transparent and without the elevation. Also make header overlapped the scrolling child view.
+ */
+public class FloatingAppBarScrollingViewBehavior extends AppBarLayout.ScrollingViewBehavior {
+ private boolean initialized;
+
+ public FloatingAppBarScrollingViewBehavior(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
+ boolean changed = super.onDependentViewChanged(parent, child, dependency);
+ if (!initialized && dependency instanceof AppBarLayout) {
+ initialized = true;
+ AppBarLayout appBarLayout = (AppBarLayout) dependency;
+ setAppBarLayoutTransparent(appBarLayout);
+ }
+ return changed;
+ }
+
+ @VisibleForTesting
+ void setAppBarLayoutTransparent(AppBarLayout appBarLayout) {
+ appBarLayout.setBackgroundColor(Color.TRANSPARENT);
+ appBarLayout.setTargetElevation(0);
+ }
+
+ @Override
+ protected boolean shouldHeaderOverlapScrollingChild() {
+ return true;
+ }
+}
diff --git a/src/com/android/settings/widget/RadioButtonPickerFragment.java b/src/com/android/settings/widget/RadioButtonPickerFragment.java
index 89df487..50c1b58 100644
--- a/src/com/android/settings/widget/RadioButtonPickerFragment.java
+++ b/src/com/android/settings/widget/RadioButtonPickerFragment.java
@@ -22,10 +22,12 @@
import android.os.UserManager;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.Toast;
import androidx.annotation.LayoutRes;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
@@ -34,16 +36,23 @@
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.InstrumentedPreferenceFragment;
+import com.android.settings.core.PreferenceXmlParserUtils;
+import com.android.settings.core.PreferenceXmlParserUtils.MetadataFlag;
import com.android.settingslib.widget.CandidateInfo;
+import java.io.IOException;
import java.util.List;
import java.util.Map;
+import org.xmlpull.v1.XmlPullParserException;
public abstract class RadioButtonPickerFragment extends InstrumentedPreferenceFragment implements
RadioButtonPreference.OnClickListener {
- @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ @VisibleForTesting
static final String EXTRA_FOR_WORK = "for_work";
+ private static final String TAG = "RadioButtonPckrFrgmt";
+ @VisibleForTesting
+ boolean mAppendStaticPreferences = false;
private final Map<String, CandidateInfo> mCandidates = new ArrayMap<>();
@@ -69,6 +78,19 @@
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
super.onCreatePreferences(savedInstanceState, rootKey);
+ try {
+ // Check if the xml specifies if static preferences should go on the top or bottom
+ final List<Bundle> metadata = PreferenceXmlParserUtils.extractMetadata(getContext(),
+ getPreferenceScreenResId(),
+ MetadataFlag.FLAG_INCLUDE_PREF_SCREEN |
+ MetadataFlag.FLAG_NEED_PREF_APPEND);
+ mAppendStaticPreferences = metadata.get(0)
+ .getBoolean(PreferenceXmlParserUtils.METADATA_APPEND);
+ } catch (IOException e) {
+ Log.e(TAG, "Error trying to open xml file", e);
+ } catch (XmlPullParserException e) {
+ Log.e(TAG, "Error parsing xml", e);
+ }
updateCandidates();
}
@@ -142,7 +164,9 @@
final String systemDefaultKey = getSystemDefaultKey();
final PreferenceScreen screen = getPreferenceScreen();
screen.removeAll();
- addStaticPreferences(screen);
+ if (!mAppendStaticPreferences) {
+ addStaticPreferences(screen);
+ }
final int customLayoutResId = getRadioButtonPreferenceCustomLayoutResId();
if (shouldShowItemNone()) {
@@ -168,6 +192,9 @@
}
}
mayCheckOnlyRadioButton();
+ if (mAppendStaticPreferences) {
+ addStaticPreferences(screen);
+ }
}
@VisibleForTesting
diff --git a/src/com/android/settings/wifi/CellularFallbackPreferenceController.java b/src/com/android/settings/wifi/CellularFallbackPreferenceController.java
index a883826..cbb8fb8 100644
--- a/src/com/android/settings/wifi/CellularFallbackPreferenceController.java
+++ b/src/com/android/settings/wifi/CellularFallbackPreferenceController.java
@@ -18,62 +18,34 @@
import android.content.Context;
import android.provider.Settings;
-import android.text.TextUtils;
-import androidx.preference.Preference;
-import androidx.preference.SwitchPreference;
-
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settings.core.TogglePreferenceController;
/**
- * {@link AbstractPreferenceController} that controls whether we should fall back to celluar when
+ * CellularFallbackPreferenceController controls whether we should fall back to celluar when
* wifi is bad.
*/
-public class CellularFallbackPreferenceController extends AbstractPreferenceController
- implements PreferenceControllerMixin {
+public class CellularFallbackPreferenceController extends TogglePreferenceController {
- private static final String KEY_CELLULAR_FALLBACK = "wifi_cellular_data_fallback";
-
-
- public CellularFallbackPreferenceController(Context context) {
- super(context);
+ public CellularFallbackPreferenceController(Context context, String key) {
+ super(context, key);
}
@Override
- public boolean isAvailable() {
- return !avoidBadWifiConfig();
+ public int getAvailabilityStatus() {
+ return !avoidBadWifiConfig() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
- public String getPreferenceKey() {
- return KEY_CELLULAR_FALLBACK;
+ public boolean isChecked() {
+ return avoidBadWifiCurrentSettings();
}
@Override
- public boolean handlePreferenceTreeClick(Preference preference) {
- if (!TextUtils.equals(preference.getKey(), KEY_CELLULAR_FALLBACK)) {
- return false;
- }
- if (!(preference instanceof SwitchPreference)) {
- return false;
- }
+ public boolean setChecked(boolean isChecked) {
// On: avoid bad wifi. Off: prompt.
- String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
- Settings.Global.putString(mContext.getContentResolver(), settingName,
- ((SwitchPreference) preference).isChecked() ? "1" : null);
- return true;
- }
-
- @Override
- public void updateState(Preference preference) {
- final boolean currentSetting = avoidBadWifiCurrentSettings();
- // TODO: can this ever be null? The return value of avoidBadWifiConfig() can only
- // change if the resources change, but if that happens the activity will be recreated...
- if (preference != null) {
- SwitchPreference pref = (SwitchPreference) preference;
- pref.setChecked(currentSetting);
- }
+ return Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.NETWORK_AVOID_BAD_WIFI, isChecked ? "1" : null);
}
private boolean avoidBadWifiConfig() {
@@ -85,4 +57,4 @@
return "1".equals(Settings.Global.getString(mContext.getContentResolver(),
Settings.Global.NETWORK_AVOID_BAD_WIFI));
}
-}
+}
\ No newline at end of file
diff --git a/src/com/android/settings/wifi/ConfigureWifiSettings.java b/src/com/android/settings/wifi/ConfigureWifiSettings.java
index 1d1c30c..8df4a41 100644
--- a/src/com/android/settings/wifi/ConfigureWifiSettings.java
+++ b/src/com/android/settings/wifi/ConfigureWifiSettings.java
@@ -85,7 +85,6 @@
controllers.add(mUseOpenWifiPreferenceController);
controllers.add(new WifiInfoPreferenceController(context, getSettingsLifecycle(),
wifiManager));
- controllers.add(new CellularFallbackPreferenceController(context));
controllers.add(new WifiP2pPreferenceController(context, getSettingsLifecycle(),
wifiManager));
return controllers;
diff --git a/src/com/android/settings/wifi/WifiSlice.java b/src/com/android/settings/wifi/WifiSlice.java
index 2382abb..64e3fc3 100644
--- a/src/com/android/settings/wifi/WifiSlice.java
+++ b/src/com/android/settings/wifi/WifiSlice.java
@@ -37,7 +37,6 @@
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.builders.ListBuilder;
-import androidx.slice.builders.ListBuilder.RowBuilder;
import androidx.slice.builders.SliceAction;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -64,9 +63,11 @@
static final int DEFAULT_EXPANDED_ROW_COUNT = 3;
private final Context mContext;
+ private final WifiManager mWifiManager;
public WifiSlice(Context context) {
mContext = context;
+ mWifiManager = mContext.getSystemService(WifiManager.class);
}
@Override
@@ -100,7 +101,7 @@
final ListBuilder listBuilder = new ListBuilder(mContext, WIFI_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor(color)
- .addRow(new RowBuilder()
+ .addRow(new ListBuilder.RowBuilder()
.setTitle(title)
.setSubtitle(summary)
.addEndItem(toggleSliceAction)
@@ -110,18 +111,25 @@
return listBuilder.build();
}
- List<AccessPoint> results = SliceBackgroundWorker.getInstance(mContext, this).getResults();
- if (results == null) {
- results = new ArrayList<>();
- }
- final int apCount = results.size();
+ final List<AccessPoint> results =
+ SliceBackgroundWorker.getInstance(mContext, this).getResults();
+
+ // Need a loading text when results are not ready.
+ boolean needLoadingRow = results == null;
+ final int apCount = needLoadingRow ? 0 : results.size();
+
// Add AP rows
final CharSequence placeholder = mContext.getText(R.string.summary_placeholder);
for (int i = 0; i < DEFAULT_EXPANDED_ROW_COUNT; i++) {
if (i < apCount) {
listBuilder.addRow(getAccessPointRow(results.get(i)));
+ } else if (needLoadingRow) {
+ listBuilder.addRow(new ListBuilder.RowBuilder()
+ .setTitle(mContext.getText(R.string.wifi_empty_list_wifi_on))
+ .setSubtitle(placeholder));
+ needLoadingRow = false;
} else {
- listBuilder.addRow(new RowBuilder()
+ listBuilder.addRow(new ListBuilder.RowBuilder()
.setTitle(placeholder)
.setSubtitle(placeholder));
}
@@ -129,12 +137,12 @@
return listBuilder.build();
}
- private RowBuilder getAccessPointRow(AccessPoint accessPoint) {
+ private ListBuilder.RowBuilder getAccessPointRow(AccessPoint accessPoint) {
final String title = accessPoint.getConfigName();
final IconCompat levelIcon = IconCompat.createWithResource(mContext,
com.android.settingslib.Utils.getWifiIconResource(accessPoint.getLevel()));
final CharSequence apSummary = accessPoint.getSettingsSummary();
- final RowBuilder rowBuilder = new RowBuilder()
+ final ListBuilder.RowBuilder rowBuilder = new ListBuilder.RowBuilder()
.setTitleItem(levelIcon, ListBuilder.ICON_IMAGE)
.setTitle(title)
.setSubtitle(!TextUtils.isEmpty(apSummary)
@@ -188,10 +196,9 @@
*/
@Override
public void onNotifyChange(Intent intent) {
- final WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
final boolean newState = intent.getBooleanExtra(EXTRA_TOGGLE_STATE,
- wifiManager.isWifiEnabled());
- wifiManager.setWifiEnabled(newState);
+ mWifiManager.isWifiEnabled());
+ mWifiManager.setWifiEnabled(newState);
// Do not notifyChange on Uri. The service takes longer to update the current value than it
// does for the Slice to check the current value again. Let {@link SliceBroadcastRelay}
// handle it.
@@ -211,26 +218,19 @@
}
private boolean isWifiEnabled() {
- final WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
-
- switch (wifiManager.getWifiState()) {
+ switch (mWifiManager.getWifiState()) {
case WifiManager.WIFI_STATE_ENABLED:
case WifiManager.WIFI_STATE_ENABLING:
return true;
- case WifiManager.WIFI_STATE_DISABLED:
- case WifiManager.WIFI_STATE_DISABLING:
- case WifiManager.WIFI_STATE_UNKNOWN:
default:
return false;
}
}
private CharSequence getSummary() {
- final WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
-
- switch (wifiManager.getWifiState()) {
+ switch (mWifiManager.getWifiState()) {
case WifiManager.WIFI_STATE_ENABLED:
- final String ssid = WifiInfo.removeDoubleQuotes(wifiManager.getConnectionInfo()
+ final String ssid = WifiInfo.removeDoubleQuotes(mWifiManager.getConnectionInfo()
.getSSID());
if (TextUtils.equals(ssid, WifiSsid.NONE)) {
return mContext.getText(R.string.disconnected);
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index a676bfa..e1179f8 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -20,6 +20,7 @@
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import android.app.Activity;
+import android.app.KeyguardManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -40,6 +41,7 @@
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.text.TextUtils;
+import android.util.FeatureFlagUtils;
import android.util.Log;
import android.widget.ImageView;
import android.widget.Toast;
@@ -54,8 +56,11 @@
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.Utils;
+import com.android.settings.core.FeatureFlags;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.widget.EntityHeaderController;
+import com.android.settings.wifi.dpp.WifiDppConfiguratorActivity;
+import com.android.settings.wifi.dpp.WifiDppUtils;
import com.android.settings.wifi.WifiDialog;
import com.android.settings.wifi.WifiDialog.WifiDialogListener;
import com.android.settings.wifi.WifiUtils;
@@ -280,7 +285,10 @@
.setButton1Icon(R.drawable.ic_settings_delete)
.setButton1OnClickListener(view -> forgetNetwork())
.setButton2Text(R.string.wifi_sign_in_button_text)
- .setButton2OnClickListener(view -> signIntoNetwork());
+ .setButton2OnClickListener(view -> signIntoNetwork())
+ .setButton3Text(R.string.share)
+ .setButton3Icon(R.drawable.ic_qrcode_24dp)
+ .setButton3OnClickListener(view -> shareNetwork());
mSignalStrengthPref = screen.findPreference(KEY_SIGNAL_STRENGTH_PREF);
mLinkSpeedPref = screen.findPreference(KEY_LINK_SPEED);
@@ -296,7 +304,7 @@
mIpv6Category = (PreferenceCategory) screen.findPreference(KEY_IPV6_CATEGORY);
mIpv6AddressPref = screen.findPreference(KEY_IPV6_ADDRESSES_PREF);
- mSecurityPref.setSummary(mAccessPoint.getSecurityString(false /* concise */));
+ mSecurityPref.setSummary(mAccessPoint.getSecurityString(/* concise */ false));
}
private void setupEntityHeader(PreferenceScreen screen) {
@@ -425,7 +433,9 @@
private void updateIpLayerInfo() {
mButtonsPref.setButton2Visible(canSignIntoNetwork());
- mButtonsPref.setVisible(canSignIntoNetwork() || canForgetNetwork());
+ mButtonsPref.setButton3Visible(isSharingNetworkEnabled());
+ mButtonsPref.setVisible(
+ canSignIntoNetwork() || canForgetNetwork() || isSharingNetworkEnabled());
if (mNetwork == null || mLinkProperties == null) {
mIpAddressPref.setVisible(false);
@@ -511,6 +521,13 @@
}
/**
+ * Returns whether the user can share the network represented by this preference with QR code.
+ */
+ private boolean isSharingNetworkEnabled() {
+ return FeatureFlagUtils.isEnabled(mContext, FeatureFlags.WIFI_SHARING);
+ }
+
+ /**
* Forgets the wifi network associated with this preference.
*/
private void forgetNetwork() {
@@ -529,6 +546,42 @@
}
/**
+ * Show QR code to share the network represented by this preference.
+ */
+ public void launchQRCodeGenerator() {
+ final Intent intent = new Intent(
+ WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
+ intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY,
+ mAccessPoint.getSecurityString(/* concise */ false));
+ intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, mAccessPoint.getSsidStr());
+ mContext.startActivity(intent);
+ }
+
+ /**
+ * Share the wifi network with QR code.
+ */
+ private void shareNetwork() {
+ final KeyguardManager keyguardManager = (KeyguardManager) mContext.getSystemService(
+ Context.KEYGUARD_SERVICE);
+ if (keyguardManager.isKeyguardSecure()) {
+ // Show authentication screen to confirm credentials (pin, pattern or password) for
+ // the current user of the device.
+ final String description = String.format(
+ mContext.getString(R.string.wifi_sharing_message),
+ mAccessPoint.getSsidStr());
+ final Intent intent = keyguardManager.createConfirmDeviceCredentialIntent(
+ mContext.getString(R.string.lockpassword_confirm_your_pattern_header),
+ description);
+ if (intent != null) {
+ mFragment.startActivityForResult(intent,
+ WifiNetworkDetailsFragment.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS);
+ }
+ } else {
+ launchQRCodeGenerator();
+ }
+ }
+
+ /**
* Sign in to the captive portal found on this wifi network associated with this preference.
*/
private void signIntoNetwork() {
diff --git a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
index 7f0e8ee..9814486 100644
--- a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
+++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
@@ -17,8 +17,10 @@
import static com.android.settings.wifi.WifiSettings.WIFI_DIALOG_ID;
+import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
+import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.os.Bundle;
@@ -52,6 +54,8 @@
private static final String TAG = "WifiNetworkDetailsFrg";
+ public static final int REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS = 1;
+
private AccessPoint mAccessPoint;
private WifiDetailPreferenceController mWifiDetailPreferenceController;
@@ -142,4 +146,14 @@
return controllers;
}
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS
+ && resultCode == Activity.RESULT_OK) {
+ mWifiDetailPreferenceController.launchQRCodeGenerator();
+ }
+ }
}
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index e105dfc..ab06f75 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -7,7 +7,6 @@
com.android.settings.accessibility.ToggleSelectToSpeakPreferenceFragmentForSetupWizard
com.android.settings.accounts.AccountDetailDashboardFragment
com.android.settings.accounts.AccountSyncSettings
-com.android.settings.accounts.ManagedProfileSettings
com.android.settings.applications.appinfo.AppInfoDashboardFragment
com.android.settings.applications.appinfo.DrawOverlayDetails
com.android.settings.applications.appinfo.ExternalSourcesDetails
diff --git a/tests/robotests/res/xml-mcc999/battery_saver_schedule_settings.xml b/tests/robotests/res/xml-mcc999/battery_saver_schedule_settings.xml
new file mode 100644
index 0000000..f91e4ca
--- /dev/null
+++ b/tests/robotests/res/xml-mcc999/battery_saver_schedule_settings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/battery_saver_schedule_settings_title"
+ settings:staticPreferenceLocation="append">
+</PreferenceScreen >
diff --git a/tests/robotests/src/com/android/settings/accounts/CrossProfileCalendarPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/CrossProfileCalendarPreferenceControllerTest.java
new file mode 100644
index 0000000..4469282
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accounts/CrossProfileCalendarPreferenceControllerTest.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.accounts;
+
+import static android.provider.Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+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 static org.robolectric.RuntimeEnvironment.application;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.ArraySet;
+import android.util.Log;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+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.annotation.Config;
+import org.robolectric.shadows.ShadowDevicePolicyManager;
+
+import java.util.Collections;
+import java.util.Set;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class CrossProfileCalendarPreferenceControllerTest {
+
+ private static final String PREF_KEY = "cross_profile_calendar";
+ private static final int MANAGED_USER_ID = 10;
+ private static final String TEST_PACKAGE_NAME = "com.test";
+ private static final ComponentName TEST_COMPONENT_NAME = new ComponentName("test", "test");
+
+ @Mock
+ private UserHandle mManagedUser;
+
+ private RestrictedSwitchPreference mPreference;
+ private Context mContext;
+ private CrossProfileCalendarPreferenceController mController;
+ private ShadowDevicePolicyManager dpm;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ mController = new CrossProfileCalendarPreferenceController(mContext, PREF_KEY);
+ mController.setManagedUser(mManagedUser);
+ mPreference = spy(new RestrictedSwitchPreference(mContext));
+ dpm = Shadows.shadowOf(application.getSystemService(DevicePolicyManager.class));
+
+ when(mManagedUser.getIdentifier()).thenReturn(MANAGED_USER_ID);
+ doReturn(mContext).when(mContext).createPackageContextAsUser(
+ any(String.class), anyInt(), any(UserHandle.class));
+ }
+
+ @Test
+ public void getAvailabilityStatus_noManagedUser_DISABLED() {
+ mController.setManagedUser(null);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isNotEqualTo(CrossProfileCalendarPreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_hasManagedUser_AVAILABLE() {
+ mController.setManagedUser(mManagedUser);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(CrossProfileCalendarPreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void updateStateToDisabled_isNotChecked() {
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ CROSS_PROFILE_CALENDAR_ENABLED, 0, mManagedUser.getIdentifier());
+
+ mController.updateState(mPreference);
+ assertThat(mPreference.isChecked()).isFalse();
+ }
+
+ @Test
+ public void updateStateToEnabled_isChecked() throws Exception {
+ // Put 0 first so we know the value is not originally 1.
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ CROSS_PROFILE_CALENDAR_ENABLED, 0, mManagedUser.getIdentifier());
+ mController.updateState(mPreference);
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ CROSS_PROFILE_CALENDAR_ENABLED, 1, mManagedUser.getIdentifier());
+
+ mController.updateState(mPreference);
+ assertThat(mPreference.isChecked()).isTrue();
+ }
+
+ @Test
+ public void updateState_noPackageAllowed_preferenceShouldBeDisabled() throws Exception {
+ dpm.setProfileOwner(TEST_COMPONENT_NAME);
+
+ mController.updateState(mPreference);
+ verify(mPreference).setDisabledByAdmin(any());
+ }
+
+ @Test
+ public void updateState_somePackagesAllowed_preferenceShouldNotBeDisabled() throws Exception {
+ dpm.setProfileOwner(TEST_COMPONENT_NAME);
+ dpm.addCrossProfileCalendarPackage(TEST_COMPONENT_NAME, TEST_PACKAGE_NAME);
+
+ mController.updateState(mPreference);
+ verify(mPreference).setDisabledByAdmin(null);
+ }
+
+ @Test
+ public void onPreferenceChangeToFalse_shouldUpdateProviderValue() {
+ mController.onPreferenceChange(mPreference, false);
+ assertThat(Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ CROSS_PROFILE_CALENDAR_ENABLED, 1, mManagedUser.getIdentifier()))
+ .isEqualTo(0);
+ }
+
+ @Test
+ public void onPreferenceChangeToTrue_shouldUpdateProviderValue() {
+ // Change to false first so we know the value is not originally 1.
+ mController.onPreferenceChange(mPreference, false);
+
+ mController.onPreferenceChange(mPreference, true);
+ assertThat(Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ CROSS_PROFILE_CALENDAR_ENABLED, 0, mManagedUser.getIdentifier()))
+ .isEqualTo(1);
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java
index b3f5b5e..4c9cacb 100644
--- a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java
@@ -28,11 +28,12 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -48,9 +49,11 @@
import android.os.UserManager;
import android.view.LayoutInflater;
import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.SearchView;
import androidx.fragment.app.FragmentActivity;
import androidx.recyclerview.widget.RecyclerView;
@@ -159,6 +162,35 @@
}
@Test
+ public void onCreateOptionsMenu_shouldSetSearchQueryListener() {
+ final SearchView searchView = mock(SearchView.class);
+ final MenuItem searchMenu = mock(MenuItem.class);
+ final MenuItem helpMenu = mock(MenuItem.class);
+ when(searchMenu.getActionView()).thenReturn(searchView);
+ when(mMenu.findItem(R.id.search_app_list_menu)).thenReturn(searchMenu);
+ when(mMenu.add(anyInt() /* groupId */, anyInt() /* itemId */, anyInt() /* order */,
+ anyInt() /* titleRes */)).thenReturn(helpMenu);
+ doReturn("Test").when(mFragment).getText(anyInt() /* resId */);
+ doNothing().when(mFragment).updateOptionsMenu();
+
+ mFragment.onCreateOptionsMenu(mMenu, mock(MenuInflater.class));
+
+ verify(searchView).setOnQueryTextListener(mFragment);
+ }
+
+ @Test
+ public void onQueryTextChange_shouldFilterSearchInApplicationsAdapter() {
+ final ManageApplications.ApplicationsAdapter adapter =
+ mock(ManageApplications.ApplicationsAdapter.class);
+ final String query = "Test App";
+ ReflectionHelpers.setField(mFragment, "mApplications", adapter);
+
+ mFragment.onQueryTextChange(query);
+
+ verify(adapter).filterSearch(query);
+ }
+
+ @Test
public void updateLoading_appLoaded_shouldNotDelayCallToHandleLoadingContainer() {
ReflectionHelpers.setField(mFragment, "mLoadingContainer", mock(View.class));
ReflectionHelpers.setField(mFragment, "mListContainer", mock(View.class));
@@ -250,6 +282,34 @@
}
@Test
+ public void onRebuildComplete_hasSearchQuery_shouldFilterSearch() {
+ final String query = "Test";
+ final RecyclerView recyclerView = mock(RecyclerView.class);
+ final View emptyView = mock(View.class);
+ ReflectionHelpers.setField(mFragment, "mRecyclerView", recyclerView);
+ ReflectionHelpers.setField(mFragment, "mEmptyView", emptyView);
+ final SearchView searchView = mock(SearchView.class);
+ ReflectionHelpers.setField(mFragment, "mSearchView", searchView);
+ when(searchView.isVisibleToUser()).thenReturn(true);
+ when(searchView.getQuery()).thenReturn(query);
+ final View listContainer = mock(View.class);
+ when(listContainer.getVisibility()).thenReturn(View.VISIBLE);
+ ReflectionHelpers.setField(mFragment, "mListContainer", listContainer);
+ ReflectionHelpers.setField(
+ mFragment, "mFilterAdapter", mock(ManageApplications.FilterSpinnerAdapter.class));
+ final ArrayList<ApplicationsState.AppEntry> appList = new ArrayList<>();
+ appList.add(mock(ApplicationsState.AppEntry.class));
+ final ManageApplications.ApplicationsAdapter adapter =
+ spy(new ManageApplications.ApplicationsAdapter(mState, mFragment,
+ AppFilterRegistry.getInstance().get(FILTER_APPS_ALL),
+ null /* savedInstanceState */));
+
+ adapter.onRebuildComplete(appList);
+
+ verify(adapter).filterSearch(query);
+ }
+
+ @Test
public void notifyItemChange_recyclerViewIdle_shouldNotify() {
final RecyclerView recyclerView = mock(RecyclerView.class);
final ManageApplications.ApplicationsAdapter adapter =
@@ -344,6 +404,48 @@
}
@Test
+ public void applicationsAdapter_filterSearch_emptyQuery_shouldShowFullList() {
+ final ManageApplications.ApplicationsAdapter adapter =
+ new ManageApplications.ApplicationsAdapter(
+ mState, mFragment, mock(AppFilterItem.class), Bundle.EMPTY);
+ final String[] appNames = {"Apricot", "Banana", "Cantaloupe", "Fig", "Mango"};
+ ReflectionHelpers.setField(adapter, "mOriginalEntries", getTestAppList(appNames));
+
+ adapter.filterSearch("");
+
+ assertThat(adapter.getItemCount()).isEqualTo(5);
+ }
+
+ @Test
+ public void applicationsAdapter_filterSearch_noMatch_shouldShowEmptyList() {
+ final ManageApplications.ApplicationsAdapter adapter =
+ new ManageApplications.ApplicationsAdapter(
+ mState, mFragment, mock(AppFilterItem.class), Bundle.EMPTY);
+ final String[] appNames = {"Apricot", "Banana", "Cantaloupe", "Fig", "Mango"};
+ ReflectionHelpers.setField(adapter, "mOriginalEntries", getTestAppList(appNames));
+
+ adapter.filterSearch("orange");
+
+ assertThat(adapter.getItemCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void applicationsAdapter_filterSearch_shouldShowMatchedItemsOnly() {
+ final ManageApplications.ApplicationsAdapter adapter =
+ new ManageApplications.ApplicationsAdapter(
+ mState, mFragment, mock(AppFilterItem.class), Bundle.EMPTY);
+ final String[] appNames = {"Apricot", "Banana", "Cantaloupe", "Fig", "Mango"};
+ ReflectionHelpers.setField(adapter, "mOriginalEntries", getTestAppList(appNames));
+
+ adapter.filterSearch("an");
+
+ assertThat(adapter.getItemCount()).isEqualTo(3);
+ assertThat(adapter.getAppEntry(0).label).isEqualTo("Banana");
+ assertThat(adapter.getAppEntry(1).label).isEqualTo("Cantaloupe");
+ assertThat(adapter.getAppEntry(2).label).isEqualTo("Mango");
+ }
+
+ @Test
public void sortOrderSavedOnRebuild() {
when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[]{});
ReflectionHelpers.setField(mFragment, "mUserManager", mUserManager);
@@ -375,4 +477,14 @@
return new RoboMenuItem(id);
});
}
+
+ private ArrayList<ApplicationsState.AppEntry> getTestAppList(String[] appNames) {
+ final ArrayList<ApplicationsState.AppEntry> appList = new ArrayList<>();
+ for (String name : appNames) {
+ final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
+ appEntry.label = name;
+ appList.add(appEntry);
+ }
+ return appList;
+ }
}
diff --git a/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java b/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java
index 3b1b5af..ebf3252 100644
--- a/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java
@@ -18,6 +18,7 @@
import static com.android.settings.core.PreferenceXmlParserUtils
.METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE;
+import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_APPEND;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEYWORDS;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_SEARCHABLE;
@@ -315,6 +316,32 @@
}
}
+ @Test
+ @Config(qualifiers = "mcc999")
+ public void extractMetadata_requestAppendProperty_shouldDefaultToFalse()
+ throws Exception {
+ final List<Bundle> metadata = PreferenceXmlParserUtils.extractMetadata(mContext,
+ R.xml.display_settings,
+ MetadataFlag.FLAG_INCLUDE_PREF_SCREEN | MetadataFlag.FLAG_NEED_PREF_APPEND);
+
+ for (Bundle bundle : metadata) {
+ assertThat(bundle.getBoolean(METADATA_APPEND)).isFalse();
+ }
+ }
+
+ @Test
+ @Config(qualifiers = "mcc999")
+ public void extractMetadata_requestAppendProperty_shouldReturnCorrectValue()
+ throws Exception {
+ final List<Bundle> metadata = PreferenceXmlParserUtils.extractMetadata(mContext,
+ R.xml.battery_saver_schedule_settings,
+ MetadataFlag.FLAG_INCLUDE_PREF_SCREEN | MetadataFlag.FLAG_NEED_PREF_APPEND);
+
+ for (Bundle bundle : metadata) {
+ assertThat(bundle.getBoolean(METADATA_APPEND)).isTrue();
+ }
+ }
+
/**
* @param resId the ID for the XML preference
* @return an XML resource parser that points to the start tag
diff --git a/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java b/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java
index af56029..0f9aed1 100644
--- a/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java
@@ -37,11 +37,14 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.TimeUnit;
@RunWith(SettingsRobolectricTestRunner.class)
public class ChartDataUsagePreferenceTest {
+ // Test cycle start date, 20 Mar 2018 22:00: GMT
private static final long TIMESTAMP_START = 1521583200000L;
+ // Test bucket end date, 22 Mar 2018 00:00:00
private static final long TIMESTAMP_END = 1521676800000L;
private List<NetworkCycleData> mNetworkCycleData;
@@ -55,8 +58,6 @@
mContext = RuntimeEnvironment.application;
mPreference = new ChartDataUsagePreference(mContext, null);
- createTestNetworkData();
- mPreference.setNetworkCycleData(mNetworkCycleChartData);
}
@Test
@@ -64,11 +65,13 @@
final UsageView usageView = mock(UsageView.class);
final ArgumentCaptor<SparseIntArray> pointsCaptor =
ArgumentCaptor.forClass(SparseIntArray.class);
+ createTestNetworkData();
+ mPreference.setNetworkCycleData(mNetworkCycleChartData);
mPreference.calcPoints(usageView, mNetworkCycleData.subList(0, 5));
verify(usageView).addPath(pointsCaptor.capture());
- SparseIntArray points = pointsCaptor.getValue();
+ final SparseIntArray points = pointsCaptor.getValue();
// the point should be normal usage data
assertThat(points.valueAt(1)).isNotEqualTo(-1);
}
@@ -78,16 +81,73 @@
final UsageView usageView = mock(UsageView.class);
final ArgumentCaptor<SparseIntArray> pointsCaptor =
ArgumentCaptor.forClass(SparseIntArray.class);
+ createTestNetworkData();
+ mPreference.setNetworkCycleData(mNetworkCycleChartData);
mPreference.calcPoints(usageView, mNetworkCycleData.subList(2, 7));
verify(usageView).addPath(pointsCaptor.capture());
- SparseIntArray points = pointsCaptor.getValue();
+ final SparseIntArray points = pointsCaptor.getValue();
// indicator that no data is available
assertThat(points.keyAt(1)).isEqualTo(points.keyAt(2) - 1);
assertThat(points.valueAt(1)).isEqualTo(-1);
}
+ @Test
+ public void calcPoints_shouldNotDrawPointForFutureDate() {
+ final UsageView usageView = mock(UsageView.class);
+ final ArgumentCaptor<SparseIntArray> pointsCaptor =
+ ArgumentCaptor.forClass(SparseIntArray.class);
+ final long tonight = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(12);
+ mNetworkCycleData = new ArrayList<>();
+ // add test usage data for last 5 days
+ mNetworkCycleData.add(createNetworkCycleData(
+ tonight - TimeUnit.DAYS.toMillis(5), tonight - TimeUnit.DAYS.toMillis(4), 743823454L));
+ mNetworkCycleData.add(createNetworkCycleData(
+ tonight - TimeUnit.DAYS.toMillis(4), tonight - TimeUnit.DAYS.toMillis(3), 64396L));
+ mNetworkCycleData.add(createNetworkCycleData(
+ tonight - TimeUnit.DAYS.toMillis(3), tonight - TimeUnit.DAYS.toMillis(2), 2832L));
+ mNetworkCycleData.add(createNetworkCycleData(
+ tonight - TimeUnit.DAYS.toMillis(2), tonight - TimeUnit.DAYS.toMillis(1), 83849690L));
+ mNetworkCycleData.add(createNetworkCycleData(
+ tonight - TimeUnit.DAYS.toMillis(1), tonight, 1883657L));
+ // add dummy usage data for next 5 days
+ mNetworkCycleData.add(createNetworkCycleData(
+ tonight, tonight + TimeUnit.DAYS.toMillis(1), 0L));
+ mNetworkCycleData.add(createNetworkCycleData(
+ tonight + TimeUnit.DAYS.toMillis(1), tonight + TimeUnit.DAYS.toMillis(2), 0L));
+ mNetworkCycleData.add(createNetworkCycleData(
+ tonight + TimeUnit.DAYS.toMillis(2), tonight + TimeUnit.DAYS.toMillis(3), 0L));
+ mNetworkCycleData.add(createNetworkCycleData(
+ tonight + TimeUnit.DAYS.toMillis(3), tonight + TimeUnit.DAYS.toMillis(4), 0L));
+ mNetworkCycleData.add(createNetworkCycleData(
+ tonight + TimeUnit.DAYS.toMillis(4), tonight + TimeUnit.DAYS.toMillis(5), 0L));
+ mNetworkCycleData.add(createNetworkCycleData(
+ tonight + TimeUnit.DAYS.toMillis(5), tonight + TimeUnit.DAYS.toMillis(6), 0L));
+
+ final NetworkCycleChartData.Builder builder = new NetworkCycleChartData.Builder();
+ builder.setUsageBuckets(mNetworkCycleData)
+ .setStartTime(tonight - TimeUnit.DAYS.toMillis(5))
+ .setEndTime(tonight + TimeUnit.DAYS.toMillis(6));
+ mNetworkCycleChartData = builder.build();
+ mPreference.setNetworkCycleData(mNetworkCycleChartData);
+
+ mPreference.calcPoints(usageView, mNetworkCycleData);
+
+ verify(usageView).addPath(pointsCaptor.capture());
+ final SparseIntArray points = pointsCaptor.getValue();
+ // should only have 7 points: 1 dummy point indicating the start of data, starting point 0,
+ // and 5 actual data point for each day
+ assertThat(points.size()).isEqualTo(7);
+ assertThat(points.keyAt(0)).isEqualTo(-1);
+ assertThat(points.keyAt(1)).isEqualTo(0);
+ assertThat(points.keyAt(2)).isEqualTo(TimeUnit.DAYS.toMinutes(1));
+ assertThat(points.keyAt(3)).isEqualTo(TimeUnit.DAYS.toMinutes(2));
+ assertThat(points.keyAt(4)).isEqualTo(TimeUnit.DAYS.toMinutes(3));
+ assertThat(points.keyAt(5)).isEqualTo(TimeUnit.DAYS.toMinutes(4));
+ assertThat(points.keyAt(6)).isEqualTo(TimeUnit.DAYS.toMinutes(5));
+ }
+
private void createTestNetworkData() {
mNetworkCycleData = new ArrayList<>();
// create 10 arbitrary network data
diff --git a/tests/robotests/src/com/android/settings/development/AngleEnabledAppPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/AngleEnabledAppPreferenceControllerTest.java
deleted file mode 100644
index 03837c2..0000000
--- a/tests/robotests/src/com/android/settings/development/AngleEnabledAppPreferenceControllerTest.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.development;
-
-import static com.android.settings.development.DevelopmentOptionsActivityRequestCodes.REQUEST_CODE_ANGLE_ENABLED_APP;
-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.Activity;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.provider.Settings;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-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.util.ReflectionHelpers;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class AngleEnabledAppPreferenceControllerTest {
-
- @Mock
- private Preference mPreference;
- @Mock
- private PreferenceScreen mPreferenceScreen;
- @Mock
- private DevelopmentSettingsDashboardFragment mFragment;
- @Mock
- private PackageManager mPackageManager;
-
- private Context mContext;
- private AngleEnabledAppPreferenceController mController;
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- mContext = RuntimeEnvironment.application;
- mController = spy(new AngleEnabledAppPreferenceController(mContext, mFragment));
- ReflectionHelpers
- .setField(mController, "mPackageManager" /* field name */, mPackageManager);
- when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
- .thenReturn(mPreference);
- mController.displayPreference(mPreferenceScreen);
- }
-
- @Test
- public void handlePreferenceTreeClick_preferenceClicked_launchActivity() {
- final Intent activityStartIntent = new Intent(mContext, AppPicker.class);
- final String preferenceKey = mController.getPreferenceKey();
- doReturn(activityStartIntent).when(mController).getActivityStartIntent();
- when(mPreference.getKey()).thenReturn(preferenceKey);
- mController.handlePreferenceTreeClick(mPreference);
-
- verify(mFragment).startActivityForResult(activityStartIntent,
- REQUEST_CODE_ANGLE_ENABLED_APP);
- }
-
- @Test
- public void updateState_foobarAppSelected_shouldUpdateSummaryWithAngleEnabledAppLabel() {
- final String angleEnabledApp = "foobar";
- final ContentResolver contentResolver = mContext.getContentResolver();
- Settings.Global.putString(contentResolver, Settings.Global.ANGLE_ENABLED_APP,
- angleEnabledApp);
- mController.updateState(mPreference);
-
- verify(mPreference).setSummary(
- mContext.getString(R.string.angle_enabled_app_set, angleEnabledApp));
- }
-
- @Test
- public void updateState_noAppSelected_shouldUpdateSummaryWithNoAppSelected() {
- final String angleEnabledApp = null;
- final ContentResolver contentResolver = mContext.getContentResolver();
- Settings.Global.putString(contentResolver, Settings.Global.ANGLE_ENABLED_APP,
- angleEnabledApp);
- mController.updateState(mPreference);
-
- verify(mPreference).setSummary(
- mContext.getString(R.string.angle_enabled_app_not_set));
- }
-
- @Test
- public void onActivityResult_foobarAppSelected_shouldUpdateSummaryWithAngleEnabledLabel() {
- Intent activityResultIntent = new Intent(mContext, AppPicker.class);
- final String appLabel = "foobar";
- activityResultIntent.setAction(appLabel);
- final boolean result = mController
- .onActivityResult(REQUEST_CODE_ANGLE_ENABLED_APP, Activity.RESULT_OK,
- activityResultIntent);
-
- assertThat(result).isTrue();
- verify(mPreference).setSummary(
- mContext.getString(R.string.angle_enabled_app_set, appLabel));
- }
-
- @Test
- public void onActivityResult_badRequestCode_shouldReturnFalse() {
- assertThat(mController.onActivityResult(
- -1 /* requestCode */, -1 /* resultCode */, null /* intent */)).isFalse();
- }
-
- @Test
- public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() {
- mController.onDeveloperOptionsSwitchDisabled();
-
- assertThat(mPreference.isEnabled()).isFalse();
- verify(mPreference).setSummary(
- mContext.getString(R.string.angle_enabled_app_not_set));
- }
-}
diff --git a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
index d2c9b65..5eb21bd 100644
--- a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
@@ -28,10 +28,15 @@
import android.provider.SearchIndexableResource;
import android.provider.Settings;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.FragmentActivity;
+
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settings.testutils.shadow.SettingsShadowResourcesImpl;
+import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settings.widget.SwitchBar;
import com.android.settings.widget.ToggleSwitch;
@@ -47,12 +52,14 @@
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
+import org.robolectric.shadows.androidx.fragment.FragmentController;
import org.robolectric.util.ReflectionHelpers;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
-@Config(shadows = ShadowUserManager.class)
+@Config(shadows = {ShadowUserManager.class, ShadowAlertDialogCompat.class,
+ SettingsShadowResourcesImpl.class})
public class DevelopmentSettingsDashboardFragmentTest {
private ToggleSwitch mSwitch;
@@ -179,6 +186,29 @@
}
@Test
+ @Config(shadows = ShadowDisableDevSettingsDialogFragment.class)
+ public void onSwitchChanged_turnOff_andOffloadIsNotDefaultValue_shouldShowWarningDialog() {
+ final BluetoothA2dpHwOffloadPreferenceController controller =
+ mock(BluetoothA2dpHwOffloadPreferenceController.class);
+ when(mDashboard.getContext()).thenReturn(mContext);
+ when(mDashboard.getDevelopmentOptionsController(
+ BluetoothA2dpHwOffloadPreferenceController.class)).thenReturn(controller);
+ when(controller.isDefaultValue()).thenReturn(false);
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
+
+ mDashboard.onSwitchChanged(mSwitch, false /* isChecked */);
+
+ AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(dialog).isNotNull();
+ ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
+ assertThat(shadowDialog.getTitle()).isEqualTo(
+ mContext.getString(R.string.bluetooth_disable_a2dp_hw_offload_dialog_title));
+ assertThat(shadowDialog.getMessage()).isEqualTo(
+ mContext.getString(R.string.bluetooth_disable_a2dp_hw_offload_dialog_message));
+ }
+
+ @Test
public void onOemUnlockDialogConfirmed_shouldCallControllerOemConfirmed() {
final OemUnlockPreferenceController controller = mock(OemUnlockPreferenceController.class);
doReturn(controller).when(mDashboard)
@@ -264,6 +294,18 @@
}
}
+ @Implements(DisableDevSettingsDialogFragment.class)
+ public static class ShadowDisableDevSettingsDialogFragment {
+
+ @Implementation
+ public static void show(DevelopmentSettingsDashboardFragment host) {
+ DisableDevSettingsDialogFragment mFragment =
+ spy(DisableDevSettingsDialogFragment.newInstance());
+ FragmentController.setupFragment(mFragment, FragmentActivity.class,
+ 0 /* containerViewId */, null /* bundle */);
+ }
+ }
+
@Implements(PictureColorModePreferenceController.class)
public static class ShadowPictureColorModePreferenceController {
@Implementation
diff --git a/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java
index 859912a..57f0ebb 100644
--- a/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java
@@ -209,6 +209,7 @@
@Test
public void onCreatePreferences_useNewTitle_shouldAddColorModePreferences() {
+ when(mFragment.getContext()).thenReturn(RuntimeEnvironment.application);
doNothing().when(mFragment).addPreferencesFromResource(anyInt());
doNothing().when(mFragment).updateCandidates();
diff --git a/tests/robotests/src/com/android/settings/flashlight/FlashlightSliceBuilderTest.java b/tests/robotests/src/com/android/settings/flashlight/FlashlightSliceTest.java
similarity index 94%
rename from tests/robotests/src/com/android/settings/flashlight/FlashlightSliceBuilderTest.java
rename to tests/robotests/src/com/android/settings/flashlight/FlashlightSliceTest.java
index 56a84bb..4af5754 100644
--- a/tests/robotests/src/com/android/settings/flashlight/FlashlightSliceBuilderTest.java
+++ b/tests/robotests/src/com/android/settings/flashlight/FlashlightSliceTest.java
@@ -42,7 +42,7 @@
@RunWith(SettingsRobolectricTestRunner.class)
-public class FlashlightSliceBuilderTest {
+public class FlashlightSliceTest {
private Context mContext;
@@ -58,7 +58,7 @@
public void getFlashlightSlice_correctData() {
Settings.Secure.putInt(
mContext.getContentResolver(), Settings.Secure.FLASHLIGHT_AVAILABLE, 1);
- final Slice slice = FlashlightSliceBuilder.getSlice(mContext);
+ final Slice slice = new FlashlightSlice(mContext).getSlice();
final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
final List<SliceAction> toggles = metadata.getToggles();
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java
index 08631f7..b3f9411 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java
@@ -16,13 +16,20 @@
package com.android.settings.homepage.contextualcards;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Matchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.content.Intent;
+import android.net.Uri;
+import android.os.UserHandle;
+import com.android.settings.intelligence.ContextualCardProto.ContextualCardList;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
@@ -31,6 +38,9 @@
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+import java.util.ArrayList;
+import java.util.List;
+
@RunWith(SettingsRobolectricTestRunner.class)
public class ContextualCardFeatureProviderImplTest {
@@ -48,7 +58,7 @@
final Intent intent = new Intent();
mImpl.sendBroadcast(mContext, intent);
- verify(mContext, never()).sendBroadcast(intent);
+ verify(mContext, never()).sendBroadcastAsUser(intent, UserHandle.ALL);
}
@Test
@@ -57,6 +67,37 @@
final Intent intent = new Intent();
mImpl.sendBroadcast(mContext, intent);
- verify(mContext).sendBroadcast(intent);
+ verify(mContext).sendBroadcastAsUser(intent, UserHandle.ALL);
+ }
+
+ @Test
+ @Config(qualifiers = "mcc999")
+ public void logContextualCardDisplay_hasAction_sendBroadcast() {
+ mImpl.logContextualCardDisplay(mContext, new ArrayList<>(), new ArrayList<>());
+
+ verify(mContext).sendBroadcastAsUser(any(Intent.class), any());
+ }
+
+ @Test
+ public void serialize_hasSizeTwo_returnSizeTwo() {
+ final List<ContextualCard> cards = new ArrayList<>();
+ cards.add(new ContextualCard.Builder()
+ .setName("name1")
+ .setSliceUri(Uri.parse("uri1"))
+ .build());
+ cards.add(new ContextualCard.Builder()
+ .setName("name2")
+ .setSliceUri(Uri.parse("uri2"))
+ .build());
+
+
+ final byte[] data = mImpl.serialize(cards);
+
+ try {
+ assertThat(ContextualCardList
+ .parseFrom(data).getCardCount()).isEqualTo(cards.size());
+ } catch (Exception e) {
+ throw new RuntimeException(e.getMessage());
+ }
}
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
index 4f50197..98943a0 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
@@ -162,7 +162,7 @@
cards.add(new ContextualCard.Builder()
.setName("test_connected")
.setCardType(ContextualCard.CardType.SLICE)
- .setSliceUri(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI)
+ .setSliceUri(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI)
.build());
cards.add(new ContextualCard.Builder()
.setName("test_gesture")
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java
new file mode 100644
index 0000000..ac6557e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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.homepage.contextualcards.slices;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.text.TextUtils;
+
+import androidx.core.graphics.drawable.IconCompat;
+import androidx.slice.Slice;
+import androidx.slice.SliceItem;
+import androidx.slice.SliceMetadata;
+import androidx.slice.SliceProvider;
+import androidx.slice.widget.SliceLiveData;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.SliceTester;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+
+import org.junit.After;
+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;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class BluetoothDevicesSliceTest {
+
+ private static final String BLUETOOTH_MOCK_SUMMARY = "BluetoothSummary";
+ private static final String BLUETOOTH_MOCK_TITLE = "BluetoothTitle";
+
+ @Mock
+ private CachedBluetoothDevice mCachedBluetoothDevice;
+
+ private List<CachedBluetoothDevice> mBluetoothDeviceList;
+ private BluetoothDevicesSlice mBluetoothDevicesSlice;
+ private Context mContext;
+ private IconCompat mIcon;
+ private PendingIntent mDetailIntent;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+
+ // Set-up specs for SliceMetadata.
+ SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+
+ mBluetoothDevicesSlice = spy(new BluetoothDevicesSlice(mContext));
+
+ // Mock the icon and detail intent of Bluetooth.
+ mIcon = IconCompat.createWithResource(mContext, R.drawable.ic_settings_bluetooth);
+ mDetailIntent = PendingIntent.getActivity(mContext, 0, new Intent("test action"), 0);
+ doReturn(mIcon).when(mBluetoothDevicesSlice).getBluetoothDeviceIcon(any());
+ doReturn(mDetailIntent).when(mBluetoothDevicesSlice).getBluetoothDetailIntent(any());
+
+ // Initial Bluetooth device list.
+ mBluetoothDeviceList = new ArrayList<>();
+ }
+
+ @After
+ public void tearDown() {
+ if (!mBluetoothDeviceList.isEmpty()) {
+ mBluetoothDeviceList.clear();
+ }
+ }
+
+ @Test
+ public void getSlice_hasBluetoothDevices_shouldHaveBluetoothDevicesTitle() {
+ mockBluetoothDeviceList();
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
+
+ final Slice slice = mBluetoothDevicesSlice.getSlice();
+
+ final List<SliceItem> sliceItems = slice.getItems();
+ SliceTester.assertTitle(sliceItems, mContext.getString(R.string.bluetooth_devices));
+ }
+
+ @Test
+ public void getSlice_hasBluetoothDevices_shouldMatchBluetoothMockTitle() {
+ mockBluetoothDeviceList();
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
+
+ final Slice slice = mBluetoothDevicesSlice.getSlice();
+
+ final List<SliceItem> sliceItems = slice.getItems();
+ SliceTester.assertTitle(sliceItems, BLUETOOTH_MOCK_TITLE);
+ }
+
+ @Test
+ public void getSlice_hasBluetoothDevices_shouldHavePairNewDevice() {
+ mockBluetoothDeviceList();
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
+
+ final Slice slice = mBluetoothDevicesSlice.getSlice();
+
+ final List<SliceItem> sliceItems = slice.getItems();
+ SliceTester.assertTitle(sliceItems,
+ mContext.getString(R.string.bluetooth_pairing_pref_title));
+ }
+
+ @Test
+ public void getSlice_noBluetoothDevices_shouldHaveNoBluetoothDevicesTitle() {
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
+
+ final Slice slice = mBluetoothDevicesSlice.getSlice();
+
+ final List<SliceItem> sliceItems = slice.getItems();
+ SliceTester.assertTitle(sliceItems, mContext.getString(R.string.no_bluetooth_devices));
+ }
+
+ @Test
+ public void getSlice_noBluetoothDevices_shouldNotHavePairNewDevice() {
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
+
+ final Slice slice = mBluetoothDevicesSlice.getSlice();
+
+ final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
+ assertThat(hasTitle(metadata,
+ mContext.getString(R.string.bluetooth_pairing_pref_title))).isFalse();
+ }
+
+ private void mockBluetoothDeviceList() {
+ doReturn(BLUETOOTH_MOCK_TITLE).when(mCachedBluetoothDevice).getName();
+ doReturn(BLUETOOTH_MOCK_SUMMARY).when(mCachedBluetoothDevice).getConnectionSummary();
+ mBluetoothDeviceList.add(mCachedBluetoothDevice);
+ }
+
+ private boolean hasTitle(SliceMetadata metadata, String title) {
+ final CharSequence sliceTitle = metadata.getTitle();
+ return TextUtils.equals(sliceTitle, title);
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java
deleted file mode 100644
index 472d2ca..0000000
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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.homepage.contextualcards.slices;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-
-import androidx.core.graphics.drawable.IconCompat;
-import androidx.slice.Slice;
-import androidx.slice.SliceItem;
-import androidx.slice.SliceProvider;
-import androidx.slice.widget.SliceLiveData;
-
-import com.android.settings.R;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.testutils.SliceTester;
-import com.android.settingslib.bluetooth.CachedBluetoothDevice;
-
-import org.junit.After;
-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;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class ConnectedDeviceSliceTest {
-
- private static final String BLUETOOTH_SUMMARY = "BluetoothSummary";
- private static final String BLUETOOTH_TITLE = "BluetoothTitle";
-
- @Mock
- private CachedBluetoothDevice mCachedBluetoothDevice;
-
- private List<CachedBluetoothDevice> mBluetoothConnectedDeviceList;
- private ConnectedDeviceSlice mConnectedDeviceSlice;
- private Context mContext;
- private IconCompat mIcon;
- private PendingIntent mDetailIntent;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mContext = RuntimeEnvironment.application;
-
- // Set-up specs for SliceMetadata.
- SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
-
- mConnectedDeviceSlice = spy(new ConnectedDeviceSlice(mContext));
-
- // Mock the icon and detail intent of Bluetooth.
- mIcon = IconCompat.createWithResource(mContext, R.drawable.ic_homepage_connected_device);
- mDetailIntent = PendingIntent.getActivity(mContext, 0, new Intent("test action"), 0);
- doReturn(mIcon).when(mConnectedDeviceSlice).getConnectedDeviceIcon(any());
- doReturn(mDetailIntent).when(mConnectedDeviceSlice).getBluetoothDetailIntent(any());
-
- // Initial Bluetooth connected device list.
- mBluetoothConnectedDeviceList = new ArrayList<>();
- }
-
- @After
- public void tearDown() {
- if (!mBluetoothConnectedDeviceList.isEmpty()) {
- mBluetoothConnectedDeviceList.clear();
- }
- }
-
- @Test
- public void getSlice_hasConnectedDevices_shouldHaveCorrectTitle() {
- mockBluetoothDeviceList();
- doReturn(mBluetoothConnectedDeviceList).when(
- mConnectedDeviceSlice).getBluetoothConnectedDevices();
-
- final Slice slice = mConnectedDeviceSlice.getSlice();
-
- final List<SliceItem> sliceItems = slice.getItems();
- SliceTester.assertTitle(sliceItems,
- mContext.getString(R.string.bluetooth_connected_devices));
- }
-
- @Test
- public void getSlice_hasConnectedDevices_shouldHaveCorrectContent() {
- mockBluetoothDeviceList();
- doReturn(mBluetoothConnectedDeviceList).when(
- mConnectedDeviceSlice).getBluetoothConnectedDevices();
-
- final Slice slice = mConnectedDeviceSlice.getSlice();
-
- final List<SliceItem> sliceItems = slice.getItems();
- SliceTester.assertTitle(sliceItems, BLUETOOTH_TITLE);
- }
-
- @Test
- public void getSlice_noConnectedDevices_shouldHaveCorrectTitle() {
- doReturn(mBluetoothConnectedDeviceList).when(
- mConnectedDeviceSlice).getBluetoothConnectedDevices();
-
- final Slice slice = mConnectedDeviceSlice.getSlice();
-
- final List<SliceItem> sliceItems = slice.getItems();
- SliceTester.assertTitle(sliceItems, mContext.getString(R.string.no_connected_devices));
- }
-
- private void mockBluetoothDeviceList() {
- doReturn(BLUETOOTH_TITLE).when(mCachedBluetoothDevice).getName();
- doReturn(BLUETOOTH_SUMMARY).when(mCachedBluetoothDevice).getConnectionSummary();
- mBluetoothConnectedDeviceList.add(mCachedBluetoothDevice);
- }
-}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
index 11d0106..7d71302 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
@@ -52,7 +52,7 @@
@RunWith(SettingsRobolectricTestRunner.class)
public class SliceContextualCardRendererTest {
- private static final String TEST_SLICE_URI = "content://test/test";
+ private static final Uri TEST_SLICE_URI = Uri.parse("content://test/test");
@Mock
private LiveData<Slice> mSliceLiveData;
@@ -91,7 +91,7 @@
@Test
public void bindView_invalidScheme_sliceShouldBeNull() {
- final String sliceUri = "contet://com.android.settings.slices/action/flashlight";
+ final Uri sliceUri = Uri.parse("contet://com.android.settings.slices/action/flashlight");
RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
mRenderer.bindView(viewHolder, buildContextualCard(sliceUri));
@@ -192,6 +192,23 @@
}
@Test
+ public void viewClick_removeCard_sliceLiveDataShouldRemoveObservers() {
+ final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
+ final View card = viewHolder.itemView.findViewById(R.id.slice_view);
+ final Button btnRemove = viewHolder.itemView.findViewById(R.id.remove);
+ final ContextualCard contextualCard = buildContextualCard(TEST_SLICE_URI);
+ mRenderer.mSliceLiveDataMap.put(TEST_SLICE_URI, mSliceLiveData);
+ mRenderer.bindView(viewHolder, contextualCard);
+ doReturn(mController).when(mControllerRendererPool).getController(mActivity,
+ ContextualCard.CardType.SLICE);
+
+ card.performLongClick();
+ btnRemove.performClick();
+
+ assertThat(mRenderer.mSliceLiveDataMap.get(TEST_SLICE_URI).hasObservers()).isFalse();
+ }
+
+ @Test
public void onStop_cardIsFlipped_shouldFlipBack() {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
final View card = viewHolder.itemView.findViewById(R.id.slice_view);
@@ -213,11 +230,11 @@
return mRenderer.createViewHolder(view);
}
- private ContextualCard buildContextualCard(String sliceUri) {
+ private ContextualCard buildContextualCard(Uri sliceUri) {
return new ContextualCard.Builder()
.setName("test_name")
.setCardType(ContextualCard.CardType.SLICE)
- .setSliceUri(Uri.parse(sliceUri))
+ .setSliceUri(sliceUri)
.build();
}
}
diff --git a/tests/robotests/src/com/android/settings/location/LocationScanningPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/location/LocationScanningPreferenceControllerTest.java
index e25b226..994a8fd 100644
--- a/tests/robotests/src/com/android/settings/location/LocationScanningPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/location/LocationScanningPreferenceControllerTest.java
@@ -18,7 +18,11 @@
import static com.google.common.truth.Truth.assertThat;
+import android.content.Context;
+import android.provider.Settings;
+
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.R;
import org.junit.Before;
import org.junit.Test;
@@ -28,22 +32,63 @@
@RunWith(SettingsRobolectricTestRunner.class)
public class LocationScanningPreferenceControllerTest {
+ private Context mContext;
+ private LocationScanningPreferenceController mController;
- private LocationScanningPreferenceController mController;
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mController = new LocationScanningPreferenceController(mContext);
+ }
- @Before
- public void setUp() {
- mController = new LocationScanningPreferenceController(RuntimeEnvironment.application);
- }
+ @Test
+ public void testLocationScanning_byDefault_shouldBeShown() {
+ assertThat(mController.isAvailable()).isTrue();
+ }
- @Test
- public void testLocationScanning_byDefault_shouldBeShown() {
- assertThat(mController.isAvailable()).isTrue();
- }
+ @Test
+ public void testLocationScanning_WifiOnBleOn() {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 1);
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 1);
+ assertThat(mController.getSummary()).isEqualTo(
+ mContext.getString(R.string.scanning_status_text_wifi_on_ble_on));
+ }
- @Test
- @Config(qualifiers = "mcc999")
- public void testLocationScanning_ifDisabled_shouldNotBeShown() {
- assertThat(mController.isAvailable()).isFalse();
- }
+ @Test
+ public void testLocationScanning_WifiOnBleOff() {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 1);
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0);
+ assertThat(mController.getSummary()).isEqualTo(
+ mContext.getString(R.string.scanning_status_text_wifi_on_ble_off));
+ }
+
+ @Test
+ public void testLocationScanning_WifiOffBleOn() {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0);
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 1);
+ assertThat(mController.getSummary()).isEqualTo(
+ mContext.getString(R.string.scanning_status_text_wifi_off_ble_on));
+ }
+
+ @Test
+ public void testLocationScanning_WifiOffBleOff() {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0);
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0);
+ assertThat(mController.getSummary()).isEqualTo(
+ mContext.getString(R.string.scanning_status_text_wifi_off_ble_off));
+ }
+
+ @Test
+ @Config(qualifiers = "mcc999")
+ public void testLocationScanning_ifDisabled_shouldNotBeShown() {
+ assertThat(mController.isAvailable()).isFalse();
+ }
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/location/LocationSliceBuilderTest.java b/tests/robotests/src/com/android/settings/location/LocationSliceTest.java
similarity index 93%
rename from tests/robotests/src/com/android/settings/location/LocationSliceBuilderTest.java
rename to tests/robotests/src/com/android/settings/location/LocationSliceTest.java
index ecbf858..8f1045a 100644
--- a/tests/robotests/src/com/android/settings/location/LocationSliceBuilderTest.java
+++ b/tests/robotests/src/com/android/settings/location/LocationSliceTest.java
@@ -24,7 +24,7 @@
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
-public class LocationSliceBuilderTest {
+public class LocationSliceTest {
private Context mContext;
@@ -38,7 +38,7 @@
@Test
public void getLocationSlice_correctSliceContent() {
- final Slice LocationSlice = LocationSliceBuilder.getSlice(mContext);
+ final Slice LocationSlice = new LocationSlice(mContext).getSlice();
final SliceMetadata metadata = SliceMetadata.from(mContext, LocationSlice);
final List<SliceAction> toggles = metadata.getToggles();
diff --git a/tests/robotests/src/com/android/settings/network/SubscriptionUtilTest.java b/tests/robotests/src/com/android/settings/network/SubscriptionUtilTest.java
new file mode 100644
index 0000000..02e4024
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/SubscriptionUtilTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+
+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 java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class SubscriptionUtilTest {
+ @Mock
+ private SubscriptionManager mManager;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void getAvailableSubscriptions_nullInfoFromSubscriptionManager_nonNullResult() {
+ when(mManager.getAvailableSubscriptionInfoList()).thenReturn(null);
+ final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mManager);
+ assertThat(subs).isNotNull();
+ assertThat(subs).isEmpty();
+ }
+
+ @Test
+ public void getAvailableSubscriptions_oneSubscription_oneResult() {
+ final SubscriptionInfo info = mock(SubscriptionInfo.class);
+ when(info.getMncString()).thenReturn("fake1234");
+ when(mManager.getAvailableSubscriptionInfoList()).thenReturn(Arrays.asList(info));
+ final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mManager);
+ assertThat(subs).isNotNull();
+ assertThat(subs).hasSize(1);
+ }
+
+ @Test
+ public void getAvailableSubscriptions_twoSubscriptions_twoResults() {
+ final SubscriptionInfo info1 = mock(SubscriptionInfo.class);
+ final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
+ when(info1.getMncString()).thenReturn("fake1234");
+ when(info2.getMncString()).thenReturn("fake5678");
+ when(mManager.getAvailableSubscriptionInfoList()).thenReturn(Arrays.asList(info1, info2));
+ final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mManager);
+ assertThat(subs).isNotNull();
+ assertThat(subs).hasSize(2);
+ }
+
+ @Test
+ public void getAvailableSubscriptions_oneSubWithHiddenNetworks_oneResult() {
+ final SubscriptionInfo info1 = mock(SubscriptionInfo.class);
+ final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
+ final SubscriptionInfo info3 = mock(SubscriptionInfo.class);
+ when(info1.getSubscriptionId()).thenReturn(1);
+ when(info1.getMncString()).thenReturn("fake1234");
+ when(mManager.getAvailableSubscriptionInfoList()).thenReturn(
+ new ArrayList<>(Arrays.asList(info1, info2, info3)));
+ final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mManager);
+ assertThat(subs).isNotNull();
+ assertThat(subs).hasSize(1);
+ assertThat(subs.get(0).getSubscriptionId()).isEqualTo(1);
+ }
+
+ @Test
+ public void getAvailableSubscriptions_twoSubsWithHiddenNetworks_twoResults() {
+ final SubscriptionInfo info1 = mock(SubscriptionInfo.class);
+ final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
+ final SubscriptionInfo info3 = mock(SubscriptionInfo.class);
+ final SubscriptionInfo info4 = mock(SubscriptionInfo.class);
+ when(info1.getSubscriptionId()).thenReturn(1);
+ when(info1.getMncString()).thenReturn("fake1234");
+ when(info4.getSubscriptionId()).thenReturn(4);
+ when(info4.getMncString()).thenReturn("fake5678");
+ when(mManager.getAvailableSubscriptionInfoList()).thenReturn(new ArrayList<>(
+ Arrays.asList(info1, info2, info3, info4)));
+ final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mManager);
+ assertThat(subs).isNotNull();
+ assertThat(subs).hasSize(2);
+ assertThat(subs.get(0).getSubscriptionId()).isEqualTo(1);
+ assertThat(subs.get(1).getSubscriptionId()).isEqualTo(4);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
index 2fc3d98..e1ad93b 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
@@ -20,6 +20,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -104,9 +105,8 @@
public void isDialogNeeded_enableNonDefaultSimInMultiSimMode_returnTrue() {
doReturn(false).when(mTelephonyManager).isDataEnabled();
doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID);
- doReturn(null).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
+ doReturn(true).when(mSubscriptionManager).isActiveSubscriptionId(anyInt());
doReturn(2).when(mTelephonyManager).getSimCount();
- doReturn(1).when(mTelephonyManager).getNumberOfModemsWithSimultaneousDataConnections();
assertThat(mController.isDialogNeeded()).isTrue();
assertThat(mController.mDialogType).isEqualTo(
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java
index 3eae266..b431c0a 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java
@@ -144,7 +144,7 @@
mockGetAutomaticZenRules(NUM_RULES, rMap);
FieldSetter.setField(mZenRulePreference, ZenRulePreference.class.getDeclaredField("mId"), testId);
mController.updateState(mockPref);
- verify(mZenRulePreference, times(1)).setChecked(false);
+ verify(mZenRulePreference, times(1)).updatePreference(any());
verify(mController, never()).reloadAllRules(any());
}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModePriorityCallsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModePriorityCallsPreferenceControllerTest.java
index 36a1382..7131250 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModePriorityCallsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModePriorityCallsPreferenceControllerTest.java
@@ -30,6 +30,9 @@
import android.content.Context;
import android.provider.Settings;
+import androidx.preference.ListPreference;
+import androidx.preference.PreferenceScreen;
+
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -43,9 +46,6 @@
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;
-import androidx.preference.ListPreference;
-import androidx.preference.PreferenceScreen;
-
@RunWith(SettingsRobolectricTestRunner.class)
public class ZenModePriorityCallsPreferenceControllerTest {
@@ -86,8 +86,8 @@
when(mBackend.getPriorityCallSenders())
.thenReturn(NotificationManager.Policy.PRIORITY_SENDERS_STARRED);
- when(mBackend.getContactsSummary(ZenModeBackend.SOURCE_NONE))
- .thenCallRealMethod();
+ when(mBackend.getAlarmsTotalSilenceCallsMessagesSummary(
+ NotificationManager.Policy.PRIORITY_CATEGORY_CALLS)).thenCallRealMethod();
when(mBackend.getContactsSummary(NotificationManager.Policy.PRIORITY_CATEGORY_CALLS))
.thenCallRealMethod();
@@ -110,7 +110,7 @@
mController.updateState(mockPref);
verify(mockPref).setEnabled(false);
- verify(mockPref).setSummary(R.string.zen_mode_from_none);
+ verify(mockPref).setSummary(R.string.zen_mode_from_none_calls);
}
@Test
@@ -121,7 +121,7 @@
mController.updateState(mockPref);
verify(mockPref).setEnabled(false);
- verify(mockPref).setSummary(R.string.zen_mode_from_none);
+ verify(mockPref).setSummary(R.string.zen_mode_from_none_calls);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModePriorityMessagesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModePriorityMessagesPreferenceControllerTest.java
index 75605a4..7b6698d 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModePriorityMessagesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModePriorityMessagesPreferenceControllerTest.java
@@ -30,6 +30,9 @@
import android.content.Context;
import android.provider.Settings;
+import androidx.preference.ListPreference;
+import androidx.preference.PreferenceScreen;
+
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -43,9 +46,6 @@
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;
-import androidx.preference.ListPreference;
-import androidx.preference.PreferenceScreen;
-
@RunWith(SettingsRobolectricTestRunner.class)
public class ZenModePriorityMessagesPreferenceControllerTest {
@@ -86,8 +86,8 @@
when(mBackend.getPriorityMessageSenders())
.thenReturn(NotificationManager.Policy.PRIORITY_SENDERS_STARRED);
- when(mBackend.getContactsSummary(ZenModeBackend.SOURCE_NONE))
- .thenCallRealMethod();
+ when(mBackend.getAlarmsTotalSilenceCallsMessagesSummary(
+ NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES)).thenCallRealMethod();
when(mBackend.getContactsSummary(NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES))
.thenCallRealMethod();
@@ -110,7 +110,7 @@
mController.updateState(mockPref);
verify(mockPref).setEnabled(false);
- verify(mockPref).setSummary(R.string.zen_mode_from_none);
+ verify(mockPref).setSummary(R.string.zen_mode_from_none_messages);
}
@Test
@@ -121,7 +121,7 @@
mController.updateState(mockPref);
verify(mockPref).setEnabled(false);
- verify(mockPref).setSummary(R.string.zen_mode_from_none);
+ verify(mockPref).setSummary(R.string.zen_mode_from_none_messages);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeSettingsTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeSettingsTest.java
index 4fc7d57..53032ac 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeSettingsTest.java
@@ -71,20 +71,20 @@
@Test
public void testGetCallsSettingSummary_none() {
Policy policy = new Policy(0, 0, 0, 0);
- assertThat(mBuilder.getCallsSettingSummary(policy)).isEqualTo("None");
+ assertThat(mBuilder.getCallsSettingSummary(policy)).isEqualTo("Don\u2019t allow any calls");
}
@Test
public void testGetCallsSettingSummary_contacts() {
Policy policy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS | Policy.PRIORITY_CATEGORY_CALLS,
Policy.PRIORITY_SENDERS_CONTACTS, 0, 0);
- assertThat(mBuilder.getCallsSettingSummary(policy)).isEqualTo("From contacts");
+ assertThat(mBuilder.getCallsSettingSummary(policy)).isEqualTo("Allow from contacts");
}
@Test
public void testGetCallsSettingSummary_repeatCallers() {
Policy policy = new Policy(Policy.PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0);
- assertThat(mBuilder.getCallsSettingSummary(policy)).isEqualTo("From repeat callers");
+ assertThat(mBuilder.getCallsSettingSummary(policy)).isEqualTo("Allow from repeat callers");
}
@Test
@@ -93,7 +93,7 @@
Policy.PRIORITY_CATEGORY_REPEAT_CALLERS | Policy.PRIORITY_CATEGORY_CALLS,
Policy.PRIORITY_SENDERS_STARRED, 0, 0);
assertThat(mBuilder.getCallsSettingSummary(policy))
- .isEqualTo("From starred contacts and repeat callers");
+ .isEqualTo("Allow from starred contacts and repeat callers");
}
@Test
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
index f9937f4..821d383 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
@@ -505,6 +505,19 @@
assertThat(actualIconResource).isEqualTo(settingsIcon);
}
+ @Test
+ public void getSafeIcon_invalidResource_shouldFallbackToSettingsIcon() {
+ final int settingsIcon = R.drawable.ic_settings;
+ final int badIcon = 0x12345678;
+ final SliceData data = getDummyData(TOGGLE_CONTROLLER, SliceData.SliceType.SWITCH,
+ badIcon);
+
+ final IconCompat actualIcon = SliceBuilderUtils.getSafeIcon(mContext, data);
+
+ final int actualIconResource = actualIcon.toIcon().getResId();
+ assertThat(actualIconResource).isEqualTo(settingsIcon);
+ }
+
private SliceData getDummyData() {
return getDummyData(TOGGLE_CONTROLLER, SUMMARY, SliceData.SliceType.SWITCH, SCREEN_TITLE,
ICON, IS_DYNAMIC_SUMMARY_ALLOWED);
diff --git a/tests/robotests/src/com/android/settings/testutils/SliceTester.java b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
index 26eeb71..c0ffdcd 100644
--- a/tests/robotests/src/com/android/settings/testutils/SliceTester.java
+++ b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
@@ -236,6 +236,7 @@
assertKeywords(metadata, sliceData);
}
+ // TODO(b/120592507): Clean up method of SliceTester
public static void assertTitle(List<SliceItem> sliceItems, String title) {
boolean hasTitle = false;
for (SliceItem item : sliceItems) {
@@ -255,6 +256,7 @@
assertThat(hasTitle).isTrue();
}
+ // TODO(b/120592507): Clean up method of SliceTester
private static void assertKeywords(SliceMetadata metadata, SliceData data) {
final List<String> keywords = metadata.getSliceKeywords();
final Set<String> expectedKeywords = Arrays.stream(data.getKeywords().split(","))
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRuntimePermissionPresenter.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRuntimePermissionPresenter.java
index f11d9e8..e0576b2 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRuntimePermissionPresenter.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRuntimePermissionPresenter.java
@@ -17,7 +17,7 @@
package com.android.settings.testutils.shadow;
import android.content.Context;
-import android.content.pm.permission.RuntimePermissionPresenter;
+import android.permission.RuntimePermissionPresenter;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
diff --git a/tests/robotests/src/com/android/settings/widget/FloatingAppBarScrollingViewBehaviorTest.java b/tests/robotests/src/com/android/settings/widget/FloatingAppBarScrollingViewBehaviorTest.java
new file mode 100644
index 0000000..6acc4d9
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/widget/FloatingAppBarScrollingViewBehaviorTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.widget;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import com.google.android.material.appbar.AppBarLayout;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class FloatingAppBarScrollingViewBehaviorTest {
+
+ private FloatingAppBarScrollingViewBehavior mScrollingViewBehavior;
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mScrollingViewBehavior = new FloatingAppBarScrollingViewBehavior(mContext,
+ Robolectric.buildAttributeSet().build());
+ }
+
+ @Test
+ public void shouldHeaderOverlapScrollingChild_returnTrue() {
+ assertThat(mScrollingViewBehavior.shouldHeaderOverlapScrollingChild()).isTrue();
+ }
+
+ @Test
+ public void setAppBarLayoutTransparent_backgroundDefaultAsWhite_shouldBeTransparent() {
+ mContext.setTheme(R.style.Theme_Settings_Home);
+ final AppBarLayout appBarLayout = new AppBarLayout(mContext);
+ appBarLayout.setBackgroundColor(Color.WHITE);
+ mScrollingViewBehavior.setAppBarLayoutTransparent(appBarLayout);
+ assertThat(((ColorDrawable) appBarLayout.getBackground()).getColor()).isEqualTo(
+ Color.TRANSPARENT);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/widget/RadioButtonPickerFragmentTest.java b/tests/robotests/src/com/android/settings/widget/RadioButtonPickerFragmentTest.java
index 64352d9..55d212f 100644
--- a/tests/robotests/src/com/android/settings/widget/RadioButtonPickerFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/widget/RadioButtonPickerFragmentTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -37,7 +38,9 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
+import org.mockito.InOrder;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
@@ -99,6 +102,26 @@
}
@Test
+ public void staticPreferencesPrepended_addedFirst() {
+ mFragment.mAppendStaticPreferences = false;
+ mFragment.updateCandidates();
+
+ InOrder inOrder = Mockito.inOrder(mFragment);
+ inOrder.verify(mFragment).addStaticPreferences(any());
+ inOrder.verify(mFragment).getRadioButtonPreferenceCustomLayoutResId();
+ }
+
+ @Test
+ public void staticPreferencesAppended_addedLast() {
+ mFragment.mAppendStaticPreferences = true;
+ mFragment.updateCandidates();
+
+ InOrder inOrder = Mockito.inOrder(mFragment);
+ inOrder.verify(mFragment).mayCheckOnlyRadioButton();
+ inOrder.verify(mFragment).addStaticPreferences(any());
+ }
+
+ @Test
public void shouldHaveNoCustomPreferenceLayout() {
assertThat(mFragment.getRadioButtonPreferenceCustomLayoutResId()).isEqualTo(0);
}
diff --git a/tests/robotests/src/com/android/settings/wifi/CellularFallbackPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/CellularFallbackPreferenceControllerTest.java
index e12053c..91598c0 100644
--- a/tests/robotests/src/com/android/settings/wifi/CellularFallbackPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/CellularFallbackPreferenceControllerTest.java
@@ -33,6 +33,7 @@
@RunWith(SettingsRobolectricTestRunner.class)
public class CellularFallbackPreferenceControllerTest {
+ private static final String KEY_CELLULAR_FALLBACK = "wifi_cellular_data_fallback";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
@@ -42,7 +43,7 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mController = new CellularFallbackPreferenceController(mContext);
+ mController = new CellularFallbackPreferenceController(mContext, KEY_CELLULAR_FALLBACK);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java
index 5ac25ed..cdd1664 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java
@@ -53,14 +53,17 @@
private Context mContext;
+ private WifiManager mWifiManager;
private WifiSlice mWifiSlice;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
+ mWifiManager = mContext.getSystemService(WifiManager.class);
// Set-up specs for SliceMetadata.
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+ mWifiManager.setWifiEnabled(true);
mWifiSlice = new WifiSlice(mContext);
}
@@ -83,13 +86,30 @@
}
@Test
- public void getWifiSlice_noAp_shouldReturnPlaceholder() {
+ public void getWifiSlice_wifiOff_shouldReturnSingleRow() {
+ mWifiManager.setWifiEnabled(false);
+
final Slice wifiSlice = mWifiSlice.getSlice();
- int rows = SliceQuery.findAll(wifiSlice, FORMAT_SLICE, HINT_LIST_ITEM,
+ final int rows = SliceQuery.findAll(wifiSlice, FORMAT_SLICE, HINT_LIST_ITEM,
null /* nonHints */).size();
+
+ // Title row
+ assertThat(rows).isEqualTo(1);
+ }
+
+ @Test
+ public void getWifiSlice_noAp_shouldReturnLoadingRow() {
+ final Slice wifiSlice = mWifiSlice.getSlice();
+
+ final int rows = SliceQuery.findAll(wifiSlice, FORMAT_SLICE, HINT_LIST_ITEM,
+ null /* nonHints */).size();
+ final List<SliceItem> sliceItems = wifiSlice.getItems();
+
// All AP rows + title row
assertThat(rows).isEqualTo(DEFAULT_EXPANDED_ROW_COUNT + 1);
+ // Has scanning text
+ SliceTester.assertTitle(sliceItems, mContext.getString(R.string.wifi_empty_list_wifi_on));
}
@Test
diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
index 39215c1..eab9e51 100644
--- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
@@ -865,6 +865,12 @@
when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+ when(pref.setButton3Text(anyInt())).thenReturn(pref);
+ when(pref.setButton3Icon(anyInt())).thenReturn(pref);
+ when(pref.setButton3Enabled(anyBoolean())).thenReturn(pref);
+ when(pref.setButton3Visible(anyBoolean())).thenReturn(pref);
+ when(pref.setButton3OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
return pref;
}
}